Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui into bugfix/scripts

This commit is contained in:
Scott Pfeil 2022-07-03 12:21:28 -04:00
commit 4a695b7430
177 changed files with 4084 additions and 1765 deletions

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 48;
objectVersion = 52;
objects = {
/* Begin PBXBuildFile section */
@ -61,6 +61,10 @@
01EB369323609801006832FA /* HeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368C23609801006832FA /* HeaderModel.swift */; };
01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368D23609801006832FA /* HeadlineBodyModel.swift */; };
01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F2A03123A4498200D954D8 /* CaretLinkModel.swift */; };
01F2C20227C81F9700DC3D36 /* SubNavManagerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F2C1FE27C81F9700DC3D36 /* SubNavManagerController.swift */; };
01F2C20327C81F9700DC3D36 /* SubNavManagerNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F2C1FF27C81F9700DC3D36 /* SubNavManagerNavigationController.swift */; };
01F2C20427C81F9700DC3D36 /* SubNavInteractor.swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F2C20027C81F9700DC3D36 /* SubNavInteractor.swift.swift */; };
01F2C20527C81F9700DC3D36 /* SubNavSwipeAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F2C20127C81F9700DC3D36 /* SubNavSwipeAnimator.swift */; };
0A0FEC7425D42A5E00AF2548 /* BaseItemPickerEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A0FEC7325D42A5E00AF2548 /* BaseItemPickerEntryField.swift */; };
0A0FEC7825D42A8500AF2548 /* BaseItemPickerEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A0FEC7725D42A8500AF2548 /* BaseItemPickerEntryFieldModel.swift */; };
0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */; };
@ -122,6 +126,7 @@
0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB423FF18D2004C5109 /* Arrow.swift */; };
0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */; };
0AF60F0926B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF60F0826B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift */; };
187FEB2A2844D2A600BF29C2 /* VDSFormControlsTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */; };
1D6D258826899B0C00DEBB08 /* ImageButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6D258626899B0B00DEBB08 /* ImageButtonModel.swift */; };
1D6D258926899B0C00DEBB08 /* ImageButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6D258726899B0B00DEBB08 /* ImageButton.swift */; };
279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */; };
@ -141,6 +146,9 @@
32D2609724C19E2100B56344 /* LockupsPlanSMLXLModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D2609524C19E2100B56344 /* LockupsPlanSMLXLModel.swift */; };
32F8804624765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F8804524765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift */; };
32F8804824765C8400C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F8804724765C8400C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinks.swift */; };
444FB7C12821B73200DFE692 /* TitleLockup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 444FB7C02821B73200DFE692 /* TitleLockup.swift */; };
444FB7C32821B76B00DFE692 /* TitleLockupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */; };
4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */; };
522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */; };
522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */; };
52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */; };
@ -268,6 +276,8 @@
AAE7270E24AC8B9300A3ED0E /* HeadersH2CaretLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE7270D24AC8B9300A3ED0E /* HeadersH2CaretLink.swift */; };
AAE96FA225341F6A0037A989 /* ListStoreLocatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE96FA125341F6A0037A989 /* ListStoreLocatorModel.swift */; };
AAE96FA525341F7D0037A989 /* ListStoreLocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE96FA425341F7D0037A989 /* ListStoreLocator.swift */; };
AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */; };
AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */; };
BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; };
BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; };
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */; };
@ -341,7 +351,7 @@
D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479932316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift */; };
D22479962316AF6E003FCCF9 /* HeadlineBodyLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479952316AF6D003FCCF9 /* HeadlineBodyLink.swift */; };
D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */; };
D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* TemplateModel.swift */; };
D22D8393241C27B100D3DF69 /* BaseTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* BaseTemplateModel.swift */; };
D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */; };
D23118B325124E18001C8440 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23118B225124E18001C8440 /* Notification.swift */; };
D2351C7A24A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */; };
@ -569,8 +579,20 @@
DBC4391922442197001AB423 /* DashLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391722442197001AB423 /* DashLine.swift */; };
DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391A224421A0001AB423 /* CaretLink.swift */; };
DBEFFA04225A829700230692 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB891E822253FA8500022516 /* Label.swift */; };
EA05EFA9278DDE2C00828819 /* ClearFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA05EFA8278DDE2C00828819 /* ClearFormFieldEffectModel.swift */; };
EA05EFAB278DE53600828819 /* ClearableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA05EFAA278DE53600828819 /* ClearableModelProtocol.swift */; };
EA41F4AC2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */; };
EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */; };
EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; };
EA7E67742758310500ABF773 /* EnableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */; };
EA7E67762758365300ABF773 /* UIUpdatableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */; };
EAA0CFAF275E7D8000D65EB0 /* FormFieldEffectProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFAE275E7D8000D65EB0 /* FormFieldEffectProtocol.swift */; };
EAA0CFB1275E823A00D65EB0 /* HideFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFB0275E823A00D65EB0 /* HideFormFieldEffectModel.swift */; };
EAA0CFB3275E831E00D65EB0 /* DisableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFB2275E831E00D65EB0 /* DisableFormFieldEffectModel.swift */; };
EAB14BC127D935F00012AB2C /* RuleCompareModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC027D935F00012AB2C /* RuleCompareModelProtocol.swift */; };
EAB14BC327D9378D0012AB2C /* RuleAnyModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */; };
EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC1402763BB8D00E78B40 /* FormLabel.swift */; };
EABFC152276913E800E78B40 /* FormLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC151276913E800E78B40 /* FormLabelModel.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@ -628,6 +650,10 @@
01EB368C23609801006832FA /* HeaderModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderModel.swift; sourceTree = "<group>"; };
01EB368D23609801006832FA /* HeadlineBodyModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeadlineBodyModel.swift; sourceTree = "<group>"; };
01F2A03123A4498200D954D8 /* CaretLinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaretLinkModel.swift; sourceTree = "<group>"; };
01F2C1FE27C81F9700DC3D36 /* SubNavManagerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubNavManagerController.swift; sourceTree = "<group>"; };
01F2C1FF27C81F9700DC3D36 /* SubNavManagerNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubNavManagerNavigationController.swift; sourceTree = "<group>"; };
01F2C20027C81F9700DC3D36 /* SubNavInteractor.swift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubNavInteractor.swift.swift; sourceTree = "<group>"; };
01F2C20127C81F9700DC3D36 /* SubNavSwipeAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubNavSwipeAnimator.swift; sourceTree = "<group>"; };
0A0FEC7325D42A5E00AF2548 /* BaseItemPickerEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseItemPickerEntryField.swift; sourceTree = "<group>"; };
0A0FEC7725D42A8500AF2548 /* BaseItemPickerEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseItemPickerEntryFieldModel.swift; sourceTree = "<group>"; };
0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = "<group>"; };
@ -691,6 +717,7 @@
0AE98BB423FF18D2004C5109 /* Arrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Arrow.swift; sourceTree = "<group>"; };
0AE98BB623FF18E9004C5109 /* ArrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrowModel.swift; sourceTree = "<group>"; };
0AF60F0826B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUIUtility+Extension.swift"; sourceTree = "<group>"; };
187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSFormControlsTokens.xcframework; path = ../SharedFrameworks/VDSFormControlsTokens.xcframework; sourceTree = "<group>"; };
1D6D258626899B0B00DEBB08 /* ImageButtonModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageButtonModel.swift; path = MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift; sourceTree = SOURCE_ROOT; };
1D6D258726899B0B00DEBB08 /* ImageButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageButton.swift; path = MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift; sourceTree = SOURCE_ROOT; };
279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionModelAdapter.swift; sourceTree = "<group>"; };
@ -710,6 +737,9 @@
32D2609524C19E2100B56344 /* LockupsPlanSMLXLModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LockupsPlanSMLXLModel.swift; sourceTree = "<group>"; };
32F8804524765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableNumberedListAllTextAndLinksModel.swift; sourceTree = "<group>"; };
32F8804724765C8400C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableNumberedListAllTextAndLinks.swift; sourceTree = "<group>"; };
444FB7C02821B73200DFE692 /* TitleLockup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockup.swift; sourceTree = "<group>"; };
444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupModel.swift; sourceTree = "<group>"; };
4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageRenderingMode+Extension.swift"; sourceTree = "<group>"; };
522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = "<group>"; };
522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksModel.swift; sourceTree = "<group>"; };
52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinks.swift; sourceTree = "<group>"; };
@ -837,6 +867,8 @@
AAE7270D24AC8B9300A3ED0E /* HeadersH2CaretLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2CaretLink.swift; sourceTree = "<group>"; };
AAE96FA125341F6A0037A989 /* ListStoreLocatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocatorModel.swift; sourceTree = "<group>"; };
AAE96FA425341F7D0037A989 /* ListStoreLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocator.swift; sourceTree = "<group>"; };
AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSColorTokens.xcframework; path = ../SharedFrameworks/VDSColorTokens.xcframework; sourceTree = "<group>"; };
AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = "<group>"; };
BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewLeftAlignedLayout.swift; sourceTree = "<group>"; };
BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = "<group>"; };
BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMedium.swift; sourceTree = "<group>"; };
@ -910,7 +942,7 @@
D22479932316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSLayoutConstraintExtension.swift; sourceTree = "<group>"; };
D22479952316AF6D003FCCF9 /* HeadlineBodyLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyLink.swift; sourceTree = "<group>"; };
D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccordionMoleculeTableViewCell.swift; sourceTree = "<group>"; };
D22D8392241C27B100D3DF69 /* TemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModel.swift; sourceTree = "<group>"; };
D22D8392241C27B100D3DF69 /* BaseTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTemplateModel.swift; sourceTree = "<group>"; };
D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackView+Extension.swift"; sourceTree = "<group>"; };
D23118B225124E18001C8440 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableToggleAllTextAndLinksModel.swift; sourceTree = "<group>"; };
@ -1139,8 +1171,20 @@
DBC4391622442196001AB423 /* CaretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretView.swift; sourceTree = "<group>"; };
DBC4391722442197001AB423 /* DashLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashLine.swift; sourceTree = "<group>"; };
DBC4391A224421A0001AB423 /* CaretLink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretLink.swift; sourceTree = "<group>"; };
EA05EFA8278DDE2C00828819 /* ClearFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearFormFieldEffectModel.swift; sourceTree = "<group>"; };
EA05EFAA278DE53600828819 /* ClearableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearableModelProtocol.swift; sourceTree = "<group>"; };
EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRuleFormFieldEffectModel.swift; sourceTree = "<group>"; };
EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButton.swift; sourceTree = "<group>"; };
EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButtonModel.swift; sourceTree = "<group>"; };
EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnableFormFieldEffectModel.swift; sourceTree = "<group>"; };
EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIUpdatableModelProtocol.swift; sourceTree = "<group>"; };
EAA0CFAE275E7D8000D65EB0 /* FormFieldEffectProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormFieldEffectProtocol.swift; sourceTree = "<group>"; };
EAA0CFB0275E823A00D65EB0 /* HideFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HideFormFieldEffectModel.swift; sourceTree = "<group>"; };
EAA0CFB2275E831E00D65EB0 /* DisableFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableFormFieldEffectModel.swift; sourceTree = "<group>"; };
EAB14BC027D935F00012AB2C /* RuleCompareModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleCompareModelProtocol.swift; sourceTree = "<group>"; };
EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyModelProtocol.swift; sourceTree = "<group>"; };
EABFC1402763BB8D00E78B40 /* FormLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabel.swift; sourceTree = "<group>"; };
EABFC151276913E800E78B40 /* FormLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabelModel.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -1149,7 +1193,9 @@
buildActionMask = 2147483647;
files = (
D29DF0E621E4F3C7003B2FB9 /* MVMCore.framework in Frameworks */,
AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */,
9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */,
187FEB2A2844D2A600BF29C2 /* VDSFormControlsTokens.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1165,6 +1211,7 @@
D23EA7FA2475F09800D60C34 /* CarouselItemProtocol.swift */,
012A88C3238D86E600FE3DA1 /* CarouselItemModelProtocol.swift */,
012A88B0238C880100FE3DA1 /* CarouselPagingModelProtocol.swift */,
EA05EFAA278DE53600828819 /* ClearableModelProtocol.swift */,
01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */,
012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */,
D28A837823C7D5BC00DFE4FC /* PageModelProtocol.swift */,
@ -1183,12 +1230,14 @@
children = (
011D95A4240455DC000E3791 /* FormGroupRule.swift */,
011D958424042432000E3791 /* RulesProtocol.swift */,
011D959A240451E3000E3791 /* RuleRequiredModel.swift */,
011D959C2404536F000E3791 /* RuleAnyValueChangedModel.swift */,
EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */,
EAB14BC027D935F00012AB2C /* RuleCompareModelProtocol.swift */,
011D959E240453A1000E3791 /* RuleAllValueChangedModel.swift */,
011D95A0240453D0000E3791 /* RuleEqualsModel.swift */,
011D959A240451E3000E3791 /* RuleRequiredModel.swift */,
011D95A2240453F8000E3791 /* RuleRegexModel.swift */,
011D959C2404536F000E3791 /* RuleAnyValueChangedModel.swift */,
0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */,
011D95A0240453D0000E3791 /* RuleEqualsModel.swift */,
0A849EFD246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift */,
);
name = Rules;
@ -1206,6 +1255,7 @@
01C74D87224298E2009C25A3 /* FormUIHelpers */ = {
isa = PBXGroup;
children = (
EAA0CFAD275E7D5A00D65EB0 /* FormFieldEffect */,
011D95882404249B000E3791 /* FormHolderModelProtocol.swift */,
011D95AC2406BB57000E3791 /* FormHolderProtocol.swift */,
011D95AA2405C553000E3791 /* FormItemProtocol.swift */,
@ -1213,11 +1263,31 @@
011D95A824057AC7000E3791 /* FormGroupWatcherFieldProtocol.swift */,
011D9601240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift */,
0105618A224BBE7700E1557D /* FormValidator.swift */,
EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */,
011D958A24042794000E3791 /* Rules */,
);
path = FormUIHelpers;
sourceTree = "<group>";
};
01F2C1FC27C81F9700DC3D36 /* Managers */ = {
isa = PBXGroup;
children = (
01F2C1FD27C81F9700DC3D36 /* SubNav */,
);
path = Managers;
sourceTree = "<group>";
};
01F2C1FD27C81F9700DC3D36 /* SubNav */ = {
isa = PBXGroup;
children = (
01F2C1FE27C81F9700DC3D36 /* SubNavManagerController.swift */,
01F2C1FF27C81F9700DC3D36 /* SubNavManagerNavigationController.swift */,
01F2C20027C81F9700DC3D36 /* SubNavInteractor.swift.swift */,
01F2C20127C81F9700DC3D36 /* SubNavSwipeAnimator.swift */,
);
path = SubNav;
sourceTree = "<group>";
};
0A0FEC7125D4246000AF2548 /* Dropdown Fields */ = {
isa = PBXGroup;
children = (
@ -1368,6 +1438,8 @@
525019DC2406430800EED91C /* ListProgressBarData.swift */,
AA45AA0A24BF0263007A6EA7 /* LockUpsPlanNamesModel.swift */,
AA45AA0C24BF0276007A6EA7 /* LockUpsPlanNames.swift */,
444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */,
444FB7C02821B73200DFE692 /* TitleLockup.swift */,
);
path = LockUps;
sourceTree = "<group>";
@ -1428,6 +1500,8 @@
94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */,
94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */,
DB891E822253FA8500022516 /* Label.swift */,
EABFC151276913E800E78B40 /* FormLabelModel.swift */,
EABFC1402763BB8D00E78B40 /* FormLabel.swift */,
);
path = Label;
sourceTree = "<group>";
@ -1477,6 +1551,15 @@
path = Miscellaneous;
sourceTree = "<group>";
};
AFE4A1D427DFBB2700C458D0 /* NavigationController */ = {
isa = PBXGroup;
children = (
D2B18B93236214AD00A9AEDC /* NavigationController.swift */,
AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */,
);
path = NavigationController;
sourceTree = "<group>";
};
D202AFE2242A5F1400E5BEDF /* Extensions */ = {
isa = PBXGroup;
children = (
@ -1491,6 +1574,7 @@
D2ED27E6254B0CE600A1C293 /* UIAlertActionStyle+Codable.swift */,
D2ED27E7254B0CE600A1C293 /* UIAlertControllerStyle+Extension.swift */,
D2E0FFF726AF68530085D696 /* UITableViewRowAnimation+Extension.swift */,
4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */,
);
path = Extensions;
sourceTree = "<group>";
@ -1886,6 +1970,7 @@
D29DF0CE21E404D4003B2FB9 /* MVMCoreUI */ = {
isa = PBXGroup;
children = (
01F2C1FC27C81F9700DC3D36 /* Managers */,
D2ED27D8254B0C1F00A1C293 /* Alerts */,
27F973512466071600CAB5C5 /* Behaviors */,
D2C78CD324252F4E00B69FDE /* Atomic */,
@ -1910,7 +1995,7 @@
D29DF0DF21E418B2003B2FB9 /* Templates */ = {
isa = PBXGroup;
children = (
D22D8392241C27B100D3DF69 /* TemplateModel.swift */,
D22D8392241C27B100D3DF69 /* BaseTemplateModel.swift */,
D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */,
014AA72823C5059B006F3E93 /* StackPageTemplateModel.swift */,
D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */,
@ -1943,6 +2028,8 @@
D29DF0E421E4F3C7003B2FB9 /* Frameworks */ = {
isa = PBXGroup;
children = (
187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */,
AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */,
D29DF0E521E4F3C7003B2FB9 /* MVMCore.framework */,
9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */,
);
@ -2013,9 +2100,9 @@
D29DF11921E68467003B2FB9 /* Containers */ = {
isa = PBXGroup;
children = (
AFE4A1D427DFBB2700C458D0 /* NavigationController */,
0ABD1369237B18EE0081388D /* Views */,
D29DF2B621E7BE66003B2FB9 /* SplitViewController */,
D2B18B93236214AD00A9AEDC /* NavigationController.swift */,
);
path = Containers;
sourceTree = "<group>";
@ -2400,6 +2487,19 @@
path = Alerts;
sourceTree = "<group>";
};
EAA0CFAD275E7D5A00D65EB0 /* FormFieldEffect */ = {
isa = PBXGroup;
children = (
EAA0CFAE275E7D8000D65EB0 /* FormFieldEffectProtocol.swift */,
EAA0CFB2275E831E00D65EB0 /* DisableFormFieldEffectModel.swift */,
EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */,
EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */,
EAA0CFB0275E823A00D65EB0 /* HideFormFieldEffectModel.swift */,
EA05EFA8278DDE2C00828819 /* ClearFormFieldEffectModel.swift */,
);
path = FormFieldEffect;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@ -2538,6 +2638,7 @@
324FB6AA249366F3002552C7 /* ListLeftVariableNumberedListBodyTextModel.swift in Sources */,
5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */,
AA0A257824766C8A00862F64 /* ListLeftVariableIconWithRightCaretBodyTextModel.swift in Sources */,
EABFC152276913E800E78B40 /* FormLabelModel.swift in Sources */,
0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */,
0AF60F0926B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift in Sources */,
8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */,
@ -2564,12 +2665,15 @@
DBC4391922442197001AB423 /* DashLine.swift in Sources */,
D2ED27FC254B0E0300A1C293 /* MVMCoreAlertObject+Swift.swift in Sources */,
D264FAAA2440F97600D98315 /* CollectionView.swift in Sources */,
AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */,
AAC23FAD24D92A0D009208DF /* ListThreeColumnSpeedTestModel.swift in Sources */,
BBC0C4FF24811DCA0087C44F /* TagModel.swift in Sources */,
01F2C20527C81F9700DC3D36 /* SubNavSwipeAnimator.swift in Sources */,
0AE277EC25D2EE310048A38D /* MultiItemDropdownEntryFieldModel.swift in Sources */,
0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */,
3265B30424BCA749000D154B /* HeadersH1NoButtonsBodyText.swift in Sources */,
AAA7CD69250641F90045B959 /* HeartModel.swift in Sources */,
444FB7C12821B73200DFE692 /* TitleLockup.swift in Sources */,
D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */,
D28BA7452481652D00B75CB8 /* TabBarProtocol.swift in Sources */,
AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */,
@ -2601,11 +2705,13 @@
D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */,
D2B18B7F2360913400A9AEDC /* Control.swift in Sources */,
D253BB8A24574CC5002DE544 /* StackModel.swift in Sources */,
EAB14BC127D935F00012AB2C /* RuleCompareModelProtocol.swift in Sources */,
011D95A924057AC7000E3791 /* FormGroupWatcherFieldProtocol.swift in Sources */,
BB2BF0EA2452A9BB001D0FC2 /* ListDeviceComplexButtonSmall.swift in Sources */,
D20C700B250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift in Sources */,
D236E5B4241FEB1000C38625 /* ListTwoColumnPriceDescription.swift in Sources */,
0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */,
EA7E67742758310500ABF773 /* EnableFormFieldEffectModel.swift in Sources */,
D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */,
942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */,
BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */,
@ -2748,6 +2854,7 @@
D2CAC7CD251104FE00C75681 /* NotificationModel.swift in Sources */,
D2ED2803254B0E0300A1C293 /* MVMCoreAlertHandler.m in Sources */,
0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */,
EAA0CFAF275E7D8000D65EB0 /* FormFieldEffectProtocol.swift in Sources */,
D20923592450ECE00044AD09 /* TableView.swift in Sources */,
BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */,
AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */,
@ -2760,6 +2867,7 @@
525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */,
32D2609624C19E2100B56344 /* LockupsPlanSMLXL.swift in Sources */,
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */,
444FB7C32821B76B00DFE692 /* TitleLockupModel.swift in Sources */,
D29C94D5242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift in Sources */,
D260105323CEA61600764D80 /* ToggleModel.swift in Sources */,
014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */,
@ -2802,6 +2910,7 @@
BB55B51D244482C1002001AD /* ListRightVariablePriceChangeBodyText.swift in Sources */,
017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */,
323AC96C24C837FF00F8E4C4 /* ListThreeColumnBillChanges.swift in Sources */,
EAB14BC327D9378D0012AB2C /* RuleAnyModelProtocol.swift in Sources */,
0A0FEC7825D42A8500AF2548 /* BaseItemPickerEntryFieldModel.swift in Sources */,
D28A837923C7D5BC00DFE4FC /* PageModelProtocol.swift in Sources */,
D2351C7C24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift in Sources */,
@ -2816,6 +2925,7 @@
D29DF28321E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.m in Sources */,
011B58F223A2AE2C0085F53C /* DropDownListItemModel.swift in Sources */,
D2509ED12472ED9B001BFB9D /* NavigationItemModelProtocol.swift in Sources */,
EA05EFAB278DE53600828819 /* ClearableModelProtocol.swift in Sources */,
8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */,
BBC0C4FD24811DBC0087C44F /* Tag.swift in Sources */,
94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */,
@ -2824,6 +2934,7 @@
C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */,
32F8804624765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift in Sources */,
011D958524042432000E3791 /* RulesProtocol.swift in Sources */,
4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */,
D23118B325124E18001C8440 /* Notification.swift in Sources */,
AA9972502475309F00FC7472 /* ListLeftVariableIconAllTextLinksModel.swift in Sources */,
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */,
@ -2930,6 +3041,7 @@
D2CAC7D12511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift in Sources */,
0A21DB83235DFBC500C160A2 /* MdnEntryField.swift in Sources */,
0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */,
01F2C20427C81F9700DC3D36 /* SubNavInteractor.swift.swift in Sources */,
D28A837D23CCA86A00DFE4FC /* TabsListItemModel.swift in Sources */,
0A51F3E32475CB73002E08B6 /* LoadingSpinner.swift in Sources */,
BB2FB3BB247E7EBC00DF73CD /* TagCollectionViewCell.swift in Sources */,
@ -2942,6 +3054,7 @@
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */,
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */,
D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */,
01F2C20227C81F9700DC3D36 /* SubNavManagerController.swift in Sources */,
AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */,
52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */,
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */,
@ -2953,12 +3066,15 @@
1D6D258826899B0C00DEBB08 /* ImageButtonModel.swift in Sources */,
AA07EA912510A442009A2AE3 /* StarModel.swift in Sources */,
D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */,
EA41F4AC2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift in Sources */,
011D95892404249B000E3791 /* FormHolderModelProtocol.swift in Sources */,
BB54C5202434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift in Sources */,
948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */,
013F801923FB4A8E00AD8013 /* UIContentMode+Extension.swift in Sources */,
AA104AC724472DB0004D2810 /* HeadersH1Button.swift in Sources */,
525239C22407BD1000454969 /* ListTwoColumnPriceDetails.swift in Sources */,
01F2C20327C81F9700DC3D36 /* SubNavManagerNavigationController.swift in Sources */,
EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */,
AA997252247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift in Sources */,
D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */,
D23EA7FB2475F09800D60C34 /* CarouselItemProtocol.swift in Sources */,
@ -2968,16 +3084,19 @@
27F973532466074500CAB5C5 /* PageBehaviorProtocol.swift in Sources */,
94C2D9A323872C110006CF46 /* LabelAttributeStrikeThroughModel.swift in Sources */,
D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */,
EAA0CFB3275E831E00D65EB0 /* DisableFormFieldEffectModel.swift in Sources */,
D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */,
D23EA7FE247EBBB700D60C34 /* NavigationLabelButtonModel.swift in Sources */,
D28A839123CD4FD400DFE4FC /* CornerLabelsModel.swift in Sources */,
012A88F123985E0100FE3DA1 /* Color.swift in Sources */,
D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */,
D22D8393241C27B100D3DF69 /* BaseTemplateModel.swift in Sources */,
012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */,
EAA0CFB1275E823A00D65EB0 /* HideFormFieldEffectModel.swift in Sources */,
D23A8FFB26123189007E14CE /* PageBehaviorModelProtocol.swift in Sources */,
52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */,
D2ED2812254B0EB800A1C293 /* MVMCoreTopAlertObject.m in Sources */,
0AA4D2E125CAEC72008DB32D /* AccessibilityModelProtocol.swift in Sources */,
EA05EFA9278DDE2C00828819 /* ClearFormFieldEffectModel.swift in Sources */,
C003506123AA94CD00B6AC29 /* Button.swift in Sources */,
DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */,
D29C559025C095210082E7D6 /* Video.swift in Sources */,
@ -3040,6 +3159,7 @@
011D95AD2406BB57000E3791 /* FormHolderProtocol.swift in Sources */,
D23A9004261234CE007E14CE /* PageBehaviorHandlerProtocol.swift in Sources */,
01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */,
EA7E67762758365300ABF773 /* UIUpdatableModelProtocol.swift in Sources */,
D2169301251E51E7002A6324 /* SectionListTemplate.swift in Sources */,
0A6682AA2435125F00AD3CA1 /* Styler.swift in Sources */,
D264FAA7243FE13B00D98315 /* RadioBox.swift in Sources */,
@ -3180,7 +3300,8 @@
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -3202,8 +3323,13 @@
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../SharedFrameworks";
INFOPLIST_FILE = MVMCoreUI/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.vzw.MVMCoreUI;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
@ -3228,8 +3354,13 @@
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../SharedFrameworks";
INFOPLIST_FILE = MVMCoreUI/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.vzw.MVMCoreUI;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;

View File

@ -52,7 +52,9 @@ public extension MVMCoreAlertHandler {
extension MVMCoreAlertHandler: MVMCorePresentationDelegateProtocol {
// Update displayable for each top alert operation when page type changes, in top queue priority order.
public func navigationController(_ navigationController: UINavigationController, displayedViewController viewController: UIViewController) {
guard navigationController == MVMCoreUISplitViewController.main()?.navigationController else { return }
guard topAlertQueue.operations.count > 0 else { return }
let viewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController)
guard viewController == MVMCoreUISplitViewController.main()?.getCurrentViewController() else { return }
let pageType = (viewController as? MVMCoreViewControllerProtocol)?.pageType
topAlertQueue.operations.compactMap {
$0 as? MVMCoreTopAlertOperation

View File

@ -104,6 +104,9 @@
/// Hides a persistent alert based on the type string.
- (void)hidePersistentTopAlertViewOfType:(nullable NSString *)type;
/// Hides a alert based on the type string.
- (void)hideTopAlertViewOfType:(nullable NSString *)type;
/// Removes a scheduled top alert given its top alert object.
- (void)removeTopAlertForObject:(nonnull MVMCoreTopAlertObject *)topAlertObject;

View File

@ -239,6 +239,19 @@
}
}
- (void)hideTopAlertViewOfType:(nullable NSString *)type {
if (type) {
for (MVMCoreTopAlertOperation *operation in self.topAlertQueue.operations) {
// Cancel all operations of this type.
if ([operation.topAlertObject.type isEqualToString:type]) {
operation.reAddAfterCancel = NO;
[operation cancel];
}
}
}
}
- (void)removeTopAlertForObject:(MVMCoreTopAlertObject *)topAlertObject {
for (MVMCoreTopAlertOperation *operation in self.topAlertQueue.operations) {
// Finds an cancels top alerts associated with the object.

View File

@ -40,6 +40,10 @@ public extension MVMCoreAlertObject {
alertObject?.alertStyle = UIAlertController.Style(rawValue: alertStyle)
}
if let analyticsData = alertJson.optionalDictionaryForKey("analyticsData") {
alertObject?.pageJson = ["analyticsData": analyticsData]
}
return alertObject
}
}

View File

@ -54,8 +54,8 @@
}
__block MVMCoreAlertObject *alert = [[MVMCoreAlertObject alloc] init];
alert.title = [responseInfo stringForKey:KeyErrorHeading];
alert.message = [responseInfo stringForKey:KeyUserMessage];
alert.title = [responseInfo string:KeyErrorHeading] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorTitle];
alert.message = [responseInfo string:KeyUserMessage] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess];
NSString *messageStyle = [responseInfo stringForKey:KeyMessageStyle];
if ([ValueTypeFieldErrors isEqualToString:[responseInfo string:KeyType]]) {
@ -151,9 +151,9 @@
+ (nullable instancetype)alertObjectWithPage:(nullable NSDictionary *)page isGreedy:(BOOL)isGreedy additionalData:(nullable NSDictionary *)additionalData delegateObject:(nullable DelegateObject *)delegateObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error {
MVMCoreAlertObject *alert = [[MVMCoreAlertObject alloc] init];
alert.title = [page stringForKey:KeyTitle];
alert.title = [page string:KeyTitle] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorTitle];
alert.pageJson = page;
alert.message = [page stringForKey:KeyMessage];
alert.message = [page string:KeyMessage] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess];
alert.isGreedy = isGreedy;
alert.type = MFAlertTypePopup;
alert.alertStyle = UIAlertControllerStyleAlert;
@ -217,9 +217,8 @@
+ (nullable instancetype)alertObjectForPageType:(nullable NSString *)pageType responseInfo:(nullable NSDictionary *)responseInfo additionalData:(nullable NSDictionary *)additionalData actionDelegate:(nullable NSObject <MVMCoreLoadDelegateProtocol,MVMCorePresentationDelegateProtocol,MVMCoreActionDelegateProtocol>*)actionDelegate {
__block MVMCoreAlertObject *alert = [[MVMCoreAlertObject alloc] init];
alert.title = [responseInfo stringForKey:KeyErrorHeading];
alert.message = [responseInfo stringForKey:KeyUserMessage];
alert.title = [responseInfo string:KeyErrorHeading] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorTitle];
alert.message = [responseInfo string:KeyUserMessage] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess];
NSString *messageStyle = [responseInfo stringForKey:KeyMessageStyle];
if ([ValueTypeFieldErrors isEqualToString:[responseInfo string:KeyType]]) {
@ -279,9 +278,9 @@
+ (nullable instancetype)alertObjectWithPage:(nullable NSDictionary *)page isGreedy:(BOOL)isGreedy additionalData:(nullable NSDictionary *)additionalData delegate:(nullable NSObject <MVMCoreLoadDelegateProtocol,MVMCorePresentationDelegateProtocol,MVMCoreActionDelegateProtocol>*)delegate error:(MVMCoreErrorObject *_Nullable *_Nullable)error {
MVMCoreAlertObject *alert = [[MVMCoreAlertObject alloc] init];
alert.title = [page stringForKey:KeyTitle];
alert.title = [page string:KeyTitle] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorTitle];
alert.pageJson = page;
alert.message = [page stringForKey:KeyMessage];
alert.message = [page string:KeyMessage] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess];
alert.isGreedy = isGreedy;
alert.type = MFAlertTypePopup;
alert.alertStyle = UIAlertControllerStyleAlert;

View File

@ -5,7 +5,7 @@
// Created by Suresh, Kamlesh on 7/9/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
@objcMembers public class ActionAlertModel: ActionModelProtocol {
//--------------------------------------------------
@ -17,4 +17,12 @@
public var alert: AlertModel
public var extraParameters: JSONValueDictionary?
public var analyticsData: JSONValueDictionary?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(alert: AlertModel) {
self.alert = alert
}
}

View File

@ -7,6 +7,7 @@
//
import UIKit
import MVMCore
public class AlertButtonModel: Codable {
@ -69,6 +70,7 @@ public class AlertModel: Codable {
public var message: String
public var style: UIAlertController.Style = .alert
public var alertActions: [AlertButtonModel]
public var analyticsData: JSONValueDictionary?
//--------------------------------------------------
// MARK: - Properties
@ -89,6 +91,7 @@ public class AlertModel: Codable {
case message
case alertActions
case style
case analyticsData
}
//--------------------------------------------------
@ -100,7 +103,8 @@ public class AlertModel: Codable {
title = try typeContainer.decode(String.self, forKey: .title)
message = try typeContainer.decode(String.self, forKey: .message)
alertActions = try typeContainer.decode([AlertButtonModel].self, forKey: .alertActions)
analyticsData = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .analyticsData)
if let style = try typeContainer.decodeIfPresent(String.self, forKey: .style) {
self.style = UIAlertController.Style(rawValue: style)
}
@ -112,5 +116,6 @@ public class AlertModel: Codable {
try container.encode(message, forKey: .message)
try container.encode(alertActions, forKey: .alertActions)
try container.encode(style.rawValueString, forKey: .style)
try container.encodeIfPresent(analyticsData, forKey: .analyticsData)
}
}

View File

@ -7,21 +7,23 @@
//
import UIKit
import VDSColorTokens
public typealias FacadeElements = (fill: UIColor?, text: UIColor?, border: UIColor?)
open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol, EnableableModelProtocol {
open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
//Making static property as class property so that subclasses can override getter function of the property
open class var identifier: String { "button" }
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var accessibilityText: String?
public var title: String
public var action: ActionModelProtocol
public var enabled: Bool = true
public var width: CGFloat?
public var style: Styler.Button.Style? {
didSet {
guard let style = style else { return }
@ -56,15 +58,23 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
public var disabledTextColor_inverted: Color?
public var disabledBorderColor_inverted: Color?
private var _backgroundColor: Color?
public var backgroundColor: Color? {
get {
if let backgroundColor = _backgroundColor { return backgroundColor }
if inverted {
return enabled ? enabledFillColor_inverted : disabledFillColor_inverted
}
return enabled ? enabledFillColor : disabledFillColor
}
set {
_backgroundColor = newValue
}
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
public func setValidity(_ valid: Bool, group: FormGroupRule) {
enabled = valid
updateUI?()
}
/// Temporary binding mechanism for the view to update on enable changes.
public var updateUI: ActionBlock?
@ -75,18 +85,21 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
public init(with title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
setFacade(by: .primary)
}
public init(secondaryButtonWith title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
style = .secondary
setFacade(by: .secondary)
}
public init(primaryButtonWith title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
style = .primary
setFacade(by: .primary)
}
//--------------------------------------------------
@ -119,40 +132,30 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
/// Defines the default appearance for the primary style.
func setPrimaryFacade() {
enabledFillColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
enabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOndark)
disabledFillColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
disabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOndark)
if enabledFillColor == nil && enabledTextColor == nil {
enabledFillColor = Color(uiColor: .mvmBlack)
enabledTextColor = Color(uiColor: .mvmWhite)
}
if disabledFillColor == nil && disabledTextColor == nil {
disabledFillColor = Color(uiColor: .mvmCoolGray6)
disabledTextColor = Color(uiColor: .mvmWhite)
}
enabledFillColor_inverted = Color(uiColor: .mvmWhite)
enabledTextColor_inverted = Color(uiColor: .mvmBlack)
disabledFillColor_inverted = Color(uiColor: .mvmCoolGray6)
disabledTextColor_inverted = Color(uiColor: .mvmBlack)
enabledFillColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
enabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOnlight)
disabledFillColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
disabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
/// Defines the default appearance for the Secondary style.
func setSecondaryFacade() {
enabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
enabledFillColor = Color(uiColor: UIColor.clear)
enabledBorderColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
disabledTextColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
disabledBorderColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
if enabledTextColor == nil && enabledBorderColor == nil {
enabledTextColor = Color(uiColor: .mvmBlack)
enabledBorderColor = Color(uiColor: .mvmBlack)
}
if disabledTextColor == nil && disabledBorderColor == nil {
disabledTextColor = Color(uiColor: .mvmCoolGray6)
disabledBorderColor = Color(uiColor: .mvmCoolGray6)
}
enabledTextColor_inverted = Color(uiColor: .mvmWhite)
enabledBorderColor_inverted = Color(uiColor: .mvmWhite)
disabledTextColor_inverted = Color(uiColor: .mvmCoolGray6)
disabledBorderColor_inverted = Color(uiColor: .mvmCoolGray6)
enabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
enabledFillColor_inverted = Color(uiColor: UIColor.clear)
enabledBorderColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
disabledTextColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
disabledBorderColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
}
public func setFacade(by style: Styler.Button.Style) {
@ -174,6 +177,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
case moleculeName
case backgroundColor
case accessibilityIdentifier
case accessibilityText
case title
case inverted
case action
@ -187,6 +191,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
case disabledFillColor
case disabledTextColor
case disabledBorderColor
case width
}
//--------------------------------------------------
@ -196,14 +201,21 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
title = try typeContainer.decode(String.self, forKey: .title)
action = try typeContainer.decodeModel(codingKey: .action)
if let style = decoder.context?.value(forKey: CodingKeys.style.stringValue) as? Styler.Button.Style{
self.style = style
setFacade(by: style)
}
if let style = try typeContainer.decodeIfPresent(Styler.Button.Style.self, forKey: .style) {
self.style = style
setFacade(by: style)
} else {
setFacade(by: .primary)
}
if let size = try typeContainer.decodeIfPresent(Styler.Button.Size.self, forKey: .size) {
@ -245,6 +257,9 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
if let disabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledBorderColor) {
self.disabledBorderColor = disabledBorderColor
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
width = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .width)
}
open func encode(to encoder: Encoder) throws {
@ -254,8 +269,9 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
try container.encode(enabled, forKey: .enabled)
try container.encode(inverted, forKey: .inverted)
try container.encodeModel(action, forKey: .action)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
try container.encodeIfPresent(enabledFillColor, forKey: .fillColor)
try container.encodeIfPresent(enabledTextColor, forKey: .textColor)
try container.encodeIfPresent(enabledBorderColor, forKey: .borderColor)
@ -265,5 +281,6 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
try container.encodeIfPresent(style, forKey: .style)
try container.encodeIfPresent(size, forKey: .size)
try container.encodeIfPresent(groupName, forKey: .groupName)
try container.encodeIfPresent(width, forKey: .width)
}
}

View File

@ -99,7 +99,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeModel(action, forKey: .action)
try container.encode(enabled, forKey: .enabledColor)
try container.encode(enabledColor, forKey: .enabledColor)
try container.encodeIfPresent(disabledColor, forKey: .disabledColor)
try container.encode(enabled, forKey: .enabled)
try container.encode(enabledColor_inverted, forKey: .enabledColor_inverted)

View File

@ -36,7 +36,7 @@ import Foundation
}
private func setState() {
public func setState() {
guard let castModel = model as? ImageButtonModel else {
return
}

View File

@ -8,7 +8,7 @@
import Foundation
open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol, EnableableModelProtocol {
open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
@ -25,11 +25,6 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro
public var disabledTintColor: Color?
public var groupName: String = ""
public func setValidity(_ valid: Bool, group: FormGroupRule) {
enabled = valid
updateUI?()
}
public var updateUI: ActionBlock?

View File

@ -7,7 +7,7 @@
//
import UIKit
import VDSColorTokens
@objcMembers open class Link: Button {
//--------------------------------------------------
@ -28,8 +28,8 @@ import UIKit
// x should be according to the text, not the button
let x = textRect.origin.x
// Line is 1 point below the text
let y = textRect.origin.y + textRect.size.height + 1
// Line is 0 point below the text
let y = textRect.origin.y + textRect.size.height
context.move(to: CGPoint(x: x, y: y))
context.addLine(to: CGPoint(x: x + textRect.size.width, y: y))
@ -38,7 +38,7 @@ import UIKit
open override var intrinsicContentSize: CGSize {
guard let size = titleLabel?.intrinsicContentSize else { return super.intrinsicContentSize }
return CGSize(width: size.width, height: size.height + 2)
return CGSize(width: size.width, height: size.height + 1)
}
//--------------------------------------------------
@ -51,10 +51,14 @@ import UIKit
guard let model = model as? LinkModel else { return }
setTitle(model.title, for: .normal)
accessibilityLabel = model.title
if let accessibilityText = model.accessibilityText {
accessibilityLabel = accessibilityText
}
setTitleColor((model.inverted ? model.enabledColor_inverted : model.enabledColor).uiColor, for: .normal)
setTitleColor((model.inverted ? model.disabledColor_inverted : model.disabledColor).uiColor, for: .disabled)
setTitleColor((model.inverted ? model.activeColor_inverted : model.activeColor).uiColor, for: .highlighted)
isEnabled = model.enabled
titleLabel?.font = model.getFont(model.size)
set(with: model.action, delegateObject: delegateObject, additionalData: additionalData)
}
@ -66,21 +70,15 @@ extension Link {
open override func updateView(_ size: CGFloat) {
super.updateView(size)
var width = size
if MVMCoreGetterUtility.fequal(a: Float.leastNormalMagnitude, b: Float(size)) {
width = MVMCoreUIUtility.getWidth()
}
titleLabel?.font = MFStyler.fontB2(forWidth: width)
}
open override func setupView() {
super.setupView()
backgroundColor = .clear
contentMode = .redraw
setTitleColor(.mvmBlack, for: .normal)
setTitleColor(.mvmCoolGray6, for: .disabled)
setTitleColor(VDSColor.elementsPrimaryOnlight, for: .normal)
setTitleColor(VDSColor.interactiveDisabledOnlight, for: .disabled)
setTitleColor(VDSColor.interactiveActiveOnlight, for: .highlighted)
titleLabel?.numberOfLines = 1
titleLabel?.lineBreakMode = .byTruncatingTail
titleLabel?.textAlignment = .left

View File

@ -7,7 +7,7 @@
//
import UIKit
import VDSColorTokens
open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableModelProtocol {
//--------------------------------------------------
@ -19,13 +19,18 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var title: String
public var accessibilityText: String?
public var action: ActionModelProtocol
public var enabled = true
public var enabledColor = Color(uiColor: .mvmBlack)
public var enabledColor_inverted = Color(uiColor: .mvmWhite)
public var disabledColor = Color(uiColor: .mvmCoolGray6)
public var disabledColor_inverted = Color(uiColor: .mvmCoolGray10)
public var enabledColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
public var enabledColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
public var disabledColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
public var disabledColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
public var activeColor = Color(uiColor: VDSColor.interactiveActiveOnlight)
public var activeColor_inverted = Color(uiColor: VDSColor.interactiveActiveOndark)
public var inverted = false
public var size:linkFontSize = linkFontSize.small
//--------------------------------------------------
// MARK: - Initializer
@ -44,6 +49,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
case moleculeName
case backgroundColor
case accessibilityIdentifier
case accessibilityText
case title
case action
case enabled
@ -51,9 +57,30 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
case enabledColor_inverted
case disabledColor
case disabledColor_inverted
case activeColor
case activeColor_inverted
case inverted
case size
}
public enum linkFontSize: String, Codable {
case small
case large
}
//--------------------------------------------------
// MARK: - Method
//--------------------------------------------------
func getFont(_ type: linkFontSize) -> UIFont {
switch type {
case .small:
return MFStyler.fontRegularBodySmall()
case .large:
return MFStyler.fontRegularBodyLarge()
}
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
@ -64,6 +91,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
title = try typeContainer.decode(String.self, forKey: .title)
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
action = try typeContainer.decodeModel(codingKey: .action)
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
@ -89,6 +117,17 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
if let disabledColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor_inverted) {
self.disabledColor_inverted = disabledColor_inverted
}
if let activeColor = try typeContainer.decodeIfPresent(Color.self, forKey: .activeColor) {
self.activeColor = activeColor
}
if let activeColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .activeColor_inverted) {
self.activeColor_inverted = activeColor_inverted
}
if let size = try typeContainer.decodeIfPresent(linkFontSize.self, forKey: .size) {
self.size = size
}
}
public func encode(to encoder: Encoder) throws {
@ -104,5 +143,8 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
try container.encode(enabledColor_inverted, forKey: .enabledColor_inverted)
try container.encode(disabledColor, forKey: .disabledColor)
try container.encode(disabledColor_inverted, forKey: .disabledColor_inverted)
try container.encode(activeColor, forKey: .activeColor)
try container.encode(activeColor_inverted, forKey: .activeColor_inverted)
try container.encodeIfPresent(size, forKey: .size)
}
}

View File

@ -7,7 +7,7 @@
//
import UIKit
import VDSColorTokens
open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
//--------------------------------------------------
@ -23,21 +23,29 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
/// Need to re-style on set.
open override var isEnabled: Bool {
didSet { style() }
didSet { style(with: buttonModel) }
}
open var buttonSize: Styler.Button.Size = .standard {
didSet { buttonModel?.size = buttonSize }
}
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
public var widthConstraint: NSLayoutConstraint?
public var minimumWidthConstraint: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@objc public convenience init(asPrimaryButton isPrimary: Bool, makeTiny istiny: Bool) {
self.init()
buttonSize = istiny ? .tiny : .standard
isPrimary ? stylePrimary() : styleSecondary()
let model = ButtonModel(with: "", action: ActionNoopModel())
model.style = isPrimary ? .primary : .secondary
model.size = istiny ? .tiny : .standard
self.init(model: model, nil, nil)
}
//--------------------------------------------------
@ -68,39 +76,26 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
/// The primary styling for a button. Should be used for main buttons
public func stylePrimary() {
enabledTitleColor = buttonModel?.enabledColors.text ?? .mvmWhite
disabledTitleColor = buttonModel?.disabledColors.text ?? .mvmWhite
layer.borderWidth = 0
backgroundColor = isEnabled ? buttonModel?.enabledColors.fill ?? .mvmBlack : buttonModel?.disabledColors.fill ?? .mvmCoolGray6
let buttonModel = ButtonModel(primaryButtonWith: "", action: ActionNoopModel())
style(with: buttonModel)
}
/// The secondary styling for a button. Should be used for secondary buttons
public func styleSecondary() {
enabledTitleColor = buttonModel?.enabledColors.text ?? .mvmBlack
disabledTitleColor = buttonModel?.disabledColors.text ?? .mvmCoolGray6
backgroundColor = .clear
layer.borderWidth = 1
borderColor = isEnabled ? buttonModel?.enabledColors.border ?? .mvmBlack : buttonModel?.disabledColors.border ?? .mvmCoolGray6
let buttonModel = ButtonModel(secondaryButtonWith: "", action: ActionNoopModel())
style(with: buttonModel)
}
/// Styles the button based on the model style
private func style() {
private func style(with model: ButtonModel?) {
switch buttonModel?.style {
case .secondary:
styleSecondary()
default:
stylePrimary()
}
layer.borderWidth = model?.style == .secondary ? 1 : 0
if let titleColor = buttonModel?.enabledColors.text {
if let titleColor = model?.enabledColors.text {
enabledTitleColor = titleColor
}
if let disabledTitleColor = buttonModel?.disabledColors.text {
if let disabledTitleColor = model?.disabledColors.text {
self.disabledTitleColor = disabledTitleColor
}
@ -110,72 +105,46 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
#endif
if isEnabled {
if let fillColor = buttonModel?.enabledColors.fill {
if let fillColor = model?.enabledColors.fill {
backgroundColor = fillColor
}
if let borderColor = buttonModel?.enabledColors.border {
layer.borderWidth = 1
if let borderColor = model?.enabledColors.border {
self.borderColor = borderColor
}
} else {
if let fillColor = buttonModel?.disabledColors.fill {
if let fillColor = model?.disabledColors.fill {
backgroundColor = fillColor
}
if let borderColor = buttonModel?.disabledColors.border {
layer.borderWidth = 1
if let borderColor = model?.disabledColors.border {
self.borderColor = borderColor
}
}
}
private func getInnerPadding() -> CGFloat {
getHeight() / 2.0
buttonSize.getHeight() / 2.0
}
private func getHeight() -> CGFloat {
PillButton.getHeight(for: buttonSize, size: size)
}
public static func getHeight(for buttonSize: Styler.Button.Size?, size: CGFloat) -> CGFloat {
private func getContentEdgeInsets() -> UIEdgeInsets {
var verticalPadding = 0.0
var horizontalPadding = 0.0
switch buttonSize {
case .standard:
verticalPadding = Padding.Three
horizontalPadding = Padding.Five
break
case .small:
verticalPadding = Padding.Two
horizontalPadding = Padding.Four
break
case .tiny:
let tinyHeight = Styler.Button.Size.tiny.getHeight()
return MFSizeObject(standardSize: tinyHeight,
standardiPadPortraitSize: 34,
iPadProLandscapeSize: 38)?.getValueBased(onSize: size) ?? tinyHeight
default:
let standardHeight = Styler.Button.Size.standard.getHeight()
return MFSizeObject(standardSize: standardHeight,
standardiPadPortraitSize: 46,
iPadProLandscapeSize: 50)?.getValueBased(onSize: size) ?? standardHeight
}
}
private func getMinimumWidth() -> CGFloat {
switch buttonSize {
case .tiny:
return MFSizeObject(standardSize: 49,
standardiPadPortraitSize: 90,
iPadProLandscapeSize: 135)?.getValueBased(onSize: size) ?? 49
default: return 151
}
}
open override var intrinsicContentSize: CGSize {
if buttonSize == .tiny {
let size = super.intrinsicContentSize
let width = size.width + (2 * getInnerPadding())
return CGSize(width: max(width, getMinimumWidth()), height: getHeight())
} else {
let width = Padding.Component.gutterForApplicationWidth + (2.0 * Padding.Component.columnFor(size: MVMCoreUISplitViewController.getApplicationViewWidth()))
return CGSize(width: min(292, width), height: getHeight())
verticalPadding = Padding.One
horizontalPadding = Padding.Two
break
}
return UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
}
//--------------------------------------------------
@ -187,7 +156,11 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ButtonModel else { return }
setTitle(model.title, for: .normal)
if let accessibilityText = model.accessibilityText {
accessibilityLabel = accessibilityText
}
if let size = model.size {
buttonSize = size
@ -203,24 +176,44 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
PillButton.getHeight(for: (model as? ButtonModel)?.size, size: MVMCoreUIUtility.getWidth())
return (model as? ButtonModel)?.size?.getHeight()
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
self.size = size
invalidateIntrinsicContentSize()
switch buttonSize {
case .tiny:
titleLabel?.font = MFFonts.mfFont75Bd(11 * (intrinsicContentSize.height / Styler.Button.Size.tiny.getHeight()))
default:
titleLabel?.font = MFFonts.mfFont75Bd(13 * (intrinsicContentSize.height / Styler.Button.Size.standard.getHeight()))
titleLabel?.font = Styler.Font.BoldMicro.getFont(false)
case .small:
titleLabel?.font = Styler.Font.BoldBodySmall.getFont(false)
case .standard:
titleLabel?.font = Styler.Font.BoldBodyLarge.getFont(false)
}
layer.cornerRadius = getInnerPadding()
contentEdgeInsets = getContentEdgeInsets()
if let contraint = buttonModel?.width {
if widthConstraint == nil {
widthConstraint = widthAnchor.constraint(equalToConstant: contraint)
} else if widthConstraint?.constant != contraint {
widthConstraint?.constant = contraint
}
widthConstraint?.isActive = true
minimumWidthConstraint?.isActive = false
} else {
if minimumWidthConstraint == nil {
minimumWidthConstraint = widthAnchor.constraint(greaterThanOrEqualToConstant: buttonSize.minimumWidth())
} else {
minimumWidthConstraint?.constant = buttonSize.minimumWidth()
}
minimumWidthConstraint?.isActive = true
widthConstraint?.isActive = false
}
}
open override func setupView() {

View File

@ -7,6 +7,7 @@
//
import Foundation
import MVMCore
@objcMembers public class TagModel: MoleculeModelProtocol {
public static var identifier: String = "tag"
@ -27,6 +28,14 @@ import Foundation
}
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(label: LabelModel) {
self.label = label
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
label = try typeContainer.decode(LabelModel.self, forKey: .label)

View File

@ -7,6 +7,7 @@
//
import Foundation
import MVMCore
@objcMembers public class TagsModel: MoleculeModelProtocol {
public static var identifier: String = "tags"
@ -19,6 +20,14 @@ import Foundation
case tags
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with tags: [TagModel]) {
self.tags = tags
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
tags = try typeContainer.decode([TagModel].self, forKey: .tags)

View File

@ -38,29 +38,6 @@ import UIKit
// Default dimensions of the DigitBox
static let size: CGSize = CGSize(width: 39, height: 44)
//--------------------------------------------------
// MARK: - Computed Properties
//--------------------------------------------------
public override var showError: Bool {
get { super.showError }
set (error) {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.borderStrokeColor = error ? .mvmOrange : .mvmCoolGray3
let barHeight: CGFloat = self.showError ? 4 : 1
self.bottomBar?.frame = CGRect(x: 0, y: self.bounds.height - barHeight, width: self.bounds.width, height: barHeight)
self.bottomBar?.backgroundColor = self.showError ? UIColor.mvmOrange.cgColor : UIColor.mvmBlack.cgColor
self.setNeedsDisplay()
self.layoutIfNeeded()
}
super.showError = error
}
}
//--------------------------------------------------
// MARK: - Delegate
//--------------------------------------------------

View File

@ -105,7 +105,7 @@ import UIKit
super.isLocked = locked
}
}
public override var placeholder: String? {
get {
var string = ""
@ -249,6 +249,10 @@ import UIKit
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
public override func showErrorView(_ show: Bool) {
//do nothing since you should show the error view
//within a digitEntryField
}
@objc public func setAsSecureTextEntry(_ secureEntry: Bool) {
@ -311,7 +315,6 @@ import UIKit
//--------------------------------------------------
@objc override func startEditing() {
selectedDigitBox?.isSelected = true
selectedDigitBox?.digitField.becomeFirstResponder()
}
@ -328,7 +331,6 @@ import UIKit
}
@objc public override func dismissFieldInput(_ sender: Any?) {
digitBoxes.forEach {
if $0.isSelected {
$0.digitField.resignFirstResponder()
@ -398,7 +400,6 @@ extension DigitEntryField {
digitEntryModel?.text = text
return false
}
return true
}
@ -411,9 +412,9 @@ extension DigitEntryField {
}
@objc public func textFieldDidBeginEditing(_ textField: UITextField) {
digitBoxes.forEach {
if $0.digitField === textField {
startEditing()
selectedDigitBox = $0
$0.isSelected = true
return
@ -429,15 +430,15 @@ extension DigitEntryField {
}
@objc public func textFieldDidEndEditing(_ textField: UITextField) {
// There should only be one digitBox to deselect.
selectedDigitBox?.isSelected = false
selectedDigitBox = nil
if !switchFieldsAutomatically && validateWhenDoneEditing {
validateText()
endInputing()
}
proprietorTextDelegate?.textFieldDidEndEditing?(textField)
}

View File

@ -44,7 +44,7 @@ import UIKit
super.isEnabled = enabled
}
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------

View File

@ -21,6 +21,7 @@
//--------------------------------------------------
public override func formFieldValue() -> AnyHashable? {
guard enabled else { return nil }
guard !options.isEmpty,
let index = selectedIndex
else { return nil }
@ -57,6 +58,6 @@
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(options, forKey: .options)
try container.encodeIfPresent(options, forKey: .selectedIndex)
try container.encodeIfPresent(selectedIndex, forKey: .selectedIndex)
}
}

View File

@ -25,7 +25,7 @@ import Foundation
//--------------------------------------------------
public override func formFieldValue() -> AnyHashable? {
guard enabled else { return nil }
guard !components.isEmpty && !selectedIndexes.isEmpty else { return nil }
return selectedRowText

View File

@ -17,11 +17,8 @@ import UIKit
//--------------------------------------------------
// MARK: - Outlets
//--------------------------------------------------
public private(set) var titleLabel: Label = {
let label = Label()
label.font = Styler.Font.RegularMicro.getFont()
label.textColor = .mvmBlack
public private(set) var titleLabel: FormLabel = {
let label = FormLabel()
label.setContentCompressionResistancePriority(.required, for: .vertical)
return label
}()
@ -29,14 +26,33 @@ import UIKit
public private(set) var entryFieldContainer = EntryFieldContainer()
/// Provides contextual information on the TextField.
public private(set) var feedbackLabel: Label = {
public private(set) var feedbackLabel: FormLabel = {
let label = FormLabel()
label.setContentCompressionResistancePriority(.required, for: .vertical)
return label
}()
public private(set) var errorLabel: Label = {
let label = Label()
label.font = Styler.Font.RegularMicro.getFont()
label.setFontStyle(.RegularMicro)
label.textColor = .mvmBlack
label.setContentCompressionResistancePriority(.required, for: .vertical)
return label
}()
public lazy var stack: UIStackView = {
errorLabel.isHidden = true
let stack = UIStackView(arrangedSubviews: [titleLabel, entryFieldContainer, errorLabel, feedbackLabel])
stack.axis = .vertical
stack.alignment = .fill
stack.distribution = .fill
stack.setCustomSpacing(Padding.One, after: titleLabel)
stack.setCustomSpacing(Padding.Two, after: entryFieldContainer)
stack.setCustomSpacing(Padding.One, after: errorLabel)
stack.translatesAutoresizingMaskIntoConstraints = false
return stack
}()
//--------------------------------------------------
// MARK: - Delegate
//--------------------------------------------------
@ -46,7 +62,6 @@ import UIKit
//--------------------------------------------------
// MARK: - Stored Properties
//--------------------------------------------------
public var isValid: Bool = false
/// Validate on each entry in the textField. Default: true
@ -60,19 +75,32 @@ import UIKit
public var isEnabled: Bool {
get { entryFieldContainer.isEnabled }
set (enabled) {
titleLabel.textColor = enabled ? .mvmBlack : .mvmCoolGray3
feedbackLabel.textColor = enabled ? .mvmBlack : .mvmCoolGray3
entryFieldContainer.isEnabled = enabled
entryFieldModel?.enabled = enabled
if(entryFieldContainer.isEnabled != enabled){
titleLabel.isEnabled = enabled
feedbackLabel.isEnabled = enabled
entryFieldContainer.isEnabled = enabled
entryFieldModel?.enabled = enabled
}
}
}
/// Toggles enabled (original) or disabled UI.
public var isRequired: Bool = true {
didSet{
titleLabel.isRequired = isRequired
}
}
/// Toggles error or original UI.
public var showError: Bool {
get { entryFieldContainer.showError }
set (error) {
feedback = error ? errorMessage : entryFieldModel?.feedback
feedbackLabel.textColor = error ? entryFieldModel?.errorTextColor?.uiColor ?? .mvmBlack : .mvmBlack
if error {
errorLabel.text = self.errorMessage ?? ""
errorLabel.isHidden = false
} else {
errorLabel.isHidden = true
}
entryFieldContainer.showError = error
entryFieldModel?.showError = error
}
@ -104,11 +132,11 @@ import UIKit
public var title: String? {
get { titleLabel.text }
set {
titleLabel.text = newValue
titleLabel.set(text: newValue ?? "")
setAccessibilityString(newValue)
}
}
/// Override this to conveniently get/set the textfield(s).
public var text: String? {
get { nil }
@ -119,7 +147,7 @@ import UIKit
public var feedback: String? {
get { feedbackLabel.text }
set {
feedbackLabel.text = newValue
feedbackLabel.set(text: newValue ?? "")
feedbackLabel.accessibilityElementsHidden = feedbackLabel.text?.isEmpty ?? true
}
}
@ -128,22 +156,6 @@ import UIKit
model as? EntryFieldModel
}
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
public var entryFieldContainerLeading: NSLayoutConstraint?
public var entryFieldContainerTrailing: NSLayoutConstraint?
public var feedbackLabelTrailing: NSLayoutConstraint?
public var feedbackLabelLeading: NSLayoutConstraint?
public var titleLabelLeading: NSLayoutConstraint?
public var titleLabelTrailing: NSLayoutConstraint?
public var titleContainerDistance: NSLayoutConstraint?
public var feedbackContainerDistance: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@ -183,37 +195,18 @@ import UIKit
isAccessibilityElement = false
setContentCompressionResistancePriority(.required, for: .vertical)
accessibilityElements = [titleLabel, feedbackLabel]
accessibilityElements = [titleLabel, errorLabel, feedbackLabel]
backgroundColor = .mvmWhite
addSubview(titleLabel)
titleLabel.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true
titleLabelLeading = titleLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
titleLabelLeading?.isActive = true
titleLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: titleLabel.trailingAnchor)
titleLabelLeading?.isActive = true
addSubview(entryFieldContainer)
addSubview(stack)
entryFieldContainer.setContentCompressionResistancePriority(.required, for: .vertical)
setupFieldContainerContent(entryFieldContainer)
titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: Padding.One)
titleContainerDistance?.isActive = true
entryFieldContainerLeading = entryFieldContainer.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
entryFieldContainerLeading?.isActive = true
entryFieldContainerTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: entryFieldContainer.trailingAnchor)
entryFieldContainerTrailing?.isActive = true
addSubview(feedbackLabel)
feedbackContainerDistance = feedbackLabel.topAnchor.constraint(equalTo: entryFieldContainer.bottomAnchor, constant: Padding.Two)
feedbackContainerDistance?.isActive = true
feedbackLabelLeading = feedbackLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
feedbackLabelLeading?.isActive = true
feedbackLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: feedbackLabel.trailingAnchor)
feedbackLabelTrailing?.isActive = true
layoutMarginsGuide.bottomAnchor.constraint(equalTo: feedbackLabel.bottomAnchor).isActive = true
stack.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true
stack.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true
layoutMarginsGuide.trailingAnchor.constraint(equalTo: stack.trailingAnchor).isActive = true
layoutMarginsGuide.bottomAnchor.constraint(equalTo: stack.bottomAnchor).isActive = true
}
@objc open override func layoutSubviews() {
@ -229,10 +222,7 @@ import UIKit
@objc open override func updateView(_ size: CGFloat) {
super.updateView(size)
titleLabel.updateView(size)
feedbackLabel.updateView(size)
entryFieldContainer.updateView(size)
stack.updateView(size)
}
//--------------------------------------------------
@ -290,19 +280,30 @@ import UIKit
titleLabel.textColor = .mvmBlack
feedbackLabel.font = Styler.Font.RegularMicro.getFont()
feedbackLabel.textColor = .mvmBlack
errorLabel.font = Styler.Font.RegularMicro.getFont()
errorLabel.textColor = .mvmBlack
errorLabel.text = nil
entryFieldContainer.disableAllBorders = false
feedbackLabel.text = nil
entryFieldContainer.reset()
entryFieldModel?.updateUI = nil
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
self.delegateObject = delegateObject
guard let model = model as? EntryFieldModel else { return }
guard let model = entryFieldModel else { return }
entryFieldContainer.set(with: model, delegateObject, additionalData)
//setup the properties for setting models
//later with enabled/showError
titleLabel.setup(model: model.titleStateLabel, delegateObject, additionalData)
feedbackLabel.setup(model: model.feedbackStateLabel, delegateObject, additionalData)
isEnabled = model.enabled && !model.readOnly
isRequired = model.required
model.updateUI = { [weak self] in
MVMCoreDispatchUtility.performBlock(onMainThread: {
guard let self = self else { return }
@ -313,6 +314,8 @@ import UIKit
} else if model.isValid ?? true && self.showError {
self.showError = false
}
self.isEnabled = model.enabled
self.text = model.text
})
}
@ -328,13 +331,10 @@ import UIKit
self.updateValidation(validState)
})
}
title = model.title
feedback = model.feedback
isEnabled = model.enabled
entryFieldContainer.disableAllBorders = model.hideBorders
accessibilityIdentifier = model.accessibilityIdentifier ?? model.fieldKey
if let isLocked = model.locked {
self.isLocked = isLocked
@ -364,3 +364,11 @@ extension EntryField {
// To Be Overriden
}
}
extension LabelModel {
public convenience init(text: String = "", fontStyle: Styler.Font, textColor: Color) {
self.init(text: text)
self.fontStyle = fontStyle
self.textColor = textColor
}
}

View File

@ -9,7 +9,8 @@
import Foundation
@objcMembers open class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, EnableableModelProtocol {
@objcMembers open class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, UIUpdatableModelProtocol, ClearableModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
@ -18,8 +19,6 @@ import Foundation
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var title: String?
public var feedback: String?
public var shouldClearText: Bool = false
public var dynamicErrorMessage: String? {
didSet {
@ -30,6 +29,8 @@ import Foundation
public var errorMessage: String?
public var errorTextColor: Color?
public var enabled: Bool = true
public var required: Bool = true
public var readOnly: Bool = false
public var showError: Bool?
public var hideBorders = false
public var locked: Bool?
@ -39,7 +40,13 @@ import Foundation
public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable?
public var wasInitiallySelected: Bool = false
public var title: String?
public var feedback: String?
//used to drive the EntryFieldView UI
public var titleStateLabel: FormLabelModel
public var feedbackStateLabel: FormLabelModel
public var isValid: Bool? = true {
didSet { updateUI?() }
}
@ -60,6 +67,7 @@ import Foundation
case accessibilityIdentifier
case title
case enabled
case readOnly
case feedback
case errorMessage
case errorTextColor
@ -70,6 +78,7 @@ import Foundation
case text
case fieldKey
case groupName
case required
}
//--------------------------------------------------
@ -77,22 +86,24 @@ import Foundation
//--------------------------------------------------
public func formFieldValue() -> AnyHashable? {
guard enabled else { return nil }
if dynamicErrorMessage != nil {
dynamicErrorMessage = nil
}
return text
}
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
public func setValidity(_ valid: Bool, errorMessage: String?) {
if let fieldKey = fieldKey, let ruleErrorMessage = rule.errorMessage?[fieldKey] {
if let ruleErrorMessage = errorMessage, fieldKey != nil {
self.errorMessage = ruleErrorMessage
}
self.isValid = valid
updateUI?()
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@ -100,6 +111,15 @@ import Foundation
public init(with text: String) {
self.text = text
baseValue = text
self.titleStateLabel = FormLabelModel(text: "")
self.feedbackStateLabel = FormLabelModel(text: "")
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
public func clear() {
self.text = ""
}
//--------------------------------------------------
@ -115,16 +135,21 @@ import Foundation
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage)
errorTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .errorTextColor)
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
required = try typeContainer.decodeIfPresent(Bool.self, forKey: .required) ?? true
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked)
selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected)
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
hideBorders = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideBorders) ?? false
baseValue = text
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
self.groupName = groupName
}
self.titleStateLabel = FormLabelModel(text: title ?? "")
self.feedbackStateLabel = FormLabelModel(model: LabelModel(text: feedback ?? "",
fontStyle: FormLabelModel.defaultFontStyle,
textColor: Color(uiColor: .mvmCoolGray6)))
}
public func encode(to encoder: Encoder) throws {
@ -142,7 +167,10 @@ import Foundation
try container.encodeIfPresent(errorMessage, forKey: .errorMessage)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encodeIfPresent(groupName, forKey: .groupName)
try container.encode(readOnly, forKey: .readOnly)
try container.encode(enabled, forKey: .enabled)
try container.encode(required, forKey: .required)
try container.encode(hideBorders, forKey: .hideBorders)
}
}

View File

@ -84,7 +84,7 @@ import UIKit
textField.accessibilityValue = nil
}
if textField.isSecureTextEntry {
if !textField.isSecureTextEntry {
showErrorView(error)
}
@ -247,6 +247,10 @@ import UIKit
/// Executes on UITextField.textDidChangeNotification (each character entry)
@objc override func valueChanged() {
super.valueChanged()
if (textEntryFieldModel?.type == .email) {
// remove spaces (either user entered Or auto-correct suggestion) for the email field
textField.text = textField.text?.replacingOccurrences(of: " ", with: "")
}
validateText()
}
@ -290,8 +294,7 @@ import UIKit
resignFirstResponder()
}
private func showErrorView(_ show: Bool) {
open func showErrorView(_ show: Bool) {
if show {
entryFieldContainer.addSubview(errorImage)

View File

@ -38,6 +38,14 @@
public var displayFormat: String?
public var displayMask: String?
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
public override init(with text: String){
super.init(with: text)
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
@ -137,7 +145,7 @@
}
}
public override func encode(to encoder: Encoder) throws {
open override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(placeholder, forKey: .placeholder)

View File

@ -46,7 +46,7 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele
if self.textView.isShowingPlaceholder {
self.textView.textColor = self.textView.placeholderTextColor
} else {
self.textView.textColor = (enabled ? self.textViewEntryFieldModel?.enabledTextColor : self.textViewEntryFieldModel?.disabledTextColor)?.uiColor
self.textView.textColor = (self.textView.isEnabled ? self.textViewEntryFieldModel?.enabledTextColor : self.textViewEntryFieldModel?.disabledTextColor)?.uiColor
}
}
}
@ -282,8 +282,5 @@ class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDele
adjustMarginConstraints(constant: 0)
}
if !model.enabled {
isEnabled = false
}
}
}

View File

@ -95,7 +95,7 @@ import MVMCore
}
}
}
public var disabledBackgroundColor: UIColor = .clear
public var disabledBorderColor: UIColor = .mvmCoolGray3
public var disabledCheckColor: UIColor = .mvmCoolGray3
@ -423,7 +423,14 @@ import MVMCore
checkAndBypassAnimations(selected: model.selected)
}
isEnabled = model.enabled
model.updateUI = { [weak self] in
MVMCoreDispatchUtility.performBlock(onMainThread: {
guard let self = self else { return }
self.isEnabled = model.enabled
})
}
isEnabled = model.enabled && !model.readOnly
if (model.action != nil || model.offAction != nil) {
actionBlock = { [weak self] in

View File

@ -13,7 +13,8 @@
var selected: Bool { get set }
}
@objcMembers public class CheckboxModel: MoleculeModelProtocol, SelectableMoleculeModelProtocol, FormFieldProtocol {
@objcMembers public class CheckboxModel: MoleculeModelProtocol, SelectableMoleculeModelProtocol, FormFieldProtocol, UIUpdatableModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
@ -23,6 +24,7 @@
public var accessibilityIdentifier: String?
public var selected: Bool = false
public var enabled: Bool = true
public var readOnly: Bool = false
public var animated: Bool = true
public var inverted: Bool = false
public var round: Bool = false
@ -42,6 +44,7 @@
public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable?
public var updateUI: ActionBlock?
//--------------------------------------------------
// MARK: - Keys
@ -52,6 +55,7 @@
case accessibilityIdentifier
case checked
case enabled
case readOnly
case inverted
case animated
case round
@ -75,7 +79,10 @@
// MARK: - Form Validation
//--------------------------------------------------
public func formFieldValue() -> AnyHashable? { selected }
public func formFieldValue() -> AnyHashable? {
guard enabled else { return nil }
return selected
}
//--------------------------------------------------
// MARK: - Initializer
@ -153,10 +160,8 @@
self.inverted = inverted
}
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
self.enabled = enabled
}
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
@ -186,7 +191,8 @@
try container.encodeIfPresent(disabledCheckColor, forKey: .disabledCheckColor)
try container.encodeIfPresent(animated, forKey: .animated)
try container.encodeIfPresent(round, forKey: .round)
try container.encodeIfPresent(enabled, forKey: .enabled)
try container.encode(enabled, forKey: .enabled)
try container.encode(readOnly, forKey: .readOnly)
try container.encodeModelIfPresent(action, forKey: .action)
try container.encodeIfPresent(groupName, forKey: .groupName)
try container.encodeModelIfPresent(offAction, forKey: .offAction)

View File

@ -62,7 +62,7 @@ import UIKit
heartPath.close()
heart.path = heartPath.cgPath
heart.fillColor = isSelected ? heartModel?.activeColor.cgColor : heartModel?.inActiveColor.cgColor
heart.opacity = 1.0
heart.opacity = isEnabled ? 1.0 : 0.5
heart.lineWidth = 1
heart.strokeColor = isSelected ? UIColor.clear.cgColor : UIColor.mvmBlack.cgColor
return heart
@ -88,7 +88,7 @@ import UIKit
self.additionalData = additionalData
guard let model = model as? HeartModel else { return }
isSelected = model.isActive
isEnabled = model.enabled
isEnabled = model.enabled && !model.readOnly
updateAccessibilityLabel()
}

View File

@ -5,7 +5,7 @@
// Created by Lekshmi S on 07/09/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
@ -21,8 +21,8 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
public var inActiveColor: Color = Color(uiColor: .clear)
public var action: ActionModelProtocol = ActionNoopModel()
public var enabled: Bool = true
//--------------------------------------------------
public var readOnly: Bool = false
// MARK: - Keys
//--------------------------------------------------
@ -35,8 +35,14 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
case inActiveColor
case action
case enabled
case readOnly
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() { }
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
@ -61,9 +67,8 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
if let action: ActionModelProtocol = try typeContainer.decodeModelIfPresent(codingKey: .action) {
self.action = action
}
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
self.enabled = enabled
}
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
}
public func encode(to encoder: Encoder) throws {
@ -76,5 +81,6 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
try container.encode(inActiveColor, forKey: .inActiveColor)
try container.encodeModel(action, forKey: .action)
try container.encode(enabled, forKey: .enabled)
try container.encode(readOnly, forKey: .readOnly)
}
}

View File

@ -39,7 +39,7 @@ open class RadioBox: Control, MFButtonProtocol {
public override var isEnabled: Bool {
didSet { updateAccessibility() }
}
//--------------------------------------------------
// MARK: - MVMCoreViewProtocol
//--------------------------------------------------
@ -89,7 +89,7 @@ open class RadioBox: Control, MFButtonProtocol {
accentColor = color
}
isSelected = model.selected
isEnabled = model.enabled
isEnabled = model.enabled && !model.readOnly
}
open override func reset() {

View File

@ -5,8 +5,9 @@
// Created by Dhamodaram Nandi on 31/03/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
@objcMembers public class RadioBoxModel: MoleculeModelProtocol {
@objcMembers public class RadioBoxModel: MoleculeModelProtocol, EnableableModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
@ -19,6 +20,7 @@
public var selectedAccentColor: Color?
public var selected: Bool = false
public var enabled: Bool = true
public var readOnly: Bool = false
public var strikethrough: Bool = false
public var fieldValue: String?
public var action: ActionModelProtocol?
@ -39,6 +41,15 @@
case strikethrough
case fieldValue
case action
case readOnly
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(text: String) {
self.text = text
}
//--------------------------------------------------
@ -57,9 +68,8 @@
selected = isSelected
}
if let isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
enabled = isEnabled
}
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) {
strikethrough = isStrikeTrough
@ -79,6 +89,7 @@
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
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.encodeIfPresent(fieldValue, forKey: .fieldValue)
try container.encodeModelIfPresent(action, forKey: .action)

View File

@ -5,6 +5,7 @@
// Created by Dhamodaram Nandi on 31/03/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
@objcMembers public class RadioBoxesModel: MoleculeModelProtocol, FormFieldProtocol {
//--------------------------------------------------
@ -20,13 +21,15 @@
public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable?
public var enabled: Bool = true
public var readOnly: Bool = false
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
/// Returns the fieldValue of the selected box, otherwise the text of the selected box.
public func formFieldValue() -> AnyHashable? {
guard enabled else { return nil }
let selectedBox = boxes.first { (box) -> Bool in
return box.selected
}
@ -39,6 +42,8 @@
private enum CodingKeys: String, CodingKey {
case moleculeName
case enabled
case readOnly
case selectedAccentColor
case backgroundColor
case accessibilityIdentifier
@ -48,6 +53,14 @@
case groupName
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with boxes: [RadioBoxModel]){
self.boxes = boxes
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
@ -63,6 +76,8 @@
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
baseValue = formFieldValue()
}
@ -75,5 +90,7 @@
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encode(groupName, forKey: .groupName)
try container.encode(enabled, forKey: .enabled)
try container.encode(readOnly, forKey: .readOnly)
}
}

View File

@ -66,7 +66,7 @@ import UIKit
open override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
let color = isEnabled ? enabledColor.cgColor : disabledColor.cgColor
let color = isEnabled == false ? disabledColor.cgColor : enabledColor.cgColor
layer.cornerRadius = bounds.width * 0.5
layer.borderColor = color
layer.borderWidth = bounds.width * 0.0333
@ -118,7 +118,8 @@ import UIKit
}
public func formFieldValue() -> AnyHashable? {
radioModel?.fieldValue
guard let radioModel = radioModel, radioModel.enabled else { return nil }
return radioModel.fieldValue
}
//--------------------------------------------------
@ -162,7 +163,7 @@ import UIKit
guard let model = model as? RadioButtonModel else { return }
isSelected = model.state
isEnabled = model.enabled
isEnabled = model.enabled && !model.readOnly
RadioButtonSelectionHelper.setupForRadioButtonGroup(model, self, delegateObject: delegateObject)
}

View File

@ -19,6 +19,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
public var accessibilityIdentifier: String?
public var state: Bool = false
public var enabled: Bool = true
public var readOnly: Bool = false
/// The specific value to send to server. TODO: update this to be more generic.
public var fieldValue: String?
@ -42,6 +43,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
case fieldKey
case groupName
case action
case readOnly
}
//--------------------------------------------------
@ -57,7 +59,10 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
// MARK: - Validation
//--------------------------------------------------
public func formFieldValue() -> AnyHashable? { fieldValue }
public func formFieldValue() -> AnyHashable? {
guard enabled else { return nil }
return fieldValue
}
//--------------------------------------------------
// MARK: - Codec
@ -69,11 +74,9 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) {
self.state = state
}
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
self.enabled = enabled
}
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
@ -93,6 +96,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(state, forKey: .state)
try container.encode(enabled, forKey: .enabled)
try container.encode(readOnly, forKey: .readOnly)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encodeIfPresent(groupName, forKey: .groupName)
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)

View File

@ -17,6 +17,8 @@
private var selectedRadioButton: RadioButton?
private var selectedRadioButtonModel: RadioButtonModel?
public var baseValue: AnyHashable?
public var enabled: Bool = true
public var readOnly: Bool = false
//--------------------------------------------------
// MARK: - Initializer
@ -39,6 +41,8 @@
} else {
radioButton.isSelected = false
}
self.enabled = radioButtonModel.enabled
self.readOnly = radioButtonModel.readOnly
}
//--------------------------------------------------
@ -75,5 +79,8 @@
// MARK: - FormValidationFormFieldProtocol
extension RadioButtonSelectionHelper {
public func formFieldValue() -> AnyHashable? { selectedRadioButtonModel?.fieldValue }
public func formFieldValue() -> AnyHashable? {
guard enabled else { return nil }
return selectedRadioButtonModel?.fieldValue
}
}

View File

@ -38,7 +38,7 @@ open class RadioSwatch: Control, MFButtonProtocol {
updateAccessibility()
}
}
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
@ -64,7 +64,7 @@ open class RadioSwatch: Control, MFButtonProtocol {
self.additionalData = additionalData
bottomText.text = model.text
isSelected = model.selected
isEnabled = model.enabled
isEnabled = model.enabled && !model.readOnly
}
public override func reset() {

View File

@ -5,9 +5,9 @@
// Created by Scott Pfeil on 4/17/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
@objcMembers public class RadioSwatchModel: MoleculeModelProtocol {
@objcMembers public class RadioSwatchModel: MoleculeModelProtocol, EnableableModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
@ -19,6 +19,7 @@
public var text: String?
public var selected: Bool = false
public var enabled: Bool = true
public var readOnly: Bool = false
public var strikethrough: Bool = false
public var fieldValue: String?
public var action: ActionModelProtocol?
@ -38,8 +39,15 @@
case strikethrough
case fieldValue
case action
case readOnly
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
@ -58,17 +66,15 @@
if let selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) {
self.selected = selected
}
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
self.enabled = enabled
}
if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) {
self.strikethrough = strikethrough
}
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
}
public func encode(to encoder: Encoder) throws {
@ -83,5 +89,6 @@
try container.encode(strikethrough, forKey: .strikethrough)
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
try container.encodeModelIfPresent(action, forKey: .action)
try container.encode(readOnly, forKey: .readOnly)
}
}

View File

@ -5,7 +5,7 @@
// Created by Lekshmi S on 31/03/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
@objcMembers public class RadioSwatchesModel: MoleculeModelProtocol, FormFieldProtocol {
//--------------------------------------------------
@ -19,6 +19,8 @@
public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable?
public var enabled: Bool = true
public var readOnly: Bool = false
//--------------------------------------------------
// MARK: - Methods
@ -26,6 +28,7 @@
/// Returns the fieldValue of the selected swatch, otherwise the text of selected swatch.
public func formFieldValue() -> AnyHashable? {
guard enabled else { return nil }
let selectedSwatch = swatches.first { (swatch) -> Bool in
return swatch.selected
}
@ -43,6 +46,16 @@
case swatches
case fieldKey
case groupName
case enabled
case readOnly
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with swatches: [RadioSwatchModel]){
self.swatches = swatches
}
//--------------------------------------------------
@ -58,6 +71,8 @@
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
baseValue = formFieldValue()
}
@ -69,5 +84,7 @@
try container.encode(swatches, forKey: .swatches)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encode(groupName, forKey: .groupName)
try container.encode(enabled, forKey: .enabled)
try container.encode(readOnly, forKey: .readOnly)
}
}

View File

@ -66,7 +66,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: isEnabled ? "AccToggleHint" : "AccDisabled")
}
}
/// Simple means to prevent user interaction with the toggle.
public var isLocked: Bool = false {
didSet { isUserInteractionEnabled = !isLocked }
@ -384,7 +384,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
isOn = model.selected
changeStateNoAnimation(isOn)
isAnimated = model.animated
isEnabled = model.enabled
isEnabled = model.enabled && !model.readOnly
if let accessibileString = model.accessibilityText {
accessibilityLabel = accessibileString

View File

@ -7,7 +7,7 @@
//
public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol {
public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
@ -18,6 +18,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
public var selected: Bool = false
public var animated: Bool = true
public var enabled: Bool = true
public var readOnly: Bool = false
public var action: ActionModelProtocol?
public var alternateAction: ActionModelProtocol?
public var accessibilityText: String?
@ -39,6 +40,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
case state
case animated
case enabled
case readOnly
case action
case backgroundColor
case accessibilityIdentifier
@ -56,7 +58,10 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
// MARK: - Form Valdiation
//--------------------------------------------------
public func formFieldValue() -> AnyHashable? { selected }
public func formFieldValue() -> AnyHashable? {
guard enabled else { return nil }
return selected
}
//--------------------------------------------------
// MARK: - Initializer
@ -78,10 +83,6 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
self.selected = state
}
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
self.enabled = enabled
}
if let animated = try typeContainer.decodeIfPresent(Bool.self, forKey: .animated) {
self.animated = animated
}
@ -114,6 +115,8 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
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
}
public func encode(to encoder: Encoder) throws {
@ -133,5 +136,6 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encodeIfPresent(groupName, forKey: .groupName)
try container.encode(readOnly, forKey: .readOnly)
}
}

View File

@ -9,7 +9,7 @@
import UIKit
open class ArrowModel: MoleculeModelProtocol {
open class ArrowModel: MoleculeModelProtocol, EnableableModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------

View File

@ -7,7 +7,7 @@
//
import Foundation
import MVMCore
@objcMembers public class CaretViewModel: MoleculeModelProtocol {
//--------------------------------------------------
@ -38,6 +38,12 @@ import Foundation
case inverted
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -20,6 +20,8 @@ open class BarsIndicatorView: CarouselIndicator {
static let width: CGFloat = 24
static let selectedHeight: CGFloat = 4
static let unselectedHeight: CGFloat = 1
static let selectedCornerRadius: CGFloat = 2
static let unselectedCornerRadius: CGFloat = 0.5
var constraint: NSLayoutConstraint?
@ -38,6 +40,7 @@ open class BarsIndicatorView: CarouselIndicator {
override func setupView() {
super.setupView()
isAccessibilityElement = true
layer.cornerRadius = 2
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccTabHint")
widthAnchor.constraint(equalToConstant: BarsIndicatorView.IndicatorBar.width).isActive = true
accessibilityTraits = .button
@ -52,7 +55,7 @@ open class BarsIndicatorView: CarouselIndicator {
stackView.axis = .horizontal
stackView.alignment = .bottom
stackView.distribution = .equalSpacing
stackView.spacing = 6
stackView.spacing = 4
return stackView
}()
@ -79,7 +82,7 @@ open class BarsIndicatorView: CarouselIndicator {
}
}
}
/// Colors the currently selected index, unique from other indicators
public var currentIndicatorColor: UIColor {
get { barsCarouselIndicatorModel?.currentIndicatorColor.uiColor ?? indicatorColor }
@ -189,6 +192,7 @@ open class BarsIndicatorView: CarouselIndicator {
let bar = IndicatorBar()
setAccessibilityLabel(view: bar, index: index)
bar.backgroundColor = isEnabled ? (index == currentIndex ? currentIndicatorColor : indicatorColor) : disabledIndicatorColor
bar.layer.cornerRadius = index == currentIndex ? BarsIndicatorView.IndicatorBar.selectedCornerRadius : BarsIndicatorView.IndicatorBar.unselectedCornerRadius
let barHeight = index == currentIndex ? BarsIndicatorView.IndicatorBar.selectedHeight : BarsIndicatorView.IndicatorBar.unselectedHeight
let heightConstraint = bar.heightAnchor.constraint(equalToConstant: barHeight)
heightConstraint.isActive = true
@ -251,6 +255,7 @@ open class BarsIndicatorView: CarouselIndicator {
barReferences.forEach {
$0.backgroundColor = isEnabled ? indicatorColor : disabledIndicatorColor
$0.constraint?.constant = IndicatorBar.unselectedHeight
$0.layer.cornerRadius = IndicatorBar.unselectedCornerRadius
}
balanceBarCount(numberOfPages - barReferences.count)
@ -260,8 +265,10 @@ open class BarsIndicatorView: CarouselIndicator {
let expression = { [self] in
barReferences[previousIndex].backgroundColor = isEnabled ? indicatorColor : disabledIndicatorColor
barReferences[previousIndex].constraint?.constant = IndicatorBar.unselectedHeight
barReferences[previousIndex].layer.cornerRadius = IndicatorBar.unselectedCornerRadius
barReferences[newIndex].backgroundColor = isEnabled ? currentIndicatorColor : disabledIndicatorColor
barReferences[newIndex].constraint?.constant = IndicatorBar.selectedHeight
barReferences[newIndex].layer.cornerRadius = IndicatorBar.selectedCornerRadius
layoutIfNeeded()
}

View File

@ -5,7 +5,7 @@
// Created by Kevin Christiano on 1/30/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import VDSColorTokens
open class CarouselIndicator: Control, CarouselPageControlProtocol {
//--------------------------------------------------
@ -71,13 +71,22 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
}
public var disabledIndicatorColor: UIColor {
get { carouselIndicatorModel?.disabledIndicatorColor.uiColor ?? .mvmCoolGray3 }
set { carouselIndicatorModel?.disabledIndicatorColor = Color(uiColor: newValue) }
get {
guard let model = carouselIndicatorModel else { return VDSColor.elementsSecondaryOnlight }
return model.inverted ? model.disabledIndicatorColor_inverted.uiColor : model.disabledIndicatorColor.uiColor
}
set {
if let model = carouselIndicatorModel, model.inverted {
model.disabledIndicatorColor_inverted = Color(uiColor: newValue)
} else {
carouselIndicatorModel?.disabledIndicatorColor = Color(uiColor: newValue)
}
}
}
public var indicatorColor: UIColor {
get {
guard let model = carouselIndicatorModel else { return .mvmBlack }
guard let model = carouselIndicatorModel else { return VDSColor.elementsPrimaryOnlight}
return model.inverted ? model.indicatorColor_inverted.uiColor : model.indicatorColor.uiColor
}
set {

View File

@ -7,9 +7,9 @@
//
import Foundation
import VDSColorTokens
open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelProtocol {
open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelProtocol, EnableableModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
@ -30,9 +30,10 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro
/// Set true to make the accessibility value as "Slide #currentPage of #totalPage", otherwise will be "Page #currentPage of #totalPage", default is false
public var accessibilityHasSlidesInsteadOfPage: Bool = false
public var enabled: Bool = true
public var disabledIndicatorColor: Color = Color(uiColor: .mvmCoolGray3)
public var indicatorColor: Color = Color(uiColor: .mvmBlack)
public var indicatorColor_inverted: Color = Color(uiColor: .mvmWhite)
public var disabledIndicatorColor: Color = Color(uiColor: VDSColor.elementsSecondaryOnlight)
public var disabledIndicatorColor_inverted: Color = Color(uiColor: VDSColor.elementsSecondaryOndark)
public var indicatorColor: Color = Color(uiColor: VDSColor.elementsPrimaryOnlight)
public var indicatorColor_inverted: Color = Color(uiColor: VDSColor.elementsPrimaryOndark)
public var position: CGFloat?
/// Allows sendActions() to trigger even if index is already at min/max index.

View File

@ -44,7 +44,7 @@ open class NumericIndicatorView: CarouselIndicator {
open override var isEnabled: Bool {
didSet { setViewColor(isEnabled ? indicatorColor : disabledIndicatorColor) }
}
/// Sets the color for pageCount text, left arrow and right arrow.
public override var indicatorColor: UIColor {
get { super.indicatorColor }

View File

@ -7,6 +7,7 @@
//
import Foundation
import MVMCore
public enum CheckboxPosition: String, Codable {
case center
@ -16,9 +17,19 @@ public enum CheckboxPosition: String, Codable {
@objcMembers public class CheckboxLabelModel: MoleculeModelProtocol {
public static var identifier: String = "checkboxLabel"
public var moleculeName: String
public var moleculeName: String = CheckboxLabelModel.identifier
public var backgroundColor: Color?
public var checkboxAlignment: CheckboxPosition?
public var checkbox: CheckboxModel
public var label: LabelModel
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(checkbox: CheckboxModel, label: LabelModel) {
self.checkbox = checkbox
self.label = label
}
}

View File

@ -7,7 +7,7 @@
//
import Foundation
import MVMCore
@objcMembers public class DashLineModel: MoleculeModelProtocol {
//--------------------------------------------------
@ -43,6 +43,12 @@ import Foundation
case isHidden
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {}
//--------------------------------------------------
// MARK: - codec
//--------------------------------------------------

View File

@ -0,0 +1,59 @@
//
// StateLabel.swift
// MVMCoreUI
//
// Created by Matt Bruce on 12/10/21.
// Copyright © 2021 Verizon Wireless. All rights reserved.
//
import Foundation
/// Subclass of label that helps with different states
public class FormLabel: Label {
//properties used in setting label
private var delegateObject: MVMCoreUIDelegateObject?
private var additionalData: [AnyHashable: Any]?
//models that drive the label UI
private var formModel: FormLabelModel!
//public properties
public override var isEnabled: Bool {
didSet{
self.formModel.enabled = isEnabled
self.set(with: isRequired ? formModel.model : formModel.requiredModel, delegateObject, additionalData)
}
}
public var isRequired: Bool = true {
didSet{
self.set(with: isRequired ? formModel.model : formModel.requiredModel, delegateObject, additionalData)
}
}
public override func reset(){
super.reset()
self.isEnabled = true
}
/// Used in setting up the Label for use
/// - Parameters:
/// - text: If there is no Model, there should be a TEXT only version of the label that will be applied to the default font / color styles
/// - model: Model takes priority over a text value. The model has its own text value that will be looked at to draw the screen, this model is used for both enabled/disabled models
/// - delegateObject: passed in from the creator
/// - additionalData: passed in from the creator
public func setup(model: FormLabelModel, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?){
self.additionalData = additionalData
self.delegateObject = delegateObject
self.formModel = model
//default to enabled state
self.reset()
}
/// Text change that will update both enabledModel and disabledModel text values
/// - Parameter text: text you want to see
public func set(text: String?){
self.formModel.set(text: text ?? "")
}
}

View File

@ -0,0 +1,81 @@
//
// StateLabelModel.swift
// MVMCoreUI
//
// Created by Matt Bruce on 12/14/21.
// Copyright © 2021 Verizon Wireless. All rights reserved.
//
import Foundation
public class FormLabelModel: EnableableModelProtocol {
static let defaultFontStyle = Styler.Font.RegularMicro
static let defaultEnabledTextColor = Color(uiColor: .mvmBlack)
static let defaultDisabledTextColor = Color(uiColor: .mvmCoolGray3)
static let defaultRequiredTextColor = Color(uiColor: .mvmCoolGray6)
private var enabledModel: LabelModel
private var disabledModel = LabelModel(fontStyle: FormLabelModel.defaultFontStyle, textColor: FormLabelModel.defaultDisabledTextColor)
//current state
public var enabled: Bool = true
//model is based on current state
public var model: LabelModel {
return enabled ? enabledModel: disabledModel
}
//init
public init(model: LabelModel){
//ensure the fontStyle exist and if so,
//make sure the disabledModel font matches
//otherwise set it to defaultFontStyle
if let modelFontStyle = model.fontStyle {
self.disabledModel.fontStyle = modelFontStyle
} else {
model.fontStyle = FormLabelModel.defaultFontStyle
}
//ensure the textColor is set
//otherwise use the defaultEnabledTextColor
if model.textColor == nil {
model.textColor = FormLabelModel.defaultEnabledTextColor
}
//set the enabledModel to the model passed in
self.enabledModel = model
//make sure the enabled & disabled text match
self.disabledModel.text = self.enabledModel.text
}
public init(text: String){
//create the enabled model
self.enabledModel = LabelModel(fontStyle: FormLabelModel.defaultFontStyle, textColor: FormLabelModel.defaultEnabledTextColor)
self.enabledModel.text = text
//make sure the enabled & disabled text match
self.disabledModel.text = self.enabledModel.text
}
public var requiredModel: LabelModel {
let required = LabelModel(fontStyle: model.fontStyle!, textColor: model.textColor!)
if enabled {
required.attributes = [LabelAttributeColorModel(FormLabelModel.defaultRequiredTextColor, model.text.count + 1, 8)]
}
required.text = "\(model.text) Optional"
return required
}
//methods
public func reset(){
self.enabled = true
}
//set text for state
public func set(text:String){
self.enabledModel.text = text
self.disabledModel.text = text
}
}

View File

@ -238,7 +238,7 @@ public typealias ActionBlock = () -> ()
case left
}
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject? = nil, _ additionalData: [AnyHashable: Any]? = nil) {
clauses = []
text = nil
@ -256,21 +256,19 @@ public typealias ActionBlock = () -> ()
* appropriately called.
* Only other reference found of issue: https://www.thetopsites.net/article/58142205.shtml
*/
if #available(iOS 13, *) {
if let attributedText = attributedText, let text = text, !text.isEmpty {
let attributedString = NSMutableAttributedString(string: text)
let range = NSRange(location: 0, length: text.count)
for attribute in attributedText.attributes(at: 0, effectiveRange: nil) {
if attribute.key == .underlineStyle {
attributedString.addAttribute(.underlineStyle, value: 0, range: range)
}
if attribute.key == .strikethroughStyle {
attributedString.addAttribute(.strikethroughStyle, value: 0, range: range)
}
if let attributedText = attributedText, let text = text, !text.isEmpty {
let attributedString = NSMutableAttributedString(string: text)
let range = NSRange(location: 0, length: text.count)
for attribute in attributedText.attributes(at: 0, effectiveRange: nil) {
if attribute.key == .underlineStyle {
attributedString.addAttribute(.underlineStyle, value: 0, range: range)
}
if attribute.key == .strikethroughStyle {
attributedString.addAttribute(.strikethroughStyle, value: 0, range: range)
}
self.attributedText = attributedString
}
self.attributedText = attributedString
}
hero = labelModel.hero
@ -297,8 +295,8 @@ public typealias ActionBlock = () -> ()
accessibilityLabel = accessibilityText
}
if let fontStyle = labelModel.fontStyle?.rawValue {
MFStyler.styleLabel(self, withStyle: fontStyle, genericScaling: false)
if let fontStyle = labelModel.fontStyle {
fontStyle.styleLabel(self, genericScaling: false)
standardFontSize = font.pointSize
} else {
let fontSize = labelModel.fontSize
@ -430,7 +428,7 @@ public typealias ActionBlock = () -> ()
label.accessibilityLabel = json?.optionalStringForKey("accessibilityText")
if let fontStyle = json?.optionalStringForKey("fontStyle") {
MFStyler.styleLabel(label, withStyle: fontStyle, genericScaling: mvmLabel == nil)
MFStyler.style(label: label, styleString: fontStyle, genericScaling: mvmLabel == nil)
mvmLabel?.standardFontSize = label.font.pointSize
} else {
let fontSize = json?["fontSize"] as? CGFloat
@ -492,7 +490,7 @@ public typealias ActionBlock = () -> ()
case "font":
if let fontStyle = attribute.optionalStringForKey("style") {
let styles = MFStyler.styleGetAttributedString("0", withStyle: fontStyle, genericScaling: mvmLabel == nil)
let styles = MFStyler.getAttributedString(for: "0", styleString: fontStyle, genericScaling: mvmLabel == nil)
attributedString.removeAttribute(.font, range: range)
attributedString.removeAttribute(.foregroundColor, range: range)
attributedString.addAttributes(styles.attributes(at: 0, effectiveRange: nil), range: range)
@ -533,8 +531,7 @@ public typealias ActionBlock = () -> ()
//------------------------------------------------------
public func setFontStyle(_ fontStyle: Styler.Font, _ scale: Bool = true) {
font = fontStyle.getFont(false)
textColor = .mvmBlack
fontStyle.styleLabel(self, genericScaling: false)
setScale(scale)
}
@ -584,9 +581,8 @@ public typealias ActionBlock = () -> ()
/// Will remove the values contained in attributedText.
func clearAttributes() {
guard let labelText = text,
let attributes = attributedText?.attributes(at: 0, longestEffectiveRange: nil, in: NSRange(location: 0, length: labelText.count))
guard let labelText = text, !labelText.isEmpty else { return }
guard let attributes = attributedText?.attributes(at: 0, longestEffectiveRange: nil, in: NSRange(location: 0, length: labelText.count))
else { return }
let attributedString = NSMutableAttributedString(string: labelText)

View File

@ -24,10 +24,14 @@
case textColor
}
public init(_ textColor: Color?, _ location: Int, _ length: Int){
self.textColor = textColor
super.init(location, length)
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
textColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor)

View File

@ -18,6 +18,14 @@
var name: String?
var size: CGFloat?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public override init(_ location: Int, _ length: Int) {
super.init(location, length)
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------

View File

@ -18,6 +18,14 @@ class LabelAttributeImageModel: LabelAttributeModel {
var name: String?
var URL: String?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public override init(_ location: Int, _ length: Int) {
super.init(location, length)
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------

View File

@ -18,10 +18,6 @@ import UIKit
get { return model as? LineModel }
}
var lineBackgroundColor: Color? {
return (lineModel?.inverted ?? false) ? lineModel?.backgroundColor_inverted : lineModel?.backgroundColor
}
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
@ -50,28 +46,36 @@ import UIKit
addLine(to: view, edge: edge, useMargin: useMargin)
}
public init() {
super.init(frame: .zero)
model = LineModel(type: .secondary)
setStyle(.secondary)
}
public override init(frame: CGRect) {
super.init(frame: frame)
model = LineModel(type: .secondary)
setStyle(.secondary)
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
model = LineModel(type: .secondary)
setStyle(.secondary)
}
public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.init(model: model, delegateObject, additionalData)
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
open func setStyle(_ style: LineModel.Style) {
switch style {
case .standard:
updateLineConstraints(constant: 1)
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmCoolGray3
case .thin:
updateLineConstraints(constant: 1)
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack
case .medium:
updateLineConstraints(constant: 2)
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack
case .heavy:
updateLineConstraints(constant: 4)
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack
case .none:
updateLineConstraints(constant: 0)
}
lineModel?.type = style
backgroundColor = lineModel?.backgroundColor?.uiColor
updateLineConstraints(constant: lineModel?.thickness ?? 1)
}
open func shouldBeVisible() -> Bool {
@ -90,12 +94,10 @@ import UIKit
open override func setupView() {
super.setupView()
heightConstraint = heightAnchor.constraint(equalToConstant: 1)
heightConstraint?.isActive = true
widthConstraint = widthAnchor.constraint(equalToConstant: 1)
widthConstraint?.isActive = false
setStyle(.standard)
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
@ -107,23 +109,11 @@ import UIKit
}
open override func reset() {
setStyle(.standard)
setStyle(.secondary)
}
public override static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
guard let type = (model as? LineModel)?.type else { return 1 }
switch type {
case .none:
return 0
case .medium:
return 2
case .heavy:
return 4
default:
return 1
}
return (model as? LineModel)?.thickness ?? 1
}
}

View File

@ -7,7 +7,7 @@
//
import UIKit
import VDSColorTokens
@objcMembers public class LineModel: MoleculeModelProtocol {
//--------------------------------------------------
@ -30,13 +30,17 @@ import UIKit
/**
The style of the line:
- standard (1 height, silver)
- thin (1 height, black)
- secondary (1 height, silver)
- primary (1 height, black)
- standard (1 height, silver) - deprecated
- thin (1 height, black) - deprecated
- medium (2 height, black)
- heavy (4 height, black)
- none (hidden)
*/
public enum Style: String, Codable {
case secondary
case primary
case standard
case thin
case medium
@ -49,13 +53,47 @@ import UIKit
//--------------------------------------------------
public static var identifier: String = "line"
public var type: Style = .standard
public var type: Style = .secondary
public var frequency: Frequency? = .allExceptTop
//TODO: use color insted of backgroundColor. Needs server changes
// public var color: Color?
public var backgroundColor: Color?
public var backgroundColor_inverted: Color = Color(uiColor: .mvmWhite)
private var _backgroundColor: Color?
public var backgroundColor: Color? {
get {
if let backgroundColor = _backgroundColor { return backgroundColor }
if inverted {
if type == .secondary || type == .standard { return Color(uiColor: VDSColor.paletteGray20) }
return Color(uiColor: VDSColor.elementsPrimaryOndark)
}
if type == .secondary || type == .standard { return Color(uiColor: VDSColor.paletteGray85) }
return Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
set {
_backgroundColor = newValue
}
}
private var _thickness: CGFloat?
public var thickness: CGFloat {
get {
if let thickness = _thickness { return thickness }
switch type {
case .heavy:
return 4
case .medium:
return 2
case .none:
return 0
default:
return 1
}
}
set {
_thickness = newValue
}
}
public var inverted: Bool = false
// Use this to show vertical line
@ -90,6 +128,7 @@ import UIKit
case frequency
case inverted
case useVerticalLine
case thickness
}
//--------------------------------------------------
@ -111,12 +150,9 @@ import UIKit
self.inverted = inverted
}
if let backgroundColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor_inverted) {
self.backgroundColor_inverted = backgroundColor_inverted
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
useVerticalLine = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalLine)
_thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness)
}
public func encode(to encoder: Encoder) throws {
@ -125,8 +161,8 @@ import UIKit
try container.encode(type, forKey: .type)
try container.encode(inverted, forKey: .inverted)
try container.encodeIfPresent(frequency, forKey: .frequency)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(backgroundColor_inverted, forKey: .backgroundColor_inverted)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(useVerticalLine, forKey: .useVerticalLine)
try container.encodeIfPresent(_thickness, forKey: .thickness)
}
}

View File

@ -7,7 +7,7 @@
//
import Foundation
import MVMCore
open class LoadingSpinnerModel: MoleculeModelProtocol {
//--------------------------------------------------
@ -32,6 +32,12 @@ open class LoadingSpinnerModel: MoleculeModelProtocol {
case diameter
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -5,6 +5,7 @@
// Created by Lekshmi S on 15/09/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
open class StarModel: MoleculeModelProtocol {
@ -30,6 +31,12 @@ open class StarModel: MoleculeModelProtocol {
case size
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -5,6 +5,7 @@
// Created by Lekshmi S on 21/09/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
@objcMembers public class StarsModel: MoleculeModelProtocol {
@ -34,6 +35,14 @@
case size
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with stars: [StarModel]) {
self.stars = stars
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -89,7 +89,7 @@ open class Video: View {
})
case .failed:
if let errorObject = item.loadFailedError {
MVMCoreLoggingHandler.shared()?.addError(toLog: errorObject)
MVMCoreLoggingHandler.addError(toLog: errorObject)
}
default:
break

View File

@ -14,7 +14,7 @@ open class VisibleBehaviorForVideoModel: PageBehaviorModelProtocol {
public var shouldAllowMultipleInstances: Bool = true
public weak var videoModel: VideoModel?
init(with videoModel: VideoModel) {
public init(with videoModel: VideoModel) {
self.videoModel = videoModel
}
}

View File

@ -170,8 +170,11 @@ extension WebView : WKNavigationDelegate {
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
//validate request url
//all validated link should be open in safari
if (navigationAction.navigationType == .linkActivated), let urlString = navigationAction.request.url?.absoluteString.removingPercentEncoding, !urlString.contains("#") {
MVMCoreActionHandler.shared()?.openURL(inWebView: navigationAction.request.url, actionInformation: nil, additionalData: nil, delegateObject: nil)
if (navigationAction.navigationType == .linkActivated),
let url = navigationAction.request.url,
let urlString = url.absoluteString.removingPercentEncoding,
!urlString.contains("#") {
MVMCoreUIActionHandler.shared()?.openURL(inSafariWebView: url)
decisionHandler(.cancel)
} else {
decisionHandler(.allow)

View File

@ -7,6 +7,7 @@
//
import Foundation
import MVMCore
@objcMembers public class WebViewModel: MoleculeModelProtocol {
public static var identifier: String = "webview"
@ -30,6 +31,12 @@ import Foundation
case borderColor
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)

View File

@ -49,125 +49,28 @@ import UIKit
}
heightConstraint?.constant = graphObject.diameter
// iOS 12 uses the conic gradient and a mask for simplicity.
if #available(iOS 12, *) {
let gradient = CAGradientLayer()
gradient.type = .conic
gradient.startPoint = CGPoint(x: 0.5, y: 0.5)
gradient.endPoint = CGPoint(x: 0.5, y: 0.0)
gradient.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter)
gradient.colors = graphObject.colors.map({ (color) -> CGColor in
return color.cgColor
})
gradientLayer = gradient
layer.addSublayer(gradient)
let center = CGPoint(x: gradient.bounds.midX, y: gradient.bounds.midY)
let radius = (graphObject.diameter - graphObject.lineWidth) / 2.0
let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: (3 / 2 * .pi), endAngle: -(1 / 2 * .pi), clockwise: false)
let mask = CAShapeLayer()
mask.fillColor = UIColor.clear.cgColor
mask.strokeColor = UIColor.white.cgColor
mask.lineWidth = graphObject.lineWidth
mask.path = path.cgPath
gradient.mask = mask
return
}
let gradient = CAGradientLayer()
gradient.type = .conic
gradient.startPoint = CGPoint(x: 0.5, y: 0.5)
gradient.endPoint = CGPoint(x: 0.5, y: 0.0)
gradient.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter)
gradient.colors = graphObject.colors.map({ (color) -> CGColor in
return color.cgColor
})
gradientLayer = gradient
layer.addSublayer(gradient)
//create circle path
let radius = graphObject.diameter / 2.0
//begin point will be at the bottom, clockwise direction
let path = UIBezierPath(arcCenter: CGPoint(x: radius
, y: radius), radius: radius - graphObject.lineWidth/2.0, startAngle: CGFloat(Wheel.getPiValue(90.0)), endAngle: CGFloat(Wheel.getPiValue(90.0 + 360.0)), clockwise: true)
path.lineWidth = graphObject.lineWidth
let circleLayer = CAShapeLayer()
circleLayer.path = path.cgPath
circleLayer.lineCap = .round
circleLayer.lineWidth = graphObject.lineWidth
circleLayer.fillColor = UIColor.clear.cgColor
circleLayer.strokeColor = UIColor.black.cgColor
//create gradient layer
let gradientLayer = createGradientLayer(graphObject)
gradientLayer.mask = circleLayer
layer.addSublayer(gradientLayer)
self.gradientLayer = gradientLayer
let center = CGPoint(x: gradient.bounds.midX, y: gradient.bounds.midY)
let radius = (graphObject.diameter - graphObject.lineWidth) / 2.0
let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: (3 / 2 * .pi), endAngle: -(1 / 2 * .pi), clockwise: false)
let mask = CAShapeLayer()
mask.fillColor = UIColor.clear.cgColor
mask.strokeColor = UIColor.white.cgColor
mask.lineWidth = graphObject.lineWidth
mask.path = path.cgPath
gradient.mask = mask
}
/*
create three gradient layer for circle layout.
_____________
| | top layer for smooth gradient
-------------
| | |
| | |
| | |
-------------
*/
func createGradientLayer(_ graphObject: WheelModel) -> CALayer {
let containLayer = CALayer()
containLayer.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter)
let radius = graphObject.diameter / 2.0
//create graident layers
guard graphObject.colors.count > 1 else {
containLayer.backgroundColor = graphObject.colors.first?.cgColor
return containLayer
}
var topGradientHeight : CGFloat = 0.0
var leftColors = graphObject.colors.prefix(through: graphObject.colors.count/2)
let rightColors = graphObject.colors.suffix(from: graphObject.colors.count/2)
// make the top layer higher than line width for smooth look
topGradientHeight = min(max(graphObject.lineWidth, 1.0/(1.0+CGFloat(graphObject.colors.count))*graphObject.diameter), graphObject.diameter)
let topLayer = CAGradientLayer()
topLayer.frame = CGRect(x: 0.0, y: 0.0, width: graphObject.diameter, height: topGradientHeight)
//make the graident edge more smoothy
topLayer.startPoint = CGPoint(x: 0.25, y: 0.0)
topLayer.endPoint = CGPoint(x: 0.75, y: 0.0)
//if number of colors is even, need to display gradient layer, otherwise make top layer as solid color layer
if graphObject.colors.count % 2 == 0 {
leftColors.removeLast()
let firstColor = leftColors.last!.cgColor
let secondColor = rightColors.first!.cgColor
topLayer.colors = [firstColor, secondColor]
} else {
topLayer.backgroundColor = leftColors.last?.cgColor
}
containLayer.addSublayer(topLayer)
let leftLayer = CAGradientLayer()
leftLayer.frame = CGRect(x: 0, y: topGradientHeight, width: radius, height: graphObject.diameter - topGradientHeight)
leftLayer.startPoint = CGPoint(x: 0, y: 1)
leftLayer.endPoint = CGPoint(x: 0, y: 0)
//count of graidentLayer.colors must be bigger than 1, otherwise set backgroundColor
if leftColors.count > 1 {
leftLayer.colors = leftColors.map({ (color) -> CGColor in
return color.cgColor
})
} else {
leftLayer.backgroundColor = leftColors.first?.cgColor
}
containLayer.addSublayer(leftLayer)
let rightLayer = CAGradientLayer()
rightLayer.frame = CGRect(x: radius, y: topGradientHeight, width: radius, height: graphObject.diameter - topGradientHeight)
rightLayer.startPoint = CGPoint(x: 0, y: 0)
rightLayer.endPoint = CGPoint(x: 0, y: 1)
if rightColors.count > 1 {
rightLayer.colors = rightColors.map({ (color) -> CGColor in
return color.cgColor
})
} else {
rightLayer.backgroundColor = rightColors.first?.cgColor
}
containLayer.addSublayer(rightLayer)
return containLayer
}
//MARK: MVMCoreUIViewConstrainingProtocol
public func needsToBeConstrained() -> Bool {
return true

View File

@ -0,0 +1,59 @@
//
// UIImageRenderingMode+Extension.swift
// MVMCoreUI
//
// Created by Nadigadda, Sumanth on 24/03/22.
// Copyright © 2022 Verizon Wireless. All rights reserved.
//
import Foundation
import UIKit
enum RenderingModeError: Error {
case notAnRenderingMode
}
extension UIImage.RenderingMode: RawRepresentable {
init?(rawValue: String) {
switch rawValue {
case "alwaysOriginal":
self = .alwaysOriginal
case "alwaysTemplate":
self = .alwaysTemplate
case "automatic":
self = .automatic
default:
return nil
}
}
var rawValueString: String {
switch self {
case .alwaysOriginal:
return "alwaysOriginal"
case .alwaysTemplate:
return "alwaysTemplate"
case .automatic:
return "automatic"
@unknown default:
return ""
}
}
}
extension UIImage.RenderingMode: Codable {
public init(from decoder: Decoder) throws {
let typeContainer = try decoder.singleValueContainer()
let string = try typeContainer.decode(String.self)
guard let renderingMode = UIImage.RenderingMode(rawValue: string) else {
throw RenderingModeError.notAnRenderingMode
}
self = renderingMode
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(rawValueString)
}
}

View File

@ -0,0 +1,123 @@
//
// TitleLockup.swift
// MVMCoreUI
//
// Created by Nadigadda, Sumanth on 04/05/22.
// Copyright © 2022 Verizon Wireless. All rights reserved.
//
@objcMembers open class TitleLockup: View {
//--------------------------------------------------
// MARK: - Outlets
//--------------------------------------------------
public let eyebrow = Label(fontStyle: .RegularBodySmall)
public let title = Label(fontStyle: .RegularBodySmall)
public let subTitle = Label(fontStyle: .RegularBodySmall)
public lazy var stack: UIStackView = {
let stack = UIStackView(arrangedSubviews: [eyebrow, title, subTitle])
stack.translatesAutoresizingMaskIntoConstraints = false
stack.axis = .vertical
return stack
}()
var castModel: TitleLockupModel? {
get { return model as? TitleLockupModel }
}
//--------------------------------------------------
// MARK: - Initialization
//--------------------------------------------------
public convenience init() {
self.init(frame: .zero)
}
//--------------------------------------------------
// MARK: - MFViewProtocol
//--------------------------------------------------
open override func setupView() {
super.setupView()
addSubview(stack)
NSLayoutConstraint.constraintPinSubview(toSuperview: stack)
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
stack.updateView(size)
}
//--------------------------------------------------
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
open override func reset() {
super.reset()
stack.reset()
}
//--------------------------------------------------
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? TitleLockupModel else { return }
stack.setCustomSpacing(model.defaultEyebrowTitleSpacing(), after: eyebrow)
stack.setCustomSpacing(model.defaultTitleSubTitleSpacing(), after: title)
stack.updateContainedMolecules(with: [model.eyebrow,
model.title,
model.subTitle],
delegateObject, additionalData)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 65
}
//--------------------------------------------------
// MARK: - Accessibility Helpers
//--------------------------------------------------
/// Returns the labels text in one message.
func getAccessibilityMessage() -> String? {
var message = ""
if let eyebrowLabel = eyebrow.text {
message += eyebrowLabel + ", "
}
if let headlineLabel = title.text {
message += headlineLabel + ", "
}
if let bodyLabel = subTitle.text {
message += bodyLabel
}
return message.count > 0 ? message : nil
}
/// Returns an array of the appropriate accessibility elements.
func getAccessibilityElements() -> [Any]? {
var elements: [UIView] = []
if eyebrow.hasText {
elements.append(eyebrow)
}
if title.hasText {
elements.append(title)
}
if subTitle.hasText {
elements.append(subTitle)
}
return elements.count > 0 ? elements : nil
}
}

View File

@ -0,0 +1,215 @@
//
// TitleLockupModel.swift
// MVMCoreUI
//
// Created by Nadigadda, Sumanth on 04/05/22.
// Copyright © 2022 Verizon Wireless. All rights reserved.
//
import VDSColorTokens
public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "titleLockup"
public var moleculeName: String = TitleLockupModel.identifier
public var eyebrow: LabelModel?
public var title: LabelModel
public var subTitle: LabelModel?
public var alignment: Alignment = .left {
didSet {
///Updating the text alignment for all labels
if let textAlignment = NSTextAlignment(rawValue: alignment.rawValue) {
eyebrow?.textAlignment = textAlignment
title.textAlignment = textAlignment
subTitle?.textAlignment = textAlignment
}
}
}
public var inverted: Bool = false {
didSet {
///Updating the text color
eyebrow?.textColor = titleColor
title.textColor = titleColor
subTitle?.textColor = subTitleColor
}
}
private var _backgroundColor: Color?
public var backgroundColor: Color? {
get {
return inverted ? Color(uiColor: VDSColor.backgroundPrimaryDark) : Color(uiColor: VDSColor.backgroundPrimaryLight)
}
set {
_backgroundColor = newValue
}
}
public var titleColor: Color? {
return inverted ? Color(uiColor: VDSColor.elementsPrimaryOndark) : Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
public var subTitleColor: Color? {
return inverted ? Color(uiColor: VDSColor.elementsSecondaryOndark) : Color(uiColor: VDSColor.elementsSecondaryOnlight)
}
public var children: [MoleculeModelProtocol] {
[eyebrow, title, subTitle].compactMap { (molecule: MoleculeModelProtocol?) in molecule }
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(eyebrow: LabelModel? = nil, title: LabelModel, subTitle: LabelModel? = nil) throws {
self.eyebrow = eyebrow
self.title = title
self.subTitle = subTitle
updateLabelAttributes()
}
//--------------------------------------------------
// MARK: - Enum
//--------------------------------------------------
public enum Alignment: String, Codable {
case left
case center
}
//--------------------------------------------------
// MARK: - Styling
//--------------------------------------------------
/// Returns the default fontStyle for the subtitle, based on the title fontStyle.
func defaultSubtitleFontStyle() -> Styler.Font {
switch title.fontStyle {
case .RegularTitleXLarge, .RegularTitle2XLarge, .RegularFeatureXSmall:
return .RegularBodyLarge
case .RegularFeatureSmall, .RegularFeatureMedium:
return .RegularTitleLarge
default:
return .RegularBodySmall
}
}
/// Returns the default spacing between the eyebrow and title, based on the title fontStyle.
func defaultEyebrowTitleSpacing() -> CGFloat {
switch title.fontStyle {
case .RegularTitleXLarge, .RegularTitle2XLarge, .RegularFeatureXSmall, .RegularFeatureSmall:
return Padding.Three
case .RegularFeatureMedium:
return subTitle?.fontStyle == .RegularBodyLarge ? Padding.Three : Padding.Four
default:
return Padding.Two
}
}
/// Returns the default spacing between the title and subTitle, based on the title fontStyle.
func defaultTitleSubTitleSpacing() -> CGFloat {
switch title.fontStyle {
case .RegularTitleXLarge:
return Padding.Three
case .RegularTitle2XLarge, .RegularFeatureXSmall, .RegularFeatureSmall:
return Padding.Four
case .RegularFeatureMedium:
return Padding.Five
default:
return Padding.Two
}
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case eyebrow
case title
case subTitle
case inverted
case alignment
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
title = try typeContainer.decodeMolecule(codingKey: .title)
eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow)
subTitle = try typeContainer.decodeMoleculeIfPresent(codingKey: .subTitle)
if let newAlignment = try typeContainer.decodeIfPresent(Alignment.self, forKey: .alignment) {
alignment = newAlignment
}
if let invertedStatus = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) {
inverted = invertedStatus
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
updateLabelAttributes()
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(eyebrow, forKey: .eyebrow)
try container.encodeModel(title, forKey: .title)
try container.encodeIfPresent(subTitle, forKey: .subTitle)
try container.encode(alignment, forKey: .alignment)
try container.encode(inverted, forKey: .inverted)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
}
//--------------------------------------------------
// MARK: - Model updates
//--------------------------------------------------
private func updateLabelAttributes() {
// If subtitle style is not available, will set font style based on the component
if subTitle?.fontStyle == nil {
subTitle?.fontStyle = defaultSubtitleFontStyle()
}
// If eyebrow style is not available, will set font style based on the component. Eyebrow and subtitle share the same font size
if eyebrow?.fontStyle == nil {
eyebrow?.fontStyle = subTitle?.fontStyle
}
// Updating the text color
if eyebrow?.textColor == nil {
eyebrow?.textColor = subTitleColor
}
if title.textColor == nil {
title.textColor = titleColor
}
if subTitle?.textColor == nil {
subTitle?.textColor = subTitleColor
}
// Updating the text alignment for all labels
if let textAlignment = NSTextAlignment(rawValue: alignment.rawValue) {
if eyebrow?.textAlignment == nil {
eyebrow?.textAlignment = textAlignment
}
if title.textAlignment == nil {
title.textAlignment = textAlignment
}
if subTitle?.textAlignment == nil {
subTitle?.textAlignment = textAlignment
}
}
}
}

View File

@ -23,7 +23,7 @@ public class ListThreeColumnInternationalDataDividerModel: ListItemModel, Molecu
// MARK: - Initializers
//------------------------------------------------------
public init (leftLabel: LabelModel, centerLabel: LabelModel, rightLabel: LabelModel) {
public init(leftLabel: LabelModel, centerLabel: LabelModel, rightLabel: LabelModel) {
self.leftLabel = leftLabel
self.centerLabel = centerLabel
self.rightLabel = rightLabel

View File

@ -33,7 +33,7 @@ open class HeaderView: Container {
public override func setupView() {
super.setupView()
line.setStyle(.heavy)
line.setStyle(.none)
addSubview(line)
NSLayoutConstraint.pinViewBottom(toSuperview: line, useMargins: false, constant: 0).isActive = true
NSLayoutConstraint.pinViewLeft(toSuperview: line, useMargins: true, constant: 0).isActive = true
@ -43,7 +43,7 @@ open class HeaderView: Container {
// MARK: - MoleculeViewProtocol
open override func reset() {
super.reset()
line.setStyle(.heavy)
line.setStyle(.none)
molecule?.reset()
}

View File

@ -31,7 +31,7 @@ public class MoleculeHeaderView: MoleculeContainer {
public override func setupView() {
super.setupView()
line.setStyle(.heavy)
line.setStyle(.none)
addSubview(line)
NSLayoutConstraint.pinViewBottom(toSuperview: line, useMargins: false, constant: 0).isActive = true
NSLayoutConstraint.pinViewLeft(toSuperview: line, useMargins: true, constant: 0).isActive = true
@ -40,7 +40,7 @@ public class MoleculeHeaderView: MoleculeContainer {
open override func reset() {
super.reset()
line.setStyle(.heavy)
line.setStyle(.none)
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {

View File

@ -22,7 +22,7 @@ import Foundation
public override func setupView() {
super.setupView()
line.setStyle(.thin)
line.setStyle(.primary)
contentView.addSubview(line)
NSLayoutConstraint.pinViewBottom(toSuperview: line, useMargins: false, constant: 0).isActive = true
NSLayoutConstraint.pinViewLeft(toSuperview: line, useMargins: true, constant: 0).isActive = true
@ -51,7 +51,7 @@ import Foundation
open override func reset() {
super.reset()
line.setStyle(.thin)
line.setStyle(.primary)
molecule?.reset()
}

View File

@ -14,6 +14,13 @@
public class override var identifier: String { "sectionHeader" }
public var line: LineModel?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public override init(with moleculeModel: MoleculeModelProtocol) {
super.init(with: moleculeModel)
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
@ -42,7 +49,7 @@
bottomPadding = PaddingDefaultVerticalSpacing3
}
if line == nil {
line = LineModel(type: .thin)
line = LineModel(type: .primary)
}
}

View File

@ -7,7 +7,7 @@
//
import Foundation
import MVMCore
@objcMembers public class RadioButtonLabelModel: MoleculeModelProtocol {
//--------------------------------------------------
@ -16,7 +16,17 @@ import Foundation
public static var identifier: String = "radioButtonLabel"
public var backgroundColor: Color?
public var moleculeName: String
public var moleculeName: String = RadioButtonLabelModel.identifier
public var radioButton: RadioButtonModel
public var label: LabelModel
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(radioButton: RadioButtonModel, label: LabelModel) {
self.radioButton = radioButton
self.label = label
}
}

View File

@ -5,7 +5,7 @@
// Created by Scott Pfeil on 5/28/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import VDSColorTokens
@objcMembers open class TabBar: UITabBar, MoleculeViewProtocol, TabBarProtocol, UITabBarDelegate {
@ -21,7 +21,6 @@
delegate = self
translatesAutoresizingMaskIntoConstraints = false
line.addLine(to: self, edge: .top, useMargin: false)
line.backgroundColor = .mvmCoolGray3
set(with: model, delegateObject, additionalData)
}
@ -34,47 +33,36 @@
self.model = model
// Set appearance
if #available(iOS 13.0, *) {
let appearance = UITabBarAppearance()
appearance.backgroundColor = model.backgroundColor?.uiColor
set(tabItemAppearance: appearance.stackedLayoutAppearance, model: model)
set(tabItemAppearance: appearance.inlineLayoutAppearance, model: model)
set(tabItemAppearance: appearance.compactInlineLayoutAppearance, model: model)
standardAppearance = appearance
} else {
// Fallback on earlier versions
backgroundColor = model.backgroundColor?.uiColor
tintColor = model.selectedColor.uiColor
unselectedItemTintColor = model.unSelectedColor.uiColor
barTintColor = model.backgroundColor?.uiColor
isTranslucent = false
}
let appearance = UITabBarAppearance()
appearance.backgroundColor = model.backgroundColor?.uiColor
set(tabItemAppearance: appearance.stackedLayoutAppearance, model: model)
set(tabItemAppearance: appearance.inlineLayoutAppearance, model: model)
set(tabItemAppearance: appearance.compactInlineLayoutAppearance, model: model)
standardAppearance = appearance
// Add buttons
var tabs: [UITabBarItem] = []
for (index, tab) in model.tabs.enumerated() {
let tabBarItem = UITabBarItem(title: tab.title, image: MVMCoreCache.shared()?.getImageFromRegisteredBundles(tab.image), tag: index)
tabBarItem.accessibilityLabel = tab.accessibilityText
if #available(iOS 13.0, *) {
} else {
tabBarItem.titlePositionAdjustment = UIOffset(horizontal: 0, vertical: -3)
tabBarItem.setTitleTextAttributes([NSAttributedString.Key.font: MFFonts.mfFontTXRegular(8)], for: .normal)
}
tabs.append(tabBarItem)
}
setItems(tabs, animated: false)
selectedItem = tabs[model.selectedTab]
guard let lineModel = line.lineModel else { return }
lineModel.inverted = model.style == .dark
line.set(with: lineModel, delegateObject, additionalData)
}
/// Sets the item colors.
@available(iOS 13.0, *)
private func set(tabItemAppearance: UITabBarItemAppearance, model: TabBarModel) {
tabItemAppearance.normal.iconColor = model.unSelectedColor.uiColor
tabItemAppearance.normal.titleTextAttributes = [NSAttributedString.Key.foregroundColor: model.unSelectedColor.uiColor, NSAttributedString.Key.font: MFFonts.mfFontTXRegular(8)]
tabItemAppearance.normal.titleTextAttributes = [NSAttributedString.Key.foregroundColor: model.unSelectedColor.uiColor, NSAttributedString.Key.font: MFFonts.mfFontTXBold(10)]
tabItemAppearance.normal.titlePositionAdjustment = UIOffset(horizontal: 0, vertical: -3)
tabItemAppearance.selected.iconColor = model.selectedColor.uiColor
tabItemAppearance.selected.titleTextAttributes = [NSAttributedString.Key.foregroundColor: model.selectedColor.uiColor, NSAttributedString.Key.font: MFFonts.mfFontTXRegular(8)]
tabItemAppearance.selected.titleTextAttributes = [NSAttributedString.Key.foregroundColor: model.selectedColor.uiColor, NSAttributedString.Key.font: MFFonts.mfFontTXBold(10)]
tabItemAppearance.selected.titlePositionAdjustment = UIOffset(horizontal: 0, vertical: -3)
}

View File

@ -7,16 +7,55 @@
//
import Foundation
import VDSColorTokens
public class TabBarModel: MoleculeModelProtocol {
open class TabBarModel: MoleculeModelProtocol {
public static var identifier: String = "tabBar"
public var backgroundColor: Color? = Color(uiColor: .white)
public var tabs: [TabBarItemModel]
public var selectedColor = Color(uiColor: .mvmBlack)
public var unSelectedColor = Color(uiColor: .mvmCoolGray6)
open var tabs: [TabBarItemModel]
private var _backgroundColor: Color?
open var backgroundColor: Color? {
get {
if let backgroundColor = _backgroundColor { return backgroundColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.backgroundPrimaryDark) }
return Color(uiColor: VDSColor.backgroundPrimaryLight)
}
set {
_backgroundColor = newValue
}
}
private var _selectedColor: Color?
open var selectedColor: Color {
get {
if let selectedColor = _selectedColor { return selectedColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.elementsPrimaryOndark) }
return Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
set {
_selectedColor = newValue
}
}
private var _unSelectedColor: Color?
open var unSelectedColor: Color {
get {
if let unSelectedColor = _unSelectedColor { return unSelectedColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.elementsSecondaryOndark) }
return Color(uiColor: VDSColor.elementsSecondaryOnlight)
}
set {
_unSelectedColor = newValue
}
}
open var style: NavigationItemStyle? = .dark
// Must be capped to 0...(tabs.count - 1)
public var selectedTab: Int = 0
open var selectedTab: Int = 0
private enum CodingKeys: String, CodingKey {
case moleculeName
@ -25,6 +64,7 @@ public class TabBarModel: MoleculeModelProtocol {
case selectedColor
case unSelectedColor
case selectedTab
case style
}
public init(with tabs: [TabBarItemModel]) {
@ -46,24 +86,28 @@ public class TabBarModel: MoleculeModelProtocol {
if let index = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedTab) {
selectedTab = index
}
if let navStyle = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style) {
style = navStyle
}
}
public func encode(to encoder: Encoder) throws {
open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(tabs, forKey: .tabs)
try container.encode(backgroundColor, forKey: .backgroundColor)
try container.encode(selectedColor, forKey: .selectedColor)
try container.encode(unSelectedColor, forKey: .unSelectedColor)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(_selectedColor, forKey: .selectedColor)
try container.encodeIfPresent(_unSelectedColor, forKey: .unSelectedColor)
try container.encode(selectedTab, forKey: .selectedTab)
try container.encodeIfPresent(style, forKey: .style)
}
}
public class TabBarItemModel: Codable {
var title: String?
var image: String
var action: ActionModelProtocol
var accessibilityText: String?
open class TabBarItemModel: Codable {
open var title: String?
open var image: String
open var action: ActionModelProtocol
open var accessibilityText: String?
private enum CodingKeys: String, CodingKey {
case title
@ -86,7 +130,7 @@ public class TabBarItemModel: Codable {
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
}
public func encode(to encoder: Encoder) throws {
open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(title, forKey: .title)
try container.encode(image, forKey: .image)

View File

@ -7,6 +7,7 @@
//
import UIKit
import VDSColorTokens
@objc public protocol TabsDelegate {
func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool
@ -15,7 +16,6 @@ import UIKit
@objcMembers open class Tabs: View, MVMCoreUIViewConstrainingProtocol, MFButtonProtocol {
public var tabsModel: TabsModel? {
get { return model as? TabsModel }
}
@ -24,7 +24,7 @@ import UIKit
var additionalData: [AnyHashable: Any]?
let layout = UICollectionViewFlowLayout()
public var collectionView: UICollectionView?
public var collectionView: CollectionView?
let bottomScrollView = UIScrollView(frame: .zero)
let bottomContentView = View()
@ -39,17 +39,15 @@ import UIKit
weak public var delegate: TabsDelegate?
//control var
public var heightConstraint: NSLayoutConstraint?
public var selectedIndex: Int = 0
public var paddingBeforeFirstTab: Bool = true
//constant
let TabCellId = "TabCell"
public let sectionPadding: CGFloat = 20.0
public let cellSpacing: CGFloat = 34.0
public let cellHeight: CGFloat = 27.0
public let itemSpacing: CGFloat = 20.0
public let cellHeight: CGFloat = 28.0
public let selectionLineHeight: CGFloat = 4.0
public let selectionLineWidth: CGFloat = 32.0
public let minimumItemWidth: CGFloat = 32.0
public let selectionLineMovingTime: TimeInterval = 0.2
//-------------------------------------------------
@ -64,11 +62,12 @@ import UIKit
open override func updateView(_ size: CGFloat) {
super.updateView(size)
collectionView?.updateView(size)
}
open override func setupView() {
super.setupView()
backgroundColor = .white
backgroundColor = VDSColor.backgroundPrimaryLight
addSubview(bottomLine)
setupCollectionView()
setupSelectionLine()
@ -77,9 +76,9 @@ import UIKit
func setupCollectionView () {
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = cellSpacing
layout.minimumLineSpacing = 0
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
let collectionView = CollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.register(TabItemCell.self, forCellWithReuseIdentifier: TabCellId)
collectionView.backgroundColor = .clear
@ -96,7 +95,7 @@ import UIKit
bottomScrollView.delegate = self
addSubview(bottomScrollView)
bottomScrollView.addSubview(bottomContentView)
selectionLine.backgroundColor = .mvmRed
selectionLine.backgroundColor = VDSColor.paletteRed
bottomContentView.addSubview(selectionLine)
bringSubviewToFront(bottomScrollView)
}
@ -114,7 +113,7 @@ import UIKit
selectionLine.heightAnchor.constraint(equalToConstant: selectionLineHeight).isActive = true
selectionLineLeftConstraint = selectionLine.leftAnchor.constraint(equalTo: bottomContentView.leftAnchor)
selectionLineLeftConstraint?.isActive = true
selectionLineWidthConstraint = selectionLine.widthAnchor.constraint(equalToConstant: selectionLineWidth)
selectionLineWidthConstraint = selectionLine.widthAnchor.constraint(equalToConstant: minimumItemWidth)
selectionLineWidthConstraint?.isActive = true
NSLayoutConstraint.constraintPinSubview(toSuperview: bottomContentView)
@ -155,8 +154,7 @@ import UIKit
self.delegateObject = delegateObject
self.additionalData = additionalData
selectedIndex = tabsModel?.selectedIndex ?? 0
// TODO: Commented out until we have model support for bar color. Should also do unselected color.
//selectionLine.backgroundColor = tabsModel?.selectedColor.uiColor
selectionLine.backgroundColor = tabsModel?.selectedBarColor.uiColor
reloadData()
}
}
@ -171,10 +169,11 @@ extension Tabs: UICollectionViewDataSource {
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let labelModel = tabsModel?.tabs[indexPath.row].label, let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TabCellId, for: indexPath) as? TabItemCell else {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TabCellId, for: indexPath) as? TabItemCell else {
return UICollectionViewCell()
}
cell.updateCell(labelModel: labelModel, indexPath: indexPath, delegateObject: delegateObject, additionalData: additionalData, selected: indexPath.row == selectedIndex, tabsModel: tabsModel)
cell.updateCell(indexPath: indexPath, delegateObject: delegateObject, additionalData: additionalData, selected: indexPath.row == selectedIndex, tabsModel: tabsModel)
updateView(collectionView.bounds.width)
return cell
}
}
@ -182,10 +181,16 @@ extension Tabs: UICollectionViewDataSource {
extension Tabs: UICollectionViewDelegateFlowLayout {
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
guard self.collectionView(collectionView, numberOfItemsInSection: indexPath.section) != 2 else {
// If two tabs, take up the screen
let insets = self.collectionView(collectionView, layout: collectionViewLayout, insetForSectionAt: indexPath.section)
let width = (collectionView.bounds.width / 2.0) - insets.left - insets.right
return CGSize(width: width, height: cellHeight)
}
guard let labelModel = tabsModel?.tabs[indexPath.row].label else {
return .zero
}
return CGSize(width: getLabelWidth(labelModel).width, height: cellHeight)
return CGSize(width: max(minimumItemWidth, getLabelWidth(labelModel).width), height: cellHeight)
}
//pre calculate the width of the collection cell
@ -200,7 +205,7 @@ extension Tabs: UICollectionViewDelegateFlowLayout {
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
guard section == 0 else {
return UIEdgeInsets(top: 0, left: sectionPadding, bottom: 0, right: 0)
return UIEdgeInsets(top: 0, left: itemSpacing, bottom: 0, right: 0)
}
guard paddingBeforeFirstTab else {
return .zero
@ -209,7 +214,11 @@ extension Tabs: UICollectionViewDelegateFlowLayout {
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return sectionPadding
// If two tabs, take up the screen, no space between items
guard self.collectionView(collectionView, numberOfItemsInSection: section) != 2 else {
return 0
}
return itemSpacing
}
public func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
@ -237,7 +246,7 @@ extension Tabs: UICollectionViewDelegateFlowLayout {
guard let collect = collectionView, tabsModel?.tabs.count ?? 0 > 0 else { return }
collect.selectItem(at: indexPath, animated: animated, scrollPosition: .centeredHorizontally)
guard let tabCell = collect.cellForItem(at: indexPath) as? TabItemCell, let tabsModel = self.tabsModel else { return }
guard let tabCell = collect.cellForItem(at: indexPath) as? TabItemCell, let tabsModel = tabsModel else { return }
moveSelectionLine(toIndex: indexPath, animated: animated, cell: tabCell)
tabCell.label.textColor = tabsModel.selectedColor.uiColor
tabCell.updateAccessibility(indexPath: indexPath, selected: true, tabsModel: tabsModel)
@ -270,15 +279,13 @@ extension Tabs: UIScrollViewDelegate {
//-------------------------------------------------
extension Tabs {
func moveSelectionLine(toIndex indexPath: IndexPath, animated: Bool, cell: TabItemCell) {
guard let collect = self.collectionView else {return}
guard let collect = collectionView else {return}
let size = collectionView(collect, layout: layout, sizeForItemAt: indexPath)
let barWidth = max(size.width, selectionLineWidth)
let animationBlock = {
[weak self] in
let x = cell.frame.origin.x
self?.selectionLineWidthConstraint?.constant = barWidth
self?.selectionLineLeftConstraint?.constant = x + (size.width - barWidth) / 2.0
self?.selectionLineWidthConstraint?.constant = size.width
self?.selectionLineLeftConstraint?.constant = cell.frame.origin.x
self?.bottomContentView.layoutIfNeeded()
}
if animated {
@ -287,11 +294,31 @@ extension Tabs {
animationBlock()
}
}
/// Adjust the line based on the percentage
func progress(from index: Int, toIndex: Int, percentage: CGFloat) {
let fromIndexPath = IndexPath(row: index, section: 0)
let toIndexPath = IndexPath(row: toIndex, section: 0)
guard let collection = collectionView,
let fromCell = collection.cellForItem(at: fromIndexPath),
let toCell = collection.cellForItem(at: toIndexPath) else { return }
// setting the width for percentage
selectionLineWidthConstraint?.constant = (toCell.bounds.width - fromCell.bounds.width) * percentage + fromCell.bounds.width
// setting the x for percentage
let originalX = fromCell.frame.origin.x
let toX = toCell.frame.origin.x
let xDifference = toX - originalX
let finalX = (xDifference * percentage) + originalX
selectionLineLeftConstraint?.constant = finalX
bottomContentView.layoutIfNeeded()
}
}
@objcMembers public class TabItemCell: CollectionViewCell {
public let label = Label()
public var labelModel: LabelModel?
public override func setupView() {
super.setupView()
@ -300,14 +327,19 @@ extension Tabs {
label.baselineAdjustment = .alignCenters
}
public func updateCell(labelModel: LabelModel, indexPath: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, selected: Bool, tabsModel: TabsModel?) {
public override func updateView(_ size: CGFloat) {
super.updateView(size)
label.updateView(size)
}
public func updateCell(indexPath: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, selected: Bool, tabsModel: TabsModel?) {
guard let tabsModel = tabsModel else { return }
label.reset()
label.set(with: labelModel, delegateObject, additionalData)
self.labelModel = labelModel
label.set(with: tabsModel.tabs[indexPath.row].label, delegateObject, additionalData)
if selected {
label.textColor = tabsModel?.selectedColor.uiColor ?? .black
label.textColor = tabsModel.selectedColor.uiColor
} else {
label.textColor = .mvmCoolGray6
label.textColor = tabsModel.unselectedColor.uiColor
}
updateAccessibility(indexPath: indexPath, selected: selected, tabsModel: tabsModel)
}

View File

@ -7,22 +7,78 @@
//
import UIKit
import VDSColorTokens
public class TabsModel: MoleculeModelProtocol {
open class TabsModel: MoleculeModelProtocol {
public static var identifier: String = "tabs"
public var backgroundColor: Color?
public var tabs: [TabItemModel]
public var selectedColor = Color(uiColor: .black)
open var tabs: [TabItemModel]
open var style: NavigationItemStyle?
private var _backgroundColor: Color?
open var backgroundColor: Color? {
get {
if let backgroundColor = _backgroundColor { return backgroundColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.backgroundPrimaryDark) }
return Color(uiColor: VDSColor.backgroundPrimaryLight)
}
set {
_backgroundColor = newValue
}
}
private var _selectedColor: Color?
open var selectedColor: Color {
get {
if let selectedColor = _selectedColor { return selectedColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.elementsPrimaryOndark) }
return Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
set {
_selectedColor = newValue
}
}
private var _unselectedColor: Color?
open var unselectedColor: Color {
get {
if let unselectedColor = _unselectedColor { return unselectedColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.elementsSecondaryOndark) }
return Color(uiColor: VDSColor.elementsSecondaryOnlight)
}
set {
_unselectedColor = newValue
}
}
private var _selectedBarColor: Color?
open var selectedBarColor: Color {
get {
if let selectedBarColor = _selectedBarColor { return selectedBarColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.elementsPrimaryOndark) }
return Color(uiColor: VDSColor.paletteRed)
}
set {
_selectedBarColor = newValue
}
}
// Must be capped to 0...(tabs.count - 1)
public var selectedIndex: Int = 0
open var selectedIndex: Int = 0
private enum CodingKeys: String, CodingKey {
case moleculeName
case tabs
case backgroundColor
case selectedColor
case unselectedColor
case selectedBarColor
case selectedIndex
case moleculeName
case style
}
public init(with tabs: [TabItemModel]) {
@ -33,31 +89,35 @@ public class TabsModel: MoleculeModelProtocol {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
tabs = try typeContainer.decode([TabItemModel].self, forKey: .tabs)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor) {
selectedColor = color
}
_selectedColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor)
_unselectedColor = try typeContainer.decodeIfPresent(Color.self, forKey: .unselectedColor)
_selectedBarColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedBarColor)
style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style)
if let index = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) {
selectedIndex = index
}
}
public func encode(to encoder: Encoder) throws {
open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(tabs, forKey: .tabs)
try container.encode(backgroundColor, forKey: .backgroundColor)
try container.encode(selectedColor, forKey: .selectedColor)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(_selectedColor, forKey: .selectedColor)
try container.encodeIfPresent(_unselectedColor, forKey: .unselectedColor)
try container.encodeIfPresent(_selectedBarColor, forKey: .selectedBarColor)
try container.encode(selectedIndex, forKey: .selectedIndex)
try container.encodeIfPresent(style, forKey: .style)
}
}
public class TabItemModel: Codable {
var label: LabelModel
var action: ActionModelProtocol?
open class TabItemModel: Codable {
open var label: LabelModel
open var action: ActionModelProtocol?
init(label: LabelModel) {
public init(label: LabelModel) {
self.label = label
}
@ -66,14 +126,26 @@ public class TabItemModel: Codable {
case action
}
open func setDefaults() {
if label.textAlignment == nil {
label.textAlignment = .center
}
}
public init(with label: LabelModel, action: ActionModelProtocol?) {
self.label = label
self.action = action
setDefaults()
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
label = try typeContainer.decode(LabelModel.self, forKey: .label)
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
setDefaults()
}
public func encode(to encoder: Encoder) throws {
open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeModel(label, forKey: .label)
try container.encodeModelIfPresent(action, forKey: .action)

View File

@ -50,13 +50,17 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol {
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
primaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .primaryButton)
if primaryButton?.style == nil {
primaryButton?.style = .primary
//set context value for 'primary' style to be set for the primaryButton in case the
//property is not returned in the JSON and once decoded, this value is removed from the context
try decoder.setContext(value: Styler.Button.Style.primary, for: "style") {
self.primaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .primaryButton)
}
secondaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .secondaryButton)
if secondaryButton?.style == nil {
secondaryButton?.style = .secondary
//set context value for 'secondary' style to be set for the primaryButton in case the
//property is not returned in the JSON and once decoded, this value is removed from the context
try decoder.setContext(value: Styler.Button.Style.secondary, for: "style") {
self.secondaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .secondaryButton)
}
}

View File

@ -42,6 +42,15 @@ class AccordionListItemModel: MoleculeListItemModel {
hideArrow = true
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with moleculeModel: MoleculeModelProtocol, molecules:[ListItemModelProtocol & MoleculeModelProtocol]) {
self.molecules = molecules
super.init(with: moleculeModel)
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -8,6 +8,7 @@
@objcMembers open class CarouselItemModel: MoleculeCollectionItemModel, CarouselItemModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
@ -18,8 +19,16 @@
public var peakingArrowColor: Color?
public var analyticsData: JSONValueDictionary?
public var fieldValue: String?
public var enabled: Bool = true
public var readOnly: Bool = false
public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable?
public func formFieldValue() -> AnyHashable? { fieldValue }
public func formFieldValue() -> AnyHashable? {
guard enabled else { return nil }
return fieldValue
}
//--------------------------------------------------
// MARK: - Keys
@ -30,6 +39,10 @@
case peakingArrowColor
case analyticsData
case fieldValue
case fieldKey
case groupName
case enabled
case readOnly
}
//--------------------------------------------------
@ -42,6 +55,17 @@
peakingArrowColor = try typeContainer.decodeIfPresent(Color.self, forKey: .peakingArrowColor)
analyticsData = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .analyticsData)
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
self.groupName = groupName
}
baseValue = fieldValue
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
self.enabled = enabled
}
if let readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) {
self.readOnly = readOnly
}
try super.init(from: decoder)
}
@ -52,5 +76,7 @@
try container.encodeIfPresent(peakingArrowColor, forKey: .peakingArrowColor)
try container.encodeIfPresent(analyticsData, forKey: .analyticsData)
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
try container.encode(enabled, forKey: .enabled)
try container.encode(readOnly, forKey: .readOnly)
}
}

View File

@ -14,4 +14,14 @@ public class ActionDetailWithImageModel: MoleculeModelProtocol {
public var backgroundColor: Color?
public var headlineBodyButton: HeadlineBodyButtonModel
public var image: ImageViewModel
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(headlineBodyButton: HeadlineBodyButtonModel, image: ImageViewModel) {
self.headlineBodyButton = headlineBodyButton
self.image = image
}
}

View File

@ -7,6 +7,7 @@
//
import UIKit
import MVMCore
public class CornerLabelsModel: ParentMoleculeModelProtocol {
public static var identifier: String = "cornerLabels"
@ -20,7 +21,7 @@ public class CornerLabelsModel: ParentMoleculeModelProtocol {
[molecule, topLeftLabel, topRightLabel, bottomLeftLabel, bottomRightLabel].compactMap { $0 }
}
init(with molecule: MoleculeModelProtocol?) {
public init(with molecule: MoleculeModelProtocol?) {
self.molecule = molecule
}

View File

@ -7,6 +7,7 @@
//
import Foundation
import MVMCore
public class LabelToggleModel: MoleculeModelProtocol {
public static var identifier: String = "labelToggle"
@ -15,7 +16,7 @@ public class LabelToggleModel: MoleculeModelProtocol {
public var label: LabelModel
public var toggle: ToggleModel
init(_ label: LabelModel, _ toggle: ToggleModel) {
public init(_ label: LabelModel, _ toggle: ToggleModel) {
self.label = label
self.toggle = toggle
}

View File

@ -5,6 +5,8 @@
// Created by Scott Pfeil on 5/18/20.
//
import UIKit
public class NavigationImageButtonModel: NavigationButtonModelProtocol, MoleculeModelProtocol {
//--------------------------------------------------
@ -17,6 +19,7 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule
public var image: String
public var action: ActionModelProtocol
public var accessibilityText: String?
public var imageRenderingMode: UIImage.RenderingMode = .automatic
//--------------------------------------------------
// MARK: - Initializer
@ -37,6 +40,7 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule
case accessibilityIdentifier
case moleculeName
case accessibilityText
case imageRenderingMode
}
//--------------------------------------------------
@ -49,6 +53,9 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule
image = try typeContainer.decode(String.self, forKey: .image)
action = try typeContainer.decodeModel(codingKey: .action)
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
if let mode = try typeContainer.decodeIfPresent(UIImage.RenderingMode.self, forKey: .imageRenderingMode) {
imageRenderingMode = mode
}
}
open func encode(to encoder: Encoder) throws {
@ -58,6 +65,7 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeModel(action, forKey: .action)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
try container.encodeIfPresent(imageRenderingMode, forKey: .imageRenderingMode)
}
//--------------------------------------------------
@ -66,7 +74,7 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule
/// Convenience function that creates a BarButtonItem for the model.
public func createNavigationItemButton(delegateObject: MVMCoreUIDelegateObject? = nil, additionalData: [AnyHashable: Any]? = nil) -> UIBarButtonItem {
let uiImage = MVMCoreCache.shared()?.getImageFromRegisteredBundles(image)
let uiImage = MVMCoreCache.shared()?.getImageFromRegisteredBundles(image)?.withRenderingMode(imageRenderingMode)
let buttonItem = ImageBarButtonItem.create(with: uiImage, model: self, delegateObject: delegateObject, additionalData: additionalData)
buttonItem.accessibilityIdentifier = accessibilityIdentifier ?? image
if let accessibilityString = accessibilityText {

View File

@ -6,6 +6,12 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import VDSColorTokens
public enum NavigationItemStyle: String, Codable {
case light
case dark
}
open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtocol {
//--------------------------------------------------
@ -14,12 +20,39 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
open class var identifier: String { "navigationBar" }
private let defaultHidesSystemBackButton = true
open var title: String?
open var hidden: Bool
open var backgroundColor: Color?
open var tintColor: Color
open var line: LineModel?
open var hidden = false
open var line: LineModel? = LineModel(type: .secondary)
open var hidesSystemBackButton = true
open var style: NavigationItemStyle?
private var _backgroundColor: Color?
open var backgroundColor: Color? {
get {
if let backgroundColor = _backgroundColor { return backgroundColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.backgroundPrimaryDark) }
return Color(uiColor: VDSColor.backgroundPrimaryLight)
}
set {
_backgroundColor = newValue
}
}
private var _tintColor: Color?
open var tintColor: Color {
get {
if let tintColor = _tintColor { return tintColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.elementsPrimaryOndark) }
return Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
set {
_tintColor = newValue
}
}
/// If true, we add the button in the backButton property. If false we do not add the button. If nil, we add the button if the controller is not the bottom of the stack
open var alwaysShowBackButton: Bool?
@ -28,17 +61,13 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
open var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
open var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
open var titleView: MoleculeModelProtocol?
open var titleOffset: UIOffset? = UIOffset(horizontal: -CGFloat.greatestFiniteMagnitude, vertical: 0)
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {
hidden = false
backgroundColor = Color(uiColor: .mvmWhite)
tintColor = Color(uiColor: .mvmBlack)
line = LineModel(type: .standard)
}
public init() {}
//--------------------------------------------------
// MARK: - Keys
@ -51,11 +80,14 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
case backgroundColor
case tintColor
case line
case hidesSystemBackButton
case alwaysShowBackButton
case backButton
case additionalLeftButtons
case additionalRightButtons
case titleView
case style
case titleOffset
}
//--------------------------------------------------
@ -65,15 +97,27 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) ?? false
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) ?? Color(uiColor: .mvmWhite)
tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor) ?? Color(uiColor: .mvmBlack)
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) ?? LineModel(type: .standard)
if let hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) {
self.hidden = hidden
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
_tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor)
if let line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) {
self.line = line
}
if let hidesSystemBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidesSystemBackButton) {
self.hidesSystemBackButton = hidesSystemBackButton
}
alwaysShowBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .alwaysShowBackButton)
backButton = try typeContainer.decodeModelIfPresent(codingKey: .backButton)
additionalLeftButtons = try typeContainer.decodeModelsIfPresent(codingKey: .additionalLeftButtons)
additionalRightButtons = try typeContainer.decodeModelsIfPresent(codingKey: .additionalRightButtons)
titleView = try typeContainer.decodeModelIfPresent(codingKey: .titleView)
style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style)
if let titleOffset = try typeContainer.decodeIfPresent(UIOffset.self, forKey: .titleOffset) {
self.titleOffset = titleOffset
}
line?.inverted = style == .dark
}
open func encode(to encoder: Encoder) throws {
@ -81,14 +125,17 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(title, forKey: .title)
try container.encode(hidden, forKey: .hidden)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encode(tintColor, forKey: .tintColor)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(_tintColor, forKey: .tintColor)
try container.encodeIfPresent(line, forKey: .line)
try container.encode(hidesSystemBackButton, forKey: .hidesSystemBackButton)
try container.encodeIfPresent(alwaysShowBackButton, forKey: .alwaysShowBackButton)
try container.encodeModelIfPresent(backButton, forKey: .backButton)
try container.encodeModelsIfPresent(additionalLeftButtons, forKey: .additionalLeftButtons)
try container.encodeModelsIfPresent(additionalRightButtons, forKey: .additionalRightButtons)
try container.encodeModelIfPresent(titleView, forKey: .titleView)
try container.encodeIfPresent(style, forKey: .style)
try container.encodeIfPresent(titleOffset, forKey: .titleOffset)
}
}

View File

@ -22,7 +22,7 @@ public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtoc
// MARK: - Initializer
//--------------------------------------------------
init(headlineBody: HeadlineBodyModel, image: ImageViewModel) {
public init(headlineBody: HeadlineBodyModel, image: ImageViewModel) {
self.headlineBody = headlineBody
self.image = image
super.init()

View File

@ -54,27 +54,27 @@ open class HeadlineBody: View {
}
public func styleLandingPageHeader() {
headlineLabel.setFontStyle(.Title2XLarge)
messageLabel.setFontStyle(.RegularBodySmall)
spaceBetweenLabelsConstant = Padding.Two
headlineLabel.setFontStyle(.RegularTitle2XLarge)
messageLabel.setFontStyle(.RegularTitleMedium)
spaceBetweenLabelsConstant = Padding.Four
}
public func stylePageHeader() {
headlineLabel.setFontStyle(.BoldTitleLarge)
headlineLabel.setFontStyle(.RegularTitleLarge)
messageLabel.setFontStyle(.RegularBodyLarge)
spaceBetweenLabelsConstant = Padding.Two
}
public func styleListItem() {
headlineLabel.setFontStyle(.RegularTitleSmall)
messageLabel.setFontStyle(.RegularBodySmall)
spaceBetweenLabelsConstant = Padding.One
}
public func styleListItem() {
headlineLabel.setFontStyle(.BoldBodySmall)
messageLabel.setFontStyle(.RegularBodySmall)
spaceBetweenLabelsConstant = 0
}
public func styleListItemDivider() {
headlineLabel.setFontStyle(.BoldTitleMedium)
headlineLabel.setFontStyle(.BoldTitleSmall)
messageLabel.setFontStyle(.RegularBodySmall)
spaceBetweenLabelsConstant = 0
spaceBetweenLabelsConstant = Padding.Two
}
//--------------------------------------------------

View File

@ -5,7 +5,7 @@
// Created by Scott Pfeil on 1/22/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
public class HeadlineBodyButtonModel: MoleculeModelProtocol {
//--------------------------------------------------
@ -20,6 +20,16 @@ public class HeadlineBodyButtonModel: MoleculeModelProtocol {
public var button: ButtonModel
public var buttonHeadlinePadding: CGFloat
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(headlineBody: HeadlineBodyModel, button: ButtonModel, buttonHeadlinePadding: CGFloat) {
self.headlineBody = headlineBody
self.button = button
self.buttonHeadlinePadding = buttonHeadlinePadding
}
//--------------------------------------------------
// MARK: - Method
//--------------------------------------------------

View File

@ -22,7 +22,7 @@ public class HeadlineBodyCaretLinkImageModel: ContainerModel, MoleculeModelProto
// MARK: - Initializer
//--------------------------------------------------
init(headlineBody: HeadlineBodyModel, image: ImageViewModel) {
public init(headlineBody: HeadlineBodyModel, image: ImageViewModel) {
self.headlineBody = headlineBody
self.image = image
super.init()

View File

@ -20,6 +20,15 @@ import Foundation
case list
case numberColor
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(numberColor: Color, molecules: [StackItemModelProtocol & MoleculeModelProtocol], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) {
self.numberColor = numberColor
super.init(molecules: molecules, axis: axis, spacing: spacing)
}
// Numbered list model comes in the from of list = [MoleculeModelProtocol]
public required init(from decoder: Decoder) throws {

View File

@ -22,7 +22,17 @@ import Foundation
case bulletChar
case bulletColor
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(bulletChar: String, bulletColor: Color, molecules: [StackItemModelProtocol & MoleculeModelProtocol], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) {
self.bulletChar = bulletChar
self.bulletColor = bulletColor
super.init(molecules: molecules, axis: axis, spacing: spacing)
}
// Numbered list model comes in the from of list = [MoleculeModelProtocol]
public required init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
@ -36,7 +46,7 @@ import Foundation
for molecule in list {
models.append(MoleculeStackItemModel(with: StringAndMoleculeModel(string: bulletChar, molecule: molecule, stringColor: bulletColor)))
}
super.init(molecules: models, spacing: 0)
super.init(molecules: models, spacing: Padding.Four)
}
public override func encode(to encoder: Encoder) throws {

View File

@ -37,6 +37,8 @@ import UIKit
public var baseValue: AnyHashable?
public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName
public var enabled: Bool = true
public var readOnly: Bool = false
public var selectable = false
public var selectedIndex: Int?
@ -46,6 +48,8 @@ import UIKit
}
public func formFieldValue() -> AnyHashable? {
guard enabled else { return nil }
guard selectable else {
// Use visible item value, else index
if let fieldValue = molecules[index].formFieldValue() {
@ -84,6 +88,8 @@ import UIKit
case fieldKey
case selectable
case selectedIndex
case enabled
case readOnly
}
//--------------------------------------------------
@ -117,10 +123,16 @@ import UIKit
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
self.groupName = groupName
}
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
self.enabled = enabled
}
if let readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) {
self.readOnly = readOnly
}
baseValue = formFieldValue()
}
public func encode(to encoder: Encoder) throws {
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
@ -142,6 +154,8 @@ import UIKit
try container.encode(index, forKey: .index)
try container.encode(selectable, forKey: .selectable)
try container.encode(selectedIndex, forKey: .selectedIndex)
try container.encode(enabled, forKey: .enabled)
try container.encode(readOnly, forKey: .readOnly)
}
}

View File

@ -7,17 +7,13 @@
//
public protocol CarouselItemModelProtocol: ContainerModelProtocol {
public protocol CarouselItemModelProtocol: FormFieldProtocol, ContainerModelProtocol {
var analyticsData: JSONValueDictionary? { get set }
func formFieldValue() -> AnyHashable?
}
public extension CarouselItemModelProtocol {
var analyticsData: JSONValueDictionary? {
get { nil }
set { analyticsData = newValue }
}
func formFieldValue() -> AnyHashable? { nil }
}

View File

@ -0,0 +1,13 @@
//
// ClearableModelProtocol.swift
// MVMCoreUI
//
// Created by Matt Bruce on 1/11/22.
// Copyright © 2022 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol ClearableModelProtocol {
func clear()
}

View File

@ -9,6 +9,6 @@
import Foundation
public protocol EnableableModelProtocol {
public protocol EnableableModelProtocol: AnyObject {
var enabled: Bool { get set }
}

View File

@ -20,4 +20,5 @@ public protocol NavigationItemModelProtocol {
var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? { get set }
var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? { get set }
var titleView: MoleculeModelProtocol? { get set }
var titleOffset: UIOffset? { get }
}

View File

@ -23,4 +23,33 @@ public protocol MoleculeDelegateProtocol: AnyObject {
extension MoleculeDelegateProtocol {
public func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { }
public func getModuleWithName(_ moleculeName: String) -> MoleculeModelProtocol? {
let moduleJSON: [AnyHashable: Any]? = getModuleWithName(moleculeName)
guard let moduleJSON = moduleJSON as? [String: Any],
let moleculeName = moduleJSON.optionalStringForKey("moleculeName"),
let modelType = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self)
else { return nil }
do {
return try modelType.decode(jsonDict: moduleJSON as [String : Any]) as? MoleculeModelProtocol
} catch {
MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)")
}
return nil
}
}
extension MoleculeDelegateProtocol where Self: TemplateProtocol {
public func getRootMolecules() -> [MoleculeModelProtocol] {
templateModel?.rootMolecules ?? []
}
}
extension MoleculeDelegateProtocol where Self: MVMCoreViewControllerProtocol {
public func getModuleWithName(_ name: String?) -> [AnyHashable : Any]? {
guard let name = name else { return nil }
return loadObject??.modulesJSON?.optionalDictionaryForKey(name)
}
}

View File

@ -70,7 +70,7 @@ public extension ModelRegistry {
return type
} catch {
if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: #function) {
MVMCoreLoggingHandler.shared()?.addError(toLog: errorObject)
MVMCoreLoggingHandler.addError(toLog: errorObject)
}
return nil
}

Some files were not shown because too many files have changed in this diff Show More