Merge remote-tracking branch 'origin/develop' into feature/page_behavior_poc
This commit is contained in:
commit
d36284e57f
@ -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 = "<group>"; };
|
||||
0A21DB82235DFBC500C160A2 /* MdnEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MdnEntryField.swift; sourceTree = "<group>"; };
|
||||
0A21DB93235E24ED00C160A2 /* DigitEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitEntryField.swift; sourceTree = "<group>"; };
|
||||
0A25209524645AFD000FA9F6 /* TextViewEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewEntryField.swift; sourceTree = "<group>"; };
|
||||
0A25209724645B76000FA9F6 /* TextViewEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewEntryFieldModel.swift; sourceTree = "<group>"; };
|
||||
0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CATransaction+Extension.swift"; sourceTree = "<group>"; };
|
||||
0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEntryField.swift; sourceTree = "<group>"; };
|
||||
0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleGuidelinesProtocol.swift; sourceTree = "<group>"; };
|
||||
@ -485,7 +491,6 @@
|
||||
0A6682A92435125F00AD3CA1 /* Styler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Styler.swift; sourceTree = "<group>"; };
|
||||
0A6682AB243531C300AD3CA1 /* Padding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Padding.swift; sourceTree = "<group>"; };
|
||||
0A6682B3243769C700AD3CA1 /* TextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextView.swift; sourceTree = "<group>"; };
|
||||
0A6682B4243769C700AD3CA1 /* TextViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextViewModel.swift; sourceTree = "<group>"; };
|
||||
0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyRequiredModel.swift; sourceTree = "<group>"; };
|
||||
0A6BF4712360C56C0028F841 /* BaseDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDropdownEntryField.swift; sourceTree = "<group>"; };
|
||||
0A7918F423F5E7EA00772FF4 /* ImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageView.swift; sourceTree = "<group>"; };
|
||||
@ -503,6 +508,7 @@
|
||||
0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryFieldModel.swift; sourceTree = "<group>"; };
|
||||
0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryFieldModel.swift; sourceTree = "<group>"; };
|
||||
0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = "<group>"; };
|
||||
0A849EFD246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleEqualsIgnoreCaseModel.swift; sourceTree = "<group>"; };
|
||||
0A9D09172433796500D2E6C0 /* BarsCarouselIndicatorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarsCarouselIndicatorModel.swift; sourceTree = "<group>"; };
|
||||
0A9D09182433796500D2E6C0 /* NumericCarouselIndicatorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumericCarouselIndicatorModel.swift; sourceTree = "<group>"; };
|
||||
0A9D09192433796500D2E6C0 /* NumericIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumericIndicatorView.swift; sourceTree = "<group>"; };
|
||||
@ -562,8 +568,6 @@
|
||||
8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDividerModel.swift; sourceTree = "<group>"; };
|
||||
8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDivider.swift; sourceTree = "<group>"; };
|
||||
9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = "<group>"; };
|
||||
942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-75Bd.otf"; sourceTree = "<group>"; };
|
||||
942C372D241149170066E45E /* NHaasGroteskDSStd-55Rg.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-55Rg.otf"; sourceTree = "<group>"; };
|
||||
942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalMoleculeListTemplate.swift; sourceTree = "<group>"; };
|
||||
942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalMoleculeStackTemplate.swift; sourceTree = "<group>"; };
|
||||
9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntryFieldContainer.swift; sourceTree = "<group>"; };
|
||||
@ -594,6 +598,8 @@
|
||||
94CA227A24058533002D6750 /* VerizonNHGeDS-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeDS-Bold.otf"; sourceTree = "<group>"; };
|
||||
94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeTX-Regular.otf"; sourceTree = "<group>"; };
|
||||
94F6516C2437954100631BF9 /* Tabs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tabs.swift; sourceTree = "<group>"; };
|
||||
AA104B1924474A66004D2810 /* HeadersH2Buttons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2Buttons.swift; sourceTree = "<group>"; };
|
||||
AA104B1B24474A76004D2810 /* HeadersH2ButtonsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2ButtonsModel.swift; sourceTree = "<group>"; };
|
||||
AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePayments.swift; sourceTree = "<group>"; };
|
||||
AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePaymentsModel.swift; sourceTree = "<group>"; };
|
||||
AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDividerModel.swift; sourceTree = "<group>"; };
|
||||
@ -611,6 +617,8 @@
|
||||
AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||
AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = "<group>"; };
|
||||
AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = "<group>"; };
|
||||
AAB7EDEE246ADA1600E54929 /* ListProgressBarThinModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListProgressBarThinModel.swift; sourceTree = "<group>"; };
|
||||
AAB7EDF0246ADA2A00E54929 /* ListProgressBarThin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListProgressBarThin.swift; sourceTree = "<group>"; };
|
||||
AAB9C10724346F4B00151545 /* RadioSwatches.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatches.swift; sourceTree = "<group>"; };
|
||||
AAB9C109243496DD00151545 /* RadioSwatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatch.swift; sourceTree = "<group>"; };
|
||||
AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchesModel.swift; sourceTree = "<group>"; };
|
||||
@ -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 = "<group>";
|
||||
@ -1253,6 +1264,8 @@
|
||||
D20492F12434CB5F00A5EED6 /* FourColumn */,
|
||||
AA4FC2A323F4F69600E251DB /* RightVariable */,
|
||||
D22B38EB23F4E0AE00490EF6 /* LeftVariable */,
|
||||
AAB7EDEE246ADA1600E54929 /* ListProgressBarThinModel.swift */,
|
||||
AAB7EDF0246ADA2A00E54929 /* ListProgressBarThin.swift */,
|
||||
);
|
||||
path = List;
|
||||
sourceTree = "<group>";
|
||||
@ -1652,6 +1665,8 @@
|
||||
0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */,
|
||||
0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */,
|
||||
0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */,
|
||||
0A25209724645B76000FA9F6 /* TextViewEntryFieldModel.swift */,
|
||||
0A25209524645AFD000FA9F6 /* TextViewEntryField.swift */,
|
||||
);
|
||||
path = TextFields;
|
||||
sourceTree = "<group>";
|
||||
@ -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 */,
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol {
|
||||
}
|
||||
|
||||
public override func updateView(_ size: CGFloat) {
|
||||
titleLabel?.font = MFStyler.fontB1()
|
||||
titleLabel?.font = MFStyler.fontBoldBodySmall()
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -6,9 +6,9 @@
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
|
||||
open class RadioSwatch: Control {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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?) {
|
||||
|
||||
@ -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)
|
||||
|
||||
279
MVMCoreUI/Atomic/Atoms/TextFields/TextViewEntryField.swift
Normal file
279
MVMCoreUI/Atomic/Atoms/TextFields/TextViewEntryField.swift
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -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]?) {
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
//--------------------------------------------------
|
||||
|
||||
public let checkbox = Checkbox()
|
||||
public let label = Label.commonLabelB2(true)
|
||||
public let label = Label.createLabelRegularBodySmall(true)
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
})}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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<StackModel>
|
||||
|
||||
//-------------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//-------------------------------------------------------
|
||||
public override init(frame: CGRect) {
|
||||
stack = Stack<StackModel>.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()
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,7 @@ import Foundation
|
||||
//--------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//--------------------------------------------------
|
||||
|
||||
let headlineBody = HeadlineBody(frame: .zero)
|
||||
|
||||
//-------------------------------------------------------
|
||||
|
||||
@ -14,7 +14,19 @@ import Foundation
|
||||
//--------------------------------------------------
|
||||
public let headlineBody = HeadlineBody(frame: .zero)
|
||||
public let button = PillButton(frame: .zero)
|
||||
public var stack = Stack<StackModel>(frame: .zero)
|
||||
public let stack: Stack<StackModel>
|
||||
|
||||
//-------------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//-------------------------------------------------------
|
||||
public override init(frame: CGRect) {
|
||||
stack = Stack<StackModel>.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<StackModel>.createStack(with: [(view: headlineBody, model: StackItemModel(horizontalAlignment: .fill)), (view: button, model: StackItemModel(spacing: spacingBetwenHeadlineBodyAndButton, horizontalAlignment: .leading))], axis: .vertical)
|
||||
headlineBody.stylePageHeader()
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
|
||||
@ -43,6 +43,7 @@ import Foundation
|
||||
// MARK: - MFViewProtocol
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
rightImageView.shouldNotifyDelegateOnUpdate = false
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
verticalStack.restack()
|
||||
|
||||
@ -43,6 +43,7 @@ import Foundation
|
||||
// MARK: - MFViewProtocol
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
rightImageView.shouldNotifyDelegateOnUpdate = false
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
verticalStack.restack()
|
||||
|
||||
@ -46,6 +46,7 @@ import Foundation
|
||||
//-----------------------------------------------------
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
rightImage.shouldNotifyDelegateOnUpdate = false
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
verticalStack.restack()
|
||||
|
||||
@ -46,6 +46,7 @@ import Foundation
|
||||
//-----------------------------------------------------
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
rightImage.shouldNotifyDelegateOnUpdate = false
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
verticalStack.restack()
|
||||
|
||||
@ -14,10 +14,10 @@ import Foundation
|
||||
// MARK: - Outlets
|
||||
//-----------------------------------------------------
|
||||
var stack: Stack<StackModel>
|
||||
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<StackModel>
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<StackModel>
|
||||
|
||||
//-----------------------------------------------------
|
||||
@ -64,7 +63,7 @@ import UIKit
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
leftLabel.styleB2(true)
|
||||
rightLabel.styleB2(true)
|
||||
leftLabel.styleRegularBodySmall(true)
|
||||
rightLabel.styleRegularBodySmall(true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<StackModel>
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -14,10 +14,12 @@ open class ListLeftVariableRadioButtonBodyText: TableViewCell {
|
||||
// MARK: - Outlets
|
||||
//-----------------------------------------------------
|
||||
|
||||
let radioButton = RadioButton(frame: .zero)
|
||||
let radioButton = RadioButton()
|
||||
let headlineBody = HeadlineBody()
|
||||
var stack: Stack<StackModel>
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<StackModel>
|
||||
public var horizontalStack: Stack<StackModel>
|
||||
public var stack: Stack<StackModel>
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//------------------------------------------------------
|
||||
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
//vertical stack with leftHeadline, leftBody
|
||||
labelStack = Stack<StackModel>.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<StackModel>(with: horizontalStackModel, stackItems: horizontalStackItems)
|
||||
|
||||
//stack with all components
|
||||
stack = Stack<StackModel>.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)
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -15,10 +15,10 @@ import Foundation
|
||||
//-----------------------------------------------------
|
||||
|
||||
var stack: Stack<StackModel>
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<StackModel>
|
||||
|
||||
//-----------------------------------------------------
|
||||
@ -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? {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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<StackModel>
|
||||
|
||||
@ -57,6 +57,6 @@ import Foundation
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
leftLabel.styleB1(true)
|
||||
leftLabel.styleBoldBodySmall(true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<StackModel>
|
||||
private let arrowStackItem: StackItem
|
||||
private let rightLabelStackItem: StackItem
|
||||
|
||||
@ -15,7 +15,7 @@ import Foundation
|
||||
private let stack: Stack<StackModel>
|
||||
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<StackModel>
|
||||
|
||||
|
||||
|
||||
@ -14,8 +14,8 @@ import Foundation
|
||||
// MARK: - Outlets
|
||||
//-----------------------------------------------------
|
||||
public var stack: Stack<StackModel>
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<StackModel>
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -13,8 +13,8 @@ import Foundation
|
||||
// MARK: - Outlets
|
||||
//-----------------------------------------------------
|
||||
public var stack: Stack<StackModel>
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,8 +13,8 @@ import Foundation
|
||||
// MARK: - Outlets
|
||||
//-----------------------------------------------------
|
||||
public var stack: Stack<StackModel>
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,8 +13,8 @@ import Foundation
|
||||
// MARK: - Outlets
|
||||
//-----------------------------------------------------
|
||||
public var stack: Stack<StackModel>
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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]?) {
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtocol {
|
||||
|
||||
@ -14,9 +14,9 @@ import UIKit
|
||||
//--------------------------------------------------
|
||||
|
||||
public let stack = Stack<StackModel>(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)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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?
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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() { }
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,6 +40,7 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
|
||||
createViewForTableHeader()
|
||||
createViewForTableFooter()
|
||||
tableView?.reloadData()
|
||||
accessibilityElements = [tableView as Any]
|
||||
}
|
||||
|
||||
override open func viewDidLoad() {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 }
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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]
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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]
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 }
|
||||
|
||||
|
||||
@ -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
|
||||
//--------------------------------------------------
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -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";
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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];
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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"];
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user