Merge branch 'develop' into feature/Headers_H2_Buttons
# Conflicts: # MVMCoreUI/Atomic/MoleculeObjectMapping.swift
This commit is contained in:
commit
91a5b3d36c
@ -61,7 +61,6 @@
|
||||
01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */; };
|
||||
01EB368F23609801006832FA /* LabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368823609801006832FA /* LabelModel.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 */; };
|
||||
01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368D23609801006832FA /* HeadlineBodyModel.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 */; };
|
||||
0A7ECC5D243CE85300C828E8 /* DoughnutChartItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */; };
|
||||
0A7ECC5F243CEB1200C828E8 /* ColorViewWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.swift */; };
|
||||
0A7ECC702441001C00C828E8 /* UIToolbar+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */; };
|
||||
0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */; };
|
||||
0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */; };
|
||||
0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */; };
|
||||
@ -103,6 +103,8 @@
|
||||
0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */; };
|
||||
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */; };
|
||||
0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B392398524F0067DD0F /* Toggle.swift */; };
|
||||
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */; };
|
||||
0AB764D324460FA400E7FE72 /* UIPickerView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */; };
|
||||
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; };
|
||||
0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; };
|
||||
0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; };
|
||||
@ -139,8 +141,12 @@
|
||||
8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; };
|
||||
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4687E1242E2DE400802879 /* ListFourColumnDataUsageListItemModel.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 */; };
|
||||
8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */; };
|
||||
8DDD6C1D244D90B8006A2232 /* ListThreeColumnDataUsage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DDD6C1C244D90B8006A2232 /* ListThreeColumnDataUsage.swift */; };
|
||||
8DDD6C1F244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DDD6C1E244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift */; };
|
||||
8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */; };
|
||||
8DEFA95E243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift */; };
|
||||
942C372E241149170066E45E /* NHaasGroteskDSStd-75Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = 942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */; };
|
||||
@ -148,8 +154,8 @@
|
||||
942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */; };
|
||||
942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */; };
|
||||
9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */; };
|
||||
943784F5236B77BB006A1E82 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* GraphView.swift */; };
|
||||
943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; };
|
||||
943784F5236B77BB006A1E82 /* Wheel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* Wheel.swift */; };
|
||||
943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */; };
|
||||
943820842432382400B43AF3 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943820832432382400B43AF3 /* WebView.swift */; };
|
||||
94382086243238D100B43AF3 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94382085243238D100B43AF3 /* WebViewModel.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 */; };
|
||||
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 */; };
|
||||
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, ); }; };
|
||||
94FB966323D797DA003D482B /* MFTextButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 94FB966123D797DA003D482B /* MFTextButton.m */; };
|
||||
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 */; };
|
||||
AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.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 */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C969124330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift */; };
|
||||
BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A585241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift */; };
|
||||
BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB47A587241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift */; };
|
||||
BB54C5202434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB54C51E2434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.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 */; };
|
||||
BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6C6ABF242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.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 */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.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 */; };
|
||||
D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.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 */; };
|
||||
D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A837E23CCA96400DFE4FC /* TabsModel.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 */; };
|
||||
D28A838923CCCFCB00DFE4FC /* LinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838823CCCFCB00DFE4FC /* LinkModel.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 */; };
|
||||
D29E28DA23D21AFA00ACEA85 /* StringAndMoleculeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29E28D923D21AFA00ACEA85 /* StringAndMoleculeModel.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 */; };
|
||||
D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -522,6 +549,7 @@
|
||||
0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxLabel.swift; sourceTree = "<group>"; };
|
||||
0A7ECC5C243CE85300C828E8 /* DoughnutChartItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoughnutChartItemModel.swift; sourceTree = "<group>"; };
|
||||
0A7ECC5E243CEB1200C828E8 /* ColorViewWithLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorViewWithLabel.swift; sourceTree = "<group>"; };
|
||||
0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIToolbar+Extension.swift"; sourceTree = "<group>"; };
|
||||
0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryFieldModel.swift; sourceTree = "<group>"; };
|
||||
0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEntryFieldModel.swift; sourceTree = "<group>"; };
|
||||
0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MdnEntryFieldModel.swift; sourceTree = "<group>"; };
|
||||
@ -532,6 +560,8 @@
|
||||
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>"; };
|
||||
0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = "<group>"; };
|
||||
0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIDatePicker+Extension.swift"; sourceTree = "<group>"; };
|
||||
0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIPickerView+Extension.swift"; sourceTree = "<group>"; };
|
||||
0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryField.swift; sourceTree = "<group>"; };
|
||||
0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryField.swift; sourceTree = "<group>"; };
|
||||
0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; };
|
||||
@ -568,8 +598,12 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnInternationalData.swift; sourceTree = "<group>"; };
|
||||
8DDD6C1C244D90B8006A2232 /* ListThreeColumnDataUsage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsage.swift; sourceTree = "<group>"; };
|
||||
8DDD6C1E244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageModel.swift; sourceTree = "<group>"; };
|
||||
8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDividerModel.swift; sourceTree = "<group>"; };
|
||||
8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDivider.swift; sourceTree = "<group>"; };
|
||||
9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = "<group>"; };
|
||||
@ -578,8 +612,8 @@
|
||||
942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalMoleculeListTemplate.swift; sourceTree = "<group>"; };
|
||||
942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalMoleculeStackTemplate.swift; sourceTree = "<group>"; };
|
||||
9432A79E23DB47BA00719041 /* EntryFieldContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntryFieldContainer.swift; sourceTree = "<group>"; };
|
||||
943784F3236B77BB006A1E82 /* GraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = "<group>"; };
|
||||
943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphViewAnimationHandler.swift; sourceTree = "<group>"; };
|
||||
943784F3236B77BB006A1E82 /* Wheel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Wheel.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>"; };
|
||||
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>"; };
|
||||
@ -610,6 +644,7 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -618,16 +653,30 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -652,9 +701,17 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -714,7 +771,7 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -837,7 +894,6 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -910,6 +966,7 @@
|
||||
D28A837823C7D5BC00DFE4FC /* PageModelProtocol.swift */,
|
||||
011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */,
|
||||
D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */,
|
||||
D2092354244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift */,
|
||||
);
|
||||
path = ModelProtocols;
|
||||
sourceTree = "<group>";
|
||||
@ -1051,6 +1108,8 @@
|
||||
children = (
|
||||
8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */,
|
||||
8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */,
|
||||
8DDD6C1E244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift */,
|
||||
8DDD6C1C244D90B8006A2232 /* ListThreeColumnDataUsage.swift */,
|
||||
);
|
||||
path = ThreeColumn;
|
||||
sourceTree = "<group>";
|
||||
@ -1099,6 +1158,10 @@
|
||||
AA11A41E23F15D3100D7962F /* ListRightVariablePayments.swift */,
|
||||
8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */,
|
||||
8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */,
|
||||
BB55B51E244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift */,
|
||||
BB55B51C244482C0002001AD /* ListRightVariablePriceChangeBodyText.swift */,
|
||||
8D8067D02444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift */,
|
||||
8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */,
|
||||
C7F8012223E846C300396FBD /* ListRVWheelModel.swift */,
|
||||
C7F8012023E8303200396FBD /* ListRVWheel.swift */,
|
||||
);
|
||||
@ -1122,6 +1185,9 @@
|
||||
D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */,
|
||||
D202AFE5242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift */,
|
||||
013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */,
|
||||
0A7ECC6F2441001C00C828E8 /* UIToolbar+Extension.swift */,
|
||||
0AB764D024460F6300E7FE72 /* UIDatePicker+Extension.swift */,
|
||||
0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
@ -1135,6 +1201,19 @@
|
||||
path = FourColumn;
|
||||
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 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1263,6 +1342,7 @@
|
||||
D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */,
|
||||
D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */,
|
||||
D28A837E23CCA96400DFE4FC /* TabsModel.swift */,
|
||||
94F6516C2437954100631BF9 /* Tabs.swift */,
|
||||
011D9625240EBB16000E3791 /* RadioButtonLabelModel.swift */,
|
||||
017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */,
|
||||
);
|
||||
@ -1287,8 +1367,7 @@
|
||||
D260105A23D0BB7100764D80 /* StackModelProtocol.swift */,
|
||||
D260106423D0CEA700764D80 /* StackModel.swift */,
|
||||
D260105C23D0BCD400764D80 /* Stack.swift */,
|
||||
01EB368B23609801006832FA /* MoleculeStackModel.swift */,
|
||||
D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */,
|
||||
D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */,
|
||||
012A88AE238C626E00FE3DA1 /* CarouselModel.swift */,
|
||||
D2A6390022CBB1820052ED1F /* Carousel.swift */,
|
||||
);
|
||||
@ -1334,6 +1413,7 @@
|
||||
D22B38EA23F4E08B00490EF6 /* List */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D20FFFB42451E32100A31DA2 /* Device */,
|
||||
52267A0523FFE0A900906CBA /* OneColumn */,
|
||||
D22D8396241FDE4700D3DF69 /* TwoColumn */,
|
||||
8DD1E36C243B3CD900D8F2DF /* ThreeColumn */,
|
||||
@ -1349,6 +1429,8 @@
|
||||
children = (
|
||||
52B201D124081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift */,
|
||||
52B201D024081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift */,
|
||||
AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */,
|
||||
AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */,
|
||||
522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */,
|
||||
522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */,
|
||||
8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */,
|
||||
@ -1435,6 +1517,11 @@
|
||||
01004F2F22721C3800991ECC /* RadioButton.swift */,
|
||||
31BE15CA23D8924C00452370 /* CheckboxModel.swift */,
|
||||
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */,
|
||||
AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */,
|
||||
AAB9C10724346F4B00151545 /* RadioSwatches.swift */,
|
||||
D2092348244A51D40044AD09 /* RadioSwatchModel.swift */,
|
||||
AAB9C109243496DD00151545 /* RadioSwatch.swift */,
|
||||
AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */,
|
||||
);
|
||||
path = Selectors;
|
||||
sourceTree = "<group>";
|
||||
@ -1484,6 +1571,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D22D8392241C27B100D3DF69 /* TemplateModel.swift */,
|
||||
D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */,
|
||||
014AA72823C5059B006F3E93 /* StackPageTemplateModel.swift */,
|
||||
D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */,
|
||||
942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */,
|
||||
@ -1495,6 +1583,8 @@
|
||||
942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */,
|
||||
014AA72A23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift */,
|
||||
D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */,
|
||||
D2092350244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift */,
|
||||
D209234E244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift */,
|
||||
D264FAA4243F66A500D98315 /* CollectionTemplateItemProtocol.swift */,
|
||||
D264FA8B243BCD8E00D98315 /* CollectionTemplateModel.swift */,
|
||||
D264FA8D243BCD9A00D98315 /* CollectionTemplate.swift */,
|
||||
@ -1682,9 +1772,9 @@
|
||||
94C2D9822386F3E30006CF46 /* Label */,
|
||||
31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */,
|
||||
0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */,
|
||||
D28A838223CCBD3F00DFE4FC /* CircleProgressModel.swift */,
|
||||
943784F3236B77BB006A1E82 /* GraphView.swift */,
|
||||
943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */,
|
||||
D28A838223CCBD3F00DFE4FC /* WheelModel.swift */,
|
||||
943784F3236B77BB006A1E82 /* Wheel.swift */,
|
||||
943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */,
|
||||
D260105223CEA61600764D80 /* ToggleModel.swift */,
|
||||
0AA33B392398524F0067DD0F /* Toggle.swift */,
|
||||
0AE98BB623FF18E9004C5109 /* ArrowModel.swift */,
|
||||
@ -1747,6 +1837,7 @@
|
||||
D29DF27421E79E81003B2FB9 /* MVMCoreUILoggingHandler.m */,
|
||||
D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */,
|
||||
D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */,
|
||||
D2092352244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift */,
|
||||
D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */,
|
||||
);
|
||||
path = OtherHandlers;
|
||||
@ -1852,6 +1943,7 @@
|
||||
D2B18B7E2360913400A9AEDC /* Control.swift */,
|
||||
D2B18B802360945C00A9AEDC /* View.swift */,
|
||||
0AE14F63238315D2005417F8 /* TextField.swift */,
|
||||
D20923582450ECE00044AD09 /* TableView.swift */,
|
||||
D2755D7A23689C7500485468 /* TableViewCell.swift */,
|
||||
D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */,
|
||||
D264FAA92440F97600D98315 /* CollectionView.swift */,
|
||||
@ -2046,10 +2138,11 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
AAC6F167243332E400F295C1 /* RadioSwatchesModel.swift in Sources */,
|
||||
5248BFED23F12E350059236A /* ListThreeColumnPlanDataDividerModel.swift in Sources */,
|
||||
0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */,
|
||||
8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */,
|
||||
943784F5236B77BB006A1E82 /* GraphView.swift in Sources */,
|
||||
943784F5236B77BB006A1E82 /* Wheel.swift in Sources */,
|
||||
31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */,
|
||||
8D3BA9BF2433789900D341BA /* ListThreeColumnInternationalDataDivider.swift in Sources */,
|
||||
94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */,
|
||||
@ -2062,6 +2155,7 @@
|
||||
D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */,
|
||||
D28A838923CCCFCB00DFE4FC /* LinkModel.swift in Sources */,
|
||||
AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */,
|
||||
AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */,
|
||||
94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */,
|
||||
DBC4391922442197001AB423 /* DashLine.swift in Sources */,
|
||||
D264FAAA2440F97600D98315 /* CollectionView.swift in Sources */,
|
||||
@ -2070,12 +2164,15 @@
|
||||
AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */,
|
||||
D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */,
|
||||
0116A4E5228B19640094F3ED /* RadioButtonSelectionHelper.swift in Sources */,
|
||||
D2092353244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift in Sources */,
|
||||
017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */,
|
||||
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */,
|
||||
94382086243238D100B43AF3 /* WebViewModel.swift in Sources */,
|
||||
D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */,
|
||||
D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */,
|
||||
D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */,
|
||||
0A6682A42434DB8D00AD3CA1 /* ListLeftVariableRadioButtonBodyTextModel.swift in Sources */,
|
||||
AA2AD116244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift in Sources */,
|
||||
D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */,
|
||||
D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */,
|
||||
01004F3022721C3800991ECC /* RadioButton.swift in Sources */,
|
||||
@ -2091,6 +2188,7 @@
|
||||
942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */,
|
||||
BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */,
|
||||
012A88C8238DB02000FE3DA1 /* MoleculeDelegateProtocol.swift in Sources */,
|
||||
8D8067D12444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift in Sources */,
|
||||
0A7EF86123D8AC2500B2AAD1 /* DigitEntryFieldModel.swift in Sources */,
|
||||
DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */,
|
||||
D224798C231450C8003FCCF9 /* HeadlineBodyToggle.swift in Sources */,
|
||||
@ -2105,10 +2203,13 @@
|
||||
D2E2A98323D8B32D000B42E6 /* EyebrowHeadlineBodyLinkModel.swift in Sources */,
|
||||
012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */,
|
||||
BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */,
|
||||
D2092351244F7BE80044AD09 /* ThreeLayerCenterTemplateModel.swift in Sources */,
|
||||
D21B7F77243BB70700051ABF /* MoleculeCollectionItemModel.swift in Sources */,
|
||||
AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */,
|
||||
D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */,
|
||||
011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */,
|
||||
D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */,
|
||||
AA617AB22453012400910B8F /* ListDeviceComplexLinkSmallModel.swift in Sources */,
|
||||
D260106323D0C05000764D80 /* StackItemModel.swift in Sources */,
|
||||
D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */,
|
||||
BBBBC87D24374A4900B0F079 /* ListThreeColumnBillChangesDividerModel.swift in Sources */,
|
||||
@ -2120,6 +2221,7 @@
|
||||
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */,
|
||||
D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */,
|
||||
AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */,
|
||||
BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */,
|
||||
D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */,
|
||||
D28A837B23C928DA00DFE4FC /* MoleculeListCellProtocol.swift in Sources */,
|
||||
014AA72F23C5059B006F3E93 /* ThreeLayerPageTemplateModel.swift in Sources */,
|
||||
@ -2128,7 +2230,6 @@
|
||||
D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */,
|
||||
D28A838B23CCDA6B00DFE4FC /* ButtonModel.swift in Sources */,
|
||||
D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */,
|
||||
D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */,
|
||||
C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */,
|
||||
D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */,
|
||||
C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */,
|
||||
@ -2155,8 +2256,8 @@
|
||||
0A21DB85235E06EF00C160A2 /* MFTextField.m in Sources */,
|
||||
014AA72623C501E2006F3E93 /* ContainerModelProtocol.swift in Sources */,
|
||||
AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */,
|
||||
01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */,
|
||||
011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */,
|
||||
8DDD6C1D244D90B8006A2232 /* ListThreeColumnDataUsage.swift in Sources */,
|
||||
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */,
|
||||
D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */,
|
||||
944589232385DA9600DE9FD4 /* ImageViewModel.swift in Sources */,
|
||||
@ -2165,10 +2266,12 @@
|
||||
525019DE2406430800EED91C /* ListProgressBarData.swift in Sources */,
|
||||
D28A837F23CCA96400DFE4FC /* TabsModel.swift in Sources */,
|
||||
012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */,
|
||||
8DDD6C1F244D90E1006A2232 /* ListThreeColumnDataUsageModel.swift in Sources */,
|
||||
BB55B51F244482D2002001AD /* ListRightVariablePriceChangeBodyTextModel.swift in Sources */,
|
||||
D2A514672213885800345BFB /* MoleculeHeaderView.swift in Sources */,
|
||||
D29E28D823D21AB800ACEA85 /* StringAndMoleculeView.swift in Sources */,
|
||||
01EB369023609801006832FA /* MoleculeListItemModel.swift in Sources */,
|
||||
D28A838323CCBD3F00DFE4FC /* CircleProgressModel.swift in Sources */,
|
||||
D28A838323CCBD3F00DFE4FC /* WheelModel.swift in Sources */,
|
||||
EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */,
|
||||
D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */,
|
||||
DBEFFA04225A829700230692 /* Label.swift in Sources */,
|
||||
@ -2182,19 +2285,25 @@
|
||||
01509D952327ED1900EF99AA /* HeadlineBodyLinkToggle.swift in Sources */,
|
||||
31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */,
|
||||
D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */,
|
||||
94F6516D2437954100631BF9 /* Tabs.swift in Sources */,
|
||||
5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */,
|
||||
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */,
|
||||
D264FA8E243BCD9A00D98315 /* CollectionTemplate.swift in Sources */,
|
||||
0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */,
|
||||
8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */,
|
||||
94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */,
|
||||
D2092357244FA1EF0044AD09 /* ThreeLayerModelBase.swift in Sources */,
|
||||
0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */,
|
||||
0A21DB8B235E06EF00C160A2 /* MFDigitTextBox.m in Sources */,
|
||||
D20923592450ECE00044AD09 /* TableView.swift in Sources */,
|
||||
D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */,
|
||||
BB47A586241615EF002BB23C /* ListOneColumnFullWidthTextDividerSubsectionModel.swift in Sources */,
|
||||
AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */,
|
||||
D2B18B812360945C00A9AEDC /* View.swift in Sources */,
|
||||
C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */,
|
||||
0A7ECC702441001C00C828E8 /* UIToolbar+Extension.swift in Sources */,
|
||||
D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */,
|
||||
D209234F244F77FD0044AD09 /* ThreeLayerCenterTemplate.swift in Sources */,
|
||||
525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */,
|
||||
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */,
|
||||
94FB966323D797DA003D482B /* MFTextButton.m in Sources */,
|
||||
@ -2210,12 +2319,14 @@
|
||||
D260105D23D0BCD400764D80 /* Stack.swift in Sources */,
|
||||
0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */,
|
||||
BB54C5212434D92F0038326C /* ListRightVariableButtonAllTextAndLinksModel.swift in Sources */,
|
||||
D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */,
|
||||
8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */,
|
||||
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */,
|
||||
01EB368F23609801006832FA /* LabelModel.swift in Sources */,
|
||||
0A6682AC243531C300AD3CA1 /* Padding.swift in Sources */,
|
||||
AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */,
|
||||
942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */,
|
||||
8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */,
|
||||
8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */,
|
||||
01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */,
|
||||
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */,
|
||||
@ -2223,6 +2334,7 @@
|
||||
D22479962316AF6E003FCCF9 /* HeadlineBodyLink.swift in Sources */,
|
||||
D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */,
|
||||
0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */,
|
||||
BB55B51D244482C1002001AD /* ListRightVariablePriceChangeBodyText.swift in Sources */,
|
||||
017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */,
|
||||
D29DF18121E69E50003B2FB9 /* MFView.m in Sources */,
|
||||
D28A837923C7D5BC00DFE4FC /* PageModelProtocol.swift in Sources */,
|
||||
@ -2246,6 +2358,7 @@
|
||||
C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */,
|
||||
011D958524042432000E3791 /* RulesProtocol.swift in Sources */,
|
||||
94AF4A3F23E9D13900676048 /* MFCaretButton.m in Sources */,
|
||||
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */,
|
||||
D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */,
|
||||
D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */,
|
||||
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */,
|
||||
@ -2281,6 +2394,7 @@
|
||||
525019E72406853600EED91C /* ListFourColumnDataUsageDivider.swift in Sources */,
|
||||
0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */,
|
||||
D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */,
|
||||
AA2AD118244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift in Sources */,
|
||||
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */,
|
||||
0A21DB89235E06EF00C160A2 /* MFMdnTextField.m in Sources */,
|
||||
D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */,
|
||||
@ -2293,9 +2407,12 @@
|
||||
94C0150A24215643005811A9 /* ActionTopAlertModel.swift in Sources */,
|
||||
012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */,
|
||||
D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */,
|
||||
D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */,
|
||||
0AE14F64238315D2005417F8 /* TextField.swift in Sources */,
|
||||
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */,
|
||||
D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */,
|
||||
D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */,
|
||||
AA617AB02453010A00910B8F /* ListDeviceComplexLinkSmall.swift in Sources */,
|
||||
C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */,
|
||||
01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */,
|
||||
D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */,
|
||||
@ -2324,11 +2441,12 @@
|
||||
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */,
|
||||
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */,
|
||||
D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */,
|
||||
AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */,
|
||||
52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */,
|
||||
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */,
|
||||
0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */,
|
||||
94AF4A4323E9D19E00676048 /* MFCaretView.m in Sources */,
|
||||
943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */,
|
||||
943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */,
|
||||
011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */,
|
||||
D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */,
|
||||
011D95892404249B000E3791 /* FormHolderModelProtocol.swift in Sources */,
|
||||
@ -2360,6 +2478,7 @@
|
||||
AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */,
|
||||
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
|
||||
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
|
||||
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */,
|
||||
D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */,
|
||||
0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */,
|
||||
0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */,
|
||||
@ -2376,6 +2495,7 @@
|
||||
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */,
|
||||
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */,
|
||||
012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */,
|
||||
0AB764D324460FA400E7FE72 /* UIPickerView+Extension.swift in Sources */,
|
||||
D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */,
|
||||
94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */,
|
||||
011D95AB2405C553000E3791 /* FormItemProtocol.swift in Sources */,
|
||||
|
||||
@ -9,9 +9,14 @@
|
||||
import UIKit
|
||||
|
||||
@objcMembers public class ActionCollapseNotificationModel: ActionModelProtocol {
|
||||
|
||||
public static var identifier: String = "collapseNotification"
|
||||
public var actionType: String
|
||||
public var actionType: String = ActionCollapseNotificationModel.identifier
|
||||
public var extraParameters: JSONValueDictionary?
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
public var title: String?
|
||||
|
||||
public init(_ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
|
||||
self.extraParameters = extraParameters
|
||||
self.analyticsData = analyticsData
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
public class ActionOpenPanelModel: ActionModelProtocol {
|
||||
|
||||
|
||||
public enum Panel: String, Codable {
|
||||
case left
|
||||
case right
|
||||
@ -22,10 +22,10 @@ public class ActionOpenPanelModel: ActionModelProtocol {
|
||||
public var panel: Panel
|
||||
public var extraParameters: 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.extraParameters = extraParameters
|
||||
self.analyticsData = analyticsData
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,15 +9,16 @@
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class ActionTopAlertModel: ActionModelProtocol {
|
||||
|
||||
public static var identifier: String = "topAlert"
|
||||
public var actionType: String = ActionTopAlertModel.identifier
|
||||
public var pageType: String
|
||||
public var extraParameters: 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.extraParameters = extraParameters
|
||||
self.analyticsData = analyticsData
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ open class ExternalLink: Link {
|
||||
|
||||
guard let model = model as? ExternalLinkModel else { return }
|
||||
|
||||
exportImageView?.tintColor = model.textColor.uiColor
|
||||
exportImageView?.tintColor = model.enabledColor.uiColor
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -52,7 +52,7 @@ import UIKit
|
||||
guard let model = model as? LinkModel else { return }
|
||||
|
||||
setTitle(model.title, for: .normal)
|
||||
setTitleColor(model.textColor.uiColor, for: .normal)
|
||||
setTitleColor(model.enabledColor.uiColor, for: .normal)
|
||||
setTitleColor(model.disabledColor.uiColor, for: .disabled)
|
||||
isEnabled = model.enabled
|
||||
set(with: model.action, delegateObject: delegateObject, additionalData: additionalData)
|
||||
|
||||
@ -21,7 +21,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol {
|
||||
public var title: String
|
||||
public var action: ActionModelProtocol
|
||||
public var enabled = true
|
||||
public var textColor = Color(uiColor: .mvmBlack)
|
||||
public var enabledColor = Color(uiColor: .mvmBlack)
|
||||
public var disabledColor = Color(uiColor: .mvmCoolGray6)
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -43,7 +43,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol {
|
||||
case title
|
||||
case action
|
||||
case enabled
|
||||
case textColor
|
||||
case enabledColor
|
||||
case disabledColor
|
||||
}
|
||||
|
||||
@ -60,8 +60,8 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol {
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor) {
|
||||
textColor = color
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledColor) {
|
||||
enabledColor = color
|
||||
}
|
||||
|
||||
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.encodeModel(action, forKey: .action)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(textColor, forKey: .textColor)
|
||||
try container.encode(enabledColor, forKey: .enabledColor)
|
||||
try container.encode(disabledColor, forKey: .disabledColor)
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,13 +19,14 @@ import UIKit
|
||||
widthConstraint?.constant = diameter
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override var isSelected: Bool {
|
||||
didSet {
|
||||
radioModel?.state = isSelected
|
||||
updateAccessibilityLabel()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var enabledColor: UIColor = .mvmBlack
|
||||
public var disabledColor: UIColor = .mvmCoolGray3
|
||||
public var delegateObject: MVMCoreUIDelegateObject?
|
||||
@ -39,12 +40,12 @@ import UIKit
|
||||
}()
|
||||
|
||||
lazy public var radioButtonSelectionHelper: RadioButtonSelectionHelper? = {
|
||||
if let radioGroupName = radioGroupName,
|
||||
let radioButtonModel = delegateObject?.formHolderDelegate?.formValidator?.radioButtonsModelByGroup[radioGroupName] {
|
||||
return radioButtonModel
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let radioGroupName = radioGroupName,
|
||||
let radioButtonModel = delegateObject?.formHolderDelegate?.formValidator?.radioButtonsModelByGroup[radioGroupName]
|
||||
else { return nil }
|
||||
|
||||
return radioButtonModel
|
||||
}()
|
||||
|
||||
public override var isEnabled: Bool {
|
||||
@ -90,6 +91,9 @@ import UIKit
|
||||
|
||||
/// The action performed when tapped.
|
||||
func tapAction() {
|
||||
if !isEnabled {
|
||||
return
|
||||
}
|
||||
if let radioButtonModel = radioButtonSelectionHelper {
|
||||
radioButtonModel.selected(self)
|
||||
} else {
|
||||
@ -115,6 +119,18 @@ import UIKit
|
||||
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
|
||||
//--------------------------------------------------
|
||||
@ -133,14 +149,15 @@ import UIKit
|
||||
isAccessibilityElement = true
|
||||
accessibilityTraits = .button
|
||||
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint")
|
||||
updateAccessibilityLabel()
|
||||
}
|
||||
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
self.delegateObject = delegateObject
|
||||
|
||||
guard let model = model as? RadioButtonModel else { return }
|
||||
|
||||
self.delegateObject = delegateObject
|
||||
isSelected = model.state
|
||||
isEnabled = model.enabled
|
||||
RadioButtonSelectionHelper.setupForRadioButtonGroup(model, self, delegateObject: delegateObject)
|
||||
|
||||
166
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift
Normal file
166
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift
Normal 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
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
64
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift
Normal file
64
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
152
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift
Normal file
152
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatches.swift
Normal 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()
|
||||
}
|
||||
}
|
||||
54
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift
Normal file
54
MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
@ -69,7 +69,7 @@ import UIKit
|
||||
textFieldTrailingConstraint = dropDownCaretView.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 6)
|
||||
textFieldTrailingConstraint?.isActive = true
|
||||
|
||||
container.trailingAnchor.constraint(equalTo: dropDownCaretView.trailingAnchor, constant: 16).isActive = true
|
||||
container.trailingAnchor.constraint(equalTo: dropDownCaretView.trailingAnchor, constant: Padding.Four).isActive = true
|
||||
dropDownCaretView.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
|
||||
}
|
||||
|
||||
|
||||
@ -31,10 +31,9 @@ import UIKit
|
||||
return formatter
|
||||
}()
|
||||
|
||||
/// Update the property value to alter the format of how the date is presented.
|
||||
public var dateFormat: String = "MMM d, y" {
|
||||
didSet {
|
||||
dateFormatter.dateFormat = dateFormat
|
||||
}
|
||||
didSet { dateFormatter.dateFormat = dateFormat }
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -69,10 +68,10 @@ import UIKit
|
||||
public override func setupFieldContainerContent(_ container: UIView) {
|
||||
super.setupFieldContainerContent(container)
|
||||
|
||||
datePicker = MVMCoreUICommonViewsUtility.addDatePicker(to: textField)
|
||||
datePicker = UIDatePicker.addDatePicker(to: textField)
|
||||
datePicker?.addTarget(self, action: #selector(pickerValueChanged), for: .valueChanged)
|
||||
datePicker?.timeZone = NSTimeZone.system
|
||||
MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: self)
|
||||
UIToolbar.addDismissToolbar(to: textField, delegate: self, action: #selector(dismissFieldInput))
|
||||
}
|
||||
|
||||
@objc public func setDatePickerDuration(from startDate: Date?, to endDate: Date?, showStartDate: Bool = true) {
|
||||
@ -104,7 +103,7 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
@objc override func dismissFieldInput(_ sender: Any?) {
|
||||
@objc public override func dismissFieldInput(_ sender: Any?) {
|
||||
|
||||
setTextWith(date: datePicker?.date)
|
||||
super.dismissFieldInput(sender)
|
||||
|
||||
@ -22,24 +22,25 @@
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case dateFormat
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
try super.init(from: decoder)
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
dateFormat = try typeContainer.decodeIfPresent(String.self, forKey: .dateFormat) ?? "MMM d, y"
|
||||
|
||||
if let dateFormat = try typeContainer.decodeIfPresent(String.self, forKey: .dateFormat) {
|
||||
self.dateFormat = dateFormat
|
||||
}
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(dateFormat, forKey: .dateFormat)
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,7 +211,9 @@ import UIKit
|
||||
|
||||
let digitBox = DigitBox()
|
||||
digitBox.isAccessibilityElement = true
|
||||
digitBox.digitField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: self)
|
||||
let observingDelegate = delegateObject?.observingTextFieldDelegate ?? self
|
||||
digitBox.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
|
||||
action: #selector(observingDelegate.dismissFieldInput))
|
||||
digitBox.digitField.delegate = self
|
||||
digitBox.digitBoxDelegate = self
|
||||
return digitBox
|
||||
@ -246,15 +248,6 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
@objc public override func defaultValidationBlock() {
|
||||
|
||||
validationBlock = { enteredValue in
|
||||
guard let enteredValue = enteredValue else { return false }
|
||||
|
||||
return enteredValue.count > 0 && enteredValue.count == self.digitBoxes.count
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func selectPreviousDigitField(_ currentTextField: UITextField?, clear: Bool) {
|
||||
|
||||
var selectPreviousField = false
|
||||
@ -322,7 +315,7 @@ import UIKit
|
||||
return true
|
||||
}
|
||||
|
||||
@objc override func dismissFieldInput(_ sender: Any?) {
|
||||
@objc public override func dismissFieldInput(_ sender: Any?) {
|
||||
|
||||
digitBoxes.forEach {
|
||||
if $0.isSelected {
|
||||
@ -337,12 +330,18 @@ import UIKit
|
||||
guard let model = model as? DigitEntryFieldModel else { return }
|
||||
|
||||
numberOfDigits = model.digits
|
||||
setAsSecureTextEntry(model.secureEntry)
|
||||
|
||||
for digitBox in digitBoxes {
|
||||
digitBox.digitField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: delegateObject?.observingTextFieldDelegate ?? self)
|
||||
if let entryType = model.type {
|
||||
setAsSecureTextEntry(entryType == .secure || entryType == .password)
|
||||
}
|
||||
|
||||
let observingDelegate = delegateObject?.observingTextFieldDelegate ?? self
|
||||
|
||||
digitBoxes.forEach {
|
||||
$0.digitField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
|
||||
action: #selector(observingDelegate.dismissFieldInput))
|
||||
}
|
||||
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
|
||||
@ -17,34 +17,31 @@
|
||||
}
|
||||
|
||||
public var digits: Int = 4
|
||||
public var secureEntry: Bool = false
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case digits
|
||||
case secureEntry
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
try super.init(from: decoder)
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
digits = try typeContainer.decodeIfPresent(Int.self, forKey: .digits) ?? 4
|
||||
secureEntry = try typeContainer.decodeIfPresent(Bool.self, forKey: .secureEntry) ?? false
|
||||
|
||||
if let digits = try typeContainer.decodeIfPresent(Int.self, forKey: .digits) {
|
||||
self.digits = digits
|
||||
}
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(digits, forKey: .digits)
|
||||
try container.encode(secureEntry, forKey: .secureEntry)
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ import UIKit
|
||||
|
||||
public private(set) var titleLabel: Label = {
|
||||
let label = Label()
|
||||
label.font = MFStyler.fontRegularMicro()
|
||||
label.font = Styler.Font.RegularMicro.getFont()
|
||||
label.textColor = .mvmBlack
|
||||
label.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
return label
|
||||
@ -31,31 +31,23 @@ import UIKit
|
||||
/// Provides contextual information on the TextField.
|
||||
public private(set) var feedbackLabel: Label = {
|
||||
let label = Label()
|
||||
label.font = MFStyler.fontRegularMicro()
|
||||
label.font = Styler.Font.RegularMicro.getFont()
|
||||
label.textColor = .mvmBlack
|
||||
label.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
return label
|
||||
}()
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Delegate
|
||||
//--------------------------------------------------
|
||||
|
||||
weak var delegateObject: MVMCoreUIDelegateObject?
|
||||
var delegateObject: MVMCoreUIDelegateObject?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Stored Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public var isValid: Bool = false
|
||||
public var errorMessage: String?
|
||||
public var standardMessage: String? {
|
||||
didSet {
|
||||
if !showError {
|
||||
feedback = standardMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Computed Properties
|
||||
@ -75,7 +67,7 @@ import UIKit
|
||||
public var showError: Bool {
|
||||
get { return entryFieldContainer.showError }
|
||||
set (error) {
|
||||
self.feedback = error ? self.errorMessage : self.standardMessage
|
||||
self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.feedback
|
||||
self.entryFieldContainer.showError = error
|
||||
}
|
||||
}
|
||||
@ -121,6 +113,10 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
public var entryFieldModel: EntryFieldModel? {
|
||||
return model as? EntryFieldModel
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
//--------------------------------------------------
|
||||
@ -174,8 +170,6 @@ import UIKit
|
||||
@objc final public override func setupView() {
|
||||
super.setupView()
|
||||
|
||||
guard subviews.isEmpty else { return }
|
||||
|
||||
isAccessibilityElement = false
|
||||
setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
accessibilityElements = [titleLabel, feedbackLabel]
|
||||
@ -193,7 +187,7 @@ import UIKit
|
||||
entryFieldContainer.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
setupFieldContainerContent(entryFieldContainer)
|
||||
|
||||
titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4)
|
||||
titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: Padding.One)
|
||||
titleContainerDistance?.isActive = true
|
||||
entryFieldContainerLeading = entryFieldContainer.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
|
||||
entryFieldContainerLeading?.isActive = true
|
||||
@ -202,7 +196,7 @@ import UIKit
|
||||
|
||||
addSubview(feedbackLabel)
|
||||
|
||||
feedbackContainerDistance = feedbackLabel.topAnchor.constraint(equalTo: entryFieldContainer.bottomAnchor, constant: PaddingOne)
|
||||
feedbackContainerDistance = feedbackLabel.topAnchor.constraint(equalTo: entryFieldContainer.bottomAnchor, constant: Padding.Two)
|
||||
feedbackContainerDistance?.isActive = true
|
||||
feedbackLabelLeading = feedbackLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
|
||||
feedbackLabelLeading?.isActive = true
|
||||
@ -217,11 +211,11 @@ import UIKit
|
||||
entryFieldContainer.refreshUI()
|
||||
}
|
||||
|
||||
/// Method to override.
|
||||
/// Intended to add the interactive content (i.e. textField) to the entryFieldContainer.
|
||||
@objc open func setupFieldContainerContent(_ container: UIView) {
|
||||
// To be overridden by subclass.
|
||||
}
|
||||
/**
|
||||
Method to override.
|
||||
Intended to add the interactive content (i.e. textField) to the entryFieldContainer.
|
||||
*/
|
||||
@objc open func setupFieldContainerContent(_ container: UIView) { }
|
||||
|
||||
@objc open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
@ -240,10 +234,11 @@ import UIKit
|
||||
|
||||
backgroundColor = .clear
|
||||
isAccessibilityElement = false
|
||||
titleLabel.font = MFStyler.fontRegularMicro()
|
||||
titleLabel.font = Styler.Font.RegularMicro.getFont()
|
||||
titleLabel.textColor = .mvmBlack
|
||||
feedbackLabel.font = MFStyler.fontRegularMicro()
|
||||
feedbackLabel.font = Styler.Font.RegularMicro.getFont()
|
||||
feedbackLabel.textColor = .mvmBlack
|
||||
feedbackLabel.text = nil
|
||||
entryFieldContainer.reset()
|
||||
}
|
||||
|
||||
@ -257,13 +252,12 @@ import UIKit
|
||||
|
||||
title = model.title
|
||||
feedback = model.feedback
|
||||
errorMessage = model.errorMessage
|
||||
isEnabled = model.isEnabled
|
||||
isEnabled = model.enabled
|
||||
|
||||
if let isLocked = model.isLocked {
|
||||
if let isLocked = model.locked {
|
||||
self.isLocked = isLocked
|
||||
|
||||
} else if let isSelected = model.isSelected{
|
||||
} else if let isSelected = model.selected {
|
||||
self.isSelected = isSelected
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol {
|
||||
@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol, EnableableModelProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
@ -22,29 +22,22 @@ import Foundation
|
||||
public var backgroundColor: Color?
|
||||
public var title: String?
|
||||
public var feedback: String?
|
||||
public var errorMessage: String = ""
|
||||
public var isEnabled: Bool = true
|
||||
public var isLocked: Bool?
|
||||
public var isSelected: Bool?
|
||||
public var errorMessage: String?
|
||||
public var enabled: Bool = true
|
||||
public var locked: Bool?
|
||||
public var selected: Bool?
|
||||
public var text: String?
|
||||
|
||||
public var fieldKey: String?
|
||||
public var groupName: String = FormValidator.defaultGroupName
|
||||
public var baseValue: AnyHashable?
|
||||
|
||||
|
||||
public var isValid: Bool? {
|
||||
didSet {
|
||||
updateUI?()
|
||||
}
|
||||
didSet { updateUI?() }
|
||||
}
|
||||
|
||||
/// Temporary binding mechanism for the view to update on enable changes.
|
||||
public var updateUI: (() -> Void)?
|
||||
public var updateUI: (() -> ())?
|
||||
|
||||
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
|
||||
self.isValid = valid
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
@ -52,23 +45,29 @@ import Foundation
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case title = "label"
|
||||
case isEnabled
|
||||
case title
|
||||
case enabled
|
||||
case feedback
|
||||
case errorMessage = "errorMsg"
|
||||
case isLocked
|
||||
case isSelected
|
||||
case isValid
|
||||
case isRequired = "required"
|
||||
case errorMessage
|
||||
case locked
|
||||
case selected
|
||||
case text
|
||||
case fieldKey
|
||||
case groupName
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Validation Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
public func formFieldValue() -> AnyHashable? {
|
||||
return text
|
||||
}
|
||||
|
||||
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
|
||||
self.isValid = valid
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
@ -78,18 +77,20 @@ import Foundation
|
||||
baseValue = text
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
|
||||
feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback)
|
||||
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) ?? ""
|
||||
isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .isEnabled) ?? true
|
||||
isLocked = try typeContainer.decodeIfPresent(Bool.self, forKey: .isLocked)
|
||||
isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .isSelected)
|
||||
isValid = try typeContainer.decodeIfPresent(Bool.self, forKey: .isValid)
|
||||
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage)
|
||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
||||
locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked)
|
||||
selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected)
|
||||
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
|
||||
|
||||
baseValue = text
|
||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
@ -103,13 +104,12 @@ import Foundation
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(title, forKey: .title)
|
||||
try container.encodeIfPresent(feedback, forKey: .feedback)
|
||||
try container.encode(errorMessage, forKey: .errorMessage)
|
||||
try container.encode(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(locked, forKey: .locked)
|
||||
try container.encodeIfPresent(selected, forKey: .selected)
|
||||
try container.encodeIfPresent(errorMessage, forKey: .errorMessage)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
public typealias TextFieldAndPickerDelegate = (UITextFieldDelegate & UIPickerViewDelegate & UIPickerViewDataSource)
|
||||
|
||||
|
||||
open class ItemDropdownEntryField: BaseDropdownEntryField {
|
||||
//--------------------------------------------------
|
||||
@ -62,7 +64,7 @@ open class ItemDropdownEntryField: BaseDropdownEntryField {
|
||||
@objc open override func setupFieldContainerContent(_ container: UIView) {
|
||||
super.setupFieldContainerContent(container)
|
||||
|
||||
pickerView = MVMCoreUICommonViewsUtility.addPicker(to: textField, delegate: self)
|
||||
pickerView = UIPickerView.addPicker(to: textField, delegate: self, dismissAction: #selector(dismissFieldInput))
|
||||
textField.hideBlinkingCaret = true
|
||||
textField.autocorrectionType = .no
|
||||
uiTextFieldDelegate = self
|
||||
|
||||
@ -17,17 +17,21 @@
|
||||
|
||||
public var options: [String] = []
|
||||
public var selectedIndex: Int = 0
|
||||
|
||||
public override func formFieldValue() -> AnyHashable? {
|
||||
guard !options.isEmpty else { return nil }
|
||||
return options[selectedIndex]
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case options
|
||||
case selectedIndex
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
@ -35,14 +39,17 @@
|
||||
required public init(from decoder: Decoder) throws {
|
||||
try super.init(from: decoder)
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
options = try typeContainer.decode([String].self, forKey: .options)
|
||||
selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) ?? 0
|
||||
|
||||
if let selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) {
|
||||
self.selectedIndex = selectedIndex
|
||||
}
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(options, forKey: .options)
|
||||
try container.encode(options, forKey: .selectedIndex)
|
||||
}
|
||||
|
||||
@ -48,6 +48,18 @@ import MVMCore
|
||||
set { text = MVMCoreUIUtility.formatMdn(newValue) }
|
||||
}
|
||||
|
||||
/// Toggles selected or original (unselected) UI.
|
||||
public override var isSelected: Bool {
|
||||
get { return entryFieldContainer.isSelected }
|
||||
set (selected) {
|
||||
if selected && showError {
|
||||
showError = false
|
||||
}
|
||||
|
||||
super.isSelected = selected
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
@ -77,11 +89,14 @@ import MVMCore
|
||||
super.setupFieldContainerContent(container)
|
||||
|
||||
textField.keyboardType = .numberPad
|
||||
}
|
||||
|
||||
open override func setupTextFieldToolbar() {
|
||||
|
||||
let toolbar = MVMCoreUICommonViewsUtility.makeEmptyToolbar()
|
||||
let toolbar = UIToolbar.createEmptyToolbar()
|
||||
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
|
||||
let contacts = UIBarButtonItem(title: MVMCoreUIUtility.hardcodedString(withKey: "textfield_contacts_barbutton"), style: .plain, target: self, action: #selector(getContacts(_:)))
|
||||
let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput(_:)))
|
||||
let contacts = UIBarButtonItem(title: MVMCoreUIUtility.hardcodedString(withKey: "textfield_contacts_barbutton"), style: .plain, target: self, action: #selector(getContacts))
|
||||
let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput))
|
||||
toolbar.items = [contacts, space, dismissButton]
|
||||
textField.inputAccessoryView = toolbar
|
||||
}
|
||||
@ -107,18 +122,18 @@ import MVMCore
|
||||
isValid = true
|
||||
return true
|
||||
}
|
||||
|
||||
let isValid = hasValidMDN()
|
||||
|
||||
if isValid {
|
||||
|
||||
isValid = hasValidMDN()
|
||||
|
||||
if self.isValid {
|
||||
showError = false
|
||||
|
||||
|
||||
} else {
|
||||
errorMessage = errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message")
|
||||
entryFieldModel?.errorMessage = entryFieldModel?.errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message")
|
||||
showError = true
|
||||
UIAccessibility.post(notification: .layoutChanged, argument: textField)
|
||||
}
|
||||
|
||||
|
||||
return isValid
|
||||
}
|
||||
|
||||
@ -196,7 +211,7 @@ import MVMCore
|
||||
}
|
||||
|
||||
@objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
|
||||
|
||||
|
||||
return proprietorTextDelegate?.textFieldShouldBeginEditing?(textField) ?? true
|
||||
}
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ import UIKit
|
||||
/// Called when the entered text becomes invalid based on the validation block
|
||||
@objc optional func isInvalid(textfield: TextEntryField?)
|
||||
/// Dismisses the keyboard.
|
||||
@objc optional func dismissFieldInput(sender: Any?)
|
||||
@objc optional func dismissFieldInput(_ sender: Any?)
|
||||
}
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ import UIKit
|
||||
let textField = TextField()
|
||||
textField.isAccessibilityElement = true
|
||||
textField.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
textField.font = MFStyler.fontRegularBodyLarge()
|
||||
textField.font = Styler.Font.RegularBodyLarge.getFont()
|
||||
textField.textColor = .mvmBlack
|
||||
textField.smartQuotesType = .no
|
||||
textField.smartDashesType = .no
|
||||
@ -36,13 +36,19 @@ import UIKit
|
||||
return textField
|
||||
}()
|
||||
|
||||
public lazy var errorImage: UIImageView = {
|
||||
let image = MVMCoreUIUtility.imageNamed("alert_standard")
|
||||
let imageView = UIImageView(image: image)
|
||||
imageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
imageView.heightAnchor.constraint(equalToConstant: 20).isActive = true
|
||||
imageView.widthAnchor.constraint(equalToConstant: 20).isActive = true
|
||||
return imageView
|
||||
}()
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Stored Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
/// Set enabled and disabled colors to be utilized when setting this texfield's isEnabled property.
|
||||
public var textColor: (enabled: UIColor?, disabled: UIColor?) = (.mvmBlack, .mvmCoolGray3)
|
||||
|
||||
private var observingForChange: Bool = false
|
||||
|
||||
/// Validate on each entry in the textField. Default: true
|
||||
@ -54,7 +60,7 @@ import UIKit
|
||||
public var textEntryFieldModel: TextEntryFieldModel? {
|
||||
return model as? TextEntryFieldModel
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Computed Properties
|
||||
//--------------------------------------------------
|
||||
@ -68,7 +74,7 @@ import UIKit
|
||||
guard let self = self else { return }
|
||||
|
||||
self.textField.isEnabled = enabled
|
||||
self.textField.textColor = enabled ? self.textColor.enabled : self.textColor.disabled
|
||||
self.textField.textColor = enabled ? self.textEntryFieldModel?.enabledTextColor.uiColor : self.textEntryFieldModel?.disabledTextColor.uiColor
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -78,11 +84,15 @@ import UIKit
|
||||
set (error) {
|
||||
|
||||
if error {
|
||||
textField.accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message") ?? "", textField.text ?? "", errorMessage ?? "")
|
||||
textField.accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message") ?? "", textField.text ?? "", entryFieldModel?.errorMessage ?? "")
|
||||
} else {
|
||||
textField.accessibilityValue = nil
|
||||
}
|
||||
|
||||
if textField.isSecureTextEntry {
|
||||
showErrorView(error)
|
||||
}
|
||||
|
||||
super.showError = error
|
||||
}
|
||||
}
|
||||
@ -102,12 +112,6 @@ import UIKit
|
||||
set { textField.placeholder = newValue }
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Property Observers
|
||||
//--------------------------------------------------
|
||||
|
||||
public var validationBlock: ((_ value: String?) -> Bool)?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Delegate Properties
|
||||
//--------------------------------------------------
|
||||
@ -169,21 +173,21 @@ import UIKit
|
||||
|
||||
@objc open override func setupFieldContainerContent(_ container: UIView) {
|
||||
|
||||
textField.font = MFStyler.fontRegularBodyLarge()
|
||||
textField.font = Styler.Font.RegularBodyLarge.getFont()
|
||||
container.addSubview(textField)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
textField.heightAnchor.constraint(equalToConstant: 24),
|
||||
textField.topAnchor.constraint(equalTo: container.topAnchor, constant: 12),
|
||||
textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16),
|
||||
container.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: 12)
|
||||
textField.heightAnchor.constraint(equalToConstant: Padding.Five),
|
||||
textField.topAnchor.constraint(equalTo: container.topAnchor, constant: Padding.Three),
|
||||
textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: Padding.Three),
|
||||
container.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: Padding.Three)
|
||||
])
|
||||
|
||||
textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 16)
|
||||
textFieldTrailingConstraint = container.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Three)
|
||||
textFieldTrailingConstraint?.isActive = true
|
||||
|
||||
textField.addTarget(self, action: #selector(startEditing), for: .editingDidBegin)
|
||||
textField.addTarget(self, action: #selector(dismissFieldInput(_:)), for: .editingDidEnd)
|
||||
textField.addTarget(self, action: #selector(dismissFieldInput), for: .editingDidEnd)
|
||||
|
||||
let tap = UITapGestureRecognizer(target: self, action: #selector(startEditing))
|
||||
entryFieldContainer.addGestureRecognizer(tap)
|
||||
@ -194,37 +198,31 @@ import UIKit
|
||||
@objc open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
|
||||
textField.font = MFStyler.fontRegularBodyLarge()
|
||||
textField.font = Styler.Font.RegularBodyLarge.getFont()
|
||||
layoutIfNeeded()
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
|
||||
textField.font = MFStyler.fontRegularBodyLarge()
|
||||
textField.font = Styler.Font.RegularBodyLarge.getFont()
|
||||
}
|
||||
|
||||
@objc deinit {
|
||||
setBothTextDelegates(to: nil)
|
||||
}
|
||||
|
||||
@objc public func setBothTextDelegates(to delegate: (UITextFieldDelegate & ObservingTextFieldDelegate)?) {
|
||||
observingTextFieldDelegate = delegate
|
||||
uiTextFieldDelegate = delegate
|
||||
}
|
||||
|
||||
open func setupTextFieldToolbar() {
|
||||
let observingDelegate = observingTextFieldDelegate ?? self
|
||||
textField.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
|
||||
action: #selector(observingDelegate.dismissFieldInput))
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Observing for Change (TextFieldDelegate)
|
||||
//--------------------------------------------------
|
||||
|
||||
public func defaultValidationBlock() {
|
||||
|
||||
validationBlock = { enteredValue in
|
||||
guard let enteredValue = enteredValue else { return false }
|
||||
return enteredValue.count > 0
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
@objc override open func resignFirstResponder() -> Bool {
|
||||
if validateWhenDoneEditing {
|
||||
@ -240,11 +238,11 @@ import UIKit
|
||||
text = textField.text
|
||||
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||
}
|
||||
|
||||
|
||||
@objc public func updateValidation(_ isValid: Bool) {
|
||||
let previousValidity = self.isValid
|
||||
self.isValid = isValid
|
||||
|
||||
|
||||
if previousValidity && !isValid {
|
||||
showError = true
|
||||
observingTextFieldDelegate?.isInvalid?(textfield: self)
|
||||
@ -276,10 +274,30 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
@objc func dismissFieldInput(_ sender: Any?) {
|
||||
@objc public func dismissFieldInput(_ sender: Any?) {
|
||||
resignFirstResponder()
|
||||
}
|
||||
|
||||
private func showErrorView(_ show: Bool) {
|
||||
|
||||
if show {
|
||||
entryFieldContainer.addSubview(errorImage)
|
||||
|
||||
textFieldTrailingConstraint?.isActive = false
|
||||
textFieldTrailingConstraint = errorImage.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two)
|
||||
textFieldTrailingConstraint?.isActive = true
|
||||
|
||||
entryFieldContainer.trailingAnchor.constraint(equalTo: errorImage.trailingAnchor, constant: Padding.Three).isActive = true
|
||||
errorImage.centerYAnchor.constraint(equalTo: entryFieldContainer.centerYAnchor).isActive = true
|
||||
|
||||
} else {
|
||||
errorImage.removeFromSuperview()
|
||||
textFieldTrailingConstraint?.isActive = false
|
||||
textFieldTrailingConstraint = entryFieldContainer.trailingAnchor.constraint(equalTo: textField.trailingAnchor, constant: Padding.Two)
|
||||
textFieldTrailingConstraint?.isActive = true
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MoleculeViewProtocol
|
||||
//--------------------------------------------------
|
||||
@ -288,44 +306,39 @@ import UIKit
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
|
||||
guard let model = model as? TextEntryFieldModel else { return }
|
||||
|
||||
|
||||
model.updateUI = { [weak self] in
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||
if self?.isSelected ?? false {
|
||||
self?.updateValidation(model.isValid ?? true)
|
||||
guard let self = self else { return }
|
||||
|
||||
if self.isSelected {
|
||||
self.updateValidation(model.isValid ?? true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
self.delegateObject = delegateObject
|
||||
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
|
||||
textColor.enabled = model.enabledTextColor?.uiColor
|
||||
textColor.disabled = model.disabledTextColor?.uiColor
|
||||
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
|
||||
text = model.text
|
||||
placeholder = model.placeholder
|
||||
|
||||
switch model.type {
|
||||
case .password:
|
||||
case .password, .secure:
|
||||
textField.isSecureTextEntry = true
|
||||
|
||||
case .number:
|
||||
textField.keyboardType = .numberPad
|
||||
|
||||
case .email:
|
||||
textField.keyboardType = .emailAddress
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
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
|
||||
observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate
|
||||
textField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self)
|
||||
setupTextFieldToolbar()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,9 +8,13 @@
|
||||
|
||||
|
||||
@objcMembers public class TextEntryFieldModel: EntryFieldModel {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Types
|
||||
//--------------------------------------------------
|
||||
|
||||
public enum EntryType: String, Codable {
|
||||
case password
|
||||
case secure
|
||||
case number
|
||||
case email
|
||||
}
|
||||
@ -24,10 +28,9 @@
|
||||
}
|
||||
|
||||
public var placeholder: String?
|
||||
public var enabledTextColor: Color?
|
||||
public var disabledTextColor: Color?
|
||||
public var enabledTextColor: Color = Color(uiColor: .mvmBlack)
|
||||
public var disabledTextColor: Color = Color(uiColor: .mvmCoolGray3)
|
||||
public var type: EntryType?
|
||||
public var regex: String?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
@ -35,38 +38,38 @@
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case text
|
||||
case placeholder
|
||||
case enabledTextColor
|
||||
case disabledTextColor
|
||||
case type
|
||||
case regex
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
try super.init(from: decoder)
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
|
||||
placeholder = try typeContainer.decodeIfPresent(String.self, forKey: .placeholder)
|
||||
enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTextColor)
|
||||
disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor)
|
||||
type = try typeContainer.decodeIfPresent(EntryType.self, forKey: .type)
|
||||
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 {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(text, forKey: .text)
|
||||
try container.encodeIfPresent(placeholder, forKey: .placeholder)
|
||||
try container.encodeIfPresent(enabledTextColor, forKey: .enabledTextColor)
|
||||
try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor)
|
||||
try container.encode(enabledTextColor, forKey: .enabledTextColor)
|
||||
try container.encode(disabledTextColor, forKey: .disabledTextColor)
|
||||
try container.encodeIfPresent(type, forKey: .type)
|
||||
try container.encodeIfPresent(regex, forKey: .regex)
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,8 +14,8 @@ import Foundation
|
||||
// MARK: - Outlets
|
||||
//------------------------------------------------------
|
||||
|
||||
let leftTextLabel = Label.commonLabelB1(true)
|
||||
let rightTextLabel = Label.commonLabelB1(true)
|
||||
let leftTextLabel = Label.createLabelBoldBodySmall(true)
|
||||
let rightTextLabel = Label.createLabelBoldBodySmall(true)
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
@ -23,6 +23,29 @@ import Foundation
|
||||
|
||||
var rightTextLabelLeading: 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
|
||||
@ -43,8 +66,6 @@ import Foundation
|
||||
override open func setupView() {
|
||||
super.setupView()
|
||||
|
||||
guard subviews.isEmpty else { return }
|
||||
|
||||
addSubview(leftTextLabel)
|
||||
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.
|
||||
if leftTextLabel.hasText && rightTextLabel.hasText {
|
||||
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
|
||||
rightTextLabel.preferredMaxLayoutWidth = round(maximumTextWidth) - 10
|
||||
} else {
|
||||
@ -84,57 +105,38 @@ import Foundation
|
||||
leftTextLabel.topAnchor.constraint(equalTo: topAnchor).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.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
|
||||
|
||||
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.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.isActive = true
|
||||
|
||||
let rightTextWidth = rightTextLabel.widthAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.widthAnchor, multiplier: 0.4)
|
||||
rightTextWidth.priority = UILayoutPriority(rawValue: 906)
|
||||
let rightTextWidth = rightTextLabel.widthAnchor.constraint(equalTo: layoutMarginsGuide.widthAnchor, multiplier: 0.4)
|
||||
rightTextWidth.priority = UILayoutPriority(rawValue: 995)
|
||||
rightTextWidth.isActive = true
|
||||
|
||||
leftTextLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 901), for: .horizontal)
|
||||
rightTextLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 902), for: .horizontal)
|
||||
|
||||
leftTextLabel.setContentHuggingPriority(.required, for: .vertical)
|
||||
rightTextLabel.setContentHuggingPriority(.required, for: .vertical)
|
||||
|
||||
rightTextLabel.setContentHuggingPriority(.required, for: .horizontal)
|
||||
leftTextLabel.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
rightTextLabel.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
rightTextLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 902), 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
|
||||
rightTextLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||
}
|
||||
|
||||
override open func reset() {
|
||||
@ -144,31 +146,31 @@ import Foundation
|
||||
constrainBothLabels()
|
||||
leftTextLabel.text = ""
|
||||
rightTextLabel.text = ""
|
||||
leftTextLabel.textAlignment = .left
|
||||
rightTextLabel.textAlignment = .right
|
||||
backgroundColor = nil
|
||||
}
|
||||
|
||||
private func deactivateMiddleConstraint() {
|
||||
|
||||
leftTextLabelTrailing?.isActive = false
|
||||
rightTextLabelLeading?.isActive = false
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Atomization
|
||||
//------------------------------------------------------
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
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)
|
||||
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 {
|
||||
constrainRightLabel()
|
||||
constrainRightLabelOnly()
|
||||
|
||||
} else if !rightTextLabel.hasText {
|
||||
constrainLeftLabel()
|
||||
constrainLeftLabelOnly()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,39 +9,27 @@
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class MultiProgress: View {
|
||||
private let stack = Stack<StackModel>()
|
||||
var multiProgressModel: MultiProgressBarModel? {
|
||||
get { return model as? MultiProgressBarModel }
|
||||
}
|
||||
|
||||
///passing value to progressList creates corresponding progress bars
|
||||
var progressList: Array<SingleProgressBarModel>? {
|
||||
didSet {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.init(frame: .zero)
|
||||
set(with: model, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
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 {
|
||||
if roundedRect {
|
||||
if roundedCorners {
|
||||
layer.cornerRadius = (thicknessConstraint?.constant ?? defaultHeight)/2
|
||||
} else {
|
||||
layer.cornerRadius = 0
|
||||
@ -57,28 +45,53 @@ import UIKit
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
backgroundColor = .mfLightSilver()
|
||||
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 {
|
||||
thicknessConstraint = heightAnchor.constraint(equalToConstant: defaultHeight)
|
||||
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
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let multiProgressModel = multiProgressModel else {
|
||||
return
|
||||
}
|
||||
roundedRect = multiProgressModel.roundedRect ?? false
|
||||
guard let multiProgressModel = multiProgressModel else { return }
|
||||
roundedCorners = multiProgressModel.roundedCorners ?? false
|
||||
thicknessConstraint?.constant = multiProgressModel.thickness ?? defaultHeight
|
||||
progressList = multiProgressModel.progressList
|
||||
|
||||
stack.model?.backgroundColor = model.backgroundColor
|
||||
set(with: multiProgressModel.progressList, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
backgroundColor = .mfLightSilver()
|
||||
progressList = nil
|
||||
stack.reset()
|
||||
set(with: [], nil, nil)
|
||||
}
|
||||
|
||||
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
|
||||
@ -9,12 +9,12 @@
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class SingleProgressBarModel: Codable {
|
||||
@Percent var progress: CGFloat
|
||||
var progressColor: Color
|
||||
@Percent var percent: CGFloat
|
||||
var color: Color
|
||||
|
||||
init(_ progress: CGFloat, color: Color) {
|
||||
self.progress = progress
|
||||
self.progressColor = color
|
||||
init(_ percent: CGFloat, color: Color) {
|
||||
self.percent = percent
|
||||
self.color = color
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,13 +23,13 @@ import Foundation
|
||||
public var progressList: [SingleProgressBarModel]
|
||||
public var backgroundColor: Color?
|
||||
public var thickness: CGFloat?
|
||||
public var roundedRect: Bool?
|
||||
public var roundedCorners: Bool?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case progressList
|
||||
case thickness
|
||||
case roundedRect
|
||||
case roundedCorners
|
||||
case backgroundColor
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ import Foundation
|
||||
progressList = try typeContainer.decode([SingleProgressBarModel].self, forKey: .progressList)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
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 {
|
||||
@ -50,7 +50,7 @@ import Foundation
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(progressList, forKey: .progressList)
|
||||
try container.encodeIfPresent(thickness, forKey: .thickness)
|
||||
try container.encodeIfPresent(roundedRect, forKey: .roundedRect)
|
||||
try container.encodeIfPresent(roundedCorners, forKey: .roundedCorners)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ import Foundation
|
||||
var thickness: CGFloat = 8.0 {
|
||||
willSet(newValue) {
|
||||
heightAnchor.constraint(equalToConstant: newValue).isActive = true
|
||||
if progressBarModel?.isRounded ?? false {
|
||||
if progressBarModel?.roundedCorners ?? false {
|
||||
layer.cornerRadius = newValue/2.0
|
||||
} else {
|
||||
progressViewStyle = .bar
|
||||
@ -52,12 +52,11 @@ import Foundation
|
||||
|
||||
//MARK: - MoleculeViewProtocol
|
||||
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
guard let progressBarModel = model as? ProgressBarModel else {
|
||||
return
|
||||
}
|
||||
guard let progressBarModel = model as? ProgressBarModel else { return }
|
||||
self.progressBarModel = progressBarModel
|
||||
thickness = progressBarModel.thickness ?? 8
|
||||
progress = Float((progressBarModel.percent)/100.0)
|
||||
progressTintColor = progressBarModel.progressColor.uiColor
|
||||
progressTintColor = progressBarModel.color.uiColor
|
||||
if let backgroundColor = progressBarModel.backgroundColor {
|
||||
trackTintColor = backgroundColor.uiColor
|
||||
}
|
||||
|
||||
@ -11,17 +11,17 @@ import Foundation
|
||||
@objcMembers public class ProgressBarModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "progressBar"
|
||||
@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 isRounded: Bool?
|
||||
public var roundedCorners: Bool?
|
||||
public var thickness: CGFloat?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case isRounded = "roundRect"
|
||||
case roundedCorners
|
||||
case thickness
|
||||
case percent
|
||||
case progressColor
|
||||
case color
|
||||
case backgroundColor
|
||||
}
|
||||
|
||||
@ -32,13 +32,13 @@ import Foundation
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
percent = try typeContainer.decode(CGFloat.self, forKey: .percent)
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .progressColor) {
|
||||
progressColor = color
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) {
|
||||
self.color = color
|
||||
}
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) {
|
||||
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)
|
||||
}
|
||||
|
||||
@ -46,9 +46,9 @@ import Foundation
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
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(isRounded, forKey: .isRounded)
|
||||
try container.encodeIfPresent(roundedCorners, forKey: .roundedCorners)
|
||||
try container.encodeIfPresent(thickness, forKey: .thickness)
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,13 +25,13 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
//--------------------------------------------------
|
||||
|
||||
/// 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.
|
||||
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..
|
||||
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.
|
||||
public var isAnimated = true
|
||||
@ -62,8 +62,8 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
didSet {
|
||||
isUserInteractionEnabled = isEnabled
|
||||
changeStateNoAnimation(isEnabled ? isOn : false)
|
||||
backgroundColor = isEnabled ? containerTintColor?.off : disabledTintColor?.container
|
||||
knobView.backgroundColor = isEnabled ? knobTintColor?.off : disabledTintColor?.knob
|
||||
backgroundColor = isEnabled ? (isOn ? containerTintColor.on : containerTintColor.off) : disabledTintColor.container
|
||||
knobView.backgroundColor = isEnabled ? (isOn ? knobTintColor.on : knobTintColor.off) : disabledTintColor.knob
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,12 +80,12 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
if isAnimated {
|
||||
UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: {
|
||||
if self.isOn {
|
||||
self.knobView.backgroundColor = self.knobTintColor?.on
|
||||
self.backgroundColor = self.containerTintColor?.on
|
||||
self.knobView.backgroundColor = self.knobTintColor.on
|
||||
self.backgroundColor = self.containerTintColor.on
|
||||
|
||||
} else {
|
||||
self.knobView.backgroundColor = self.knobTintColor?.off
|
||||
self.backgroundColor = self.containerTintColor?.off
|
||||
self.knobView.backgroundColor = self.knobTintColor.off
|
||||
self.backgroundColor = self.containerTintColor.off
|
||||
}
|
||||
}, completion: nil)
|
||||
|
||||
@ -96,12 +96,12 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
}, completion: nil)
|
||||
|
||||
} else {
|
||||
backgroundColor = isOn ? containerTintColor?.on : containerTintColor?.off
|
||||
knobView.backgroundColor = isOn ? knobTintColor?.on : knobTintColor?.off
|
||||
backgroundColor = isOn ? containerTintColor.on : containerTintColor.off
|
||||
knobView.backgroundColor = isOn ? knobTintColor.on : knobTintColor.off
|
||||
self.constrainKnob()
|
||||
}
|
||||
|
||||
(model as? ToggleModel)?.state = isOn
|
||||
toggleModel?.state = isOn
|
||||
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||
accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff")
|
||||
setNeedsLayout()
|
||||
@ -109,6 +109,10 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
}
|
||||
}
|
||||
|
||||
public var toggleModel: ToggleModel? {
|
||||
return model as? ToggleModel
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Delegate
|
||||
//--------------------------------------------------
|
||||
@ -127,8 +131,26 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
private var widthConstraint: NSLayoutConstraint?
|
||||
|
||||
private func constrainKnob() {
|
||||
knobLeadingConstraint?.isActive = !isOn
|
||||
knobTrailingConstraint?.isActive = isOn
|
||||
|
||||
knobLeadingConstraint?.isActive = false
|
||||
knobTrailingConstraint?.isActive = false
|
||||
|
||||
_ = isOn ? constrainKnobOn() : constrainKnobOff()
|
||||
|
||||
knobTrailingConstraint?.isActive = true
|
||||
knobLeadingConstraint?.isActive = true
|
||||
}
|
||||
|
||||
private func constrainKnobOn() {
|
||||
|
||||
knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 1)
|
||||
knobLeadingConstraint = knobView.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor)
|
||||
}
|
||||
|
||||
private func constrainKnobOff() {
|
||||
|
||||
knobTrailingConstraint = trailingAnchor.constraint(greaterThanOrEqualTo: knobView.trailingAnchor)
|
||||
knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -185,11 +207,13 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
|
||||
layer.cornerRadius = Self.getContainerHeight() / 2.0
|
||||
knobView.layer.cornerRadius = Self.getKnobHeight() / 2.0
|
||||
|
||||
changeStateNoAnimation(isOn)
|
||||
}
|
||||
|
||||
public override func setupView() {
|
||||
super.setupView()
|
||||
guard subviews.isEmpty else { return }
|
||||
|
||||
isAccessibilityElement = true
|
||||
accessibilityTraits = .button
|
||||
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccToggleHint")
|
||||
@ -202,7 +226,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
widthConstraint?.isActive = true
|
||||
|
||||
layer.cornerRadius = Self.containerSize.height / 2.0
|
||||
backgroundColor = containerTintColor?.off
|
||||
backgroundColor = containerTintColor.off
|
||||
|
||||
addSubview(knobView)
|
||||
|
||||
@ -214,19 +238,16 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
knobView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true
|
||||
bottomAnchor.constraint(greaterThanOrEqualTo: knobView.bottomAnchor).isActive = true
|
||||
|
||||
knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 1)
|
||||
knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1)
|
||||
knobLeadingConstraint?.isActive = true
|
||||
constrainKnobOff()
|
||||
}
|
||||
|
||||
public override func reset() {
|
||||
super.reset()
|
||||
|
||||
backgroundColor = containerTintColor?.off
|
||||
knobView.backgroundColor = knobTintColor?.off
|
||||
isAnimated = false
|
||||
isOn = false
|
||||
constrainKnob()
|
||||
backgroundColor = containerTintColor.off
|
||||
knobView.backgroundColor = knobTintColor.off
|
||||
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel")
|
||||
isAnimated = true
|
||||
didToggleAction = nil
|
||||
shouldToggleAction = { return true }
|
||||
}
|
||||
@ -344,26 +365,19 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
|
||||
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
|
||||
|
||||
if let color = model.onTintColor?.uiColor {
|
||||
containerTintColor?.on = color
|
||||
}
|
||||
|
||||
if let color = model.offTintColor?.uiColor {
|
||||
containerTintColor?.off = color
|
||||
}
|
||||
|
||||
if let color = model.onKnobTintColor?.uiColor {
|
||||
knobTintColor?.on = color
|
||||
}
|
||||
|
||||
if let color = model.offKnobTintColor?.uiColor {
|
||||
knobTintColor?.off = color
|
||||
}
|
||||
|
||||
changeStateNoAnimation(model.state)
|
||||
containerTintColor.on = model.onTintColor.uiColor
|
||||
containerTintColor.off = model.offTintColor.uiColor
|
||||
knobTintColor.on = model.onKnobTintColor.uiColor
|
||||
knobTintColor.off = model.offKnobTintColor.uiColor
|
||||
isOn = model.state
|
||||
changeStateNoAnimation(isOn)
|
||||
isAnimated = model.animated
|
||||
isEnabled = model.enabled
|
||||
|
||||
|
||||
if let accessibileString = model.accessibilityText {
|
||||
accessibilityLabel = accessibileString
|
||||
}
|
||||
|
||||
if let actionMap = model.action?.toJSON() {
|
||||
didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) }
|
||||
}
|
||||
|
||||
@ -8,8 +8,12 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol {
|
||||
|
||||
public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "toggle"
|
||||
public var backgroundColor: Color?
|
||||
public var state: Bool = false
|
||||
@ -18,10 +22,10 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
|
||||
public var action: ActionModelProtocol?
|
||||
public var alternateAction: ActionModelProtocol?
|
||||
public var accessibilityText: String?
|
||||
public var onTintColor: Color?
|
||||
public var offTintColor: Color?
|
||||
public var onKnobTintColor: Color?
|
||||
public var offKnobTintColor: Color?
|
||||
public var onTintColor: Color = Color(uiColor: .mvmGreen)
|
||||
public var offTintColor: Color = Color(uiColor: .mvmBlack)
|
||||
public var onKnobTintColor: Color = Color(uiColor: .mvmWhite)
|
||||
public var offKnobTintColor: Color = Color(uiColor: .mvmWhite)
|
||||
|
||||
public var fieldKey: String?
|
||||
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) {
|
||||
self.state = state
|
||||
}
|
||||
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
|
||||
if let animated = try typeContainer.decodeIfPresent(Bool.self, forKey: .animated) {
|
||||
self.animated = animated
|
||||
}
|
||||
|
||||
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
||||
alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
onTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onTintColor)
|
||||
offTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offTintColor)
|
||||
onKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onKnobTintColor)
|
||||
offKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offKnobTintColor)
|
||||
|
||||
if let onTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onTintColor) {
|
||||
self.onTintColor = onTintColor
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
baseValue = state
|
||||
@ -106,10 +126,10 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
|
||||
try container.encode(state, forKey: .state)
|
||||
try container.encode(animated, forKey: .animated)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encodeIfPresent(onTintColor, forKey: .onTintColor)
|
||||
try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor)
|
||||
try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor)
|
||||
try container.encodeIfPresent(offKnobTintColor, forKey: .offKnobTintColor)
|
||||
try container.encode(onTintColor, forKey: .onTintColor)
|
||||
try container.encode(onKnobTintColor, forKey: .onKnobTintColor)
|
||||
try container.encode(onKnobTintColor, forKey: .onKnobTintColor)
|
||||
try container.encode(offKnobTintColor, forKey: .offKnobTintColor)
|
||||
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// GraphView.swift
|
||||
// Wheel.swift
|
||||
// MobileFirstFramework
|
||||
//
|
||||
// Created by Ryan on 10/24/19.
|
||||
@ -8,12 +8,12 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class GraphView: View, MVMCoreUIViewConstrainingProtocol {
|
||||
@objcMembers open class Wheel: View, MVMCoreUIViewConstrainingProtocol {
|
||||
|
||||
var heightConstraint: NSLayoutConstraint?
|
||||
var gradientLayer: CALayer?
|
||||
var graphModel: CircleProgressModel? {
|
||||
return model as? CircleProgressModel
|
||||
var graphModel: WheelModel? {
|
||||
return model as? WheelModel
|
||||
}
|
||||
|
||||
// MARK: setup
|
||||
@ -28,7 +28,7 @@ import UIKit
|
||||
|
||||
override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? CircleProgressModel else { return }
|
||||
guard let model = model as? WheelModel else { return }
|
||||
createGraphCircle(model)
|
||||
rotationAnimation(model)
|
||||
}
|
||||
@ -42,7 +42,7 @@ import UIKit
|
||||
}
|
||||
|
||||
// MARK: circle
|
||||
open func createGraphCircle(_ graphObject: CircleProgressModel) {
|
||||
open func createGraphCircle(_ graphObject: WheelModel) {
|
||||
if let sublayers = layer.sublayers {
|
||||
for sublayer in sublayers {
|
||||
sublayer.removeAllAnimations()
|
||||
@ -56,7 +56,7 @@ import UIKit
|
||||
|
||||
//begin point will be at the bottom, clockwise direction
|
||||
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
|
||||
|
||||
let circleLayer = CAShapeLayer()
|
||||
@ -83,7 +83,7 @@ import UIKit
|
||||
| | |
|
||||
-------------
|
||||
*/
|
||||
func createGradientLayer(_ graphObject: CircleProgressModel) -> CALayer {
|
||||
func createGradientLayer(_ graphObject: WheelModel) -> CALayer {
|
||||
let containLayer = CALayer()
|
||||
containLayer.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter)
|
||||
let radius = graphObject.diameter / 2.0
|
||||
@ -151,18 +151,18 @@ import UIKit
|
||||
}
|
||||
|
||||
//MARK: Animation
|
||||
func rotationAnimation(_ object: CircleProgressModel) {
|
||||
func rotationAnimation(_ object: WheelModel) {
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread:{
|
||||
let rotation = CABasicAnimation(keyPath: "transform.rotation")
|
||||
let animationHandler = GraphViewAnimationHandler.shared
|
||||
let animationHandler = WheelAnimationHandler.shared
|
||||
let startAngle = animationHandler.getAnimationStartAngle(object.duration, CACurrentMediaTime())
|
||||
if startAngle == 0.0 {
|
||||
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 {
|
||||
fromValue = GraphView.getPiValue(360.0 - startAngle)
|
||||
toValue = GraphView.getPiValue(0.0 - startAngle)
|
||||
fromValue = Wheel.getPiValue(360.0 - startAngle)
|
||||
toValue = Wheel.getPiValue(0.0 - startAngle)
|
||||
}
|
||||
rotation.fromValue = fromValue
|
||||
rotation.toValue = toValue
|
||||
@ -180,7 +180,7 @@ import UIKit
|
||||
}
|
||||
|
||||
|
||||
extension GraphView: CAAnimationDelegate {
|
||||
extension Wheel: CAAnimationDelegate {
|
||||
public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
|
||||
if let object = graphModel {
|
||||
rotationAnimation(object)
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// GraphViewAnimationHandler.swift
|
||||
// WheelAnimationHandler.swift
|
||||
// MobileFirstFramework
|
||||
//
|
||||
// Created by Ryan on 10/29/19.
|
||||
@ -8,12 +8,12 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class GraphViewAnimationHandler: NSObject {
|
||||
@objcMembers open class WheelAnimationHandler: NSObject {
|
||||
|
||||
/// duration : CACurrentMediaTime()
|
||||
private var animations = [Double: Double]()
|
||||
|
||||
static let shared = GraphViewAnimationHandler()
|
||||
static let shared = WheelAnimationHandler()
|
||||
|
||||
open func storeAnimation(_ duration: Double, _ currentTime: CFTimeInterval) {
|
||||
guard animations[duration] == nil else {
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// CircleProgressModel.swift
|
||||
// WheelModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 1/13/20.
|
||||
@ -16,9 +16,9 @@ public enum GraphStyle: String, Codable {
|
||||
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 {
|
||||
didSet {
|
||||
updateStyle()
|
||||
37
MVMCoreUI/Atomic/Extensions/UIDatePicker+Extension.swift
Normal file
37
MVMCoreUI/Atomic/Extensions/UIDatePicker+Extension.swift
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// UIDatePicker+Extension.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kevin Christiano on 4/14/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
public extension UIDatePicker {
|
||||
|
||||
class func addDatePicker(to textField: UITextField) -> UIDatePicker {
|
||||
|
||||
let datePicker = UIDatePicker()
|
||||
datePicker.backgroundColor = .mvmWhite
|
||||
datePicker.datePickerMode = .date
|
||||
|
||||
let locale = NSLocale.current as NSLocale
|
||||
datePicker.locale = locale as Locale
|
||||
datePicker.calendar = locale.object(forKey: .calendar) as? Calendar
|
||||
textField.inputView = datePicker
|
||||
|
||||
return datePicker
|
||||
}
|
||||
|
||||
class func addTimeAndDatePicker(to textField: UITextField) -> UIDatePicker {
|
||||
|
||||
let datePicker = UIDatePicker()
|
||||
datePicker.backgroundColor = .mvmWhite
|
||||
datePicker.datePickerMode = .time
|
||||
textField.inputView = datePicker
|
||||
|
||||
return datePicker
|
||||
}
|
||||
}
|
||||
38
MVMCoreUI/Atomic/Extensions/UIPickerView+Extension.swift
Normal file
38
MVMCoreUI/Atomic/Extensions/UIPickerView+Extension.swift
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// UIPickerView.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kevin Christiano on 4/14/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
public extension UIPickerView {
|
||||
|
||||
class func createPickerView() -> UIPickerView {
|
||||
|
||||
let picker = UIPickerView(frame: .zero)
|
||||
picker.backgroundColor = .mvmWhite
|
||||
picker.showsSelectionIndicator = true
|
||||
return picker
|
||||
}
|
||||
|
||||
class func addPicker(to textField: UITextField, delegate: TextFieldAndPickerDelegate?, dismissAction: Selector?) -> UIPickerView {
|
||||
|
||||
// Sets up the picker (same tag as the textfield)
|
||||
let picker = createPickerView()
|
||||
picker.delegate = delegate
|
||||
picker.dataSource = delegate
|
||||
picker.tag = textField.tag
|
||||
textField.inputView = picker
|
||||
|
||||
// Adds a dismiss toolbar, since all fields with pickers should have one.
|
||||
if let dismissAction = dismissAction {
|
||||
UIToolbar.addDismissToolbar(to: textField, delegate: delegate, action: dismissAction)
|
||||
}
|
||||
|
||||
return picker
|
||||
}
|
||||
}
|
||||
56
MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift
Normal file
56
MVMCoreUI/Atomic/Extensions/UIToolbar+Extension.swift
Normal file
@ -0,0 +1,56 @@
|
||||
//
|
||||
// UIToolbar+Extension.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kevin Christiano on 4/10/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol TextFieldOrView { }
|
||||
|
||||
extension UITextView: TextFieldOrView { }
|
||||
extension UITextField: TextFieldOrView { }
|
||||
|
||||
|
||||
public extension UIToolbar {
|
||||
|
||||
class func createEmptyToolbar() -> UIToolbar {
|
||||
|
||||
let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44))
|
||||
toolbar.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleWidth]
|
||||
toolbar.barStyle = .default
|
||||
toolbar.barTintColor = .mvmCoolGray3
|
||||
toolbar.tintColor = .mvmBlack
|
||||
toolbar.isTranslucent = true
|
||||
|
||||
return toolbar
|
||||
}
|
||||
|
||||
class func getToolbarWithDoneButton(delegate: Any?, action: Selector) -> UIToolbar {
|
||||
|
||||
let toolbar = createEmptyToolbar()
|
||||
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
|
||||
let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: action)
|
||||
toolbar.setItems([space, button], animated: false)
|
||||
|
||||
return toolbar
|
||||
}
|
||||
|
||||
class func addDismissToolbar(to object: TextFieldOrView, delegate: Any?, action: Selector) {
|
||||
|
||||
let toolbar = Self.getToolbarWithDoneButton(delegate: delegate, action: action)
|
||||
|
||||
switch object {
|
||||
case is UITextField:
|
||||
(object as? UITextField)?.inputAccessoryView = toolbar
|
||||
|
||||
case is UITextView:
|
||||
(object as? UITextView)?.inputAccessoryView = toolbar
|
||||
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -37,8 +37,7 @@ import Foundation
|
||||
/// Call to register all of the CoreUI molecules.
|
||||
public static func registerObjects() {
|
||||
// Stacks
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeStackView.self, viewModelClass: MoleculeStackModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: Stack<StackModel>.self, viewModelClass: StackModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeStackView.self, viewModelClass: StackModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: UnOrderedList.self, viewModelClass: UnOrderedListModel.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: RadioBoxes.self, viewModelClass: RadioBoxesModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: Checkbox.self, viewModelClass: CheckboxModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: RadioSwatches.self, viewModelClass: RadioSwatchesModel.self)
|
||||
|
||||
// Other Atoms
|
||||
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: MFLoadImageView.self, viewModelClass: ImageViewModel.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: CheckboxLabel.self, viewModelClass: CheckboxLabelModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: Arrow.self, viewModelClass: ArrowModel.self)
|
||||
@ -88,6 +88,7 @@ import Foundation
|
||||
// Horizontal Combination Molecules
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ImageHeadlineBody.self, viewModelClass: ImageHeadlineBodyModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: Tabs.self, viewModelClass: TabsModel.self)
|
||||
|
||||
// Vertical Combination Molecules
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: HeadlineBody.self, viewModelClass: HeadlineBodyModel.self)
|
||||
@ -120,6 +121,7 @@ import Foundation
|
||||
|
||||
|
||||
// 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: FooterView.self, viewModelClass: FooterModel.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: ListLeftVariableRadioButtonAndPaymentMethod.self, viewModelClass: ListLeftVariableRadioButtonAndPaymentMethodModel.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: ListRightVariablePayments.self, viewModelClass: ListRightVariablePaymentsModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTotalData.self, viewModelClass: ListRightVariableTotalDataModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableTextLinkAllTextAndLinks.self, viewModelClass: ListRightVariableTextLinkAllTextAndLinksModel.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: ListOneColumnFullWidthTextBodyText.self, viewModelClass: ListOneColumnFullWidthTextBodyTextModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnCompareChanges.self, viewModelClass: ListTwoColumnCompareChangesModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDetails.self, viewModelClass: ListTwoColumnPriceDetailsModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnInternationalData.self, viewModelClass: ListThreeColumnInternationalDataModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnDataUsage.self, viewModelClass: ListThreeColumnDataUsageModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageListItem.self, viewModelClass: ListFourColumnDataUsageListItemModel.self)
|
||||
|
||||
|
||||
// Designed Section Dividers
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self)
|
||||
@ -164,6 +170,11 @@ import Foundation
|
||||
// Designed Headers
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2NoButtonsBodyText.self, viewModelClass: HeadersH2NoButtonsBodyTextModel.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
|
||||
try? ModelRegistry.register(TabsModel.self)
|
||||
|
||||
@ -25,8 +25,8 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
|
||||
|
||||
public override func setDefaults() {
|
||||
super.setDefaults()
|
||||
topMarginPadding = PaddingDefaultVerticalSpacing3
|
||||
bottomMarginPadding = PaddingDefaultVerticalSpacing3
|
||||
topPadding = PaddingDefaultVerticalSpacing3
|
||||
bottomPadding = PaddingDefaultVerticalSpacing3
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -0,0 +1,79 @@
|
||||
//
|
||||
// ListDeviceComplexButtonMedium.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Dhamodaram Nandi on 21/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@objcMembers open class ListDeviceComplexButtonMedium: TableViewCell {
|
||||
|
||||
public var verticalStack: Stack<StackModel>
|
||||
public let eyebrow = Label.createLabelRegularMicro(true)
|
||||
public let headline = Label.createLabelBoldTitleMedium(true)
|
||||
public let body = Label.createLabelRegularBodySmall(true)
|
||||
public let body2 = Label.createLabelRegularBodySmall(true)
|
||||
public let button = PillButton(frame: .zero)
|
||||
public let rightImageView = MFLoadImageView()
|
||||
public var stack: Stack<StackModel>
|
||||
|
||||
// MARK: - Initializers
|
||||
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
rightImageView.addSizeConstraintsForAspectRatio = true
|
||||
rightImageView.heightAnchor.constraint(equalToConstant: 116.0).isActive = true
|
||||
rightImageView.widthAnchor.constraint(equalToConstant: 116.0).isActive = true
|
||||
verticalStack = Stack<StackModel>.createStack(with: [(view: eyebrow, model: StackItemModel(horizontalAlignment: .leading)),
|
||||
(view: headline, model: StackItemModel(horizontalAlignment: .leading)),
|
||||
(view: body, model: StackItemModel(horizontalAlignment: .leading)),
|
||||
(view: body2, model: StackItemModel(horizontalAlignment: .leading)),
|
||||
(view: button, model: StackItemModel(spacing:16, horizontalAlignment: .leading))],
|
||||
axis: .vertical, spacing: 0)
|
||||
stack = Stack<StackModel>.createStack(with: [(view: verticalStack, model: StackItemModel(horizontalAlignment: .leading, verticalAlignment: .leading)),
|
||||
(view: rightImageView, model: StackItemModel(horizontalAlignment: .fill, verticalAlignment: .center))],
|
||||
axis: .horizontal)
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
// MARK: - MFViewProtocol
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
verticalStack.restack()
|
||||
}
|
||||
|
||||
// MARK: - ModelMoleculeViewProtocol
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListDeviceComplexButtonMediumModel else { return }
|
||||
verticalStack.updateContainedMolecules(with: [model.eyebrow,
|
||||
model.headline,
|
||||
model.body,
|
||||
model.body2,
|
||||
model.button],
|
||||
delegateObject, additionalData)
|
||||
rightImageView.set(with: model.image, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 120
|
||||
}
|
||||
|
||||
public func setDefault() {
|
||||
eyebrow.styleRegularMicro(true)
|
||||
headline.styleBoldTitleMedium(true)
|
||||
body.styleRegularBodySmall(true)
|
||||
body2.styleRegularBodySmall(true)
|
||||
eyebrow.textColor = .mvmCoolGray6
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
setDefault()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
//
|
||||
// ListDeviceComplexButtonMediumModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Dhamodaram Nandi on 21/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
public class ListDeviceComplexButtonMediumModel: ListItemModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "listDvcBtnM"
|
||||
public var eyebrow: LabelModel?
|
||||
public var headline: LabelModel?
|
||||
public var body: LabelModel?
|
||||
public var body2: LabelModel?
|
||||
public var button: ButtonModel
|
||||
public var image: ImageViewModel
|
||||
|
||||
public init(eyebrow: LabelModel, headline:LabelModel, body: LabelModel, body2: LabelModel, button: ButtonModel, image: ImageViewModel) {
|
||||
self.eyebrow = eyebrow
|
||||
self.headline = headline
|
||||
self.body = body
|
||||
self.body2 = body2
|
||||
self.button = button
|
||||
self.image = image
|
||||
super.init()
|
||||
}
|
||||
|
||||
/// Defaults to set
|
||||
override public func setDefaults() {
|
||||
super.setDefaults()
|
||||
button.size = .tiny
|
||||
button.style = .secondary
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case eyebrow
|
||||
case headline
|
||||
case body
|
||||
case body2
|
||||
case button
|
||||
case image
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow)
|
||||
headline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .headline)
|
||||
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
|
||||
body2 = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body2)
|
||||
button = try typeContainer.decode(ButtonModel.self, forKey: .button)
|
||||
image = try typeContainer.decode(ImageViewModel.self, forKey: .image)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(eyebrow, forKey: .eyebrow)
|
||||
try container.encodeIfPresent(headline, forKey: .headline)
|
||||
try container.encodeIfPresent(body, forKey: .body)
|
||||
try container.encodeIfPresent(body2, forKey: .body2)
|
||||
try container.encode(button, forKey: .button)
|
||||
try container.encode(image, forKey: .image)
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -71,9 +71,6 @@ import UIKit
|
||||
}
|
||||
|
||||
public override func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
|
||||
if radioButton.isEnabled {
|
||||
radioButton.tapAction()
|
||||
}
|
||||
radioButton.tapAction()
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,24 +40,18 @@ import Foundation
|
||||
override open func setupView() {
|
||||
super.setupView()
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?){
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListOneColumnFullWidthTextAllTextAndLinksModel else { return }
|
||||
eyebrow.setOptional(with: model.eyebrow, delegateObject, additionalData)
|
||||
headline.setOptional(with: model.headline, delegateObject, additionalData)
|
||||
subHeadline.setOptional(with: model.subHeadline, delegateObject, additionalData)
|
||||
body.setOptional(with: model.body, delegateObject, additionalData)
|
||||
link.setOptional(with: model.link, delegateObject, additionalData)
|
||||
|
||||
// Hide labels if neeeded.
|
||||
stack.stackModel?.molecules[0].gone = !eyebrow.hasText
|
||||
stack.stackModel?.molecules[1].gone = !headline.hasText
|
||||
stack.stackModel?.molecules[2].gone = !subHeadline.hasText
|
||||
stack.stackModel?.molecules[3].gone = !body.hasText
|
||||
stack.stackModel?.molecules[4].gone = (link.titleLabel?.text?.count ?? 0) == 0
|
||||
stack.restack()
|
||||
stack.updateContainedMolecules(with: [model.eyebrow,
|
||||
model.headline,
|
||||
model.subHeadline,
|
||||
model.body,
|
||||
model.link],
|
||||
delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
@objcMembers open class ListRVWheel: TableViewCell {
|
||||
let wheel = GraphView(frame: .zero)
|
||||
let wheel = Wheel(frame: .zero)
|
||||
let leftLabel = Label.commonLabelB1(true)
|
||||
let rightLabel = Label.commonLabelB2(true)
|
||||
var stack: Stack<StackModel>
|
||||
|
||||
@ -11,9 +11,9 @@ public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "listRVWheel"
|
||||
public var leftLabel: 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.rightLabel = rightLabel
|
||||
self.wheel = wheel
|
||||
@ -37,7 +37,7 @@ public class ListRVWheelModel: ListItemModel, MoleculeModelProtocol {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel)
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
//
|
||||
// ListThreeColumnDataUsage.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kruthika KP on 20/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers open class ListThreeColumnDataUsage: TableViewCell {
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//-------------------------------------------------------
|
||||
public let leftLabel = Label.createLabelRegularBodySmall(true)
|
||||
public let centerLabel = Label.createLabelRegularBodySmall(true)
|
||||
public let rightLabel = Label.createLabelRegularBodySmall(true)
|
||||
var stack: Stack<StackModel>
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//------------------------------------------------------
|
||||
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
stack = Stack<StackModel>.createStack(with: [(view: leftLabel, model: StackItemModel(percent: 40, horizontalAlignment: .leading)),
|
||||
(view: centerLabel, model: StackItemModel(percent: 37, horizontalAlignment: .leading)),
|
||||
(view: rightLabel, model: StackItemModel(percent: 23, horizontalAlignment: .leading))],
|
||||
axis: .horizontal)
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
addMolecule(stack)
|
||||
stack.restack()
|
||||
}
|
||||
|
||||
// MARK: - ModelMoleculeViewProtocol
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListThreeColumnDataUsageModel else { return }
|
||||
leftLabel.set(with: model.leftLabel, delegateObject, additionalData)
|
||||
centerLabel.set(with: model.centerLabel, delegateObject, additionalData)
|
||||
rightLabel.set(with: model.rightLabel, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 121
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
leftLabel.styleRegularBodySmall(true)
|
||||
centerLabel.styleRegularBodySmall(true)
|
||||
rightLabel.styleRegularBodySmall(true)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
//
|
||||
// ListThreeColumnDataUsageModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kruthika KP on 20/04/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ListThreeColumnDataUsageModel: ListItemModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "list3CDataUsg"
|
||||
public var leftLabel: LabelModel
|
||||
public var centerLabel: LabelModel
|
||||
public var rightLabel: LabelModel
|
||||
|
||||
public init(leftLabel:LabelModel, centerLabel:LabelModel, rightLabel:LabelModel) {
|
||||
self.leftLabel = leftLabel
|
||||
self.centerLabel = centerLabel
|
||||
self.rightLabel = rightLabel
|
||||
super.init()
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case leftLabel
|
||||
case centerLabel
|
||||
case rightLabel
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel)
|
||||
centerLabel = try typeContainer.decode(LabelModel.self, forKey: .centerLabel)
|
||||
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(leftLabel, forKey: .leftLabel)
|
||||
try container.encode(centerLabel, forKey: .centerLabel)
|
||||
try container.encode(rightLabel, forKey: .rightLabel)
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ import Foundation
|
||||
for item in model.sections {
|
||||
stackItems.append(MoleculeStackItemModel(with: item))
|
||||
}
|
||||
let stack = MoleculeStackModel(molecules: stackItems)
|
||||
let stack = StackModel(molecules: stackItems)
|
||||
stack.verticalAlignment = .fill
|
||||
colorLablesStack.set(with: stack, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
@ -9,47 +9,24 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
@objcMembers public class FooterModel: MoleculeContainerModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "footer"
|
||||
public var backgroundColor: Color?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
@objcMembers public class FooterModel: MoleculeContainerModel {
|
||||
public override class var identifier: String {
|
||||
return "footer"
|
||||
}
|
||||
|
||||
/// Defaults to set
|
||||
func setDefaults() {
|
||||
public override func setDefaults() {
|
||||
if useHorizontalMargins == nil {
|
||||
useHorizontalMargins = true
|
||||
}
|
||||
if useVerticalMargins == nil {
|
||||
useVerticalMargins = true
|
||||
}
|
||||
if topMarginPadding == nil {
|
||||
topMarginPadding = PaddingDefaultVerticalSpacing
|
||||
if topPadding == nil {
|
||||
topPadding = PaddingDefaultVerticalSpacing
|
||||
}
|
||||
if bottomMarginPadding == nil {
|
||||
bottomMarginPadding = PaddingDefaultVerticalSpacing
|
||||
if bottomPadding == nil {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,18 +18,18 @@ import Foundation
|
||||
}
|
||||
|
||||
/// Defaults to set
|
||||
public func setDefaults() {
|
||||
public override func setDefaults() {
|
||||
if useHorizontalMargins == nil {
|
||||
useHorizontalMargins = true
|
||||
}
|
||||
if useVerticalMargins == nil {
|
||||
useVerticalMargins = true
|
||||
}
|
||||
if topMarginPadding == nil {
|
||||
topMarginPadding = PaddingDefaultVerticalSpacing
|
||||
if topPadding == nil {
|
||||
topPadding = PaddingDefaultVerticalSpacing
|
||||
}
|
||||
if bottomMarginPadding == nil {
|
||||
bottomMarginPadding = PaddingDefaultVerticalSpacing
|
||||
if bottomPadding == nil {
|
||||
bottomPadding = PaddingDefaultVerticalSpacing
|
||||
}
|
||||
if line == nil {
|
||||
line = LineModel(type: .heavy)
|
||||
@ -38,7 +38,6 @@ import Foundation
|
||||
|
||||
public override init() {
|
||||
super.init()
|
||||
setDefaults()
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
@ -46,7 +45,6 @@ import Foundation
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
setDefaults()
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
|
||||
320
MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift
Normal file
320
MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift
Normal 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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ import UIKit
|
||||
public class TabsModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "tabs"
|
||||
public var backgroundColor: Color?
|
||||
public var tabs: [LabelModel]
|
||||
public var tabs: [TabItemModel]
|
||||
public var selectedColor = Color(uiColor: .mfTomatoRed())
|
||||
|
||||
// Must be capped to 0...(tabs.count - 1)
|
||||
@ -25,13 +25,13 @@ public class TabsModel: MoleculeModelProtocol {
|
||||
case moleculeName
|
||||
}
|
||||
|
||||
public init(with tabs: [LabelModel]) {
|
||||
public init(with tabs: [TabItemModel]) {
|
||||
self.tabs = tabs
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
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)
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor) {
|
||||
selectedColor = color
|
||||
@ -50,3 +50,33 @@ public class TabsModel: MoleculeModelProtocol {
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ import Foundation
|
||||
//--------------------------------------------------
|
||||
|
||||
/// Defaults to set
|
||||
open func setDefaults() {
|
||||
open override func setDefaults() {
|
||||
if useHorizontalMargins == nil {
|
||||
useHorizontalMargins = true
|
||||
}
|
||||
@ -54,9 +54,12 @@ import Foundation
|
||||
// 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() {
|
||||
super.init()
|
||||
setDefaults()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -71,7 +74,6 @@ import Foundation
|
||||
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
|
||||
style = try typeContainer.decodeIfPresent(String.self, forKey: .style)
|
||||
try super.init(from: decoder)
|
||||
setDefaults()
|
||||
}
|
||||
|
||||
open override func encode(to encoder: Encoder) throws {
|
||||
|
||||
@ -9,49 +9,36 @@
|
||||
import Foundation
|
||||
|
||||
/// A model for a collection item that is a container for any molecule.
|
||||
@objcMembers public class MoleculeCollectionItemModel: MoleculeContainerModel, CollectionItemModelProtocol, MoleculeModelProtocol {
|
||||
open class var identifier: String {
|
||||
@objcMembers public class MoleculeCollectionItemModel: MoleculeContainerModel, CollectionItemModelProtocol {
|
||||
open override class var identifier: String {
|
||||
return "collectionItem"
|
||||
}
|
||||
public var backgroundColor: Color?
|
||||
|
||||
/// Defaults to set
|
||||
public func setDefaults() {
|
||||
public override func setDefaults() {
|
||||
if useHorizontalMargins == nil {
|
||||
useHorizontalMargins = true
|
||||
}
|
||||
if useVerticalMargins == nil {
|
||||
useVerticalMargins = true
|
||||
}
|
||||
if topMarginPadding == nil {
|
||||
topMarginPadding = PaddingDefault
|
||||
if topPadding == nil {
|
||||
topPadding = PaddingDefault
|
||||
}
|
||||
if bottomMarginPadding == nil {
|
||||
bottomMarginPadding = PaddingDefault
|
||||
if bottomPadding == nil {
|
||||
bottomPadding = PaddingDefault
|
||||
}
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,6 +54,6 @@ open class MoleculeCollectionViewCell: CollectionViewCell {
|
||||
let height = classType.estimatedHeight(with: model.molecule, delegateObject)
|
||||
else { return 100 }
|
||||
|
||||
return height + (model.topMarginPadding ?? 0) + (model.bottomMarginPadding ?? 0)
|
||||
return height + (model.topPadding ?? 0) + (model.bottomPadding ?? 0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,15 +8,15 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class MoleculeStackItemModel: MoleculeContainerModel, MoleculeModelProtocol, StackItemModelProtocol {
|
||||
public static var identifier: String = "stackItem"
|
||||
public var backgroundColor: Color?
|
||||
@objcMembers public class MoleculeStackItemModel: MoleculeContainerModel, StackItemModelProtocol {
|
||||
public override class var identifier: String {
|
||||
return "stackItem"
|
||||
}
|
||||
public var spacing: CGFloat?
|
||||
public var percent: Int?
|
||||
public var gone: Bool = false
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case spacing
|
||||
case percent
|
||||
case gone
|
||||
@ -39,7 +39,6 @@ import Foundation
|
||||
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(spacing, forKey: .spacing)
|
||||
try container.encodeIfPresent(percent, forKey: .percent)
|
||||
try container.encode(gone, forKey: .gone)
|
||||
|
||||
@ -24,16 +24,17 @@ import Foundation
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
public convenience 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
|
||||
public init(spacing: CGFloat? = nil, percent: Int? = nil, horizontalAlignment: UIStackView.Alignment? = nil, verticalAlignment: UIStackView.Alignment? = nil, gone: Bool? = nil) {
|
||||
self.spacing = spacing
|
||||
self.percent = percent
|
||||
|
||||
if let 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")
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol StackItemModelProtocol: MoleculeModelProtocol {
|
||||
public protocol StackItemModelProtocol {
|
||||
var spacing: CGFloat? { get set }
|
||||
var percent: Int? { get set }
|
||||
var gone: Bool { get set }
|
||||
|
||||
@ -24,8 +24,8 @@ public class TabsListItemModel: ListItemModel, MoleculeModelProtocol {
|
||||
hideArrow = true
|
||||
action = nil
|
||||
style = nil
|
||||
topMarginPadding = 8
|
||||
bottomMarginPadding = 0
|
||||
topPadding = 8
|
||||
bottomPadding = 0
|
||||
}
|
||||
|
||||
public init(with tabs: TabsModel, molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]) {
|
||||
|
||||
@ -12,7 +12,7 @@ import UIKit
|
||||
var tabsListItemModel: TabsListItemModel? {
|
||||
return listItemModel as? TabsListItemModel
|
||||
}
|
||||
let tabs = TopTabbar(frame: .zero)
|
||||
let tabs = Tabs(frame: .zero)
|
||||
var delegateObject: MVMCoreUIDelegateObject?
|
||||
var previousTabIndex = 0
|
||||
|
||||
@ -22,7 +22,6 @@ import UIKit
|
||||
tabs.paddingBeforeFirstTab = false
|
||||
tabs.translatesAutoresizingMaskIntoConstraints = false
|
||||
tabs.delegate = self
|
||||
tabs.datasource = self
|
||||
contentView.addSubview(tabs)
|
||||
|
||||
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]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
self.delegateObject = delegateObject
|
||||
tabs.reloadData()
|
||||
if let tabsModel = tabsListItemModel?.tabs {
|
||||
tabs.set(with: tabsModel, delegateObject, additionalData)
|
||||
}
|
||||
}
|
||||
|
||||
public override func reset() {
|
||||
@ -53,33 +54,22 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
extension TabsTableViewCell: TopTabbarDelegate {
|
||||
public func shouldSelectItem(at index: Int, topTabbar: TopTabbar) -> Bool {
|
||||
extension TabsTableViewCell: TabsDelegate {
|
||||
public func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool {
|
||||
if let model = tabsListItemModel {
|
||||
let molecules = model.molecules[topTabbar.selectedIndex]
|
||||
delegateObject?.moleculeDelegate?.removeMolecules(molecules, animation: index < tabs.selectedIndex ? .right : .left)
|
||||
let molecules = model.molecules[tabs.selectedIndex]
|
||||
delegateObject?.moleculeDelegate?.removeMolecules(molecules, animation: indexPath.row < tabs.selectedIndex ? .right : .left)
|
||||
}
|
||||
previousTabIndex = tabs.selectedIndex
|
||||
return true
|
||||
}
|
||||
|
||||
public func topTabbar(_ topTabbar: TopTabbar, didSelectItemAt index: Int) {
|
||||
guard let model = tabsListItemModel,
|
||||
let indexPath = delegateObject?.moleculeDelegate?.getIndexPath(for: model) else { return }
|
||||
let molecules = model.molecules[index]
|
||||
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"
|
||||
public func didSelectItem(_ indexPath: IndexPath, tabs: Tabs) {
|
||||
let index = indexPath.row
|
||||
if let model = tabsListItemModel, index < model.molecules.count {
|
||||
let molecules = model.molecules[index]
|
||||
delegateObject?.moleculeDelegate?.addMolecules(molecules, indexPath: indexPath, animation: index < previousTabIndex ? .left : .right)
|
||||
}
|
||||
return title
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -164,10 +164,12 @@ import UIKit
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? CornerLabelsModel else { return }
|
||||
if middleView != nil {
|
||||
(middleView as? MoleculeViewProtocol)?.set(with: model, delegateObject, additionalData)
|
||||
} else if let moleculeModel = model.molecule, let molecule = MoleculeObjectMapping.shared()?.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) {
|
||||
addMiddleView(molecule)
|
||||
if let moleculeModel = model.molecule {
|
||||
if middleView != nil {
|
||||
(middleView as? MoleculeViewProtocol)?.set(with: moleculeModel, delegateObject, additionalData)
|
||||
} else if let molecule = MoleculeObjectMapping.shared()?.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) {
|
||||
addMiddleView(molecule)
|
||||
}
|
||||
}
|
||||
|
||||
topLeftLabel.setOptional(with: model.topLeftLabel, delegateObject, additionalData)
|
||||
|
||||
@ -8,11 +8,19 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
|
||||
@objcMembers open class LabelToggle: View {
|
||||
public let label = Label.commonLabelB1(true)
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public let label = Label.createLabelBoldBodySmall(true)
|
||||
public let toggle = Toggle()
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MVMCoreViewProtocol
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
label.updateView(size)
|
||||
@ -21,28 +29,26 @@ import UIKit
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
guard toggle.superview == nil else {
|
||||
return
|
||||
}
|
||||
|
||||
addSubview(label)
|
||||
addSubview(toggle)
|
||||
label.setContentHuggingPriority(UILayoutPriority.required, for: NSLayoutConstraint.Axis.vertical)
|
||||
label.setContentHuggingPriority(.required, for: .vertical)
|
||||
NSLayoutConstraint.pinViews(leftView: label, rightView: toggle, alignTop: false)
|
||||
}
|
||||
|
||||
// MARK:- MoleculeViewProtocol
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
guard let model = model as? LabelToggleModel,
|
||||
let toggleHeight = Toggle.estimatedHeight(with: model.toggle, delegateObject),
|
||||
let labelHeight = Label.estimatedHeight(with: model.label, delegateObject) else { return nil }
|
||||
let labelHeight = Label.estimatedHeight(with: model.label, delegateObject)
|
||||
else { return nil }
|
||||
|
||||
return max(toggleHeight, labelHeight)
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
guard let labelToggleModel = model as? LabelToggleModel else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let labelToggleModel = model as? LabelToggleModel else { return }
|
||||
|
||||
label.set(with: labelToggleModel.label, delegateObject, additionalData)
|
||||
toggle.set(with: labelToggleModel.toggle, delegateObject, additionalData)
|
||||
}
|
||||
@ -52,6 +58,6 @@ import UIKit
|
||||
super.reset()
|
||||
label.reset()
|
||||
toggle.reset()
|
||||
label.styleB1(true)
|
||||
label.styleBoldBodySmall(true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,17 +10,16 @@ import Foundation
|
||||
|
||||
public protocol NavigationItemModelProtocol {
|
||||
var title: String? { get set }
|
||||
var titleView: MoleculeModelProtocol? { get set }
|
||||
var hidden: Bool { get set }
|
||||
var backgroundColor: Color? { get set }
|
||||
var transparent: Bool { get set }
|
||||
var translucent: Bool { get set }
|
||||
var tintColor: Color { get set }
|
||||
var line: LineModel? { get set }
|
||||
var systemBackButton: Bool { get set }
|
||||
var showLeftPanelButton: Bool? { get set }
|
||||
var showRightPanelButton: Bool? { get set }
|
||||
var additionalLeftItems: [NavigationItemButtonModel]? { get set }
|
||||
var additionalRightItems: [NavigationItemButtonModel]? { get set }
|
||||
var showLeftPanelButton: Bool { get set }
|
||||
var showRightPanelButton: Bool { get set }
|
||||
var backButton: NavigationItemButtonModel? { get set }
|
||||
var additionalLeftButtons: [NavigationItemButtonModel]? { get set }
|
||||
var additionalRightButtons: [NavigationItemButtonModel]? { get set }
|
||||
}
|
||||
|
||||
public class NavigationItemButtonModel: Codable {
|
||||
@ -52,74 +51,73 @@ public class NavigationItemButtonModel: Codable {
|
||||
|
||||
public class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtocol {
|
||||
public class var identifier: String {
|
||||
return "navigationItem"
|
||||
return "navigationBar"
|
||||
}
|
||||
|
||||
public var title: String?
|
||||
public var titleView: MoleculeModelProtocol?
|
||||
public var hidden: Bool
|
||||
public var backgroundColor: Color?
|
||||
public var transparent: Bool
|
||||
public var translucent: Bool
|
||||
public var tintColor: Color
|
||||
public var line: LineModel?
|
||||
public var systemBackButton = false
|
||||
public var showLeftPanelButton: Bool?
|
||||
public var showRightPanelButton: Bool?
|
||||
public var additionalLeftItems: [NavigationItemButtonModel]?
|
||||
public var additionalRightItems: [NavigationItemButtonModel]?
|
||||
public var showLeftPanelButton: Bool
|
||||
public var showRightPanelButton: Bool
|
||||
public var backButton: NavigationItemButtonModel?
|
||||
public var additionalLeftButtons: [NavigationItemButtonModel]?
|
||||
public var additionalRightButtons: [NavigationItemButtonModel]?
|
||||
|
||||
init() {
|
||||
public init() {
|
||||
hidden = false
|
||||
transparent = false
|
||||
translucent = false
|
||||
backgroundColor = Color(uiColor: .white)
|
||||
tintColor = Color(uiColor: .black)
|
||||
line = LineModel(type: .standard)
|
||||
showLeftPanelButton = true
|
||||
showRightPanelButton = true
|
||||
backButton = NavigationItemButtonModel(with: "back", action: ActionBackModel())
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case title
|
||||
case titleView
|
||||
case hidden
|
||||
case backgroundColor
|
||||
case transparent
|
||||
case translucent
|
||||
case tintColor
|
||||
case line
|
||||
case systemBackButton
|
||||
case backButton
|
||||
case showLeftPanelButton
|
||||
case showRightPanelButton
|
||||
case additionalLeftItems
|
||||
case additionalRightItems
|
||||
case additionalLeftButtons
|
||||
case additionalRightButtons
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
|
||||
titleView = try typeContainer.decodeModelIfPresent(codingKey: .titleView)
|
||||
hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) ?? false
|
||||
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)
|
||||
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
|
||||
systemBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .systemBackButton) ?? false
|
||||
showLeftPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showLeftPanelButton)
|
||||
showRightPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showRightPanelButton)
|
||||
additionalLeftItems = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalLeftItems)
|
||||
additionalRightItems = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalRightItems)
|
||||
backButton = try typeContainer.decodeIfPresent(NavigationItemButtonModel.self, forKey: .backButton) ?? NavigationItemButtonModel(with: "back", action: ActionBackModel())
|
||||
showLeftPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showLeftPanelButton) ?? true
|
||||
showRightPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showRightPanelButton) ?? true
|
||||
additionalLeftButtons = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalLeftButtons)
|
||||
additionalRightButtons = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalRightButtons)
|
||||
}
|
||||
|
||||
open func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(title, forKey: .title)
|
||||
try container.encodeModelIfPresent(titleView, forKey: .titleView)
|
||||
try container.encode(hidden, forKey: .hidden)
|
||||
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.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(showRightPanelButton, forKey: .showRightPanelButton)
|
||||
try container.encodeIfPresent(additionalLeftItems, forKey: .additionalLeftItems)
|
||||
try container.encodeIfPresent(additionalRightItems, forKey: .additionalRightItems)
|
||||
try container.encodeIfPresent(additionalLeftButtons, forKey: .additionalLeftButtons)
|
||||
try container.encodeIfPresent(additionalRightButtons, forKey: .additionalRightButtons)
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,8 +8,9 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
public class ScrollerModel: MoleculeContainerModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "scroller"
|
||||
public class ScrollerModel: MoleculeContainerModel {
|
||||
public override class var identifier: String {
|
||||
return "scroller"
|
||||
}
|
||||
public var moleculeName: String = ScrollerModel.identifier
|
||||
public var backgroundColor: Color?
|
||||
}
|
||||
|
||||
@ -20,22 +20,21 @@ public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtoc
|
||||
self.headlineBody = headlineBody
|
||||
self.image = image
|
||||
super.init()
|
||||
setDefaults()
|
||||
}
|
||||
|
||||
/// Defaults to set
|
||||
func setDefaults() {
|
||||
public override func setDefaults() {
|
||||
if useHorizontalMargins == nil {
|
||||
useHorizontalMargins = true
|
||||
}
|
||||
if useVerticalMargins == nil {
|
||||
useVerticalMargins = true
|
||||
}
|
||||
if topMarginPadding == nil {
|
||||
topMarginPadding = PaddingDefault
|
||||
if topPadding == nil {
|
||||
topPadding = PaddingDefault
|
||||
}
|
||||
if bottomMarginPadding == nil {
|
||||
bottomMarginPadding = PaddingDefault
|
||||
if bottomPadding == nil {
|
||||
bottomPadding = PaddingDefault
|
||||
}
|
||||
if image.height == nil {
|
||||
image.height = BGImageHeadlineBodyButton.heightConstant
|
||||
@ -59,7 +58,6 @@ public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtoc
|
||||
image = try typeContainer.decode(ImageViewModel.self, forKey: .image)
|
||||
button = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .button)
|
||||
try super.init(from: decoder)
|
||||
setDefaults()
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
|
||||
@ -33,6 +33,7 @@ import UIKit
|
||||
stack.stackModel?.spacing = 0
|
||||
addSubview(stack)
|
||||
NSLayoutConstraint.constraintPinSubview(toSuperview: stack)
|
||||
stack.restack()
|
||||
}
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
@ -58,18 +59,11 @@ import UIKit
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
|
||||
eyebrow.setOptional(with: castModel?.eyebrow, delegateObject, additionalData)
|
||||
headline.setOptional(with: castModel?.headline, delegateObject, additionalData)
|
||||
body.setOptional(with: castModel?.body, delegateObject, additionalData)
|
||||
link.setOptional(with: castModel?.link, delegateObject, additionalData)
|
||||
|
||||
// Hide labels if neeeded.
|
||||
stack.stackModel?.molecules[0].gone = !eyebrow.hasText
|
||||
stack.stackModel?.molecules[1].gone = !headline.hasText
|
||||
stack.stackModel?.molecules[2].gone = !body.hasText
|
||||
stack.stackModel?.molecules[3].gone = (link.titleLabel?.text?.count ?? 0) == 0
|
||||
stack.restack()
|
||||
stack.updateContainedMolecules(with: [castModel?.eyebrow,
|
||||
castModel?.headline,
|
||||
castModel?.body,
|
||||
castModel?.link],
|
||||
delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
|
||||
@ -19,22 +19,21 @@ public class HeadlineBodyCaretLinkImageModel: ContainerModel, MoleculeModelProto
|
||||
self.headlineBody = headlineBody
|
||||
self.image = image
|
||||
super.init()
|
||||
setDefaults()
|
||||
}
|
||||
|
||||
/// Defaults to set
|
||||
func setDefaults() {
|
||||
public override func setDefaults() {
|
||||
if useHorizontalMargins == nil {
|
||||
useHorizontalMargins = true
|
||||
}
|
||||
if useVerticalMargins == nil {
|
||||
useVerticalMargins = true
|
||||
}
|
||||
if topMarginPadding == nil {
|
||||
topMarginPadding = PaddingDefault
|
||||
if topPadding == nil {
|
||||
topPadding = PaddingDefault
|
||||
}
|
||||
if bottomMarginPadding == nil {
|
||||
bottomMarginPadding = PaddingDefault
|
||||
if bottomPadding == nil {
|
||||
bottomPadding = PaddingDefault
|
||||
}
|
||||
if image.height == nil {
|
||||
image.height = HeadLineBodyCaretLinkImage.heightConstant
|
||||
@ -56,7 +55,6 @@ public class HeadlineBodyCaretLinkImageModel: ContainerModel, MoleculeModelProto
|
||||
image = try typeContainer.decode(ImageViewModel.self, forKey: .image)
|
||||
caretLink = try typeContainer.decodeIfPresent(CaretLinkModel.self, forKey: .caretLink)
|
||||
try super.init(from: decoder)
|
||||
setDefaults()
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class NumberedListModel: MoleculeStackModel {
|
||||
@objcMembers public class NumberedListModel: StackModel {
|
||||
public override class var identifier: String {
|
||||
return "numberedList"
|
||||
}
|
||||
@ -28,8 +28,7 @@ import Foundation
|
||||
for (index, molecule) in list.enumerated() {
|
||||
models.append(MoleculeStackItemModel(with: StringAndMoleculeModel(string: "\(index+1).", molecule: molecule)))
|
||||
}
|
||||
super.init(molecules: models)
|
||||
spacing = 0
|
||||
super.init(molecules: models, spacing: 0)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
@ -39,7 +38,7 @@ import Foundation
|
||||
|
||||
var models: [MoleculeModelProtocol] = []
|
||||
for molecule in molecules {
|
||||
models.append(molecule.molecule)
|
||||
models.append(((molecule as! MoleculeStackItemModel).molecule as! StringAndMoleculeModel).molecule)
|
||||
}
|
||||
try container.encodeModels(models, forKey: .list)
|
||||
}
|
||||
|
||||
@ -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.
|
||||
open class StringAndMoleculeStack: MoleculeStackView {
|
||||
override open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
guard let model = stackModel else { return }
|
||||
for stackItemModel in model.molecules {
|
||||
guard let model = model as? StackModelProtocol,
|
||||
let molcules = model.molecules as? [MoleculeStackItemModel] else { return }
|
||||
for stackItemModel in molcules {
|
||||
guard let stringAndMoleculeModel = stackItemModel.molecule as? StringAndMoleculeModel,
|
||||
let molecule = MoleculeObjectMapping.shared()?.createMolecule(stringAndMoleculeModel.molecule, delegateObject: delegateObject
|
||||
, additionalData: additionalData) else {
|
||||
|
||||
@ -10,7 +10,6 @@ import Foundation
|
||||
|
||||
open class StringAndMoleculeView: View {
|
||||
var label = Label.commonLabelB2(true)
|
||||
var string: String
|
||||
var molecule: MoleculeViewProtocol
|
||||
|
||||
var leftWidthConstraint: NSLayoutConstraint?
|
||||
@ -28,7 +27,7 @@ open class StringAndMoleculeView: View {
|
||||
|
||||
// MARK: - Inits
|
||||
public init(string: String, molecule: MoleculeViewProtocol) {
|
||||
self.string = string
|
||||
self.label.text = string
|
||||
self.molecule = molecule
|
||||
super.init(frame: .zero)
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class UnOrderedListModel: MoleculeStackModel {
|
||||
@objcMembers public class UnOrderedListModel: StackModel {
|
||||
public override class var identifier: String {
|
||||
return "unOrderedList"
|
||||
}
|
||||
@ -33,8 +33,7 @@ import Foundation
|
||||
for molecule in list {
|
||||
models.append(MoleculeStackItemModel(with: StringAndMoleculeModel(string: bulletChar, molecule: molecule)))
|
||||
}
|
||||
super.init(molecules: models)
|
||||
spacing = 0
|
||||
super.init(molecules: models, spacing: 0)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
@ -45,7 +44,7 @@ import Foundation
|
||||
|
||||
var models: [MoleculeModelProtocol] = []
|
||||
for molecule in molecules {
|
||||
models.append(molecule.molecule)
|
||||
models.append(((molecule as! MoleculeStackItemModel).molecule as! StringAndMoleculeModel).molecule)
|
||||
}
|
||||
try container.encodeModels(models, forKey: .list)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -5,13 +5,12 @@
|
||||
// Created by Scott Pfeil on 2/11/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
// This is a dynamic stack view that creates molecules if needed on set.
|
||||
|
||||
import UIKit
|
||||
|
||||
open class MoleculeStackView: Stack<MoleculeStackModel> {
|
||||
open override var stackModel: MoleculeStackModel? {
|
||||
get { return model as? MoleculeStackModel }
|
||||
}
|
||||
open class MoleculeStackView: Stack<StackModel> {
|
||||
var previousModel: MoleculeModelProtocol?
|
||||
|
||||
/// Convenience function, adds a molecule to a MoleculeStackItem to the MoleculeStack
|
||||
func setup(with views: [View], lastItem: Bool) {
|
||||
@ -26,14 +25,16 @@ open class MoleculeStackView: Stack<MoleculeStackModel> {
|
||||
if let stackModel = stackModel {
|
||||
stackModel.molecules = models
|
||||
} else {
|
||||
model = MoleculeStackModel(molecules: models)
|
||||
model = StackModel(molecules: models)
|
||||
}
|
||||
restack()
|
||||
}
|
||||
|
||||
|
||||
|
||||
// MARK: - Adding to stack
|
||||
/// Creates all of the stackItems for the stackItemModels
|
||||
override open func createStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
/// 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]?) {
|
||||
guard let stackItemModels = stackModel?.molecules else { return }
|
||||
for model in stackItemModels {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
//--------------------------------------------------
|
||||
@ -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]?) {
|
||||
let previousModel = self.model
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
removeAllItemViews()
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
setStackItemsFromModel(model, delegateObject, additionalData)
|
||||
restack()
|
||||
}
|
||||
|
||||
@ -216,9 +232,6 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
|
||||
// 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
|
||||
open func setStackItemsFromModel(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
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.
|
||||
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 }
|
||||
var stackItems: [StackItem] = []
|
||||
var models: [T.AnyStackItemModel] = []
|
||||
var models: [StackItemModel] = []
|
||||
for item in viewModels {
|
||||
stackItems.append(StackItem(andContain: item.view))
|
||||
models.append(item.model)
|
||||
@ -307,7 +320,7 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
|
||||
if let percent = model.percent {
|
||||
let multiplier = CGFloat(percent) / 100.0
|
||||
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 {
|
||||
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 {
|
||||
let multiplier = CGFloat(percent) / 100.0
|
||||
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 {
|
||||
pinView(contentView, toView: view, attribute: .right, relation: .equal, priority: .required, constant: 0)
|
||||
|
||||
@ -8,17 +8,19 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class StackModel: StackModelProtocol, MoleculeModelProtocol {
|
||||
@objcMembers public class StackModel: ContainerModel, StackModelProtocol, MoleculeModelProtocol {
|
||||
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 molecules: [StackItemModel]
|
||||
public var molecules: [StackItemModelProtocol & MoleculeModelProtocol]
|
||||
public var axis: NSLayoutConstraint.Axis = .vertical
|
||||
public var spacing: CGFloat = StackModel.defaultSpacing
|
||||
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
|
||||
if let axis = axis {
|
||||
self.axis = axis
|
||||
@ -26,6 +28,7 @@ import Foundation
|
||||
if let spacing = spacing {
|
||||
self.spacing = spacing
|
||||
}
|
||||
super.init()
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
@ -38,21 +41,24 @@ import Foundation
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
molecules = try typeContainer.decode([StackItemModel].self, forKey: .molecules)
|
||||
molecules = try typeContainer.decodeModels(codingKey: .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
|
||||
}
|
||||
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)
|
||||
try container.encodeIfPresent(molecules, forKey: .molecules)
|
||||
try container.encodeModels(molecules, forKey: .molecules)
|
||||
try container.encodeIfPresent(axis.rawValueString, forKey: .axis)
|
||||
try container.encodeIfPresent(spacing, forKey: .spacing)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,9 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
public protocol StackModelProtocol {
|
||||
associatedtype AnyStackItemModel: StackItemModelProtocol
|
||||
|
||||
var molecules: [AnyStackItemModel] { get set }
|
||||
var molecules: [StackItemModelProtocol & MoleculeModelProtocol] { get set }
|
||||
var axis: NSLayoutConstraint.Axis { get set }
|
||||
var spacing: CGFloat { get set }
|
||||
var useStackSpacingBeforeFirstItem: Bool { get set }
|
||||
|
||||
@ -11,10 +11,12 @@ import Foundation
|
||||
|
||||
public protocol ContainerModelProtocol {
|
||||
var horizontalAlignment: UIStackView.Alignment? { get set }
|
||||
var verticalAlignment: UIStackView.Alignment? { 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 topMarginPadding: CGFloat? { get set }
|
||||
var bottomMarginPadding: CGFloat? { get set }
|
||||
var topPadding: CGFloat? { get set }
|
||||
var bottomPadding: CGFloat? { get set }
|
||||
}
|
||||
|
||||
@ -12,5 +12,6 @@ public protocol PageModelProtocol {
|
||||
var pageType: String { get set }
|
||||
/// Temporary: for legacy response
|
||||
var screenHeading: String? { get set }
|
||||
var backgroundColor: Color? { get set }
|
||||
var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)? { get set }
|
||||
}
|
||||
|
||||
@ -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 }
|
||||
}
|
||||
@ -22,5 +22,8 @@ public extension TemplateProtocol where Self: ViewController {
|
||||
let templateModel = try decoder.decode(TemplateModel.self, from: data)
|
||||
self.templateModel = templateModel
|
||||
self.pageModel = templateModel as? MVMControllerModelProtocol
|
||||
if let backgroundColor = templateModel.backgroundColor {
|
||||
view.backgroundColor = backgroundColor.uiColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,6 +79,8 @@ import Foundation
|
||||
|
||||
|
||||
open override func handleNewData() {
|
||||
topViewOutsideOfScrollArea = templateModel?.anchorHeader ?? false
|
||||
bottomViewOutsideOfScrollArea = templateModel?.anchorFooter ?? false
|
||||
setup()
|
||||
registerCells()
|
||||
super.handleNewData()
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class CollectionTemplateModel: TemplateModel {
|
||||
@objcMembers public class CollectionTemplateModel: ThreeLayerModelBase {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -16,9 +16,7 @@ import Foundation
|
||||
public override class var identifier: String {
|
||||
return "collection"
|
||||
}
|
||||
public var header: MoleculeModelProtocol?
|
||||
public var molecules: [CollectionItemModelProtocol & MoleculeModelProtocol]?
|
||||
public var footer: MoleculeModelProtocol?
|
||||
public var columns: Int?
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -37,8 +35,6 @@ import Foundation
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case molecules
|
||||
case header
|
||||
case footer
|
||||
case columns
|
||||
}
|
||||
|
||||
@ -49,8 +45,6 @@ import Foundation
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
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)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
@ -59,8 +53,6 @@ import Foundation
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeModelsIfPresent(molecules, forKey: .molecules)
|
||||
try container.encodeModelIfPresent(header, forKey: .header)
|
||||
try container.encodeModelIfPresent(footer, forKey: .footer)
|
||||
try container.encodeIfPresent(columns, forKey: .columns)
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class ListPageTemplateModel: TemplateModel {
|
||||
@objcMembers public class ListPageTemplateModel: ThreeLayerModelBase {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -16,9 +16,7 @@ import Foundation
|
||||
public override class var identifier: String {
|
||||
return "list"
|
||||
}
|
||||
public var header: MoleculeModelProtocol?
|
||||
public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]?
|
||||
public var footer: MoleculeModelProtocol?
|
||||
public var line: LineModel?
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -37,8 +35,6 @@ import Foundation
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case molecules
|
||||
case header
|
||||
case footer
|
||||
case line
|
||||
}
|
||||
|
||||
@ -49,8 +45,6 @@ import Foundation
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
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)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
@ -59,8 +53,6 @@ import Foundation
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeModelsIfPresent(molecules, forKey: .molecules)
|
||||
try container.encodeModelIfPresent(header, forKey: .header)
|
||||
try container.encodeModelIfPresent(footer, forKey: .footer)
|
||||
try container.encode(line, forKey: .line)
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,6 +81,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
}
|
||||
|
||||
open override func handleNewData() {
|
||||
topViewOutsideOfScrollArea = templateModel?.anchorHeader ?? false
|
||||
bottomViewOutsideOfScrollArea = templateModel?.anchorFooter ?? false
|
||||
setup()
|
||||
registerWithTable()
|
||||
super.handleNewData()
|
||||
|
||||
@ -11,6 +11,12 @@ import UIKit
|
||||
open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol {
|
||||
var observer: NSKeyValueObservation?
|
||||
public var templateModel: StackPageTemplateModel?
|
||||
|
||||
open override func handleNewData() {
|
||||
topViewOutsideOfScroll = templateModel?.anchorHeader ?? false
|
||||
bottomViewOutsideOfScroll = templateModel?.anchorFooter ?? false
|
||||
super.handleNewData()
|
||||
}
|
||||
|
||||
open override func parsePageJSON() throws {
|
||||
try parseTemplate(json: loadObject?.pageJSON)
|
||||
|
||||
@ -9,31 +9,24 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
@objcMembers public class StackPageTemplateModel: TemplateModel {
|
||||
@objcMembers public class StackPageTemplateModel: ThreeLayerModelBase {
|
||||
public override class var identifier: String {
|
||||
return "stack"
|
||||
}
|
||||
|
||||
public var header: MoleculeModelProtocol?
|
||||
public var moleculeStack: MoleculeStackModel
|
||||
public var footer: MoleculeModelProtocol?
|
||||
public var moleculeStack: StackModel
|
||||
|
||||
public init(pageType: String, moleculeStack: MoleculeStackModel) {
|
||||
public init(pageType: String, moleculeStack: StackModel) {
|
||||
self.moleculeStack = moleculeStack
|
||||
super.init(pageType: pageType)
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case header
|
||||
case footer
|
||||
case stack
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
moleculeStack = try typeContainer.decode(MoleculeStackModel.self, forKey: .stack)
|
||||
header = try typeContainer.decodeModelIfPresent(codingKey: .header)
|
||||
footer = try typeContainer.decodeModelIfPresent(codingKey: .footer)
|
||||
moleculeStack = try typeContainer.decode(StackModel.self, forKey: .stack)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
@ -41,7 +34,5 @@ import Foundation
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeStack, forKey: .stack)
|
||||
try container.encodeModelIfPresent(header, forKey: .header)
|
||||
try container.encodeModelIfPresent(footer, forKey: .footer)
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ import Foundation
|
||||
// Although this is done in the extension, it is needed for the encoding.
|
||||
return Self.identifier
|
||||
}
|
||||
public var backgroundColor: Color?
|
||||
public var screenHeading: String?
|
||||
public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)?
|
||||
public var formRules: [FormGroupRule]?
|
||||
@ -29,6 +30,7 @@ import Foundation
|
||||
case pageType
|
||||
case template
|
||||
case screenHeading
|
||||
case backgroundColor
|
||||
case formRules
|
||||
case navigationItem
|
||||
}
|
||||
@ -37,6 +39,7 @@ import Foundation
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
pageType = try typeContainer.decode(String.self, forKey: .pageType)
|
||||
screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
formRules = try typeContainer.decodeIfPresent([FormGroupRule].self, forKey: .formRules)
|
||||
navigationItem = try typeContainer.decodeModelIfPresent(codingKey: .navigationItem)
|
||||
}
|
||||
@ -45,6 +48,7 @@ import Foundation
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(pageType, forKey: .pageType)
|
||||
try container.encode(template, forKey: .template)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(screenHeading, forKey: .screenHeading)
|
||||
try container.encodeIfPresent(formRules, forKey: .formRules)
|
||||
try container.encodeModelIfPresent(navigationItem, forKey: .navigationItem)
|
||||
|
||||
15
MVMCoreUI/Atomic/Templates/ThreeLayerCenterTemplate.swift
Normal file
15
MVMCoreUI/Atomic/Templates/ThreeLayerCenterTemplate.swift
Normal 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
|
||||
}
|
||||
}
|
||||
@ -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
Loading…
Reference in New Issue
Block a user