merging
This commit is contained in:
commit
9503f109f9
@ -94,6 +94,7 @@
|
||||
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; };
|
||||
0A7ECC5D243CE85300C828E8 /* DoughnutChartItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */; };
|
||||
0A7ECC5F243CEB1200C828E8 /* ColorViewWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.swift */; };
|
||||
0A7ECC702441001C00C828E8 /* UIToolbar+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */; };
|
||||
0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */; };
|
||||
0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */; };
|
||||
0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */; };
|
||||
@ -108,6 +109,8 @@
|
||||
0A9D09212433796500D2E6C0 /* CarouselIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D091B2433796500D2E6C0 /* CarouselIndicatorModel.swift */; };
|
||||
0A9D09222433796500D2E6C0 /* CarouselIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D091C2433796500D2E6C0 /* CarouselIndicator.swift */; };
|
||||
0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B392398524F0067DD0F /* Toggle.swift */; };
|
||||
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */; };
|
||||
0AB764D324460FA400E7FE72 /* UIPickerView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */; };
|
||||
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; };
|
||||
0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; };
|
||||
0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; };
|
||||
@ -148,6 +151,8 @@
|
||||
8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */; };
|
||||
8DD1E36E243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */; };
|
||||
8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */; };
|
||||
8DDD6C1D244D90B8006A2232 /* ListThreeColumnDataUsage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DDD6C1C244D90B8006A2232 /* ListThreeColumnDataUsage.swift */; };
|
||||
8DDD6C1F244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DDD6C1E244D90E1006A2232 /* ListThreeColumnDataUsageModel.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 */; };
|
||||
@ -157,7 +162,7 @@
|
||||
9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */; };
|
||||
943784F5236B77BB006A1E82 /* Wheel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* Wheel.swift */; };
|
||||
943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */; };
|
||||
943820842432382400B43AF3 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943820832432382400B43AF3 /* WebView.swift */; };
|
||||
943820842432382400B43AF3 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943820832432382400B43AF3 /* WebView.swift */; };
|
||||
94382086243238D100B43AF3 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94382085243238D100B43AF3 /* WebViewModel.swift */; };
|
||||
9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */; };
|
||||
9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890D2385C3F800DE9FD4 /* MultiProgressModel.swift */; };
|
||||
@ -205,6 +210,8 @@
|
||||
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 */; };
|
||||
BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; };
|
||||
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */; };
|
||||
BB2C968F24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */; };
|
||||
BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */; };
|
||||
BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */; };
|
||||
@ -536,6 +543,7 @@
|
||||
0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxLabel.swift; sourceTree = "<group>"; };
|
||||
0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoughnutChartItemModel.swift; sourceTree = "<group>"; };
|
||||
0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorViewWithLabel.swift; sourceTree = "<group>"; };
|
||||
0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIToolbar+Extension.swift"; sourceTree = "<group>"; };
|
||||
0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryFieldModel.swift; sourceTree = "<group>"; };
|
||||
0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEntryFieldModel.swift; sourceTree = "<group>"; };
|
||||
0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MdnEntryFieldModel.swift; sourceTree = "<group>"; };
|
||||
@ -552,6 +560,8 @@
|
||||
0A9D091C2433796500D2E6C0 /* CarouselIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CarouselIndicator.swift; sourceTree = "<group>"; };
|
||||
0AA33B33239813C50067DD0F /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = "<group>"; };
|
||||
0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = "<group>"; };
|
||||
0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIDatePicker+Extension.swift"; sourceTree = "<group>"; };
|
||||
0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIPickerView+Extension.swift"; sourceTree = "<group>"; };
|
||||
0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryField.swift; sourceTree = "<group>"; };
|
||||
0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryField.swift; sourceTree = "<group>"; };
|
||||
0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; };
|
||||
@ -592,6 +602,8 @@
|
||||
8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeAllTextAndLinks.swift; sourceTree = "<group>"; };
|
||||
8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnInternationalDataModel.swift; sourceTree = "<group>"; };
|
||||
8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnInternationalData.swift; sourceTree = "<group>"; };
|
||||
8DDD6C1C244D90B8006A2232 /* ListThreeColumnDataUsage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsage.swift; sourceTree = "<group>"; };
|
||||
8DDD6C1E244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageModel.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>"; };
|
||||
9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = "<group>"; };
|
||||
@ -648,6 +660,8 @@
|
||||
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>"; };
|
||||
BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = "<group>"; };
|
||||
BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMedium.swift; sourceTree = "<group>"; };
|
||||
BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinksModel.swift; sourceTree = "<group>"; };
|
||||
BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableTextLinkAllTextAndLinks.swift; sourceTree = "<group>"; };
|
||||
BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsectionModel.swift; sourceTree = "<group>"; };
|
||||
@ -1091,6 +1105,8 @@
|
||||
children = (
|
||||
8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */,
|
||||
8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */,
|
||||
8DDD6C1E244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift */,
|
||||
8DDD6C1C244D90B8006A2232 /* ListThreeColumnDataUsage.swift */,
|
||||
);
|
||||
path = ThreeColumn;
|
||||
sourceTree = "<group>";
|
||||
@ -1159,6 +1175,9 @@
|
||||
D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */,
|
||||
D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */,
|
||||
013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */,
|
||||
0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */,
|
||||
0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */,
|
||||
0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
@ -1172,6 +1191,15 @@
|
||||
path = FourColumn;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D20FFFB42451E32100A31DA2 /* Device */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */,
|
||||
BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */,
|
||||
);
|
||||
path = Device;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D213347423842FE3008E41B3 /* Controllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1370,6 +1398,7 @@
|
||||
D22B38EA23F4E08B00490EF6 /* List */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D20FFFB42451E32100A31DA2 /* Device */,
|
||||
52267A0523FFE0A900906CBA /* OneColumn */,
|
||||
D22D8396241FDE4700D3DF69 /* TwoColumn */,
|
||||
8DD1E36C243B3CD900D8F2DF /* ThreeColumn */,
|
||||
@ -2170,6 +2199,7 @@
|
||||
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */,
|
||||
D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */,
|
||||
AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */,
|
||||
BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */,
|
||||
D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */,
|
||||
D28A837B23C928DA00DFE4FC /* MoleculeListCellProtocol.swift in Sources */,
|
||||
014AA72F23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift in Sources */,
|
||||
@ -2206,6 +2236,7 @@
|
||||
014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */,
|
||||
AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */,
|
||||
011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */,
|
||||
8DDD6C1D244D90B8006A2232 /* ListThreeColumnDataUsage.swift in Sources */,
|
||||
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */,
|
||||
D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */,
|
||||
944589232385DA9600DE9FD4 /* ImageViewModel.swift in Sources */,
|
||||
@ -2214,6 +2245,7 @@
|
||||
525019DE2406430800EED91C /* ListProgressBarData.swift in Sources */,
|
||||
D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */,
|
||||
012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */,
|
||||
8DDD6C1F244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift in Sources */,
|
||||
BB55B51F244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift in Sources */,
|
||||
D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */,
|
||||
D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */,
|
||||
@ -2248,6 +2280,7 @@
|
||||
AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */,
|
||||
D2B18B812360945C00A9AEDC /* View.swift in Sources */,
|
||||
C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */,
|
||||
0A7ECC702441001C00C828E8 /* UIToolbar+Extension.swift in Sources */,
|
||||
D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */,
|
||||
525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */,
|
||||
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */,
|
||||
@ -2354,6 +2387,7 @@
|
||||
012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */,
|
||||
D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */,
|
||||
0AE14F64238315D2005417F8 /* TextField.swift in Sources */,
|
||||
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */,
|
||||
D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */,
|
||||
D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */,
|
||||
C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */,
|
||||
@ -2419,6 +2453,7 @@
|
||||
D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */,
|
||||
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
|
||||
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
|
||||
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */,
|
||||
D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */,
|
||||
0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */,
|
||||
0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */,
|
||||
@ -2435,6 +2470,7 @@
|
||||
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */,
|
||||
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */,
|
||||
012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */,
|
||||
0AB764D324460FA400E7FE72 /* UIPickerView+Extension.swift in Sources */,
|
||||
D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */,
|
||||
94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */,
|
||||
011D95AB2405C553000E3791 /* FormItemProtocol.swift in Sources */,
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
import UIKit
|
||||
|
||||
@objcMembers public class ActionCollapseNotificationModel: ActionModelProtocol {
|
||||
|
||||
public static var identifier: String = "collapseNotification"
|
||||
public var actionType: String
|
||||
public var extraParameters: JSONValueDictionary?
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
public class ActionOpenPanelModel: ActionModelProtocol {
|
||||
|
||||
|
||||
public enum Panel: String, Codable {
|
||||
case left
|
||||
case right
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class ActionTopAlertModel: ActionModelProtocol {
|
||||
|
||||
public static var identifier: String = "topAlert"
|
||||
public var actionType: String = ActionTopAlertModel.identifier
|
||||
public var pageType: String
|
||||
|
||||
@ -69,7 +69,7 @@ import UIKit
|
||||
textFieldTrailingConstraint = dropDownCaretView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 6)
|
||||
textFieldTrailingConstraint?.isActive = true
|
||||
|
||||
container.trailingAnchor.constraint(equalTo: dropDownCaretView.trailingAnchor, constant: 16).isActive = true
|
||||
container.trailingAnchor.constraint(equalTo: dropDownCaretView.trailingAnchor, constant: Padding.Four).isActive = true
|
||||
dropDownCaretView.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
|
||||
}
|
||||
|
||||
|
||||
@ -31,10 +31,9 @@ import UIKit
|
||||
return formatter
|
||||
}()
|
||||
|
||||
/// Update the property value to alter the format of how the date is presented.
|
||||
public var dateFormat: String = "MMM d, y" {
|
||||
didSet {
|
||||
dateFormatter.dateFormat = dateFormat
|
||||
}
|
||||
didSet { dateFormatter.dateFormat = dateFormat }
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -69,10 +68,10 @@ import UIKit
|
||||
public override func setupFieldContainerContent(_ container: UIView) {
|
||||
super.setupFieldContainerContent(container)
|
||||
|
||||
datePicker = MVMCoreUICommonViewsUtility.addDatePicker(to: textField)
|
||||
datePicker = UIDatePicker.addDatePicker(to: textField)
|
||||
datePicker?.addTarget(self, action: #selector(pickerValueChanged), for: .valueChanged)
|
||||
datePicker?.timeZone = NSTimeZone.system
|
||||
MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: self)
|
||||
UIToolbar.addDismissToolbar(to: textField, delegate: self, action: #selector(dismissFieldInput))
|
||||
}
|
||||
|
||||
@objc public func setDatePickerDuration(from startDate: Date?, to endDate: Date?, showStartDate: Bool = true) {
|
||||
@ -104,7 +103,7 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
@objc override func dismissFieldInput(_ sender: Any?) {
|
||||
@objc public override func dismissFieldInput(_ sender: Any?) {
|
||||
|
||||
setTextWith(date: datePicker?.date)
|
||||
super.dismissFieldInput(sender)
|
||||
|
||||
@ -22,24 +22,25 @@
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case dateFormat
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
try super.init(from: decoder)
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
dateFormat = try typeContainer.decodeIfPresent(String.self, forKey: .dateFormat) ?? "MMM d, y"
|
||||
|
||||
if let dateFormat = try typeContainer.decodeIfPresent(String.self, forKey: .dateFormat) {
|
||||
self.dateFormat = dateFormat
|
||||
}
|
||||
}
|
||||
|
||||
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(dateFormat, forKey: .dateFormat)
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,7 +211,9 @@ import UIKit
|
||||
|
||||
let digitBox = DigitBox()
|
||||
digitBox.isAccessibilityElement = true
|
||||
digitBox.digitField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: self)
|
||||
let observingDelegate = delegateObject?.observingTextFieldDelegate ?? self
|
||||
digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
|
||||
action: #selector(observingDelegate.dismissFieldInput))
|
||||
digitBox.digitField.delegate = self
|
||||
digitBox.digitBoxDelegate = self
|
||||
return digitBox
|
||||
@ -246,15 +248,6 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
@objc public override func defaultValidationBlock() {
|
||||
|
||||
validationBlock = { enteredValue in
|
||||
guard let enteredValue = enteredValue else { return false }
|
||||
|
||||
return enteredValue.count > 0 && enteredValue.count == self.digitBoxes.count
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func selectPreviousDigitField(_ currentTextField: UITextField?, clear: Bool) {
|
||||
|
||||
var selectPreviousField = false
|
||||
@ -322,7 +315,7 @@ import UIKit
|
||||
return true
|
||||
}
|
||||
|
||||
@objc override func dismissFieldInput(_ sender: Any?) {
|
||||
@objc public override func dismissFieldInput(_ sender: Any?) {
|
||||
|
||||
digitBoxes.forEach {
|
||||
if $0.isSelected {
|
||||
@ -337,12 +330,18 @@ import UIKit
|
||||
guard let model = model as? DigitEntryFieldModel else { return }
|
||||
|
||||
numberOfDigits = model.digits
|
||||
setAsSecureTextEntry(model.secureEntry)
|
||||
|
||||
for digitBox in digitBoxes {
|
||||
digitBox.digitField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: delegateObject?.observingTextFieldDelegate ?? self)
|
||||
if let entryType = model.type {
|
||||
setAsSecureTextEntry(entryType == .secure || entryType == .password)
|
||||
}
|
||||
|
||||
let observingDelegate = delegateObject?.observingTextFieldDelegate ?? self
|
||||
|
||||
digitBoxes.forEach {
|
||||
$0.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
|
||||
action: #selector(observingDelegate.dismissFieldInput))
|
||||
}
|
||||
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
|
||||
@ -17,34 +17,31 @@
|
||||
}
|
||||
|
||||
public var digits: Int = 4
|
||||
public var secureEntry: Bool = false
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case digits
|
||||
case secureEntry
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
try super.init(from: decoder)
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
digits = try typeContainer.decodeIfPresent(Int.self, forKey: .digits) ?? 4
|
||||
secureEntry = try typeContainer.decodeIfPresent(Bool.self, forKey: .secureEntry) ?? false
|
||||
|
||||
if let digits = try typeContainer.decodeIfPresent(Int.self, forKey: .digits) {
|
||||
self.digits = digits
|
||||
}
|
||||
}
|
||||
|
||||
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(digits, forKey: .digits)
|
||||
try container.encode(secureEntry, forKey: .secureEntry)
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ import UIKit
|
||||
|
||||
public private(set) var titleLabel: Label = {
|
||||
let label = Label()
|
||||
label.font = MFStyler.fontRegularMicro()
|
||||
label.font = Styler.Font.RegularMicro.getFont()
|
||||
label.textColor = .mvmBlack
|
||||
label.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
return label
|
||||
@ -31,12 +31,12 @@ import UIKit
|
||||
/// Provides contextual information on the TextField.
|
||||
public private(set) var feedbackLabel: Label = {
|
||||
let label = Label()
|
||||
label.font = MFStyler.fontRegularMicro()
|
||||
label.font = Styler.Font.RegularMicro.getFont()
|
||||
label.textColor = .mvmBlack
|
||||
label.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
return label
|
||||
}()
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Delegate
|
||||
//--------------------------------------------------
|
||||
@ -48,14 +48,6 @@ import UIKit
|
||||
//--------------------------------------------------
|
||||
|
||||
public var isValid: Bool = false
|
||||
public var errorMessage: String?
|
||||
public var standardMessage: String? {
|
||||
didSet {
|
||||
if !showError {
|
||||
feedback = standardMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Computed Properties
|
||||
@ -75,7 +67,7 @@ import UIKit
|
||||
public var showError: Bool {
|
||||
get { return entryFieldContainer.showError }
|
||||
set (error) {
|
||||
self.feedback = error ? self.errorMessage : self.standardMessage
|
||||
self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.feedback
|
||||
self.entryFieldContainer.showError = error
|
||||
}
|
||||
}
|
||||
@ -121,6 +113,10 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
public var entryFieldModel: EntryFieldModel? {
|
||||
return model as? EntryFieldModel
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
//--------------------------------------------------
|
||||
@ -174,8 +170,6 @@ import UIKit
|
||||
@objc final public override func setupView() {
|
||||
super.setupView()
|
||||
|
||||
guard subviews.isEmpty else { return }
|
||||
|
||||
isAccessibilityElement = false
|
||||
setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
accessibilityElements = [titleLabel, feedbackLabel]
|
||||
@ -193,7 +187,7 @@ import UIKit
|
||||
entryFieldContainer.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
setupFieldContainerContent(entryFieldContainer)
|
||||
|
||||
titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4)
|
||||
titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: Padding.One)
|
||||
titleContainerDistance?.isActive = true
|
||||
entryFieldContainerLeading = entryFieldContainer.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
|
||||
entryFieldContainerLeading?.isActive = true
|
||||
@ -202,7 +196,7 @@ import UIKit
|
||||
|
||||
addSubview(feedbackLabel)
|
||||
|
||||
feedbackContainerDistance = feedbackLabel.topAnchor.constraint(equalTo: entryFieldContainer.bottomAnchor, constant: PaddingOne)
|
||||
feedbackContainerDistance = feedbackLabel.topAnchor.constraint(equalTo: entryFieldContainer.bottomAnchor, constant: Padding.Two)
|
||||
feedbackContainerDistance?.isActive = true
|
||||
feedbackLabelLeading = feedbackLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
|
||||
feedbackLabelLeading?.isActive = true
|
||||
@ -217,11 +211,11 @@ 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) {
|
||||
// To be overridden by subclass.
|
||||
}
|
||||
/**
|
||||
Method to override.
|
||||
Intended to add the interactive content (i.e. textField) to the entryFieldContainer.
|
||||
*/
|
||||
@objc open func setupFieldContainerContent(_ container: UIView) { }
|
||||
|
||||
@objc open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
@ -240,10 +234,11 @@ import UIKit
|
||||
|
||||
backgroundColor = .clear
|
||||
isAccessibilityElement = false
|
||||
titleLabel.font = MFStyler.fontRegularMicro()
|
||||
titleLabel.font = Styler.Font.RegularMicro.getFont()
|
||||
titleLabel.textColor = .mvmBlack
|
||||
feedbackLabel.font = MFStyler.fontRegularMicro()
|
||||
feedbackLabel.font = Styler.Font.RegularMicro.getFont()
|
||||
feedbackLabel.textColor = .mvmBlack
|
||||
feedbackLabel.text = nil
|
||||
entryFieldContainer.reset()
|
||||
}
|
||||
|
||||
@ -257,7 +252,6 @@ import UIKit
|
||||
|
||||
title = model.title
|
||||
feedback = model.feedback
|
||||
errorMessage = model.errorMessage
|
||||
isEnabled = model.enabled
|
||||
|
||||
if let isLocked = model.locked {
|
||||
|
||||
@ -22,29 +22,22 @@ import Foundation
|
||||
public var backgroundColor: Color?
|
||||
public var title: String?
|
||||
public var feedback: String?
|
||||
public var errorMessage: String = ""
|
||||
public var errorMessage: String?
|
||||
public var enabled: Bool = true
|
||||
public var locked: Bool?
|
||||
public var selected: Bool?
|
||||
public var text: String?
|
||||
|
||||
public var fieldKey: String?
|
||||
public var groupName: String = FormValidator.defaultGroupName
|
||||
public var baseValue: AnyHashable?
|
||||
|
||||
|
||||
public var isValid: Bool? {
|
||||
didSet {
|
||||
updateUI?()
|
||||
}
|
||||
didSet { updateUI?() }
|
||||
}
|
||||
|
||||
/// Temporary binding mechanism for the view to update on enable changes.
|
||||
public var updateUI: (() -> Void)?
|
||||
public var updateUI: (() -> ())?
|
||||
|
||||
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
|
||||
self.isValid = valid
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
@ -62,11 +55,19 @@ import Foundation
|
||||
case fieldKey
|
||||
case groupName
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Validation Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
public func formFieldValue() -> AnyHashable? {
|
||||
return text
|
||||
}
|
||||
|
||||
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
|
||||
self.isValid = valid
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
@ -76,17 +77,20 @@ import Foundation
|
||||
baseValue = text
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
|
||||
feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback)
|
||||
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) ?? ""
|
||||
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage)
|
||||
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)
|
||||
|
||||
baseValue = text
|
||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
@ -100,11 +104,11 @@ import Foundation
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(title, forKey: .title)
|
||||
try container.encodeIfPresent(feedback, forKey: .feedback)
|
||||
try container.encode(errorMessage, forKey: .errorMessage)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(locked, forKey: .locked)
|
||||
try container.encode(selected, forKey: .selected)
|
||||
try container.encodeIfPresent(text, forKey: .text)
|
||||
try container.encodeIfPresent(locked, forKey: .locked)
|
||||
try container.encodeIfPresent(selected, forKey: .selected)
|
||||
try container.encodeIfPresent(errorMessage, forKey: .errorMessage)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
public typealias TextFieldAndPickerDelegate = (UITextFieldDelegate & UIPickerViewDelegate & UIPickerViewDataSource)
|
||||
|
||||
|
||||
open class ItemDropdownEntryField: BaseDropdownEntryField {
|
||||
//--------------------------------------------------
|
||||
@ -62,7 +64,7 @@ open class ItemDropdownEntryField: BaseDropdownEntryField {
|
||||
@objc open override func setupFieldContainerContent(_ container: UIView) {
|
||||
super.setupFieldContainerContent(container)
|
||||
|
||||
pickerView = MVMCoreUICommonViewsUtility.addPicker(to: textField, delegate: self)
|
||||
pickerView = UIPickerView.addPicker(to: textField, delegate: self, dismissAction: #selector(dismissFieldInput))
|
||||
textField.hideBlinkingCaret = true
|
||||
textField.autocorrectionType = .no
|
||||
uiTextFieldDelegate = self
|
||||
|
||||
@ -17,17 +17,21 @@
|
||||
|
||||
public var options: [String] = []
|
||||
public var selectedIndex: Int = 0
|
||||
|
||||
public override func formFieldValue() -> AnyHashable? {
|
||||
guard !options.isEmpty else { return nil }
|
||||
return options[selectedIndex]
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case options
|
||||
case selectedIndex
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
@ -35,14 +39,17 @@
|
||||
required public init(from decoder: Decoder) throws {
|
||||
try super.init(from: decoder)
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
options = try typeContainer.decode([String].self, forKey: .options)
|
||||
selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) ?? 0
|
||||
|
||||
if let selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) {
|
||||
self.selectedIndex = selectedIndex
|
||||
}
|
||||
}
|
||||
|
||||
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(options, forKey: .options)
|
||||
try container.encode(options, forKey: .selectedIndex)
|
||||
}
|
||||
|
||||
@ -48,6 +48,18 @@ import MVMCore
|
||||
set { text = MVMCoreUIUtility.formatMdn(newValue) }
|
||||
}
|
||||
|
||||
/// Toggles selected or original (unselected) UI.
|
||||
public override var isSelected: Bool {
|
||||
get { return entryFieldContainer.isSelected }
|
||||
set (selected) {
|
||||
if selected && showError {
|
||||
showError = false
|
||||
}
|
||||
|
||||
super.isSelected = selected
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
@ -77,11 +89,14 @@ import MVMCore
|
||||
super.setupFieldContainerContent(container)
|
||||
|
||||
textField.keyboardType = .numberPad
|
||||
}
|
||||
|
||||
open override func setupTextFieldToolbar() {
|
||||
|
||||
let toolbar = MVMCoreUICommonViewsUtility.makeEmptyToolbar()
|
||||
let toolbar = UIToolbar.createEmptyToolbar()
|
||||
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
|
||||
let contacts = UIBarButtonItem(title: MVMCoreUIUtility.hardcodedString(withKey: "textfield_contacts_barbutton"), style: .plain, target: self, action: #selector(getContacts(_:)))
|
||||
let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput(_:)))
|
||||
let contacts = UIBarButtonItem(title: MVMCoreUIUtility.hardcodedString(withKey: "textfield_contacts_barbutton"), style: .plain, target: self, action: #selector(getContacts))
|
||||
let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput))
|
||||
toolbar.items = [contacts, space, dismissButton]
|
||||
textField.inputAccessoryView = toolbar
|
||||
}
|
||||
@ -107,18 +122,18 @@ import MVMCore
|
||||
isValid = true
|
||||
return true
|
||||
}
|
||||
|
||||
let isValid = hasValidMDN()
|
||||
|
||||
if isValid {
|
||||
|
||||
isValid = hasValidMDN()
|
||||
|
||||
if self.isValid {
|
||||
showError = false
|
||||
|
||||
|
||||
} else {
|
||||
errorMessage = errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message")
|
||||
entryFieldModel?.errorMessage = entryFieldModel?.errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message")
|
||||
showError = true
|
||||
UIAccessibility.post(notification: .layoutChanged, argument: textField)
|
||||
}
|
||||
|
||||
|
||||
return isValid
|
||||
}
|
||||
|
||||
@ -196,7 +211,7 @@ import MVMCore
|
||||
}
|
||||
|
||||
@objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
|
||||
|
||||
|
||||
return proprietorTextDelegate?.textFieldShouldBeginEditing?(textField) ?? true
|
||||
}
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ import UIKit
|
||||
/// Called when the entered text becomes invalid based on the validation block
|
||||
@objc optional func isInvalid(textfield: TextEntryField?)
|
||||
/// Dismisses the keyboard.
|
||||
@objc optional func dismissFieldInput(sender: Any?)
|
||||
@objc optional func dismissFieldInput(_ sender: Any?)
|
||||
}
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ import UIKit
|
||||
let textField = TextField()
|
||||
textField.isAccessibilityElement = true
|
||||
textField.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
textField.font = MFStyler.fontRegularBodyLarge()
|
||||
textField.font = Styler.Font.RegularBodyLarge.getFont()
|
||||
textField.textColor = .mvmBlack
|
||||
textField.smartQuotesType = .no
|
||||
textField.smartDashesType = .no
|
||||
@ -36,13 +36,19 @@ import UIKit
|
||||
return textField
|
||||
}()
|
||||
|
||||
public lazy var errorImage: UIImageView = {
|
||||
let image = MVMCoreUIUtility.imageNamed("alert_standard")
|
||||
let imageView = UIImageView(image: image)
|
||||
imageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
imageView.heightAnchor.constraint(equalToConstant: 20).isActive = true
|
||||
imageView.widthAnchor.constraint(equalToConstant: 20).isActive = true
|
||||
return imageView
|
||||
}()
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Stored Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
/// Set enabled and disabled colors to be utilized when setting this texfield's isEnabled property.
|
||||
public var textColor: (enabled: UIColor?, disabled: UIColor?) = (.mvmBlack, .mvmCoolGray3)
|
||||
|
||||
private var observingForChange: Bool = false
|
||||
|
||||
/// Validate on each entry in the textField. Default: true
|
||||
@ -54,7 +60,7 @@ import UIKit
|
||||
public var textEntryFieldModel: TextEntryFieldModel? {
|
||||
return model as? TextEntryFieldModel
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Computed Properties
|
||||
//--------------------------------------------------
|
||||
@ -68,7 +74,7 @@ import UIKit
|
||||
guard let self = self else { return }
|
||||
|
||||
self.textField.isEnabled = enabled
|
||||
self.textField.textColor = enabled ? self.textColor.enabled : self.textColor.disabled
|
||||
self.textField.textColor = enabled ? self.textEntryFieldModel?.enabledTextColor.uiColor : self.textEntryFieldModel?.disabledTextColor.uiColor
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -78,11 +84,15 @@ import UIKit
|
||||
set (error) {
|
||||
|
||||
if error {
|
||||
textField.accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message") ?? "", textField.text ?? "", errorMessage ?? "")
|
||||
textField.accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message") ?? "", textField.text ?? "", entryFieldModel?.errorMessage ?? "")
|
||||
} else {
|
||||
textField.accessibilityValue = nil
|
||||
}
|
||||
|
||||
if textField.isSecureTextEntry {
|
||||
showErrorView(error)
|
||||
}
|
||||
|
||||
super.showError = error
|
||||
}
|
||||
}
|
||||
@ -102,12 +112,6 @@ import UIKit
|
||||
set { textField.placeholder = newValue }
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Property Observers
|
||||
//--------------------------------------------------
|
||||
|
||||
public var validationBlock: ((_ value: String?) -> Bool)?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Delegate Properties
|
||||
//--------------------------------------------------
|
||||
@ -169,21 +173,21 @@ import UIKit
|
||||
|
||||
@objc open override func setupFieldContainerContent(_ container: UIView) {
|
||||
|
||||
textField.font = MFStyler.fontRegularBodyLarge()
|
||||
textField.font = Styler.Font.RegularBodyLarge.getFont()
|
||||
container.addSubview(textField)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
textField.heightAnchor.constraint(equalToConstant: 24),
|
||||
textField.topAnchor.constraint(equalTo: container.topAnchor, constant: 12),
|
||||
textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16),
|
||||
container.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: 12)
|
||||
textField.heightAnchor.constraint(equalToConstant: Padding.Five),
|
||||
textField.topAnchor.constraint(equalTo: container.topAnchor, constant: Padding.Three),
|
||||
textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: Padding.Three),
|
||||
container.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: Padding.Three)
|
||||
])
|
||||
|
||||
textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 16)
|
||||
textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Three)
|
||||
textFieldTrailingConstraint?.isActive = true
|
||||
|
||||
textField.addTarget(self, action: #selector(startEditing), for: .editingDidBegin)
|
||||
textField.addTarget(self, action: #selector(dismissFieldInput(_:)), for: .editingDidEnd)
|
||||
textField.addTarget(self, action: #selector(dismissFieldInput), for: .editingDidEnd)
|
||||
|
||||
let tap = UITapGestureRecognizer(target: self, action: #selector(startEditing))
|
||||
entryFieldContainer.addGestureRecognizer(tap)
|
||||
@ -194,37 +198,31 @@ import UIKit
|
||||
@objc open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
|
||||
textField.font = MFStyler.fontRegularBodyLarge()
|
||||
textField.font = Styler.Font.RegularBodyLarge.getFont()
|
||||
layoutIfNeeded()
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
|
||||
textField.font = MFStyler.fontRegularBodyLarge()
|
||||
textField.font = Styler.Font.RegularBodyLarge.getFont()
|
||||
}
|
||||
|
||||
@objc deinit {
|
||||
setBothTextDelegates(to: nil)
|
||||
}
|
||||
|
||||
@objc public func setBothTextDelegates(to delegate: (UITextFieldDelegate & ObservingTextFieldDelegate)?) {
|
||||
observingTextFieldDelegate = delegate
|
||||
uiTextFieldDelegate = delegate
|
||||
}
|
||||
|
||||
open func setupTextFieldToolbar() {
|
||||
let observingDelegate = observingTextFieldDelegate ?? self
|
||||
textField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
|
||||
action: #selector(observingDelegate.dismissFieldInput))
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Observing for Change (TextFieldDelegate)
|
||||
//--------------------------------------------------
|
||||
|
||||
public func defaultValidationBlock() {
|
||||
|
||||
validationBlock = { enteredValue in
|
||||
guard let enteredValue = enteredValue else { return false }
|
||||
return enteredValue.count > 0
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
@objc override open func resignFirstResponder() -> Bool {
|
||||
if validateWhenDoneEditing {
|
||||
@ -240,11 +238,11 @@ import UIKit
|
||||
text = textField.text
|
||||
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||
}
|
||||
|
||||
|
||||
@objc public func updateValidation(_ isValid: Bool) {
|
||||
let previousValidity = self.isValid
|
||||
self.isValid = isValid
|
||||
|
||||
|
||||
if previousValidity && !isValid {
|
||||
showError = true
|
||||
observingTextFieldDelegate?.isInvalid?(textfield: self)
|
||||
@ -276,10 +274,30 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
@objc func dismissFieldInput(_ sender: Any?) {
|
||||
@objc public func dismissFieldInput(_ sender: Any?) {
|
||||
resignFirstResponder()
|
||||
}
|
||||
|
||||
private func showErrorView(_ show: Bool) {
|
||||
|
||||
if show {
|
||||
entryFieldContainer.addSubview(errorImage)
|
||||
|
||||
textFieldTrailingConstraint?.isActive = false
|
||||
textFieldTrailingConstraint = errorImage.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two)
|
||||
textFieldTrailingConstraint?.isActive = true
|
||||
|
||||
entryFieldContainer.trailingAnchor.constraint(equalTo: errorImage.trailingAnchor, constant: Padding.Three).isActive = true
|
||||
errorImage.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true
|
||||
|
||||
} else {
|
||||
errorImage.removeFromSuperview()
|
||||
textFieldTrailingConstraint?.isActive = false
|
||||
textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two)
|
||||
textFieldTrailingConstraint?.isActive = true
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MoleculeViewProtocol
|
||||
//--------------------------------------------------
|
||||
@ -288,37 +306,39 @@ import UIKit
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
|
||||
guard let model = model as? TextEntryFieldModel else { return }
|
||||
|
||||
|
||||
model.updateUI = { [weak self] in
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||
if self?.isSelected ?? false {
|
||||
self?.updateValidation(model.isValid ?? true)
|
||||
guard let self = self else { return }
|
||||
|
||||
if self.isSelected {
|
||||
self.updateValidation(model.isValid ?? true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
self.delegateObject = delegateObject
|
||||
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
|
||||
textColor.enabled = model.enabledTextColor?.uiColor
|
||||
textColor.disabled = model.disabledTextColor?.uiColor
|
||||
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
|
||||
text = model.text
|
||||
placeholder = model.placeholder
|
||||
|
||||
switch model.type {
|
||||
case .password:
|
||||
case .password, .secure:
|
||||
textField.isSecureTextEntry = true
|
||||
|
||||
case .number:
|
||||
textField.keyboardType = .numberPad
|
||||
|
||||
case .email:
|
||||
textField.keyboardType = .emailAddress
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
defaultValidationBlock()
|
||||
|
||||
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
|
||||
observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate
|
||||
textField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self)
|
||||
setupTextFieldToolbar()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,9 +8,13 @@
|
||||
|
||||
|
||||
@objcMembers public class TextEntryFieldModel: EntryFieldModel {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Types
|
||||
//--------------------------------------------------
|
||||
|
||||
public enum EntryType: String, Codable {
|
||||
case password
|
||||
case secure
|
||||
case number
|
||||
case email
|
||||
}
|
||||
@ -24,8 +28,8 @@
|
||||
}
|
||||
|
||||
public var placeholder: String?
|
||||
public var enabledTextColor: Color?
|
||||
public var disabledTextColor: Color?
|
||||
public var enabledTextColor: Color = Color(uiColor: .mvmBlack)
|
||||
public var disabledTextColor: Color = Color(uiColor: .mvmCoolGray3)
|
||||
public var type: EntryType?
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -34,7 +38,6 @@
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case text
|
||||
case placeholder
|
||||
case enabledTextColor
|
||||
case disabledTextColor
|
||||
@ -42,27 +45,31 @@
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
try super.init(from: decoder)
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
|
||||
placeholder = try typeContainer.decodeIfPresent(String.self, forKey: .placeholder)
|
||||
enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTextColor)
|
||||
disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor)
|
||||
type = try typeContainer.decodeIfPresent(EntryType.self, forKey: .type)
|
||||
|
||||
if let enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTextColor) {
|
||||
self.enabledTextColor = enabledTextColor
|
||||
}
|
||||
|
||||
if let disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) {
|
||||
self.disabledTextColor = disabledTextColor
|
||||
}
|
||||
}
|
||||
|
||||
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.encodeIfPresent(text, forKey: .text)
|
||||
try container.encodeIfPresent(placeholder, forKey: .placeholder)
|
||||
try container.encodeIfPresent(enabledTextColor, forKey: .enabledTextColor)
|
||||
try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor)
|
||||
try container.encode(enabledTextColor, forKey: .enabledTextColor)
|
||||
try container.encode(disabledTextColor, forKey: .disabledTextColor)
|
||||
try container.encodeIfPresent(type, forKey: .type)
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,8 +131,26 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
private var widthConstraint: NSLayoutConstraint?
|
||||
|
||||
private func constrainKnob() {
|
||||
knobLeadingConstraint?.isActive = !isOn
|
||||
knobTrailingConstraint?.isActive = isOn
|
||||
|
||||
knobLeadingConstraint?.isActive = false
|
||||
knobTrailingConstraint?.isActive = false
|
||||
|
||||
_ = isOn ? constrainKnobOn() : constrainKnobOff()
|
||||
|
||||
knobTrailingConstraint?.isActive = true
|
||||
knobLeadingConstraint?.isActive = true
|
||||
}
|
||||
|
||||
private func constrainKnobOn() {
|
||||
|
||||
knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 1)
|
||||
knobLeadingConstraint = knobView.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor)
|
||||
}
|
||||
|
||||
private func constrainKnobOff() {
|
||||
|
||||
knobTrailingConstraint = trailingAnchor.constraint(greaterThanOrEqualTo: knobView.trailingAnchor)
|
||||
knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -189,6 +207,8 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
|
||||
layer.cornerRadius = Self.getContainerHeight() / 2.0
|
||||
knobView.layer.cornerRadius = Self.getKnobHeight() / 2.0
|
||||
|
||||
changeStateNoAnimation(isOn)
|
||||
}
|
||||
|
||||
public override func setupView() {
|
||||
@ -218,9 +238,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
knobView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true
|
||||
bottomAnchor.constraint(greaterThanOrEqualTo: knobView.bottomAnchor).isActive = true
|
||||
|
||||
knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 1)
|
||||
knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1)
|
||||
knobLeadingConstraint?.isActive = true
|
||||
constrainKnobOff()
|
||||
}
|
||||
|
||||
public override func reset() {
|
||||
@ -228,9 +246,8 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
|
||||
backgroundColor = containerTintColor.off
|
||||
knobView.backgroundColor = knobTintColor.off
|
||||
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel")
|
||||
isAnimated = true
|
||||
isOn = false
|
||||
constrainKnob()
|
||||
didToggleAction = nil
|
||||
shouldToggleAction = { return true }
|
||||
}
|
||||
@ -352,10 +369,15 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
containerTintColor.off = model.offTintColor.uiColor
|
||||
knobTintColor.on = model.onKnobTintColor.uiColor
|
||||
knobTintColor.off = model.offKnobTintColor.uiColor
|
||||
changeStateNoAnimation(model.state)
|
||||
isOn = model.state
|
||||
changeStateNoAnimation(isOn)
|
||||
isAnimated = model.animated
|
||||
isEnabled = model.enabled
|
||||
|
||||
if let accessibileString = model.accessibilityText {
|
||||
accessibilityLabel = accessibileString
|
||||
}
|
||||
|
||||
if let actionMap = model.action?.toJSON() {
|
||||
didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) }
|
||||
}
|
||||
|
||||
37
MVMCoreUI/Atomic/Extensions/UIDatePicker+Extension.swift
Normal file
37
MVMCoreUI/Atomic/Extensions/UIDatePicker+Extension.swift
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// UIDatePicker+Extension.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kevin Christiano on 4/14/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
public extension UIDatePicker {
|
||||
|
||||
class func addDatePicker(to textField: UITextField) -> UIDatePicker {
|
||||
|
||||
let datePicker = UIDatePicker()
|
||||
datePicker.backgroundColor = .mvmWhite
|
||||
datePicker.datePickerMode = .date
|
||||
|
||||
let locale = NSLocale.current as NSLocale
|
||||
datePicker.locale = locale as Locale
|
||||
datePicker.calendar = locale.object(forKey: .calendar) as? Calendar
|
||||
textField.inputView = datePicker
|
||||
|
||||
return datePicker
|
||||
}
|
||||
|
||||
class func addTimeAndDatePicker(to textField: UITextField) -> UIDatePicker {
|
||||
|
||||
let datePicker = UIDatePicker()
|
||||
datePicker.backgroundColor = .mvmWhite
|
||||
datePicker.datePickerMode = .time
|
||||
textField.inputView = datePicker
|
||||
|
||||
return datePicker
|
||||
}
|
||||
}
|
||||
38
MVMCoreUI/Atomic/Extensions/UIPickerView+Extension.swift
Normal file
38
MVMCoreUI/Atomic/Extensions/UIPickerView+Extension.swift
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// UIPickerView.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kevin Christiano on 4/14/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
public extension UIPickerView {
|
||||
|
||||
class func createPickerView() -> UIPickerView {
|
||||
|
||||
let picker = UIPickerView(frame: .zero)
|
||||
picker.backgroundColor = .mvmWhite
|
||||
picker.showsSelectionIndicator = true
|
||||
return picker
|
||||
}
|
||||
|
||||
class func addPicker(to textField: UITextField, delegate: TextFieldAndPickerDelegate?, dismissAction: Selector?) -> UIPickerView {
|
||||
|
||||
// Sets up the picker (same tag as the textfield)
|
||||
let picker = createPickerView()
|
||||
picker.delegate = delegate
|
||||
picker.dataSource = delegate
|
||||
picker.tag = textField.tag
|
||||
textField.inputView = picker
|
||||
|
||||
// Adds a dismiss toolbar, since all fields with pickers should have one.
|
||||
if let dismissAction = dismissAction {
|
||||
UIToolbar.addDismissToolbar(to: textField, delegate: delegate, action: dismissAction)
|
||||
}
|
||||
|
||||
return picker
|
||||
}
|
||||
}
|
||||
56
MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift
Normal file
56
MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift
Normal file
@ -0,0 +1,56 @@
|
||||
//
|
||||
// UIToolbar+Extension.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kevin Christiano on 4/10/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol TextFieldOrView { }
|
||||
|
||||
extension UITextView: TextFieldOrView { }
|
||||
extension UITextField: TextFieldOrView { }
|
||||
|
||||
|
||||
public extension UIToolbar {
|
||||
|
||||
class func createEmptyToolbar() -> UIToolbar {
|
||||
|
||||
let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44))
|
||||
toolbar.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleWidth]
|
||||
toolbar.barStyle = .default
|
||||
toolbar.barTintColor = .mvmCoolGray3
|
||||
toolbar.tintColor = .mvmBlack
|
||||
toolbar.isTranslucent = true
|
||||
|
||||
return toolbar
|
||||
}
|
||||
|
||||
class func getToolbarWithDoneButton(delegate: Any?, action: Selector) -> UIToolbar {
|
||||
|
||||
let toolbar = createEmptyToolbar()
|
||||
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
|
||||
let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: action)
|
||||
toolbar.setItems([space, button], animated: false)
|
||||
|
||||
return toolbar
|
||||
}
|
||||
|
||||
class func addDismissToolbar(to object: TextFieldOrView, delegate: Any?, action: Selector) {
|
||||
|
||||
let toolbar = Self.getToolbarWithDoneButton(delegate: delegate, action: action)
|
||||
|
||||
switch object {
|
||||
case is UITextField:
|
||||
(object as? UITextField)?.inputAccessoryView = toolbar
|
||||
|
||||
case is UITextView:
|
||||
(object as? UITextView)?.inputAccessoryView = toolbar
|
||||
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,6 +152,7 @@ import Foundation
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDetails.self, viewModelClass: ListTwoColumnPriceDetailsModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self)
|
||||
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)
|
||||
|
||||
// Designed Section Dividers
|
||||
@ -168,6 +169,10 @@ import Foundation
|
||||
|
||||
// Designed Headers
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2NoButtonsBodyText.self, viewModelClass: HeadersH2NoButtonsBodyTextModel.self)
|
||||
|
||||
|
||||
// Device Items
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexButtonMedium.self, viewModelClass: ListDeviceComplexButtonMediumModel.self)
|
||||
|
||||
// TODO: Need View
|
||||
try? ModelRegistry.register(TabsModel.self)
|
||||
|
||||
@ -0,0 +1,79 @@
|
||||
//
|
||||
// ListDeviceComplexButtonMedium.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Dhamodaram Nandi on 21/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@objcMembers open class ListDeviceComplexButtonMedium: TableViewCell {
|
||||
|
||||
public var verticalStack: Stack<StackModel>
|
||||
public let eyebrow = Label.createLabelRegularMicro(true)
|
||||
public let headline = Label.createLabelBoldTitleMedium(true)
|
||||
public let body = Label.createLabelRegularBodySmall(true)
|
||||
public let body2 = Label.createLabelRegularBodySmall(true)
|
||||
public let button = PillButton(frame: .zero)
|
||||
public let rightImageView = MFLoadImageView()
|
||||
public var stack: Stack<StackModel>
|
||||
|
||||
// MARK: - Initializers
|
||||
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
rightImageView.addSizeConstraintsForAspectRatio = true
|
||||
rightImageView.heightAnchor.constraint(equalToConstant: 116.0).isActive = true
|
||||
rightImageView.widthAnchor.constraint(equalToConstant: 116.0).isActive = true
|
||||
verticalStack = Stack<StackModel>.createStack(with: [(view: eyebrow, model: StackItemModel(horizontalAlignment: .leading)),
|
||||
(view: headline, model: StackItemModel(horizontalAlignment: .leading)),
|
||||
(view: body, model: StackItemModel(horizontalAlignment: .leading)),
|
||||
(view: body2, model: StackItemModel(horizontalAlignment: .leading)),
|
||||
(view: button, model: StackItemModel(spacing:16, horizontalAlignment: .leading))],
|
||||
axis: .vertical, spacing: 0)
|
||||
stack = Stack<StackModel>.createStack(with: [(view: verticalStack, model: StackItemModel(horizontalAlignment: .leading, verticalAlignment: .leading)),
|
||||
(view: rightImageView, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .center))],
|
||||
axis: .horizontal)
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
// MARK: - MFViewProtocol
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
verticalStack.restack()
|
||||
}
|
||||
|
||||
// MARK: - ModelMoleculeViewProtocol
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListDeviceComplexButtonMediumModel else { return }
|
||||
verticalStack.updateContainedMolecules(with: [model.eyebrow,
|
||||
model.headline,
|
||||
model.body,
|
||||
model.body2,
|
||||
model.button],
|
||||
delegateObject, additionalData)
|
||||
rightImageView.set(with: model.image, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 120
|
||||
}
|
||||
|
||||
public func setDefault() {
|
||||
eyebrow.styleRegularMicro(true)
|
||||
headline.styleBoldTitleMedium(true)
|
||||
body.styleRegularBodySmall(true)
|
||||
body2.styleRegularBodySmall(true)
|
||||
eyebrow.textColor = .mvmCoolGray6
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
setDefault()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
//
|
||||
// ListDeviceComplexButtonMediumModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Dhamodaram Nandi on 21/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
public class ListDeviceComplexButtonMediumModel: ListItemModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "listDvcBtnM"
|
||||
public var eyebrow: LabelModel?
|
||||
public var headline: LabelModel?
|
||||
public var body: LabelModel?
|
||||
public var body2: LabelModel?
|
||||
public var button: ButtonModel
|
||||
public var image: ImageViewModel
|
||||
|
||||
public init(eyebrow: LabelModel, headline:LabelModel, body: LabelModel, body2: LabelModel, button: ButtonModel, image: ImageViewModel) {
|
||||
self.eyebrow = eyebrow
|
||||
self.headline = headline
|
||||
self.body = body
|
||||
self.body2 = body2
|
||||
self.button = button
|
||||
self.image = image
|
||||
super.init()
|
||||
}
|
||||
|
||||
/// Defaults to set
|
||||
override public func setDefaults() {
|
||||
super.setDefaults()
|
||||
button.size = .tiny
|
||||
button.style = .secondary
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case eyebrow
|
||||
case headline
|
||||
case body
|
||||
case body2
|
||||
case button
|
||||
case image
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow)
|
||||
headline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .headline)
|
||||
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
|
||||
body2 = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body2)
|
||||
button = try typeContainer.decode(ButtonModel.self, forKey: .button)
|
||||
image = try typeContainer.decode(ImageViewModel.self, forKey: .image)
|
||||
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.encodeIfPresent(eyebrow, forKey: .eyebrow)
|
||||
try container.encodeIfPresent(headline, forKey: .headline)
|
||||
try container.encodeIfPresent(body, forKey: .body)
|
||||
try container.encodeIfPresent(body2, forKey: .body2)
|
||||
try container.encode(button, forKey: .button)
|
||||
try container.encode(image, forKey: .image)
|
||||
}
|
||||
}
|
||||
@ -40,24 +40,18 @@ import Foundation
|
||||
override open func setupView() {
|
||||
super.setupView()
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?){
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListOneColumnFullWidthTextAllTextAndLinksModel else { return }
|
||||
eyebrow.setOptional(with: model.eyebrow, delegateObject, additionalData)
|
||||
headline.setOptional(with: model.headline, delegateObject, additionalData)
|
||||
subHeadline.setOptional(with: model.subHeadline, delegateObject, additionalData)
|
||||
body.setOptional(with: model.body, delegateObject, additionalData)
|
||||
link.setOptional(with: model.link, delegateObject, additionalData)
|
||||
|
||||
// Hide labels if neeeded.
|
||||
stack.stackModel?.molecules[0].gone = !eyebrow.hasText
|
||||
stack.stackModel?.molecules[1].gone = !headline.hasText
|
||||
stack.stackModel?.molecules[2].gone = !subHeadline.hasText
|
||||
stack.stackModel?.molecules[3].gone = !body.hasText
|
||||
stack.stackModel?.molecules[4].gone = (link.titleLabel?.text?.count ?? 0) == 0
|
||||
stack.restack()
|
||||
stack.updateContainedMolecules(with: [model.eyebrow,
|
||||
model.headline,
|
||||
model.subHeadline,
|
||||
model.body,
|
||||
model.link],
|
||||
delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
//
|
||||
// ListThreeColumnDataUsage.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kruthika KP on 20/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers open class ListThreeColumnDataUsage: TableViewCell {
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//-------------------------------------------------------
|
||||
public let leftLabel = Label.createLabelRegularBodySmall(true)
|
||||
public let centerLabel = Label.createLabelRegularBodySmall(true)
|
||||
public let rightLabel = Label.createLabelRegularBodySmall(true)
|
||||
var stack: Stack<StackModel>
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//------------------------------------------------------
|
||||
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
stack = Stack<StackModel>.createStack(with: [(view: leftLabel, model: StackItemModel(percent: 40, horizontalAlignment: .leading)),
|
||||
(view: centerLabel, model: StackItemModel(percent: 37, horizontalAlignment: .leading)),
|
||||
(view: rightLabel, model: StackItemModel(percent: 23, horizontalAlignment: .leading))],
|
||||
axis: .horizontal)
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
}
|
||||
|
||||
// MARK: - ModelMoleculeViewProtocol
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListThreeColumnDataUsageModel else { return }
|
||||
leftLabel.set(with: model.leftLabel, delegateObject, additionalData)
|
||||
centerLabel.set(with: model.centerLabel, delegateObject, additionalData)
|
||||
rightLabel.set(with: model.rightLabel, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 121
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
leftLabel.styleRegularBodySmall(true)
|
||||
centerLabel.styleRegularBodySmall(true)
|
||||
rightLabel.styleRegularBodySmall(true)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
//
|
||||
// ListThreeColumnDataUsageModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kruthika KP on 20/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ListThreeColumnDataUsageModel: ListItemModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "list3CDataUsg"
|
||||
public var leftLabel: LabelModel
|
||||
public var centerLabel: LabelModel
|
||||
public var rightLabel: LabelModel
|
||||
|
||||
public init(leftLabel:LabelModel, centerLabel:LabelModel, rightLabel:LabelModel) {
|
||||
self.leftLabel = leftLabel
|
||||
self.centerLabel = centerLabel
|
||||
self.rightLabel = rightLabel
|
||||
super.init()
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case leftLabel
|
||||
case centerLabel
|
||||
case rightLabel
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel)
|
||||
centerLabel = try typeContainer.decode(LabelModel.self, forKey: .centerLabel)
|
||||
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(leftLabel, forKey: .leftLabel)
|
||||
try container.encode(centerLabel, forKey: .centerLabel)
|
||||
try container.encode(rightLabel, forKey: .rightLabel)
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ import Foundation
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case spacing
|
||||
case percent
|
||||
case gone
|
||||
@ -33,6 +34,7 @@ import Foundation
|
||||
if let gone = try typeContainer.decodeIfPresent(Bool.self, forKey: .gone) {
|
||||
self.gone = gone
|
||||
}
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
@ -43,5 +45,6 @@ import Foundation
|
||||
try container.encodeIfPresent(spacing, forKey: .spacing)
|
||||
try container.encodeIfPresent(percent, forKey: .percent)
|
||||
try container.encode(gone, forKey: .gone)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,11 +8,19 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
|
||||
@objcMembers open class LabelToggle: View {
|
||||
public let label = Label.commonLabelB1(true)
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public let label = Label.createLabelBoldBodySmall(true)
|
||||
public let toggle = Toggle()
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MVMCoreViewProtocol
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
label.updateView(size)
|
||||
@ -21,28 +29,26 @@ import UIKit
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
guard toggle.superview == nil else {
|
||||
return
|
||||
}
|
||||
|
||||
addSubview(label)
|
||||
addSubview(toggle)
|
||||
label.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical)
|
||||
label.setContentHuggingPriority(.required, for: .vertical)
|
||||
NSLayoutConstraint.pinViews(leftView: label, rightView: toggle, alignTop: false)
|
||||
}
|
||||
|
||||
// MARK:- MoleculeViewProtocol
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
guard let model = model as? LabelToggleModel,
|
||||
let toggleHeight = Toggle.estimatedHeight(with: model.toggle, delegateObject),
|
||||
let labelHeight = Label.estimatedHeight(with: model.label, delegateObject) else { return nil }
|
||||
let labelHeight = Label.estimatedHeight(with: model.label, delegateObject)
|
||||
else { return nil }
|
||||
|
||||
return max(toggleHeight, labelHeight)
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
guard let labelToggleModel = model as? LabelToggleModel else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let labelToggleModel = model as? LabelToggleModel else { return }
|
||||
|
||||
label.set(with: labelToggleModel.label, delegateObject, additionalData)
|
||||
toggle.set(with: labelToggleModel.toggle, delegateObject, additionalData)
|
||||
}
|
||||
@ -52,6 +58,6 @@ import UIKit
|
||||
super.reset()
|
||||
label.reset()
|
||||
toggle.reset()
|
||||
label.styleB1(true)
|
||||
label.styleBoldBodySmall(true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ import UIKit
|
||||
stack.stackModel?.spacing = 0
|
||||
addSubview(stack)
|
||||
NSLayoutConstraint.constraintPinSubview(toSuperview: stack)
|
||||
stack.restack()
|
||||
}
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
@ -58,18 +59,11 @@ import UIKit
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
|
||||
eyebrow.setOptional(with: castModel?.eyebrow, delegateObject, additionalData)
|
||||
headline.setOptional(with: castModel?.headline, delegateObject, additionalData)
|
||||
body.setOptional(with: castModel?.body, delegateObject, additionalData)
|
||||
link.setOptional(with: castModel?.link, delegateObject, additionalData)
|
||||
|
||||
// Hide labels if neeeded.
|
||||
stack.stackModel?.molecules[0].gone = !eyebrow.hasText
|
||||
stack.stackModel?.molecules[1].gone = !headline.hasText
|
||||
stack.stackModel?.molecules[2].gone = !body.hasText
|
||||
stack.stackModel?.molecules[3].gone = (link.titleLabel?.text?.count ?? 0) == 0
|
||||
stack.restack()
|
||||
stack.updateContainedMolecules(with: [castModel?.eyebrow,
|
||||
castModel?.headline,
|
||||
castModel?.body,
|
||||
castModel?.link],
|
||||
delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
|
||||
@ -62,6 +62,32 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
|
||||
}
|
||||
}
|
||||
|
||||
/// A convenience function for when the stackItems are containers and we want to update them based on the contained molecules models. If model is nil, stackItem is set to gone. Restacks if necessary.
|
||||
open func updateContainedMolecules(with models: [MoleculeModelProtocol?], _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
guard var stackModel = stackModel else { return }
|
||||
var needsRestack = false
|
||||
for (index, item) in stackItems.enumerated() {
|
||||
guard let container = item as? UIView & ContainerProtocol,
|
||||
let contained = container.view as? MoleculeViewProtocol else {
|
||||
continue
|
||||
}
|
||||
if let model = models[index] {
|
||||
contained.set(with: model, delegateObject, additionalData)
|
||||
if stackModel.molecules[index].gone {
|
||||
stackModel.molecules[index].gone = false
|
||||
needsRestack = true
|
||||
}
|
||||
} else if !stackModel.molecules[index].gone {
|
||||
stackModel.molecules[index].gone = true
|
||||
needsRestack = true
|
||||
}
|
||||
}
|
||||
|
||||
if needsRestack {
|
||||
restack()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -48,6 +48,7 @@ import Foundation
|
||||
if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) {
|
||||
self.spacing = spacing
|
||||
}
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
@ -58,5 +59,6 @@ import Foundation
|
||||
try container.encodeIfPresent(axis.rawValueString, forKey: .axis)
|
||||
try container.encodeIfPresent(spacing, forKey: .spacing)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ open class ScrollingViewController: ViewController {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Adds the tap gesture to dismiss the keyboard.
|
||||
dismissKeyboardTapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissFieldInput(sender:)))
|
||||
dismissKeyboardTapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissFieldInput))
|
||||
view.addGestureRecognizer(dismissKeyboardTapGesture!)
|
||||
dismissKeyboardTapGesture?.isEnabled = false
|
||||
scrollView.alwaysBounceVertical = false
|
||||
|
||||
@ -405,7 +405,7 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
@objc open func dismissFieldInput(sender: Any?) {
|
||||
@objc open func dismissFieldInput(_ sender: Any?) {
|
||||
selectedField?.resignFirstResponder()
|
||||
}
|
||||
|
||||
|
||||
@ -25,9 +25,7 @@ import UIKit
|
||||
|
||||
/// Total control over the drawn top, bottom, left and right borders.
|
||||
public var disableAllBorders = false {
|
||||
didSet {
|
||||
bottomBar?.isHidden = disableAllBorders
|
||||
}
|
||||
didSet { bottomBar?.isHidden = disableAllBorders }
|
||||
}
|
||||
|
||||
private(set) var fieldState: FieldState = .original {
|
||||
|
||||
@ -10,10 +10,8 @@ import Foundation
|
||||
|
||||
|
||||
open class Styler {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Enums
|
||||
//--------------------------------------------------
|
||||
|
||||
// MARK:- Font Enum
|
||||
public enum Font: String, Codable {
|
||||
case Title2XLarge
|
||||
case TitleXLarge
|
||||
|
||||
23
MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/Contents.json
vendored
Normal file
23
MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "alert_standard @1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "alert_standard @2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "alert_standard @3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @1x.png
vendored
Normal file
BIN
MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @1x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 279 B |
BIN
MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @2x.png
vendored
Normal file
BIN
MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 525 B |
BIN
MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @3x.png
vendored
Normal file
BIN
MVMCoreUI/SupportingFiles/Media.xcassets/alert_standard.imageset/alert_standard @3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 771 B |
@ -198,7 +198,7 @@
|
||||
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|->=space-[button]->=space-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"space":@(PaddingFive)} views:NSDictionaryOfVariableBindings(button)]];
|
||||
[NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0].active = YES;
|
||||
[NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.centerView attribute:NSLayoutAttributeRight multiplier:1 constant:PaddingThree].active = YES;
|
||||
[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:button attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : PaddingThree)].active = YES;
|
||||
[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:button attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : PaddingFive)].active = YES;
|
||||
self.button = button;
|
||||
}
|
||||
} else {
|
||||
@ -210,7 +210,7 @@
|
||||
}
|
||||
|
||||
if (!self.labelRightConstraint) {
|
||||
self.labelRightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.centerView attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : PaddingThree)];
|
||||
self.labelRightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.centerView attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : PaddingFive)];
|
||||
}
|
||||
self.labelRightConstraint.active = YES;
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ public extension MVMCoreUICommonViewsUtility {
|
||||
|
||||
let toolbar = self.makeEmptyToolbar()
|
||||
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
|
||||
let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: #selector(ObservingTextFieldDelegate.dismissFieldInput(sender:)))
|
||||
let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: #selector(ObservingTextFieldDelegate.dismissFieldInput))
|
||||
button.tintColor = .black
|
||||
toolbar.setItems([space, button], animated: false)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user