This commit is contained in:
Pfeil, Scott Robert 2020-05-18 20:51:24 -04:00
commit d293b93adc
84 changed files with 1250 additions and 604 deletions

View File

@ -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 */; };
@ -108,6 +110,8 @@
0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB423FF18D2004C5109 /* Arrow.swift */; };
0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */; };
279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */; };
27F973532466074500CAB5C5 /* PageBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F973522466074500CAB5C5 /* PageBehavior.swift */; };
27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */; };
31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */; };
31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15CA23D8924C00452370 /* CheckboxModel.swift */; };
522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */; };
@ -146,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 */; };
@ -179,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 */; };
@ -196,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 */; };
@ -478,6 +484,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>"; };
@ -486,7 +494,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>"; };
@ -504,6 +511,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>"; };
@ -522,6 +530,8 @@
0AE98BB423FF18D2004C5109 /* Arrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Arrow.swift; sourceTree = "<group>"; };
0AE98BB623FF18E9004C5109 /* ArrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrowModel.swift; sourceTree = "<group>"; };
279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionModelAdapter.swift; sourceTree = "<group>"; };
27F973522466074500CAB5C5 /* PageBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehavior.swift; sourceTree = "<group>"; };
27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenBrightnessModifierBehavior.swift; sourceTree = "<group>"; };
31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxLabelModel.swift; sourceTree = "<group>"; };
31BE15CA23D8924C00452370 /* CheckboxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxModel.swift; sourceTree = "<group>"; };
522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = "<group>"; };
@ -561,8 +571,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>"; };
@ -593,6 +601,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>"; };
@ -610,6 +620,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>"; };
@ -875,6 +887,7 @@
011D95A0240453D0000E3791 /* RuleEqualsModel.swift */,
011D95A2240453F8000E3791 /* RuleRegexModel.swift */,
0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */,
0A849EFD246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift */,
);
name = Rules;
path = Rules/Rules;
@ -956,6 +969,15 @@
path = Adapters;
sourceTree = "<group>";
};
27F973512466071600CAB5C5 /* Behaviors */ = {
isa = PBXGroup;
children = (
27F973522466074500CAB5C5 /* PageBehavior.swift */,
27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */,
);
path = Behaviors;
sourceTree = "<group>";
};
5206F150241144A900658DC5 /* Headers */ = {
isa = PBXGroup;
children = (
@ -963,6 +985,8 @@
AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */,
AA26850D244840C300CE34CC /* HeadersH2TinyButtonModel.swift */,
AA26850B244840AE00CE34CC /* HeadersH2TinyButton.swift */,
AA104B1B24474A76004D2810 /* HeadersH2ButtonsModel.swift */,
AA104B1924474A66004D2810 /* HeadersH2Buttons.swift */,
);
path = Headers;
sourceTree = "<group>";
@ -1248,6 +1272,8 @@
D20492F12434CB5F00A5EED6 /* FourColumn */,
AA4FC2A323F4F69600E251DB /* RightVariable */,
D22B38EB23F4E0AE00490EF6 /* LeftVariable */,
AAB7EDEE246ADA1600E54929 /* ListProgressBarThinModel.swift */,
AAB7EDF0246ADA2A00E54929 /* ListProgressBarThin.swift */,
);
path = List;
sourceTree = "<group>";
@ -1400,6 +1426,7 @@
D29DF0CE21E404D4003B2FB9 /* MVMCoreUI */ = {
isa = PBXGroup;
children = (
27F973512466071600CAB5C5 /* Behaviors */,
D2C78CD324252F4E00B69FDE /* Atomic */,
012A88EF23985E0100FE3DA1 /* CustomPrimitives */,
D2B18B7D236090D500A9AEDC /* BaseClasses */,
@ -1655,6 +1682,8 @@
0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */,
0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */,
0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */,
0A25209724645B76000FA9F6 /* TextViewEntryFieldModel.swift */,
0A25209524645AFD000FA9F6 /* TextViewEntryField.swift */,
);
path = TextFields;
sourceTree = "<group>";
@ -1725,8 +1754,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;
@ -1765,7 +1792,6 @@
D2B18B7D236090D500A9AEDC /* BaseClasses */ = {
isa = PBXGroup;
children = (
0A6682B4243769C700AD3CA1 /* TextViewModel.swift */,
0A6682B3243769C700AD3CA1 /* TextView.swift */,
C003506023AA94CD00B6AC29 /* Button.swift */,
D2B18B7E2360913400A9AEDC /* Control.swift */,
@ -1913,8 +1939,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 */,
@ -2044,10 +2068,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 */,
@ -2148,6 +2174,7 @@
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */,
D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */,
D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */,
27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */,
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */,
526A265E240D200500B0D828 /* ListTwoColumnCompareChanges.swift in Sources */,
8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */,
@ -2158,7 +2185,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 */,
@ -2200,6 +2226,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 */,
@ -2240,6 +2267,7 @@
D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */,
D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */,
D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */,
27F973532466074500CAB5C5 /* PageBehavior.swift in Sources */,
94C2D9A323872C110006CF46 /* LabelAttributeStrikeThroughModel.swift in Sources */,
D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */,
D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */,
@ -2251,10 +2279,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 */,
@ -2277,6 +2307,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 */,
@ -2284,6 +2315,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 */,

View File

@ -71,7 +71,7 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol {
}
public override func updateView(_ size: CGFloat) {
titleLabel?.font = MFStyler.fontB1()
titleLabel?.font = MFStyler.fontBoldBodySmall()
}
//------------------------------------------------------

View File

@ -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
}
}

View File

@ -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
}

View File

@ -6,9 +6,9 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
import UIKit
open class RadioSwatch: Control {
//--------------------------------------------------
// MARK: - Properties

View File

@ -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

View File

@ -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)
}

View File

@ -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?) {

View File

@ -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)

View 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
}
}
}

View File

@ -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)
}
}

View File

@ -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

View File

@ -13,7 +13,7 @@
//--------------------------------------------------
public let checkbox = Checkbox()
public let label = Label.commonLabelB2(true)
public let label = Label.createLabelRegularBodySmall(true)
//--------------------------------------------------
// MARK: - Properties

View File

@ -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)
}
@ -101,6 +101,7 @@ import UIKit
}
extension Line: MVMCoreUIViewConstrainingProtocol {
open func needsToBeConstrained() -> Bool {
return true
}

View File

@ -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)
})}

View File

@ -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,12 +194,16 @@ 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
try? ModelRegistry.register(ActionTopAlertModel.self)
try? ModelRegistry.register(ActionCollapseNotificationModel.self)
try? ModelRegistry.register(ActionOpenPanelModel.self)
// Behaviors
try? ModelRegistry.register(ScreenBrightnessModifierBehavior.self)
}
/// Convenience function to get required modules for a give model

View File

@ -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()
}
}

View File

@ -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)
}
}

View File

@ -12,6 +12,7 @@ import Foundation
//--------------------------------------------------
// MARK: - Outlets
//--------------------------------------------------
let headlineBody = HeadlineBody(frame: .zero)
//-------------------------------------------------------

View File

@ -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()

View File

@ -43,6 +43,7 @@ import Foundation
// MARK: - MFViewProtocol
open override func setupView() {
super.setupView()
rightImageView.shouldNotifyDelegateOnUpdate = false
addMolecule(stack)
stack.restack()
verticalStack.restack()

View File

@ -43,6 +43,7 @@ import Foundation
// MARK: - MFViewProtocol
open override func setupView() {
super.setupView()
rightImageView.shouldNotifyDelegateOnUpdate = false
addMolecule(stack)
stack.restack()
verticalStack.restack()

View File

@ -46,6 +46,7 @@ import Foundation
//-----------------------------------------------------
open override func setupView() {
super.setupView()
rightImage.shouldNotifyDelegateOnUpdate = false
addMolecule(stack)
stack.restack()
verticalStack.restack()

View File

@ -46,6 +46,7 @@ import Foundation
//-----------------------------------------------------
open override func setupView() {
super.setupView()
rightImage.shouldNotifyDelegateOnUpdate = false
addMolecule(stack)
stack.restack()
verticalStack.restack()

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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
}
}

View File

@ -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)

View File

@ -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
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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? {

View File

@ -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)
}
}

View File

@ -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

View File

@ -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>

View File

@ -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)
}
}

View File

@ -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 {

View File

@ -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)
}
}

View File

@ -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 {

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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()
}

View File

@ -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)
}
}

View File

@ -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]?) {

View File

@ -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

View File

@ -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 {

View File

@ -6,7 +6,6 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
import UIKit
public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtocol {

View File

@ -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)
}
//--------------------------------------------------

View File

@ -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
}

View File

@ -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

View File

@ -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 {

View File

@ -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?

View File

@ -1,14 +0,0 @@
//
// PanelNavigationItemModelProtocol.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 5/18/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol PanelNavigationItemModelProtocol {
var showLeftPanelButton: Bool { get set }
var showRightPanelButton: Bool { get set }
}

View File

@ -6,8 +6,6 @@
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
import UIKit
import MVMCore.MVMCoreViewProtocol

View File

@ -8,7 +8,6 @@
import Foundation
public protocol TemplateProtocol: AnyObject {
associatedtype TemplateModel: TemplateModelProtocol
var templateModel: TemplateModel? { get set }
@ -19,6 +18,7 @@ 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

View File

@ -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)
}
}

View File

@ -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() { }
}

View File

@ -209,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)
}

View File

@ -28,6 +28,7 @@ import Foundation
public var screenHeading: String?
public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)?
public var formRules: [FormGroupRule]?
public var behaviors: [PageBehaviorProtocol]?
//--------------------------------------------------
// MARK: - Initializer
@ -47,6 +48,7 @@ import Foundation
case screenHeading
case backgroundColor
case formRules
case behaviors
case navigationItem
}
@ -60,6 +62,7 @@ import Foundation
screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
formRules = try typeContainer.decodeIfPresent([FormGroupRule].self, forKey: .formRules)
behaviors = try typeContainer.decodeModelsIfPresent(codingKey: .behaviors)
navigationItem = try typeContainer.decodeModelIfPresent(codingKey: .navigationItem)
}

View File

@ -0,0 +1,9 @@
//
// BarButtonItem.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 5/18/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation

View File

@ -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() {

View File

@ -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()
}
}

View File

@ -9,6 +9,6 @@
import Foundation
public protocol MVMControllerModelProtocol: TemplateModelProtocol, FormHolderModelProtocol {
public protocol MVMControllerModelProtocol: TemplateModelProtocol, FormHolderModelProtocol, PageBehaviorsTemplateProtocol {
}

View File

@ -40,6 +40,7 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController {
createViewForTableHeader()
createViewForTableFooter()
tableView?.reloadData()
accessibilityElements = [tableView as Any]
}
override open func viewDidLoad() {

View File

@ -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
}
@ -264,9 +267,6 @@ import UIKit
// Presents from the bottom.
modalPresentationStyle = MVMCoreGetterUtility.isOnIPad() ? .formSheet : .overCurrentContext
// Create the default delegate object.
delegateObjectIVar = MVMCoreUIDelegateObject.create(withDelegateForAll: self)
// Do some initial loading.
if !initialLoadFinished {
initialLoadFinished = true
@ -310,6 +310,18 @@ import UIKit
MVMCoreUISession.sharedGlobal()?.currentPageType = pageType
MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self)
}
executeBehaviors { (behavior: PageVisibilityBehavior) in
behavior.onPageShown()
}
}
open override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
executeBehaviors { (behavior: PageVisibilityBehavior) in
behavior.onPageHidden()
}
}
deinit {
@ -424,4 +436,9 @@ import UIKit
selectedField = nil
}
}
// MARK: - Behavior Execution
func executeBehaviors<T>(_ behaviorBlock:(_ behavior:T)->Void) {
pageModel?.behaviors?.compactMap({ $0 as? T }).forEach({ behaviorBlock($0) })
}
}

View File

@ -0,0 +1,44 @@
//
// PageBehaviors.swift
// MVMCoreUI
//
// Created by Kyle on 5/8/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol PageBehaviorProtocol: ModelProtocol {
// The type of rule
var behaviorName: String { get }
}
public extension PageBehaviorProtocol {
var behaviorName: String {
get { return Self.identifier }
}
static var categoryCodingKey: String {
return "behaviorName"
}
static var categoryName: String {
return "\(PageBehaviorProtocol.self)"
}
}
public protocol PageVisibilityBehavior: PageBehaviorProtocol {
func onPageShown()
func onPageHidden()
}
public protocol PageBehaviorsTemplateProtocol {
var behaviors: [PageBehaviorProtocol]? { get }
}

View File

@ -0,0 +1,68 @@
//
// ScreenBrightnessModifierBehavior.swift
// MVMCoreUI
//
// Created by Kyle on 5/9/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
public class ScreenBrightnessModifierBehavior: PageVisibilityBehavior {
public static var identifier = "screenBrightnessModifier"
@Clamping(range: 0...1) var screenBrightness: CGFloat
var originalScreenBrightness: CGFloat?
//MARK:- PageVisibilityBehavior
public func onPageShown() {
changeScreenBrightness()
}
public func onPageHidden() {
restoreScreenBrightness()
}
//MARK:- Behavior
func changeScreenBrightness() {
guard originalScreenBrightness == nil else { return }
originalScreenBrightness = UIScreen.main.brightness
UIScreen.main.brightness = screenBrightness
NotificationCenter.default.addObserver(self, selector: #selector(willResignActive), name: UIApplication.willResignActiveNotification, object: nil)
}
func restoreScreenBrightness() {
guard let originalScreenBrightness = originalScreenBrightness else { return }
UIScreen.main.brightness = originalScreenBrightness
self.originalScreenBrightness = nil
NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil)
}
@objc func willResignActive() {
restoreScreenBrightness()
NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
}
@objc func didBecomeActive() {
NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
changeScreenBrightness()
}
//MARK:- Codable
private enum CodingKeys: String, CodingKey {
case screenBrightness
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
screenBrightness = try typeContainer.decode(CGFloat.self, forKey: .screenBrightness)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(screenBrightness, forKey: .screenBrightness)
}
}

View File

@ -57,7 +57,7 @@ import UIKit
// Update line.
if let navigationController = navigationController as? NavigationController {
navigationController.separatorView?.setStyle(navigationItemModel.line?.type ?? .standard)
navigationController.separatorView?.isHidden = navigationItemModel.line?.type ?? .standard == .none
}
// Update icons if main navigation controller.

View File

@ -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) {

View File

@ -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]
//--------------------------------------------------

View File

@ -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

View File

@ -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]
//--------------------------------------------------

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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

View File

@ -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 }

View File

@ -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";

View File

@ -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

View File

@ -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"];
});
}