Merge branch 'develop' into feature/Headers_H2_Buttons

# Conflicts:
#	MVMCoreUI/Atomic/MoleculeObjectMapping.swift
This commit is contained in:
Lekshmi S 2020-04-28 12:13:54 +05:30
commit 91a5b3d36c
132 changed files with 3270 additions and 1051 deletions

View File

@ -61,7 +61,6 @@
01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */; }; 01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */; };
01EB368F23609801006832FA /* LabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368823609801006832FA /* LabelModel.swift */; }; 01EB368F23609801006832FA /* LabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368823609801006832FA /* LabelModel.swift */; };
01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368923609801006832FA /* MoleculeListItemModel.swift */; }; 01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368923609801006832FA /* MoleculeListItemModel.swift */; };
01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368B23609801006832FA /* MoleculeStackModel.swift */; };
01EB369323609801006832FA /* HeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368C23609801006832FA /* HeaderModel.swift */; }; 01EB369323609801006832FA /* HeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368C23609801006832FA /* HeaderModel.swift */; };
01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368D23609801006832FA /* HeadlineBodyModel.swift */; }; 01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368D23609801006832FA /* HeadlineBodyModel.swift */; };
01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F2A03123A4498200D954D8 /* CaretLinkModel.swift */; }; 01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F2A03123A4498200D954D8 /* CaretLinkModel.swift */; };
@ -95,6 +94,7 @@
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; }; 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; };
0A7ECC5D243CE85300C828E8 /* DoughnutChartItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */; }; 0A7ECC5D243CE85300C828E8 /* DoughnutChartItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */; };
0A7ECC5F243CEB1200C828E8 /* ColorViewWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.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 */; }; 0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */; };
0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */; }; 0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */; };
0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */; }; 0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */; };
@ -103,6 +103,8 @@
0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */; }; 0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */; };
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */; }; 0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */; };
0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B392398524F0067DD0F /* Toggle.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 */; }; 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; };
0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; }; 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; };
0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; }; 0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; };
@ -139,8 +141,12 @@
8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; }; 8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; };
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4687E1242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift */; }; 8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4687E1242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift */; };
8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */; }; 8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */; };
8D8067D12444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8067D02444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift */; };
8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */; };
8DD1E36E243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */; }; 8DD1E36E243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */; };
8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.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 */; }; 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 */; }; 942C372E241149170066E45E /* NHaasGroteskDSStd-75Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = 942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */; };
@ -148,8 +154,8 @@
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 */; };
943784F5236B77BB006A1E82 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* GraphView.swift */; }; 943784F5236B77BB006A1E82 /* Wheel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* Wheel.swift */; };
943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.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 */; }; 94382086243238D100B43AF3 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94382085243238D100B43AF3 /* WebViewModel.swift */; };
9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */; }; 9445890C2385BCE300DE9FD4 /* ProgressBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */; };
@ -182,6 +188,7 @@
94CA227F24058534002D6750 /* VerizonNHGeTX-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */; }; 94CA227F24058534002D6750 /* VerizonNHGeTX-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */; };
94F217B623E0BF6100A47C06 /* PrimaryButtonView.h in Headers */ = {isa = PBXBuildFile; fileRef = 94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 94F217B623E0BF6100A47C06 /* PrimaryButtonView.h in Headers */ = {isa = PBXBuildFile; fileRef = 94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */; settings = {ATTRIBUTES = (Public, ); }; };
94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */; }; 94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */; };
94F6516D2437954100631BF9 /* Tabs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94F6516C2437954100631BF9 /* Tabs.swift */; };
94FB966223D797DA003D482B /* MFTextButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 94FB966023D797DA003D482B /* MFTextButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 94FB966223D797DA003D482B /* MFTextButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 94FB966023D797DA003D482B /* MFTextButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
94FB966323D797DA003D482B /* MFTextButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 94FB966123D797DA003D482B /* MFTextButton.m */; }; 94FB966323D797DA003D482B /* MFTextButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 94FB966123D797DA003D482B /* MFTextButton.m */; };
AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA104B1924474A66004D2810 /* HeadersH2Buttons.swift */; }; AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA104B1924474A66004D2810 /* HeadersH2Buttons.swift */; };
@ -190,16 +197,30 @@
AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */; }; AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */; };
AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift */; }; AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift */; };
AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */; }; AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */; };
AA2AD116244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2AD115244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift */; };
AA2AD118244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA2AD117244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift */; };
AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */; }; AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */; };
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */; }; AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */; };
AA617AB02453010A00910B8F /* ListDeviceComplexLinkSmall.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA617AAF2453010A00910B8F /* ListDeviceComplexLinkSmall.swift */; };
AA617AB22453012400910B8F /* ListDeviceComplexLinkSmallModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA617AB12453012400910B8F /* ListDeviceComplexLinkSmallModel.swift */; };
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */; };
AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.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 */; };
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 */; }; BB2C968F24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C968D24330EA7006FF80C /* ListRightVariableTextLinkAllTextAndLinksModel.swift */; };
BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */; }; BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */; };
BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */; }; BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */; };
BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */; }; BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */; };
BB54C5202434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift */; }; BB54C5202434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift */; };
BB54C5212434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB54C51F2434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift */; }; BB54C5212434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB54C51F2434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift */; };
BB55B51D244482C1002001AD /* ListRightVariablePriceChangeBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */; };
BB55B51F244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */; };
BB6C6AC0242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABE242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift */; }; BB6C6AC0242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABE242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift */; };
BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift */; }; BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift */; };
BB6C6AC824225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6AC62422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift */; }; BB6C6AC824225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6AC62422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift */; };
@ -224,9 +245,17 @@
C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012223E846C300396FBD /* ListRVWheelModel.swift */; }; C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012223E846C300396FBD /* ListRVWheelModel.swift */; };
D202AFE4242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */; }; D202AFE4242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */; };
D202AFE6242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */; }; D202AFE6242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */; };
D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092348244A51D40044AD09 /* RadioSwatchModel.swift */; };
D209234F244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D209234E244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift */; };
D2092351244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092350244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift */; };
D2092353244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092352244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift */; };
D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092354244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift */; };
D2092357244FA1EF0044AD09 /* ThreeLayerModelBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */; };
D20923592450ECE00044AD09 /* TableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20923582450ECE00044AD09 /* TableView.swift */; };
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; };
D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */; }; D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */; };
D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; };
D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */; };
D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */; }; D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */; };
D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */; }; D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */; };
D21B7F75243BAC8900051ABF /* CarouselItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F74243BAC8900051ABF /* CarouselItem.swift */; }; D21B7F75243BAC8900051ABF /* CarouselItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F74243BAC8900051ABF /* CarouselItem.swift */; };
@ -287,7 +316,7 @@
D28A837D23CCA86A00DFE4FC /* TabsListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A837C23CCA86A00DFE4FC /* TabsListItemModel.swift */; }; D28A837D23CCA86A00DFE4FC /* TabsListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A837C23CCA86A00DFE4FC /* TabsListItemModel.swift */; };
D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A837E23CCA96400DFE4FC /* TabsModel.swift */; }; D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A837E23CCA96400DFE4FC /* TabsModel.swift */; };
D28A838123CCB0D800DFE4FC /* AccordionListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838023CCB0D800DFE4FC /* AccordionListItemModel.swift */; }; D28A838123CCB0D800DFE4FC /* AccordionListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838023CCB0D800DFE4FC /* AccordionListItemModel.swift */; };
D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */; }; D28A838323CCBD3F00DFE4FC /* WheelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838223CCBD3F00DFE4FC /* WheelModel.swift */; };
D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */; }; D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */; };
D28A838923CCCFCB00DFE4FC /* LinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838823CCCFCB00DFE4FC /* LinkModel.swift */; }; D28A838923CCCFCB00DFE4FC /* LinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838823CCCFCB00DFE4FC /* LinkModel.swift */; };
D28A838B23CCDA6B00DFE4FC /* ButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */; }; D28A838B23CCDA6B00DFE4FC /* ButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */; };
@ -395,7 +424,6 @@
D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28D723D21AB800ACEA85 /* StringAndMoleculeView.swift */; }; D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28D723D21AB800ACEA85 /* StringAndMoleculeView.swift */; };
D29E28DA23D21AFA00ACEA85 /* StringAndMoleculeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28D923D21AFA00ACEA85 /* StringAndMoleculeModel.swift */; }; D29E28DA23D21AFA00ACEA85 /* StringAndMoleculeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28D923D21AFA00ACEA85 /* StringAndMoleculeModel.swift */; };
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28DC23D7404C00ACEA85 /* ContainerHelper.swift */; }; D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28DC23D7404C00ACEA85 /* ContainerHelper.swift */; };
D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */; };
D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */; }; D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */; };
D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */; }; D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */; };
D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514662213885800345BFB /* MoleculeHeaderView.swift */; }; D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514662213885800345BFB /* MoleculeHeaderView.swift */; };
@ -499,7 +527,6 @@
01EB368823609801006832FA /* LabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelModel.swift; sourceTree = "<group>"; }; 01EB368823609801006832FA /* LabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelModel.swift; sourceTree = "<group>"; };
01EB368923609801006832FA /* MoleculeListItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeListItemModel.swift; sourceTree = "<group>"; }; 01EB368923609801006832FA /* MoleculeListItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeListItemModel.swift; sourceTree = "<group>"; };
01EB368A23609801006832FA /* MoleculeStackItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackItemModel.swift; sourceTree = "<group>"; }; 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackItemModel.swift; sourceTree = "<group>"; };
01EB368B23609801006832FA /* MoleculeStackModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackModel.swift; sourceTree = "<group>"; };
01EB368C23609801006832FA /* HeaderModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderModel.swift; sourceTree = "<group>"; }; 01EB368C23609801006832FA /* HeaderModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderModel.swift; sourceTree = "<group>"; };
01EB368D23609801006832FA /* HeadlineBodyModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeadlineBodyModel.swift; sourceTree = "<group>"; }; 01EB368D23609801006832FA /* HeadlineBodyModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeadlineBodyModel.swift; sourceTree = "<group>"; };
01F2A03123A4498200D954D8 /* CaretLinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaretLinkModel.swift; sourceTree = "<group>"; }; 01F2A03123A4498200D954D8 /* CaretLinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaretLinkModel.swift; sourceTree = "<group>"; };
@ -522,6 +549,7 @@
0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxLabel.swift; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MdnEntryFieldModel.swift; sourceTree = "<group>"; };
@ -532,6 +560,8 @@
0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = "<group>"; }; 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = "<group>"; };
0AA33B33239813C50067DD0F /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.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>"; }; 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>"; }; 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>"; }; 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>"; }; 0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; };
@ -568,8 +598,12 @@
8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = "<group>"; }; 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = "<group>"; };
8D4687E1242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageListItemModel.swift; sourceTree = "<group>"; }; 8D4687E1242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageListItemModel.swift; sourceTree = "<group>"; };
8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageListItem.swift; sourceTree = "<group>"; }; 8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageListItem.swift; sourceTree = "<group>"; };
8D8067D02444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeAllTextAndLinksModel.swift; sourceTree = "<group>"; };
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>"; }; 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>"; }; 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>"; }; 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>"; };
@ -578,8 +612,8 @@
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>"; };
943784F3236B77BB006A1E82 /* GraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = "<group>"; }; 943784F3236B77BB006A1E82 /* Wheel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Wheel.swift; sourceTree = "<group>"; };
943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphViewAnimationHandler.swift; sourceTree = "<group>"; }; 943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WheelAnimationHandler.swift; sourceTree = "<group>"; };
943820832432382400B43AF3 /* WebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = "<group>"; }; 943820832432382400B43AF3 /* WebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = "<group>"; };
94382085243238D100B43AF3 /* WebViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewModel.swift; sourceTree = "<group>"; }; 94382085243238D100B43AF3 /* WebViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewModel.swift; sourceTree = "<group>"; };
9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBarModel.swift; sourceTree = "<group>"; }; 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBarModel.swift; sourceTree = "<group>"; };
@ -610,6 +644,7 @@
94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeTX-Regular.otf"; sourceTree = "<group>"; }; 94CA227B24058533002D6750 /* VerizonNHGeTX-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VerizonNHGeTX-Regular.otf"; sourceTree = "<group>"; };
94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrimaryButtonView.h; sourceTree = "<group>"; }; 94F217B423E0BF6100A47C06 /* PrimaryButtonView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrimaryButtonView.h; sourceTree = "<group>"; };
94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrimaryButtonView.m; sourceTree = "<group>"; }; 94F217B523E0BF6100A47C06 /* PrimaryButtonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrimaryButtonView.m; sourceTree = "<group>"; };
94F6516C2437954100631BF9 /* Tabs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tabs.swift; sourceTree = "<group>"; };
94FB966023D797DA003D482B /* MFTextButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTextButton.h; sourceTree = "<group>"; }; 94FB966023D797DA003D482B /* MFTextButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFTextButton.h; sourceTree = "<group>"; };
94FB966123D797DA003D482B /* MFTextButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTextButton.m; sourceTree = "<group>"; }; 94FB966123D797DA003D482B /* MFTextButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFTextButton.m; sourceTree = "<group>"; };
AA104B1924474A66004D2810 /* HeadersH2Buttons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2Buttons.swift; sourceTree = "<group>"; }; AA104B1924474A66004D2810 /* HeadersH2Buttons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2Buttons.swift; sourceTree = "<group>"; };
@ -618,16 +653,30 @@
AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePaymentsModel.swift; sourceTree = "<group>"; }; AA11A42023F15D7000D7962F /* ListRightVariablePaymentsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePaymentsModel.swift; sourceTree = "<group>"; };
AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDividerModel.swift; sourceTree = "<group>"; }; AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDividerModel.swift; sourceTree = "<group>"; };
AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDivider.swift; sourceTree = "<group>"; }; AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnSpeedTestDivider.swift; sourceTree = "<group>"; };
AA2AD115244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexLinkMedium.swift; sourceTree = "<group>"; };
AA2AD117244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexLinkMediumModel.swift; sourceTree = "<group>"; };
AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDividerModel.swift; sourceTree = "<group>"; }; AA56A20E243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDividerModel.swift; sourceTree = "<group>"; };
AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDivider.swift; sourceTree = "<group>"; }; AA56A210243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnSubsectionDivider.swift; sourceTree = "<group>"; };
AA617AAF2453010A00910B8F /* ListDeviceComplexLinkSmall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexLinkSmall.swift; sourceTree = "<group>"; };
AA617AB12453012400910B8F /* ListDeviceComplexLinkSmallModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexLinkSmallModel.swift; sourceTree = "<group>"; };
AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyText.swift; sourceTree = "<group>"; };
AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyTextModel.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>"; };
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>"; }; 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>"; }; 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>"; }; BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsectionModel.swift; sourceTree = "<group>"; };
BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsection.swift; sourceTree = "<group>"; }; BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextDividerSubsection.swift; sourceTree = "<group>"; };
BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableButtonAllTextAndLinks.swift; sourceTree = "<group>"; }; BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableButtonAllTextAndLinks.swift; sourceTree = "<group>"; };
BB54C51F2434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableButtonAllTextAndLinksModel.swift; sourceTree = "<group>"; }; BB54C51F2434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRightVariableButtonAllTextAndLinksModel.swift; sourceTree = "<group>"; };
BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeBodyText.swift; sourceTree = "<group>"; };
BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariablePriceChangeBodyTextModel.swift; sourceTree = "<group>"; };
BB6C6ABE242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerTallModel.swift; sourceTree = "<group>"; }; BB6C6ABE242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerTallModel.swift; sourceTree = "<group>"; };
BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerTall.swift; sourceTree = "<group>"; }; BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerTall.swift; sourceTree = "<group>"; };
BB6C6AC62422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerShort.swift; sourceTree = "<group>"; }; BB6C6AC62422528F005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListOneColumnTextWithWhitespaceDividerShort.swift; sourceTree = "<group>"; };
@ -652,9 +701,17 @@
C7F8012223E846C300396FBD /* ListRVWheelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRVWheelModel.swift; sourceTree = "<group>"; }; C7F8012223E846C300396FBD /* ListRVWheelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRVWheelModel.swift; sourceTree = "<group>"; };
D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSTextAlignment+Extension.swift"; sourceTree = "<group>"; }; D202AFE3242A5F5E00E5BEDF /* NSTextAlignment+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSTextAlignment+Extension.swift"; sourceTree = "<group>"; };
D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionViewScrollPosition+Extension.swift"; sourceTree = "<group>"; }; D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionViewScrollPosition+Extension.swift"; sourceTree = "<group>"; };
D2092348244A51D40044AD09 /* RadioSwatchModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchModel.swift; sourceTree = "<group>"; };
D209234E244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerCenterTemplate.swift; sourceTree = "<group>"; };
D2092350244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerCenterTemplateModel.swift; sourceTree = "<group>"; };
D2092352244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUIViewControllerMappingObject+Extension.swift"; sourceTree = "<group>"; };
D2092354244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplateModelProtocol.swift; sourceTree = "<group>"; };
D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerModelBase.swift; sourceTree = "<group>"; };
D20923582450ECE00044AD09 /* TableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableView.swift; sourceTree = "<group>"; };
D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = "<group>"; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = "<group>"; };
D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = "<group>"; }; D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = "<group>"; };
D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackView.swift; sourceTree = "<group>"; };
D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = "<group>"; }; D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = "<group>"; };
D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionItemModelProtocol.swift; sourceTree = "<group>"; }; D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionItemModelProtocol.swift; sourceTree = "<group>"; };
D21B7F74243BAC8900051ABF /* CarouselItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselItem.swift; sourceTree = "<group>"; }; D21B7F74243BAC8900051ABF /* CarouselItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselItem.swift; sourceTree = "<group>"; };
@ -714,7 +771,7 @@
D28A837C23CCA86A00DFE4FC /* TabsListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsListItemModel.swift; sourceTree = "<group>"; }; D28A837C23CCA86A00DFE4FC /* TabsListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsListItemModel.swift; sourceTree = "<group>"; };
D28A837E23CCA96400DFE4FC /* TabsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsModel.swift; sourceTree = "<group>"; }; D28A837E23CCA96400DFE4FC /* TabsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsModel.swift; sourceTree = "<group>"; };
D28A838023CCB0D800DFE4FC /* AccordionListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccordionListItemModel.swift; sourceTree = "<group>"; }; D28A838023CCB0D800DFE4FC /* AccordionListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccordionListItemModel.swift; sourceTree = "<group>"; };
D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleProgressModel.swift; sourceTree = "<group>"; }; D28A838223CCBD3F00DFE4FC /* WheelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WheelModel.swift; sourceTree = "<group>"; };
D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollerModel.swift; sourceTree = "<group>"; }; D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollerModel.swift; sourceTree = "<group>"; };
D28A838823CCCFCB00DFE4FC /* LinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkModel.swift; sourceTree = "<group>"; }; D28A838823CCCFCB00DFE4FC /* LinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkModel.swift; sourceTree = "<group>"; };
D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModel.swift; sourceTree = "<group>"; }; D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModel.swift; sourceTree = "<group>"; };
@ -837,7 +894,6 @@
D29E28D723D21AB800ACEA85 /* StringAndMoleculeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAndMoleculeView.swift; sourceTree = "<group>"; }; D29E28D723D21AB800ACEA85 /* StringAndMoleculeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAndMoleculeView.swift; sourceTree = "<group>"; };
D29E28D923D21AFA00ACEA85 /* StringAndMoleculeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAndMoleculeModel.swift; sourceTree = "<group>"; }; D29E28D923D21AFA00ACEA85 /* StringAndMoleculeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAndMoleculeModel.swift; sourceTree = "<group>"; };
D29E28DC23D7404C00ACEA85 /* ContainerHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerHelper.swift; sourceTree = "<group>"; }; D29E28DC23D7404C00ACEA85 /* ContainerHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerHelper.swift; sourceTree = "<group>"; };
D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackView.swift; sourceTree = "<group>"; };
D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackTemplate.swift; sourceTree = "<group>"; }; D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackTemplate.swift; sourceTree = "<group>"; };
D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackCenteredTemplate.swift; sourceTree = "<group>"; }; D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackCenteredTemplate.swift; sourceTree = "<group>"; };
D2A514662213885800345BFB /* MoleculeHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderView.swift; sourceTree = "<group>"; }; D2A514662213885800345BFB /* MoleculeHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderView.swift; sourceTree = "<group>"; };
@ -910,6 +966,7 @@
D28A837823C7D5BC00DFE4FC /* PageModelProtocol.swift */, D28A837823C7D5BC00DFE4FC /* PageModelProtocol.swift */,
011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */, 011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */,
D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */, D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */,
D2092354244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift */,
); );
path = ModelProtocols; path = ModelProtocols;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1051,6 +1108,8 @@
children = ( children = (
8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */, 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */,
8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */, 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */,
8DDD6C1E244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift */,
8DDD6C1C244D90B8006A2232 /* ListThreeColumnDataUsage.swift */,
); );
path = ThreeColumn; path = ThreeColumn;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1099,6 +1158,10 @@
AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */, AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */,
8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */, 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */,
8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */, 8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */,
BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */,
BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */,
8D8067D02444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift */,
8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */,
C7F8012223E846C300396FBD /* ListRVWheelModel.swift */, C7F8012223E846C300396FBD /* ListRVWheelModel.swift */,
C7F8012023E8303200396FBD /* ListRVWheel.swift */, C7F8012023E8303200396FBD /* ListRVWheel.swift */,
); );
@ -1122,6 +1185,9 @@
D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */, D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */,
D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */, D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */,
013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */, 013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */,
0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */,
0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */,
0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */,
); );
path = Extensions; path = Extensions;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1135,6 +1201,19 @@
path = FourColumn; path = FourColumn;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
D20FFFB42451E32100A31DA2 /* Device */ = {
isa = PBXGroup;
children = (
BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */,
BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */,
AA617AB12453012400910B8F /* ListDeviceComplexLinkSmallModel.swift */,
AA617AAF2453010A00910B8F /* ListDeviceComplexLinkSmall.swift */,
AA2AD117244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift */,
AA2AD115244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift */,
);
path = Device;
sourceTree = "<group>";
};
D213347423842FE3008E41B3 /* Controllers */ = { D213347423842FE3008E41B3 /* Controllers */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -1263,6 +1342,7 @@
D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */, D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */,
D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */, D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */,
D28A837E23CCA96400DFE4FC /* TabsModel.swift */, D28A837E23CCA96400DFE4FC /* TabsModel.swift */,
94F6516C2437954100631BF9 /* Tabs.swift */,
011D9625240EBB16000E3791 /* RadioButtonLabelModel.swift */, 011D9625240EBB16000E3791 /* RadioButtonLabelModel.swift */,
017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */, 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */,
); );
@ -1287,8 +1367,7 @@
D260105A23D0BB7100764D80 /* StackModelProtocol.swift */, D260105A23D0BB7100764D80 /* StackModelProtocol.swift */,
D260106423D0CEA700764D80 /* StackModel.swift */, D260106423D0CEA700764D80 /* StackModel.swift */,
D260105C23D0BCD400764D80 /* Stack.swift */, D260105C23D0BCD400764D80 /* Stack.swift */,
01EB368B23609801006832FA /* MoleculeStackModel.swift */, D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */,
D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */,
012A88AE238C626E00FE3DA1 /* CarouselModel.swift */, 012A88AE238C626E00FE3DA1 /* CarouselModel.swift */,
D2A6390022CBB1820052ED1F /* Carousel.swift */, D2A6390022CBB1820052ED1F /* Carousel.swift */,
); );
@ -1334,6 +1413,7 @@
D22B38EA23F4E08B00490EF6 /* List */ = { D22B38EA23F4E08B00490EF6 /* List */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D20FFFB42451E32100A31DA2 /* Device */,
52267A0523FFE0A900906CBA /* OneColumn */, 52267A0523FFE0A900906CBA /* OneColumn */,
D22D8396241FDE4700D3DF69 /* TwoColumn */, D22D8396241FDE4700D3DF69 /* TwoColumn */,
8DD1E36C243B3CD900D8F2DF /* ThreeColumn */, 8DD1E36C243B3CD900D8F2DF /* ThreeColumn */,
@ -1349,6 +1429,8 @@
children = ( children = (
52B201D124081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift */, 52B201D124081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift */,
52B201D024081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift */, 52B201D024081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift */,
AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */,
AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */,
522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */, 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */,
522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */, 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */,
8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */, 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */,
@ -1435,6 +1517,11 @@
01004F2F22721C3800991ECC /* RadioButton.swift */, 01004F2F22721C3800991ECC /* RadioButton.swift */,
31BE15CA23D8924C00452370 /* CheckboxModel.swift */, 31BE15CA23D8924C00452370 /* CheckboxModel.swift */,
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */, 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */,
AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */,
AAB9C10724346F4B00151545 /* RadioSwatches.swift */,
D2092348244A51D40044AD09 /* RadioSwatchModel.swift */,
AAB9C109243496DD00151545 /* RadioSwatch.swift */,
AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */,
); );
path = Selectors; path = Selectors;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1484,6 +1571,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D22D8392241C27B100D3DF69 /* TemplateModel.swift */, D22D8392241C27B100D3DF69 /* TemplateModel.swift */,
D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */,
014AA72823C5059B006F3E93 /* StackPageTemplateModel.swift */, 014AA72823C5059B006F3E93 /* StackPageTemplateModel.swift */,
D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */, D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */,
942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */, 942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */,
@ -1495,6 +1583,8 @@
942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */, 942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */,
014AA72A23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift */, 014AA72A23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift */,
D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */, D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */,
D2092350244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift */,
D209234E244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift */,
D264FAA4243F66A500D98315 /* CollectionTemplateItemProtocol.swift */, D264FAA4243F66A500D98315 /* CollectionTemplateItemProtocol.swift */,
D264FA8B243BCD8E00D98315 /* CollectionTemplateModel.swift */, D264FA8B243BCD8E00D98315 /* CollectionTemplateModel.swift */,
D264FA8D243BCD9A00D98315 /* CollectionTemplate.swift */, D264FA8D243BCD9A00D98315 /* CollectionTemplate.swift */,
@ -1682,9 +1772,9 @@
94C2D9822386F3E30006CF46 /* Label */, 94C2D9822386F3E30006CF46 /* Label */,
31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */, 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */,
0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */, 0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */,
D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */, D28A838223CCBD3F00DFE4FC /* WheelModel.swift */,
943784F3236B77BB006A1E82 /* GraphView.swift */, 943784F3236B77BB006A1E82 /* Wheel.swift */,
943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */, 943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */,
D260105223CEA61600764D80 /* ToggleModel.swift */, D260105223CEA61600764D80 /* ToggleModel.swift */,
0AA33B392398524F0067DD0F /* Toggle.swift */, 0AA33B392398524F0067DD0F /* Toggle.swift */,
0AE98BB623FF18E9004C5109 /* ArrowModel.swift */, 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */,
@ -1747,6 +1837,7 @@
D29DF27421E79E81003B2FB9 /* MVMCoreUILoggingHandler.m */, D29DF27421E79E81003B2FB9 /* MVMCoreUILoggingHandler.m */,
D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */, D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */,
D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */, D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */,
D2092352244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift */,
D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */, D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */,
); );
path = OtherHandlers; path = OtherHandlers;
@ -1852,6 +1943,7 @@
D2B18B7E2360913400A9AEDC /* Control.swift */, D2B18B7E2360913400A9AEDC /* Control.swift */,
D2B18B802360945C00A9AEDC /* View.swift */, D2B18B802360945C00A9AEDC /* View.swift */,
0AE14F63238315D2005417F8 /* TextField.swift */, 0AE14F63238315D2005417F8 /* TextField.swift */,
D20923582450ECE00044AD09 /* TableView.swift */,
D2755D7A23689C7500485468 /* TableViewCell.swift */, D2755D7A23689C7500485468 /* TableViewCell.swift */,
D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */, D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */,
D264FAA92440F97600D98315 /* CollectionView.swift */, D264FAA92440F97600D98315 /* CollectionView.swift */,
@ -2046,10 +2138,11 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */,
5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */, 5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */,
0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */, 0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */,
8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */, 8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */,
943784F5236B77BB006A1E82 /* GraphView.swift in Sources */, 943784F5236B77BB006A1E82 /* Wheel.swift in Sources */,
31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */, 31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */,
8D3BA9BF2433789900D341BA /* ListThreeColumnInternationalDataDivider.swift in Sources */, 8D3BA9BF2433789900D341BA /* ListThreeColumnInternationalDataDivider.swift in Sources */,
94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */, 94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */,
@ -2062,6 +2155,7 @@
D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */, D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */,
D28A838923CCCFCB00DFE4FC /* LinkModel.swift in Sources */, D28A838923CCCFCB00DFE4FC /* LinkModel.swift in Sources */,
AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */, AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */,
AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */,
94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */, 94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */,
DBC4391922442197001AB423 /* DashLine.swift in Sources */, DBC4391922442197001AB423 /* DashLine.swift in Sources */,
D264FAAA2440F97600D98315 /* CollectionView.swift in Sources */, D264FAAA2440F97600D98315 /* CollectionView.swift in Sources */,
@ -2070,12 +2164,15 @@
AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */, AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */,
D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */,
0116A4E5228B19640094F3ED /* RadioButtonSelectionHelper.swift in Sources */, 0116A4E5228B19640094F3ED /* RadioButtonSelectionHelper.swift in Sources */,
D2092353244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift in Sources */,
017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */, 017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */,
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */, D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */,
94382086243238D100B43AF3 /* WebViewModel.swift in Sources */, 94382086243238D100B43AF3 /* WebViewModel.swift in Sources */,
D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */, D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */,
D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */, D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */,
D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */,
0A6682A42434DB8D00AD3CA1 /* ListLeftVariableRadioButtonBodyTextModel.swift in Sources */, 0A6682A42434DB8D00AD3CA1 /* ListLeftVariableRadioButtonBodyTextModel.swift in Sources */,
AA2AD116244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift in Sources */,
D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */,
D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */, D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */,
01004F3022721C3800991ECC /* RadioButton.swift in Sources */, 01004F3022721C3800991ECC /* RadioButton.swift in Sources */,
@ -2091,6 +2188,7 @@
942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */, 942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */,
BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */, BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */,
012A88C8238DB02000FE3DA1 /* MoleculeDelegateProtocol.swift in Sources */, 012A88C8238DB02000FE3DA1 /* MoleculeDelegateProtocol.swift in Sources */,
8D8067D12444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift in Sources */,
0A7EF86123D8AC2500B2AAD1 /* DigitEntryFieldModel.swift in Sources */, 0A7EF86123D8AC2500B2AAD1 /* DigitEntryFieldModel.swift in Sources */,
DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */, DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */,
D224798C231450C8003FCCF9 /* HeadlineBodyToggle.swift in Sources */, D224798C231450C8003FCCF9 /* HeadlineBodyToggle.swift in Sources */,
@ -2105,10 +2203,13 @@
D2E2A98323D8B32D000B42E6 /* EyebrowHeadlineBodyLinkModel.swift in Sources */, D2E2A98323D8B32D000B42E6 /* EyebrowHeadlineBodyLinkModel.swift in Sources */,
012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */, 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */,
BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */, BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */,
D2092351244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift in Sources */,
D21B7F77243BB70700051ABF /* MoleculeCollectionItemModel.swift in Sources */, D21B7F77243BB70700051ABF /* MoleculeCollectionItemModel.swift in Sources */,
AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */,
D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */,
011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */, 011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */,
D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */, D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */,
AA617AB22453012400910B8F /* ListDeviceComplexLinkSmallModel.swift in Sources */,
D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, D260106323D0C05000764D80 /* StackItemModel.swift in Sources */,
D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */, D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */,
BBBBC87D24374A4900B0F079 /* ListThreeColumnBillChangesDividerModel.swift in Sources */, BBBBC87D24374A4900B0F079 /* ListThreeColumnBillChangesDividerModel.swift in Sources */,
@ -2120,6 +2221,7 @@
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */, D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */,
D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */, D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */,
AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */, AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */,
BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */,
D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */, D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */,
D28A837B23C928DA00DFE4FC /* MoleculeListCellProtocol.swift in Sources */, D28A837B23C928DA00DFE4FC /* MoleculeListCellProtocol.swift in Sources */,
014AA72F23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift in Sources */, 014AA72F23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift in Sources */,
@ -2128,7 +2230,6 @@
D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */, D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */,
D28A838B23CCDA6B00DFE4FC /* ButtonModel.swift in Sources */, D28A838B23CCDA6B00DFE4FC /* ButtonModel.swift in Sources */,
D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */, D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */,
D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */,
C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */, C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */,
D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */,
C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */, C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */,
@ -2155,8 +2256,8 @@
0A21DB85235E06EF00C160A2 /* MFTextField.m in Sources */, 0A21DB85235E06EF00C160A2 /* MFTextField.m in Sources */,
014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */, 014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */,
AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */, AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */,
01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */,
011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */, 011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */,
8DDD6C1D244D90B8006A2232 /* ListThreeColumnDataUsage.swift in Sources */,
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */, AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */,
D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */, D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */,
944589232385DA9600DE9FD4 /* ImageViewModel.swift in Sources */, 944589232385DA9600DE9FD4 /* ImageViewModel.swift in Sources */,
@ -2165,10 +2266,12 @@
525019DE2406430800EED91C /* ListProgressBarData.swift in Sources */, 525019DE2406430800EED91C /* ListProgressBarData.swift in Sources */,
D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */, D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */,
012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */, 012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */,
8DDD6C1F244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift in Sources */,
BB55B51F244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift in Sources */,
D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */, D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */,
D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */, D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */,
01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */, 01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */,
D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */, D28A838323CCBD3F00DFE4FC /* WheelModel.swift in Sources */,
EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */, EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */,
D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */, D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */,
DBEFFA04225A829700230692 /* Label.swift in Sources */, DBEFFA04225A829700230692 /* Label.swift in Sources */,
@ -2182,19 +2285,25 @@
01509D952327ED1900EF99AA /* HeadlineBodyLinkToggle.swift in Sources */, 01509D952327ED1900EF99AA /* HeadlineBodyLinkToggle.swift in Sources */,
31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */, 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */,
D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */, D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */,
94F6516D2437954100631BF9 /* Tabs.swift in Sources */,
5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */, 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */,
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */, 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */,
D264FA8E243BCD9A00D98315 /* CollectionTemplate.swift in Sources */, D264FA8E243BCD9A00D98315 /* CollectionTemplate.swift in Sources */,
0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */, 0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */,
8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */, 8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */,
94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */, 94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */,
D2092357244FA1EF0044AD09 /* ThreeLayerModelBase.swift in Sources */,
0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */, 0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */,
0A21DB8B235E06EF00C160A2 /* MFDigitTextBox.m in Sources */, 0A21DB8B235E06EF00C160A2 /* MFDigitTextBox.m in Sources */,
D20923592450ECE00044AD09 /* TableView.swift in Sources */,
D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */, D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */,
BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */, BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */,
AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */,
D2B18B812360945C00A9AEDC /* View.swift in Sources */, D2B18B812360945C00A9AEDC /* View.swift in Sources */,
C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */, C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */,
0A7ECC702441001C00C828E8 /* UIToolbar+Extension.swift in Sources */,
D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */, D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */,
D209234F244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift in Sources */,
525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */, 525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */,
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */, 0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */,
94FB966323D797DA003D482B /* MFTextButton.m in Sources */, 94FB966323D797DA003D482B /* MFTextButton.m in Sources */,
@ -2210,12 +2319,14 @@
D260105D23D0BCD400764D80 /* Stack.swift in Sources */, D260105D23D0BCD400764D80 /* Stack.swift in Sources */,
0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */, 0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */,
BB54C5212434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift in Sources */, BB54C5212434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift in Sources */,
D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */,
8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */, 8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */,
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */, D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */,
01EB368F23609801006832FA /* LabelModel.swift in Sources */, 01EB368F23609801006832FA /* LabelModel.swift in Sources */,
0A6682AC243531C300AD3CA1 /* Padding.swift in Sources */, 0A6682AC243531C300AD3CA1 /* Padding.swift in Sources */,
AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */, AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */,
942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */, 942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */,
8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */,
8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */, 8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */,
01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */, 01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */,
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */, 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */,
@ -2223,6 +2334,7 @@
D22479962316AF6E003FCCF9 /* HeadlineBodyLink.swift in Sources */, D22479962316AF6E003FCCF9 /* HeadlineBodyLink.swift in Sources */,
D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */, D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */,
0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */, 0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */,
BB55B51D244482C1002001AD /* ListRightVariablePriceChangeBodyText.swift in Sources */,
017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */, 017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */,
D29DF18121E69E50003B2FB9 /* MFView.m in Sources */, D29DF18121E69E50003B2FB9 /* MFView.m in Sources */,
D28A837923C7D5BC00DFE4FC /* PageModelProtocol.swift in Sources */, D28A837923C7D5BC00DFE4FC /* PageModelProtocol.swift in Sources */,
@ -2246,6 +2358,7 @@
C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */, C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */,
011D958524042432000E3791 /* RulesProtocol.swift in Sources */, 011D958524042432000E3791 /* RulesProtocol.swift in Sources */,
94AF4A3F23E9D13900676048 /* MFCaretButton.m in Sources */, 94AF4A3F23E9D13900676048 /* MFCaretButton.m in Sources */,
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */,
D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */, D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */,
D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */,
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */,
@ -2281,6 +2394,7 @@
525019E72406853600EED91C /* ListFourColumnDataUsageDivider.swift in Sources */, 525019E72406853600EED91C /* ListFourColumnDataUsageDivider.swift in Sources */,
0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */, 0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */,
D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */, D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */,
AA2AD118244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift in Sources */,
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */, DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */,
0A21DB89235E06EF00C160A2 /* MFMdnTextField.m in Sources */, 0A21DB89235E06EF00C160A2 /* MFMdnTextField.m in Sources */,
D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */, D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */,
@ -2293,9 +2407,12 @@
94C0150A24215643005811A9 /* ActionTopAlertModel.swift in Sources */, 94C0150A24215643005811A9 /* ActionTopAlertModel.swift in Sources */,
012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */, 012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */,
D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */,
D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */,
0AE14F64238315D2005417F8 /* TextField.swift in Sources */, 0AE14F64238315D2005417F8 /* TextField.swift in Sources */,
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */,
D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */, D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */,
D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */, D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */,
AA617AB02453010A00910B8F /* ListDeviceComplexLinkSmall.swift in Sources */,
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 */,
@ -2324,11 +2441,12 @@
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */, 0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */,
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */, AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */,
D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */, D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */,
AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */,
52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */, 52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */,
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */, D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */,
0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */, 0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */,
94AF4A4323E9D19E00676048 /* MFCaretView.m in Sources */, 94AF4A4323E9D19E00676048 /* MFCaretView.m in Sources */,
943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */, 943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */,
011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */, 011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */,
D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */,
011D95892404249B000E3791 /* FormHolderModelProtocol.swift in Sources */, 011D95892404249B000E3791 /* FormHolderModelProtocol.swift in Sources */,
@ -2360,6 +2478,7 @@
AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */, AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */,
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */, C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */, D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */,
D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */, D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */,
0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */, 0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */,
0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */, 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */,
@ -2376,6 +2495,7 @@
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */, 8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */,
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */, D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */,
012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */, 012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */,
0AB764D324460FA400E7FE72 /* UIPickerView+Extension.swift in Sources */,
D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */, D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */,
94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */, 94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */,
011D95AB2405C553000E3791 /* FormItemProtocol.swift in Sources */, 011D95AB2405C553000E3791 /* FormItemProtocol.swift in Sources */,

View File

@ -9,9 +9,14 @@
import UIKit import UIKit
@objcMembers public class ActionCollapseNotificationModel: ActionModelProtocol { @objcMembers public class ActionCollapseNotificationModel: ActionModelProtocol {
public static var identifier: String = "collapseNotification" public static var identifier: String = "collapseNotification"
public var actionType: String public var actionType: String = ActionCollapseNotificationModel.identifier
public var extraParameters: JSONValueDictionary? public var extraParameters: JSONValueDictionary?
public var analyticsData: JSONValueDictionary? public var analyticsData: JSONValueDictionary?
public var title: String?
public init(_ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
self.extraParameters = extraParameters
self.analyticsData = analyticsData
}
} }

View File

@ -9,7 +9,7 @@
import Foundation import Foundation
public class ActionOpenPanelModel: ActionModelProtocol { public class ActionOpenPanelModel: ActionModelProtocol {
public enum Panel: String, Codable { public enum Panel: String, Codable {
case left case left
case right case right
@ -22,10 +22,10 @@ public class ActionOpenPanelModel: ActionModelProtocol {
public var panel: Panel public var panel: Panel
public var extraParameters: JSONValueDictionary? public var extraParameters: JSONValueDictionary?
public var analyticsData: JSONValueDictionary? public var analyticsData: JSONValueDictionary?
// Temporary fix till server changes
public var title: String?
public init(panel: Panel) { public init(panel: Panel, _ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
self.panel = panel self.panel = panel
self.extraParameters = extraParameters
self.analyticsData = analyticsData
} }
} }

View File

@ -9,15 +9,16 @@
import Foundation import Foundation
@objcMembers public class ActionTopAlertModel: ActionModelProtocol { @objcMembers public class ActionTopAlertModel: ActionModelProtocol {
public static var identifier: String = "topAlert" public static var identifier: String = "topAlert"
public var actionType: String = ActionTopAlertModel.identifier public var actionType: String = ActionTopAlertModel.identifier
public var pageType: String public var pageType: String
public var extraParameters: JSONValueDictionary? public var extraParameters: JSONValueDictionary?
public var analyticsData: JSONValueDictionary? public var analyticsData: JSONValueDictionary?
// Temporary fix till server changes
public var title: String?
public init(pageType: String) { public init(pageType: String, _ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
self.pageType = pageType self.pageType = pageType
self.extraParameters = extraParameters
self.analyticsData = analyticsData
} }
} }

View File

@ -25,7 +25,7 @@ open class ExternalLink: Link {
guard let model = model as? ExternalLinkModel else { return } guard let model = model as? ExternalLinkModel else { return }
exportImageView?.tintColor = model.textColor.uiColor exportImageView?.tintColor = model.enabledColor.uiColor
} }
//-------------------------------------------------- //--------------------------------------------------

View File

@ -52,7 +52,7 @@ import UIKit
guard let model = model as? LinkModel else { return } guard let model = model as? LinkModel else { return }
setTitle(model.title, for: .normal) setTitle(model.title, for: .normal)
setTitleColor(model.textColor.uiColor, for: .normal) setTitleColor(model.enabledColor.uiColor, for: .normal)
setTitleColor(model.disabledColor.uiColor, for: .disabled) setTitleColor(model.disabledColor.uiColor, for: .disabled)
isEnabled = model.enabled isEnabled = model.enabled
set(with: model.action, delegateObject: delegateObject, additionalData: additionalData) set(with: model.action, delegateObject: delegateObject, additionalData: additionalData)

View File

@ -21,7 +21,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol {
public var title: String public var title: String
public var action: ActionModelProtocol public var action: ActionModelProtocol
public var enabled = true public var enabled = true
public var textColor = Color(uiColor: .mvmBlack) public var enabledColor = Color(uiColor: .mvmBlack)
public var disabledColor = Color(uiColor: .mvmCoolGray6) public var disabledColor = Color(uiColor: .mvmCoolGray6)
//-------------------------------------------------- //--------------------------------------------------
@ -43,7 +43,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol {
case title case title
case action case action
case enabled case enabled
case textColor case enabledColor
case disabledColor case disabledColor
} }
@ -60,8 +60,8 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol {
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
self.enabled = enabled self.enabled = enabled
} }
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor) { if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledColor) {
textColor = color enabledColor = color
} }
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor) { if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor) {
@ -76,7 +76,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol {
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeModel(action, forKey: .action) try container.encodeModel(action, forKey: .action)
try container.encode(enabled, forKey: .enabled) try container.encode(enabled, forKey: .enabled)
try container.encode(textColor, forKey: .textColor) try container.encode(enabledColor, forKey: .enabledColor)
try container.encode(disabledColor, forKey: .disabledColor) try container.encode(disabledColor, forKey: .disabledColor)
} }
} }

View File

@ -19,13 +19,14 @@ import UIKit
widthConstraint?.constant = diameter widthConstraint?.constant = diameter
} }
} }
public override var isSelected: Bool { public override var isSelected: Bool {
didSet { didSet {
radioModel?.state = isSelected radioModel?.state = isSelected
updateAccessibilityLabel()
} }
} }
public var enabledColor: UIColor = .mvmBlack public var enabledColor: UIColor = .mvmBlack
public var disabledColor: UIColor = .mvmCoolGray3 public var disabledColor: UIColor = .mvmCoolGray3
public var delegateObject: MVMCoreUIDelegateObject? public var delegateObject: MVMCoreUIDelegateObject?
@ -39,12 +40,12 @@ import UIKit
}() }()
lazy public var radioButtonSelectionHelper: RadioButtonSelectionHelper? = { lazy public var radioButtonSelectionHelper: RadioButtonSelectionHelper? = {
if let radioGroupName = radioGroupName,
let radioButtonModel = delegateObject?.formHolderDelegate?.formValidator?.radioButtonsModelByGroup[radioGroupName] { guard let radioGroupName = radioGroupName,
return radioButtonModel let radioButtonModel = delegateObject?.formHolderDelegate?.formValidator?.radioButtonsModelByGroup[radioGroupName]
} else { else { return nil }
return nil
} return radioButtonModel
}() }()
public override var isEnabled: Bool { public override var isEnabled: Bool {
@ -90,6 +91,9 @@ import UIKit
/// The action performed when tapped. /// The action performed when tapped.
func tapAction() { func tapAction() {
if !isEnabled {
return
}
if let radioButtonModel = radioButtonSelectionHelper { if let radioButtonModel = radioButtonSelectionHelper {
radioButtonModel.selected(self) radioButtonModel.selected(self)
} else { } else {
@ -115,6 +119,18 @@ import UIKit
return radioModel?.fieldValue return radioModel?.fieldValue
} }
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
/// Adjust accessibility label based on state of RadioButton.
func updateAccessibilityLabel() {
if let state = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "radio_selected_state" : "radio_not_selected_state") {
accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "radio_desc_state") ?? "%@%@", "", state)
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - MVMViewProtocol // MARK: - MVMViewProtocol
//-------------------------------------------------- //--------------------------------------------------
@ -133,14 +149,15 @@ import UIKit
isAccessibilityElement = true isAccessibilityElement = true
accessibilityTraits = .button accessibilityTraits = .button
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint")
updateAccessibilityLabel()
} }
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
self.delegateObject = delegateObject
guard let model = model as? RadioButtonModel else { return } guard let model = model as? RadioButtonModel else { return }
self.delegateObject = delegateObject
isSelected = model.state isSelected = model.state
isEnabled = model.enabled isEnabled = model.enabled
RadioButtonSelectionHelper.setupForRadioButtonGroup(model, self, delegateObject: delegateObject) RadioButtonSelectionHelper.setupForRadioButtonGroup(model, self, delegateObject: delegateObject)

View File

@ -0,0 +1,166 @@
//
// RadioSwatch.swift
// MVMCoreUI
//
// Created by Lekshmi S on 01/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
import UIKit
open class RadioSwatch: Control {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public let bottomText = Label.createLabelRegularMicro(true)
private var circleLayer: CAShapeLayer?
private var selectedLayer: CALayer?
private var strikeLayer: CALayer?
private var maskLayer: CALayer?
public var radioSwatchModel: RadioSwatchModel? {
return model as? RadioSwatchModel
}
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func updateView(_ size: CGFloat) {
super.updateView(size)
bottomText.updateView(size)
layer.setNeedsDisplay()
}
open override func setupView() {
super.setupView()
addSubview(bottomText)
bottomText.textAlignment = .center
NSLayoutConstraint.constraintPinSubview(bottomText, pinTop: true, topConstant: 38, pinBottom: true, bottomConstant: 0, pinLeft: true, leftConstant: 0, pinRight: true, rightConstant: 0)
addTarget(self, action: #selector(selectSwatch), for: .touchUpInside)
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? RadioSwatchModel else { return }
isSelected = model.selected
isEnabled = model.enabled
bottomText.text = model.text
}
public override func reset() {
super.reset()
isSelected = false
isEnabled = true
bottomText.text = nil
}
//------------------------------------------------------
// MARK: - State Handling
//------------------------------------------------------
open override func draw(_ layer: CALayer, in ctx: CGContext) {
//Draw the swatch
circleLayer?.removeFromSuperlayer()
let circle = getCircle(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1)
layer.addSublayer(circle)
circleLayer = circle
//Draw the strikethrough
strikeLayer?.removeFromSuperlayer()
if radioSwatchModel?.strikethrough ?? false {
let line = getStrikeThrough(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1)
layer.addSublayer(line)
strikeLayer = line
}
//Draw the selected layer
selectedLayer?.removeFromSuperlayer()
if isSelected {
let outerCircle = getSelectedLayer(color: isSelected ? .mvmBlack : .mvmCoolGray6, thickness: 1)
layer.addSublayer(outerCircle)
selectedLayer = outerCircle
bottomText.isHidden = false
} else {
bottomText.isHidden = true
}
//Handle Mask
maskLayer?.removeFromSuperlayer()
if !isEnabled {
let mask = getMaskLayer()
layer.mask = mask
maskLayer = mask
}
}
open override func layoutSubviews() {
super.layoutSubviews()
// Accounts for any size changes
layer.setNeedsDisplay()
}
@objc open func selectSwatch() {
guard isEnabled else { return }
isSelected = true
radioSwatchModel?.selected = isSelected
layer.setNeedsDisplay()
}
@objc open func deselectSwatch() {
isSelected = false
radioSwatchModel?.selected = isSelected
layer.setNeedsDisplay()
}
func getCircle(color: UIColor, thickness: CGFloat) -> CAShapeLayer {
let circle = CAShapeLayer()
circle.name = "innercircle"
circle.fillColor = radioSwatchModel?.color.cgColor ?? UIColor.blue.cgColor
circle.opacity = 1.0
circle.lineWidth = thickness
circle.strokeColor = color.cgColor
let circlePath = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30))
circle.path = circlePath.cgPath
return circle
}
func getStrikeThrough(color: UIColor, thickness: CGFloat) -> CAShapeLayer {
let strikeThrough = CAShapeLayer()
strikeThrough.name = "strikethrough"
strikeThrough.fillColor = nil
strikeThrough.opacity = 1.0
strikeThrough.lineWidth = thickness
strikeThrough.strokeColor = color.cgColor
let linePath = UIBezierPath()
linePath.move(to: CGPoint(x: 12, y: 31))
linePath.addLine(to: CGPoint(x: 42, y: 1))
strikeThrough.path = linePath.cgPath
return strikeThrough
}
func getSelectedLayer(color: UIColor, thickness: CGFloat) -> CAShapeLayer {
circleLayer?.path = UIBezierPath(ovalIn: CGRect(x: 15, y: 4, width: 24, height: 24)).cgPath
let circle = CAShapeLayer()
circle.name = "outercircle"
circle.fillColor = UIColor.clear.cgColor
circle.opacity = 1.0
circle.lineWidth = thickness
circle.strokeColor = color.cgColor
let circlePath = UIBezierPath(ovalIn: CGRect(x: 12, y: 1, width: 30, height: 30))
circle.path = circlePath.cgPath
return circle
}
func getMaskLayer() -> CALayer {
let mask = CALayer()
mask.backgroundColor = UIColor.white.cgColor
mask.opacity = 0.3
mask.frame = bounds
return mask
}
}

View File

@ -0,0 +1,23 @@
//
// RadioSwatchCollectionViewCell.swift
// MVMCoreUI
//
// Created by Lekshmi S on 13/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
open class RadioSwatchCollectionViewCell: CollectionViewCell {
public let radioSwatch = RadioSwatch()
open override func setupView() {
super.setupView()
addMolecule(radioSwatch)
MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0)
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let model = model as? RadioSwatchModel else { return }
radioSwatch.set(with: model, delegateObject, additionalData)
}
}

View File

@ -0,0 +1,64 @@
//
// RadioSwatchModel.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 4/17/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class RadioSwatchModel: MoleculeModelProtocol {
public static var identifier: String = "radioSwatch"
public var backgroundColor: Color?
public var color: Color = Color(uiColor: .mvmBlue)
public var text: String?
public var selected: Bool = false
public var enabled: Bool = true
public var strikethrough: Bool = false
public var fieldValue: String?
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case color
case text
case selected
case enabled
case strikethrough
case fieldValue
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) {
self.color = color
}
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
if let selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) {
self.selected = selected
}
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
self.enabled = enabled
}
if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) {
self.strikethrough = strikethrough
}
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encode(color, forKey: .color)
try container.encodeIfPresent(text, forKey: .text)
try container.encode(selected, forKey: .selected)
try container.encode(enabled, forKey: .enabled)
try container.encode(strikethrough, forKey: .strikethrough)
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
}
}

View File

@ -0,0 +1,152 @@
//
// RadioSwatches.swift
// MVMCoreUI
//
// Created by Lekshmi S on 01/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
open class RadioSwatches: View {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var collectionView: CollectionView!
public var swatches: [RadioSwatchModel]?
private var size: CGFloat?
private var delegateObject: MVMCoreUIDelegateObject?
//------------------------------------------------------
// MARK: - Constraints
//------------------------------------------------------
public var collectionViewHeight: NSLayoutConstraint?
private let cellSize: CGFloat = 54.0
private let itemSpacing: CGFloat = 8.0
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func layoutSubviews() {
super.layoutSubviews()
// Accounts for any collection size changes
setHeight()
DispatchQueue.main.async {
self.collectionView.collectionViewLayout.invalidateLayout()
}
}
open override func setupView() {
super.setupView()
collectionView = createCollectionView()
addSubview(collectionView)
NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView)
collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 100)
collectionViewHeight?.isActive = true
}
@objc override open func updateView(_ size: CGFloat) {
super.updateView(size)
self.size = size
collectionView.updateView(size)
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
self.delegateObject = delegateObject
guard let radioSwatchesModel = model as? RadioSwatchesModel else { return }
swatches = radioSwatchesModel.swatches
FormValidator.setupValidation(for: radioSwatchesModel, delegate: delegateObject?.formHolderDelegate)
collectionView.reloadData()
}
//------------------------------------------------------
// MARK: - Methods
//------------------------------------------------------
/// Creates the collection view.
open func createCollectionView() -> CollectionView {
let collection = CollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout())
collection.dataSource = self
collection.delegate = self
collection.register(RadioSwatchCollectionViewCell.self, forCellWithReuseIdentifier: "RadioSwatchCollectionViewCell")
return collection
}
/// Creates the layout for the collection.
open func createCollectionViewLayout() -> UICollectionViewLayout {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = itemSpacing
layout.minimumInteritemSpacing = itemSpacing
return layout
}
open func setHeight() {
guard let swatches = swatches, swatches.count > 0 else {
collectionViewHeight?.constant = 0
return
}
// Calculate the height
let swatchesInRow = floor(CGFloat(collectionView.bounds.width/(cellSize + itemSpacing)))
let numberOfRows = ceil(CGFloat(swatches.count)/swatchesInRow)
let height = (numberOfRows * cellSize) + (itemSpacing * (numberOfRows-1))
if let oldHeight = collectionViewHeight?.constant,
height != oldHeight {
// Notify delegate of height change, called async to avoid various race conditions caused while happening while laying out initially.
DispatchQueue.main.async {
self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
}
}
collectionViewHeight?.constant = CGFloat(height)
}
}
//------------------------------------------------------
// MARK: - Delegate methods
//------------------------------------------------------
extension RadioSwatches: UICollectionViewDelegateFlowLayout {
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: cellSize, height: cellSize)
}
}
extension RadioSwatches: UICollectionViewDataSource {
open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return swatches?.count ?? 0
}
open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let molecule = swatches?[indexPath.row], let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioSwatchCollectionViewCell", for: indexPath) as? RadioSwatchCollectionViewCell else {
fatalError()
}
cell.reset()
cell.radioSwatch.isUserInteractionEnabled = false
cell.set(with: molecule, delegateObject, nil)
cell.updateView(size ?? collectionView.bounds.width)
if molecule.selected {
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically)
}
cell.layoutIfNeeded()
return cell
}
}
extension RadioSwatches: UICollectionViewDelegate {
open func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
guard let molecule = swatches?[indexPath.row] else { return false }
return molecule.enabled
}
open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchCollectionViewCell else { return }
cell.radioSwatch.selectSwatch()
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
}
open func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchCollectionViewCell else { return }
cell.radioSwatch.deselectSwatch()
}
}

View File

@ -0,0 +1,54 @@
//
// RadioSwatchesModel.swift
// MVMCoreUI
//
// Created by Lekshmi S on 31/03/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class RadioSwatchesModel: MoleculeModelProtocol, FormFieldProtocol {
public static var identifier: String = "radioSwatches"
public var backgroundColor: Color?
public var swatches: [RadioSwatchModel]
public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable?
/// Returns the fieldValue of the selected swatch, otherwise the text of selected swatch.
public func formFieldValue() -> AnyHashable? {
let selectedSwatch = swatches.first { (swatch) -> Bool in
return swatch.selected
}
return selectedSwatch?.fieldValue ?? selectedSwatch?.text
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case swatches
case fieldKey
case groupName
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
swatches = try typeContainer.decode([RadioSwatchModel].self, forKey: .swatches)
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
self.groupName = groupName
}
baseValue = formFieldValue()
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encode(swatches, forKey: .swatches)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encode(groupName, forKey: .groupName)
}
}

View File

@ -69,7 +69,7 @@ import UIKit
textFieldTrailingConstraint = dropDownCaretView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 6) textFieldTrailingConstraint = dropDownCaretView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 6)
textFieldTrailingConstraint?.isActive = true 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 dropDownCaretView.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
} }

View File

@ -31,10 +31,9 @@ import UIKit
return formatter return formatter
}() }()
/// Update the property value to alter the format of how the date is presented.
public var dateFormat: String = "MMM d, y" { public var dateFormat: String = "MMM d, y" {
didSet { didSet { dateFormatter.dateFormat = dateFormat }
dateFormatter.dateFormat = dateFormat
}
} }
//-------------------------------------------------- //--------------------------------------------------
@ -69,10 +68,10 @@ import UIKit
public override func setupFieldContainerContent(_ container: UIView) { public override func setupFieldContainerContent(_ container: UIView) {
super.setupFieldContainerContent(container) super.setupFieldContainerContent(container)
datePicker = MVMCoreUICommonViewsUtility.addDatePicker(to: textField) datePicker = UIDatePicker.addDatePicker(to: textField)
datePicker?.addTarget(self, action: #selector(pickerValueChanged), for: .valueChanged) datePicker?.addTarget(self, action: #selector(pickerValueChanged), for: .valueChanged)
datePicker?.timeZone = NSTimeZone.system 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) { @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) setTextWith(date: datePicker?.date)
super.dismissFieldInput(sender) super.dismissFieldInput(sender)

View File

@ -22,24 +22,25 @@
//-------------------------------------------------- //--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName
case dateFormat case dateFormat
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Codec
//-------------------------------------------------- //--------------------------------------------------
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)
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 { 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.encode(moleculeName, forKey: .moleculeName)
try container.encode(dateFormat, forKey: .dateFormat) try container.encode(dateFormat, forKey: .dateFormat)
} }
} }

View File

@ -211,7 +211,9 @@ import UIKit
let digitBox = DigitBox() let digitBox = DigitBox()
digitBox.isAccessibilityElement = true 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.digitField.delegate = self
digitBox.digitBoxDelegate = self digitBox.digitBoxDelegate = self
return digitBox 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) { @objc public func selectPreviousDigitField(_ currentTextField: UITextField?, clear: Bool) {
var selectPreviousField = false var selectPreviousField = false
@ -322,7 +315,7 @@ import UIKit
return true return true
} }
@objc override func dismissFieldInput(_ sender: Any?) { @objc public override func dismissFieldInput(_ sender: Any?) {
digitBoxes.forEach { digitBoxes.forEach {
if $0.isSelected { if $0.isSelected {
@ -337,12 +330,18 @@ import UIKit
guard let model = model as? DigitEntryFieldModel else { return } guard let model = model as? DigitEntryFieldModel else { return }
numberOfDigits = model.digits numberOfDigits = model.digits
setAsSecureTextEntry(model.secureEntry)
for digitBox in digitBoxes { if let entryType = model.type {
digitBox.digitField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: delegateObject?.observingTextFieldDelegate ?? self) 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) super.set(with: model, delegateObject, additionalData)
} }

View File

@ -17,34 +17,31 @@
} }
public var digits: Int = 4 public var digits: Int = 4
public var secureEntry: Bool = false
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
//-------------------------------------------------- //--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName
case digits case digits
case secureEntry
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Codec
//-------------------------------------------------- //--------------------------------------------------
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)
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 { 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.encode(moleculeName, forKey: .moleculeName)
try container.encode(digits, forKey: .digits) try container.encode(digits, forKey: .digits)
try container.encode(secureEntry, forKey: .secureEntry)
} }
} }

View File

@ -20,7 +20,7 @@ import UIKit
public private(set) var titleLabel: Label = { public private(set) var titleLabel: Label = {
let label = Label() let label = Label()
label.font = MFStyler.fontRegularMicro() label.font = Styler.Font.RegularMicro.getFont()
label.textColor = .mvmBlack label.textColor = .mvmBlack
label.setContentCompressionResistancePriority(.required, for: .vertical) label.setContentCompressionResistancePriority(.required, for: .vertical)
return label return label
@ -31,31 +31,23 @@ import UIKit
/// Provides contextual information on the TextField. /// Provides contextual information on the TextField.
public private(set) var feedbackLabel: Label = { public private(set) var feedbackLabel: Label = {
let label = Label() let label = Label()
label.font = MFStyler.fontRegularMicro() label.font = Styler.Font.RegularMicro.getFont()
label.textColor = .mvmBlack label.textColor = .mvmBlack
label.setContentCompressionResistancePriority(.required, for: .vertical) label.setContentCompressionResistancePriority(.required, for: .vertical)
return label return label
}() }()
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Delegate // MARK: - Delegate
//-------------------------------------------------- //--------------------------------------------------
weak var delegateObject: MVMCoreUIDelegateObject? var delegateObject: MVMCoreUIDelegateObject?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Stored Properties // MARK: - Stored Properties
//-------------------------------------------------- //--------------------------------------------------
public var isValid: Bool = false public var isValid: Bool = false
public var errorMessage: String?
public var standardMessage: String? {
didSet {
if !showError {
feedback = standardMessage
}
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Computed Properties // MARK: - Computed Properties
@ -75,7 +67,7 @@ import UIKit
public var showError: Bool { public var showError: Bool {
get { return entryFieldContainer.showError } get { return entryFieldContainer.showError }
set (error) { set (error) {
self.feedback = error ? self.errorMessage : self.standardMessage self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.feedback
self.entryFieldContainer.showError = error self.entryFieldContainer.showError = error
} }
} }
@ -121,6 +113,10 @@ import UIKit
} }
} }
public var entryFieldModel: EntryFieldModel? {
return model as? EntryFieldModel
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Constraints // MARK: - Constraints
//-------------------------------------------------- //--------------------------------------------------
@ -174,8 +170,6 @@ import UIKit
@objc final public override func setupView() { @objc final public override func setupView() {
super.setupView() super.setupView()
guard subviews.isEmpty else { return }
isAccessibilityElement = false isAccessibilityElement = false
setContentCompressionResistancePriority(.required, for: .vertical) setContentCompressionResistancePriority(.required, for: .vertical)
accessibilityElements = [titleLabel, feedbackLabel] accessibilityElements = [titleLabel, feedbackLabel]
@ -193,7 +187,7 @@ import UIKit
entryFieldContainer.setContentCompressionResistancePriority(.required, for: .vertical) entryFieldContainer.setContentCompressionResistancePriority(.required, for: .vertical)
setupFieldContainerContent(entryFieldContainer) setupFieldContainerContent(entryFieldContainer)
titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4) titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: Padding.One)
titleContainerDistance?.isActive = true titleContainerDistance?.isActive = true
entryFieldContainerLeading = entryFieldContainer.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor) entryFieldContainerLeading = entryFieldContainer.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
entryFieldContainerLeading?.isActive = true entryFieldContainerLeading?.isActive = true
@ -202,7 +196,7 @@ import UIKit
addSubview(feedbackLabel) addSubview(feedbackLabel)
feedbackContainerDistance = feedbackLabel.topAnchor.constraint(equalTo: entryFieldContainer.bottomAnchor, constant: PaddingOne) feedbackContainerDistance = feedbackLabel.topAnchor.constraint(equalTo: entryFieldContainer.bottomAnchor, constant: Padding.Two)
feedbackContainerDistance?.isActive = true feedbackContainerDistance?.isActive = true
feedbackLabelLeading = feedbackLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor) feedbackLabelLeading = feedbackLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
feedbackLabelLeading?.isActive = true feedbackLabelLeading?.isActive = true
@ -217,11 +211,11 @@ import UIKit
entryFieldContainer.refreshUI() entryFieldContainer.refreshUI()
} }
/// Method to override. /**
/// 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 overridden by subclass. */
} @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)
@ -240,10 +234,11 @@ import UIKit
backgroundColor = .clear backgroundColor = .clear
isAccessibilityElement = false isAccessibilityElement = false
titleLabel.font = MFStyler.fontRegularMicro() titleLabel.font = Styler.Font.RegularMicro.getFont()
titleLabel.textColor = .mvmBlack titleLabel.textColor = .mvmBlack
feedbackLabel.font = MFStyler.fontRegularMicro() feedbackLabel.font = Styler.Font.RegularMicro.getFont()
feedbackLabel.textColor = .mvmBlack feedbackLabel.textColor = .mvmBlack
feedbackLabel.text = nil
entryFieldContainer.reset() entryFieldContainer.reset()
} }
@ -257,13 +252,12 @@ import UIKit
title = model.title title = model.title
feedback = model.feedback feedback = model.feedback
errorMessage = model.errorMessage isEnabled = model.enabled
isEnabled = model.isEnabled
if let isLocked = model.isLocked { if let isLocked = model.locked {
self.isLocked = isLocked self.isLocked = isLocked
} else if let isSelected = model.isSelected{ } else if let isSelected = model.selected {
self.isSelected = isSelected self.isSelected = isSelected
} }
} }

View File

@ -9,7 +9,7 @@
import Foundation import Foundation
@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol { @objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, EnableableModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
@ -22,29 +22,22 @@ import Foundation
public var backgroundColor: Color? public var backgroundColor: Color?
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 isEnabled: Bool = true public var enabled: Bool = true
public var isLocked: Bool? public var locked: Bool?
public var isSelected: Bool? public var selected: Bool?
public var text: String? public var text: String?
public var fieldKey: String? public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable? public var baseValue: AnyHashable?
public var isValid: Bool? { public var isValid: Bool? {
didSet { didSet { updateUI?() }
updateUI?()
}
} }
/// 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: (() -> Void)? public var updateUI: (() -> ())?
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
self.isValid = valid
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
//-------------------------------------------------- //--------------------------------------------------
@ -52,23 +45,29 @@ import Foundation
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case backgroundColor case backgroundColor
case title = "label" case title
case isEnabled case enabled
case feedback case feedback
case errorMessage = "errorMsg" case errorMessage
case isLocked case locked
case isSelected case selected
case isValid
case isRequired = "required"
case text case text
case fieldKey case fieldKey
case groupName case groupName
} }
//--------------------------------------------------
// MARK: - Validation Methods
//--------------------------------------------------
public func formFieldValue() -> AnyHashable? { public func formFieldValue() -> AnyHashable? {
return text return text
} }
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
self.isValid = valid
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
//-------------------------------------------------- //--------------------------------------------------
@ -78,18 +77,20 @@ import Foundation
baseValue = text baseValue = text
} }
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
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)
isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .isEnabled) ?? true enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
isLocked = try typeContainer.decodeIfPresent(Bool.self, forKey: .isLocked) locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked)
isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .isSelected) selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected)
isValid = try typeContainer.decodeIfPresent(Bool.self, forKey: .isValid)
text = try typeContainer.decodeIfPresent(String.self, forKey: .text) text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
baseValue = text baseValue = text
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
@ -103,13 +104,12 @@ import Foundation
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(title, forKey: .title) try container.encodeIfPresent(title, forKey: .title)
try container.encodeIfPresent(feedback, forKey: .feedback) try container.encodeIfPresent(feedback, forKey: .feedback)
try container.encode(errorMessage, forKey: .errorMessage)
try container.encode(isEnabled, forKey: .isEnabled)
try container.encode(isLocked, forKey: .isLocked)
try container.encode(isSelected, forKey: .isSelected)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encodeIfPresent(isValid, forKey: .isValid)
try container.encodeIfPresent(text, forKey: .text) 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) try container.encodeIfPresent(groupName, forKey: .groupName)
} }
} }

View File

@ -8,6 +8,8 @@
import UIKit import UIKit
public typealias TextFieldAndPickerDelegate = (UITextFieldDelegate & UIPickerViewDelegate & UIPickerViewDataSource)
open class ItemDropdownEntryField: BaseDropdownEntryField { open class ItemDropdownEntryField: BaseDropdownEntryField {
//-------------------------------------------------- //--------------------------------------------------
@ -62,7 +64,7 @@ open class ItemDropdownEntryField: BaseDropdownEntryField {
@objc open override func setupFieldContainerContent(_ container: UIView) { @objc open override func setupFieldContainerContent(_ container: UIView) {
super.setupFieldContainerContent(container) super.setupFieldContainerContent(container)
pickerView = MVMCoreUICommonViewsUtility.addPicker(to: textField, delegate: self) pickerView = UIPickerView.addPicker(to: textField, delegate: self, dismissAction: #selector(dismissFieldInput))
textField.hideBlinkingCaret = true textField.hideBlinkingCaret = true
textField.autocorrectionType = .no textField.autocorrectionType = .no
uiTextFieldDelegate = self uiTextFieldDelegate = self

View File

@ -17,17 +17,21 @@
public var options: [String] = [] public var options: [String] = []
public var selectedIndex: Int = 0 public var selectedIndex: Int = 0
public override func formFieldValue() -> AnyHashable? {
guard !options.isEmpty else { return nil }
return options[selectedIndex]
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
//-------------------------------------------------- //--------------------------------------------------
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName
case options case options
case selectedIndex case selectedIndex
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
//-------------------------------------------------- //--------------------------------------------------
@ -35,14 +39,17 @@
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)
options = try typeContainer.decode([String].self, forKey: .options) 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 { 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.encode(moleculeName, forKey: .moleculeName)
try container.encode(options, forKey: .options) try container.encode(options, forKey: .options)
try container.encode(options, forKey: .selectedIndex) try container.encode(options, forKey: .selectedIndex)
} }

View File

@ -48,6 +48,18 @@ import MVMCore
set { text = MVMCoreUIUtility.formatMdn(newValue) } 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 // MARK: - Initializers
//-------------------------------------------------- //--------------------------------------------------
@ -77,11 +89,14 @@ import MVMCore
super.setupFieldContainerContent(container) super.setupFieldContainerContent(container)
textField.keyboardType = .numberPad 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 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 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 dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput))
toolbar.items = [contacts, space, dismissButton] toolbar.items = [contacts, space, dismissButton]
textField.inputAccessoryView = toolbar textField.inputAccessoryView = toolbar
} }
@ -107,18 +122,18 @@ import MVMCore
isValid = true isValid = true
return true return true
} }
let isValid = hasValidMDN() isValid = hasValidMDN()
if isValid { if self.isValid {
showError = false showError = false
} else { } 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 showError = true
UIAccessibility.post(notification: .layoutChanged, argument: textField) UIAccessibility.post(notification: .layoutChanged, argument: textField)
} }
return isValid return isValid
} }
@ -196,7 +211,7 @@ import MVMCore
} }
@objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { @objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return proprietorTextDelegate?.textFieldShouldBeginEditing?(textField) ?? true return proprietorTextDelegate?.textFieldShouldBeginEditing?(textField) ?? true
} }

View File

@ -15,7 +15,7 @@ import UIKit
/// Called when the entered text becomes invalid based on the validation block /// Called when the entered text becomes invalid based on the validation block
@objc optional func isInvalid(textfield: TextEntryField?) @objc optional func isInvalid(textfield: TextEntryField?)
/// Dismisses the keyboard. /// Dismisses the keyboard.
@objc optional func dismissFieldInput(sender: Any?) @objc optional func dismissFieldInput(_ sender: Any?)
} }
@ -28,7 +28,7 @@ import UIKit
let textField = TextField() let textField = TextField()
textField.isAccessibilityElement = true textField.isAccessibilityElement = true
textField.setContentCompressionResistancePriority(.required, for: .vertical) textField.setContentCompressionResistancePriority(.required, for: .vertical)
textField.font = MFStyler.fontRegularBodyLarge() textField.font = Styler.Font.RegularBodyLarge.getFont()
textField.textColor = .mvmBlack textField.textColor = .mvmBlack
textField.smartQuotesType = .no textField.smartQuotesType = .no
textField.smartDashesType = .no textField.smartDashesType = .no
@ -36,13 +36,19 @@ import UIKit
return textField 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 // 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 private var observingForChange: Bool = false
/// Validate on each entry in the textField. Default: true /// Validate on each entry in the textField. Default: true
@ -54,7 +60,7 @@ import UIKit
public var textEntryFieldModel: TextEntryFieldModel? { public var textEntryFieldModel: TextEntryFieldModel? {
return model as? TextEntryFieldModel return model as? TextEntryFieldModel
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Computed Properties // MARK: - Computed Properties
//-------------------------------------------------- //--------------------------------------------------
@ -68,7 +74,7 @@ import UIKit
guard let self = self else { return } guard let self = self else { return }
self.textField.isEnabled = enabled 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) { set (error) {
if 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 { } else {
textField.accessibilityValue = nil textField.accessibilityValue = nil
} }
if textField.isSecureTextEntry {
showErrorView(error)
}
super.showError = error super.showError = error
} }
} }
@ -102,12 +112,6 @@ import UIKit
set { textField.placeholder = newValue } set { textField.placeholder = newValue }
} }
//--------------------------------------------------
// MARK: - Property Observers
//--------------------------------------------------
public var validationBlock: ((_ value: String?) -> Bool)?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Delegate Properties // MARK: - Delegate Properties
//-------------------------------------------------- //--------------------------------------------------
@ -169,21 +173,21 @@ import UIKit
@objc open override func setupFieldContainerContent(_ container: UIView) { @objc open override func setupFieldContainerContent(_ container: UIView) {
textField.font = MFStyler.fontRegularBodyLarge() textField.font = Styler.Font.RegularBodyLarge.getFont()
container.addSubview(textField) container.addSubview(textField)
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
textField.heightAnchor.constraint(equalToConstant: 24), textField.heightAnchor.constraint(equalToConstant: Padding.Five),
textField.topAnchor.constraint(equalTo: container.topAnchor, constant: 12), textField.topAnchor.constraint(equalTo: container.topAnchor, constant: Padding.Three),
textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16), textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: Padding.Three),
container.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: 12) 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 textFieldTrailingConstraint?.isActive = true
textField.addTarget(self, action: #selector(startEditing), for: .editingDidBegin) 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)) let tap = UITapGestureRecognizer(target: self, action: #selector(startEditing))
entryFieldContainer.addGestureRecognizer(tap) entryFieldContainer.addGestureRecognizer(tap)
@ -194,37 +198,31 @@ import UIKit
@objc open override func updateView(_ size: CGFloat) { @objc open override func updateView(_ size: CGFloat) {
super.updateView(size) super.updateView(size)
textField.font = MFStyler.fontRegularBodyLarge() textField.font = Styler.Font.RegularBodyLarge.getFont()
layoutIfNeeded() layoutIfNeeded()
} }
open override func reset() { open override func reset() {
super.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)?) { @objc public func setBothTextDelegates(to delegate: (UITextFieldDelegate & ObservingTextFieldDelegate)?) {
observingTextFieldDelegate = delegate observingTextFieldDelegate = delegate
uiTextFieldDelegate = 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) // MARK: - Observing for Change (TextFieldDelegate)
//-------------------------------------------------- //--------------------------------------------------
public func defaultValidationBlock() {
validationBlock = { enteredValue in
guard let enteredValue = enteredValue else { return false }
return enteredValue.count > 0
}
}
@discardableResult @discardableResult
@objc override open func resignFirstResponder() -> Bool { @objc override open func resignFirstResponder() -> Bool {
if validateWhenDoneEditing { if validateWhenDoneEditing {
@ -240,11 +238,11 @@ import UIKit
text = textField.text text = textField.text
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
} }
@objc public func updateValidation(_ isValid: Bool) { @objc public func updateValidation(_ isValid: Bool) {
let previousValidity = self.isValid let previousValidity = self.isValid
self.isValid = isValid self.isValid = isValid
if previousValidity && !isValid { if previousValidity && !isValid {
showError = true showError = true
observingTextFieldDelegate?.isInvalid?(textfield: self) observingTextFieldDelegate?.isInvalid?(textfield: self)
@ -276,10 +274,30 @@ import UIKit
} }
} }
@objc func dismissFieldInput(_ sender: Any?) { @objc public func dismissFieldInput(_ sender: Any?) {
resignFirstResponder() 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 // MARK: - MoleculeViewProtocol
//-------------------------------------------------- //--------------------------------------------------
@ -288,44 +306,39 @@ import UIKit
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
guard let model = model as? TextEntryFieldModel else { return } guard let model = model as? TextEntryFieldModel else { return }
model.updateUI = { [weak self] in model.updateUI = { [weak self] in
MVMCoreDispatchUtility.performBlock(onMainThread: { MVMCoreDispatchUtility.performBlock(onMainThread: {
if self?.isSelected ?? false { guard let self = self else { return }
self?.updateValidation(model.isValid ?? true)
if self.isSelected {
self.updateValidation(model.isValid ?? true)
} }
}) })
} }
self.delegateObject = delegateObject self.delegateObject = delegateObject
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
textColor.enabled = model.enabledTextColor?.uiColor
textColor.disabled = model.disabledTextColor?.uiColor
text = model.text text = model.text
placeholder = model.placeholder placeholder = model.placeholder
switch model.type { switch model.type {
case .password: case .password, .secure:
textField.isSecureTextEntry = true textField.isSecureTextEntry = true
case .number: case .number:
textField.keyboardType = .numberPad textField.keyboardType = .numberPad
case .email: case .email:
textField.keyboardType = .emailAddress textField.keyboardType = .emailAddress
default: default:
break break
} }
if let regex = model.regex, !regex.isEmpty {
validationBlock = { enteredValue in
guard let value = enteredValue else { return false }
return MVMCoreUIUtility.validate(value, withRegularExpression: regex)
}
} else {
defaultValidationBlock()
}
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate
textField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self) setupTextFieldToolbar()
} }
} }

View File

@ -8,9 +8,13 @@
@objcMembers public class TextEntryFieldModel: EntryFieldModel { @objcMembers public class TextEntryFieldModel: EntryFieldModel {
//--------------------------------------------------
// MARK: - Types
//--------------------------------------------------
public enum EntryType: String, Codable { public enum EntryType: String, Codable {
case password case password
case secure
case number case number
case email case email
} }
@ -24,10 +28,9 @@
} }
public var placeholder: String? public var placeholder: String?
public var enabledTextColor: Color? public var enabledTextColor: Color = Color(uiColor: .mvmBlack)
public var disabledTextColor: Color? public var disabledTextColor: Color = Color(uiColor: .mvmCoolGray3)
public var type: EntryType? public var type: EntryType?
public var regex: String?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
@ -35,38 +38,38 @@
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case text
case placeholder case placeholder
case enabledTextColor case enabledTextColor
case disabledTextColor case disabledTextColor
case type case type
case regex
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Codec
//-------------------------------------------------- //--------------------------------------------------
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)
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
placeholder = try typeContainer.decodeIfPresent(String.self, forKey: .placeholder) 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) type = try typeContainer.decodeIfPresent(EntryType.self, forKey: .type)
regex = try typeContainer.decodeIfPresent(String.self, forKey: .regex)
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 { 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.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(text, forKey: .text)
try container.encodeIfPresent(placeholder, forKey: .placeholder) try container.encodeIfPresent(placeholder, forKey: .placeholder)
try container.encodeIfPresent(enabledTextColor, forKey: .enabledTextColor) try container.encode(enabledTextColor, forKey: .enabledTextColor)
try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor) try container.encode(disabledTextColor, forKey: .disabledTextColor)
try container.encodeIfPresent(type, forKey: .type) try container.encodeIfPresent(type, forKey: .type)
try container.encodeIfPresent(regex, forKey: .regex)
} }
} }

View File

@ -14,8 +14,8 @@ import Foundation
// MARK: - Outlets // MARK: - Outlets
//------------------------------------------------------ //------------------------------------------------------
let leftTextLabel = Label.commonLabelB1(true) let leftTextLabel = Label.createLabelBoldBodySmall(true)
let rightTextLabel = Label.commonLabelB1(true) let rightTextLabel = Label.createLabelBoldBodySmall(true)
//------------------------------------------------------ //------------------------------------------------------
// MARK: - Constraints // MARK: - Constraints
@ -23,6 +23,29 @@ import Foundation
var rightTextLabelLeading: NSLayoutConstraint? var rightTextLabelLeading: NSLayoutConstraint?
var leftTextLabelTrailing: NSLayoutConstraint? var leftTextLabelTrailing: NSLayoutConstraint?
var rightTextLabelTrailing: NSLayoutConstraint?
private func constrainLeftLabelOnly() {
deactivateMiddleConstraint()
leftTextLabelTrailing?.isActive = false
leftTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor)
leftTextLabelTrailing?.isActive = true
}
private func constrainRightLabelOnly() {
deactivateMiddleConstraint()
rightTextLabelLeading?.isActive = false
rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
rightTextLabelLeading?.isActive = true
}
private func deactivateMiddleConstraint() {
leftTextLabelTrailing?.isActive = false
rightTextLabelLeading?.isActive = false
}
//------------------------------------------------------ //------------------------------------------------------
// MARK: - Initialization // MARK: - Initialization
@ -43,8 +66,6 @@ import Foundation
override open func setupView() { override open func setupView() {
super.setupView() super.setupView()
guard subviews.isEmpty else { return }
addSubview(leftTextLabel) addSubview(leftTextLabel)
addSubview(rightTextLabel) addSubview(rightTextLabel)
@ -67,7 +88,7 @@ import Foundation
// Resolves text layout issues found between both dynamically sized labels, number is not exact but performs as required. // Resolves text layout issues found between both dynamically sized labels, number is not exact but performs as required.
if leftTextLabel.hasText && rightTextLabel.hasText { if leftTextLabel.hasText && rightTextLabel.hasText {
let padding = MFStyler.defaultHorizontalPadding(forSize: size) * 2 let padding = MFStyler.defaultHorizontalPadding(forSize: size) * 2
let maximumTextWidth = (size - (padding + 16)) * 0.4 let maximumTextWidth = (size - (padding + Padding.Four)) * 0.4
// Subtracting 10 resolves issues of SE and iPad // Subtracting 10 resolves issues of SE and iPad
rightTextLabel.preferredMaxLayoutWidth = round(maximumTextWidth) - 10 rightTextLabel.preferredMaxLayoutWidth = round(maximumTextWidth) - 10
} else { } else {
@ -84,57 +105,38 @@ import Foundation
leftTextLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true leftTextLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true
leftTextLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true leftTextLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true
let leftTextBottom = leftTextLabel.bottomAnchor.constraint(equalTo: bottomAnchor) let leftTextBottom = bottomAnchor.constraint(equalTo: leftTextLabel.bottomAnchor)
leftTextBottom.priority = UILayoutPriority(249) leftTextBottom.priority = UILayoutPriority(249)
leftTextBottom.isActive = true leftTextBottom.isActive = true
bottomAnchor.constraint(greaterThanOrEqualTo: leftTextLabel.bottomAnchor).isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: leftTextLabel.bottomAnchor).isActive = true
rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor, constant: 16) rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor, constant: Padding.Four)
rightTextLabelLeading?.isActive = true rightTextLabelLeading?.isActive = true
rightTextLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true rightTextLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true
let rightLayout = layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightTextLabel.trailingAnchor)
rightLayout.priority = UILayoutPriority(rawValue: 995)
rightLayout.isActive = true
let rightTextBottom = rightTextLabel.bottomAnchor.constraint(equalTo: bottomAnchor) rightTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightTextLabel.trailingAnchor)
rightTextLabelTrailing?.isActive = true
let rightTextBottom = bottomAnchor.constraint(equalTo: rightTextLabel.bottomAnchor)
rightTextBottom.priority = UILayoutPriority(rawValue: 249) rightTextBottom.priority = UILayoutPriority(rawValue: 249)
rightTextBottom.isActive = true rightTextBottom.isActive = true
bottomAnchor.constraint(greaterThanOrEqualTo: rightTextLabel.bottomAnchor).isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: rightTextLabel.bottomAnchor).isActive = true
let leftTextWidth = leftTextLabel.widthAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.widthAnchor, multiplier: 0.6) let leftTextWidth = leftTextLabel.widthAnchor.constraint(equalTo: layoutMarginsGuide.widthAnchor, multiplier: 0.6)
leftTextWidth.priority = UILayoutPriority(rawValue: 995) leftTextWidth.priority = UILayoutPriority(rawValue: 995)
leftTextWidth.isActive = true leftTextWidth.isActive = true
let rightTextWidth = rightTextLabel.widthAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.widthAnchor, multiplier: 0.4) let rightTextWidth = rightTextLabel.widthAnchor.constraint(equalTo: layoutMarginsGuide.widthAnchor, multiplier: 0.4)
rightTextWidth.priority = UILayoutPriority(rawValue: 906) rightTextWidth.priority = UILayoutPriority(rawValue: 995)
rightTextWidth.isActive = true rightTextWidth.isActive = true
leftTextLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal) rightTextLabel.setContentHuggingPriority(.required, for: .horizontal)
rightTextLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal)
leftTextLabel.setContentHuggingPriority(.required, for: .vertical)
rightTextLabel.setContentHuggingPriority(.required, for: .vertical)
leftTextLabel.setContentCompressionResistancePriority(.required, for: .vertical) leftTextLabel.setContentCompressionResistancePriority(.required, for: .vertical)
rightTextLabel.setContentCompressionResistancePriority(.required, for: .vertical) rightTextLabel.setContentCompressionResistancePriority(.required, for: .vertical)
rightTextLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 902), for: .horizontal) rightTextLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
}
private func constrainLeftLabel() {
deactivateMiddleConstraint()
leftTextLabelTrailing = layoutMarginsGuide.trailingAnchor.constraint(equalTo: leftTextLabel.trailingAnchor)
leftTextLabelTrailing?.isActive = true
}
private func constrainRightLabel() {
deactivateMiddleConstraint()
rightTextLabelLeading = rightTextLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
rightTextLabelLeading?.isActive = true
} }
override open func reset() { override open func reset() {
@ -144,31 +146,31 @@ import Foundation
constrainBothLabels() constrainBothLabels()
leftTextLabel.text = "" leftTextLabel.text = ""
rightTextLabel.text = "" rightTextLabel.text = ""
leftTextLabel.textAlignment = .left
rightTextLabel.textAlignment = .right
backgroundColor = nil backgroundColor = nil
} }
private func deactivateMiddleConstraint() {
leftTextLabelTrailing?.isActive = false
rightTextLabelLeading?.isActive = false
}
//------------------------------------------------------ //------------------------------------------------------
// MARK: - Atomization // MARK: - Atomization
//------------------------------------------------------ //------------------------------------------------------
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
guard let leftRightLabelModel = model as? LeftRightLabelModel else {
return guard let leftRightLabelModel = model as? LeftRightLabelModel else { return }
}
leftTextLabel.set(with: leftRightLabelModel.leftText, delegateObject, additionalData) leftTextLabel.set(with: leftRightLabelModel.leftText, delegateObject, additionalData)
rightTextLabel.setOptional(with: leftRightLabelModel.rightText, delegateObject, additionalData) rightTextLabel.setOptional(with: leftRightLabelModel.rightText, delegateObject, additionalData)
// Label defaults to .left if no textAlignment value is provided in model.
rightTextLabel.textAlignment = leftRightLabelModel.rightText?.textAlignment ?? .right
if !leftTextLabel.hasText { if !leftTextLabel.hasText {
constrainRightLabel() constrainRightLabelOnly()
} else if !rightTextLabel.hasText { } else if !rightTextLabel.hasText {
constrainLeftLabel() constrainLeftLabelOnly()
} }
} }
} }

View File

@ -9,39 +9,27 @@
import UIKit import UIKit
@objcMembers open class MultiProgress: View { @objcMembers open class MultiProgress: View {
private let stack = Stack<StackModel>()
var multiProgressModel: MultiProgressBarModel? { var multiProgressModel: MultiProgressBarModel? {
get { return model as? MultiProgressBarModel } get { return model as? MultiProgressBarModel }
} }
///passing value to progressList creates corresponding progress bars public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
var progressList: Array<SingleProgressBarModel>? { super.init(frame: .zero)
didSet { set(with: model, delegateObject, additionalData)
for subview in subviews {
subview.removeFromSuperview()
}
guard (progressList?.count ?? 0) > 0 else {
return
}
var previous: UIView?
for progressObject in progressList! {
guard progressObject.progress > 0.0 else {
continue
}
let view = UIView(frame: .zero)
view.translatesAutoresizingMaskIntoConstraints = false
addSubview(view)
view.backgroundColor = progressObject.progressColor.uiColor
view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: progressObject.progress/100.0).isActive = true
view.leadingAnchor.constraint(equalTo: previous?.trailingAnchor ?? leadingAnchor).isActive = true
previous = view
NSLayoutConstraint.constraintPinSubview(view, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false)
}
}
} }
var roundedRect: Bool = false { public required init?(coder: NSCoder) {
super.init(coder: coder)
}
public override init(frame: CGRect) {
super.init(frame: frame)
}
var roundedCorners: Bool = false {
didSet { didSet {
if roundedRect { if roundedCorners {
layer.cornerRadius = (thicknessConstraint?.constant ?? defaultHeight)/2 layer.cornerRadius = (thicknessConstraint?.constant ?? defaultHeight)/2
} else { } else {
layer.cornerRadius = 0 layer.cornerRadius = 0
@ -57,28 +45,53 @@ import UIKit
translatesAutoresizingMaskIntoConstraints = false translatesAutoresizingMaskIntoConstraints = false
backgroundColor = .mfLightSilver() backgroundColor = .mfLightSilver()
clipsToBounds = true clipsToBounds = true
addSubview(stack)
NSLayoutConstraint.constraintPinSubview(toSuperview: stack)
stack.backgroundColor = backgroundColor
stack.contentView.backgroundColor = .white
stack.model = StackModel(molecules: [], axis: .horizontal, spacing: 2)
stack.stackModel?.horizontalAlignment = .leading
if thicknessConstraint == nil { if thicknessConstraint == nil {
thicknessConstraint = heightAnchor.constraint(equalToConstant: defaultHeight) thicknessConstraint = heightAnchor.constraint(equalToConstant: defaultHeight)
thicknessConstraint?.isActive = true thicknessConstraint?.isActive = true
} }
} }
/// Creates the bars
open func set(with progressList: Array<SingleProgressBarModel>, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
stack.removeAllItemViews()
guard let stackModel = stack.stackModel else { return }
var views: [StackItem] = []
var models: [StackItemModel] = []
for progressObject in progressList {
guard progressObject.percent > 0.0 else { continue }
let model = StackItemModel(percent: Int(progressObject.percent), horizontalAlignment: .fill, verticalAlignment: .fill)
model.backgroundColor = progressObject.color
models.append(model)
views.append(StackItem())
}
stack.stackItems = views
stackModel.molecules = models
stack.set(with: stackModel, delegateObject, additionalData)
}
//MARK: - MoleculeViewProtocol //MARK: - MoleculeViewProtocol
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
guard let multiProgressModel = multiProgressModel else { guard let multiProgressModel = multiProgressModel else { return }
return roundedCorners = multiProgressModel.roundedCorners ?? false
}
roundedRect = multiProgressModel.roundedRect ?? false
thicknessConstraint?.constant = multiProgressModel.thickness ?? defaultHeight thicknessConstraint?.constant = multiProgressModel.thickness ?? defaultHeight
progressList = multiProgressModel.progressList stack.model?.backgroundColor = model.backgroundColor
set(with: multiProgressModel.progressList, delegateObject, additionalData)
} }
open override func reset() { open override func reset() {
super.reset() super.reset()
backgroundColor = .mfLightSilver() backgroundColor = .mfLightSilver()
progressList = nil stack.reset()
set(with: [], nil, nil)
} }
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {

View File

@ -9,12 +9,12 @@
import Foundation import Foundation
@objcMembers public class SingleProgressBarModel: Codable { @objcMembers public class SingleProgressBarModel: Codable {
@Percent var progress: CGFloat @Percent var percent: CGFloat
var progressColor: Color var color: Color
init(_ progress: CGFloat, color: Color) { init(_ percent: CGFloat, color: Color) {
self.progress = progress self.percent = percent
self.progressColor = color self.color = color
} }
} }
@ -23,13 +23,13 @@ import Foundation
public var progressList: [SingleProgressBarModel] public var progressList: [SingleProgressBarModel]
public var backgroundColor: Color? public var backgroundColor: Color?
public var thickness: CGFloat? public var thickness: CGFloat?
public var roundedRect: Bool? public var roundedCorners: Bool?
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case progressList case progressList
case thickness case thickness
case roundedRect case roundedCorners
case backgroundColor case backgroundColor
} }
@ -42,7 +42,7 @@ import Foundation
progressList = try typeContainer.decode([SingleProgressBarModel].self, forKey: .progressList) progressList = try typeContainer.decode([SingleProgressBarModel].self, forKey: .progressList)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness) thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness)
roundedRect = try typeContainer.decodeIfPresent(Bool.self, forKey: .roundedRect) roundedCorners = try typeContainer.decodeIfPresent(Bool.self, forKey: .roundedCorners)
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -50,7 +50,7 @@ import Foundation
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(progressList, forKey: .progressList) try container.encode(progressList, forKey: .progressList)
try container.encodeIfPresent(thickness, forKey: .thickness) try container.encodeIfPresent(thickness, forKey: .thickness)
try container.encodeIfPresent(roundedRect, forKey: .roundedRect) try container.encodeIfPresent(roundedCorners, forKey: .roundedCorners)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
} }
} }

View File

@ -14,7 +14,7 @@ import Foundation
var thickness: CGFloat = 8.0 { var thickness: CGFloat = 8.0 {
willSet(newValue) { willSet(newValue) {
heightAnchor.constraint(equalToConstant: newValue).isActive = true heightAnchor.constraint(equalToConstant: newValue).isActive = true
if progressBarModel?.isRounded ?? false { if progressBarModel?.roundedCorners ?? false {
layer.cornerRadius = newValue/2.0 layer.cornerRadius = newValue/2.0
} else { } else {
progressViewStyle = .bar progressViewStyle = .bar
@ -52,12 +52,11 @@ import Foundation
//MARK: - MoleculeViewProtocol //MARK: - MoleculeViewProtocol
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let progressBarModel = model as? ProgressBarModel else { guard let progressBarModel = model as? ProgressBarModel else { return }
return self.progressBarModel = progressBarModel
}
thickness = progressBarModel.thickness ?? 8 thickness = progressBarModel.thickness ?? 8
progress = Float((progressBarModel.percent)/100.0) progress = Float((progressBarModel.percent)/100.0)
progressTintColor = progressBarModel.progressColor.uiColor progressTintColor = progressBarModel.color.uiColor
if let backgroundColor = progressBarModel.backgroundColor { if let backgroundColor = progressBarModel.backgroundColor {
trackTintColor = backgroundColor.uiColor trackTintColor = backgroundColor.uiColor
} }

View File

@ -11,17 +11,17 @@ import Foundation
@objcMembers public class ProgressBarModel: MoleculeModelProtocol { @objcMembers public class ProgressBarModel: MoleculeModelProtocol {
public static var identifier: String = "progressBar" public static var identifier: String = "progressBar"
@Percent public var percent: CGFloat @Percent public var percent: CGFloat
public var progressColor: Color = Color(uiColor: .mfCerulean()) public var color: Color = Color(uiColor: .mfCerulean())
public var backgroundColor: Color? = Color(uiColor: .mfLightSilver()) public var backgroundColor: Color? = Color(uiColor: .mfLightSilver())
public var isRounded: Bool? public var roundedCorners: Bool?
public var thickness: CGFloat? public var thickness: CGFloat?
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case isRounded = "roundRect" case roundedCorners
case thickness case thickness
case percent case percent
case progressColor case color
case backgroundColor case backgroundColor
} }
@ -32,13 +32,13 @@ import Foundation
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
percent = try typeContainer.decode(CGFloat.self, forKey: .percent) percent = try typeContainer.decode(CGFloat.self, forKey: .percent)
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .progressColor) { if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) {
progressColor = color self.color = color
} }
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) { if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) {
backgroundColor = color backgroundColor = color
} }
isRounded = try typeContainer.decodeIfPresent(Bool.self, forKey: .isRounded) roundedCorners = try typeContainer.decodeIfPresent(Bool.self, forKey: .roundedCorners)
thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness) thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness)
} }
@ -46,9 +46,9 @@ import Foundation
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(percent, forKey: .percent) try container.encode(percent, forKey: .percent)
try container.encode(progressColor, forKey: .progressColor) try container.encode(color, forKey: .color)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(isRounded, forKey: .isRounded) try container.encodeIfPresent(roundedCorners, forKey: .roundedCorners)
try container.encodeIfPresent(thickness, forKey: .thickness) try container.encodeIfPresent(thickness, forKey: .thickness)
} }
} }

View File

@ -25,13 +25,13 @@ public typealias ActionBlockConfirmation = () -> (Bool)
//-------------------------------------------------- //--------------------------------------------------
/// Holds the on and off colors for the container. /// Holds the on and off colors for the container.
public var containerTintColor: (on: UIColor?, off: UIColor?)? = (on: .mvmGreen, off: .mvmBlack) public var containerTintColor: (on: UIColor, off: UIColor) = (on: .mvmGreen, off: .mvmBlack)
/// Holds the on and off colors for the knob. /// Holds the on and off colors for the knob.
public var knobTintColor: (on: UIColor?, off: UIColor?)? = (on: .mvmWhite, off: .mvmWhite) public var knobTintColor: (on: UIColor, off: UIColor) = (on: .mvmWhite, off: .mvmWhite)
/// Holds the on and off colors for the disabled state.. /// Holds the on and off colors for the disabled state..
public var disabledTintColor: (container: UIColor?, knob: UIColor?)? = (container: .mvmCoolGray3, knob: .mvmWhite) public var disabledTintColor: (container: UIColor, knob: UIColor) = (container: .mvmCoolGray3, knob: .mvmWhite)
/// Set this flag to false if you do not want to animate state changes. /// Set this flag to false if you do not want to animate state changes.
public var isAnimated = true public var isAnimated = true
@ -62,8 +62,8 @@ public typealias ActionBlockConfirmation = () -> (Bool)
didSet { didSet {
isUserInteractionEnabled = isEnabled isUserInteractionEnabled = isEnabled
changeStateNoAnimation(isEnabled ? isOn : false) changeStateNoAnimation(isEnabled ? isOn : false)
backgroundColor = isEnabled ? containerTintColor?.off : disabledTintColor?.container backgroundColor = isEnabled ? (isOn ? containerTintColor.on : containerTintColor.off) : disabledTintColor.container
knobView.backgroundColor = isEnabled ? knobTintColor?.off : disabledTintColor?.knob knobView.backgroundColor = isEnabled ? (isOn ? knobTintColor.on : knobTintColor.off) : disabledTintColor.knob
} }
} }
@ -80,12 +80,12 @@ public typealias ActionBlockConfirmation = () -> (Bool)
if isAnimated { if isAnimated {
UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: { UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: {
if self.isOn { if self.isOn {
self.knobView.backgroundColor = self.knobTintColor?.on self.knobView.backgroundColor = self.knobTintColor.on
self.backgroundColor = self.containerTintColor?.on self.backgroundColor = self.containerTintColor.on
} else { } else {
self.knobView.backgroundColor = self.knobTintColor?.off self.knobView.backgroundColor = self.knobTintColor.off
self.backgroundColor = self.containerTintColor?.off self.backgroundColor = self.containerTintColor.off
} }
}, completion: nil) }, completion: nil)
@ -96,12 +96,12 @@ public typealias ActionBlockConfirmation = () -> (Bool)
}, completion: nil) }, completion: nil)
} else { } else {
backgroundColor = isOn ? containerTintColor?.on : containerTintColor?.off backgroundColor = isOn ? containerTintColor.on : containerTintColor.off
knobView.backgroundColor = isOn ? knobTintColor?.on : knobTintColor?.off knobView.backgroundColor = isOn ? knobTintColor.on : knobTintColor.off
self.constrainKnob() self.constrainKnob()
} }
(model as? ToggleModel)?.state = isOn toggleModel?.state = isOn
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff")
setNeedsLayout() setNeedsLayout()
@ -109,6 +109,10 @@ public typealias ActionBlockConfirmation = () -> (Bool)
} }
} }
public var toggleModel: ToggleModel? {
return model as? ToggleModel
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Delegate // MARK: - Delegate
//-------------------------------------------------- //--------------------------------------------------
@ -127,8 +131,26 @@ public typealias ActionBlockConfirmation = () -> (Bool)
private var widthConstraint: NSLayoutConstraint? private var widthConstraint: NSLayoutConstraint?
private func constrainKnob() { 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)
} }
//-------------------------------------------------- //--------------------------------------------------
@ -185,11 +207,13 @@ public typealias ActionBlockConfirmation = () -> (Bool)
layer.cornerRadius = Self.getContainerHeight() / 2.0 layer.cornerRadius = Self.getContainerHeight() / 2.0
knobView.layer.cornerRadius = Self.getKnobHeight() / 2.0 knobView.layer.cornerRadius = Self.getKnobHeight() / 2.0
changeStateNoAnimation(isOn)
} }
public override func setupView() { public override func setupView() {
super.setupView() super.setupView()
guard subviews.isEmpty else { return }
isAccessibilityElement = true isAccessibilityElement = true
accessibilityTraits = .button accessibilityTraits = .button
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccToggleHint") accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccToggleHint")
@ -202,7 +226,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
widthConstraint?.isActive = true widthConstraint?.isActive = true
layer.cornerRadius = Self.containerSize.height / 2.0 layer.cornerRadius = Self.containerSize.height / 2.0
backgroundColor = containerTintColor?.off backgroundColor = containerTintColor.off
addSubview(knobView) addSubview(knobView)
@ -214,19 +238,16 @@ public typealias ActionBlockConfirmation = () -> (Bool)
knobView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true knobView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true
bottomAnchor.constraint(greaterThanOrEqualTo: knobView.bottomAnchor).isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: knobView.bottomAnchor).isActive = true
knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 1) constrainKnobOff()
knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1)
knobLeadingConstraint?.isActive = true
} }
public override func reset() { public override func reset() {
super.reset() super.reset()
backgroundColor = containerTintColor?.off backgroundColor = containerTintColor.off
knobView.backgroundColor = knobTintColor?.off knobView.backgroundColor = knobTintColor.off
isAnimated = false accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel")
isOn = false isAnimated = true
constrainKnob()
didToggleAction = nil didToggleAction = nil
shouldToggleAction = { return true } shouldToggleAction = { return true }
} }
@ -344,26 +365,19 @@ public typealias ActionBlockConfirmation = () -> (Bool)
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
if let color = model.onTintColor?.uiColor { containerTintColor.on = model.onTintColor.uiColor
containerTintColor?.on = color containerTintColor.off = model.offTintColor.uiColor
} knobTintColor.on = model.onKnobTintColor.uiColor
knobTintColor.off = model.offKnobTintColor.uiColor
if let color = model.offTintColor?.uiColor { isOn = model.state
containerTintColor?.off = color changeStateNoAnimation(isOn)
}
if let color = model.onKnobTintColor?.uiColor {
knobTintColor?.on = color
}
if let color = model.offKnobTintColor?.uiColor {
knobTintColor?.off = color
}
changeStateNoAnimation(model.state)
isAnimated = model.animated isAnimated = model.animated
isEnabled = model.enabled isEnabled = model.enabled
if let accessibileString = model.accessibilityText {
accessibilityLabel = accessibileString
}
if let actionMap = model.action?.toJSON() { if let actionMap = model.action?.toJSON() {
didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) }
} }

View File

@ -8,8 +8,12 @@
import UIKit import UIKit
public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol {
public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "toggle" public static var identifier: String = "toggle"
public var backgroundColor: Color? public var backgroundColor: Color?
public var state: Bool = false public var state: Bool = false
@ -18,10 +22,10 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
public var action: ActionModelProtocol? public var action: ActionModelProtocol?
public var alternateAction: ActionModelProtocol? public var alternateAction: ActionModelProtocol?
public var accessibilityText: String? public var accessibilityText: String?
public var onTintColor: Color? public var onTintColor: Color = Color(uiColor: .mvmGreen)
public var offTintColor: Color? public var offTintColor: Color = Color(uiColor: .mvmBlack)
public var onKnobTintColor: Color? public var onKnobTintColor: Color = Color(uiColor: .mvmWhite)
public var offKnobTintColor: Color? public var offKnobTintColor: Color = Color(uiColor: .mvmWhite)
public var fieldKey: String? public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName public var groupName: String = FormValidator.defaultGroupName
@ -75,19 +79,35 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) { if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) {
self.state = state self.state = state
} }
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
self.enabled = enabled self.enabled = enabled
} }
if let animated = try typeContainer.decodeIfPresent(Bool.self, forKey: .animated) { if let animated = try typeContainer.decodeIfPresent(Bool.self, forKey: .animated) {
self.animated = animated self.animated = animated
} }
action = try typeContainer.decodeModelIfPresent(codingKey: .action) action = try typeContainer.decodeModelIfPresent(codingKey: .action)
alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction) alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
onTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onTintColor)
offTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offTintColor) if let onTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onTintColor) {
onKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onKnobTintColor) self.onTintColor = onTintColor
offKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offKnobTintColor) }
if let offTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offTintColor) {
self.offTintColor = offTintColor
}
if let onKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onKnobTintColor) {
self.onKnobTintColor = onKnobTintColor
}
if let offKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offKnobTintColor) {
self.offKnobTintColor = offKnobTintColor
}
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
baseValue = state baseValue = state
@ -106,10 +126,10 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
try container.encode(state, forKey: .state) try container.encode(state, forKey: .state)
try container.encode(animated, forKey: .animated) try container.encode(animated, forKey: .animated)
try container.encode(enabled, forKey: .enabled) try container.encode(enabled, forKey: .enabled)
try container.encodeIfPresent(onTintColor, forKey: .onTintColor) try container.encode(onTintColor, forKey: .onTintColor)
try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor) try container.encode(onKnobTintColor, forKey: .onKnobTintColor)
try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor) try container.encode(onKnobTintColor, forKey: .onKnobTintColor)
try container.encodeIfPresent(offKnobTintColor, forKey: .offKnobTintColor) try container.encode(offKnobTintColor, forKey: .offKnobTintColor)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
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

@ -1,5 +1,5 @@
// //
// GraphView.swift // Wheel.swift
// MobileFirstFramework // MobileFirstFramework
// //
// Created by Ryan on 10/24/19. // Created by Ryan on 10/24/19.
@ -8,12 +8,12 @@
import UIKit import UIKit
@objcMembers open class GraphView: View, MVMCoreUIViewConstrainingProtocol { @objcMembers open class Wheel: View, MVMCoreUIViewConstrainingProtocol {
var heightConstraint: NSLayoutConstraint? var heightConstraint: NSLayoutConstraint?
var gradientLayer: CALayer? var gradientLayer: CALayer?
var graphModel: CircleProgressModel? { var graphModel: WheelModel? {
return model as? CircleProgressModel return model as? WheelModel
} }
// MARK: setup // MARK: setup
@ -28,7 +28,7 @@ import UIKit
override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
guard let model = model as? CircleProgressModel else { return } guard let model = model as? WheelModel else { return }
createGraphCircle(model) createGraphCircle(model)
rotationAnimation(model) rotationAnimation(model)
} }
@ -42,7 +42,7 @@ import UIKit
} }
// MARK: circle // MARK: circle
open func createGraphCircle(_ graphObject: CircleProgressModel) { open func createGraphCircle(_ graphObject: WheelModel) {
if let sublayers = layer.sublayers { if let sublayers = layer.sublayers {
for sublayer in sublayers { for sublayer in sublayers {
sublayer.removeAllAnimations() sublayer.removeAllAnimations()
@ -56,7 +56,7 @@ import UIKit
//begin point will be at the bottom, clockwise direction //begin point will be at the bottom, clockwise direction
let path = UIBezierPath(arcCenter: CGPoint(x: radius let path = UIBezierPath(arcCenter: CGPoint(x: radius
, y: radius), radius: radius - graphObject.lineWidth/2.0, startAngle: CGFloat(GraphView.getPiValue(90.0)), endAngle: CGFloat(GraphView.getPiValue(90.0 + 360.0)), clockwise: true) , y: radius), radius: radius - graphObject.lineWidth/2.0, startAngle: CGFloat(Wheel.getPiValue(90.0)), endAngle: CGFloat(Wheel.getPiValue(90.0 + 360.0)), clockwise: true)
path.lineWidth = graphObject.lineWidth path.lineWidth = graphObject.lineWidth
let circleLayer = CAShapeLayer() let circleLayer = CAShapeLayer()
@ -83,7 +83,7 @@ import UIKit
| | | | | |
------------- -------------
*/ */
func createGradientLayer(_ graphObject: CircleProgressModel) -> CALayer { func createGradientLayer(_ graphObject: WheelModel) -> CALayer {
let containLayer = CALayer() let containLayer = CALayer()
containLayer.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter) containLayer.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter)
let radius = graphObject.diameter / 2.0 let radius = graphObject.diameter / 2.0
@ -151,18 +151,18 @@ import UIKit
} }
//MARK: Animation //MARK: Animation
func rotationAnimation(_ object: CircleProgressModel) { func rotationAnimation(_ object: WheelModel) {
MVMCoreDispatchUtility.performBlock(onMainThread:{ MVMCoreDispatchUtility.performBlock(onMainThread:{
let rotation = CABasicAnimation(keyPath: "transform.rotation") let rotation = CABasicAnimation(keyPath: "transform.rotation")
let animationHandler = GraphViewAnimationHandler.shared let animationHandler = WheelAnimationHandler.shared
let startAngle = animationHandler.getAnimationStartAngle(object.duration, CACurrentMediaTime()) let startAngle = animationHandler.getAnimationStartAngle(object.duration, CACurrentMediaTime())
if startAngle == 0.0 { if startAngle == 0.0 {
animationHandler.storeAnimation(object.duration, CACurrentMediaTime()) animationHandler.storeAnimation(object.duration, CACurrentMediaTime())
} }
var fromValue = GraphView.getPiValue(0.0 + startAngle), toValue = GraphView.getPiValue(360.0 + startAngle) var fromValue = Wheel.getPiValue(0.0 + startAngle), toValue = Wheel.getPiValue(360.0 + startAngle)
if !object.clockwise { if !object.clockwise {
fromValue = GraphView.getPiValue(360.0 - startAngle) fromValue = Wheel.getPiValue(360.0 - startAngle)
toValue = GraphView.getPiValue(0.0 - startAngle) toValue = Wheel.getPiValue(0.0 - startAngle)
} }
rotation.fromValue = fromValue rotation.fromValue = fromValue
rotation.toValue = toValue rotation.toValue = toValue
@ -180,7 +180,7 @@ import UIKit
} }
extension GraphView: CAAnimationDelegate { extension Wheel: CAAnimationDelegate {
public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
if let object = graphModel { if let object = graphModel {
rotationAnimation(object) rotationAnimation(object)

View File

@ -1,5 +1,5 @@
// //
// GraphViewAnimationHandler.swift // WheelAnimationHandler.swift
// MobileFirstFramework // MobileFirstFramework
// //
// Created by Ryan on 10/29/19. // Created by Ryan on 10/29/19.
@ -8,12 +8,12 @@
import UIKit import UIKit
@objcMembers open class GraphViewAnimationHandler: NSObject { @objcMembers open class WheelAnimationHandler: NSObject {
/// duration : CACurrentMediaTime() /// duration : CACurrentMediaTime()
private var animations = [Double: Double]() private var animations = [Double: Double]()
static let shared = GraphViewAnimationHandler() static let shared = WheelAnimationHandler()
open func storeAnimation(_ duration: Double, _ currentTime: CFTimeInterval) { open func storeAnimation(_ duration: Double, _ currentTime: CFTimeInterval) {
guard animations[duration] == nil else { guard animations[duration] == nil else {

View File

@ -1,5 +1,5 @@
// //
// CircleProgressModel.swift // WheelModel.swift
// MVMCoreUI // MVMCoreUI
// //
// Created by Scott Pfeil on 1/13/20. // Created by Scott Pfeil on 1/13/20.
@ -16,9 +16,9 @@ public enum GraphStyle: String, Codable {
case unlimited, safetyMode case unlimited, safetyMode
} }
public class CircleProgressModel: MoleculeModelProtocol { public class WheelModel: MoleculeModelProtocol {
public static var identifier: String = "circleProgress" public static var identifier: String = "wheel"
public var style: GraphStyle = .unlimited { public var style: GraphStyle = .unlimited {
didSet { didSet {
updateStyle() updateStyle()

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

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

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

View File

@ -37,8 +37,7 @@ import Foundation
/// Call to register all of the CoreUI molecules. /// Call to register all of the CoreUI molecules.
public static func registerObjects() { public static func registerObjects() {
// Stacks // Stacks
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeStackView.self, viewModelClass: MoleculeStackModel.self) MoleculeObjectMapping.shared()?.register(viewClass: MoleculeStackView.self, viewModelClass: StackModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: Stack<StackModel>.self, viewModelClass: StackModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: UnOrderedList.self, viewModelClass: UnOrderedListModel.self) MoleculeObjectMapping.shared()?.register(viewClass: UnOrderedList.self, viewModelClass: UnOrderedListModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: NumberedList.self, viewModelClass: NumberedListModel.self) MoleculeObjectMapping.shared()?.register(viewClass: NumberedList.self, viewModelClass: NumberedListModel.self)
@ -70,6 +69,7 @@ import Foundation
MoleculeObjectMapping.shared()?.register(viewClass: RadioButton.self, viewModelClass: RadioButtonModel.self) MoleculeObjectMapping.shared()?.register(viewClass: RadioButton.self, viewModelClass: RadioButtonModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: RadioBoxes.self, viewModelClass: RadioBoxesModel.self) MoleculeObjectMapping.shared()?.register(viewClass: RadioBoxes.self, viewModelClass: RadioBoxesModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: Checkbox.self, viewModelClass: CheckboxModel.self) MoleculeObjectMapping.shared()?.register(viewClass: Checkbox.self, viewModelClass: CheckboxModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: RadioSwatches.self, viewModelClass: RadioSwatchesModel.self)
// Other Atoms // Other Atoms
MoleculeObjectMapping.shared()?.register(viewClass: ProgressBar.self, viewModelClass: ProgressBarModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ProgressBar.self, viewModelClass: ProgressBarModel.self)
@ -78,7 +78,7 @@ import Foundation
MoleculeObjectMapping.shared()?.register(viewClass: DashLine.self, viewModelClass: DashLineModel.self) MoleculeObjectMapping.shared()?.register(viewClass: DashLine.self, viewModelClass: DashLineModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: MFLoadImageView.self, viewModelClass: ImageViewModel.self) MoleculeObjectMapping.shared()?.register(viewClass: MFLoadImageView.self, viewModelClass: ImageViewModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: Line.self, viewModelClass: LineModel.self) MoleculeObjectMapping.shared()?.register(viewClass: Line.self, viewModelClass: LineModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: GraphView.self, viewModelClass: CircleProgressModel.self) MoleculeObjectMapping.shared()?.register(viewClass: Wheel.self, viewModelClass: WheelModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: Toggle.self, viewModelClass: ToggleModel.self) MoleculeObjectMapping.shared()?.register(viewClass: Toggle.self, viewModelClass: ToggleModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: CheckboxLabel.self, viewModelClass: CheckboxLabelModel.self) MoleculeObjectMapping.shared()?.register(viewClass: CheckboxLabel.self, viewModelClass: CheckboxLabelModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: Arrow.self, viewModelClass: ArrowModel.self) MoleculeObjectMapping.shared()?.register(viewClass: Arrow.self, viewModelClass: ArrowModel.self)
@ -88,6 +88,7 @@ import Foundation
// Horizontal Combination Molecules // Horizontal Combination Molecules
MoleculeObjectMapping.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self) MoleculeObjectMapping.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: Tabs.self, viewModelClass: TabsModel.self)
// Vertical Combination Molecules // Vertical Combination Molecules
MoleculeObjectMapping.shared()?.register(viewClass: HeadlineBody.self, viewModelClass: HeadlineBodyModel.self) MoleculeObjectMapping.shared()?.register(viewClass: HeadlineBody.self, viewModelClass: HeadlineBodyModel.self)
@ -120,6 +121,7 @@ import Foundation
// Other Container Molecules // Other Container Molecules
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeContainer.self, viewModelClass: MoleculeContainerModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeHeaderView.self, viewModelClass: MoleculeHeaderModel.self) MoleculeObjectMapping.shared()?.register(viewClass: MoleculeHeaderView.self, viewModelClass: MoleculeHeaderModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: FooterView.self, viewModelClass: FooterModel.self) MoleculeObjectMapping.shared()?.register(viewClass: FooterView.self, viewModelClass: FooterModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: Scroller.self, viewModelClass: ScrollerModel.self) MoleculeObjectMapping.shared()?.register(viewClass: Scroller.self, viewModelClass: ScrollerModel.self)
@ -136,19 +138,23 @@ import Foundation
MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableCheckboxAllTextAndLinks.self, viewModelClass: ListLeftVariableCheckboxAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableCheckboxAllTextAndLinks.self, viewModelClass: ListLeftVariableCheckboxAllTextAndLinksModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableRadioButtonAndPaymentMethod.self, viewModelClass: ListLeftVariableRadioButtonAndPaymentMethodModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableRadioButtonAndPaymentMethod.self, viewModelClass: ListLeftVariableRadioButtonAndPaymentMethodModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableRadioButtonBodyText.self, viewModelClass: ListLeftVariableRadioButtonBodyTextModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableRadioButtonBodyText.self, viewModelClass: ListLeftVariableRadioButtonBodyTextModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListLeftVariableCheckboxBodyText.self, viewModelClass: ListLeftVariableCheckboxBodyTextModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListRVWheel.self, viewModelClass: ListRVWheelModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRVWheel.self, viewModelClass: ListRVWheelModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePayments.self, viewModelClass: ListRightVariablePaymentsModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePayments.self, viewModelClass: ListRightVariablePaymentsModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTotalData.self, viewModelClass: ListRightVariableTotalDataModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTotalData.self, viewModelClass: ListRightVariableTotalDataModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTextLinkAllTextAndLinks.self, viewModelClass: ListRightVariableTextLinkAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTextLinkAllTextAndLinks.self, viewModelClass: ListRightVariableTextLinkAllTextAndLinksModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableButtonAllTextAndLinks.self, viewModelClass: ListRightVariableButtonAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableButtonAllTextAndLinks.self, viewModelClass: ListRightVariableButtonAllTextAndLinksModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeBodyText.self, viewModelClass: ListRightVariablePriceChangeBodyTextModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeAllTextAndLinks.self, viewModelClass: ListRightVariablePriceChangeAllTextAndLinksModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextBodyText.self, viewModelClass: ListOneColumnFullWidthTextBodyTextModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextBodyText.self, viewModelClass: ListOneColumnFullWidthTextBodyTextModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnCompareChanges.self, viewModelClass: ListTwoColumnCompareChangesModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnCompareChanges.self, viewModelClass: ListTwoColumnCompareChangesModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDetails.self, viewModelClass: ListTwoColumnPriceDetailsModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDetails.self, viewModelClass: ListTwoColumnPriceDetailsModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self)
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: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.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)
MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self)
@ -164,6 +170,11 @@ import Foundation
// Designed Headers // Designed Headers
MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2NoButtonsBodyText.self, viewModelClass: HeadersH2NoButtonsBodyTextModel.self) MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2NoButtonsBodyText.self, viewModelClass: HeadersH2NoButtonsBodyTextModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2Buttons.self, viewModelClass: HeadersH2ButtonsModel.self) MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2Buttons.self, viewModelClass: HeadersH2ButtonsModel.self)
// Device Items
MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexButtonMedium.self, viewModelClass: ListDeviceComplexButtonMediumModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexLinkSmall.self, viewModelClass: ListDeviceComplexLinkSmallModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexLinkMedium.self, viewModelClass: ListDeviceComplexLinkMediumModel.self)
// TODO: Need View // TODO: Need View
try? ModelRegistry.register(TabsModel.self) try? ModelRegistry.register(TabsModel.self)

View File

@ -25,8 +25,8 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
public override func setDefaults() { public override func setDefaults() {
super.setDefaults() super.setDefaults()
topMarginPadding = PaddingDefaultVerticalSpacing3 topPadding = PaddingDefaultVerticalSpacing3
bottomMarginPadding = PaddingDefaultVerticalSpacing3 bottomPadding = PaddingDefaultVerticalSpacing3
} }
//-------------------------------------------------- //--------------------------------------------------

View File

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

View File

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

View File

@ -0,0 +1,73 @@
//
// ListDeviceComplexLinkMedium.swift
// MVMCoreUI
//
// Created by Lekshmi S on 21/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class ListDeviceComplexLinkMedium: TableViewCell {
//-----------------------------------------------------
// MARK: - Outlets
//-----------------------------------------------------
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 link = Link()
public let rightImage = MFLoadImageView()
let verticalStack: Stack<StackModel>
public let stack: Stack<StackModel>
//------------------------------------------------------
// MARK: - Initializers
//------------------------------------------------------
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
rightImage.addSizeConstraintsForAspectRatio = true
rightImage.heightAnchor.constraint(equalToConstant: 116.0).isActive = true
rightImage.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: link, model: StackItemModel(spacing: 16, horizontalAlignment: .leading))], axis: .vertical, spacing: 0)
stack = Stack<StackModel>.createStack(with: [(view: verticalStack, model: StackItemModel(horizontalAlignment: .leading)), (view: rightImage, model: StackItemModel(verticalAlignment: .center))], axis: .horizontal)
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//-----------------------------------------------------
// MARK: - View Lifecycle
//-----------------------------------------------------
open override func setupView() {
super.setupView()
addMolecule(stack)
stack.restack()
verticalStack.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? ListDeviceComplexLinkMediumModel else { return }
verticalStack.updateContainedMolecules(with: [model.eyebrow, model.headline, model.body, model.body2, model.link], delegateObject, additionalData)
rightImage.set(with: model.image, delegateObject, additionalData)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 120
}
open override func reset() {
super.reset()
eyebrow.styleRegularMicro(true)
headline.styleBoldTitleMedium(true)
body.styleRegularBodySmall(true)
body2.styleRegularBodySmall(true)
eyebrow.textColor = .mvmCoolGray6
}
}

View File

@ -0,0 +1,61 @@
//
// ListDeviceComplexLinkMediumModel.swift
// MVMCoreUI
//
// Created by Lekshmi S on 21/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public class ListDeviceComplexLinkMediumModel: ListItemModel, MoleculeModelProtocol {
public static var identifier: String = "listDvcLnkM"
public var eyebrow: LabelModel?
public var headline: LabelModel?
public var body: LabelModel?
public var body2: LabelModel?
public var link: LinkModel
public var image: ImageViewModel
public init(eyebrow: LabelModel, headline: LabelModel, body: LabelModel, body2: LabelModel, link: LinkModel, image: ImageViewModel) {
self.eyebrow = eyebrow
self.headline = headline
self.body = body
self.body2 = body2
self.link = link
self.image = image
super.init()
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case eyebrow
case headline
case body
case body2
case link
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)
link = try typeContainer.decode(LinkModel.self, forKey: .link)
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(link, forKey: .link)
try container.encode(image, forKey: .image)
}
}

View File

@ -0,0 +1,73 @@
//
// ListDeviceComplexLinkSmall.swift
// MVMCoreUI
//
// Created by Lekshmi S on 24/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class ListDeviceComplexLinkSmall: TableViewCell {
//-----------------------------------------------------
// MARK: - Outlets
//-----------------------------------------------------
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 link = Link()
public let rightImage = MFLoadImageView()
let verticalStack: Stack<StackModel>
public let stack: Stack<StackModel>
//------------------------------------------------------
// MARK: - Initializers
//------------------------------------------------------
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
rightImage.addSizeConstraintsForAspectRatio = true
rightImage.heightAnchor.constraint(equalToConstant: 71.0).isActive = true
rightImage.widthAnchor.constraint(equalToConstant: 71.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: link, model: StackItemModel(spacing: 16, horizontalAlignment: .leading))], axis: .vertical, spacing: 0)
stack = Stack<StackModel>.createStack(with: [(view: verticalStack, model: StackItemModel(horizontalAlignment: .leading)), (view: rightImage, model: StackItemModel(verticalAlignment: .center))], axis: .horizontal)
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//-----------------------------------------------------
// MARK: - View Lifecycle
//-----------------------------------------------------
open override func setupView() {
super.setupView()
addMolecule(stack)
stack.restack()
verticalStack.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? ListDeviceComplexLinkSmallModel else { return }
verticalStack.updateContainedMolecules(with: [model.eyebrow, model.headline, model.body, model.body2, model.link], delegateObject, additionalData)
rightImage.set(with: model.image, delegateObject, additionalData)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 120
}
open override func reset() {
super.reset()
eyebrow.styleRegularMicro(true)
headline.styleBoldTitleMedium(true)
body.styleRegularBodySmall(true)
body2.styleRegularBodySmall(true)
eyebrow.textColor = .mvmCoolGray6
}
}

View File

@ -0,0 +1,61 @@
//
// ListDeviceComplexLinkSmallModel.swift
// MVMCoreUI
//
// Created by Lekshmi S on 24/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public class ListDeviceComplexLinkSmallModel: ListItemModel, MoleculeModelProtocol {
public static var identifier: String = "listDvcLnkS"
public var eyebrow: LabelModel?
public var headline: LabelModel?
public var body: LabelModel?
public var body2: LabelModel?
public var link: LinkModel
public var image: ImageViewModel
public init(eyebrow: LabelModel, headline: LabelModel, body: LabelModel, body2: LabelModel, link: LinkModel, image: ImageViewModel) {
self.eyebrow = eyebrow
self.headline = headline
self.body = body
self.body2 = body2
self.link = link
self.image = image
super.init()
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case eyebrow
case headline
case body
case body2
case link
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)
link = try typeContainer.decode(LinkModel.self, forKey: .link)
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(link, forKey: .link)
try container.encode(image, forKey: .image)
}
}

View File

@ -0,0 +1,55 @@
//
// ListLeftVariableCheckboxBodyText.swift
// MVMCoreUI
//
// Created by Lekshmi S on 14/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class ListLeftVariableCheckboxBodyText: TableViewCell {
//-----------------------------------------------------
// MARK: - Outlets
//-----------------------------------------------------
public let checkbox = Checkbox(frame: .zero)
public var headlineBody = HeadlineBody()
public var stack: Stack<StackModel>
//-----------------------------------------------------
// MARK: - Initializers
//-----------------------------------------------------
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
stack = Stack<StackModel>.createStack(with: [(view: checkbox, model: StackItemModel(horizontalAlignment: .fill)),
(view: headlineBody, model: StackItemModel(horizontalAlignment: .leading))],
axis: .horizontal)
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//-----------------------------------------------------
// MARK: - View Lifecycle
//-----------------------------------------------------
override open func setupView() {
super.setupView()
addMolecule(stack)
stack.restack()
}
//----------------------------------------------------
// MARK: - Molecule
//----------------------------------------------------
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ListLeftVariableCheckboxBodyTextModel else { return }
checkbox.set(with: model.checkbox, delegateObject, additionalData)
headlineBody.set(with: model.headlineBody, delegateObject, additionalData)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 90
}
}

View File

@ -0,0 +1,62 @@
//
// ListLeftVariableCheckboxBodyTextModel.swift
// MVMCoreUI
//
// Created by Lekshmi S on 14/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
open class ListLeftVariableCheckboxBodyTextModel: ListItemModel, MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "listLVCBBdy"
public var checkbox: CheckboxModel
public var headlineBody: HeadlineBodyModel
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(checkbox: CheckboxModel, headlineBody: HeadlineBodyModel) {
self.checkbox = checkbox
self.headlineBody = headlineBody
super.init()
}
open override func setDefaults() {
super.setDefaults()
headlineBody.style = .item
if let headline = headlineBody.headline {
headline.hero = 0
}
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case headlineBody
case checkbox
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody)
checkbox = try typeContainer.decode(CheckboxModel.self, forKey: .checkbox)
try super.init(from: decoder)
}
open override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(headlineBody, forKey: .headlineBody)
try container.encode(checkbox, forKey: .checkbox)
}
}

View File

@ -71,9 +71,6 @@ import UIKit
} }
public override func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { public override func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
radioButton.tapAction()
if radioButton.isEnabled {
radioButton.tapAction()
}
} }
} }

View File

@ -40,24 +40,18 @@ import Foundation
override open func setupView() { override open func setupView() {
super.setupView() super.setupView()
addMolecule(stack) addMolecule(stack)
stack.restack()
} }
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?){ open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?){
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
guard let model = model as? ListOneColumnFullWidthTextAllTextAndLinksModel else { return } guard let model = model as? ListOneColumnFullWidthTextAllTextAndLinksModel else { return }
eyebrow.setOptional(with: model.eyebrow, delegateObject, additionalData) stack.updateContainedMolecules(with: [model.eyebrow,
headline.setOptional(with: model.headline, delegateObject, additionalData) model.headline,
subHeadline.setOptional(with: model.subHeadline, delegateObject, additionalData) model.subHeadline,
body.setOptional(with: model.body, delegateObject, additionalData) model.body,
link.setOptional(with: model.link, delegateObject, additionalData) 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()
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {

View File

@ -8,7 +8,7 @@
import Foundation import Foundation
@objcMembers open class ListRVWheel: TableViewCell { @objcMembers open class ListRVWheel: TableViewCell {
let wheel = GraphView(frame: .zero) let wheel = Wheel(frame: .zero)
let leftLabel = Label.commonLabelB1(true) let leftLabel = Label.commonLabelB1(true)
let rightLabel = Label.commonLabelB2(true) let rightLabel = Label.commonLabelB2(true)
var stack: Stack<StackModel> var stack: Stack<StackModel>

View File

@ -11,9 +11,9 @@ public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol {
public static var identifier: String = "listRVWheel" public static var identifier: String = "listRVWheel"
public var leftLabel: LabelModel public var leftLabel: LabelModel
public var rightLabel: LabelModel public var rightLabel: LabelModel
public var wheel : CircleProgressModel public var wheel: WheelModel
public init(leftLabel: LabelModel, rightLabel: LabelModel, wheel: CircleProgressModel) { public init(leftLabel: LabelModel, rightLabel: LabelModel, wheel: WheelModel) {
self.leftLabel = leftLabel self.leftLabel = leftLabel
self.rightLabel = rightLabel self.rightLabel = rightLabel
self.wheel = wheel self.wheel = wheel
@ -37,7 +37,7 @@ public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel)
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
wheel = try typeContainer.decodeIfPresent(CircleProgressModel.self, forKey: .wheel) ?? CircleProgressModel() wheel = try typeContainer.decodeIfPresent(WheelModel.self, forKey: .wheel) ?? WheelModel()
try super.init(from: decoder) try super.init(from: decoder)
} }

View File

@ -0,0 +1,82 @@
//
// ListRightVariablePriceChangeAllTextAndLinks.swift
// MVMCoreUI
//
// Created by Kruthika KP on 13/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class ListRightVariablePriceChangeAllTextAndLinks: TableViewCell {
//-----------------------------------------------------
// MARK: - Outlets
//-----------------------------------------------------
public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink(frame: .zero)
public let arrow = Arrow(frame: .zero)
public let rightLabel = Label.commonLabelB2(true)
private let stack: Stack<StackModel>
private let arrowStackItem: StackItem
private let rightLabelStackItem: StackItem
//-----------------------------------------------------
// MARK: - Initializers
//-----------------------------------------------------
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
let stackModel = StackModel(molecules: [StackItemModel(horizontalAlignment: .leading),
StackItemModel(horizontalAlignment: .fill),
StackItemModel(spacing: 6, horizontalAlignment: .fill)],
axis: .horizontal)
arrowStackItem = StackItem(andContain: arrow)
rightLabelStackItem = StackItem(andContain: rightLabel)
let stackItems = [StackItem(andContain: eyebrowHeadlineBodyLink), arrowStackItem, rightLabelStackItem]
stack = Stack<StackModel>(with: stackModel, stackItems: stackItems)
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//-----------------------------------------------------
// MARK: - View Lifecycle
//-----------------------------------------------------
open override func alignAccessoryToHero() -> CGPoint? {
let heroCenter = super.alignAccessoryToHero()
// Aligns the center of the right side items to the headline.
if let heroCenter = heroCenter {
let convertedPoint = stack.convert(heroCenter, from: self)
arrowStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - stack.bounds.midY
rightLabelStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - stack.bounds.midY
}
return heroCenter
}
open override func setupView() {
super.setupView()
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal)
rightLabel.numberOfLines = 1
arrow.pinHeightAndWidth()
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? ListRightVariablePriceChangeAllTextAndLinksModel else { return }
eyebrowHeadlineBodyLink.set(with: model.eyebrowHeadlineBodyLink, delegateObject, additionalData)
rightLabel.set(with: model.rightLabel, delegateObject, additionalData)
arrow.set(with: model.arrow, delegateObject, additionalData)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 121
}
}

View File

@ -0,0 +1,47 @@
//
// ListRightVariablePriceChangeAllTextAndLinksModel.swift
// MVMCoreUI
//
// Created by Kruthika KP on 13/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public class ListRightVariablePriceChangeAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol {
public static var identifier: String = "listRVArwAll"
public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel
public var rightLabel: LabelModel
public var arrow: ArrowModel
public init(eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel, rightLabel: LabelModel, arrow: ArrowModel) {
self.eyebrowHeadlineBodyLink = eyebrowHeadlineBodyLink
self.rightLabel = rightLabel
self.arrow = arrow
super.init()
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case eyebrowHeadlineBodyLink
case rightLabel
case arrow
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink)
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
arrow = try typeContainer.decode(ArrowModel.self, forKey: .arrow)
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(eyebrowHeadlineBodyLink, forKey: .eyebrowHeadlineBodyLink)
try container.encode(rightLabel, forKey: .rightLabel)
try container.encode(arrow, forKey: .arrow)
}
}

View File

@ -0,0 +1,70 @@
//
// ListRightVariablePriceChangeBodyText.swift
// MVMCoreUI
//
// Created by Dhamodaram Nandi on 13/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class ListRightVariablePriceChangeBodyText: TableViewCell {
//-----------------------------------------------------
// MARK: - Outlets
//-----------------------------------------------------
private let stack: Stack<StackModel>
public let headlineBody = HeadlineBody(frame: .zero)
public let arrow = Arrow(frame: .zero)
public let rightLabel = Label.commonLabelB2(true)
let arrowAndRightLabelStack: Stack<StackModel>
// MARK: - Initializers
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
arrowAndRightLabelStack = Stack<StackModel>.createStack(with: [(view: arrow, model: StackItemModel(horizontalAlignment: .fill)),
(view: rightLabel, model: StackItemModel(horizontalAlignment: .fill))],
axis: .horizontal, spacing: 6)
stack = Stack<StackModel>.createStack(with: [(view: headlineBody, model: StackItemModel(horizontalAlignment: .leading)),
(view: arrowAndRightLabelStack, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .leading))],
axis: .horizontal)
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//-----------------------------------------------------
// MARK: - View Lifecycle
//-----------------------------------------------------
open override func setupView() {
super.setupView()
headlineBody.styleListItem()
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal)
rightLabel.numberOfLines = 1
arrow.pinHeightAndWidth()
addMolecule(stack)
stack.restack()
arrowAndRightLabelStack.restack()
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ListRightVariablePriceChangeBodyTextModel else { return }
headlineBody.set(with: model.headlineBody, delegateObject, additionalData)
rightLabel.set(with: model.rightLabel, delegateObject, additionalData)
arrow.set(with: model.arrow, delegateObject, additionalData)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 80
}
open override func reset() {
super.reset()
headlineBody.styleListItem()
}
}

View File

@ -0,0 +1,54 @@
//
// ListRightVariablePriceChangeBodyTextModel.swift
// MVMCoreUI
//
// Created by Dhamodaram Nandi on 13/04/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public class ListRightVariablePriceChangeBodyTextModel: ListItemModel, MoleculeModelProtocol {
public static var identifier: String = "listRVArwBdy"
public var headlineBody: HeadlineBodyModel
public var rightLabel: LabelModel
public var arrow: ArrowModel
public init(headlineBody: HeadlineBodyModel,rightLabel: LabelModel,arrow: ArrowModel) {
self.headlineBody = headlineBody
self.rightLabel = rightLabel
self.arrow = arrow
super.init()
}
/// Defaults to set
public override func setDefaults() {
super.setDefaults()
if let headline = headlineBody.headline {
headline.hero = 0
}
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case headlineBody
case rightLabel
case arrow
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody)
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
arrow = try typeContainer.decode(ArrowModel.self, forKey: .arrow)
try super.init(from: decoder)
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(headlineBody, forKey: .headlineBody)
try container.encode(rightLabel, forKey: .rightLabel)
try container.encode(arrow, forKey: .arrow)
}
}

View File

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

View File

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

View File

@ -86,7 +86,7 @@ import Foundation
for item in model.sections { for item in model.sections {
stackItems.append(MoleculeStackItemModel(with: item)) stackItems.append(MoleculeStackItemModel(with: item))
} }
let stack = MoleculeStackModel(molecules: stackItems) let stack = StackModel(molecules: stackItems)
stack.verticalAlignment = .fill stack.verticalAlignment = .fill
colorLablesStack.set(with: stack, delegateObject, additionalData) colorLablesStack.set(with: stack, delegateObject, additionalData)
} }

View File

@ -9,47 +9,24 @@
import Foundation import Foundation
@objcMembers public class FooterModel: MoleculeContainerModel, MoleculeModelProtocol { @objcMembers public class FooterModel: MoleculeContainerModel {
public static var identifier: String = "footer" public override class var identifier: String {
public var backgroundColor: Color? return "footer"
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
} }
/// Defaults to set /// Defaults to set
func setDefaults() { public override func setDefaults() {
if useHorizontalMargins == nil { if useHorizontalMargins == nil {
useHorizontalMargins = true useHorizontalMargins = true
} }
if useVerticalMargins == nil { if useVerticalMargins == nil {
useVerticalMargins = true useVerticalMargins = true
} }
if topMarginPadding == nil { if topPadding == nil {
topMarginPadding = PaddingDefaultVerticalSpacing topPadding = PaddingDefaultVerticalSpacing
} }
if bottomMarginPadding == nil { if bottomPadding == nil {
bottomMarginPadding = PaddingDefaultVerticalSpacing bottomPadding = PaddingDefaultVerticalSpacing
} }
} }
public override init(with moleculeModel: MoleculeModelProtocol) {
super.init(with: moleculeModel)
setDefaults()
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
try super.init(from: decoder)
setDefaults()
}
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(backgroundColor, forKey: .backgroundColor)
}
} }

View File

@ -18,18 +18,18 @@ import Foundation
} }
/// Defaults to set /// Defaults to set
public func setDefaults() { public override func setDefaults() {
if useHorizontalMargins == nil { if useHorizontalMargins == nil {
useHorizontalMargins = true useHorizontalMargins = true
} }
if useVerticalMargins == nil { if useVerticalMargins == nil {
useVerticalMargins = true useVerticalMargins = true
} }
if topMarginPadding == nil { if topPadding == nil {
topMarginPadding = PaddingDefaultVerticalSpacing topPadding = PaddingDefaultVerticalSpacing
} }
if bottomMarginPadding == nil { if bottomPadding == nil {
bottomMarginPadding = PaddingDefaultVerticalSpacing bottomPadding = PaddingDefaultVerticalSpacing
} }
if line == nil { if line == nil {
line = LineModel(type: .heavy) line = LineModel(type: .heavy)
@ -38,7 +38,6 @@ import Foundation
public override init() { public override init() {
super.init() super.init()
setDefaults()
} }
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
@ -46,7 +45,6 @@ import Foundation
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
setDefaults()
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {

View File

@ -0,0 +1,320 @@
//
// Tabs.swift
// MVMCoreUI
//
// Created by Ryan on 2/7/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import UIKit
@objc public protocol TabsDelegate {
func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool
func didSelectItem(_ indexPath: IndexPath, tabs: Tabs)
}
@objcMembers open class Tabs: View, MVMCoreUIViewConstrainingProtocol {
public var tabsModel: TabsModel? {
get { return model as? TabsModel }
}
var delegateObject: MVMCoreUIDelegateObject?
var additionalData: [AnyHashable: Any]?
let layout = UICollectionViewFlowLayout()
public var collectionView: UICollectionView?
let bottomScrollView = UIScrollView(frame: .zero)
let bottomContentView = View()
let bottomLine = View()
var bottomLineLeftConstraint: NSLayoutConstraint?
var bottomLineWidthConstraint: NSLayoutConstraint?
private var widthLabel = Label()
//delegate
weak public var delegate: TabsDelegate?
//control var
public var heightConstraint: NSLayoutConstraint?
public var selectedIndex: Int = 0
public var paddingBeforeFirstTab: Bool = true
//constant
let TabCellId = "TabCell"
public let sectionPadding: CGFloat = 20.0
public let cellSpacing: CGFloat = 34.0
public let cellHeight: CGFloat = 34.0
public let bottomLineHeight: CGFloat = 4.0
public let bottomLineWidth: CGFloat = 32.0
public let tabsHeight: CGFloat = 38.0
public let bottomLineMovingTime: TimeInterval = 0.2
//-------------------------------------------------
// MARK:- Layout Views
//-------------------------------------------------
open override func reset() {
super.reset()
heightConstraint?.constant = tabsHeight
selectedIndex = 0
paddingBeforeFirstTab = true
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
}
open override func setupView() {
super.setupView()
backgroundColor = .white
setupCollectionView()
setupBottomLine()
setupConstraints()
}
func setupCollectionView () {
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = cellSpacing
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.register(TabItemCell.self, forCellWithReuseIdentifier: TabCellId)
collectionView.backgroundColor = .clear
collectionView.showsVerticalScrollIndicator = false
collectionView.showsHorizontalScrollIndicator = false
collectionView.dataSource = self
collectionView.delegate = self
addSubview(collectionView)
self.collectionView = collectionView
}
func setupBottomLine() {
bottomScrollView.translatesAutoresizingMaskIntoConstraints = false
bottomScrollView.delegate = self
addSubview(bottomScrollView)
bottomScrollView.addSubview(bottomContentView)
bottomLine.backgroundColor = .mvmRed
bottomContentView.addSubview(bottomLine)
bringSubviewToFront(bottomScrollView)
}
func setupConstraints() {
//collection view
NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView)
//bottom lines
NSLayoutConstraint.constraintPinSubview(bottomScrollView, pinTop: false, pinBottom: true, pinLeft: true, pinRight: true)
bottomScrollView.heightAnchor.constraint(equalToConstant: bottomLineHeight).isActive = true
NSLayoutConstraint.constraintPinSubview(bottomLine, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false)
bottomLine.heightAnchor.constraint(equalToConstant: bottomLineHeight).isActive = true
bottomLineLeftConstraint = bottomLine.leftAnchor.constraint(equalTo: bottomContentView.leftAnchor)
bottomLineLeftConstraint?.isActive = true
bottomLineWidthConstraint = bottomLine.widthAnchor.constraint(equalToConstant: bottomLineWidth)
bottomLineWidthConstraint?.isActive = true
NSLayoutConstraint.constraintPinSubview(toSuperview: bottomContentView)
//height
heightConstraint = heightAnchor.constraint(equalToConstant: tabsHeight)
heightConstraint?.isActive = true
}
//-------------------------------------------------
// MARK:- Control Methods
//-------------------------------------------------
public func pinHeight(_ height: CGFloat) {
heightConstraint?.constant = height
setNeedsLayout()
layoutIfNeeded()
}
public func selectIndex(_ index: Int, animated: Bool) {
guard let _ = collectionView, tabsModel?.tabs.count ?? 0 > 0 else {
selectedIndex = index
return
}
MVMCoreDispatchUtility.performBlock(onMainThread: {
let currentIndex = self.selectedIndex
self.selectedIndex = index
self.deselect(indexPath: IndexPath(row: currentIndex, section: 0))
self.selectItem(atIndexPath: IndexPath(row: index, section: 0), animated: animated)
})
}
public func reloadData() {
collectionView?.reloadData()
}
//-------------------------------------------------
// MARK:- Molecule Setup
//-------------------------------------------------
override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.set(with: model, delegateObject, additionalData)
self.delegateObject = delegateObject
self.additionalData = additionalData
self.selectedIndex = tabsModel?.selectedIndex ?? 0
self.bottomLine.backgroundColor = tabsModel?.selectedColor.uiColor
reloadData()
}
}
//-------------------------------------------------
// MARK:- Collection View Methods
//-------------------------------------------------
extension Tabs: UICollectionViewDataSource {
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return tabsModel?.tabs.count ?? 0
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let labelModel = tabsModel?.tabs[indexPath.row].label, let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TabCellId, for: indexPath) as? TabItemCell else {
return UICollectionViewCell()
}
cell.updateCell(labelModel: labelModel, indexPath: indexPath, delegateObject: delegateObject, additionalData: additionalData, selected: indexPath.row == selectedIndex, tabsModel: tabsModel)
return cell
}
}
extension Tabs: UICollectionViewDelegateFlowLayout {
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
guard let labelModel = tabsModel?.tabs[indexPath.row].label else {
return .zero
}
return CGSize(width: getLabelWidth(labelModel).width, height: cellHeight)
}
//pre calculate the width of the collection cell
//when user select tabs, it will reload related collectionview, if we use autosize, it would relayout the width, need to keep the cell width constant.
func getLabelWidth(_ labelModel: LabelModel?) -> CGSize {
guard let labelModel = labelModel else { return .zero}
widthLabel.set(with: labelModel, nil, nil)
let cgSize = widthLabel.intrinsicContentSize
widthLabel.reset()
return cgSize
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
if !paddingBeforeFirstTab && section == 0 {
return .zero
} else {
return UIEdgeInsets(top: 0, left: sectionPadding, bottom: 0, right: 0)
}
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return sectionPadding
}
public func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
return delegate?.shouldSelectItem(indexPath, tabs: self) ?? true
}
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectIndex(indexPath.row, animated: true)
}
public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
guard let tabCell = cell as? TabItemCell else { return }
if indexPath.row == selectedIndex {
moveBottomLine(toIndex: indexPath, animated: false, cell: tabCell)
}
}
func deselect(indexPath:IndexPath) {
collectionView?.deselectItem(at: indexPath, animated: false)
collectionView?.reloadItems(at: [indexPath])
}
func selectItem(atIndexPath indexPath: IndexPath, animated: Bool) {
guard let collect = collectionView, tabsModel?.tabs.count ?? 0 > 0 else { return }
collect.selectItem(at: indexPath, animated: animated, scrollPosition: .centeredHorizontally)
guard let tabCell = collect.cellForItem(at: indexPath) as? TabItemCell, let tabsModel = self.tabsModel else { return }
self.moveBottomLine(toIndex: indexPath, animated: animated, cell: tabCell)
tabCell.label.textColor = tabsModel.selectedColor.uiColor
tabCell.updateAccessibility(indexPath: indexPath, selected: true, tabsModel: tabsModel)
tabCell.setNeedsDisplay()
tabCell.setNeedsLayout()
tabCell.layoutIfNeeded()
self.delegate?.didSelectItem(indexPath, tabs: self)
}
}
extension Tabs: UIScrollViewDelegate {
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
/*bottomScrollview is subview of self, it's not belongs to collectionview.
When collectionview is scrolling, bottomScrollView will stay without moving
Adding collectionview's offset to bottomScrollView, will make the bottomScrollview looks like scrolling with the selected tab item.
*/
guard let offsetX = collectionView?.contentOffset.x else { return }
bottomScrollView.setContentOffset(CGPoint(x: offsetX, y: bottomScrollView.contentOffset.y), animated: false)
}
}
//-------------------------------------------------
// MARK:- Bottom Line Methods
//-------------------------------------------------
extension Tabs {
func moveBottomLine(toIndex indexPath: IndexPath, animated: Bool, cell: TabItemCell) {
guard let collect = self.collectionView else {return}
let size = collectionView(collect, layout: layout, sizeForItemAt: indexPath)
let barWidth = max(size.width, bottomLineWidth)
let animationBlock = {
[weak self] in
let x = cell.frame.origin.x
self?.bottomLineWidthConstraint?.constant = barWidth
self?.bottomLineLeftConstraint?.constant = x + (size.width - barWidth) / 2.0
self?.bottomContentView.layoutIfNeeded()
}
if animated {
UIView.animate(withDuration: bottomLineMovingTime, animations: animationBlock)
} else {
animationBlock()
}
}
}
@objcMembers public class TabItemCell: CollectionViewCell {
public let label = Label()
public var labelModel: LabelModel?
public override func setupView() {
super.setupView()
contentView.addSubview(label)
NSLayoutConstraint.constraintPinSubview(label, pinTop: false, pinBottom: false, pinLeft: true, pinRight: true)
label.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
label.baselineAdjustment = .alignCenters
}
public func updateCell(labelModel: LabelModel, indexPath: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, selected: Bool, tabsModel: TabsModel?) {
label.reset()
label.set(with: labelModel, delegateObject, additionalData)
self.labelModel = labelModel
if selected, let selectedColor = tabsModel?.selectedColor {
label.textColor = selectedColor.uiColor
}
updateAccessibility(indexPath: indexPath, selected: selected, tabsModel: tabsModel)
}
public func updateAccessibility(indexPath: IndexPath, selected: Bool, tabsModel: TabsModel?) {
//Accessibility
isAccessibilityElement = false
contentView.isAccessibilityElement = true
let accKey = selected ? "toptabbar_tab_selected" : "AccTab"
let accLabel = "\(label.text ?? "") \(MVMCoreUIUtility.hardcodedString(withKey: accKey) ?? "")"
let accOrder = String(format: MVMCoreUIUtility.hardcodedString(withKey: "AccTabIndex") ?? "", indexPath.row + 1, tabsModel?.tabs.count ?? 0)
contentView.accessibilityLabel = "\(accLabel) \(accOrder)"
contentView.accessibilityHint = selected ? nil : MVMCoreUIUtility.hardcodedString(withKey: "AccTabHint")
}
}

View File

@ -11,7 +11,7 @@ import UIKit
public class TabsModel: MoleculeModelProtocol { public class TabsModel: MoleculeModelProtocol {
public static var identifier: String = "tabs" public static var identifier: String = "tabs"
public var backgroundColor: Color? public var backgroundColor: Color?
public var tabs: [LabelModel] public var tabs: [TabItemModel]
public var selectedColor = Color(uiColor: .mfTomatoRed()) public var selectedColor = Color(uiColor: .mfTomatoRed())
// Must be capped to 0...(tabs.count - 1) // Must be capped to 0...(tabs.count - 1)
@ -25,13 +25,13 @@ public class TabsModel: MoleculeModelProtocol {
case moleculeName case moleculeName
} }
public init(with tabs: [LabelModel]) { public init(with tabs: [TabItemModel]) {
self.tabs = tabs self.tabs = tabs
} }
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
tabs = try typeContainer.decode([LabelModel].self, forKey: .tabs) tabs = try typeContainer.decode([TabItemModel].self, forKey: .tabs)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor) { if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor) {
selectedColor = color selectedColor = color
@ -50,3 +50,33 @@ public class TabsModel: MoleculeModelProtocol {
try container.encode(selectedIndex, forKey: .selectedIndex) try container.encode(selectedIndex, forKey: .selectedIndex)
} }
} }
public class TabItemModel: Codable {
var label: LabelModel
var action: ActionModelProtocol?
init(label: LabelModel) {
self.label = label
}
private enum CodingKeys: String, CodingKey {
case label
case action
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
label = try typeContainer.decode(LabelModel.self, forKey: .label)
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeModel(label, forKey: .label)
try container.encodeModelIfPresent(action, forKey: .action)
}
}

View File

@ -38,7 +38,7 @@ import Foundation
//-------------------------------------------------- //--------------------------------------------------
/// Defaults to set /// Defaults to set
open func setDefaults() { open override func setDefaults() {
if useHorizontalMargins == nil { if useHorizontalMargins == nil {
useHorizontalMargins = true useHorizontalMargins = true
} }
@ -54,9 +54,12 @@ import Foundation
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public override init(horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, useHorizontalMargins: Bool? = nil, leftPadding: CGFloat? = nil, rightPadding: CGFloat? = nil, useVerticalMargins: Bool? = nil, topPadding: CGFloat? = nil, bottomPadding: CGFloat? = nil) {
super.init(horizontalAlignment: horizontalAlignment, verticalAlignment: verticalAlignment, useHorizontalMargins: useHorizontalMargins, leftPadding: leftPadding, rightPadding: rightPadding, useVerticalMargins: useVerticalMargins, topPadding: topPadding, bottomPadding: bottomPadding)
}
public override init() { public override init() {
super.init() super.init()
setDefaults()
} }
//-------------------------------------------------- //--------------------------------------------------
@ -71,7 +74,6 @@ import Foundation
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
style = try typeContainer.decodeIfPresent(String.self, forKey: .style) style = try typeContainer.decodeIfPresent(String.self, forKey: .style)
try super.init(from: decoder) try super.init(from: decoder)
setDefaults()
} }
open override func encode(to encoder: Encoder) throws { open override func encode(to encoder: Encoder) throws {

View File

@ -9,49 +9,36 @@
import Foundation import Foundation
/// A model for a collection item that is a container for any molecule. /// A model for a collection item that is a container for any molecule.
@objcMembers public class MoleculeCollectionItemModel: MoleculeContainerModel, CollectionItemModelProtocol, MoleculeModelProtocol { @objcMembers public class MoleculeCollectionItemModel: MoleculeContainerModel, CollectionItemModelProtocol {
open class var identifier: String { open override class var identifier: String {
return "collectionItem" return "collectionItem"
} }
public var backgroundColor: Color?
/// Defaults to set /// Defaults to set
public func setDefaults() { public override func setDefaults() {
if useHorizontalMargins == nil { if useHorizontalMargins == nil {
useHorizontalMargins = true useHorizontalMargins = true
} }
if useVerticalMargins == nil { if useVerticalMargins == nil {
useVerticalMargins = true useVerticalMargins = true
} }
if topMarginPadding == nil { if topPadding == nil {
topMarginPadding = PaddingDefault topPadding = PaddingDefault
} }
if bottomMarginPadding == nil { if bottomPadding == nil {
bottomMarginPadding = PaddingDefault bottomPadding = PaddingDefault
} }
} }
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
}
public override init(with moleculeModel: MoleculeModelProtocol) { public override init(with moleculeModel: MoleculeModelProtocol) {
super.init(with: moleculeModel) super.init(with: moleculeModel)
setDefaults()
} }
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
try super.init(from: decoder) try super.init(from: decoder)
setDefaults()
} }
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)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
} }
} }

View File

@ -54,6 +54,6 @@ open class MoleculeCollectionViewCell: CollectionViewCell {
let height = classType.estimatedHeight(with: model.molecule, delegateObject) let height = classType.estimatedHeight(with: model.molecule, delegateObject)
else { return 100 } else { return 100 }
return height + (model.topMarginPadding ?? 0) + (model.bottomMarginPadding ?? 0) return height + (model.topPadding ?? 0) + (model.bottomPadding ?? 0)
} }
} }

View File

@ -8,15 +8,15 @@
import Foundation import Foundation
@objcMembers public class MoleculeStackItemModel: MoleculeContainerModel, MoleculeModelProtocol, StackItemModelProtocol { @objcMembers public class MoleculeStackItemModel: MoleculeContainerModel, StackItemModelProtocol {
public static var identifier: String = "stackItem" public override class var identifier: String {
public var backgroundColor: Color? return "stackItem"
}
public var spacing: CGFloat? public var spacing: CGFloat?
public var percent: Int? public var percent: Int?
public var gone: Bool = false public var gone: Bool = false
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName
case spacing case spacing
case percent case percent
case gone case gone
@ -39,7 +39,6 @@ import Foundation
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.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(spacing, forKey: .spacing) try container.encodeIfPresent(spacing, forKey: .spacing)
try container.encodeIfPresent(percent, forKey: .percent) try container.encodeIfPresent(percent, forKey: .percent)
try container.encode(gone, forKey: .gone) try container.encode(gone, forKey: .gone)

View File

@ -24,16 +24,17 @@ import Foundation
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public convenience init(spacing: CGFloat? = nil, percent: Int? = nil, horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, gone: Bool? = nil) { public init(spacing: CGFloat? = nil, percent: Int? = nil, horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, gone: Bool? = nil) {
self.init()
self.horizontalAlignment = horizontalAlignment
self.verticalAlignment = verticalAlignment
self.spacing = spacing self.spacing = spacing
self.percent = percent self.percent = percent
if let gone = gone { if let gone = gone {
self.gone = gone self.gone = gone
} }
super.init(horizontalAlignment: horizontalAlignment, verticalAlignment: verticalAlignment)
}
required public init(from decoder: Decoder) throws {
fatalError("init(from:) has not been implemented")
} }
} }

View File

@ -8,7 +8,7 @@
import Foundation import Foundation
public protocol StackItemModelProtocol: MoleculeModelProtocol { public protocol StackItemModelProtocol {
var spacing: CGFloat? { get set } var spacing: CGFloat? { get set }
var percent: Int? { get set } var percent: Int? { get set }
var gone: Bool { get set } var gone: Bool { get set }

View File

@ -24,8 +24,8 @@ public class TabsListItemModel: ListItemModel, MoleculeModelProtocol {
hideArrow = true hideArrow = true
action = nil action = nil
style = nil style = nil
topMarginPadding = 8 topPadding = 8
bottomMarginPadding = 0 bottomPadding = 0
} }
public init(with tabs: TabsModel, molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]) { public init(with tabs: TabsModel, molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]) {

View File

@ -12,7 +12,7 @@ import UIKit
var tabsListItemModel: TabsListItemModel? { var tabsListItemModel: TabsListItemModel? {
return listItemModel as? TabsListItemModel return listItemModel as? TabsListItemModel
} }
let tabs = TopTabbar(frame: .zero) let tabs = Tabs(frame: .zero)
var delegateObject: MVMCoreUIDelegateObject? var delegateObject: MVMCoreUIDelegateObject?
var previousTabIndex = 0 var previousTabIndex = 0
@ -22,7 +22,6 @@ import UIKit
tabs.paddingBeforeFirstTab = false tabs.paddingBeforeFirstTab = false
tabs.translatesAutoresizingMaskIntoConstraints = false tabs.translatesAutoresizingMaskIntoConstraints = false
tabs.delegate = self tabs.delegate = self
tabs.datasource = self
contentView.addSubview(tabs) contentView.addSubview(tabs)
NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: tabs, useMargins: true).values)) NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: tabs, useMargins: true).values))
@ -39,7 +38,9 @@ import UIKit
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
self.delegateObject = delegateObject self.delegateObject = delegateObject
tabs.reloadData() if let tabsModel = tabsListItemModel?.tabs {
tabs.set(with: tabsModel, delegateObject, additionalData)
}
} }
public override func reset() { public override func reset() {
@ -53,33 +54,22 @@ import UIKit
} }
} }
extension TabsTableViewCell: TopTabbarDelegate { extension TabsTableViewCell: TabsDelegate {
public func shouldSelectItem(at index: Int, topTabbar: TopTabbar) -> Bool { public func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool {
if let model = tabsListItemModel { if let model = tabsListItemModel {
let molecules = model.molecules[topTabbar.selectedIndex] let molecules = model.molecules[tabs.selectedIndex]
delegateObject?.moleculeDelegate?.removeMolecules(molecules, animation: index < tabs.selectedIndex ? .right : .left) delegateObject?.moleculeDelegate?.removeMolecules(molecules, animation: indexPath.row < tabs.selectedIndex ? .right : .left)
} }
previousTabIndex = tabs.selectedIndex previousTabIndex = tabs.selectedIndex
return true return true
} }
public func topTabbar(_ topTabbar: TopTabbar, didSelectItemAt index: Int) { public func didSelectItem(_ indexPath: IndexPath, tabs: Tabs) {
guard let model = tabsListItemModel, let index = indexPath.row
let indexPath = delegateObject?.moleculeDelegate?.getIndexPath(for: model) else { return } if let model = tabsListItemModel, index < model.molecules.count {
let molecules = model.molecules[index] let molecules = model.molecules[index]
delegateObject?.moleculeDelegate?.addMolecules(molecules, indexPath: indexPath, animation: index < previousTabIndex ? .left : .right) delegateObject?.moleculeDelegate?.addMolecules(molecules, indexPath: indexPath, animation: index < previousTabIndex ? .left : .right)
}
}
extension TabsTableViewCell: TopTabbarDataSource {
public func number(ofTopTabbarItems topTabbar: TopTabbar) -> Int {
return tabsListItemModel?.tabs.tabs.count ?? 0
}
public func topTabbar(_ topTabbar: TopTabbar, titleForItemAt index: Int) -> String? {
guard let title = tabsListItemModel?.tabs.tabs[index].text else {
return "Select"
} }
return title
} }
} }

View File

@ -164,10 +164,12 @@ import UIKit
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
guard let model = model as? CornerLabelsModel else { return } guard let model = model as? CornerLabelsModel else { return }
if middleView != nil { if let moleculeModel = model.molecule {
(middleView as? MoleculeViewProtocol)?.set(with: model, delegateObject, additionalData) if middleView != nil {
} else if let moleculeModel = model.molecule, let molecule = MoleculeObjectMapping.shared()?.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) { (middleView as? MoleculeViewProtocol)?.set(with: moleculeModel, delegateObject, additionalData)
addMiddleView(molecule) } else if let molecule = MoleculeObjectMapping.shared()?.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) {
addMiddleView(molecule)
}
} }
topLeftLabel.setOptional(with: model.topLeftLabel, delegateObject, additionalData) topLeftLabel.setOptional(with: model.topLeftLabel, delegateObject, additionalData)

View File

@ -8,11 +8,19 @@
import UIKit import UIKit
@objcMembers open class LabelToggle: View { @objcMembers open class LabelToggle: View {
public let label = Label.commonLabelB1(true) //--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public let label = Label.createLabelBoldBodySmall(true)
public let toggle = Toggle() public let toggle = Toggle()
//--------------------------------------------------
// MARK: - MVMCoreViewProtocol // MARK: - MVMCoreViewProtocol
//--------------------------------------------------
open override func updateView(_ size: CGFloat) { open override func updateView(_ size: CGFloat) {
super.updateView(size) super.updateView(size)
label.updateView(size) label.updateView(size)
@ -21,28 +29,26 @@ import UIKit
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
guard toggle.superview == nil else {
return
}
addSubview(label) addSubview(label)
addSubview(toggle) addSubview(toggle)
label.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical) label.setContentHuggingPriority(.required, for: .vertical)
NSLayoutConstraint.pinViews(leftView: label, rightView: toggle, alignTop: false) NSLayoutConstraint.pinViews(leftView: label, rightView: toggle, alignTop: false)
} }
// MARK:- MoleculeViewProtocol
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
guard let model = model as? LabelToggleModel, guard let model = model as? LabelToggleModel,
let toggleHeight = Toggle.estimatedHeight(with: model.toggle, delegateObject), 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) return max(toggleHeight, labelHeight)
} }
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { 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) label.set(with: labelToggleModel.label, delegateObject, additionalData)
toggle.set(with: labelToggleModel.toggle, delegateObject, additionalData) toggle.set(with: labelToggleModel.toggle, delegateObject, additionalData)
} }
@ -52,6 +58,6 @@ import UIKit
super.reset() super.reset()
label.reset() label.reset()
toggle.reset() toggle.reset()
label.styleB1(true) label.styleBoldBodySmall(true)
} }
} }

View File

@ -10,17 +10,16 @@ import Foundation
public protocol NavigationItemModelProtocol { public protocol NavigationItemModelProtocol {
var title: String? { get set } var title: String? { get set }
var titleView: MoleculeModelProtocol? { get set }
var hidden: Bool { get set } var hidden: Bool { get set }
var backgroundColor: Color? { get set } var backgroundColor: Color? { get set }
var transparent: Bool { get set } var translucent: Bool { get set }
var tintColor: Color { get set } var tintColor: Color { get set }
var line: LineModel? { get set } var line: LineModel? { get set }
var systemBackButton: Bool { get set } var showLeftPanelButton: Bool { get set }
var showLeftPanelButton: Bool? { get set } var showRightPanelButton: Bool { get set }
var showRightPanelButton: Bool? { get set } var backButton: NavigationItemButtonModel? { get set }
var additionalLeftItems: [NavigationItemButtonModel]? { get set } var additionalLeftButtons: [NavigationItemButtonModel]? { get set }
var additionalRightItems: [NavigationItemButtonModel]? { get set } var additionalRightButtons: [NavigationItemButtonModel]? { get set }
} }
public class NavigationItemButtonModel: Codable { public class NavigationItemButtonModel: Codable {
@ -52,74 +51,73 @@ public class NavigationItemButtonModel: Codable {
public class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtocol { public class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtocol {
public class var identifier: String { public class var identifier: String {
return "navigationItem" return "navigationBar"
} }
public var title: String? public var title: String?
public var titleView: MoleculeModelProtocol?
public var hidden: Bool public var hidden: Bool
public var backgroundColor: Color? public var backgroundColor: Color?
public var transparent: Bool public var translucent: Bool
public var tintColor: Color public var tintColor: Color
public var line: LineModel? public var line: LineModel?
public var systemBackButton = false public var showLeftPanelButton: Bool
public var showLeftPanelButton: Bool? public var showRightPanelButton: Bool
public var showRightPanelButton: Bool? public var backButton: NavigationItemButtonModel?
public var additionalLeftItems: [NavigationItemButtonModel]? public var additionalLeftButtons: [NavigationItemButtonModel]?
public var additionalRightItems: [NavigationItemButtonModel]? public var additionalRightButtons: [NavigationItemButtonModel]?
init() { public init() {
hidden = false hidden = false
transparent = false translucent = false
backgroundColor = Color(uiColor: .white) backgroundColor = Color(uiColor: .white)
tintColor = Color(uiColor: .black) tintColor = Color(uiColor: .black)
line = LineModel(type: .standard) line = LineModel(type: .standard)
showLeftPanelButton = true
showRightPanelButton = true
backButton = NavigationItemButtonModel(with: "back", action: ActionBackModel())
} }
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case title case title
case titleView
case hidden case hidden
case backgroundColor case backgroundColor
case transparent case translucent
case tintColor case tintColor
case line case line
case systemBackButton case backButton
case showLeftPanelButton case showLeftPanelButton
case showRightPanelButton case showRightPanelButton
case additionalLeftItems case additionalLeftButtons
case additionalRightItems case additionalRightButtons
} }
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
title = try typeContainer.decodeIfPresent(String.self, forKey: .title) title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
titleView = try typeContainer.decodeModelIfPresent(codingKey: .titleView)
hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) ?? false hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) ?? false
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) ?? Color(uiColor: .white) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) ?? Color(uiColor: .white)
transparent = try typeContainer.decodeIfPresent(Bool.self, forKey: .transparent) ?? false translucent = try typeContainer.decodeIfPresent(Bool.self, forKey: .translucent) ?? false
tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor) ?? Color(uiColor: .black) tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor) ?? Color(uiColor: .black)
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
systemBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .systemBackButton) ?? false backButton = try typeContainer.decodeIfPresent(NavigationItemButtonModel.self, forKey: .backButton) ?? NavigationItemButtonModel(with: "back", action: ActionBackModel())
showLeftPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showLeftPanelButton) showLeftPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showLeftPanelButton) ?? true
showRightPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showRightPanelButton) showRightPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showRightPanelButton) ?? true
additionalLeftItems = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalLeftItems) additionalLeftButtons = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalLeftButtons)
additionalRightItems = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalRightItems) additionalRightButtons = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalRightButtons)
} }
open func encode(to encoder: Encoder) throws { open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(title, forKey: .title) try container.encodeIfPresent(title, forKey: .title)
try container.encodeModelIfPresent(titleView, forKey: .titleView)
try container.encode(hidden, forKey: .hidden) try container.encode(hidden, forKey: .hidden)
try container.encode(backgroundColor, forKey: .backgroundColor) try container.encode(backgroundColor, forKey: .backgroundColor)
try container.encode(transparent, forKey: .transparent) try container.encode(translucent, forKey: .translucent)
try container.encode(tintColor, forKey: .tintColor) try container.encode(tintColor, forKey: .tintColor)
try container.encodeIfPresent(line, forKey: .line) try container.encodeIfPresent(line, forKey: .line)
try container.encode(systemBackButton, forKey: .systemBackButton) try container.encodeIfPresent(backButton, forKey: .backButton)
try container.encode(showLeftPanelButton, forKey: .showLeftPanelButton) try container.encode(showLeftPanelButton, forKey: .showLeftPanelButton)
try container.encode(showRightPanelButton, forKey: .showRightPanelButton) try container.encode(showRightPanelButton, forKey: .showRightPanelButton)
try container.encodeIfPresent(additionalLeftItems, forKey: .additionalLeftItems) try container.encodeIfPresent(additionalLeftButtons, forKey: .additionalLeftButtons)
try container.encodeIfPresent(additionalRightItems, forKey: .additionalRightItems) try container.encodeIfPresent(additionalRightButtons, forKey: .additionalRightButtons)
} }
} }

View File

@ -8,8 +8,9 @@
import UIKit import UIKit
public class ScrollerModel: MoleculeContainerModel, MoleculeModelProtocol { public class ScrollerModel: MoleculeContainerModel {
public static var identifier: String = "scroller" public override class var identifier: String {
return "scroller"
}
public var moleculeName: String = ScrollerModel.identifier public var moleculeName: String = ScrollerModel.identifier
public var backgroundColor: Color?
} }

View File

@ -20,22 +20,21 @@ public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtoc
self.headlineBody = headlineBody self.headlineBody = headlineBody
self.image = image self.image = image
super.init() super.init()
setDefaults()
} }
/// Defaults to set /// Defaults to set
func setDefaults() { public override func setDefaults() {
if useHorizontalMargins == nil { if useHorizontalMargins == nil {
useHorizontalMargins = true useHorizontalMargins = true
} }
if useVerticalMargins == nil { if useVerticalMargins == nil {
useVerticalMargins = true useVerticalMargins = true
} }
if topMarginPadding == nil { if topPadding == nil {
topMarginPadding = PaddingDefault topPadding = PaddingDefault
} }
if bottomMarginPadding == nil { if bottomPadding == nil {
bottomMarginPadding = PaddingDefault bottomPadding = PaddingDefault
} }
if image.height == nil { if image.height == nil {
image.height = BGImageHeadlineBodyButton.heightConstant image.height = BGImageHeadlineBodyButton.heightConstant
@ -59,7 +58,6 @@ public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtoc
image = try typeContainer.decode(ImageViewModel.self, forKey: .image) image = try typeContainer.decode(ImageViewModel.self, forKey: .image)
button = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .button) button = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .button)
try super.init(from: decoder) try super.init(from: decoder)
setDefaults()
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {

View File

@ -33,6 +33,7 @@ import UIKit
stack.stackModel?.spacing = 0 stack.stackModel?.spacing = 0
addSubview(stack) addSubview(stack)
NSLayoutConstraint.constraintPinSubview(toSuperview: stack) NSLayoutConstraint.constraintPinSubview(toSuperview: stack)
stack.restack()
} }
open override func updateView(_ size: CGFloat) { open override func updateView(_ size: CGFloat) {
@ -58,18 +59,11 @@ import UIKit
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
stack.updateContainedMolecules(with: [castModel?.eyebrow,
eyebrow.setOptional(with: castModel?.eyebrow, delegateObject, additionalData) castModel?.headline,
headline.setOptional(with: castModel?.headline, delegateObject, additionalData) castModel?.body,
body.setOptional(with: castModel?.body, delegateObject, additionalData) castModel?.link],
link.setOptional(with: castModel?.link, delegateObject, additionalData) 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()
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {

View File

@ -19,22 +19,21 @@ public class HeadlineBodyCaretLinkImageModel: ContainerModel, MoleculeModelProto
self.headlineBody = headlineBody self.headlineBody = headlineBody
self.image = image self.image = image
super.init() super.init()
setDefaults()
} }
/// Defaults to set /// Defaults to set
func setDefaults() { public override func setDefaults() {
if useHorizontalMargins == nil { if useHorizontalMargins == nil {
useHorizontalMargins = true useHorizontalMargins = true
} }
if useVerticalMargins == nil { if useVerticalMargins == nil {
useVerticalMargins = true useVerticalMargins = true
} }
if topMarginPadding == nil { if topPadding == nil {
topMarginPadding = PaddingDefault topPadding = PaddingDefault
} }
if bottomMarginPadding == nil { if bottomPadding == nil {
bottomMarginPadding = PaddingDefault bottomPadding = PaddingDefault
} }
if image.height == nil { if image.height == nil {
image.height = HeadLineBodyCaretLinkImage.heightConstant image.height = HeadLineBodyCaretLinkImage.heightConstant
@ -56,7 +55,6 @@ public class HeadlineBodyCaretLinkImageModel: ContainerModel, MoleculeModelProto
image = try typeContainer.decode(ImageViewModel.self, forKey: .image) image = try typeContainer.decode(ImageViewModel.self, forKey: .image)
caretLink = try typeContainer.decodeIfPresent(CaretLinkModel.self, forKey: .caretLink) caretLink = try typeContainer.decodeIfPresent(CaretLinkModel.self, forKey: .caretLink)
try super.init(from: decoder) try super.init(from: decoder)
setDefaults()
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {

View File

@ -8,7 +8,7 @@
import Foundation import Foundation
@objcMembers public class NumberedListModel: MoleculeStackModel { @objcMembers public class NumberedListModel: StackModel {
public override class var identifier: String { public override class var identifier: String {
return "numberedList" return "numberedList"
} }
@ -28,8 +28,7 @@ import Foundation
for (index, molecule) in list.enumerated() { for (index, molecule) in list.enumerated() {
models.append(MoleculeStackItemModel(with: StringAndMoleculeModel(string: "\(index+1).", molecule: molecule))) models.append(MoleculeStackItemModel(with: StringAndMoleculeModel(string: "\(index+1).", molecule: molecule)))
} }
super.init(molecules: models) super.init(molecules: models, spacing: 0)
spacing = 0
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
@ -39,7 +38,7 @@ import Foundation
var models: [MoleculeModelProtocol] = [] var models: [MoleculeModelProtocol] = []
for molecule in molecules { for molecule in molecules {
models.append(molecule.molecule) models.append(((molecule as! MoleculeStackItemModel).molecule as! StringAndMoleculeModel).molecule)
} }
try container.encodeModels(models, forKey: .list) try container.encodeModels(models, forKey: .list)
} }

View File

@ -11,8 +11,9 @@ import UIKit
// This class is only temporarily necessary. Eventually we will have initWithModel instad of just init for moleculeviews, which will remove this need. // This class is only temporarily necessary. Eventually we will have initWithModel instad of just init for moleculeviews, which will remove this need.
open class StringAndMoleculeStack: MoleculeStackView { open class StringAndMoleculeStack: MoleculeStackView {
override open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { override open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
guard let model = stackModel else { return } guard let model = model as? StackModelProtocol,
for stackItemModel in model.molecules { let molcules = model.molecules as? [MoleculeStackItemModel] else { return }
for stackItemModel in molcules {
guard let stringAndMoleculeModel = stackItemModel.molecule as? StringAndMoleculeModel, guard let stringAndMoleculeModel = stackItemModel.molecule as? StringAndMoleculeModel,
let molecule = MoleculeObjectMapping.shared()?.createMolecule(stringAndMoleculeModel.molecule, delegateObject: delegateObject let molecule = MoleculeObjectMapping.shared()?.createMolecule(stringAndMoleculeModel.molecule, delegateObject: delegateObject
, additionalData: additionalData) else { , additionalData: additionalData) else {

View File

@ -10,7 +10,6 @@ import Foundation
open class StringAndMoleculeView: View { open class StringAndMoleculeView: View {
var label = Label.commonLabelB2(true) var label = Label.commonLabelB2(true)
var string: String
var molecule: MoleculeViewProtocol var molecule: MoleculeViewProtocol
var leftWidthConstraint: NSLayoutConstraint? var leftWidthConstraint: NSLayoutConstraint?
@ -28,7 +27,7 @@ open class StringAndMoleculeView: View {
// MARK: - Inits // MARK: - Inits
public init(string: String, molecule: MoleculeViewProtocol) { public init(string: String, molecule: MoleculeViewProtocol) {
self.string = string self.label.text = string
self.molecule = molecule self.molecule = molecule
super.init(frame: .zero) super.init(frame: .zero)
} }

View File

@ -8,7 +8,7 @@
import Foundation import Foundation
@objcMembers public class UnOrderedListModel: MoleculeStackModel { @objcMembers public class UnOrderedListModel: StackModel {
public override class var identifier: String { public override class var identifier: String {
return "unOrderedList" return "unOrderedList"
} }
@ -33,8 +33,7 @@ import Foundation
for molecule in list { for molecule in list {
models.append(MoleculeStackItemModel(with: StringAndMoleculeModel(string: bulletChar, molecule: molecule))) models.append(MoleculeStackItemModel(with: StringAndMoleculeModel(string: bulletChar, molecule: molecule)))
} }
super.init(molecules: models) super.init(molecules: models, spacing: 0)
spacing = 0
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
@ -45,7 +44,7 @@ import Foundation
var models: [MoleculeModelProtocol] = [] var models: [MoleculeModelProtocol] = []
for molecule in molecules { for molecule in molecules {
models.append(molecule.molecule) models.append(((molecule as! MoleculeStackItemModel).molecule as! StringAndMoleculeModel).molecule)
} }
try container.encodeModels(models, forKey: .list) try container.encodeModels(models, forKey: .list)
} }

View File

@ -1,54 +0,0 @@
//
// MoleculeStack.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 10/3/19.
// Copyright © 2019 Suresh, Kamlesh. All rights reserved.
//
// A stack that has a list molecule stack items.
import Foundation
@objcMembers public class MoleculeStackModel: ContainerModel, MoleculeModelProtocol, StackModelProtocol {
public class var identifier: String {
return "stack"
}
public var backgroundColor: Color?
public var molecules: [MoleculeStackItemModel]
public var axis: NSLayoutConstraint.Axis = .vertical
public var spacing: CGFloat = 16.0
public var useStackSpacingBeforeFirstItem = false
public init(molecules: [MoleculeStackItemModel]) {
self.molecules = molecules
super.init()
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case molecules
case axis
case spacing
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
molecules = try typeContainer.decode([MoleculeStackItemModel].self, forKey: .molecules)
if let axisString = try typeContainer.decodeIfPresent(String.self, forKey: .axis), let optionalAxis = NSLayoutConstraint.Axis(rawValue: axisString) {
axis = optionalAxis
}
if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) {
self.spacing = spacing
}
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(molecules, forKey: .molecules)
try container.encodeIfPresent(axis.rawValueString, forKey: .axis)
try container.encodeIfPresent(spacing, forKey: .spacing)
}
}

View File

@ -5,13 +5,12 @@
// Created by Scott Pfeil on 2/11/19. // Created by Scott Pfeil on 2/11/19.
// Copyright © 2019 Verizon Wireless. All rights reserved. // Copyright © 2019 Verizon Wireless. All rights reserved.
// //
// This is a dynamic stack view that creates molecules if needed on set.
import UIKit import UIKit
open class MoleculeStackView: Stack<MoleculeStackModel> { open class MoleculeStackView: Stack<StackModel> {
open override var stackModel: MoleculeStackModel? { var previousModel: MoleculeModelProtocol?
get { return model as? MoleculeStackModel }
}
/// Convenience function, adds a molecule to a MoleculeStackItem to the MoleculeStack /// Convenience function, adds a molecule to a MoleculeStackItem to the MoleculeStack
func setup(with views: [View], lastItem: Bool) { func setup(with views: [View], lastItem: Bool) {
@ -26,14 +25,16 @@ open class MoleculeStackView: Stack<MoleculeStackModel> {
if let stackModel = stackModel { if let stackModel = stackModel {
stackModel.molecules = models stackModel.molecules = models
} else { } else {
model = MoleculeStackModel(molecules: models) model = StackModel(molecules: models)
} }
restack() restack()
} }
// MARK: - Adding to stack // MARK: - Adding to stack
/// Creates all of the stackItems for the stackItemModels /// Can be subclassed to create views when we get stack item models and have no views yet
override open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
guard let stackItemModels = stackModel?.molecules else { return } guard let stackItemModels = stackModel?.molecules else { return }
for model in stackItemModels { for model in stackItemModels {
if let stackItem = MoleculeObjectMapping.shared()?.createMolecule(model, delegateObject: delegateObject, additionalData: additionalData) as? MoleculeStackItem { if let stackItem = MoleculeObjectMapping.shared()?.createMolecule(model, delegateObject: delegateObject, additionalData: additionalData) as? MoleculeStackItem {
@ -41,4 +42,20 @@ open class MoleculeStackView: Stack<MoleculeStackModel> {
} }
} }
} }
open override func setStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
// If the items in the stack are different, clear them, create new ones.
if (previousModel == nil) || Self.nameForReuse(with: previousModel!, delegateObject) != Self.nameForReuse(with: model, delegateObject) {
removeAllItemViews()
stackItems = []
createStackItemsFromModel(model, delegateObject, additionalData)
} else {
super.setStackItemsFromModel(model, delegateObject, additionalData)
}
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
previousModel = self.model
super.set(with: model, delegateObject, additionalData)
}
} }

View File

@ -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 // MARK: - Initializers
//-------------------------------------------------- //--------------------------------------------------
@ -147,18 +173,8 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
} }
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
let previousModel = self.model
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
removeAllItemViews() setStackItemsFromModel(model, delegateObject, additionalData)
// If the items in the stack are different, clear them, create new ones.
if (previousModel == nil) || Self.nameForReuse(with: previousModel!, delegateObject) != Self.nameForReuse(with: model, delegateObject) {
stackItems = []
createStackItemsFromModel(model, delegateObject, additionalData)
} else {
setStackItemsFromModel(model, delegateObject, additionalData)
}
restack() restack()
} }
@ -216,9 +232,6 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
// MARK: - Subclassables // MARK: - Subclassables
//-------------------------------------------------- //--------------------------------------------------
/// Can be subclassed to create views when we get stack item models and have no views yet
open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { }
/// Can be subclassed to set stack items with model when we already have views /// Can be subclassed to set stack items with model when we already have views
open func setStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { open func setStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let models = stackModel?.molecules else { return } guard let models = stackModel?.molecules else { return }
@ -243,10 +256,10 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
} }
/// Sets the stack with StackItems containing the passed in views and sets the StackModel with models. /// Sets the stack with StackItems containing the passed in views and sets the StackModel with models.
open func set(with viewModels:[(view: UIView, model: T.AnyStackItemModel)]) { open func set(with viewModels:[(view: UIView, model: StackItemModel)]) {
guard var stackModel = self.stackModel else { return } guard var stackModel = self.stackModel else { return }
var stackItems: [StackItem] = [] var stackItems: [StackItem] = []
var models: [T.AnyStackItemModel] = [] var models: [StackItemModel] = []
for item in viewModels { for item in viewModels {
stackItems.append(StackItem(andContain: item.view)) stackItems.append(StackItem(andContain: item.view))
models.append(item.model) models.append(item.model)
@ -307,7 +320,7 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
if let percent = model.percent { if let percent = model.percent {
let multiplier = CGFloat(percent) / 100.0 let multiplier = CGFloat(percent) / 100.0
let constant = multiplier * totalSpacing let constant = multiplier * totalSpacing
view.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: multiplier, constant: -constant).isActive = true view.heightAnchor.constraint(equalTo: heightAnchor, multiplier: multiplier, constant: -constant).isActive = true
} }
if lastItem { if lastItem {
pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .bottom, relation: .equal, priority: .required, constant: 0)
@ -326,7 +339,7 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
if let percent = model.percent { if let percent = model.percent {
let multiplier = CGFloat(percent) / 100.0 let multiplier = CGFloat(percent) / 100.0
let constant = multiplier * totalSpacing let constant = multiplier * totalSpacing
view.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: multiplier, constant: -constant).isActive = true view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: multiplier, constant: -constant).isActive = true
} }
if lastItem { if lastItem {
pinView(contentView, toView: view, attribute: .right, relation: .equal, priority: .required, constant: 0) pinView(contentView, toView: view, attribute: .right, relation: .equal, priority: .required, constant: 0)

View File

@ -8,17 +8,19 @@
import Foundation import Foundation
@objcMembers public class StackModel: StackModelProtocol, MoleculeModelProtocol { @objcMembers public class StackModel: ContainerModel, StackModelProtocol, MoleculeModelProtocol {
static let defaultSpacing: CGFloat = 16.0 static let defaultSpacing: CGFloat = 16.0
public static var identifier: String = "simpleStack" public class var identifier: String {
return "stack"
}
public var backgroundColor: Color? public var backgroundColor: Color?
public var molecules: [StackItemModel] public var molecules: [StackItemModelProtocol & MoleculeModelProtocol]
public var axis: NSLayoutConstraint.Axis = .vertical public var axis: NSLayoutConstraint.Axis = .vertical
public var spacing: CGFloat = StackModel.defaultSpacing public var spacing: CGFloat = StackModel.defaultSpacing
public var useStackSpacingBeforeFirstItem = false public var useStackSpacingBeforeFirstItem = false
public init(molecules: [StackItemModel], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) { public init(molecules: [StackItemModelProtocol & MoleculeModelProtocol], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) {
self.molecules = molecules self.molecules = molecules
if let axis = axis { if let axis = axis {
self.axis = axis self.axis = axis
@ -26,6 +28,7 @@ import Foundation
if let spacing = spacing { if let spacing = spacing {
self.spacing = spacing self.spacing = spacing
} }
super.init()
} }
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
@ -38,21 +41,24 @@ import Foundation
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
molecules = try typeContainer.decodeModels(codingKey: .molecules)
molecules = try typeContainer.decode([StackItemModel].self, forKey: .molecules)
if let axisString = try typeContainer.decodeIfPresent(String.self, forKey: .axis), let optionalAxis = NSLayoutConstraint.Axis(rawValue: axisString) { if let axisString = try typeContainer.decodeIfPresent(String.self, forKey: .axis), let optionalAxis = NSLayoutConstraint.Axis(rawValue: axisString) {
axis = optionalAxis axis = optionalAxis
} }
if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) { if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) {
self.spacing = spacing self.spacing = spacing
} }
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
try super.init(from: decoder)
} }
public func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(molecules, forKey: .molecules) try container.encodeModels(molecules, forKey: .molecules)
try container.encodeIfPresent(axis.rawValueString, forKey: .axis) try container.encodeIfPresent(axis.rawValueString, forKey: .axis)
try container.encodeIfPresent(spacing, forKey: .spacing) try container.encodeIfPresent(spacing, forKey: .spacing)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
} }
} }

View File

@ -9,9 +9,7 @@
import Foundation import Foundation
public protocol StackModelProtocol { public protocol StackModelProtocol {
associatedtype AnyStackItemModel: StackItemModelProtocol var molecules: [StackItemModelProtocol & MoleculeModelProtocol] { get set }
var molecules: [AnyStackItemModel] { get set }
var axis: NSLayoutConstraint.Axis { get set } var axis: NSLayoutConstraint.Axis { get set }
var spacing: CGFloat { get set } var spacing: CGFloat { get set }
var useStackSpacingBeforeFirstItem: Bool { get set } var useStackSpacingBeforeFirstItem: Bool { get set }

View File

@ -11,10 +11,12 @@ import Foundation
public protocol ContainerModelProtocol { public protocol ContainerModelProtocol {
var horizontalAlignment: UIStackView.Alignment? { get set } var horizontalAlignment: UIStackView.Alignment? { get set }
var verticalAlignment: UIStackView.Alignment? { get set }
var useHorizontalMargins: Bool? { get set } var useHorizontalMargins: Bool? { get set }
var leftPadding: CGFloat? { get set }
var rightPadding: CGFloat? { get set }
var verticalAlignment: UIStackView.Alignment? { get set }
var useVerticalMargins: Bool? { get set } var useVerticalMargins: Bool? { get set }
var topMarginPadding: CGFloat? { get set } var topPadding: CGFloat? { get set }
var bottomMarginPadding: CGFloat? { get set } var bottomPadding: CGFloat? { get set }
} }

View File

@ -12,5 +12,6 @@ public protocol PageModelProtocol {
var pageType: String { get set } var pageType: String { get set }
/// Temporary: for legacy response /// Temporary: for legacy response
var screenHeading: String? { get set } var screenHeading: String? { get set }
var backgroundColor: Color? { get set }
var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)? { get set } var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)? { get set }
} }

View File

@ -0,0 +1,17 @@
//
// ThreeLayerTemplateModelProtocol.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 4/21/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol ThreeLayerTemplateModelProtocol: TemplateModelProtocol {
var anchorHeader: Bool { get set }
var header: MoleculeModelProtocol? { get set }
var anchorFooter: Bool { get set }
var footer: MoleculeModelProtocol? { get set }
}

View File

@ -22,5 +22,8 @@ public extension TemplateProtocol where Self: ViewController {
let templateModel = try decoder.decode(TemplateModel.self, from: data) let templateModel = try decoder.decode(TemplateModel.self, from: data)
self.templateModel = templateModel self.templateModel = templateModel
self.pageModel = templateModel as? MVMControllerModelProtocol self.pageModel = templateModel as? MVMControllerModelProtocol
if let backgroundColor = templateModel.backgroundColor {
view.backgroundColor = backgroundColor.uiColor
}
} }
} }

View File

@ -79,6 +79,8 @@ import Foundation
open override func handleNewData() { open override func handleNewData() {
topViewOutsideOfScrollArea = templateModel?.anchorHeader ?? false
bottomViewOutsideOfScrollArea = templateModel?.anchorFooter ?? false
setup() setup()
registerCells() registerCells()
super.handleNewData() super.handleNewData()

View File

@ -8,7 +8,7 @@
import Foundation import Foundation
@objcMembers public class CollectionTemplateModel: TemplateModel { @objcMembers public class CollectionTemplateModel: ThreeLayerModelBase {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -16,9 +16,7 @@ import Foundation
public override class var identifier: String { public override class var identifier: String {
return "collection" return "collection"
} }
public var header: MoleculeModelProtocol?
public var molecules: [CollectionItemModelProtocol & MoleculeModelProtocol]? public var molecules: [CollectionItemModelProtocol & MoleculeModelProtocol]?
public var footer: MoleculeModelProtocol?
public var columns: Int? public var columns: Int?
//-------------------------------------------------- //--------------------------------------------------
@ -37,8 +35,6 @@ import Foundation
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case molecules case molecules
case header
case footer
case columns case columns
} }
@ -49,8 +45,6 @@ import Foundation
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
molecules = try typeContainer.decodeModelsIfPresent(codingKey: .molecules) molecules = try typeContainer.decodeModelsIfPresent(codingKey: .molecules)
header = try typeContainer.decodeModelIfPresent(codingKey: .header)
footer = try typeContainer.decodeModelIfPresent(codingKey: .footer)
columns = try typeContainer.decodeIfPresent(Int.self, forKey: .columns) columns = try typeContainer.decodeIfPresent(Int.self, forKey: .columns)
try super.init(from: decoder) try super.init(from: decoder)
} }
@ -59,8 +53,6 @@ import Foundation
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.encodeModelsIfPresent(molecules, forKey: .molecules) try container.encodeModelsIfPresent(molecules, forKey: .molecules)
try container.encodeModelIfPresent(header, forKey: .header)
try container.encodeModelIfPresent(footer, forKey: .footer)
try container.encodeIfPresent(columns, forKey: .columns) try container.encodeIfPresent(columns, forKey: .columns)
} }
} }

View File

@ -8,7 +8,7 @@
import Foundation import Foundation
@objcMembers public class ListPageTemplateModel: TemplateModel { @objcMembers public class ListPageTemplateModel: ThreeLayerModelBase {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -16,9 +16,7 @@ import Foundation
public override class var identifier: String { public override class var identifier: String {
return "list" return "list"
} }
public var header: MoleculeModelProtocol?
public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]? public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]?
public var footer: MoleculeModelProtocol?
public var line: LineModel? public var line: LineModel?
//-------------------------------------------------- //--------------------------------------------------
@ -37,8 +35,6 @@ import Foundation
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case molecules case molecules
case header
case footer
case line case line
} }
@ -49,8 +45,6 @@ import Foundation
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
molecules = try typeContainer.decodeModelsIfPresent(codingKey: .molecules) molecules = try typeContainer.decodeModelsIfPresent(codingKey: .molecules)
header = try typeContainer.decodeModelIfPresent(codingKey: .header)
footer = try typeContainer.decodeModelIfPresent(codingKey: .footer)
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
try super.init(from: decoder) try super.init(from: decoder)
} }
@ -59,8 +53,6 @@ import Foundation
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.encodeModelsIfPresent(molecules, forKey: .molecules) try container.encodeModelsIfPresent(molecules, forKey: .molecules)
try container.encodeModelIfPresent(header, forKey: .header)
try container.encodeModelIfPresent(footer, forKey: .footer)
try container.encode(line, forKey: .line) try container.encode(line, forKey: .line)
} }
} }

View File

@ -81,6 +81,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
} }
open override func handleNewData() { open override func handleNewData() {
topViewOutsideOfScrollArea = templateModel?.anchorHeader ?? false
bottomViewOutsideOfScrollArea = templateModel?.anchorFooter ?? false
setup() setup()
registerWithTable() registerWithTable()
super.handleNewData() super.handleNewData()

View File

@ -11,6 +11,12 @@ import UIKit
open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol {
var observer: NSKeyValueObservation? var observer: NSKeyValueObservation?
public var templateModel: StackPageTemplateModel? public var templateModel: StackPageTemplateModel?
open override func handleNewData() {
topViewOutsideOfScroll = templateModel?.anchorHeader ?? false
bottomViewOutsideOfScroll = templateModel?.anchorFooter ?? false
super.handleNewData()
}
open override func parsePageJSON() throws { open override func parsePageJSON() throws {
try parseTemplate(json: loadObject?.pageJSON) try parseTemplate(json: loadObject?.pageJSON)

View File

@ -9,31 +9,24 @@
import Foundation import Foundation
@objcMembers public class StackPageTemplateModel: TemplateModel { @objcMembers public class StackPageTemplateModel: ThreeLayerModelBase {
public override class var identifier: String { public override class var identifier: String {
return "stack" return "stack"
} }
public var moleculeStack: StackModel
public var header: MoleculeModelProtocol?
public var moleculeStack: MoleculeStackModel
public var footer: MoleculeModelProtocol?
public init(pageType: String, moleculeStack: MoleculeStackModel) { public init(pageType: String, moleculeStack: StackModel) {
self.moleculeStack = moleculeStack self.moleculeStack = moleculeStack
super.init(pageType: pageType) super.init(pageType: pageType)
} }
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case header
case footer
case stack case stack
} }
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
moleculeStack = try typeContainer.decode(MoleculeStackModel.self, forKey: .stack) moleculeStack = try typeContainer.decode(StackModel.self, forKey: .stack)
header = try typeContainer.decodeModelIfPresent(codingKey: .header)
footer = try typeContainer.decodeModelIfPresent(codingKey: .footer)
try super.init(from: decoder) try super.init(from: decoder)
} }
@ -41,7 +34,5 @@ import Foundation
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.encode(moleculeStack, forKey: .stack) try container.encode(moleculeStack, forKey: .stack)
try container.encodeModelIfPresent(header, forKey: .header)
try container.encodeModelIfPresent(footer, forKey: .footer)
} }
} }

View File

@ -17,6 +17,7 @@ import Foundation
// Although this is done in the extension, it is needed for the encoding. // Although this is done in the extension, it is needed for the encoding.
return Self.identifier return Self.identifier
} }
public var backgroundColor: Color?
public var screenHeading: String? public var screenHeading: String?
public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)? public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)?
public var formRules: [FormGroupRule]? public var formRules: [FormGroupRule]?
@ -29,6 +30,7 @@ import Foundation
case pageType case pageType
case template case template
case screenHeading case screenHeading
case backgroundColor
case formRules case formRules
case navigationItem case navigationItem
} }
@ -37,6 +39,7 @@ import Foundation
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
pageType = try typeContainer.decode(String.self, forKey: .pageType) pageType = try typeContainer.decode(String.self, forKey: .pageType)
screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading) screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
formRules = try typeContainer.decodeIfPresent([FormGroupRule].self, forKey: .formRules) formRules = try typeContainer.decodeIfPresent([FormGroupRule].self, forKey: .formRules)
navigationItem = try typeContainer.decodeModelIfPresent(codingKey: .navigationItem) navigationItem = try typeContainer.decodeModelIfPresent(codingKey: .navigationItem)
} }
@ -45,6 +48,7 @@ import Foundation
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(pageType, forKey: .pageType) try container.encode(pageType, forKey: .pageType)
try container.encode(template, forKey: .template) try container.encode(template, forKey: .template)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(screenHeading, forKey: .screenHeading) try container.encodeIfPresent(screenHeading, forKey: .screenHeading)
try container.encodeIfPresent(formRules, forKey: .formRules) try container.encodeIfPresent(formRules, forKey: .formRules)
try container.encodeModelIfPresent(navigationItem, forKey: .navigationItem) try container.encodeModelIfPresent(navigationItem, forKey: .navigationItem)

View File

@ -0,0 +1,15 @@
//
// ThreeLayerCenterTemplate.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 4/21/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers open class ThreeLayerCenterTemplate: ThreeLayerTemplate<ThreeLayerCenterPageTemplateModel> {
open override func spaceBetweenTopAndMiddle() -> CGFloat? {
return nil
}
}

View File

@ -0,0 +1,15 @@
//
// ThreeLayerCenterTemplateModel.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 4/21/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class ThreeLayerCenterPageTemplateModel: ThreeLayerPageTemplateModel {
public override class var identifier: String {
return "threeLayerCenter"
}
}

Some files were not shown because too many files have changed in this diff Show More