This commit is contained in:
Subhankar Acharya 2020-05-15 22:15:31 +05:30
commit dccb36b96e
29 changed files with 606 additions and 437 deletions

View File

@ -68,6 +68,8 @@
0A21DB83235DFBC500C160A2 /* MdnEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A21DB82235DFBC500C160A2 /* MdnEntryField.swift */; }; 0A21DB83235DFBC500C160A2 /* MdnEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A21DB82235DFBC500C160A2 /* MdnEntryField.swift */; };
0A21DB91235E0EDB00C160A2 /* DigitBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */; }; 0A21DB91235E0EDB00C160A2 /* DigitBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */; };
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A21DB93235E24ED00C160A2 /* DigitEntryField.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 */; }; 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; };
0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */; }; 0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */; };
0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.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 */; }; 0A6682AA2435125F00AD3CA1 /* Styler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6682A92435125F00AD3CA1 /* Styler.swift */; };
0A6682AC243531C300AD3CA1 /* Padding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6682AB243531C300AD3CA1 /* Padding.swift */; }; 0A6682AC243531C300AD3CA1 /* Padding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6682AB243531C300AD3CA1 /* Padding.swift */; };
0A6682B5243769C700AD3CA1 /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6682B3243769C700AD3CA1 /* TextView.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 */; }; 0A69F611241BDEA700F7231B /* RuleAnyRequiredModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */; };
0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6BF4712360C56C0028F841 /* BaseDropdownEntryField.swift */; }; 0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6BF4712360C56C0028F841 /* BaseDropdownEntryField.swift */; };
0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; }; 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; };
@ -146,8 +147,6 @@
8DE5BECF2456F7B100772E76 /* ListTwoColumnDropdownSelectors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DE5BECE2456F7B100772E76 /* ListTwoColumnDropdownSelectors.swift */; }; 8DE5BECF2456F7B100772E76 /* ListTwoColumnDropdownSelectors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DE5BECE2456F7B100772E76 /* ListTwoColumnDropdownSelectors.swift */; };
8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */; }; 8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */; };
8DEFA95E243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.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 */; }; 942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */; };
942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */; }; 942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */; };
9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */; }; 9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */; };
@ -198,6 +197,8 @@
AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */; }; AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */; };
AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; }; AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; };
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.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 */; }; AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C10724346F4B00151545 /* RadioSwatches.swift */; };
AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C109243496DD00151545 /* RadioSwatch.swift */; }; AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB9C109243496DD00151545 /* RadioSwatch.swift */; };
AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */; }; AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */; };
@ -477,6 +478,8 @@
0A21DB7E235DECC500C160A2 /* EntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryField.swift; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleGuidelinesProtocol.swift; sourceTree = "<group>"; };
@ -485,7 +488,6 @@
0A6682A92435125F00AD3CA1 /* Styler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Styler.swift; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 0A7918F423F5E7EA00772FF4 /* ImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageView.swift; sourceTree = "<group>"; };
@ -560,8 +562,6 @@
8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDividerModel.swift; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntryFieldContainer.swift; sourceTree = "<group>"; };
@ -611,6 +611,8 @@
AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchCollectionViewCell.swift; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchesModel.swift; sourceTree = "<group>"; };
@ -1246,6 +1248,8 @@
D20492F12434CB5F00A5EED6 /* FourColumn */, D20492F12434CB5F00A5EED6 /* FourColumn */,
AA4FC2A323F4F69600E251DB /* RightVariable */, AA4FC2A323F4F69600E251DB /* RightVariable */,
D22B38EB23F4E0AE00490EF6 /* LeftVariable */, D22B38EB23F4E0AE00490EF6 /* LeftVariable */,
AAB7EDEE246ADA1600E54929 /* ListProgressBarThinModel.swift */,
AAB7EDF0246ADA2A00E54929 /* ListProgressBarThin.swift */,
); );
path = List; path = List;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1644,6 +1648,8 @@
0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */, 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */,
0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */, 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */,
0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */, 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */,
0A25209724645B76000FA9F6 /* TextViewEntryFieldModel.swift */,
0A25209524645AFD000FA9F6 /* TextViewEntryField.swift */,
); );
path = TextFields; path = TextFields;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1714,8 +1720,6 @@
94CA227924058533002D6750 /* VerizonNHGeDS-Regular.otf */, 94CA227924058533002D6750 /* VerizonNHGeDS-Regular.otf */,
94CA227824058533002D6750 /* VerizonNHGeTX-Bold.otf */, 94CA227824058533002D6750 /* VerizonNHGeTX-Bold.otf */,
94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */, 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */,
942C372D241149170066E45E /* NHaasGroteskDSStd-55Rg.otf */,
942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */,
D29DF31721ECECC0003B2FB9 /* OCRAExtended.ttf */, D29DF31721ECECC0003B2FB9 /* OCRAExtended.ttf */,
); );
path = Fonts; path = Fonts;
@ -1754,7 +1758,6 @@
D2B18B7D236090D500A9AEDC /* BaseClasses */ = { D2B18B7D236090D500A9AEDC /* BaseClasses */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0A6682B4243769C700AD3CA1 /* TextViewModel.swift */,
0A6682B3243769C700AD3CA1 /* TextView.swift */, 0A6682B3243769C700AD3CA1 /* TextView.swift */,
C003506023AA94CD00B6AC29 /* Button.swift */, C003506023AA94CD00B6AC29 /* Button.swift */,
D2B18B7E2360913400A9AEDC /* Control.swift */, D2B18B7E2360913400A9AEDC /* Control.swift */,
@ -1902,8 +1905,6 @@
D29DF32C21EE8736003B2FB9 /* Localizable.strings in Resources */, D29DF32C21EE8736003B2FB9 /* Localizable.strings in Resources */,
94CA227D24058534002D6750 /* VerizonNHGeDS-Regular.otf in Resources */, 94CA227D24058534002D6750 /* VerizonNHGeDS-Regular.otf in Resources */,
D29DF32E21EE8C3D003B2FB9 /* Media.xcassets 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 */, 94CA227E24058534002D6750 /* VerizonNHGeDS-Bold.otf in Resources */,
D287651A245B338E00CB882D /* VerizonNHGeTX-Regular.otf in Resources */, D287651A245B338E00CB882D /* VerizonNHGeTX-Regular.otf in Resources */,
D29DF31B21ECECC0003B2FB9 /* OCRAExtended.ttf in Resources */, D29DF31B21ECECC0003B2FB9 /* OCRAExtended.ttf in Resources */,
@ -2032,6 +2033,7 @@
943820842432382400B43AF3 /* WebView.swift in Sources */, 943820842432382400B43AF3 /* WebView.swift in Sources */,
0103B84E23D7E33A009C315C /* HeadlineBodyToggleModel.swift in Sources */, 0103B84E23D7E33A009C315C /* HeadlineBodyToggleModel.swift in Sources */,
D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */, D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */,
0A25209624645AFD000FA9F6 /* TextViewEntryField.swift in Sources */,
014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */, 014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */,
AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */, AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */,
011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */, 011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */,
@ -2144,7 +2146,6 @@
012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */, 012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */,
0A9D091E2433796500D2E6C0 /* NumericCarouselIndicatorModel.swift in Sources */, 0A9D091E2433796500D2E6C0 /* NumericCarouselIndicatorModel.swift in Sources */,
D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */, D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */,
0A6682B6243769C700AD3CA1 /* TextViewModel.swift in Sources */,
9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */, 9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */,
011D95A5240455DC000E3791 /* FormGroupRule.swift in Sources */, 011D95A5240455DC000E3791 /* FormGroupRule.swift in Sources */,
D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */, D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */,
@ -2186,6 +2187,7 @@
C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */, C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */,
01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */, 01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */,
D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */, D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */,
AAB7EDF1246ADA2A00E54929 /* ListProgressBarThin.swift in Sources */,
8D070BB2241B56AD0099AC56 /* ListRightVariableTotalData.swift in Sources */, 8D070BB2241B56AD0099AC56 /* ListRightVariableTotalData.swift in Sources */,
D264FAA5243F66A500D98315 /* CollectionTemplateItemProtocol.swift in Sources */, D264FAA5243F66A500D98315 /* CollectionTemplateItemProtocol.swift in Sources */,
D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */, D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */,
@ -2265,6 +2267,7 @@
AA26850C244840AE00CE34CC /* HeadersH2TinyButton.swift in Sources */, AA26850C244840AE00CE34CC /* HeadersH2TinyButton.swift in Sources */,
011D95AB2405C553000E3791 /* FormItemProtocol.swift in Sources */, 011D95AB2405C553000E3791 /* FormItemProtocol.swift in Sources */,
D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */, D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */,
0A25209824645B76000FA9F6 /* TextViewEntryFieldModel.swift in Sources */,
525019DD2406430800EED91C /* ListProgressBarDataModel.swift in Sources */, 525019DD2406430800EED91C /* ListProgressBarDataModel.swift in Sources */,
C6FA7D5223C77A4A00A3614A /* UnOrderedList.swift in Sources */, C6FA7D5223C77A4A00A3614A /* UnOrderedList.swift in Sources */,
01509D8F2327EC6F00EF99AA /* MoleculeTableViewCell.swift in Sources */, 01509D8F2327EC6F00EF99AA /* MoleculeTableViewCell.swift in Sources */,
@ -2272,6 +2275,7 @@
EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */, EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */,
0105618D224BBE7700E1557D /* FormValidator.swift in Sources */, 0105618D224BBE7700E1557D /* FormValidator.swift in Sources */,
01509D912327ECE600EF99AA /* CornerLabels.swift in Sources */, 01509D912327ECE600EF99AA /* CornerLabels.swift in Sources */,
AAB7EDEF246ADA1600E54929 /* ListProgressBarThinModel.swift in Sources */,
D21B7F75243BAC8900051ABF /* CarouselItem.swift in Sources */, D21B7F75243BAC8900051ABF /* CarouselItem.swift in Sources */,
C695A69823C990C200BFB94E /* DoughnutChartView.swift in Sources */, C695A69823C990C200BFB94E /* DoughnutChartView.swift in Sources */,
8D3BA9BD2433787000D341BA /* ListThreeColumnInternationalDataDividerModel.swift in Sources */, 8D3BA9BD2433787000D341BA /* ListThreeColumnInternationalDataDividerModel.swift in Sources */,

View File

@ -69,6 +69,7 @@ import UIKit
get { return entryFieldContainer.showError } get { return entryFieldContainer.showError }
set (error) { set (error) {
self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.feedback self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.feedback
self.feedbackLabel.textColor = error ? entryFieldModel?.errorTextColor?.uiColor ?? .mvmBlack : .mvmBlack
self.entryFieldContainer.showError = error self.entryFieldContainer.showError = error
self.entryFieldModel?.showError = error self.entryFieldModel?.showError = error
} }
@ -215,11 +216,10 @@ import UIKit
entryFieldContainer.refreshUI() entryFieldContainer.refreshUI()
} }
/** /// Intended to add the interactive content (i.e. textField) to the entryFieldContainer.
Method to override. @objc open func setupFieldContainerContent(_ container: UIView) {
Intended to add the interactive content (i.e. textField) to the entryFieldContainer. // To Be Overriden
*/ }
@objc open func setupFieldContainerContent(_ container: UIView) { }
@objc open override func updateView(_ size: CGFloat) { @objc open override func updateView(_ size: CGFloat) {
super.updateView(size) super.updateView(size)
@ -242,6 +242,7 @@ import UIKit
titleLabel.textColor = .mvmBlack titleLabel.textColor = .mvmBlack
feedbackLabel.font = Styler.Font.RegularMicro.getFont() feedbackLabel.font = Styler.Font.RegularMicro.getFont()
feedbackLabel.textColor = .mvmBlack feedbackLabel.textColor = .mvmBlack
entryFieldContainer.disableAllBorders = false
feedbackLabel.text = nil feedbackLabel.text = nil
entryFieldContainer.reset() entryFieldContainer.reset()
} }
@ -257,6 +258,7 @@ import UIKit
title = model.title title = model.title
feedback = model.feedback feedback = model.feedback
isEnabled = model.enabled isEnabled = model.enabled
entryFieldContainer.disableAllBorders = model.hideBorders
if let isLocked = model.locked { if let isLocked = model.locked {
self.isLocked = isLocked self.isLocked = isLocked

View File

@ -22,8 +22,10 @@ import Foundation
public var title: String? public var title: String?
public var feedback: String? public var feedback: String?
public var errorMessage: String? public var errorMessage: String?
public var errorTextColor: Color?
public var enabled: Bool = true public var enabled: Bool = true
public var showError: Bool? public var showError: Bool?
public var hideBorders = false
public var locked: Bool? public var locked: Bool?
public var selected: Bool? public var selected: Bool?
public var text: String? public var text: String?
@ -37,7 +39,7 @@ import Foundation
} }
/// Temporary binding mechanism for the view to update on enable changes. /// Temporary binding mechanism for the view to update on enable changes.
public var updateUI: (() -> ())? public var updateUI: ActionBlock?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
@ -50,9 +52,11 @@ import Foundation
case enabled case enabled
case feedback case feedback
case errorMessage case errorMessage
case errorTextColor
case locked case locked
case selected case selected
case showError case showError
case hideBorders
case text case text
case fieldKey case fieldKey
case groupName case groupName
@ -67,7 +71,12 @@ import Foundation
} }
public func setValidity(_ valid: Bool, rule: RulesProtocol) { public func setValidity(_ valid: Bool, rule: RulesProtocol) {
if let fieldKey = fieldKey,
let ruleErrorMessage = rule.errorMessage?[fieldKey] {
self.errorMessage = ruleErrorMessage
}
self.isValid = valid self.isValid = valid
} }
//-------------------------------------------------- //--------------------------------------------------
@ -89,10 +98,12 @@ import Foundation
title = try typeContainer.decodeIfPresent(String.self, forKey: .title) title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback) feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback)
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) 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 enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked) locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked)
selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected)
text = try typeContainer.decodeIfPresent(String.self, forKey: .text) text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
hideBorders = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideBorders) ?? false
baseValue = text baseValue = text
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
@ -111,8 +122,10 @@ import Foundation
try container.encodeIfPresent(locked, forKey: .locked) try container.encodeIfPresent(locked, forKey: .locked)
try container.encodeIfPresent(showError, forKey: .showError) try container.encodeIfPresent(showError, forKey: .showError)
try container.encodeIfPresent(selected, forKey: .selected) try container.encodeIfPresent(selected, forKey: .selected)
try container.encodeIfPresent(errorTextColor, forKey: .errorTextColor)
try container.encodeIfPresent(errorMessage, forKey: .errorMessage) try container.encodeIfPresent(errorMessage, forKey: .errorMessage)
try container.encode(enabled, forKey: .enabled) try container.encode(enabled, forKey: .enabled)
try container.encode(hideBorders, forKey: .hideBorders)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(groupName, forKey: .groupName)
} }

View File

@ -244,14 +244,21 @@ import UIKit
self.isValid = isValid self.isValid = isValid
if previousValidity && !isValid { if previousValidity && !isValid {
showError = true shouldShowError(true)
observingTextFieldDelegate?.isInvalid?(textfield: self)
} else if (!previousValidity && isValid) { } else if (!previousValidity && isValid) {
showError = false shouldShowError(false)
observingTextFieldDelegate?.isValid?(textfield: self) }
}
func shouldShowError(_ showError: Bool) {
self.showError = showError
if showError {
observingTextFieldDelegate?.isValid?(textfield: self)
entryFieldContainer.originalUI()
} else {
observingTextFieldDelegate?.isInvalid?(textfield: self)
} }
} }
/// Executes on UITextField.textDidBeginEditingNotification /// Executes on UITextField.textDidBeginEditingNotification
@objc func startEditing() { @objc func startEditing() {
isSelected = true isSelected = true
@ -268,10 +275,16 @@ import UIKit
/// Executes on UITextField.textDidEndEditingNotification /// Executes on UITextField.textDidEndEditingNotification
@objc func endInputing() { @objc func endInputing() {
resignFirstResponder() resignFirstResponder()
if isValid {
showError = false // Don't show error till user starts typing.
entryFieldContainer.bottomBar?.backgroundColor = UIColor.mvmBlack.cgColor 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?) { @objc public func dismissFieldInput(_ sender: Any?) {

View File

@ -31,6 +31,7 @@
public var placeholder: String? public var placeholder: String?
public var enabledTextColor: Color = Color(uiColor: .mvmBlack) public var enabledTextColor: Color = Color(uiColor: .mvmBlack)
public var disabledTextColor: Color = Color(uiColor: .mvmCoolGray3) public var disabledTextColor: Color = Color(uiColor: .mvmCoolGray3)
public var textAlignment: NSTextAlignment = .left
public var type: EntryType? public var type: EntryType?
//-------------------------------------------------- //--------------------------------------------------
@ -39,6 +40,7 @@
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case placeholder case placeholder
case textAlignment
case enabledTextColor case enabledTextColor
case disabledTextColor case disabledTextColor
case type case type
@ -51,6 +53,7 @@
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
try super.init(from: decoder) try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
placeholder = try typeContainer.decodeIfPresent(String.self, forKey: .placeholder) placeholder = try typeContainer.decodeIfPresent(String.self, forKey: .placeholder)
type = try typeContainer.decodeIfPresent(EntryType.self, forKey: .type) type = try typeContainer.decodeIfPresent(EntryType.self, forKey: .type)
@ -61,12 +64,17 @@
if let disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) { if let disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) {
self.disabledTextColor = 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 { public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(placeholder, forKey: .placeholder) try container.encodeIfPresent(placeholder, forKey: .placeholder)
try container.encodeIfPresent(textAlignment, forKey: .textAlignment)
try container.encode(enabledTextColor, forKey: .enabledTextColor) try container.encode(enabledTextColor, forKey: .enabledTextColor)
try container.encode(disabledTextColor, forKey: .disabledTextColor) try container.encode(disabledTextColor, forKey: .disabledTextColor)
try container.encodeIfPresent(type, forKey: .type) 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 // MVMCoreUI
// //
// Created by Kevin Christiano on 4/2/20. // Created by Kevin Christiano on 5/7/20.
// Copyright © 2020 Verizon Wireless. All rights reserved. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
import Foundation import UIKit
open class TextViewModel: TextEntryFieldModel { class TextViewEntryFieldModel: TextEntryFieldModel {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -19,26 +19,21 @@ open class TextViewModel: TextEntryFieldModel {
} }
public var accessibilityText: String? public var accessibilityText: String?
public var fontStyle: Styler.Font = Styler.Font.RegularBodySmall public var fontStyle: Styler.Font = Styler.Font.RegularBodyLarge
public var textAlignment: NSTextAlignment = .left
public var height: CGFloat? public var height: CGFloat?
public var placeholderTextColor: Color = Color(uiColor: .mvmCoolGray3) public var placeholderTextColor: Color = Color(uiColor: .mvmCoolGray3)
public var placeholderFontStyle: Styler.Font = Styler.Font.RegularMicro 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 editable: Bool = true
public var showsPlaceholder: Bool = false
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
//-------------------------------------------------- //--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case text
case accessibilityText case accessibilityText
case fontStyle case fontStyle
case textAlignment
case height case height
case hideBorders
case placeholderFontStyle case placeholderFontStyle
case placeholderTextColor case placeholderTextColor
case editable case editable
@ -60,22 +55,14 @@ open class TextViewModel: TextEntryFieldModel {
self.placeholderTextColor = placeholderTextColor self.placeholderTextColor = placeholderTextColor
} }
if let textAlignment = try typeContainer.decodeIfPresent(NSTextAlignment.self, forKey: .textAlignment) { if let fontStyle = try typeContainer.decodeIfPresent(Styler.Font.self, forKey: .fontStyle) {
self.textAlignment = textAlignment self.fontStyle = fontStyle
}
if let hideBorders = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideBorders) {
self.hideBorders = hideBorders
} }
if let editable = try typeContainer.decodeIfPresent(Bool.self, forKey: .editable) { if let editable = try typeContainer.decodeIfPresent(Bool.self, forKey: .editable) {
self.editable = 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) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
height = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .height) 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(accessibilityText, forKey: .accessibilityText)
try container.encodeIfPresent(height, forKey: .height) try container.encodeIfPresent(height, forKey: .height)
try container.encode(fontStyle, forKey: .fontStyle) try container.encode(fontStyle, forKey: .fontStyle)
try container.encode(hideBorders, forKey: .hideBorders) try container.encode(editable, forKey: .editable)
try container.encode(text, forKey: .text)
try container.encode(placeholderFontStyle, forKey: .placeholderFontStyle) try container.encode(placeholderFontStyle, forKey: .placeholderFontStyle)
try container.encode(placeholderTextColor, forKey: .placeholderTextColor) try container.encode(placeholderTextColor, forKey: .placeholderTextColor)
try container.encode(textAlignment, forKey: .textAlignment)
try container.encode(editable, forKey: .editable)
} }
} }

View File

@ -32,16 +32,16 @@ import UIKit
switch style { switch style {
case .standard: case .standard:
updateLineConstraints(constant: 1) updateLineConstraints(constant: 1)
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mfSilver() backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmCoolGray3
case .thin: case .thin:
updateLineConstraints(constant: 1) updateLineConstraints(constant: 1)
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .black backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack
case .medium: case .medium:
updateLineConstraints(constant: 2) updateLineConstraints(constant: 2)
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .black backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack
case .heavy: case .heavy:
updateLineConstraints(constant: 4) updateLineConstraints(constant: 4)
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .black backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack
case .none: case .none:
updateLineConstraints(constant: 0) updateLineConstraints(constant: 0)
} }
@ -97,6 +97,7 @@ import UIKit
} }
extension Line: MVMCoreUIViewConstrainingProtocol { extension Line: MVMCoreUIViewConstrainingProtocol {
open func needsToBeConstrained() -> Bool { open func needsToBeConstrained() -> Bool {
return true return true
} }

View File

@ -12,6 +12,7 @@ import UIKit
public let loadingSpinner = MFLoadingSpinner(frame: .zero) public let loadingSpinner = MFLoadingSpinner(frame: .zero)
public let imageView = MFTransparentGIFView(frame: .zero) public let imageView = MFTransparentGIFView(frame: .zero)
public var addSizeConstraintsForAspectRatio = false public var addSizeConstraintsForAspectRatio = false
public var shouldNotifyDelegateOnUpdate = true
var centerX: NSLayoutConstraint? var centerX: NSLayoutConstraint?
var centerY: NSLayoutConstraint? var centerY: NSLayoutConstraint?
var widthConstraint: NSLayoutConstraint? var widthConstraint: NSLayoutConstraint?
@ -264,16 +265,15 @@ import UIKit
} }
let finishedLoadingBlock: MVMCoreGetImageBlock = {[weak self] (image, data, isFallbackImage) in MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in let finishedLoadingBlock: MVMCoreGetImageBlock = {[weak self] (image, data, isFallbackImage) in MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in
guard let loadingImageName = self?.currentImageName, loadingImageName == imageName else { guard let self = self,
return let loadingImageName = self.currentImageName, loadingImageName == imageName else { return }
} self.isFallbackImage = isFallbackImage
self?.isFallbackImage = isFallbackImage self.loadingSpinner.pause()
self?.loadingSpinner.pause() let layoutWillChange = self.shouldNotifyDelegateOnUpdate ? self.layoutWillChange(width: self.currentImageWidth, height: self.currentImageHeight, size: image?.size) : false
let layoutWillChange = self?.layoutWillChange(width: self?.currentImageWidth, height: self?.currentImageHeight, size: image?.size) ?? false self.addConstraints(width: width, height: height, size: image?.size)
self?.addConstraints(width: width, height: height, size: image?.size) self.loadingSpinnerHeightConstraint?.constant = 0
self?.loadingSpinnerHeightConstraint?.constant = 0
if layoutWillChange { if layoutWillChange {
self?.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self!) self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
} }
completionBlock(image,data,isFallbackImage) completionBlock(image,data,isFallbackImage)
})} })}

View File

@ -52,7 +52,7 @@ import Foundation
try? ModelRegistry.register(LabelAttributeActionModel.self) try? ModelRegistry.register(LabelAttributeActionModel.self)
// TextView // TextView
MoleculeObjectMapping.shared()?.register(viewClass: TextView.self, viewModelClass: TextViewModel.self) MoleculeObjectMapping.shared()?.register(viewClass: TextViewEntryField.self, viewModelClass: TextViewEntryFieldModel.self)
// Buttons // Buttons
MoleculeObjectMapping.shared()?.register(viewClass: PillButton.self, viewModelClass: ButtonModel.self) 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: ListThreeColumnInternationalData.self, viewModelClass: ListThreeColumnInternationalDataModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnDataUsage.self, viewModelClass: ListThreeColumnDataUsageModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnDataUsage.self, viewModelClass: ListThreeColumnDataUsageModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListProgressBarThin.self, viewModelClass: ListProgressBarThinModel.self)
// Designed Section Dividers // Designed Section Dividers
MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self)

View File

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

View File

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

View File

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

View File

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

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

@ -9,7 +9,7 @@
import UIKit import UIKit
@objc open class TextView: UITextView, UITextViewDelegate, MVMCoreViewProtocol { @objc open class TextView: UITextView, MVMCoreViewProtocol, MoleculeViewProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -19,87 +19,18 @@ import UIKit
private var initialSetupPerformed = false private var initialSetupPerformed = false
/// If true then text textView is currently displaying the stored placeholder text as there is not content to display. /// If true then text textView is currently displaying the stored placeholder text as there is not content to display.
public var isShowingPlaceholder: Bool = false { public var isShowingPlaceholder: Bool = false
didSet { textViewModel?.showsPlaceholder = isShowingPlaceholder }
}
/// Set to true to hide the blinking textField cursor. /// Set to true to hide the blinking textField cursor.
public var hideBlinkingCaret = false public var hideBlinkingCaret = false
public var textViewModel: TextViewModel? { public var placeholder = ""
return model as? TextViewModel public var fontStyle: Styler.Font = Styler.Font.RegularBodyLarge
} public var placeholderFontStyle: Styler.Font = Styler.Font.RegularMicro
public var placeholderTextColor: UIColor = .mvmCoolGray3
//-------------------------------------------------- public var isEnabled: Bool = true {
// MARK: - Drawing Properties didSet { isUserInteractionEnabled = isEnabled }
//--------------------------------------------------
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
}
}
} }
//-------------------------------------------------- //--------------------------------------------------
@ -109,26 +40,6 @@ import UIKit
/// Holds a reference to the delegating class so this class can internally influence the TextField behavior as well. /// Holds a reference to the delegating class so this class can internally influence the TextField behavior as well.
public weak var didDeleteDelegate: TextInputDidDeleteProtocol? 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 // MARK: - Initialization
//-------------------------------------------------- //--------------------------------------------------
@ -147,11 +58,6 @@ import UIKit
initialSetup() initialSetup()
} }
convenience init(delegate: UITextViewDelegate) {
self.init(frame: .zero, textContainer: nil)
self.delegate = delegate
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Lifecycle // MARK: - Lifecycle
//-------------------------------------------------- //--------------------------------------------------
@ -166,172 +72,53 @@ import UIKit
} }
open func updateView(_ size: CGFloat) { open func updateView(_ size: CGFloat) {
font = (isShowingPlaceholder ? placeholderFontStyle : fontStyle).getFont()
setNeedsDisplay()
} }
/// Will be called only once. /// Will be called only once.
open func setupView() { open func setupView() {
translatesAutoresizingMaskIntoConstraints = false translatesAutoresizingMaskIntoConstraints = false
initialConfiguration() defaultConfiguration()
} }
public func initialConfiguration() { public func defaultConfiguration() {
text = ""
placeholder = ""
textAlignment = .left
insetsLayoutMarginsFromSafeArea = false insetsLayoutMarginsFromSafeArea = false
showsVerticalScrollIndicator = false showsVerticalScrollIndicator = false
showsHorizontalScrollIndicator = false showsHorizontalScrollIndicator = false
isSecureTextEntry = false isSecureTextEntry = false
textContainerInset = UIEdgeInsets(top: Padding.Three, left: Padding.Three, bottom: Padding.Three, right: Padding.Three)
backgroundColor = .mvmWhite backgroundColor = .mvmWhite
clipsToBounds = true clipsToBounds = true
smartQuotesType = .no smartQuotesType = .no
smartDashesType = .no smartDashesType = .no
smartInsertDeleteType = .no smartInsertDeleteType = .no
inputAccessoryView = nil inputAccessoryView = nil
font = textViewModel?.fontStyle.getFont() isAccessibilityElement = true
accessibilityTraits = .staticText
font = fontStyle.getFont()
keyboardType = .default
isEditable = true isEditable = true
isOpaque = false
} }
open func reset() { open func reset() {
fontStyle = Styler.Font.RegularBodyLarge
placeholderFontStyle = Styler.Font.RegularMicro
placeholderTextColor = .mvmCoolGray3
textColor = .mvmBlack
isEnabled = true
text = "" text = ""
isShowingPlaceholder = false
inputAccessoryView?.removeFromSuperview() inputAccessoryView?.removeFromSuperview()
inputAccessoryView = nil defaultConfiguration()
initialConfiguration()
}
open override func layoutSubviews() {
super.layoutSubviews()
setNeedsDisplay()
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Draw // MARK: - TextInputDidDeleteProtocol
//--------------------------------------------------
/// 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
//-------------------------------------------------- //--------------------------------------------------
/// Alters the blinking caret line as per design standards. /// Alters the blinking caret line as per design standards.
@ -350,141 +137,49 @@ import UIKit
didDeleteDelegate?.textInputDidDelete() didDeleteDelegate?.textInputDidDelete()
} }
public func setTextAppearance() { //--------------------------------------------------
// MARK: - Text / Placeholder
//--------------------------------------------------
open override func becomeFirstResponder() -> Bool {
if isShowingPlaceholder { if isShowingPlaceholder {
setTextContentTraits() setTextContentTraits()
} }
return super.becomeFirstResponder()
}
open override func resignFirstResponder() -> Bool {
setPlaceholderIfAvailable()
return super.resignFirstResponder()
} }
public func setPlaceholderIfAvailable() { public func setPlaceholderIfAvailable() {
if let placeholder = textViewModel?.placeholder, !placeholder.isEmpty && text.isEmpty { if !placeholder.isEmpty && text.isEmpty {
setPlaceholderContentTraits() setPlaceholderContentTraits()
} }
} }
public func setTextContentTraits() { open func setTextContentTraits() {
isShowingPlaceholder = false isShowingPlaceholder = false
text = "" text = ""
font = textViewModel?.fontStyle.getFont() font = fontStyle.getFont()
textColor = textViewModel?.enabledTextColor.uiColor textColor = .mvmBlack
} }
public func setPlaceholderContentTraits() { open func setPlaceholderContentTraits() {
isShowingPlaceholder = true isShowingPlaceholder = true
textColor = textViewModel?.placeholderTextColor.uiColor textColor = placeholderTextColor
font = textViewModel?.placeholderFontStyle.getFont() font = placeholderFontStyle.getFont()
text = textViewModel?.placeholder text = placeholder
} }
@objc func dismissFieldInput(_ sender: TextView) { @objc open func dismissFieldInput(_ sender: TextView) {
resignFirstResponder() _ = 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
}
} }
} }

View File

@ -58,7 +58,7 @@ import UIKit
if navigationController == MVMCoreUISession.sharedGlobal()?.navigationController, if navigationController == MVMCoreUISession.sharedGlobal()?.navigationController,
navigationController.topViewController == viewController { navigationController.topViewController == viewController {
// Update line. // Update line.
MVMCoreUISession.sharedGlobal()?.navigationController?.separatorView?.setStyle(navigationItemModel.line?.type ?? .standard) MVMCoreUISession.sharedGlobal()?.navigationController?.separatorView?.isHidden = navigationItemModel.line?.type ?? .standard == .none
} }
if navigationController == MVMCoreUISplitViewController.main()?.navigationController, if navigationController == MVMCoreUISplitViewController.main()?.navigationController,

View File

@ -15,6 +15,7 @@ public class RuleAllValueChangedModel: RulesProtocol {
public static var identifier: String = "allValueChanged" public static var identifier: String = "allValueChanged"
public var type: String = RuleAllValueChangedModel.identifier public var type: String = RuleAllValueChangedModel.identifier
public var errorMessage: [String: String]?
public var fields: [String] public var fields: [String]
//-------------------------------------------------- //--------------------------------------------------

View File

@ -17,6 +17,7 @@ public class RuleAnyRequiredModel: RulesProtocol {
public static var identifier: String = "anyRequired" public static var identifier: String = "anyRequired"
public var type: String = RuleRequiredModel.identifier public var type: String = RuleRequiredModel.identifier
public var fields: [String] public var fields: [String]
public var errorMessage: [String: String]?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Methods // MARK: - Methods

View File

@ -16,6 +16,7 @@ public class RuleAnyValueChangedModel: RulesProtocol {
public static var identifier: String = "anyValueChanged" public static var identifier: String = "anyValueChanged"
public var type: String = RuleAnyValueChangedModel.identifier public var type: String = RuleAnyValueChangedModel.identifier
public var errorMessage: [String: String]?
public var fields: [String] public var fields: [String]
//-------------------------------------------------- //--------------------------------------------------

View File

@ -17,6 +17,7 @@ public class RuleEqualsModel: RulesProtocol {
public static var identifier: String = "equals" public static var identifier: String = "equals"
public var type: String = RuleEqualsModel.identifier public var type: String = RuleEqualsModel.identifier
public var fields: [String] public var fields: [String]
public var errorMessage: [String: String]?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Validation // MARK: - Validation
@ -27,9 +28,9 @@ public class RuleEqualsModel: RulesProtocol {
} }
public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
var valid = true var valid = true
var compareValue: AnyHashable? var compareValue: AnyHashable?
for formKey in fields { for formKey in fields {
guard let formField = fieldMolecules[formKey] else { continue } guard let formField = fieldMolecules[formKey] else { continue }
@ -37,13 +38,16 @@ public class RuleEqualsModel: RulesProtocol {
compareValue = formField.formFieldValue() compareValue = formField.formFieldValue()
continue continue
} }
if compareValue != formField.formFieldValue() { if compareValue != formField.formFieldValue() {
valid = false valid = false
(formField as? FormRuleWatcherFieldProtocol)?.setValidity(valid, rule: self)
break 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 type: String = RuleRegexModel.identifier
public var fields: [String] public var fields: [String]
public var regex: String public var regex: String
public var errorMessage: [String: String]?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties

View File

@ -16,6 +16,7 @@ public class RuleRequiredModel: RulesProtocol {
public static var identifier: String = "allRequired" public static var identifier: String = "allRequired"
public var type: String = RuleRequiredModel.identifier public var type: String = RuleRequiredModel.identifier
public var errorMessage: [String: String]?
public var fields: [String] public var fields: [String]
//-------------------------------------------------- //--------------------------------------------------

View File

@ -16,7 +16,9 @@ public enum RulesCodingKey: String, CodingKey {
public protocol RulesProtocol: ModelProtocol { public protocol RulesProtocol: ModelProtocol {
// The type of rule // The type of rule
var type: String { get } var type: String { get }
var errorMessage: [String: String]? { get }
// The fields that this rule applies to. // The fields that this rule applies to.
var fields: [String] { get set } var fields: [String] { get set }

View File

@ -14,9 +14,6 @@ extern NSString * _Nonnull const DSBold;
extern NSString * _Nonnull const DSRegular; extern NSString * _Nonnull const DSRegular;
extern NSString * _Nonnull const TXBold; extern NSString * _Nonnull const TXBold;
extern NSString * _Nonnull const TXRegular; extern NSString * _Nonnull const TXRegular;
//2.0 font
extern NSString * _Nonnull const DS75Bd;
extern NSString * _Nonnull const DS55Rg;
@interface MFFonts : NSObject @interface MFFonts : NSObject

View File

@ -17,11 +17,6 @@ NSString * const DSRegular = @"VerizonNHGeDS-Regular";
NSString * const TXBold = @"VerizonNHGeTX-Bold"; NSString * const TXBold = @"VerizonNHGeTX-Bold";
NSString * const TXRegular = @"VerizonNHGeTX-Regular"; NSString * const TXRegular = @"VerizonNHGeTX-Regular";
//2.0 font
NSString * const DS75Bd = @"NHaasGroteskDSStd-75Bd";
NSString * const DS55Rg = @"NHaasGroteskDSStd-55Rg";
@implementation MFFonts @implementation MFFonts
+ (void)loadMVMFonts { + (void)loadMVMFonts {
@ -31,8 +26,6 @@ NSString * const DS55Rg = @"NHaasGroteskDSStd-55Rg";
[MFFonts loadFont:DSRegular type:@"otf"]; [MFFonts loadFont:DSRegular type:@"otf"];
[MFFonts loadFont:TXBold type:@"otf"]; [MFFonts loadFont:TXBold type:@"otf"];
[MFFonts loadFont:TXRegular type:@"otf"]; [MFFonts loadFont:TXRegular type:@"otf"];
[MFFonts loadFont:DS75Bd type:@"otf"];
[MFFonts loadFont:DS55Rg type:@"otf"];
[MFFonts loadFont:@"OCRAExtended" type:@"ttf"]; [MFFonts loadFont:@"OCRAExtended" type:@"ttf"];
}); });
} }