diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 6bae9611..08865ee9 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -68,6 +68,8 @@ 0A21DB83235DFBC500C160A2 /* MdnEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A21DB82235DFBC500C160A2 /* MdnEntryField.swift */; }; 0A21DB91235E0EDB00C160A2 /* DigitBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */; }; 0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A21DB93235E24ED00C160A2 /* DigitEntryField.swift */; }; + 0A25209624645AFD000FA9F6 /* TextViewEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A25209524645AFD000FA9F6 /* TextViewEntryField.swift */; }; + 0A25209824645B76000FA9F6 /* TextViewEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A25209724645B76000FA9F6 /* TextViewEntryFieldModel.swift */; }; 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; }; 0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */; }; 0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */; }; @@ -76,7 +78,6 @@ 0A6682AA2435125F00AD3CA1 /* Styler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6682A92435125F00AD3CA1 /* Styler.swift */; }; 0A6682AC243531C300AD3CA1 /* Padding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6682AB243531C300AD3CA1 /* Padding.swift */; }; 0A6682B5243769C700AD3CA1 /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6682B3243769C700AD3CA1 /* TextView.swift */; }; - 0A6682B6243769C700AD3CA1 /* TextViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6682B4243769C700AD3CA1 /* TextViewModel.swift */; }; 0A69F611241BDEA700F7231B /* RuleAnyRequiredModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */; }; 0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6BF4712360C56C0028F841 /* BaseDropdownEntryField.swift */; }; 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; }; @@ -91,6 +92,7 @@ 0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86223D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift */; }; 0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */; }; 0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */; }; + 0A849EFE246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A849EFD246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift */; }; 0A9D091D2433796500D2E6C0 /* BarsCarouselIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D09172433796500D2E6C0 /* BarsCarouselIndicatorModel.swift */; }; 0A9D091E2433796500D2E6C0 /* NumericCarouselIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D09182433796500D2E6C0 /* NumericCarouselIndicatorModel.swift */; }; 0A9D091F2433796500D2E6C0 /* NumericIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D09192433796500D2E6C0 /* NumericIndicatorView.swift */; }; @@ -148,8 +150,6 @@ 8DE5BECF2456F7B100772E76 /* ListTwoColumnDropdownSelectors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DE5BECE2456F7B100772E76 /* ListTwoColumnDropdownSelectors.swift */; }; 8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */; }; 8DEFA95E243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift */; }; - 942C372E241149170066E45E /* NHaasGroteskDSStd-75Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = 942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */; }; - 942C372F241149170066E45E /* NHaasGroteskDSStd-55Rg.otf in Resources */ = {isa = PBXBuildFile; fileRef = 942C372D241149170066E45E /* NHaasGroteskDSStd-55Rg.otf */; }; 942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */; }; 942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */; }; 9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */; }; @@ -181,6 +181,8 @@ 94CA227D24058534002D6750 /* VerizonNHGeDS-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227924058533002D6750 /* VerizonNHGeDS-Regular.otf */; }; 94CA227E24058534002D6750 /* VerizonNHGeDS-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227A24058533002D6750 /* VerizonNHGeDS-Bold.otf */; }; 94F6516D2437954100631BF9 /* Tabs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94F6516C2437954100631BF9 /* Tabs.swift */; }; + AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA104B1924474A66004D2810 /* HeadersH2Buttons.swift */; }; + AA104B1C24474A76004D2810 /* HeadersH2ButtonsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA104B1B24474A76004D2810 /* HeadersH2ButtonsModel.swift */; }; AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */; }; AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */; }; AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift */; }; @@ -198,6 +200,8 @@ AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */; }; AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; }; AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; }; + AAB7EDEF246ADA1600E54929 /* ListProgressBarThinModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB7EDEE246ADA1600E54929 /* ListProgressBarThinModel.swift */; }; + AAB7EDF1246ADA2A00E54929 /* ListProgressBarThin.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB7EDF0246ADA2A00E54929 /* ListProgressBarThin.swift */; }; AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; }; AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C109243496DD00151545 /* RadioSwatch.swift */; }; AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */; }; @@ -477,6 +481,8 @@ 0A21DB7E235DECC500C160A2 /* EntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryField.swift; sourceTree = ""; }; 0A21DB82235DFBC500C160A2 /* MdnEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MdnEntryField.swift; sourceTree = ""; }; 0A21DB93235E24ED00C160A2 /* DigitEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitEntryField.swift; sourceTree = ""; }; + 0A25209524645AFD000FA9F6 /* TextViewEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewEntryField.swift; sourceTree = ""; }; + 0A25209724645B76000FA9F6 /* TextViewEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewEntryFieldModel.swift; sourceTree = ""; }; 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CATransaction+Extension.swift"; sourceTree = ""; }; 0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEntryField.swift; sourceTree = ""; }; 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleGuidelinesProtocol.swift; sourceTree = ""; }; @@ -485,7 +491,6 @@ 0A6682A92435125F00AD3CA1 /* Styler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Styler.swift; sourceTree = ""; }; 0A6682AB243531C300AD3CA1 /* Padding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Padding.swift; sourceTree = ""; }; 0A6682B3243769C700AD3CA1 /* TextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextView.swift; sourceTree = ""; }; - 0A6682B4243769C700AD3CA1 /* TextViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextViewModel.swift; sourceTree = ""; }; 0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyRequiredModel.swift; sourceTree = ""; }; 0A6BF4712360C56C0028F841 /* BaseDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDropdownEntryField.swift; sourceTree = ""; }; 0A7918F423F5E7EA00772FF4 /* ImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageView.swift; sourceTree = ""; }; @@ -503,6 +508,7 @@ 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryFieldModel.swift; sourceTree = ""; }; 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryFieldModel.swift; sourceTree = ""; }; 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = ""; }; + 0A849EFD246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleEqualsIgnoreCaseModel.swift; sourceTree = ""; }; 0A9D09172433796500D2E6C0 /* BarsCarouselIndicatorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarsCarouselIndicatorModel.swift; sourceTree = ""; }; 0A9D09182433796500D2E6C0 /* NumericCarouselIndicatorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumericCarouselIndicatorModel.swift; sourceTree = ""; }; 0A9D09192433796500D2E6C0 /* NumericIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumericIndicatorView.swift; sourceTree = ""; }; @@ -562,8 +568,6 @@ 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDividerModel.swift; sourceTree = ""; }; 8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDivider.swift; sourceTree = ""; }; 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = ""; }; - 942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-75Bd.otf"; sourceTree = ""; }; - 942C372D241149170066E45E /* NHaasGroteskDSStd-55Rg.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-55Rg.otf"; sourceTree = ""; }; 942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalMoleculeListTemplate.swift; sourceTree = ""; }; 942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalMoleculeStackTemplate.swift; sourceTree = ""; }; 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntryFieldContainer.swift; sourceTree = ""; }; @@ -594,6 +598,8 @@ 94CA227A24058533002D6750 /* VerizonNHGeDS-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeDS-Bold.otf"; sourceTree = ""; }; 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeTX-Regular.otf"; sourceTree = ""; }; 94F6516C2437954100631BF9 /* Tabs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tabs.swift; sourceTree = ""; }; + AA104B1924474A66004D2810 /* HeadersH2Buttons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2Buttons.swift; sourceTree = ""; }; + AA104B1B24474A76004D2810 /* HeadersH2ButtonsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2ButtonsModel.swift; sourceTree = ""; }; AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePayments.swift; sourceTree = ""; }; AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePaymentsModel.swift; sourceTree = ""; }; AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDividerModel.swift; sourceTree = ""; }; @@ -611,6 +617,8 @@ AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchCollectionViewCell.swift; sourceTree = ""; }; AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = ""; }; AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = ""; }; + AAB7EDEE246ADA1600E54929 /* ListProgressBarThinModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListProgressBarThinModel.swift; sourceTree = ""; }; + AAB7EDF0246ADA2A00E54929 /* ListProgressBarThin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListProgressBarThin.swift; sourceTree = ""; }; AAB9C10724346F4B00151545 /* RadioSwatches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatches.swift; sourceTree = ""; }; AAB9C109243496DD00151545 /* RadioSwatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatch.swift; sourceTree = ""; }; AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchesModel.swift; sourceTree = ""; }; @@ -871,6 +879,7 @@ 011D95A0240453D0000E3791 /* RuleEqualsModel.swift */, 011D95A2240453F8000E3791 /* RuleRegexModel.swift */, 0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */, + 0A849EFD246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift */, ); name = Rules; path = Rules/Rules; @@ -968,6 +977,8 @@ AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */, AA26850D244840C300CE34CC /* HeadersH2TinyButtonModel.swift */, AA26850B244840AE00CE34CC /* HeadersH2TinyButton.swift */, + AA104B1B24474A76004D2810 /* HeadersH2ButtonsModel.swift */, + AA104B1924474A66004D2810 /* HeadersH2Buttons.swift */, ); path = Headers; sourceTree = ""; @@ -1253,6 +1264,8 @@ D20492F12434CB5F00A5EED6 /* FourColumn */, AA4FC2A323F4F69600E251DB /* RightVariable */, D22B38EB23F4E0AE00490EF6 /* LeftVariable */, + AAB7EDEE246ADA1600E54929 /* ListProgressBarThinModel.swift */, + AAB7EDF0246ADA2A00E54929 /* ListProgressBarThin.swift */, ); path = List; sourceTree = ""; @@ -1652,6 +1665,8 @@ 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */, 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */, 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */, + 0A25209724645B76000FA9F6 /* TextViewEntryFieldModel.swift */, + 0A25209524645AFD000FA9F6 /* TextViewEntryField.swift */, ); path = TextFields; sourceTree = ""; @@ -1722,8 +1737,6 @@ 94CA227924058533002D6750 /* VerizonNHGeDS-Regular.otf */, 94CA227824058533002D6750 /* VerizonNHGeTX-Bold.otf */, 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */, - 942C372D241149170066E45E /* NHaasGroteskDSStd-55Rg.otf */, - 942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */, D29DF31721ECECC0003B2FB9 /* OCRAExtended.ttf */, ); path = Fonts; @@ -1762,7 +1775,6 @@ D2B18B7D236090D500A9AEDC /* BaseClasses */ = { isa = PBXGroup; children = ( - 0A6682B4243769C700AD3CA1 /* TextViewModel.swift */, 0A6682B3243769C700AD3CA1 /* TextView.swift */, C003506023AA94CD00B6AC29 /* Button.swift */, D2B18B7E2360913400A9AEDC /* Control.swift */, @@ -1910,8 +1922,6 @@ D29DF32C21EE8736003B2FB9 /* Localizable.strings in Resources */, 94CA227D24058534002D6750 /* VerizonNHGeDS-Regular.otf in Resources */, D29DF32E21EE8C3D003B2FB9 /* Media.xcassets in Resources */, - 942C372E241149170066E45E /* NHaasGroteskDSStd-75Bd.otf in Resources */, - 942C372F241149170066E45E /* NHaasGroteskDSStd-55Rg.otf in Resources */, 94CA227E24058534002D6750 /* VerizonNHGeDS-Bold.otf in Resources */, D287651A245B338E00CB882D /* VerizonNHGeTX-Regular.otf in Resources */, D29DF31B21ECECC0003B2FB9 /* OCRAExtended.ttf in Resources */, @@ -2040,10 +2050,12 @@ 943820842432382400B43AF3 /* WebView.swift in Sources */, 0103B84E23D7E33A009C315C /* HeadlineBodyToggleModel.swift in Sources */, D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */, + 0A25209624645AFD000FA9F6 /* TextViewEntryField.swift in Sources */, 014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */, AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */, 011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */, 8DDD6C1D244D90B8006A2232 /* ListThreeColumnDataUsage.swift in Sources */, + 0A849EFE246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift in Sources */, D28764FB245A33A500CB882D /* TwoLinkViewModel.swift in Sources */, AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */, D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */, @@ -2153,7 +2165,6 @@ 012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */, 0A9D091E2433796500D2E6C0 /* NumericCarouselIndicatorModel.swift in Sources */, D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */, - 0A6682B6243769C700AD3CA1 /* TextViewModel.swift in Sources */, 9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */, 011D95A5240455DC000E3791 /* FormGroupRule.swift in Sources */, D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */, @@ -2195,6 +2206,7 @@ C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */, 01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */, D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */, + AAB7EDF1246ADA2A00E54929 /* ListProgressBarThin.swift in Sources */, 8D070BB2241B56AD0099AC56 /* ListRightVariableTotalData.swift in Sources */, D264FAA5243F66A500D98315 /* CollectionTemplateItemProtocol.swift in Sources */, D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */, @@ -2247,10 +2259,12 @@ C003506123AA94CD00B6AC29 /* Button.swift in Sources */, DBC4391B224421A0001AB423 /* CaretLink.swift in Sources */, D264FA90243BCE6800D98315 /* ThreeLayerCollectionViewController.swift in Sources */, + AA104B1C24474A76004D2810 /* HeadersH2ButtonsModel.swift in Sources */, 0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */, BB6C6AC824225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift in Sources */, 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */, D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */, + AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */, C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */, D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */, BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */, @@ -2273,6 +2287,7 @@ AA26850C244840AE00CE34CC /* HeadersH2TinyButton.swift in Sources */, 011D95AB2405C553000E3791 /* FormItemProtocol.swift in Sources */, D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */, + 0A25209824645B76000FA9F6 /* TextViewEntryFieldModel.swift in Sources */, 525019DD2406430800EED91C /* ListProgressBarDataModel.swift in Sources */, C6FA7D5223C77A4A00A3614A /* UnOrderedList.swift in Sources */, 01509D8F2327EC6F00EF99AA /* MoleculeTableViewCell.swift in Sources */, @@ -2280,6 +2295,7 @@ EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */, 0105618D224BBE7700E1557D /* FormValidator.swift in Sources */, 01509D912327ECE600EF99AA /* CornerLabels.swift in Sources */, + AAB7EDEF246ADA1600E54929 /* ListProgressBarThinModel.swift in Sources */, D21B7F75243BAC8900051ABF /* CarouselItem.swift in Sources */, C695A69823C990C200BFB94E /* DoughnutChartView.swift in Sources */, 8D3BA9BD2433787000D341BA /* ListThreeColumnInternationalDataDividerModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift index abdc1242..b0e4d54d 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift @@ -8,40 +8,69 @@ import UIKit -public enum ButtonStyle: String, Codable { - case primary - case secondary -} +public typealias FacadeElements = (fill: UIColor?, text: UIColor?, border: UIColor?) -public enum ButtonSize: String, Codable { - case standard - case tiny -} public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "button" public var backgroundColor: Color? public var title: String public var action: ActionModelProtocol public var enabled: Bool = true - public var style: ButtonStyle? - public var size: ButtonSize? = .standard - public var fillColor: Color? - public var textColor: Color? - public var borderColor: Color? + public var style: Styler.Button.Style? { + didSet { + guard let style = style else { return } + setFacade(by: style) + } + } + public var size: Styler.Button.Size? = .standard + public var groupName: String = "" + public var inverted: Bool = false + + public lazy var enabledColors: FacadeElements = (fill: enabled_fillColor(), + text: enabled_textColor(), + border: enabled_borderColor()) + + public lazy var disabledColors: FacadeElements = (fill: disabled_fillColor(), + text: disabled_textColor(), + border: disabled_borderColor()) + + public var enabledFillColor: Color? + public var enabledTextColor: Color? + public var enabledBorderColor: Color? + + public var enabledFillColor_inverted: Color? + public var enabledTextColor_inverted: Color? + public var enabledBorderColor_inverted: Color? + public var disabledFillColor: Color? public var disabledTextColor: Color? public var disabledBorderColor: Color? - public var groupName: String = "" - + + public var disabledFillColor_inverted: Color? + public var disabledTextColor_inverted: Color? + public var disabledBorderColor_inverted: Color? + + //-------------------------------------------------- + // 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: (() -> Void)? - + public var updateUI: ActionBlock? + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + public init(with title: String, action: ActionModelProtocol) { self.title = title self.action = action @@ -52,71 +81,185 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW self.action = action style = .secondary } - + public init(primaryButtonWith title: String, action: ActionModelProtocol) { self.title = title self.action = action style = .primary } + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + + public func enabled_fillColor() -> UIColor? { + return (inverted ? enabledFillColor_inverted : enabledFillColor)?.uiColor + } + + public func enabled_textColor() -> UIColor? { + return (inverted ? enabledTextColor_inverted : enabledTextColor)?.uiColor + } + + public func enabled_borderColor() -> UIColor? { + return (inverted ? enabledBorderColor_inverted : enabledBorderColor)?.uiColor + } + + public func disabled_fillColor() -> UIColor? { + return (inverted ? disabledFillColor_inverted : disabledFillColor)?.uiColor + } + + public func disabled_textColor() -> UIColor? { + return (inverted ? disabledTextColor_inverted : disabledTextColor)?.uiColor + } + + public func disabled_borderColor() -> UIColor? { + return (inverted ? disabledBorderColor_inverted : disabledBorderColor)?.uiColor + } + + /// Defines the default appearance for the primary style. + func setPrimaryFacade() { + + 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) + } + + /// Defines the default appearance for the Secondary style. + func setSecondaryFacade() { + + 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) + } + + public func setFacade(by style: Styler.Button.Style) { + + switch style { + case .primary: + setPrimaryFacade() + + case .secondary: + setSecondaryFacade() + } + } + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { case moleculeName case backgroundColor case title + case inverted case action case enabled case style case size + case groupName case fillColor case textColor case borderColor case disabledFillColor case disabledTextColor case disabledBorderColor - case groupName } - + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) title = try typeContainer.decode(String.self, forKey: .title) action = try typeContainer.decodeModel(codingKey: .action) - if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { - self.groupName = groupName - } - if let style = try typeContainer.decodeIfPresent(ButtonStyle.self, forKey: .style) { + + if let style = try typeContainer.decodeIfPresent(Styler.Button.Style.self, forKey: .style) { self.style = style + setFacade(by: style) } - if let size = try typeContainer.decodeIfPresent(ButtonSize.self, forKey: .size) { + + if let size = try typeContainer.decodeIfPresent(Styler.Button.Size.self, forKey: .size) { self.size = size } + if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { self.enabled = enabled } - fillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .fillColor) - textColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor) - borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor) - disabledFillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledFillColor) - disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) - disabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledBorderColor) + + if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) { + self.inverted = inverted + } + + if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { + self.groupName = groupName + } + + if let enabledFillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .fillColor) { + self.enabledFillColor = enabledFillColor + } + + if let enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor) { + self.enabledTextColor = enabledTextColor + } + + if let enabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor) { + self.enabledBorderColor = enabledBorderColor + } + + if let disabledFillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledFillColor) { + self.disabledFillColor = disabledFillColor + } + + if let disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) { + self.disabledTextColor = disabledTextColor + } + + if let disabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledBorderColor) { + self.disabledBorderColor = disabledBorderColor + } } - + public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(title, forKey: .title) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) - try container.encodeModel(action, forKey: .action) try container.encode(enabled, forKey: .enabled) - try container.encodeIfPresent(style, forKey: .style) - try container.encodeIfPresent(size, forKey: .size) - try container.encodeIfPresent(fillColor, forKey: .fillColor) - try container.encodeIfPresent(textColor, forKey: .textColor) - try container.encodeIfPresent(borderColor, forKey: .borderColor) + try container.encode(inverted, forKey: .inverted) + try container.encodeModel(action, forKey: .action) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encodeIfPresent(enabledFillColor, forKey: .fillColor) + try container.encodeIfPresent(enabledTextColor, forKey: .textColor) + try container.encodeIfPresent(enabledBorderColor, forKey: .borderColor) try container.encodeIfPresent(disabledFillColor, forKey: .disabledFillColor) try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor) try container.encodeIfPresent(disabledBorderColor, forKey: .disabledBorderColor) + try container.encodeIfPresent(style, forKey: .style) + try container.encodeIfPresent(size, forKey: .size) try container.encodeIfPresent(groupName, forKey: .groupName) } } diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift index b437a56f..d23a2606 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift @@ -71,7 +71,7 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { } public override func updateView(_ size: CGFloat) { - titleLabel?.font = MFStyler.fontB1() + titleLabel?.font = MFStyler.fontBoldBodySmall() } //------------------------------------------------------ diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index 19f032fc..f5a7ed44 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -8,80 +8,121 @@ import UIKit + open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { - // Used to size the button. + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + /// Used to size the button. var size = MVMCoreUIUtility.getWidth() var buttonModel: ButtonModel? { get { return model as? ButtonModel } } - // Need to re-style on set. + /// Need to re-style on set. open override var isEnabled: Bool { + didSet { style() } + } + + open var buttonSize: Styler.Button.Size = .standard { didSet { - style() + buttonModel?.size = buttonSize } } - private enum ButtonHeight: CGFloat { - case tiny = 20 - case standard = 42 + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + + @objc public convenience init(asPrimaryButton isPrimary: Bool, makeTiny istiny: Bool) { + self.init() + buttonSize = istiny ? .tiny : .standard + isPrimary ? stylePrimary() : styleSecondary() } + //-------------------------------------------------- + // MARK: - Computed Properties + //-------------------------------------------------- + + public var enabledTitleColor: UIColor? { + get { return titleColor(for: .normal) } + set { setTitleColor(newValue, for: .normal) } + } + + public var disabledTitleColor: UIColor? { + get { return titleColor(for: .disabled) } + set { setTitleColor(newValue, for: .disabled) } + } + + public var borderColor: UIColor? { + get { + guard let currentColor = layer.borderColor else { return nil } + return UIColor(cgColor: currentColor) + } + set { layer.borderColor = newValue?.cgColor } + } + + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + /// The primary styling for a button. Should be used for main buttons public func stylePrimary() { - setTitleColor(.white, for: .normal) - setTitleColor(.white, for: .disabled) + + enabledTitleColor = buttonModel?.enabledColors.text ?? .mvmWhite + disabledTitleColor = buttonModel?.disabledColors.text ?? .mvmWhite layer.borderWidth = 0 - if isEnabled { - backgroundColor = .black - } else { - backgroundColor = .mvmCoolGray6 - } + backgroundColor = isEnabled ? buttonModel?.enabledColors.fill ?? .mvmBlack : buttonModel?.disabledColors.fill ?? .mvmCoolGray6 } /// The secondary styling for a button. Should be used for secondary buttons public func styleSecondary() { - setTitleColor(.black, for: .normal) - setTitleColor(.mvmCoolGray6, for: .disabled) + + enabledTitleColor = buttonModel?.enabledColors.text ?? .mvmBlack + disabledTitleColor = buttonModel?.disabledColors.text ?? .mvmCoolGray6 backgroundColor = .clear layer.borderWidth = 1 - if isEnabled { - layer.borderColor = UIColor.black.cgColor - } else { - layer.borderColor = UIColor.mvmCoolGray6.cgColor - } + borderColor = isEnabled ? buttonModel?.enabledColors.border ?? .mvmBlack : buttonModel?.disabledColors.border ?? .mvmCoolGray6 } /// Styles the button based on the model style private func style() { + switch buttonModel?.style { case .secondary: styleSecondary() + default: stylePrimary() } - if let titleColor = buttonModel?.textColor { - setTitleColor(titleColor.uiColor, for: .normal) + + if let titleColor = buttonModel?.enabledColors.text { + enabledTitleColor = titleColor } - if let disabledTitleColor = buttonModel?.disabledTextColor { - setTitleColor(disabledTitleColor.uiColor, for: .disabled) + + if let disabledTitleColor = buttonModel?.disabledColors.text { + self.disabledTitleColor = disabledTitleColor } + if isEnabled { - if let fillColor = buttonModel?.fillColor { - backgroundColor = fillColor.uiColor + if let fillColor = buttonModel?.enabledColors.fill { + backgroundColor = fillColor } - if let borderColor = buttonModel?.borderColor { + + if let borderColor = buttonModel?.enabledColors.border { layer.borderWidth = 1 - layer.borderColor = borderColor.cgColor + self.borderColor = borderColor } } else { - if let fillColor = buttonModel?.disabledFillColor { - backgroundColor = fillColor.uiColor + if let fillColor = buttonModel?.disabledColors.fill { + backgroundColor = fillColor } - if let borderColor = buttonModel?.disabledBorderColor { + + if let borderColor = buttonModel?.disabledColors.border { layer.borderWidth = 1 - layer.borderColor = borderColor.cgColor + self.borderColor = borderColor } } } @@ -91,41 +132,58 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { } private func getHeight() -> CGFloat { - PillButton.getHeight(for: buttonModel?.size, size: size) + PillButton.getHeight(for: buttonSize, size: size) } - public static func getHeight(for buttonSize: ButtonSize?, size: CGFloat) -> CGFloat { + public static func getHeight(for buttonSize: Styler.Button.Size?, size: CGFloat) -> CGFloat { + switch buttonSize { case .tiny: - return MFSizeObject(standardSize: ButtonHeight.tiny.rawValue, standardiPadPortraitSize: 34, iPadProLandscapeSize: 38)?.getValueBased(onSize: size) ?? ButtonHeight.tiny.rawValue + let tinyHeight = Styler.Button.Size.tiny.getHeight() + return MFSizeObject(standardSize: tinyHeight, + standardiPadPortraitSize: 34, + iPadProLandscapeSize: 38)?.getValueBased(onSize: size) ?? tinyHeight + default: - return MFSizeObject(standardSize: ButtonHeight.standard.rawValue, standardiPadPortraitSize: 46, iPadProLandscapeSize: 50)?.getValueBased(onSize: size) ?? ButtonHeight.standard.rawValue + let standardHeight = Styler.Button.Size.standard.getHeight() + return MFSizeObject(standardSize: standardHeight, + standardiPadPortraitSize: 46, + iPadProLandscapeSize: 50)?.getValueBased(onSize: size) ?? standardHeight } } - + private func getMinimumWidth() -> CGFloat { - switch buttonModel?.size { + + switch buttonSize { case .tiny: - return MFSizeObject(standardSize: 49.0, standardiPadPortraitSize: 90.0, iPadProLandscapeSize: 135.0)?.getValueBased(onSize: size) ?? 49.0 - default: - return 151.0 + return MFSizeObject(standardSize: 49, + standardiPadPortraitSize: 90, + iPadProLandscapeSize: 135)?.getValueBased(onSize: size) ?? 49 + + default: return 151 } } open override var intrinsicContentSize: CGSize { + let size = super.intrinsicContentSize let width = size.width + (2 * getInnerPadding()) return CGSize(width: max(width, getMinimumWidth()), height: getHeight()) } - // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { // The button will get styled in the enable check in super. super.set(with: model, delegateObject, additionalData) - + guard let model = model as? ButtonModel else { return } setTitle(model.title, for: .normal) - + if let size = model.size { + buttonSize = size + } model.updateUI = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { self?.enableField(model.enabled) @@ -134,39 +192,46 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) } - + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { PillButton.getHeight(for: (model as? ButtonModel)?.size, size: MVMCoreUIUtility.getWidth()) } - // MARK: - MVMCoreViewProtocol open override func updateView(_ size: CGFloat) { super.updateView(size) self.size = size + invalidateIntrinsicContentSize() - switch buttonModel?.size { + + switch buttonSize { case .tiny: - titleLabel?.font = MFFonts.mfFont75Bd(11 * (intrinsicContentSize.height / ButtonHeight.tiny.rawValue)) + titleLabel?.font = MFFonts.mfFont75Bd(11 * (intrinsicContentSize.height / Styler.Button.Size.tiny.getHeight())) + default: - titleLabel?.font = MFFonts.mfFont75Bd(13 * (intrinsicContentSize.height / ButtonHeight.standard.rawValue)) + titleLabel?.font = MFFonts.mfFont75Bd(13 * (intrinsicContentSize.height / Styler.Button.Size.standard.getHeight())) } + layer.cornerRadius = getInnerPadding() } - + open override func setupView() { super.setupView() + titleLabel?.numberOfLines = 1 titleLabel?.lineBreakMode = .byTruncatingTail titleLabel?.textAlignment = .center contentHorizontalAlignment = .center stylePrimary() } - + + //-------------------------------------------------- // MARK: - MVMCoreUIViewConstrainingProtocol + //-------------------------------------------------- + open func horizontalAlignment() -> UIStackView.Alignment { return .center } - + public func enableField(_ enable: Bool) { isEnabled = enable } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift index 2b22fcee..1ac28ded 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift @@ -20,7 +20,7 @@ import UIKit } } - public override var isSelected: Bool { + @objc public override var isSelected: Bool { didSet { radioModel?.state = isSelected updateAccessibilityLabel() @@ -127,7 +127,7 @@ import UIKit func updateAccessibilityLabel() { if let state = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "radio_selected_state" : "radio_not_selected_state") { - accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "radio_desc_state") ?? "%@%@", "", state) + accessibilityLabel = state } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonSelectionHelper.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonSelectionHelper.swift index 5196bb9c..4765766b 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonSelectionHelper.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonSelectionHelper.swift @@ -19,22 +19,22 @@ import Foundation private var selectedRadioButton: RadioButton? private var selectedRadioButtonModel: RadioButtonModel? public var baseValue: AnyHashable? - -//-------------------------------------------------- -// MARK: - Initializer -//-------------------------------------------------- - + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + public func set(_ radioButtonModel: RadioButtonModel, _ radioButton: RadioButton) { self.fieldKey = radioButtonModel.fieldKey self.groupName = radioButtonModel.groupName - + if radioButtonModel.state { if self.baseValue == nil, let selected = radioButtonModel.baseValue as? Bool, selected { self.baseValue = radioButtonModel.fieldValue } selectedRadioButtonModel = radioButtonModel - + // Below code is needed for cell resuse scenario. radioButton.isSelected = true selectedRadioButton = radioButton @@ -50,24 +50,24 @@ import Foundation public static func setupForRadioButtonGroup(_ radioButtonModel: RadioButtonModel, _ radioButton: RadioButton, delegateObject: MVMCoreUIDelegateObject?) { guard let groupName = radioButtonModel.fieldKey, - let formValidator = delegateObject?.formHolderDelegate?.formValidator else { - return - } - + let formValidator = delegateObject?.formHolderDelegate?.formValidator + else { return } + let radioButtonSelectionHelper = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonSelectionHelper() radioButtonSelectionHelper.set(radioButtonModel, radioButton) formValidator.radioButtonsModelByGroup[groupName] = radioButtonSelectionHelper FormValidator.setupValidation(for: radioButtonSelectionHelper, delegate: delegateObject?.formHolderDelegate) } - + public func selected(_ radioButton: RadioButton) { + // Checks because the view could be reused if selectedRadioButton?.radioModel === selectedRadioButtonModel { selectedRadioButton?.isSelected = false } else { selectedRadioButtonModel?.state = false } - + selectedRadioButton = radioButton selectedRadioButton?.isSelected = true selectedRadioButtonModel = selectedRadioButton?.radioModel @@ -76,6 +76,7 @@ import Foundation // MARK: - FormValidationFormFieldProtocol extension RadioButtonSelectionHelper { + public func formFieldValue() -> AnyHashable? { return selectedRadioButtonModel?.fieldValue } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift index 35294457..d7413e07 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift @@ -6,9 +6,9 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // -import Foundation import UIKit + open class RadioSwatch: Control { //-------------------------------------------------- // MARK: - Properties diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift index 1fe0b1af..e54cb80f 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryField.swift @@ -69,6 +69,7 @@ import UIKit get { return entryFieldContainer.showError } set (error) { self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.feedback + self.feedbackLabel.textColor = error ? entryFieldModel?.errorTextColor?.uiColor ?? .mvmBlack : .mvmBlack self.entryFieldContainer.showError = error self.entryFieldModel?.showError = error } @@ -215,11 +216,10 @@ import UIKit entryFieldContainer.refreshUI() } - /** - Method to override. - Intended to add the interactive content (i.e. textField) to the entryFieldContainer. - */ - @objc open func setupFieldContainerContent(_ container: UIView) { } + /// Intended to add the interactive content (i.e. textField) to the entryFieldContainer. + @objc open func setupFieldContainerContent(_ container: UIView) { + // To Be Overriden + } @objc open override func updateView(_ size: CGFloat) { super.updateView(size) @@ -242,6 +242,7 @@ import UIKit titleLabel.textColor = .mvmBlack feedbackLabel.font = Styler.Font.RegularMicro.getFont() feedbackLabel.textColor = .mvmBlack + entryFieldContainer.disableAllBorders = false feedbackLabel.text = nil entryFieldContainer.reset() } @@ -257,6 +258,7 @@ import UIKit title = model.title feedback = model.feedback isEnabled = model.enabled + entryFieldContainer.disableAllBorders = model.hideBorders if let isLocked = model.locked { self.isLocked = isLocked diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift index f7886848..1d6e9221 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift @@ -22,8 +22,10 @@ import Foundation public var title: String? public var feedback: String? public var errorMessage: String? + public var errorTextColor: Color? public var enabled: Bool = true public var showError: Bool? + public var hideBorders = false public var locked: Bool? public var selected: Bool? public var text: String? @@ -37,7 +39,7 @@ import Foundation } /// Temporary binding mechanism for the view to update on enable changes. - public var updateUI: (() -> ())? + public var updateUI: ActionBlock? //-------------------------------------------------- // MARK: - Keys @@ -50,9 +52,11 @@ import Foundation case enabled case feedback case errorMessage + case errorTextColor case locked case selected case showError + case hideBorders case text case fieldKey case groupName @@ -67,7 +71,12 @@ import Foundation } public func setValidity(_ valid: Bool, rule: RulesProtocol) { + if let fieldKey = fieldKey, + let ruleErrorMessage = rule.errorMessage?[fieldKey] { + self.errorMessage = ruleErrorMessage + } self.isValid = valid + } //-------------------------------------------------- @@ -89,10 +98,12 @@ import Foundation title = try typeContainer.decodeIfPresent(String.self, forKey: .title) feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback) 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 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) @@ -111,8 +122,10 @@ import Foundation try container.encodeIfPresent(locked, forKey: .locked) try container.encodeIfPresent(showError, forKey: .showError) try container.encodeIfPresent(selected, forKey: .selected) + try container.encodeIfPresent(errorTextColor, forKey: .errorTextColor) try container.encodeIfPresent(errorMessage, forKey: .errorMessage) try container.encode(enabled, forKey: .enabled) + try container.encode(hideBorders, forKey: .hideBorders) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(groupName, forKey: .groupName) } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index 894fadd4..9d7c8927 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -244,14 +244,21 @@ import UIKit self.isValid = isValid if previousValidity && !isValid { - showError = true - observingTextFieldDelegate?.isInvalid?(textfield: self) + shouldShowError(true) } else if (!previousValidity && isValid) { - showError = false - observingTextFieldDelegate?.isValid?(textfield: self) + shouldShowError(false) + } + } + + func shouldShowError(_ showError: Bool) { + self.showError = showError + if showError { + observingTextFieldDelegate?.isValid?(textfield: self) + entryFieldContainer.originalUI() + } else { + observingTextFieldDelegate?.isInvalid?(textfield: self) } } - /// Executes on UITextField.textDidBeginEditingNotification @objc func startEditing() { isSelected = true @@ -268,10 +275,16 @@ import UIKit /// Executes on UITextField.textDidEndEditingNotification @objc func endInputing() { resignFirstResponder() - if isValid { - showError = false - entryFieldContainer.bottomBar?.backgroundColor = UIColor.mvmBlack.cgColor + + // Don't show error till user starts typing. + guard text?.count ?? 0 != 0 else { + return } + + if let isValid = (model as? TextEntryFieldModel)?.isValid { + self.isValid = isValid + } + shouldShowError(!isValid) } @objc public func dismissFieldInput(_ sender: Any?) { diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift index d47b9802..db5f3724 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryFieldModel.swift @@ -31,6 +31,7 @@ public var placeholder: String? public var enabledTextColor: Color = Color(uiColor: .mvmBlack) public var disabledTextColor: Color = Color(uiColor: .mvmCoolGray3) + public var textAlignment: NSTextAlignment = .left public var type: EntryType? //-------------------------------------------------- @@ -39,6 +40,7 @@ private enum CodingKeys: String, CodingKey { case placeholder + case textAlignment case enabledTextColor case disabledTextColor case type @@ -51,6 +53,7 @@ required public init(from decoder: Decoder) throws { try super.init(from: decoder) let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + placeholder = try typeContainer.decodeIfPresent(String.self, forKey: .placeholder) type = try typeContainer.decodeIfPresent(EntryType.self, forKey: .type) @@ -61,12 +64,17 @@ if let disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) { self.disabledTextColor = disabledTextColor } + + if let textAlignment = try typeContainer.decodeIfPresent(NSTextAlignment.self, forKey: .textAlignment) { + self.textAlignment = textAlignment + } } public 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) + try container.encodeIfPresent(textAlignment, forKey: .textAlignment) try container.encode(enabledTextColor, forKey: .enabledTextColor) try container.encode(disabledTextColor, forKey: .disabledTextColor) try container.encodeIfPresent(type, forKey: .type) diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextViewEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextViewEntryField.swift new file mode 100644 index 00000000..546b5c30 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextViewEntryField.swift @@ -0,0 +1,279 @@ +// +// TextViewEntryField.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 5/7/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + + +class TextViewEntryField: EntryField, UITextViewDelegate, ObservingTextFieldDelegate { + //-------------------------------------------------- + // MARK: - Outlets + //-------------------------------------------------- + + open private(set) var textView: TextView = { + let textView = TextView() + textView.setContentCompressionResistancePriority(.required, for: .vertical) + return textView + }() + + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + /// Validate on each entry in the textView. Default: true + public var validateEachCharacter: Bool = true + + private var observingForChange: Bool = false + + //-------------------------------------------------- + // MARK: - Computed Properties + //-------------------------------------------------- + + public var textViewEntryFieldModel: TextViewEntryFieldModel? { + return model as? TextViewEntryFieldModel + } + + public override var isEnabled: Bool { + get { return super.isEnabled } + set (enabled) { + super.isEnabled = enabled + + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + + self.textView.isEnabled = enabled + if self.textView.isShowingPlaceholder { + self.textView.textColor = self.textView.placeholderTextColor + } else { + self.textView.textColor = (enabled ? self.textViewEntryFieldModel?.enabledTextColor : self.textViewEntryFieldModel?.disabledTextColor)?.uiColor + } + } + } + } + + public override var showError: Bool { + get { return super.showError } + set (error) { + + if error { + textView.accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textView_error_message") ?? "", textView.text ?? "", entryFieldModel?.errorMessage ?? "") + } else { + textView.accessibilityValue = nil + } + + super.showError = error + } + } + + /// The text of this textView. + open override var text: String? { + get { return textView.text } + set { + textView.text = newValue + textViewEntryFieldModel?.text = newValue + } + } + + /// Placeholder access for the textView. + public var placeholder: String? { + get { return textViewEntryFieldModel?.placeholder } + set { + textView.placeholder = newValue ?? "" + textViewEntryFieldModel?.placeholder = newValue + textView.setPlaceholderIfAvailable() + } + } + + //-------------------------------------------------- + // MARK: - Constraint + //-------------------------------------------------- + + public var heightConstraint: NSLayoutConstraint? + private var topConstraint: NSLayoutConstraint? + private var leadingConstraint: NSLayoutConstraint? + private var trailingConstraint: NSLayoutConstraint? + private var bottomConstraint: NSLayoutConstraint? + + private func adjustMarginConstraints(constant: CGFloat) { + + topConstraint?.constant = constant + leadingConstraint?.constant = constant + trailingConstraint?.constant = constant + bottomConstraint?.constant = constant + } + + //-------------------------------------------------- + // MARK: - Delegate Properties + //-------------------------------------------------- + + /// The delegate and block for validation. Validates if the text that the user has entered. + public weak var observingTextViewDelegate: ObservingTextFieldDelegate? { + didSet { + if observingTextViewDelegate != nil && !observingForChange { + observingForChange = true + NotificationCenter.default.addObserver(self, selector: #selector(valueChanged), name: UITextView.textDidChangeNotification, object: textView) + NotificationCenter.default.addObserver(self, selector: #selector(endInputing), name: UITextView.textDidEndEditingNotification, object: textView) + NotificationCenter.default.addObserver(self, selector: #selector(startEditing), name: UITextView.textDidBeginEditingNotification, object: textView) + + } else if observingTextViewDelegate == nil && observingForChange { + observingForChange = false + NotificationCenter.default.removeObserver(self, name: UITextView.textDidChangeNotification, object: textView) + NotificationCenter.default.removeObserver(self, name: UITextView.textDidEndEditingNotification, object: textView) + NotificationCenter.default.removeObserver(self, name: UITextView.textDidBeginEditingNotification, object: textView) + } + } + } + + /// If you're using a ViewController, you must set this to it + public weak var uiTextViewDelegate: UITextViewDelegate? { + get { return textView.delegate } + set { textView.delegate = newValue } + } + + @objc public func setBothTextDelegates(to delegate: (UITextViewDelegate & ObservingTextFieldDelegate)?) { + observingTextViewDelegate = delegate + uiTextViewDelegate = delegate + } + + open func setupTextViewToolbar() { + let observingDelegate = observingTextViewDelegate ?? self + textView.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate, + action: #selector(observingDelegate.dismissFieldInput)) + } + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + + @objc open override func setupFieldContainerContent(_ container: UIView) { + + container.addSubview(textView) + + topConstraint = textView.topAnchor.constraint(equalTo: container.topAnchor, constant: Padding.Three) + leadingConstraint = textView.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: Padding.Three) + trailingConstraint = container.trailingAnchor.constraint(equalTo: textView.trailingAnchor, constant: Padding.Three) + bottomConstraint = container.bottomAnchor.constraint(equalTo: textView.bottomAnchor, constant: Padding.Three) + + topConstraint?.isActive = true + leadingConstraint?.isActive = true + trailingConstraint?.isActive = true + bottomConstraint?.isActive = true + + heightConstraint = textView.heightAnchor.constraint(equalToConstant: 0) + accessibilityElements = [titleLabel, textView, feedbackLabel] + } + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + textView.updateView(size) + } + + open override func reset() { + super.reset() + + textView.reset() + adjustMarginConstraints(constant: Padding.Three) + heightConstraint?.constant = 0 + heightConstraint?.isActive = false + } + + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + + /// Validates the text of the entry field. + @objc public func validateTextView() { + text = textView.text + if let isValid = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) { + self.isValid = isValid + } + } + + /// Executes on UITextView.textDidBeginEditingNotification + @objc func startEditing() { + isSelected = true + _ = textView.becomeFirstResponder() + } + + /// Executes on UITextView.textDidChangeNotification (each character entry) + @objc func valueChanged() { + guard validateEachCharacter else { return } + validateTextView() + } + + /// Executes on UITextView.textDidEndEditingNotification + @objc func endInputing() { + resignFirstResponder() + isSelected = false + showError = !isValid + } + + //-------------------------------------------------- + // 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? TextViewEntryFieldModel else { return } + + if let height = model.height { + heightConstraint?.constant = height + heightConstraint?.isActive = true + } + + text = model.text + uiTextViewDelegate = delegateObject?.uiTextViewDelegate + observingTextViewDelegate = delegateObject?.observingTextFieldDelegate + + if let accessibilityText = model.accessibilityText { + accessibilityLabel = accessibilityText + } + + textView.isEditable = model.editable + textView.textAlignment = model.textAlignment + textView.textColor = model.enabled ? model.enabledTextColor.uiColor : model.disabledTextColor.uiColor + textView.font = model.fontStyle.getFont() + textView.placeholder = model.placeholder ?? "" + textView.placeholderFontStyle = model.placeholderFontStyle + textView.placeholderTextColor = model.placeholderTextColor.uiColor + textView.setPlaceholderIfAvailable() + + switch model.type { + case .secure, .password: + textView.isSecureTextEntry = true + + case .number: + textView.keyboardType = .numberPad + + case .email: + textView.keyboardType = .emailAddress + + default: break + } + + /// No point in configuring if the TextView is Read-only. + if textView.isEditable { + FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) + setupTextViewToolbar() + + if isSelected { + DispatchQueue.main.async { + _ = self.textView.becomeFirstResponder() + } + } + } + + if model.hideBorders { + adjustMarginConstraints(constant: 0) + } + + if !model.enabled { + isEnabled = false + } + } +} diff --git a/MVMCoreUI/BaseClasses/TextViewModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextViewEntryFieldModel.swift similarity index 75% rename from MVMCoreUI/BaseClasses/TextViewModel.swift rename to MVMCoreUI/Atomic/Atoms/TextFields/TextViewEntryFieldModel.swift index d9505275..ce1173ae 100644 --- a/MVMCoreUI/BaseClasses/TextViewModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextViewEntryFieldModel.swift @@ -1,15 +1,15 @@ // -// TextViewModel.swift +// TextViewEntryFieldModel.swift // MVMCoreUI // -// Created by Kevin Christiano on 4/2/20. +// Created by Kevin Christiano on 5/7/20. // Copyright © 2020 Verizon Wireless. All rights reserved. // -import Foundation +import UIKit -open class TextViewModel: TextEntryFieldModel { +class TextViewEntryFieldModel: TextEntryFieldModel { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -19,26 +19,21 @@ open class TextViewModel: TextEntryFieldModel { } public var accessibilityText: String? - public var fontStyle: Styler.Font = Styler.Font.RegularBodySmall - public var textAlignment: NSTextAlignment = .left + public var fontStyle: Styler.Font = Styler.Font.RegularBodyLarge public var height: CGFloat? public var placeholderTextColor: Color = Color(uiColor: .mvmCoolGray3) public var placeholderFontStyle: Styler.Font = Styler.Font.RegularMicro - public var showsPlaceholder: Bool = false - public var hideBorders: Bool = false public var editable: Bool = true - + public var showsPlaceholder: Bool = false + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- private enum CodingKeys: String, CodingKey { - case text case accessibilityText case fontStyle - case textAlignment case height - case hideBorders case placeholderFontStyle case placeholderTextColor case editable @@ -60,22 +55,14 @@ open class TextViewModel: TextEntryFieldModel { self.placeholderTextColor = placeholderTextColor } - if let textAlignment = try typeContainer.decodeIfPresent(NSTextAlignment.self, forKey: .textAlignment) { - self.textAlignment = textAlignment - } - - if let hideBorders = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideBorders) { - self.hideBorders = hideBorders + if let fontStyle = try typeContainer.decodeIfPresent(Styler.Font.self, forKey: .fontStyle) { + self.fontStyle = fontStyle } if let editable = try typeContainer.decodeIfPresent(Bool.self, forKey: .editable) { self.editable = editable } - if let fontStyle = try typeContainer.decodeIfPresent(Styler.Font.self, forKey: .fontStyle) { - self.fontStyle = fontStyle - } - accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) height = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .height) } @@ -86,11 +73,8 @@ open class TextViewModel: TextEntryFieldModel { try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) try container.encodeIfPresent(height, forKey: .height) try container.encode(fontStyle, forKey: .fontStyle) - try container.encode(hideBorders, forKey: .hideBorders) - try container.encode(text, forKey: .text) + try container.encode(editable, forKey: .editable) try container.encode(placeholderFontStyle, forKey: .placeholderFontStyle) try container.encode(placeholderTextColor, forKey: .placeholderTextColor) - try container.encode(textAlignment, forKey: .textAlignment) - try container.encode(editable, forKey: .editable) } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/BarsIndicatorView.swift b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/BarsIndicatorView.swift index 691dbfa0..972ea7ca 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/BarsIndicatorView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/BarsIndicatorView.swift @@ -134,6 +134,7 @@ open class BarsIndicatorView: CarouselIndicator { public override func assessTouchOf(_ touchPoint_X: CGFloat) { currentIndex = barReferences.firstIndex { $0.0.frame.maxX >= touchPoint_X && $0.0.frame.minX <= touchPoint_X } ?? 0 + performAction() } open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { diff --git a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicator.swift b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicator.swift index d1f12d85..9380e8c0 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicator.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicator.swift @@ -48,13 +48,10 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol { previousIndex = currentIndex carouselIndicatorModel?.currentIndex = newIndex - if previousIndex != newIndex { - updateUI(previousIndex: previousIndex, - newIndex: newIndex, - totalCount: numberOfPages, - isAnimated: carouselIndicatorModel?.animated ?? true) - performAction() - } + updateUI(previousIndex: previousIndex, + newIndex: newIndex, + totalCount: numberOfPages, + isAnimated: carouselIndicatorModel?.animated ?? true) } } @@ -141,11 +138,13 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol { func incrementCurrentIndex() { currentIndex = (currentIndex + 1) % numberOfPages + performAction() } func decrementCurrentIndex() { let newIndex = currentIndex - 1 currentIndex = newIndex < 0 ? numberOfPages - 1 : newIndex + performAction() } /// Increments the currentIndex value. diff --git a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/NumericIndicatorView.swift b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/NumericIndicatorView.swift index 3585be05..04ea2fcd 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/NumericIndicatorView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/NumericIndicatorView.swift @@ -16,7 +16,7 @@ open class NumericIndicatorView: CarouselIndicator { /// Text to display the current count of total pages for viewing. open var pageCount: Label = { - let label = Label.commonLabelB2(true) + let label = Label.createLabelRegularBodySmall(true) label.isAccessibilityElement = false label.setContentCompressionResistancePriority(.required, for: .vertical) label.textAlignment = .center diff --git a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift index 5d4f68be..9d203ea9 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift @@ -13,7 +13,7 @@ //-------------------------------------------------- public let checkbox = Checkbox() - public let label = Label.commonLabelB2(true) + public let label = Label.createLabelRegularBodySmall(true) //-------------------------------------------------- // MARK: - Properties diff --git a/MVMCoreUI/Atomic/Atoms/Views/Line.swift b/MVMCoreUI/Atomic/Atoms/Views/Line.swift index 62550503..42043c8f 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Line.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Line.swift @@ -32,16 +32,16 @@ import UIKit switch style { case .standard: updateLineConstraints(constant: 1) - backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mfSilver() + backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmCoolGray3 case .thin: updateLineConstraints(constant: 1) - backgroundColor = lineModel?.backgroundColor?.uiColor ?? .black + backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack case .medium: updateLineConstraints(constant: 2) - backgroundColor = lineModel?.backgroundColor?.uiColor ?? .black + backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack case .heavy: updateLineConstraints(constant: 4) - backgroundColor = lineModel?.backgroundColor?.uiColor ?? .black + backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack case .none: updateLineConstraints(constant: 0) } @@ -97,6 +97,7 @@ import UIKit } extension Line: MVMCoreUIViewConstrainingProtocol { + open func needsToBeConstrained() -> Bool { return true } diff --git a/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift b/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift index a8d0ba9a..baa63ee8 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift @@ -11,7 +11,8 @@ import UIKit @objcMembers open class LoadImageView: View { public let loadingSpinner = MFLoadingSpinner(frame: .zero) public let imageView = MFTransparentGIFView(frame: .zero) - public var addSizeConstraintsForAspectRatio = false + public var addSizeConstraintsForAspectRatio = true + public var shouldNotifyDelegateOnUpdate = true var centerX: NSLayoutConstraint? var centerY: NSLayoutConstraint? var widthConstraint: NSLayoutConstraint? @@ -172,7 +173,6 @@ import UIKit } else { heightConstraint?.isActive = false heightConstraint = imageView.heightAnchor.constraint(equalToConstant: height) - heightConstraint?.priority = UILayoutPriority(rawValue: 900) } heightConstraint?.isActive = true } @@ -182,7 +182,6 @@ import UIKit widthConstraint.constant = width } else { widthConstraint = imageView.widthAnchor.constraint(equalToConstant: width) - widthConstraint?.priority = UILayoutPriority(rawValue: 900) } widthConstraint?.isActive = true } @@ -264,16 +263,15 @@ import UIKit } let finishedLoadingBlock: MVMCoreGetImageBlock = {[weak self] (image, data, isFallbackImage) in MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in - guard let loadingImageName = self?.currentImageName, loadingImageName == imageName else { - return - } - self?.isFallbackImage = isFallbackImage - self?.loadingSpinner.pause() - let layoutWillChange = self?.layoutWillChange(width: self?.currentImageWidth, height: self?.currentImageHeight, size: image?.size) ?? false - self?.addConstraints(width: width, height: height, size: image?.size) - self?.loadingSpinnerHeightConstraint?.constant = 0 + guard let self = self, + let loadingImageName = self.currentImageName, loadingImageName == imageName else { return } + self.isFallbackImage = isFallbackImage + self.loadingSpinner.pause() + let layoutWillChange = self.shouldNotifyDelegateOnUpdate ? self.layoutWillChange(width: self.currentImageWidth, height: self.currentImageHeight, size: image?.size) : false + self.addConstraints(width: width, height: height, size: image?.size) + self.loadingSpinnerHeightConstraint?.constant = 0 if layoutWillChange { - self?.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self!) + self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) } completionBlock(image,data,isFallbackImage) })} diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index a77b50f4..dbff52fe 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -52,7 +52,7 @@ import Foundation try? ModelRegistry.register(LabelAttributeActionModel.self) // TextView - MoleculeObjectMapping.shared()?.register(viewClass: TextView.self, viewModelClass: TextViewModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: TextViewEntryField.self, viewModelClass: TextViewEntryFieldModel.self) // Buttons MoleculeObjectMapping.shared()?.register(viewClass: PillButton.self, viewModelClass: ButtonModel.self) @@ -162,6 +162,7 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnInternationalData.self, viewModelClass: ListThreeColumnInternationalDataModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnDataUsage.self, viewModelClass: ListThreeColumnDataUsageModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: ListProgressBarThin.self, viewModelClass: ListProgressBarThinModel.self) // Designed Section Dividers MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) @@ -178,6 +179,7 @@ import Foundation // Designed Headers MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2NoButtonsBodyText.self, viewModelClass: HeadersH2NoButtonsBodyTextModel.self) MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2TinyButton.self, viewModelClass: HeadersH2TinyButtonModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2Buttons.self, viewModelClass: HeadersH2ButtonsModel.self) // Device Items MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexButtonMedium.self, viewModelClass: ListDeviceComplexButtonMediumModel.self) @@ -192,6 +194,7 @@ import Foundation try? ModelRegistry.register(RuleAnyValueChangedModel.self) try? ModelRegistry.register(RuleAllValueChangedModel.self) try? ModelRegistry.register(RuleEqualsModel.self) + try? ModelRegistry.register(RuleEqualsIgnoreCaseModel.self) try? ModelRegistry.register(RuleRegexModel.self) // Actions diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2Buttons.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2Buttons.swift new file mode 100644 index 00000000..57e62d24 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2Buttons.swift @@ -0,0 +1,59 @@ +// +// HeadersH2Buttons.swift +// MVMCoreUI +// +// Created by Lekshmi S on 10/03/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class HeadersH2Buttons: HeaderView { + //-------------------------------------------------- + // MARK: - Outlets + //-------------------------------------------------- + public let headlineBody = HeadlineBody(frame: .zero) + public let buttons = TwoButtonView(frame: .zero) + public let stack: Stack + + //------------------------------------------------------- + // MARK: - Initializers + //------------------------------------------------------- + public override init(frame: CGRect) { + stack = Stack.createStack(with: [headlineBody, buttons], spacing: PaddingDefaultVerticalSpacing3) + super.init(frame: frame) + } + + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + //------------------------------------------------------- + // MARK: - View Lifecycle + //------------------------------------------------------- + open override func setupView() { + super.setupView() + headlineBody.stylePageHeader() + addMolecule(stack) + stack.restack() + } + + //---------------------------------------------------- + // MARK: - Molecule + //------------------------------------------------------ + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) + guard let model = model as? HeadersH2ButtonsModel else { return } + headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + buttons.set(with: model.buttons, delegateObject, additionalData) + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 121 + } + + open override func reset() { + super.reset() + headlineBody.stylePageHeader() + } +} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2ButtonsModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2ButtonsModel.swift new file mode 100644 index 00000000..afc57f2e --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2ButtonsModel.swift @@ -0,0 +1,60 @@ +// +// HeadersH2ButtonsModel.swift +// MVMCoreUI +// +// Created by Lekshmi S on 10/03/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "headerH2Btns" + public var headlineBody: HeadlineBodyModel + public var buttons: TwoButtonViewModel + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + public init(headlineBody: HeadlineBodyModel, buttons: TwoButtonViewModel) { + self.headlineBody = headlineBody + self.buttons = buttons + super.init() + } + + public override func setDefaults() { + super.setDefaults() + topPadding = PaddingDefaultVerticalSpacing3 + bottomPadding = PaddingDefaultVerticalSpacing3 + } + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { + case moleculeName + case headlineBody + case buttons + } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) + buttons = try typeContainer.decode(TwoButtonViewModel.self, forKey: .buttons) + try super.init(from: decoder) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(headlineBody, forKey: .headlineBody) + try container.encode(buttons, forKey: .buttons) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2NoButtonsBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2NoButtonsBodyText.swift index 69bdbbba..8826a239 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2NoButtonsBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2NoButtonsBodyText.swift @@ -12,6 +12,7 @@ import Foundation //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- + let headlineBody = HeadlineBody(frame: .zero) //------------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2TinyButton.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2TinyButton.swift index 0991eec6..788a6a89 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2TinyButton.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/HeadersH2TinyButton.swift @@ -14,7 +14,19 @@ import Foundation //-------------------------------------------------- public let headlineBody = HeadlineBody(frame: .zero) public let button = PillButton(frame: .zero) - public var stack = Stack(frame: .zero) + public let stack: Stack + + //------------------------------------------------------- + // MARK: - Initializers + //------------------------------------------------------- + public override init(frame: CGRect) { + stack = Stack.createStack(with: [(view: headlineBody, model: StackItemModel(horizontalAlignment: .fill)), (view: button, model: StackItemModel(spacing: spacingBetwenHeadlineBodyAndButton, horizontalAlignment: .leading))], axis: .vertical) + super.init(frame: frame) + } + + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } //------------------------------------------------------ // MARK: - Constants @@ -26,7 +38,6 @@ import Foundation //------------------------------------------------------- open override func setupView() { super.setupView() - stack = Stack.createStack(with: [(view: headlineBody, model: StackItemModel(horizontalAlignment: .fill)), (view: button, model: StackItemModel(spacing: spacingBetwenHeadlineBodyAndButton, horizontalAlignment: .leading))], axis: .vertical) headlineBody.stylePageHeader() addMolecule(stack) stack.restack() diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift index c39bce65..e6e226cb 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonMedium.swift @@ -43,6 +43,7 @@ import Foundation // MARK: - MFViewProtocol open override func setupView() { super.setupView() + rightImageView.shouldNotifyDelegateOnUpdate = false addMolecule(stack) stack.restack() verticalStack.restack() diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmall.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmall.swift index 77a189c2..e8436620 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmall.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexButtonSmall.swift @@ -43,6 +43,7 @@ import Foundation // MARK: - MFViewProtocol open override func setupView() { super.setupView() + rightImageView.shouldNotifyDelegateOnUpdate = false addMolecule(stack) stack.restack() verticalStack.restack() diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift index f53da09c..573335c0 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkMedium.swift @@ -46,6 +46,7 @@ import Foundation //----------------------------------------------------- open override func setupView() { super.setupView() + rightImage.shouldNotifyDelegateOnUpdate = false addMolecule(stack) stack.restack() verticalStack.restack() diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmall.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmall.swift index 5ba8ac97..49173067 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmall.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/Device/ListDeviceComplexLinkSmall.swift @@ -46,6 +46,7 @@ import Foundation //----------------------------------------------------- open override func setupView() { super.setupView() + rightImage.shouldNotifyDelegateOnUpdate = false addMolecule(stack) stack.restack() verticalStack.restack() diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/FourColumn/ListFourColumnDataUsageListItem.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/FourColumn/ListFourColumnDataUsageListItem.swift index 2377a1f2..a42b6797 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/FourColumn/ListFourColumnDataUsageListItem.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/FourColumn/ListFourColumnDataUsageListItem.swift @@ -14,10 +14,10 @@ import Foundation // MARK: - Outlets //----------------------------------------------------- var stack: Stack - let label1 = Label.commonLabelB2(true) - let label2 = Label.commonLabelB2(true) - let label3 = Label.commonLabelB2(true) - let label4 = Label.commonLabelB2(true) + let label1 = Label.createLabelRegularBodySmall(true) + let label2 = Label.createLabelRegularBodySmall(true) + let label3 = Label.createLabelRegularBodySmall(true) + let label4 = Label.createLabelRegularBodySmall(true) let arrow = Arrow(frame: .zero) let arrowAndLabel2Stack: Stack @@ -69,9 +69,9 @@ import Foundation open override func reset() { super.reset() - label1.styleB2(true) - label2.styleB2(true) - label3.styleB2(true) - label4.styleB2(true) + label1.styleRegularBodySmall(true) + label2.styleRegularBodySmall(true) + label3.styleRegularBodySmall(true) + label4.styleRegularBodySmall(true) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift index 7031e239..db7decbd 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaret.swift @@ -6,7 +6,6 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // -import Foundation import UIKit @objcMembers open class ListLeftVariableIconWithRightCaret: TableViewCell { @@ -15,8 +14,8 @@ import UIKit // MARK: - Outlets //------------------------------------------------------- let leftImage = LoadImageView(pinnedEdges: .all) - let leftLabel = Label.commonLabelB2(true) - let rightLabel = Label.commonLabelB2(true) + let leftLabel = Label.createLabelRegularBodySmall(true) + let rightLabel = Label.createLabelRegularBodySmall(true) var stack: Stack //----------------------------------------------------- @@ -64,7 +63,7 @@ import UIKit open override func reset() { super.reset() - leftLabel.styleB2(true) - rightLabel.styleB2(true) + leftLabel.styleRegularBodySmall(true) + rightLabel.styleRegularBodySmall(true) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift index ee4900c5..688f457c 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift @@ -14,11 +14,13 @@ import UIKit // MARK: - Outlets //----------------------------------------------------- - let radioButton = RadioButton(frame: .zero) + let radioButton = RadioButton() let leftImage = LoadImageView(pinnedEdges: .all) let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink() var stack: Stack + private var observation: NSKeyValueObservation? = nil + //----------------------------------------------------- // MARK: - Initializers //----------------------------------------------------- @@ -46,6 +48,16 @@ import UIKit stack.restack() eyebrowHeadlineBodyLink.body.textColor = .mvmOrangeAA eyebrowHeadlineBodyLink.headline.styleBoldBodySmall(true) + radioButton.isAccessibilityElement = false + isAccessibilityElement = true + updateAccessibilityLabel() + accessibilityTraits = .button + accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") + updateAccessibilityLabel() + + observation = observe(\.radioButton.isSelected, options: [.new]) { [weak self] _, _ in + self?.updateAccessibilityLabel() + } } open override func reset() { @@ -64,6 +76,7 @@ import UIKit radioButton.set(with: model.radioButton, delegateObject, additionalData) leftImage.set(with: model.image, delegateObject, additionalData) eyebrowHeadlineBodyLink.set(with: model.eyebrowHeadlineBodyLink, delegateObject, additionalData) + updateAccessibilityLabel() } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { @@ -71,6 +84,34 @@ import UIKit } public override func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - radioButton.tapAction() + radioButton.tapAction() + } + + func updateAccessibilityLabel() { + + var message = MVMCoreUIUtility.hardcodedString(withKey: "radio_button") ?? "" + + radioButton.updateAccessibilityLabel() + if let radioButtonLabel = radioButton.accessibilityLabel { + message += radioButtonLabel + ", " + } + + if let leftImageLabel = leftImage.accessibilityLabel { + message += leftImageLabel + ", " + } + + if let eyebrowLabel = eyebrowHeadlineBodyLink.eyebrow.text { + message += eyebrowLabel + ", " + } + + if let headlineLabel = eyebrowHeadlineBodyLink.headline.text { + message += headlineLabel + ", " + } + + if let bodyLabel = eyebrowHeadlineBodyLink.body.text { + message += bodyLabel + } + + accessibilityLabel = message } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethodModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethodModel.swift index 5ea28778..f455882e 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethodModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethodModel.swift @@ -9,11 +9,19 @@ import Foundation public class ListLeftVariableRadioButtonAndPaymentMethodModel: ListItemModel, MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "listLVRBImg" public var radioButton: RadioButtonModel public var image: ImageViewModel public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + public init(radioButton: RadioButtonModel, image: ImageViewModel, eyebrowHeadlineBodyLink:EyebrowHeadlineBodyLinkModel) { self.radioButton = radioButton self.image = image @@ -21,6 +29,10 @@ public class ListLeftVariableRadioButtonAndPaymentMethodModel: ListItemModel, Mo super.init() } + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + public override func setDefaults() { super.setDefaults() if image.width == nil, image.height == nil { @@ -29,6 +41,10 @@ public class ListLeftVariableRadioButtonAndPaymentMethodModel: ListItemModel, Mo } } + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { case moleculeName case radioButton @@ -36,6 +52,10 @@ public class ListLeftVariableRadioButtonAndPaymentMethodModel: ListItemModel, Mo case eyebrowHeadlineBodyLink } + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) radioButton = try typeContainer.decode(RadioButtonModel.self, forKey: .radioButton) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonBodyText.swift index 9b45eec7..d89604f9 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonBodyText.swift @@ -14,10 +14,12 @@ open class ListLeftVariableRadioButtonBodyText: TableViewCell { // MARK: - Outlets //----------------------------------------------------- - let radioButton = RadioButton(frame: .zero) + let radioButton = RadioButton() let headlineBody = HeadlineBody() var stack: Stack + private var observation: NSKeyValueObservation? = nil + //----------------------------------------------------- // MARK: - Initializers //----------------------------------------------------- @@ -42,6 +44,15 @@ open class ListLeftVariableRadioButtonBodyText: TableViewCell { addMolecule(stack) stack.restack() + isAccessibilityElement = true + radioButton.isAccessibilityElement = false + accessibilityTraits = .button + accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") + updateAccessibilityLabel() + + observation = observe(\.radioButton.isSelected, options: [.new]) { [weak self] _, _ in + self?.updateAccessibilityLabel() + } } //---------------------------------------------------- @@ -55,6 +66,7 @@ open class ListLeftVariableRadioButtonBodyText: TableViewCell { radioButton.set(with: model.radioButton, delegateObject, additionalData) headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + updateAccessibilityLabel() } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { @@ -64,4 +76,24 @@ open class ListLeftVariableRadioButtonBodyText: TableViewCell { public override func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { radioButton.tapAction() } + + func updateAccessibilityLabel() { + + var message = MVMCoreUIUtility.hardcodedString(withKey: "radio_button") ?? "" + + radioButton.updateAccessibilityLabel() + if let radioButtonLabel = radioButton.accessibilityLabel { + message += radioButtonLabel + ", " + } + + if let headlineLabel = headlineBody.headlineLabel.text { + message += headlineLabel + ", " + } + + if let messageLabel = headlineBody.messageLabel.text { + message += messageLabel + } + + accessibilityLabel = message + } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift new file mode 100644 index 00000000..072be6bb --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThin.swift @@ -0,0 +1,99 @@ +// +// ListProgressBarThin.swift +// MVMCoreUI +// +// Created by Lekshmi S on 12/05/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +@objcMembers open class ListProgressBarThin: TableViewCell { + //-------------------------------------------------- + // MARK: - Outlets + //-------------------------------------------------- + public let progressBar = ProgressBar() + public let leftHeadline = Label.commonLabelB1(true) + public let leftBody = Label.commonLabelB2(true) + public let rightBar = Line() + public let rightLabel = Label.commonLabelB2(true) + private let barStackItem: StackItem + private let rightLabelStackItem: StackItem + public var labelStack: Stack + public var horizontalStack: Stack + public var stack: Stack + + //------------------------------------------------------ + // MARK: - Initializers + //------------------------------------------------------ + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + //vertical stack with leftHeadline, leftBody + labelStack = Stack.createStack(with: [leftHeadline, leftBody], axis: .vertical, spacing: 2) + + //horizontal stack with leftHeadline, leftBody, bar, rightLabel + barStackItem = StackItem(andContain: rightBar) + rightLabelStackItem = StackItem(andContain: rightLabel) + let horizontalStackItems = [StackItem(andContain: labelStack), barStackItem, rightLabelStackItem] + let horizontalStackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading), StackItemModel(horizontalAlignment: .fill), StackItemModel(spacing: 5, horizontalAlignment: .fill)], + axis: .horizontal) + horizontalStack = Stack(with: horizontalStackModel, stackItems: horizontalStackItems) + + //stack with all components + stack = Stack.createStack(with: [horizontalStack, progressBar], axis: .vertical, spacing: PaddingDefaultVerticalSpacing3) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + open override func alignAccessoryToHero() -> CGPoint? { + // Ensures that the right items are centered with the arrow. + let heroCenter = super.alignAccessoryToHero() + if let heroCenter = heroCenter { + let convertedPoint = horizontalStack.convert(heroCenter, from: self) + barStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - horizontalStack.bounds.midY + rightLabelStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - horizontalStack.bounds.midY + } + return heroCenter + } + + //------------------------------------------------------- + // MARK: - View Lifecycle + //------------------------------------------------------- + open override func setupView() { + super.setupView() + rightBar.widthAnchor.constraint(equalToConstant: 20).isActive = true + rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) + rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal) + rightLabel.numberOfLines = 1 + addMolecule(stack) + stack.restack() + horizontalStack.restack() + labelStack.restack() + } + + //------------------------------------------------------ + // MARK: - Molecule + //------------------------------------------------------ + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) + guard let model = model as? ListProgressBarThinModel else { return } + labelStack.updateContainedMolecules(with: [model.leftHeadline, + model.leftBody], delegateObject, additionalData) + progressBar.set(with: model.progressBar, delegateObject, additionalData) + rightBar.set(with: model.rightBar, delegateObject, additionalData) + rightLabel.set(with: model.rightLabel, delegateObject, additionalData) + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + return 120 + } + + open override func reset() { + super.reset() + leftHeadline.styleB1(true) + leftBody.styleB2(true) + rightLabel.styleB2(true) + rightBar.setStyle(.medium) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThinModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThinModel.swift new file mode 100644 index 00000000..acd8e013 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/ListProgressBarThinModel.swift @@ -0,0 +1,65 @@ +// +// ListProgressBarThinModel.swift +// MVMCoreUI +// +// Created by Lekshmi S on 12/05/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation +public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol { + public static var identifier = "listPrgBarThin" + public var progressBar: ProgressBarModel + public var leftHeadline: LabelModel + public var leftBody: LabelModel? + public var rightBar: LineModel + public var rightLabel: LabelModel + + public init(progressBar: ProgressBarModel, leftHeadline: LabelModel, leftBody: LabelModel? = nil, rightBar: LineModel, rightLabel: LabelModel) { + self.progressBar = progressBar + self.leftHeadline = leftHeadline + self.leftBody = leftBody + self.rightBar = rightBar + self.rightLabel = rightLabel + super.init() + } + + override public func setDefaults() { + super.setDefaults() + rightBar.type = .medium + if rightBar.backgroundColor == nil { + rightBar.backgroundColor = Color(uiColor: .gray) + } + leftHeadline.hero = 0 + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case progressBar + case leftHeadline + case leftBody + case rightBar + case rightLabel + } + + public required init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + progressBar = try typeContainer.decode(ProgressBarModel.self, forKey:.progressBar) + leftHeadline = try typeContainer.decode(LabelModel.self, forKey: .leftHeadline) + leftBody = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .leftBody) + rightBar = try typeContainer.decode(LineModel.self, forKey: .rightBar) + rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) + try super.init(from: decoder) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(progressBar, forKey: .progressBar) + try container.encode(leftHeadline, forKey: .leftHeadline) + try container.encodeIfPresent(leftBody, forKey: .leftBody) + try container.encode(rightBar, forKey: .rightBar) + try container.encode(rightLabel, forKey: .rightLabel) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift index 599d0cdf..2291c080 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/OneColumn/ListOneColumnFullWidthTextAllTextAndLinks.swift @@ -15,10 +15,10 @@ import Foundation //----------------------------------------------------- var stack: Stack - let eyebrow = Label.commonLabelB3(true) - let headline = Label.commonLabelH3(true) - let subHeadline = Label.commonLabelB1(true) - let body = Label.commonLabelB2(true) + let eyebrow = Label.createLabelRegularMicro(true) + let headline = Label.createLabelBoldTitleMedium(true) + let subHeadline = Label.createLabelBoldBodySmall(true) + let body = Label.createLabelRegularBodySmall(true) let link = Link() //----------------------------------------------------- @@ -62,9 +62,9 @@ import Foundation open override func reset() { super.reset() - eyebrow.styleB3(true) - headline.styleH3(true) - subHeadline.styleB1(true) - body.styleB2(true) + eyebrow.styleRegularMicro(true) + headline.styleBoldTitleMedium(true) + subHeadline.styleBoldBodySmall(true) + body.styleRegularBodySmall(true) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift index f7c65dbe..40579a09 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRVWheel.swift @@ -9,8 +9,8 @@ import Foundation @objcMembers open class ListRVWheel: TableViewCell { let wheel = Wheel(frame: .zero) - let leftLabel = Label.commonLabelB1(true) - let rightLabel = Label.commonLabelB2(true) + let leftLabel = Label.createLabelBoldBodySmall(true) + let rightLabel = Label.createLabelRegularBodySmall(true) var stack: Stack //----------------------------------------------------- @@ -54,8 +54,8 @@ import Foundation //------------------------------------------------- open override func reset() { super.reset() - leftLabel.styleB1(true) - rightLabel.styleB2(true) + leftLabel.styleBoldBodySmall(true) + rightLabel.styleRegularBodySmall(true) } public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinksModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinksModel.swift index 41d4ec72..de9e5d63 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinksModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableButtonAllTextAndLinksModel.swift @@ -22,7 +22,7 @@ public class ListRightVariableButtonAllTextAndLinksModel: ListItemModel, Molecul override public func setDefaults() { super.setDefaults() self.button.size = .tiny - self.button.style = ButtonStyle.secondary + self.button.style = .secondary } private enum CodingKeys: String, CodingKey { diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift index 505f9c48..ce73c082 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePayments.swift @@ -13,7 +13,7 @@ import Foundation //----------------------------------------------------- // MARK: - Outlets //------------------------------------------------------- - let leftLabel = Label.commonLabelB1(true) + let leftLabel = Label.createLabelBoldBodySmall(true) let rightImage = LoadImageView(pinnedEdges: .all) var stack: Stack @@ -57,6 +57,6 @@ import Foundation open override func reset() { super.reset() - leftLabel.styleB1(true) + leftLabel.styleBoldBodySmall(true) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift index 7a74de6e..ab135eb6 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeAllTextAndLinks.swift @@ -15,7 +15,7 @@ import Foundation //----------------------------------------------------- public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero) public let arrow = Arrow(frame: .zero) - public let rightLabel = Label.commonLabelB2(true) + public let rightLabel = Label.createLabelRegularBodySmall(true) private let stack: Stack private let arrowStackItem: StackItem private let rightLabelStackItem: StackItem diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift index 2b87294a..63e90d34 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariablePriceChangeBodyText.swift @@ -15,7 +15,7 @@ import Foundation private let stack: Stack public let headlineBody = HeadlineBody(frame: .zero) public let arrow = Arrow(frame: .zero) - public let rightLabel = Label.commonLabelB2(true) + public let rightLabel = Label.createLabelRegularBodySmall(true) let arrowAndRightLabelStack: Stack diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift index abef078a..bb6ebd9e 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableTotalData.swift @@ -14,8 +14,8 @@ import Foundation // MARK: - Outlets //----------------------------------------------------- public var stack: Stack - public let leftLabel = Label.commonLabelB1(true) - public let rightLabel = Label.commonLabelB2(true) + public let leftLabel = Label.createLabelBoldBodySmall(true) + public let rightLabel = Label.createLabelRegularBodySmall(true) public let bar = Line() //----------------------------------------------------- @@ -61,8 +61,8 @@ import Foundation open override func reset() { super.reset() - leftLabel.styleB1(true) - rightLabel.styleB2(true) + leftLabel.styleBoldBodySmall(true) + rightLabel.styleRegularBodySmall(true) bar.setStyle(.heavy) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnCompareChanges.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnCompareChanges.swift index c007b8c7..e9a78f1b 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnCompareChanges.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnCompareChanges.swift @@ -13,15 +13,15 @@ import Foundation //------------------------------------------------------- // MARK: - Outlets //------------------------------------------------------- - let leftHeadline1 = Label.commonLabelB1(true) - let leftHeadline2 = Label.commonLabelB1(true) - let leftHeadline3 = Label.commonLabelB1(true) - let leftBody = Label.commonLabelB2(true) + let leftHeadline1 = Label.createLabelBoldBodySmall(true) + let leftHeadline2 = Label.createLabelBoldBodySmall(true) + let leftHeadline3 = Label.createLabelBoldBodySmall(true) + let leftBody = Label.createLabelRegularBodySmall(true) let leftLink = Link() - let rightHeadline1 = Label.commonLabelB1(true) - let rightHeadline2 = Label.commonLabelB1(true) - let rightHeadline3 = Label.commonLabelB1(true) - let rightBody = Label.commonLabelB2(true) + let rightHeadline1 = Label.createLabelBoldBodySmall(true) + let rightHeadline2 = Label.createLabelBoldBodySmall(true) + let rightHeadline3 = Label.createLabelBoldBodySmall(true) + let rightBody = Label.createLabelRegularBodySmall(true) let rightLink = Link() let containingStack: Stack @@ -97,14 +97,14 @@ import Foundation open override func reset() { super.reset() - leftHeadline1.styleB1(true) - leftHeadline2.styleB1(true) - leftHeadline3.styleB1(true) - leftBody.styleB2(true) - rightHeadline1.styleB1(true) - rightHeadline2.styleB1(true) - rightHeadline3.styleB1(true) - rightBody.styleB2(true) + leftHeadline1.styleBoldBodySmall(true) + leftHeadline2.styleBoldBodySmall(true) + leftHeadline3.styleBoldBodySmall(true) + leftBody.styleRegularBodySmall(true) + rightHeadline1.styleBoldBodySmall(true) + rightHeadline2.styleBoldBodySmall(true) + rightHeadline3.styleBoldBodySmall(true) + rightBody.styleRegularBodySmall(true) } public override class func estimatedHeight(with molecule: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnPriceDescription.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnPriceDescription.swift index 9f4f60b2..ecae14e8 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnPriceDescription.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnPriceDescription.swift @@ -13,10 +13,10 @@ import Foundation //----------------------------------------------------- // MARK: - Outlets //------------------------------------------------------- - public let leftHeadline = Label.commonLabelB1(true) - public let leftBody = Label.commonLabelB2(true) - public let rightLabel = Label.commonLabelB2(true) - public let rightSubLabel = Label.commonLabelB2(true) + public let leftHeadline = Label.createLabelBoldBodySmall(true) + public let leftBody = Label.createLabelRegularBodySmall(true) + public let rightLabel = Label.createLabelRegularBodySmall(true) + public let rightSubLabel = Label.createLabelRegularBodySmall(true) public let view = MVMCoreUICommonViewsUtility.commonView() public let leftVerticalStack: UIStackView @@ -86,9 +86,9 @@ import Foundation super.reset() leftVerticalStack.reset() rightVerticalStack.reset() - leftHeadline.styleB1(true) - leftBody.styleB2(true) - rightLabel.styleB2(true) - rightSubLabel.styleB2(true) + leftHeadline.styleBoldBodySmall(true) + leftBody.styleRegularBodySmall(true) + rightLabel.styleRegularBodySmall(true) + rightSubLabel.styleRegularBodySmall(true) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnPriceDetails.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnPriceDetails.swift index 43836cf0..3fbac0f3 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnPriceDetails.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnPriceDetails.swift @@ -10,8 +10,8 @@ import UIKit @objcMembers open class ListTwoColumnPriceDetails: TableViewCell { - let leftLabel = Label.commonLabelB2(true) - let rightLabel = Label.commonLabelB2(true) + let leftLabel = Label.createLabelRegularBodySmall(true) + let rightLabel = Label.createLabelRegularBodySmall(true) let view = MVMCoreUICommonViewsUtility.commonView() // MARK: - MFViewProtocol @@ -44,8 +44,8 @@ import UIKit super.reset() leftLabel.reset() rightLabel.reset() - leftLabel.styleB2(true) - rightLabel.styleB2(true) + leftLabel.styleRegularBodySmall(true) + rightLabel.styleRegularBodySmall(true) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsection.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsection.swift index c1583583..18529ebe 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsection.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnFullWidthTextDividerSubsection.swift @@ -13,8 +13,8 @@ import Foundation // MARK: - Outlets //----------------------------------------------------- public var stack: Stack - public let headline = Label.commonLabelB1(true) - public let body = Label.commonLabelB2(true) + public let headline = Label.createLabelBoldBodySmall(true) + public let body = Label.createLabelRegularBodySmall(true) // MARK: - Initializers public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { @@ -50,7 +50,7 @@ import Foundation open override func reset() { super.reset() - headline.styleB1(true) - body.styleB2(true) + headline.styleBoldBodySmall(true) + body.styleRegularBodySmall(true) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShort.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShort.swift index ec65967d..3198a72d 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShort.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerShort.swift @@ -13,8 +13,8 @@ import Foundation // MARK: - Outlets //----------------------------------------------------- public var stack: Stack - public let headline = Label.commonLabelH3(true) - public let body = Label.commonLabelB2(true) + public let headline = Label.createLabelBoldTitleMedium(true) + public let body = Label.createLabelRegularBodySmall(true) // MARK: - Initializers public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { @@ -50,7 +50,7 @@ import Foundation open override func reset() { super.reset() - headline.styleH3(true) - body.styleB2(true) + headline.styleBoldTitleMedium(true) + body.styleRegularBodySmall(true) } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTall.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTall.swift index 1f2bcd6f..d725ff61 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTall.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/OneColumn/ListOneColumnTextWithWhitespaceDividerTall.swift @@ -13,8 +13,8 @@ import Foundation // MARK: - Outlets //----------------------------------------------------- public var stack: Stack - public let headline = Label.commonLabelH3(true) - public let body = Label.commonLabelB2(true) + public let headline = Label.createLabelBoldTitleMedium(true) + public let body = Label.createLabelRegularBodySmall(true) // MARK: - Initializers public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { @@ -50,7 +50,7 @@ import Foundation open override func reset() { super.reset() - headline.styleH3(true) - body.styleB2(true) + headline.styleBoldTitleMedium(true) + body.styleRegularBodySmall(true) } } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift index 35f3ac29..ff770da3 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/ImageHeadlineBody.swift @@ -18,7 +18,7 @@ import UIKit open override func setupView() { super.setupView() - headlineBody.headlineLabel.styleB1(true) + headlineBody.headlineLabel.styleBoldBodySmall(true) headlineBody.spaceBetweenLabelsConstant = 0 imageView.addSizeConstraintsForAspectRatio = true @@ -43,7 +43,7 @@ import UIKit open override func reset() { super.reset() headlineBody.reset() - headlineBody.headlineLabel.styleB1(true) + headlineBody.headlineLabel.styleBoldBodySmall(true) headlineBody.spaceBetweenLabelsConstant = 0 imageView.reset() } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift index 285c429c..31420e56 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -9,11 +9,24 @@ import UIKit @objcMembers open class TwoButtonView: View, MVMCoreUIViewConstrainingProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + open var primaryButton: PillButton = PillButton() open var secondaryButton: PillButton = PillButton() private var stack = UIStackView() + + //-------------------------------------------------- + // MARK: - Constraints + //-------------------------------------------------- + private var equalWidthConstraint: NSLayoutConstraint? - + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + public init() { super.init(frame: .zero) } @@ -26,16 +39,21 @@ import UIKit super.init(frame: frame) } - public func setDefault() { + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + + public func setDefaultAppearance() { + primaryButton.stylePrimary() secondaryButton.styleSecondary() } - // MARK: - MVMCoreViewProtocol open override func updateView(_ size: CGFloat) { super.updateView(size) - self.primaryButton.updateView(size) - self.secondaryButton.updateView(size) + + primaryButton.updateView(size) + secondaryButton.updateView(size) } open override func setupView() { @@ -52,58 +70,70 @@ import UIKit equalWidthConstraint?.isActive = true } + //-------------------------------------------------- // MARK: - Stack Manipulation + //-------------------------------------------------- + public func showPrimaryButton() { + if !stack.arrangedSubviews.contains(primaryButton) { stack.addArrangedSubview(primaryButton) primaryButton.isHidden = false } + if secondaryButton.superview != nil { equalWidthConstraint?.isActive = true } } public func showSecondaryButton() { + if !stack.arrangedSubviews.contains(secondaryButton) { stack.insertArrangedSubview(secondaryButton, at: 0) secondaryButton.isHidden = false } + if primaryButton.superview != nil { equalWidthConstraint?.isActive = true } } public func hidePrimaryButton() { + if primaryButton.superview != nil { stack.removeArrangedSubview(primaryButton) primaryButton.isHidden = true } + equalWidthConstraint?.isActive = false } public func hideSecondaryButton() { + if secondaryButton.superview != nil { stack.removeArrangedSubview(secondaryButton) secondaryButton.isHidden = true } + equalWidthConstraint?.isActive = false } + //-------------------------------------------------- // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + open override func reset() { super.reset() - setDefault() - } - - // MARK: - MVMCoreUIViewConstrainingProtocol - open func horizontalAlignment() -> UIStackView.Alignment { - return .center + + setDefaultAppearance() } - // MARK: - MoleculeViewProtocol public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + guard let model = model as? TwoButtonViewModel, - let buttonModel = model.primaryButton ?? model.secondaryButton else { return 0 } + let buttonModel = model.primaryButton ?? model.secondaryButton + else { return 0 } + return PillButton.estimatedHeight(with: buttonModel, delegateObject) } @@ -118,6 +148,7 @@ import UIKit } else { hideSecondaryButton() } + if let primaryModel = model.primaryButton { showPrimaryButton() primaryButton.set(with: primaryModel, delegateObject, additionalData) @@ -125,4 +156,11 @@ import UIKit hidePrimaryButton() } } + //-------------------------------------------------- + // MARK: - MVMCoreUIViewConstrainingProtocol + //-------------------------------------------------- + + open func horizontalAlignment() -> UIStackView.Alignment { + return .center + } } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift index 057203e9..d4da0ba4 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonViewModel.swift @@ -8,35 +8,54 @@ import UIKit + public class TwoButtonViewModel: MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "twoButtonView" public var backgroundColor: Color? public var primaryButton: ButtonModel? public var secondaryButton: ButtonModel? + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { case moleculeName case backgroundColor case primaryButton case secondaryButton } - + + //-------------------------------------------------- + // MARK: - Initialzer + //-------------------------------------------------- + public init(_ primaryButton: ButtonModel?, _ secondaryButton: ButtonModel?) { self.primaryButton = primaryButton self.secondaryButton = secondaryButton } + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) primaryButton = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .primaryButton) + if primaryButton?.style == nil { + primaryButton?.style = .primary + } secondaryButton = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .secondaryButton) - // Default value if secondaryButton?.style == nil { secondaryButton?.style = .secondary } } - + public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) diff --git a/MVMCoreUI/Atomic/Molecules/Items/MoleculeListItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/MoleculeListItemModel.swift index 1384ee88..bee9d612 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/MoleculeListItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/MoleculeListItemModel.swift @@ -9,21 +9,39 @@ import Foundation import MVMCore + @objcMembers public class MoleculeListItemModel: ListItemModel, MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public class var identifier: String { return "listItem" } + public var molecule: MoleculeModelProtocol + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { case moleculeName case molecule } + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + public init(with moleculeModel: MoleculeModelProtocol) { molecule = moleculeModel super.init() } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) @@ -38,4 +56,3 @@ import MVMCore try container.encodeModel(molecule, forKey: .molecule) } } - diff --git a/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift b/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift index 0c9dec3b..6e1f2965 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/MoleculeTableViewCell.swift @@ -10,8 +10,9 @@ import UIKit @objcMembers open class MoleculeTableViewCell: TableViewCell { - + //-------------------------------------------------- // MARK: - MoleculeViewProtocol + //-------------------------------------------------- public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImage.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImage.swift index 5dd6c722..ab0924b2 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImage.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/ActionDetailWithImage.swift @@ -92,8 +92,8 @@ import UIKit private func setDefaultState() { - headlineBodyButton.headlineBody.headlineLabel.font = MFStyler.fontH3() - headlineBodyButton.headlineBody.messageLabel.font = MFStyler.fontB3() + headlineBodyButton.headlineBody.headlineLabel.font = MFStyler.fontBoldTitleMedium() + headlineBodyButton.headlineBody.messageLabel.font = MFStyler.fontRegularMicro() imageLoader.imageView.contentMode = .scaleAspectFit imageLoader.addSizeConstraintsForAspectRatio = true buttonHeaderPadding = PaddingTwo diff --git a/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift b/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift index 7eb3282b..5751fbc2 100644 --- a/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift +++ b/MVMCoreUI/Atomic/Molecules/LeftRightViews/CornerLabels.swift @@ -10,10 +10,10 @@ import UIKit @objcMembers public class CornerLabels: View { var middleView: UIView? - let topLeftLabel = Label.commonLabelB1(true) - let topRightLabel = Label.commonLabelB1(true) - let bottomLeftLabel = Label.commonLabelB3(true) - let bottomRightLabel = Label.commonLabelB3(true) + let topLeftLabel = Label.createLabelBoldBodySmall(true) + let topRightLabel = Label.createLabelBoldBodySmall(true) + let bottomLeftLabel = Label.createLabelRegularMicro(true) + let bottomRightLabel = Label.createLabelRegularMicro(true) let topLabelsView = MVMCoreUICommonViewsUtility.commonView() let bottomLabelsView = MVMCoreUICommonViewsUtility.commonView() @@ -151,10 +151,10 @@ import UIKit } func styleDefault() { - topLeftLabel.styleB1(true) - topRightLabel.styleB1(true) - bottomLeftLabel.styleB3(true) - bottomRightLabel.styleB3(true) + topLeftLabel.styleBoldBodySmall(true) + topRightLabel.styleBoldBodySmall(true) + bottomLeftLabel.styleRegularMicro(true) + bottomRightLabel.styleRegularMicro(true) } public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift index f6fd4fcf..040b368c 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/BGImageHeadlineBodyButtonModel.swift @@ -6,7 +6,6 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // -import Foundation import UIKit public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtocol { diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift index dd04140b..9ad26015 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLink.swift @@ -14,9 +14,9 @@ import UIKit //-------------------------------------------------- public let stack = Stack(frame: .zero) - public let eyebrow = Label.commonLabelB3(true) - public let headline = Label.commonLabelB1(true) - public let body = Label.commonLabelB2(true) + public let eyebrow = Label.createLabelRegularMicro(true) + public let headline = Label.createLabelBoldBodySmall(true) + public let body = Label.createLabelRegularBodySmall(true) public let link = Link() var castModel: EyebrowHeadlineBodyLinkModel? { @@ -48,9 +48,9 @@ import UIKit open override func reset() { super.reset() stack.reset() - eyebrow.styleB3(true) - headline.styleB1(true) - body.styleB2(true) + eyebrow.styleRegularMicro(true) + headline.styleBoldBodySmall(true) + body.styleRegularBodySmall(true) } //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift index b36525f9..4e9b97dd 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBody.swift @@ -10,8 +10,8 @@ import UIKit open class HeadlineBody: View { - let headlineLabel = Label.commonLabelH2(true) - let messageLabel = Label.commonLabelB2(true) + let headlineLabel = Label.createLabelBoldTitleLarge(true) + let messageLabel = Label.createLabelRegularBodySmall(true) var spaceBetweenLabelsConstant = PaddingOne var spaceBetweenLabels: NSLayoutConstraint? var leftConstraintTitle: NSLayoutConstraint? @@ -39,26 +39,26 @@ open class HeadlineBody: View { } func styleLandingPageHeader() { - headlineLabel.styleH1(true) - messageLabel.styleB2(true) + headlineLabel.styleTitle2XLarge(true) + messageLabel.styleRegularBodySmall(true) spaceBetweenLabelsConstant = PaddingTwo } func stylePageHeader() { - headlineLabel.styleH2(true) - messageLabel.styleB2(true) + headlineLabel.styleBoldTitleLarge(true) + messageLabel.styleRegularBodySmall(true) spaceBetweenLabelsConstant = PaddingOne } func styleListItem() { - headlineLabel.styleB1(true) - messageLabel.styleB2(true) + headlineLabel.styleBoldBodySmall(true) + messageLabel.styleRegularBodySmall(true) spaceBetweenLabelsConstant = 0 } func styleListItemDivider() { - headlineLabel.styleH3(true) - messageLabel.styleB2(true) + headlineLabel.styleBoldTitleMedium(true) + messageLabel.styleRegularBodySmall(true) spaceBetweenLabelsConstant = 0 } diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift index 35522146..c1c3a709 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/HeadlineBodyButton.swift @@ -82,8 +82,8 @@ import UIKit private func defaultState() { - headlineBody.headlineLabel.font = MFStyler.fontH3() - headlineBody.messageLabel.font = MFStyler.fontB3() + headlineBody.headlineLabel.font = MFStyler.fontBoldTitleMedium() + headlineBody.messageLabel.font = MFStyler.fontRegularMicro() button.styleSecondary() button.isHidden = false buttonHeadlinePadding = PaddingTwo diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift index c887e838..8630e607 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift @@ -10,7 +10,7 @@ import UIKit // This class is only temporarily necessary. Eventually we will have initWithModel instad of just init for moleculeviews, which will remove this need. open class StringAndMoleculeStack: MoleculeStackView { - override open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + override open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let model = model as? StackModelProtocol, let molcules = model.molecules as? [MoleculeStackItemModel] else { return } for stackItemModel in molcules { diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift index a7c9e20d..30a82134 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeView.swift @@ -9,7 +9,7 @@ import Foundation open class StringAndMoleculeView: View { - var label = Label.commonLabelB2(true) + var label = Label.createLabelRegularBodySmall(true) var molecule: MoleculeViewProtocol var leftWidthConstraint: NSLayoutConstraint? diff --git a/MVMCoreUI/Atomic/Organisms/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel.swift index 5fd0df36..4cf65f1b 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel.swift @@ -26,10 +26,8 @@ open class Carousel: View { /// The index of the page, does not include dummy cells. public var pageIndex: Int { - get { - return loop ? currentIndex - 2 : currentIndex - } - set(newIndex) { + get { return loop ? currentIndex - 2 : currentIndex } + set (newIndex) { currentIndex = loop ? newIndex + 2 : newIndex } } @@ -90,6 +88,7 @@ open class Carousel: View { } } + //-------------------------------------------------- // MARK: - MVMCoreViewProtocol //-------------------------------------------------- @@ -194,7 +193,7 @@ open class Carousel: View { pagingView = MoleculeObjectMapping.shared()?.createMolecule(molecule, delegateObject: delegateObject) as? (UIView & CarouselPageControlProtocol) } - addPaging(view: pagingView , position: (CGFloat(molecule?.position ?? 20))) + addPaging(view: pagingView, position: (CGFloat(molecule?.position ?? 20))) } /// Registers the cells with the collection view @@ -213,9 +212,7 @@ open class Carousel: View { /// Returns the (identifier, class) of the molecule for the given map. func getMoleculeInfo(with molecule: MoleculeModelProtocol, delegateObject: MVMCoreUIDelegateObject?) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? { - guard let className = MoleculeObjectMapping.shared()?.getMoleculeClass(molecule) else { - return nil - } + guard let className = MoleculeObjectMapping.shared()?.getMoleculeClass(molecule) else { return nil } return (className.nameForReuse(with: molecule, delegateObject) ?? molecule.moleculeName, className, molecule) } diff --git a/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift b/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift index db0de647..a8600c79 100644 --- a/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift @@ -6,8 +6,6 @@ // Copyright © 2019 Verizon Wireless. All rights reserved. // -import Foundation - import UIKit import MVMCore.MVMCoreViewProtocol @@ -45,8 +43,8 @@ extension MoleculeViewProtocol { } // Do nothing, optionals. - public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {} - public func reset() {} + public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { } + public func reset() { } public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return nil diff --git a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift index fc9873bd..04280042 100644 --- a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift @@ -8,7 +8,6 @@ import Foundation - public protocol TemplateProtocol: AnyObject { associatedtype TemplateModel: TemplateModelProtocol var templateModel: TemplateModel? { get set } @@ -19,11 +18,9 @@ public extension TemplateProtocol where Self: ViewController { guard let pageJSON = json else { return } let data = try JSONSerialization.data(withJSONObject: pageJSON) let decoder = JSONDecoder() + try decoder.add(delegateObject: delegateObjectIVar) let templateModel = try decoder.decode(TemplateModel.self, from: data) self.templateModel = templateModel self.pageModel = templateModel as? MVMControllerModelProtocol - if let backgroundColor = templateModel.backgroundColor { - view.backgroundColor = backgroundColor.uiColor - } } } diff --git a/MVMCoreUI/Atomic/Templates/ModalMoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/ModalMoleculeListTemplate.swift index e82e57a0..a141ef0e 100644 --- a/MVMCoreUI/Atomic/Templates/ModalMoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/ModalMoleculeListTemplate.swift @@ -9,6 +9,9 @@ import UIKit open class ModalMoleculeListTemplate: MoleculeListTemplate { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- public var closeButton: Button? @@ -17,5 +20,8 @@ open class ModalMoleculeListTemplate: MoleculeListTemplate { closeButton = MVMCoreUICommonViewsUtility.addCloseButton(to: view, action: { _ in MVMCoreNavigationHandler.shared()?.removeCurrentViewController() }) + + accessibilityElements = [closeButton as Any, tableView as Any] + UIAccessibility.post(notification: .layoutChanged, argument: closeButton) } } diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListCellProtocol.swift b/MVMCoreUI/Atomic/Templates/MoleculeListCellProtocol.swift index b9cfc02f..46c9a0fa 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListCellProtocol.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListCellProtocol.swift @@ -21,12 +21,10 @@ public protocol MoleculeListCellProtocol: UITableViewCell { // Default implementation does nothing extension MoleculeListCellProtocol { - public func setLines(with model: LineModel?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, indexPath: IndexPath) { - } - public func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - } - - func willDisplay() { - } + public func setLines(with model: LineModel?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, indexPath: IndexPath) { } + + public func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { } + + func willDisplay() { } } diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift index e40fbc33..521a0d45 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift @@ -12,6 +12,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol //-------------------------------------------------- // MARK: - Stored Properties //-------------------------------------------------- + public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: (ListItemModelProtocol & MoleculeModelProtocol))]? var observer: NSKeyValueObservation? @@ -208,8 +209,11 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol func getMoleculeInfo(with listItem: (ListItemModelProtocol & MoleculeModelProtocol)?) -> (identifier: String, class: AnyClass, molecule: ListItemModelProtocol & MoleculeModelProtocol)? { guard let listItem = listItem, - let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(listItem) else { return nil } + let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(listItem) + else { return nil } + let moleculeName = moleculeClass.nameForReuse(with: listItem, delegateObject() as? MVMCoreUIDelegateObject) ?? listItem.moleculeName + return (moleculeName, moleculeClass, listItem) } diff --git a/MVMCoreUI/Atomic/Templates/TemplateModel.swift b/MVMCoreUI/Atomic/Templates/TemplateModel.swift index 864c2bf8..e8992e58 100644 --- a/MVMCoreUI/Atomic/Templates/TemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/TemplateModel.swift @@ -8,26 +8,40 @@ import Foundation + @objcMembers public class TemplateModel: MVMControllerModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- public class var identifier: String { return "" } + public var pageType: String public var template: String { // Although this is done in the extension, it is needed for the encoding. return Self.identifier } + public var backgroundColor: Color? public var screenHeading: String? public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)? public var formRules: [FormGroupRule]? public var behaviors: [PageBehaviorProtocol]? + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- public init(pageType: String) { self.pageType = pageType } + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { case pageType case template @@ -37,6 +51,10 @@ import Foundation case behaviors case navigationItem } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift index c393297b..f1b2633c 100644 --- a/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift @@ -24,25 +24,25 @@ import UIKit open override func viewForTop() -> UIView? { guard let headerModel = templateModel?.header, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(headerModel, delegateObject: delegateObjectIVar) else { - return nil - } + let molecule = MoleculeObjectMapping.shared()?.createMolecule(headerModel, delegateObject: delegateObjectIVar) + else { return nil } + return molecule } open override func viewForMiddle() -> UIView? { guard let middleModel = templateModel?.middle, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(middleModel, delegateObject: delegateObjectIVar) else { - return nil - } + let molecule = MoleculeObjectMapping.shared()?.createMolecule(middleModel, delegateObject: delegateObjectIVar) + else { return nil } + return molecule } override open func viewForBottom() -> UIView? { guard let footerModel = templateModel?.footer, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(footerModel, delegateObject: delegateObjectIVar) else { - return nil - } + let molecule = MoleculeObjectMapping.shared()?.createMolecule(footerModel, delegateObject: delegateObjectIVar) + else { return nil } + return molecule } diff --git a/MVMCoreUI/BaseClasses/TableViewCell.swift b/MVMCoreUI/BaseClasses/TableViewCell.swift index b549b6d0..f07b1ee2 100644 --- a/MVMCoreUI/BaseClasses/TableViewCell.swift +++ b/MVMCoreUI/BaseClasses/TableViewCell.swift @@ -205,6 +205,8 @@ import UIKit let caret = CaretView(lineWidth: 1) caret.translatesAutoresizingMaskIntoConstraints = true caret.isAccessibilityElement = true + caret.accessibilityTraits = .button + caret.accessibilityLabel = "Caret," caret.accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccTabHint") caret.size = .small(.vertical) if let size = caret.size?.dimensions() { diff --git a/MVMCoreUI/BaseClasses/TextView.swift b/MVMCoreUI/BaseClasses/TextView.swift index 191806bb..2c609e02 100644 --- a/MVMCoreUI/BaseClasses/TextView.swift +++ b/MVMCoreUI/BaseClasses/TextView.swift @@ -9,7 +9,7 @@ import UIKit -@objc open class TextView: UITextView, UITextViewDelegate, MVMCoreViewProtocol { +@objc open class TextView: UITextView, MVMCoreViewProtocol, MoleculeViewProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -19,87 +19,18 @@ import UIKit private var initialSetupPerformed = false /// If true then text textView is currently displaying the stored placeholder text as there is not content to display. - public var isShowingPlaceholder: Bool = false { - didSet { textViewModel?.showsPlaceholder = isShowingPlaceholder } - } + public var isShowingPlaceholder: Bool = false /// Set to true to hide the blinking textField cursor. public var hideBlinkingCaret = false - public var textViewModel: TextViewModel? { - return model as? TextViewModel - } + public var placeholder = "" + public var fontStyle: Styler.Font = Styler.Font.RegularBodyLarge + public var placeholderFontStyle: Styler.Font = Styler.Font.RegularMicro + public var placeholderTextColor: UIColor = .mvmCoolGray3 - //-------------------------------------------------- - // MARK: - Drawing Properties - //-------------------------------------------------- - - private(set) var fieldState: FieldState = .original { - didSet (oldState) { - // Will not update if new state is the same as old. - if fieldState != oldState { - DispatchQueue.main.async { [weak self] in - guard let self = self else { return } - - self.fieldState.setStateUI(for: self) - } - } - } - } - - /// Determines if the top, left, and right borders should be drawn. - private var hideBorders = false - - public var borderStrokeColor: UIColor = .mvmCoolGray3 - public var bottomStrokeColor: UIColor = .mvmBlack - private var borderPath: UIBezierPath = UIBezierPath() - private var bottomPath: UIBezierPath = UIBezierPath() - - //-------------------------------------------------- - // MARK: - Property Observers - //-------------------------------------------------- - - private var _isEnabled: Bool = true - private var _showError: Bool = false - private var _isSelected: Bool = false - - public var isEnabled: Bool { - get { return _isEnabled } - set (enabled) { - - _isEnabled = enabled - _isSelected = false - _showError = false - - fieldState = enabled ? .original : .disabled - } - } - - public var showError: Bool { - get { return _showError } - set (error) { - - _showError = error - _isEnabled = true - _isSelected = false - - fieldState = error ? .error : .original - } - } - - public var isSelected: Bool { - get { return _isSelected } - set (selected) { - - _isSelected = selected - _isEnabled = true - - if _showError { - fieldState = selected ? .selectedError : .error - } else { - fieldState = selected ? .selected : .original - } - } + public var isEnabled: Bool = true { + didSet { isUserInteractionEnabled = isEnabled } } //-------------------------------------------------- @@ -109,26 +40,6 @@ import UIKit /// Holds a reference to the delegating class so this class can internally influence the TextField behavior as well. public weak var didDeleteDelegate: TextInputDidDeleteProtocol? - /// Holds a reference to the delegating class so this class can internally influence the TextField behavior as well. - private weak var proprietorTextDelegate: UITextViewDelegate? - - /// If you're using a ViewController, you must set this to it. - public weak var uiTextViewDelegate: UITextViewDelegate? { - get { return delegate } - set { - delegate = self - proprietorTextDelegate = newValue - } - } - - var delegateObject: MVMCoreUIDelegateObject? - - //-------------------------------------------------- - // MARK: - Constraint - //-------------------------------------------------- - - public var heightConstraint: NSLayoutConstraint? - //-------------------------------------------------- // MARK: - Initialization //-------------------------------------------------- @@ -147,11 +58,6 @@ import UIKit initialSetup() } - convenience init(delegate: UITextViewDelegate) { - self.init(frame: .zero, textContainer: nil) - self.delegate = delegate - } - //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- @@ -166,172 +72,53 @@ import UIKit } open func updateView(_ size: CGFloat) { - - setNeedsDisplay() + font = (isShowingPlaceholder ? placeholderFontStyle : fontStyle).getFont() } /// Will be called only once. open func setupView() { translatesAutoresizingMaskIntoConstraints = false - initialConfiguration() + defaultConfiguration() } - public func initialConfiguration() { + public func defaultConfiguration() { + text = "" + placeholder = "" + textAlignment = .left insetsLayoutMarginsFromSafeArea = false showsVerticalScrollIndicator = false showsHorizontalScrollIndicator = false isSecureTextEntry = false - textContainerInset = UIEdgeInsets(top: Padding.Three, left: Padding.Three, bottom: Padding.Three, right: Padding.Three) backgroundColor = .mvmWhite clipsToBounds = true smartQuotesType = .no smartDashesType = .no smartInsertDeleteType = .no inputAccessoryView = nil - font = textViewModel?.fontStyle.getFont() + isAccessibilityElement = true + accessibilityTraits = .staticText + font = fontStyle.getFont() + keyboardType = .default isEditable = true - isOpaque = false } open func reset() { + fontStyle = Styler.Font.RegularBodyLarge + placeholderFontStyle = Styler.Font.RegularMicro + placeholderTextColor = .mvmCoolGray3 + textColor = .mvmBlack + isEnabled = true text = "" + isShowingPlaceholder = false inputAccessoryView?.removeFromSuperview() - inputAccessoryView = nil - initialConfiguration() - } - - open override func layoutSubviews() { - super.layoutSubviews() - - setNeedsDisplay() + defaultConfiguration() } //-------------------------------------------------- - // MARK: - Draw - //-------------------------------------------------- - - /// This handles the top, left, and right border lines. - open override func draw(_ rect: CGRect) { - super.draw(rect) - - borderPath.removeAllPoints() - bottomPath.removeAllPoints() - - if !hideBorders { - // Brings the other half of the line inside the view to prevent line cropping. - let origin = bounds.origin - let size = frame.size - let insetLean: CGFloat = 0.5 - borderPath.lineWidth = 1 - - // Drawing begins and ends from the bottom left. - borderPath.move(to: CGPoint(x: origin.x + insetLean, y: origin.y + size.height)) - borderPath.addLine(to: CGPoint(x: origin.x + insetLean, y: origin.y + insetLean)) - borderPath.addLine(to: CGPoint(x: origin.x + size.width - insetLean, y: origin.y + insetLean)) - borderPath.addLine(to: CGPoint(x: origin.x + size.width - insetLean, y: origin.y + size.height)) - - borderStrokeColor.setStroke() - borderPath.stroke() - - let lineWidth: CGFloat = showError || isSelected ? 4 : 1 - bottomPath.lineWidth = lineWidth - bottomPath.move(to: CGPoint(x: origin.x + size.width, y: origin.y + size.height - (lineWidth / 2))) - bottomPath.addLine(to: CGPoint(x: origin.x, y: origin.y + size.height - (lineWidth / 2))) - - bottomStrokeColor.setStroke() - bottomPath.stroke() - } - } - - //-------------------------------------------------- - // MARK: - Draw States - //-------------------------------------------------- - - public enum FieldState { - case original - case error - case selectedError - case selected - case disabled - - public func setStateUI(for inputField: TextView) { - - switch self { - case .original: - inputField.originalUI() - - case .error: - inputField.errorUI() - - case .selectedError: - inputField.selectedErrorUI() - - case .selected: - inputField.selectedUI() - - case .disabled: - inputField.disabledUI() - } - - inputField.setNeedsDisplay() - } - } - - open func originalUI() { - - isEditable = textViewModel?.editable ?? true - isUserInteractionEnabled = true - hideBorders = textViewModel?.hideBorders ?? false - borderStrokeColor = .mvmCoolGray3 - bottomStrokeColor = .mvmBlack - textColor = isShowingPlaceholder ? textViewModel?.placeholderTextColor.uiColor : textViewModel?.enabledTextColor.uiColor - } - - open func errorUI() { - - isEditable = textViewModel?.editable ?? true - isUserInteractionEnabled = true - hideBorders = textViewModel?.hideBorders ?? false - borderStrokeColor = .mvmOrange - bottomStrokeColor = .mvmOrange - textColor = textViewModel?.enabledTextColor.uiColor - } - - open func selectedErrorUI() { - - isEditable = textViewModel?.editable ?? true - isUserInteractionEnabled = true - hideBorders = textViewModel?.hideBorders ?? false - borderStrokeColor = .mvmBlack - bottomStrokeColor = .mvmOrange - textColor = textViewModel?.enabledTextColor.uiColor - } - - open func selectedUI() { - - isEditable = textViewModel?.editable ?? true - isUserInteractionEnabled = true - hideBorders = textViewModel?.hideBorders ?? false - borderStrokeColor = .mvmBlack - bottomStrokeColor = .mvmBlack - textColor = textViewModel?.enabledTextColor.uiColor - } - - open func disabledUI() { - - isEditable = textViewModel?.editable ?? false - isUserInteractionEnabled = false - hideBorders = textViewModel?.hideBorders ?? false - borderStrokeColor = .mvmCoolGray3 - bottomStrokeColor = .mvmCoolGray3 - textColor = textViewModel?.disabledTextColor.uiColor - } - - //-------------------------------------------------- - // MARK: - Methods + // MARK: - TextInputDidDeleteProtocol //-------------------------------------------------- /// Alters the blinking caret line as per design standards. @@ -350,141 +137,49 @@ import UIKit didDeleteDelegate?.textInputDidDelete() } - public func setTextAppearance() { + //-------------------------------------------------- + // MARK: - Text / Placeholder + //-------------------------------------------------- + + open override func becomeFirstResponder() -> Bool { if isShowingPlaceholder { setTextContentTraits() } + return super.becomeFirstResponder() + } + + open override func resignFirstResponder() -> Bool { + + setPlaceholderIfAvailable() + return super.resignFirstResponder() } public func setPlaceholderIfAvailable() { - if let placeholder = textViewModel?.placeholder, !placeholder.isEmpty && text.isEmpty { + if !placeholder.isEmpty && text.isEmpty { setPlaceholderContentTraits() } } - public func setTextContentTraits() { + open func setTextContentTraits() { isShowingPlaceholder = false text = "" - font = textViewModel?.fontStyle.getFont() - textColor = textViewModel?.enabledTextColor.uiColor + font = fontStyle.getFont() + textColor = .mvmBlack } - public func setPlaceholderContentTraits() { + open func setPlaceholderContentTraits() { isShowingPlaceholder = true - textColor = textViewModel?.placeholderTextColor.uiColor - font = textViewModel?.placeholderFontStyle.getFont() - text = textViewModel?.placeholder + textColor = placeholderTextColor + font = placeholderFontStyle.getFont() + text = placeholder } - @objc func dismissFieldInput(_ sender: TextView) { + @objc open func dismissFieldInput(_ sender: TextView) { - resignFirstResponder() - } - - //-------------------------------------------------- - // MARK: - UITextViewDelegate - //-------------------------------------------------- - - @objc public func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { - - return proprietorTextDelegate?.textViewShouldBeginEditing?(textView) ?? true - } - - @objc public func textViewDidBeginEditing(_ textView: UITextView) { - - setTextAppearance() - isSelected = true - proprietorTextDelegate?.textViewDidBeginEditing?(textView) - } - - @objc public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { - - return proprietorTextDelegate?.textView?(textView, shouldChangeTextIn: range, replacementText: text) ?? true - } - - @objc public func textViewDidChange(_ textView: UITextView) { - - textViewModel?.text = textView.text - proprietorTextDelegate?.textViewDidChange?(textView) - } - - @objc public func textViewShouldEndEditing(_ textView: UITextView) -> Bool { - - return proprietorTextDelegate?.textViewShouldEndEditing?(textView) ?? true - } - - @objc public func textViewDidEndEditing(_ textView: UITextView) { - - setPlaceholderIfAvailable() - isSelected = false - proprietorTextDelegate?.textViewDidEndEditing?(textView) - } -} - -// MARK:- MoleculeViewProtocol -extension TextView: MoleculeViewProtocol { - - open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - self.model = model - self.delegateObject = delegateObject - - if let color = model.backgroundColor?.uiColor { - backgroundColor = color - } - - guard let model = model as? TextViewModel else { return } - - heightConstraint?.isActive = false - if let height = model.height { - heightConstraint = heightAnchor.constraint(equalToConstant: height) - heightConstraint?.isActive = true - } - - isEditable = model.editable - textAlignment = model.textAlignment - textColor = model.enabledTextColor.uiColor - hideBorders = model.hideBorders - text = model.text - uiTextViewDelegate = delegateObject?.uiTextViewDelegate - - if let accessibilityText = model.accessibilityText { - accessibilityLabel = accessibilityText - } - - switch model.type { - case .secure, .password: - isSecureTextEntry = true - case .number: - keyboardType = .numberPad - case .email: - keyboardType = .emailAddress - default: - break - } - - font = model.fontStyle.getFont() - setPlaceholderIfAvailable() - - if isEditable { - FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) - let observingDelegate = delegateObject?.uiTextViewDelegate ?? self - inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate, - action: #selector(dismissFieldInput)) - - if (model.selected ?? false) && !model.wasInitiallySelected { - model.wasInitiallySelected = true - DispatchQueue.main.async { - self.becomeFirstResponder() - } - } - } - - if !model.enabled { - isEnabled = false - } + _ = resignFirstResponder() } } diff --git a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift index 8e01cf6c..7962dcf5 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift @@ -40,6 +40,7 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { createViewForTableHeader() createViewForTableFooter() tableView?.reloadData() + accessibilityElements = [tableView as Any] } override open func viewDidLoad() { diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 28aacc6e..c44a8d47 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -17,7 +17,10 @@ import UIKit public var manager: (UIViewController & MVMCoreViewManagerProtocol)? /// A temporary iVar backer for delegateObject() until we change the protocol - public var delegateObjectIVar: MVMCoreUIDelegateObject? + public lazy var delegateObjectIVar: MVMCoreUIDelegateObject = { + return MVMCoreUIDelegateObject.create(withDelegateForAll: self) + }() + public func delegateObject() -> DelegateObject? { return delegateObjectIVar } @@ -171,6 +174,10 @@ import UIKit let rules = pageModel?.formRules formValidator = FormValidator(rules) } + + if let backgroundColor = pageModel?.backgroundColor { + view.backgroundColor = backgroundColor.uiColor + } } // MARK: - Navigation Item (Move to model base) @@ -258,10 +265,7 @@ import UIKit viewRespectsSystemMinimumLayoutMargins = false // Presents from the bottom. - modalPresentationStyle = MVMCoreGetterUtility.isOnIPad() ? UIModalPresentationStyle.formSheet : UIModalPresentationStyle.overCurrentContext - - // Create the default delegate object. - delegateObjectIVar = MVMCoreUIDelegateObject.create(withDelegateForAll: self) + modalPresentationStyle = MVMCoreGetterUtility.isOnIPad() ? .formSheet : .overCurrentContext // Do some initial loading. if !initialLoadFinished { @@ -351,18 +355,18 @@ import UIKit } // MARK: - MVMCoreActionDelegateProtocol - open func handleOpenPage(for requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) { + open func handleOpenPage(for requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) { formValidator?.addFormParams(requestParameters: requestParameters) requestParameters.parentPageType = loadObject?.pageJSON?.optionalStringForKey("parentPageType") MVMCoreActionHandler.defaultHandleOpenPage(for: requestParameters, additionalData: additionalData, delegateObject: delegateObject()) } - open func logAction(withActionInformation actionInformation: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) { + open func logAction(withActionInformation actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) { MVMCoreUILoggingHandler.shared()?.defaultLogAction(forController: self, actionInformation: actionInformation, additionalData: additionalData) } // MARK: - MoleculeDelegateProtocol - open func getModuleWithName(_ name: String?) -> [AnyHashable : Any]? { + open func getModuleWithName(_ name: String?) -> [AnyHashable: Any]? { guard let name = name else { return nil } return loadObject?.modulesJSON?.optionalDictionaryForKey(name) } @@ -403,7 +407,7 @@ import UIKit view.accessibilityElements = [pickerView, toolBar] } DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { - UIAccessibility.post(notification: UIAccessibility.Notification.layoutChanged, argument: textField.inputView) + UIAccessibility.post(notification: .layoutChanged, argument: textField.inputView) } } } @@ -412,7 +416,7 @@ import UIKit if textField === selectedField { if UIAccessibility.isVoiceOverRunning { view.accessibilityElements = nil - UIAccessibility.post(notification: UIAccessibility.Notification.layoutChanged, argument: textField) + UIAccessibility.post(notification: .layoutChanged, argument: textField) } selectedField = nil } diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index f278236c..05e5c406 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -58,7 +58,7 @@ import UIKit if navigationController == MVMCoreUISession.sharedGlobal()?.navigationController, navigationController.topViewController == viewController { // Update line. - MVMCoreUISession.sharedGlobal()?.navigationController?.separatorView?.setStyle(navigationItemModel.line?.type ?? .standard) + MVMCoreUISession.sharedGlobal()?.navigationController?.separatorView?.isHidden = navigationItemModel.line?.type ?? .standard == .none } if navigationController == MVMCoreUISplitViewController.main()?.navigationController, diff --git a/MVMCoreUI/Containers/Views/Container.swift b/MVMCoreUI/Containers/Views/Container.swift index eb05cd21..8c95f110 100644 --- a/MVMCoreUI/Containers/Views/Container.swift +++ b/MVMCoreUI/Containers/Views/Container.swift @@ -9,8 +9,10 @@ import UIKit open class Container: View, ContainerProtocol { + public var view: UIView? let containerHelper = ContainerHelper() + var containerModel: ContainerModelProtocol? { get { return model as? ContainerModelProtocol } } diff --git a/MVMCoreUI/Containers/Views/ContainerHelper.swift b/MVMCoreUI/Containers/Views/ContainerHelper.swift index 4ce97f5c..f60d1ee6 100644 --- a/MVMCoreUI/Containers/Views/ContainerHelper.swift +++ b/MVMCoreUI/Containers/Views/ContainerHelper.swift @@ -9,7 +9,12 @@ import Foundation + open class ContainerHelper: NSObject { + //-------------------------------------------------- + // MARK: - Constraints + //-------------------------------------------------- + var leftConstraint: NSLayoutConstraint? var topConstraint: NSLayoutConstraint? var bottomConstraint: NSLayoutConstraint? @@ -28,17 +33,26 @@ open class ContainerHelper: NSObject { var bottomLowConstraint: NSLayoutConstraint? var rightLowConstraint: NSLayoutConstraint? + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + open func constrainView(_ view: UIView) { guard let margins = view.superview?.layoutMarginsGuide else { return } + + leftConstraint?.isActive = false leftConstraint = view.leftAnchor.constraint(equalTo: margins.leftAnchor) leftConstraint?.isActive = true + topConstraint?.isActive = false topConstraint = view.topAnchor.constraint(equalTo: margins.topAnchor) topConstraint?.isActive = true + rightConstraint?.isActive = false rightConstraint = margins.rightAnchor.constraint(equalTo: view.rightAnchor) rightConstraint?.isActive = true + bottomConstraint?.isActive = false bottomConstraint = margins.bottomAnchor.constraint(equalTo: view.bottomAnchor) bottomConstraint?.isActive = true @@ -50,23 +64,25 @@ open class ContainerHelper: NSObject { alignCenterTopConstraint = view.topAnchor.constraint(greaterThanOrEqualTo: margins.topAnchor) alignCenterBottomConstraint = margins.bottomAnchor.constraint(greaterThanOrEqualTo: view.bottomAnchor) + leftLowConstraint?.isActive = false leftLowConstraint = view.leftAnchor.constraint(equalTo: margins.leftAnchor) leftLowConstraint?.priority = UILayoutPriority(rawValue: 200) leftLowConstraint?.isActive = true + topLowConstraint?.isActive = false topLowConstraint = view.topAnchor.constraint(equalTo: margins.topAnchor) topLowConstraint?.priority = UILayoutPriority(rawValue: 200) topLowConstraint?.isActive = true + rightLowConstraint?.isActive = false rightLowConstraint = margins.rightAnchor.constraint(equalTo: view.rightAnchor) rightLowConstraint?.priority = UILayoutPriority(rawValue: 200) rightLowConstraint?.isActive = true + bottomLowConstraint?.isActive = false bottomLowConstraint = margins.bottomAnchor.constraint(equalTo: view.bottomAnchor) bottomLowConstraint?.priority = UILayoutPriority(rawValue: 200) bottomLowConstraint?.isActive = true - - setAccessibility(view) } open func setAccessibility(_ view: UIView) { diff --git a/MVMCoreUI/CustomPrimitives/Color.swift b/MVMCoreUI/CustomPrimitives/Color.swift index f06b337c..42c7a600 100644 --- a/MVMCoreUI/CustomPrimitives/Color.swift +++ b/MVMCoreUI/CustomPrimitives/Color.swift @@ -55,6 +55,13 @@ public final class Color: Codable { determineRGBA() } + public init?(uiColor: UIColor?) { + guard let uiColor = uiColor else { return nil } + self.uiColor = uiColor + hex = UIColor.hexString(for: uiColor) ?? "" + determineRGBA() + } + init?(name: String) { guard let colorTuple = UIColor.names[name] else { return nil } self.uiColor = colorTuple.uiColor diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAllValueChangedModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAllValueChangedModel.swift index 1f50bcc7..aa80f5b0 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAllValueChangedModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAllValueChangedModel.swift @@ -15,6 +15,7 @@ public class RuleAllValueChangedModel: RulesProtocol { public static var identifier: String = "allValueChanged" public var type: String = RuleAllValueChangedModel.identifier + public var errorMessage: [String: String]? public var fields: [String] //-------------------------------------------------- diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift index 6ca905bf..7f153e83 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift @@ -17,6 +17,7 @@ public class RuleAnyRequiredModel: RulesProtocol { public static var identifier: String = "anyRequired" public var type: String = RuleRequiredModel.identifier public var fields: [String] + public var errorMessage: [String: String]? //-------------------------------------------------- // MARK: - Methods diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift index 450fdb2a..07cf451f 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift @@ -16,6 +16,7 @@ public class RuleAnyValueChangedModel: RulesProtocol { public static var identifier: String = "anyValueChanged" public var type: String = RuleAnyValueChangedModel.identifier + public var errorMessage: [String: String]? public var fields: [String] //-------------------------------------------------- diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift new file mode 100644 index 00000000..0bdd7ca3 --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift @@ -0,0 +1,52 @@ +// +// RuleEqualsIgnoreCaseModel.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 5/15/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + + +public class RuleEqualsIgnoreCaseModel: RulesProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public static var identifier: String = "equalsIgnoreCase" + public var type: String = RuleEqualsIgnoreCaseModel.identifier + public var fields: [String] + public var errorMessage: [String: String]? + + //-------------------------------------------------- + // MARK: - Validation + //-------------------------------------------------- + + public func isValid(_ formField: FormFieldProtocol) -> Bool { + return false + } + + public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { + var valid = false + var compareText: String? + + for formKey in fields { + guard let formField = fieldMolecules[formKey] else { continue } + + guard let compareString = compareText else { + compareText = formField.formFieldValue() as? String + continue + } + + if let fieldValue = formField.formFieldValue() as? String, + compareString.caseInsensitiveCompare(fieldValue) == .orderedSame { + valid = true + } + + (formField as? FormRuleWatcherFieldProtocol)?.setValidity(valid, rule: self) + } + + return valid + } +} diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift index fb7585f2..fa73ed51 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift @@ -17,6 +17,7 @@ public class RuleEqualsModel: RulesProtocol { public static var identifier: String = "equals" public var type: String = RuleEqualsModel.identifier public var fields: [String] + public var errorMessage: [String: String]? //-------------------------------------------------- // MARK: - Validation @@ -27,9 +28,9 @@ public class RuleEqualsModel: RulesProtocol { } public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { - var valid = true - var compareValue: AnyHashable? - + var valid = true + var compareValue: AnyHashable? + for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } @@ -37,13 +38,16 @@ public class RuleEqualsModel: RulesProtocol { compareValue = formField.formFieldValue() continue } - + if compareValue != formField.formFieldValue() { valid = false + (formField as? FormRuleWatcherFieldProtocol)?.setValidity(valid, rule: self) break + } else { + (formField as? FormRuleWatcherFieldProtocol)?.setValidity(valid, rule: self) } } - - return valid + + return valid } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRegexModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRegexModel.swift index 68eea7e5..5f60a61b 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRegexModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRegexModel.swift @@ -18,6 +18,7 @@ public class RuleRegexModel: RulesProtocol { public var type: String = RuleRegexModel.identifier public var fields: [String] public var regex: String + public var errorMessage: [String: String]? //-------------------------------------------------- // MARK: - Properties diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRequiredModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRequiredModel.swift index b34a24df..77cdf254 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRequiredModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRequiredModel.swift @@ -16,6 +16,7 @@ public class RuleRequiredModel: RulesProtocol { public static var identifier: String = "allRequired" public var type: String = RuleRequiredModel.identifier + public var errorMessage: [String: String]? public var fields: [String] //-------------------------------------------------- @@ -23,6 +24,7 @@ public class RuleRequiredModel: RulesProtocol { //-------------------------------------------------- public func isValid(_ formField: FormFieldProtocol) -> Bool { + guard let value = formField.formFieldValue() else { return false } var valid = true diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift index 305b4c35..7392ea8f 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift @@ -16,7 +16,9 @@ public enum RulesCodingKey: String, CodingKey { public protocol RulesProtocol: ModelProtocol { // The type of rule var type: String { get } - + + var errorMessage: [String: String]? { get } + // The fields that this rule applies to. var fields: [String] { get set } diff --git a/MVMCoreUI/Styles/Styler.swift b/MVMCoreUI/Styles/Styler.swift index 863d4703..d8d0a519 100644 --- a/MVMCoreUI/Styles/Styler.swift +++ b/MVMCoreUI/Styles/Styler.swift @@ -172,6 +172,29 @@ open class Styler { } } + public enum Button { + + public enum Style: String, Codable { + case primary + case secondary + } + + public enum Size: String, Codable { + case standard + case tiny + + func getHeight() -> CGFloat { + switch self { + case .standard: + return 42 + + case .tiny: + return 20 + } + } + } + } + //-------------------------------------------------- // MARK: - Functions //-------------------------------------------------- diff --git a/MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-55Rg.otf b/MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-55Rg.otf deleted file mode 100644 index f56ed7aa..00000000 Binary files a/MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-55Rg.otf and /dev/null differ diff --git a/MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-75Bd.otf b/MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-75Bd.otf deleted file mode 100644 index fbcba354..00000000 Binary files a/MVMCoreUI/SupportingFiles/Fonts/NHaasGroteskDSStd-75Bd.otf and /dev/null differ diff --git a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings index 25dd849b..da55d597 100644 --- a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings @@ -53,6 +53,7 @@ // MARK: Radio Button +"radio_button" = "Radio Button,"; "radio_action_hint" = "Double tap to select"; "radio_selected_state" = "Selected"; "radio_not_selected_state" = "Not Selected"; diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m index 2021cb15..eeff9cfe 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m @@ -188,14 +188,13 @@ self.labelRightConstraint.active = NO; // Sets up to use a button action. Always uses the top view controller - PillButton *button = [[PillButton alloc] init]; + PillButton *button = [[PillButton alloc] initAsPrimaryButton:false makeTiny:true]; [button styleSecondary]; [button setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal]; [button setContentHuggingPriority:800 forAxis:UILayoutConstraintAxisHorizontal]; button.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:button]; - [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|->=space-[button]->=space-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"space":@(PaddingFive)} views:NSDictionaryOfVariableBindings(button)]]; [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0].active = YES; [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.centerView attribute:NSLayoutAttributeRight multiplier:1 constant:PaddingThree].active = YES; [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:button attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : PaddingFive)].active = YES; diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m index b3dacb21..d8c21b45 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m @@ -160,6 +160,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; UIColor *statusBarColor = nil; UIStatusBarStyle statusBarStyle = UIStatusBarStyleDefault; MVMCoreUITopAlertBaseView *view = [self topAlertViewForTopAlertObject:topAlertObject animationDelegate:animationDelegate statusBarColor:&statusBarColor statusBarStyle:&statusBarStyle]; + [view updateView:CGRectGetWidth(self.bounds)]; if (!statusBarColor) { statusBarColor = [UIColor whiteColor]; } diff --git a/MVMCoreUI/Utility/MFFonts.h b/MVMCoreUI/Utility/MFFonts.h index fb4bbe92..46947581 100644 --- a/MVMCoreUI/Utility/MFFonts.h +++ b/MVMCoreUI/Utility/MFFonts.h @@ -14,9 +14,6 @@ extern NSString * _Nonnull const DSBold; extern NSString * _Nonnull const DSRegular; extern NSString * _Nonnull const TXBold; extern NSString * _Nonnull const TXRegular; -//2.0 font -extern NSString * _Nonnull const DS75Bd; -extern NSString * _Nonnull const DS55Rg; @interface MFFonts : NSObject diff --git a/MVMCoreUI/Utility/MFFonts.m b/MVMCoreUI/Utility/MFFonts.m index 150cffa7..d16f15ec 100644 --- a/MVMCoreUI/Utility/MFFonts.m +++ b/MVMCoreUI/Utility/MFFonts.m @@ -17,11 +17,6 @@ NSString * const DSRegular = @"VerizonNHGeDS-Regular"; NSString * const TXBold = @"VerizonNHGeTX-Bold"; NSString * const TXRegular = @"VerizonNHGeTX-Regular"; -//2.0 font -NSString * const DS75Bd = @"NHaasGroteskDSStd-75Bd"; -NSString * const DS55Rg = @"NHaasGroteskDSStd-55Rg"; - - @implementation MFFonts + (void)loadMVMFonts { @@ -31,8 +26,6 @@ NSString * const DS55Rg = @"NHaasGroteskDSStd-55Rg"; [MFFonts loadFont:DSRegular type:@"otf"]; [MFFonts loadFont:TXBold type:@"otf"]; [MFFonts loadFont:TXRegular type:@"otf"]; - [MFFonts loadFont:DS75Bd type:@"otf"]; - [MFFonts loadFont:DS55Rg type:@"otf"]; [MFFonts loadFont:@"OCRAExtended" type:@"ttf"]; }); }