Merge branch 'develop' into bugfix/focusStuckIssue

This commit is contained in:
Keerthy 2023-11-01 13:46:09 +05:30
commit fe40639a19
42 changed files with 608 additions and 867 deletions

View File

@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 52; objectVersion = 54;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
@ -289,12 +289,15 @@
AF766D262A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF766D252A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift */; }; AF766D262A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF766D252A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift */; };
AF7E509829E477C1009DC2AD /* AlertHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E509629E477C0009DC2AD /* AlertHandler.swift */; }; AF7E509829E477C1009DC2AD /* AlertHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E509629E477C0009DC2AD /* AlertHandler.swift */; };
AF7E509929E477C1009DC2AD /* AlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E509729E477C0009DC2AD /* AlertController.swift */; }; AF7E509929E477C1009DC2AD /* AlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E509729E477C0009DC2AD /* AlertController.swift */; };
AF8118302AB39B0900FAD1BA /* RawRepresentableCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF81182F2AB39B0900FAD1BA /* RawRepresentableCodable.swift */; };
AFA4932029E5CA73001A9663 /* AlertOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4931F29E5CA73001A9663 /* AlertOperation.swift */; }; AFA4932029E5CA73001A9663 /* AlertOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4931F29E5CA73001A9663 /* AlertOperation.swift */; };
AFA4932229E5EF2E001A9663 /* NotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4932129E5EF2E001A9663 /* NotificationHandler.swift */; }; AFA4932229E5EF2E001A9663 /* NotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4932129E5EF2E001A9663 /* NotificationHandler.swift */; };
AFA4933F29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4933E29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift */; }; AFA4933F29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4933E29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift */; };
AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */; }; AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */; };
AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */; }; AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */; };
AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */; }; AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */; };
B4CC8FBF29DF34730005D28B /* BadgeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBE29DF34730005D28B /* BadgeModel.swift */; };
B4CC8FBD29DF34680005D28B /* Badge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBC29DF34680005D28B /* Badge.swift */; };
BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; }; BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; };
BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; }; BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; };
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */; }; BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */; };
@ -571,8 +574,8 @@
EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; }; EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; };
EA7E67742758310500ABF773 /* EnableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */; }; EA7E67742758310500ABF773 /* EnableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */; };
EA7E67762758365300ABF773 /* UIUpdatableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */; }; EA7E67762758365300ABF773 /* UIUpdatableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */; };
EA985C3E2970938F00F2FF2E /* Tilelet.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3D2970938F00F2FF2E /* Tilelet.swift */; };
EA985C402970939A00F2FF2E /* TileletModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3F2970939A00F2FF2E /* TileletModel.swift */; }; EA985C402970939A00F2FF2E /* TileletModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3F2970939A00F2FF2E /* TileletModel.swift */; };
EA985C3E2970938F00F2FF2E /* Tilelet.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3D2970938F00F2FF2E /* Tilelet.swift */; };
EA985C602970A3F000F2FF2E /* VDS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C5F2970A3F000F2FF2E /* VDS.framework */; }; EA985C602970A3F000F2FF2E /* VDS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C5F2970A3F000F2FF2E /* VDS.framework */; };
EA985C642970A40E00F2FF2E /* VDSTypographyTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C632970A40E00F2FF2E /* VDSTypographyTokens.xcframework */; }; EA985C642970A40E00F2FF2E /* VDSTypographyTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C632970A40E00F2FF2E /* VDSTypographyTokens.xcframework */; };
EA985C852981AA9C00F2FF2E /* VDS-Enums+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C842981AA9C00F2FF2E /* VDS-Enums+Codable.swift */; }; EA985C852981AA9C00F2FF2E /* VDS-Enums+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C842981AA9C00F2FF2E /* VDS-Enums+Codable.swift */; };
@ -587,6 +590,7 @@
EAB14BC327D9378D0012AB2C /* RuleAnyModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */; }; EAB14BC327D9378D0012AB2C /* RuleAnyModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */; };
EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC1402763BB8D00E78B40 /* FormLabel.swift */; }; EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC1402763BB8D00E78B40 /* FormLabel.swift */; };
EABFC152276913E800E78B40 /* FormLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC151276913E800E78B40 /* FormLabelModel.swift */; }; EABFC152276913E800E78B40 /* FormLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC151276913E800E78B40 /* FormLabelModel.swift */; };
EACCF38C2ABB346700E0F104 /* VDS-Interpreters.swift in Sources */ = {isa = PBXBuildFile; fileRef = EACCF38B2ABB346700E0F104 /* VDS-Interpreters.swift */; };
FD99130028E21E4900542CC3 /* RuleNotEqualsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */; }; FD99130028E21E4900542CC3 /* RuleNotEqualsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@ -875,12 +879,15 @@
AF766D252A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAccessibilityTraits+Codable.swift"; sourceTree = "<group>"; }; AF766D252A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAccessibilityTraits+Codable.swift"; sourceTree = "<group>"; };
AF7E509629E477C0009DC2AD /* AlertHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertHandler.swift; sourceTree = "<group>"; }; AF7E509629E477C0009DC2AD /* AlertHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertHandler.swift; sourceTree = "<group>"; };
AF7E509729E477C0009DC2AD /* AlertController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertController.swift; sourceTree = "<group>"; }; AF7E509729E477C0009DC2AD /* AlertController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertController.swift; sourceTree = "<group>"; };
AF81182F2AB39B0900FAD1BA /* RawRepresentableCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RawRepresentableCodable.swift; sourceTree = "<group>"; };
AFA4931F29E5CA73001A9663 /* AlertOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertOperation.swift; sourceTree = "<group>"; }; AFA4931F29E5CA73001A9663 /* AlertOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertOperation.swift; sourceTree = "<group>"; };
AFA4932129E5EF2E001A9663 /* NotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationHandler.swift; sourceTree = "<group>"; }; AFA4932129E5EF2E001A9663 /* NotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationHandler.swift; sourceTree = "<group>"; };
AFA4933E29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingDelegateProtocol.swift; sourceTree = "<group>"; }; AFA4933E29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingDelegateProtocol.swift; sourceTree = "<group>"; };
AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertDelegateProtocol.swift; sourceTree = "<group>"; }; AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertDelegateProtocol.swift; sourceTree = "<group>"; };
AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSColorTokens.xcframework; path = ../SharedFrameworks/VDSColorTokens.xcframework; sourceTree = "<group>"; }; AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSColorTokens.xcframework; path = ../SharedFrameworks/VDSColorTokens.xcframework; sourceTree = "<group>"; };
AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = "<group>"; }; AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = "<group>"; };
B4CC8FBE29DF34730005D28B /* BadgeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeModel.swift; sourceTree = "<group>"; };
B4CC8FBC29DF34680005D28B /* Badge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Badge.swift; sourceTree = "<group>"; };
BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewLeftAlignedLayout.swift; sourceTree = "<group>"; }; BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewLeftAlignedLayout.swift; sourceTree = "<group>"; };
BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.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>"; }; BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMedium.swift; sourceTree = "<group>"; };
@ -1174,6 +1181,7 @@
EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyModelProtocol.swift; sourceTree = "<group>"; }; EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyModelProtocol.swift; sourceTree = "<group>"; };
EABFC1402763BB8D00E78B40 /* FormLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabel.swift; sourceTree = "<group>"; }; EABFC1402763BB8D00E78B40 /* FormLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabel.swift; sourceTree = "<group>"; };
EABFC151276913E800E78B40 /* FormLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabelModel.swift; sourceTree = "<group>"; }; EABFC151276913E800E78B40 /* FormLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabelModel.swift; sourceTree = "<group>"; };
EACCF38B2ABB346700E0F104 /* VDS-Interpreters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VDS-Interpreters.swift"; sourceTree = "<group>"; };
FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleNotEqualsModel.swift; sourceTree = "<group>"; }; FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleNotEqualsModel.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@ -2152,6 +2160,7 @@
D29DF2A821E7B2F9003B2FB9 /* MVMCoreUIConstants.m */, D29DF2A821E7B2F9003B2FB9 /* MVMCoreUIConstants.m */,
0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */, 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */,
0AF60F0826B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift */, 0AF60F0826B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift */,
AF81182F2AB39B0900FAD1BA /* RawRepresentableCodable.swift */,
); );
path = Utility; path = Utility;
sourceTree = "<group>"; sourceTree = "<group>";
@ -2215,8 +2224,10 @@
AA37CBD42519072F0027344C /* Stars.swift */, AA37CBD42519072F0027344C /* Stars.swift */,
AA07EA902510A442009A2AE3 /* StarModel.swift */, AA07EA902510A442009A2AE3 /* StarModel.swift */,
AA07EA922510A451009A2AE3 /* Star.swift */, AA07EA922510A451009A2AE3 /* Star.swift */,
EA985C3D2970938F00F2FF2E /* Tilelet.swift */, B4CC8FBE29DF34730005D28B /* BadgeModel.swift */,
B4CC8FBC29DF34680005D28B /* Badge.swift */,
EA985C3F2970939A00F2FF2E /* TileletModel.swift */, EA985C3F2970939A00F2FF2E /* TileletModel.swift */,
EA985C3D2970938F00F2FF2E /* Tilelet.swift */,
); );
path = Views; path = Views;
sourceTree = "<group>"; sourceTree = "<group>";
@ -2415,6 +2426,7 @@
011B58EE23A2AA850085F53C /* ModelProtocols */, 011B58EE23A2AA850085F53C /* ModelProtocols */,
27559EFB27D691D3000836C1 /* ViewMaskingProtocol.swift */, 27559EFB27D691D3000836C1 /* ViewMaskingProtocol.swift */,
EAA7801F290081320057DFDF /* VDSMoleculeViewProtocol.swift */, EAA7801F290081320057DFDF /* VDSMoleculeViewProtocol.swift */,
EACCF38B2ABB346700E0F104 /* VDS-Interpreters.swift */,
); );
path = Protocols; path = Protocols;
sourceTree = "<group>"; sourceTree = "<group>";
@ -2746,6 +2758,7 @@
0AE98BAF23FEF956004C5109 /* ExternalLink.swift in Sources */, 0AE98BAF23FEF956004C5109 /* ExternalLink.swift in Sources */,
012A88C4238D86E600FE3DA1 /* CarouselItemModelProtocol.swift in Sources */, 012A88C4238D86E600FE3DA1 /* CarouselItemModelProtocol.swift in Sources */,
D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */, D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */,
AF8118302AB39B0900FAD1BA /* RawRepresentableCodable.swift in Sources */,
94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */, 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */,
D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */, D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */,
52B201D324081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift in Sources */, 52B201D324081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift in Sources */,
@ -2916,6 +2929,7 @@
27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */, 27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */,
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */,
526A265E240D200500B0D828 /* ListTwoColumnCompareChanges.swift in Sources */, 526A265E240D200500B0D828 /* ListTwoColumnCompareChanges.swift in Sources */,
B4CC8FBD29DF34680005D28B /* Badge.swift in Sources */,
8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */, 8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */,
3265B30224BCA737000D154B /* HeadersH1NoButtonsBodyTextModel.swift in Sources */, 3265B30224BCA737000D154B /* HeadersH1NoButtonsBodyTextModel.swift in Sources */,
D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */, D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */,
@ -2972,6 +2986,7 @@
D28BA741248025A300B75CB8 /* TabBarModel.swift in Sources */, D28BA741248025A300B75CB8 /* TabBarModel.swift in Sources */,
D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */, D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */,
D2A92882241AAB67004E01C6 /* ScrollingViewController.swift in Sources */, D2A92882241AAB67004E01C6 /* ScrollingViewController.swift in Sources */,
EACCF38C2ABB346700E0F104 /* VDS-Interpreters.swift in Sources */,
C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */, C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */,
0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */, 0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */,
D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */, D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */,
@ -3023,6 +3038,7 @@
22B678F929E7944E00CF4196 /* GetNotificationAuthStatusBehavior.swift in Sources */, 22B678F929E7944E00CF4196 /* GetNotificationAuthStatusBehavior.swift in Sources */,
BB2FB3BB247E7EBC00DF73CD /* TagCollectionViewCell.swift in Sources */, BB2FB3BB247E7EBC00DF73CD /* TagCollectionViewCell.swift in Sources */,
012A88C6238DA34000FE3DA1 /* ModuleMoleculeModel.swift in Sources */, 012A88C6238DA34000FE3DA1 /* ModuleMoleculeModel.swift in Sources */,
B4CC8FBF29DF34730005D28B /* BadgeModel.swift in Sources */,
94C2D9A123872BCC0006CF46 /* LabelAttributeUnderlineModel.swift in Sources */, 94C2D9A123872BCC0006CF46 /* LabelAttributeUnderlineModel.swift in Sources */,
EA985C852981AA9C00F2FF2E /* VDS-Enums+Codable.swift in Sources */, EA985C852981AA9C00F2FF2E /* VDS-Enums+Codable.swift in Sources */,
AAB8549824DC01BD00477C40 /* ListThreeColumnBillHistoryDividerModel.swift in Sources */, AAB8549824DC01BD00477C40 /* ListThreeColumnBillHistoryDividerModel.swift in Sources */,

View File

@ -8,10 +8,11 @@
import UIKit import UIKit
import VDSColorTokens import VDSColorTokens
import VDS
import MVMCore
public typealias FacadeElements = (fill: UIColor?, text: UIColor?, border: UIColor?) public typealias FacadeElements = (fill: UIColor?, text: UIColor?, border: UIColor?)
open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol { open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
@ -26,53 +27,11 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
public var action: ActionModelProtocol public var action: ActionModelProtocol
public var enabled: Bool = true public var enabled: Bool = true
public var width: CGFloat? public var width: CGFloat?
public var style: Styler.Button.Style? { public var style: Use = .primary
didSet { public var size: VDS.Button.Size = .large
guard let style = style else { return }
setFacade(by: style)
}
}
public var size: Styler.Button.Size? = .standard
public var groupName: String = "" public var groupName: String = ""
public var inverted: Bool = false public var inverted: Bool = false
public var backgroundColor: Color?
public lazy var enabledColors: FacadeElements = (fill: enabled_fillColor(),
text: enabled_textColor(),
border: enabled_borderColor())
public lazy var disabledColors: FacadeElements = (fill: disabled_fillColor(),
text: disabled_textColor(),
border: disabled_borderColor())
public var enabledFillColor: Color?
public var enabledTextColor: Color?
public var enabledBorderColor: Color?
public var enabledFillColor_inverted: Color?
public var enabledTextColor_inverted: Color?
public var enabledBorderColor_inverted: Color?
public var disabledFillColor: Color?
public var disabledTextColor: Color?
public var disabledBorderColor: Color?
public var disabledFillColor_inverted: Color?
public var disabledTextColor_inverted: Color?
public var disabledBorderColor_inverted: Color?
private var _backgroundColor: Color?
public var backgroundColor: Color? {
get {
if let backgroundColor = _backgroundColor { return backgroundColor }
if inverted {
return enabled ? enabledFillColor_inverted : disabledFillColor_inverted
}
return enabled ? enabledFillColor : disabledFillColor
}
set {
_backgroundColor = newValue
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Methods // MARK: - Methods
@ -87,88 +46,18 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
public init(with title: String, action: ActionModelProtocol) { public init(with title: String, action: ActionModelProtocol) {
self.title = title self.title = title
self.action = action self.action = action
setFacade(by: .primary)
} }
public init(secondaryButtonWith title: String, action: ActionModelProtocol) { public init(secondaryButtonWith title: String, action: ActionModelProtocol) {
self.title = title self.title = title
self.action = action self.action = action
style = .secondary style = .secondary
setFacade(by: .secondary)
} }
public init(primaryButtonWith title: String, action: ActionModelProtocol) { public init(primaryButtonWith title: String, action: ActionModelProtocol) {
self.title = title self.title = title
self.action = action self.action = action
style = .primary style = .primary
setFacade(by: .primary)
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
public func enabled_fillColor() -> UIColor? {
(inverted ? enabledFillColor_inverted : enabledFillColor)?.uiColor
}
public func enabled_textColor() -> UIColor? {
(inverted ? enabledTextColor_inverted : enabledTextColor)?.uiColor
}
public func enabled_borderColor() -> UIColor? {
(inverted ? enabledBorderColor_inverted : enabledBorderColor)?.uiColor
}
public func disabled_fillColor() -> UIColor? {
(inverted ? disabledFillColor_inverted : disabledFillColor)?.uiColor
}
public func disabled_textColor() -> UIColor? {
(inverted ? disabledTextColor_inverted : disabledTextColor)?.uiColor
}
public func disabled_borderColor() -> UIColor? {
(inverted ? disabledBorderColor_inverted : disabledBorderColor)?.uiColor
}
/// Defines the default appearance for the primary style.
func setPrimaryFacade() {
enabledFillColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
enabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOndark)
disabledFillColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
disabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOndark)
enabledFillColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
enabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOnlight)
disabledFillColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
disabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
/// Defines the default appearance for the Secondary style.
func setSecondaryFacade() {
enabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
enabledFillColor = Color(uiColor: UIColor.clear)
enabledBorderColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
disabledTextColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
disabledBorderColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
enabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
enabledFillColor_inverted = Color(uiColor: UIColor.clear)
enabledBorderColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
disabledTextColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
disabledBorderColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
}
public func setFacade(by style: Styler.Button.Style) {
switch style {
case .primary:
setPrimaryFacade()
case .secondary:
setSecondaryFacade()
}
} }
//-------------------------------------------------- //--------------------------------------------------
@ -178,7 +67,6 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case id case id
case moleculeName case moleculeName
case backgroundColor
case accessibilityIdentifier case accessibilityIdentifier
case accessibilityText case accessibilityText
case title case title
@ -188,12 +76,6 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
case style case style
case size case size
case groupName case groupName
case fillColor
case textColor
case borderColor
case disabledFillColor
case disabledTextColor
case disabledBorderColor
case width case width
} }
@ -211,17 +93,13 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
action = try typeContainer.decodeModel(codingKey: .action) action = try typeContainer.decodeModel(codingKey: .action)
///Style captured from the JSON ///Style captured from the JSON
if let style = try typeContainer.decodeIfPresent(Styler.Button.Style.self, forKey: .style){ if let style = try typeContainer.decodeIfPresent(Use.self, forKey: .style) {
self.style = style self.style = style
setFacade(by: style) } else if let style = decoder.context?.value(forKey: CodingKeys.style.stringValue) as? Use { ///Reading the style param from context which is set is molecules, ex: TwoButtonView
} else if let style = decoder.context?.value(forKey: CodingKeys.style.stringValue) as? Styler.Button.Style { ///Reading the style param from context which is set is molecules, ex: TwoButtonView
self.style = style self.style = style
setFacade(by: style)
} else { ///Default style
setFacade(by: .primary)
} }
if let size = try typeContainer.decodeIfPresent(Styler.Button.Size.self, forKey: .size) { if let size = try typeContainer.decodeIfPresent(VDS.Button.Size.self, forKey: .size) {
self.size = size self.size = size
} }
@ -229,40 +107,57 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
self.enabled = enabled self.enabled = enabled
} }
if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) {
self.inverted = inverted
}
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
self.groupName = groupName self.groupName = groupName
} }
width = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .width)
if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) {
self.inverted = inverted
} else {
try setInverted(deprecatedFrom: decoder)
}
}
private enum DeprecatedCodingKeys: String, CodingKey {
case fillColor
case textColor
case borderColor
case backgroundColor
}
private func setInverted(deprecatedFrom decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: DeprecatedCodingKeys.self)
if let enabledFillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .fillColor) { if let enabledFillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .fillColor) {
self.enabledFillColor = enabledFillColor if (self.style == .secondary) {
self.inverted = enabledFillColor.uiColor.isDark()
} else {
self.inverted = !enabledFillColor.uiColor.isDark()
}
} }
if let enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor) { if let enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor) {
self.enabledTextColor = enabledTextColor if (self.style == .secondary) {
self.inverted = !enabledTextColor.uiColor.isDark()
} else {
self.inverted = enabledTextColor.uiColor.isDark()
}
} }
if let enabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor) { if let enabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor) {
self.enabledBorderColor = enabledBorderColor if (self.style == .secondary) {
self.inverted = !enabledBorderColor.uiColor.isDark()
}
} }
if let disabledFillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledFillColor) { if let backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) {
self.disabledFillColor = disabledFillColor if (self.style == .secondary) {
self.inverted = backgroundColor.uiColor.isDark()
} else {
self.inverted = !backgroundColor.uiColor.isDark()
}
} }
if let disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) {
self.disabledTextColor = disabledTextColor
}
if let disabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledBorderColor) {
self.disabledBorderColor = disabledBorderColor
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
width = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .width)
} }
open func encode(to encoder: Encoder) throws { open func encode(to encoder: Encoder) throws {
@ -273,17 +168,10 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
try container.encode(enabled, forKey: .enabled) try container.encode(enabled, forKey: .enabled)
try container.encode(inverted, forKey: .inverted) try container.encode(inverted, forKey: .inverted)
try container.encodeModel(action, forKey: .action) try container.encodeModel(action, forKey: .action)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
try container.encodeIfPresent(enabledFillColor, forKey: .fillColor) try container.encode(style, forKey: .style)
try container.encodeIfPresent(enabledTextColor, forKey: .textColor) try container.encode(size, forKey: .size)
try container.encodeIfPresent(enabledBorderColor, forKey: .borderColor)
try container.encodeIfPresent(disabledFillColor, forKey: .disabledFillColor)
try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor)
try container.encodeIfPresent(disabledBorderColor, forKey: .disabledBorderColor)
try container.encodeIfPresent(style, forKey: .style)
try container.encodeIfPresent(size, forKey: .size)
try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(groupName, forKey: .groupName)
try container.encodeIfPresent(width, forKey: .width) try container.encodeIfPresent(width, forKey: .width)
} }

View File

@ -11,29 +11,25 @@ import UIKit
open class ExternalLink: Link { open class ExternalLink: Link {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Public Properties
//-------------------------------------------------- //--------------------------------------------------
open var exportImageView: UIImageView?
public var exportImageView: UIImageView? open var exportImageHeight: NSLayoutConstraint?
open var exportImageWidth: NSLayoutConstraint?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - MoleculeViewProtocol // MARK: - Overrides
//-------------------------------------------------- //--------------------------------------------------
open override func viewModelDidUpdate() {
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.viewModelDidUpdate()
super.set(with: model, delegateObject, additionalData) exportImageView?.tintColor = textColor
exportImageWidth?.constant = textStyle.lineHeight
guard let model = model as? ExternalLinkModel else { return } exportImageHeight?.constant = textStyle.lineHeight
exportImageView?.tintColor = titleColor(for: model.enabled ? .normal : .disabled)
} }
//-------------------------------------------------- open override func setup() {
// MARK: - MVMCoreViewProtocol super.setup()
//-------------------------------------------------- contentHorizontalAlignment = .left
open override func setupView() {
super.setupView()
let image = MVMCoreUIUtility.imageNamed("externalLink") let image = MVMCoreUIUtility.imageNamed("externalLink")
exportImageView = UIImageView(image: image?.withRenderingMode(.alwaysTemplate)) exportImageView = UIImageView(image: image?.withRenderingMode(.alwaysTemplate))
@ -46,10 +42,10 @@ open class ExternalLink: Link {
addSubview(exportIcon) addSubview(exportIcon)
trailingAnchor.constraint(greaterThanOrEqualTo: exportIcon.trailingAnchor).isActive = true trailingAnchor.constraint(greaterThanOrEqualTo: exportIcon.trailingAnchor).isActive = true
if let titleLabel = titleLabel { exportImageHeight = exportIcon.heightAnchor.constraint(equalToConstant: textStyle.pointSize).activate()
let dimension = titleLabel.font.pointSize exportImageWidth = exportIcon.widthAnchor.constraint(equalToConstant: textStyle.pointSize).activate()
exportIcon.heightAnchor.constraint(equalToConstant: dimension).isActive = true
exportIcon.widthAnchor.constraint(equalToConstant: dimension).isActive = true if let titleLabel {
exportIcon.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 4).isActive = true exportIcon.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 4).isActive = true
exportIcon.bottomAnchor.constraint(equalTo: titleLabel.lastBaselineAnchor, constant: 3).isActive = true exportIcon.bottomAnchor.constraint(equalTo: titleLabel.lastBaselineAnchor, constant: 3).isActive = true
} }

View File

@ -8,83 +8,59 @@
import UIKit import UIKit
import VDSColorTokens import VDSColorTokens
import VDS
open class Link: VDS.TextLink, VDSMoleculeViewProtocol {
@objcMembers open class Link: Button {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Draw // MARK: - Public Properties
//-------------------------------------------------- //--------------------------------------------------
open var viewModel: LinkModel!
open var delegateObject: MVMCoreUIDelegateObject?
open var additionalData: [AnyHashable : Any]?
open override func draw(_ rect: CGRect) { //--------------------------------------------------
// MARK: - Public Functions
//--------------------------------------------------
open func viewModelDidUpdate() {
isEnabled = viewModel.enabled
size = viewModel.size
text = viewModel.title
surface = viewModel.surface
guard let textRect = titleLabel?.frame, onClick = { [weak self] control in
let context = UIGraphicsGetCurrentContext() guard let self else { return }
else { return } MVMCoreUIActionHandler.performActionUnstructured(with: self.viewModel.action,
sourceModel: self.viewModel,
additionalData: self.additionalData,
delegateObject: self.delegateObject)
}
}
// Set line to the same color as the text //--------------------------------------------------
if let color = titleColor(for: state)?.cgColor { // MARK: - Overrides
context.setStrokeColor(color) //--------------------------------------------------
open override func updateAccessibility() {
super.updateAccessibility()
guard let viewModel = viewModel else { return }
if let accessibilityText = viewModel.accessibilityText {
self.accessibilityLabel = accessibilityText
} }
// x should be according to the text, not the button if let accessibilityIdentifier = viewModel.accessibilityIdentifier {
let x = textRect.origin.x self.accessibilityIdentifier = accessibilityIdentifier
// Line is 0 point below the text
let y = textRect.origin.y + textRect.size.height
context.move(to: CGPoint(x: x, y: y))
context.addLine(to: CGPoint(x: x + textRect.size.width, y: y))
context.strokePath()
}
open override var intrinsicContentSize: CGSize {
guard let size = titleLabel?.intrinsicContentSize else { return super.intrinsicContentSize }
return CGSize(width: size.width, height: size.height + 1)
}
//--------------------------------------------------
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? LinkModel else { return }
setTitle(model.title, for: .normal)
if let accessibilityText = model.accessibilityText {
accessibilityLabel = accessibilityText
} }
setTitleColor((model.inverted ? model.enabledColor_inverted : model.enabledColor).uiColor, for: .normal)
setTitleColor((model.inverted ? model.disabledColor_inverted : model.disabledColor).uiColor, for: .disabled)
setTitleColor((model.inverted ? model.activeColor_inverted : model.activeColor).uiColor, for: .highlighted)
isEnabled = model.enabled
titleLabel?.font = model.getFont(model.size)
set(with: model.action, delegateObject: delegateObject, additionalData: additionalData)
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 31 } //--------------------------------------------------
} // MARK: - MVMCoreViewProtocol
//--------------------------------------------------
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 31 }
// MARK: - MVMCoreViewProtocol open func updateView(_ size: CGFloat) { }
extension Link {
open override func updateView(_ size: CGFloat) { open func setupView() {}
super.updateView(size)
}
open override func setupView() {
super.setupView()
backgroundColor = .clear
contentMode = .redraw
setTitleColor(VDSColor.elementsPrimaryOnlight, for: .normal)
setTitleColor(VDSColor.interactiveDisabledOnlight, for: .disabled)
setTitleColor(VDSColor.interactiveActiveOnlight, for: .highlighted)
titleLabel?.numberOfLines = 1
titleLabel?.lineBreakMode = .byTruncatingTail
titleLabel?.textAlignment = .left
contentHorizontalAlignment = .left
contentVerticalAlignment = .top
}
} }
// MARK: - MVMCoreUIViewConstrainingProtocol // MARK: - MVMCoreUIViewConstrainingProtocol

View File

@ -7,7 +7,7 @@
// //
import UIKit import UIKit
import VDSColorTokens import VDS
open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableModelProtocol { open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
@ -23,15 +23,9 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
public var accessibilityText: String? public var accessibilityText: String?
public var action: ActionModelProtocol public var action: ActionModelProtocol
public var enabled = true public var enabled = true
public var enabledColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
public var enabledColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
public var disabledColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
public var disabledColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
public var activeColor = Color(uiColor: VDSColor.interactiveActiveOnlight)
public var activeColor_inverted = Color(uiColor: VDSColor.interactiveActiveOndark)
public var inverted = false public var inverted = false
public var size:linkFontSize = linkFontSize.small public var size: TextLink.Size = .small
public var shouldMaskRecordedView: Bool? = false public var shouldMaskRecordedView: Bool? = false
@ -57,35 +51,11 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
case title case title
case action case action
case enabled case enabled
case enabledColor
case enabledColor_inverted
case disabledColor
case disabledColor_inverted
case activeColor
case activeColor_inverted
case inverted case inverted
case size case size
case shouldMaskRecordedView case shouldMaskRecordedView
} }
public enum linkFontSize: String, Codable {
case small
case large
}
//--------------------------------------------------
// MARK: - Method
//--------------------------------------------------
func getFont(_ type: linkFontSize) -> UIFont {
switch type {
case .small:
return MFStyler.fontRegularBodySmall()
case .large:
return MFStyler.fontRegularBodyLarge()
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Codec // MARK: - Codec
//-------------------------------------------------- //--------------------------------------------------
@ -108,30 +78,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
self.inverted = inverted self.inverted = inverted
} }
if let enabledColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledColor) { if let size = try typeContainer.decodeIfPresent(TextLink.Size.self, forKey: .size) {
self.enabledColor = enabledColor
}
if let enabledColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledColor_inverted) {
self.enabledColor_inverted = enabledColor_inverted
}
if let disabledColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor) {
self.disabledColor = disabledColor
}
if let disabledColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor_inverted) {
self.disabledColor_inverted = disabledColor_inverted
}
if let activeColor = try typeContainer.decodeIfPresent(Color.self, forKey: .activeColor) {
self.activeColor = activeColor
}
if let activeColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .activeColor_inverted) {
self.activeColor_inverted = activeColor_inverted
}
if let size = try typeContainer.decodeIfPresent(linkFontSize.self, forKey: .size) {
self.size = size self.size = size
} }
@ -148,13 +95,11 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
try container.encodeModel(action, forKey: .action) try container.encodeModel(action, forKey: .action)
try container.encode(inverted, forKey: .inverted) try container.encode(inverted, forKey: .inverted)
try container.encode(enabled, forKey: .enabled) try container.encode(enabled, forKey: .enabled)
try container.encode(enabledColor, forKey: .enabledColor)
try container.encode(enabledColor_inverted, forKey: .enabledColor_inverted)
try container.encode(disabledColor, forKey: .disabledColor)
try container.encode(disabledColor_inverted, forKey: .disabledColor_inverted)
try container.encode(activeColor, forKey: .activeColor)
try container.encode(activeColor_inverted, forKey: .activeColor_inverted)
try container.encodeIfPresent(size, forKey: .size) try container.encodeIfPresent(size, forKey: .size)
try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView) try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
} }
} }
extension LinkModel {
public var surface: Surface { inverted ? .dark : .light }
}

View File

@ -8,223 +8,68 @@
import UIKit import UIKit
import VDSColorTokens import VDSColorTokens
import VDS
import MVMCore
import Combine
open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MFButtonProtocol, VDSMoleculeViewProtocol {
open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
/// Used to size the button. open var viewModel: ButtonModel!
var size = MVMCoreUIUtility.getWidth() public var delegateObject: MVMCoreUIDelegateObject?
public var additionalData: [AnyHashable: Any]?
var buttonModel: ButtonModel? { internal var onClickCancellable: Cancellable?
get { model as? ButtonModel }
}
/// Need to re-style on set.
open override var isEnabled: Bool {
didSet { style(with: buttonModel) }
}
open var buttonSize: Styler.Button.Size = .standard {
didSet { buttonModel?.size = buttonSize }
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Constraints // MARK: - VDSMoleculeViewProtocol
//-------------------------------------------------- //--------------------------------------------------
public var widthConstraint: NSLayoutConstraint? open func viewModelDidUpdate() {
public var minimumWidthConstraint: NSLayoutConstraint? if let accessibilityIdentifier = viewModel.accessibilityIdentifier {
self.accessibilityIdentifier = accessibilityIdentifier
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@objc public convenience init(asPrimaryButton isPrimary: Bool, makeTiny istiny: Bool) {
let model = ButtonModel(with: "", action: ActionNoopModel())
model.style = isPrimary ? .primary : .secondary
model.size = istiny ? .tiny : .standard
self.init(model: model, nil, nil)
}
//--------------------------------------------------
// MARK: - Computed Properties
//--------------------------------------------------
public var enabledTitleColor: UIColor? {
get { titleColor(for: .normal) }
set { setTitleColor(newValue, for: .normal) }
}
public var disabledTitleColor: UIColor? {
get { titleColor(for: .disabled) }
set { setTitleColor(newValue, for: .disabled) }
}
public var borderColor: UIColor? {
get {
guard let currentColor = layer.borderColor else { return nil }
return UIColor(cgColor: currentColor)
}
set { layer.borderColor = newValue?.cgColor }
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
/// The primary styling for a button. Should be used for main buttons
public func stylePrimary() {
let buttonModel = ButtonModel(primaryButtonWith: "", action: ActionNoopModel())
style(with: buttonModel)
}
/// The secondary styling for a button. Should be used for secondary buttons
public func styleSecondary() {
let buttonModel = ButtonModel(secondaryButtonWith: "", action: ActionNoopModel())
style(with: buttonModel)
}
/// Styles the button based on the model style
private func style(with model: ButtonModel?) {
layer.borderWidth = model?.style == .secondary ? 1 : 0
if let titleColor = model?.enabledColors.text {
enabledTitleColor = titleColor
} }
if let disabledTitleColor = model?.disabledColors.text { text = viewModel.title
self.disabledTitleColor = disabledTitleColor isEnabled = viewModel.enabled
size = viewModel.size
use = viewModel.style ?? .primary
surface = viewModel.inverted ? .dark : .light
if let accessibilityText = viewModel.accessibilityText {
accessibilityLabel = accessibilityText
} }
#if DEBUG set(with: viewModel.action, delegateObject: delegateObject, additionalData: additionalData)
// Useful to detect with isHittable when performing UI testing.
isAccessibilityElement = isEnabled
#endif
if isEnabled { viewModel.updateUI = { [weak self] in
if let fillColor = model?.enabledColors.fill { MVMCoreDispatchUtility.performBlock(onMainThread: {
backgroundColor = fillColor guard let self = self else { return }
} self.isEnabled = self.viewModel.enabled
})
if let borderColor = model?.enabledColors.border {
self.borderColor = borderColor
}
} else {
if let fillColor = model?.disabledColors.fill {
backgroundColor = fillColor
}
if let borderColor = model?.disabledColors.border {
self.borderColor = borderColor
}
} }
}
private func getInnerPadding() -> CGFloat { FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate)
buttonSize.getHeight() / 2.0
}
private func getContentEdgeInsets() -> UIEdgeInsets {
var verticalPadding = 0.0
var horizontalPadding = 0.0
switch buttonSize {
case .standard:
verticalPadding = Padding.Three
horizontalPadding = Padding.Five
break
case .small:
verticalPadding = Padding.Two
horizontalPadding = Padding.Four
break
case .tiny:
verticalPadding = Padding.One
horizontalPadding = Padding.Two
break
}
return UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - MVMCoreViewProtocol // MARK: - MVMCoreViewProtocol
//-------------------------------------------------- //--------------------------------------------------
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
// The button will get styled in the enable check in super. return (model as? ButtonModel)?.size.height
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ButtonModel else { return }
setTitle(model.title, for: .normal)
if let accessibilityText = model.accessibilityText {
accessibilityLabel = accessibilityText
}
if let size = model.size {
buttonSize = size
}
model.updateUI = { [weak self] in
MVMCoreDispatchUtility.performBlock(onMainThread: {
self?.enableField(model.enabled)
})
}
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open func updateView(_ size: CGFloat) {}
return (model as? ButtonModel)?.size?.getHeight()
open override func setup() {
super.setup()
setupView()
} }
open override func updateView(_ size: CGFloat) { open func setupView() {}
super.updateView(size)
self.size = size
switch buttonSize {
case .tiny:
titleLabel?.font = Styler.Font.BoldMicro.getFont(false)
case .small:
titleLabel?.font = Styler.Font.BoldBodySmall.getFont(false)
case .standard:
titleLabel?.font = Styler.Font.BoldBodyLarge.getFont(false)
}
layer.cornerRadius = getInnerPadding()
contentEdgeInsets = getContentEdgeInsets()
if let contraint = buttonModel?.width {
if widthConstraint == nil {
widthConstraint = widthAnchor.constraint(equalToConstant: contraint)
} else if widthConstraint?.constant != contraint {
widthConstraint?.constant = contraint
}
widthConstraint?.isActive = true
minimumWidthConstraint?.isActive = false
} else {
if minimumWidthConstraint == nil {
minimumWidthConstraint = widthAnchor.constraint(greaterThanOrEqualToConstant: buttonSize.minimumWidth())
} else {
minimumWidthConstraint?.constant = buttonSize.minimumWidth()
}
minimumWidthConstraint?.isActive = true
widthConstraint?.isActive = false
}
}
open override func setupView() {
super.setupView()
titleLabel?.numberOfLines = 1
titleLabel?.lineBreakMode = .byTruncatingTail
titleLabel?.textAlignment = .center
contentHorizontalAlignment = .center
stylePrimary()
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - MVMCoreUIViewConstrainingProtocol // MARK: - MVMCoreUIViewConstrainingProtocol
@ -232,7 +77,21 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
open func horizontalAlignment() -> UIStackView.Alignment { .center } open func horizontalAlignment() -> UIStackView.Alignment { .center }
public func enableField(_ enable: Bool) { //--------------------------------------------------
isEnabled = enable // MARK: - Action
//--------------------------------------------------
open func set(with actionModel: ActionModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
onClick = { [weak self] control in
guard let self = self, let viewModel = self.viewModel else { return }
Task(priority: .userInitiated) {
try await Self.performButtonAction(with: viewModel.action, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: viewModel)
}
}
}
open class func performButtonAction(with model: ActionModelProtocol, button: MFButtonProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, sourceModel: MoleculeModelProtocol? = nil) async throws {
guard delegateObject?.buttonDelegate?.button?(button, shouldPerformActionWithMap: model.toJSON(), additionalData: additionalData) ?? true else { return }
try await (delegateObject?.actionDelegate as? ActionDelegateProtocol)?.performAction(with: model, additionalData: MVMCoreUIActionHandler.add(sourceModel: sourceModel, to: additionalData), delegateObject: delegateObject)
} }
} }

View File

@ -0,0 +1,60 @@
//
// Badge.swift
// MVMCoreUI
//
// Created by Rebecca Antonelli on 4/6/23.
// Copyright © 2023 Verizon Wireless. All rights reserved.
//
import Foundation
import MVMCore
import VDS
import Combine
open class Badge: VDS.Badge, VDSMoleculeViewProtocol {
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
public var viewModel: BadgeModel!
public var delegateObject: MVMCoreUIDelegateObject?
public var additionalData: [AnyHashable : Any]?
//--------------------------------------------------
// MARK: - Public Methods
//--------------------------------------------------
public func viewModelDidUpdate() {
text = viewModel.text
maxWidth = viewModel.maxWidth
numberOfLines = viewModel.numberOfLines
fillColor = viewModel.fillColor
surface = viewModel.surface
}
public func updateView(_ size: CGFloat) {}
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
open override func updateAccessibility() {
super.updateAccessibility()
if let viewModel {
if let accessibilityText = viewModel.accessibilityText {
self.accessibilityLabel = accessibilityText
}
}
}
}
//to deal with how it's parent constrains this control
extension Badge: MVMCoreUIViewConstrainingProtocol {
public func needsToBeConstrained() -> Bool { true }
public func horizontalAlignment() -> UIStackView.Alignment { .leading }
}

View File

@ -0,0 +1,56 @@
//
// BadgeModel.swift
// MVMCoreUI
//
// Created by Rebecca Antonelli on 4/6/23.
// Copyright © 2023 Verizon Wireless. All rights reserved.
//
import Foundation
import VDS
open class BadgeModel: MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "badge"
public var id: String = UUID().uuidString
public var backgroundColor: Color?
//--------------------------------------------------
// MARK: - VDS Properties
//--------------------------------------------------
public var text: String = ""
public var accessibilityText: String?
public var maxWidth: CGFloat?
public var numberOfLines: Int = 1
public var fillColor = Badge.FillColor.red
public var surface: Surface = .light
private enum CodingKeys: String, CodingKey {
case id, text, accessibilityText, fillColor, surface, numberOfLines, maxWidth
}
required public convenience init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
text = try container.decode(String.self, forKey: .text)
accessibilityText = try container.decodeIfPresent(String.self, forKey: .accessibilityText)
fillColor = try container.decodeIfPresent(Badge.FillColor.self, forKey: .fillColor) ?? .red
surface = try container.decodeIfPresent(Surface.self, forKey: .surface) ?? .light
numberOfLines = try container.decodeIfPresent(Int.self, forKey: .numberOfLines) ?? 1
maxWidth = try container.decodeIfPresent(CGFloat.self, forKey: .maxWidth)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(text, forKey: .text)
try container.encode(accessibilityText, forKey: .accessibilityText)
try container.encode(fillColor, forKey: .fillColor)
try container.encode(surface, forKey: .surface)
try container.encode(numberOfLines, forKey: .numberOfLines)
try container.encodeIfPresent(maxWidth, forKey: .maxWidth)
}
}

View File

@ -213,7 +213,9 @@ open class BarsIndicatorView: CarouselIndicator {
let accessibleIndex = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: index + 1)) let accessibleIndex = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: index + 1))
else { return } else { return }
view.accessibilityLabel = String(format: accessibleValueFormat, accessibleIndex, numberOfPages) let accessibilityValue = String(format: accessibleValueFormat, accessibleIndex, numberOfPages)
view.accessibilityLabel = accessibilityValue
view.accessibilityIdentifier = accessibilityValue
} }
public override func assessTouchOf(_ touchPoint_X: CGFloat) { public override func assessTouchOf(_ touchPoint_X: CGFloat) {

View File

@ -7,116 +7,112 @@
// //
import UIKit import UIKit
import VDS
@objcMembers open class Line: VDS.Line, VDSMoleculeViewProtocol {
@objcMembers open class Line: View {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
open var viewModel: LineModel!
open var delegateObject: MVMCoreUIDelegateObject?
open var additionalData: [AnyHashable : Any]?
var lineModel: LineModel? { open override var orientation: Line.Orientation {
get { return model as? LineModel } didSet {
} if orientation == .horizontal {
setContentHuggingPriority(.defaultLow, for: .horizontal)
//-------------------------------------------------- setContentHuggingPriority(.required, for: .vertical)
// MARK: - Constraints setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
//-------------------------------------------------- setContentCompressionResistancePriority(.required, for: .vertical)
} else {
public var heightConstraint: NSLayoutConstraint? setContentHuggingPriority(.required, for: .horizontal)
public var widthConstraint: NSLayoutConstraint? setContentHuggingPriority(.defaultLow, for: .vertical)
setContentCompressionResistancePriority(.required, for: .horizontal)
open func updateLineConstraints(constant: CGFloat) { setContentCompressionResistancePriority(.defaultLow, for: .vertical)
if let useVerticalLine = lineModel?.useVerticalLine, useVerticalLine { }
heightConstraint?.isActive = false
widthConstraint?.isActive = true
widthConstraint?.constant = constant
} else {
widthConstraint?.isActive = false
heightConstraint?.isActive = true
heightConstraint?.constant = constant
} }
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public convenience init(pinTo view: UIView, edge: UIRectEdge, useMargin: Bool) { public convenience init(pinTo view: UIView, edge: UIRectEdge, useMargin: Bool) {
self.init(frame: .zero) self.init(frame: .zero)
addLine(to: view, edge: edge, useMargin: useMargin) addLine(to: view, edge: edge, useMargin: useMargin)
} }
public init() { public required init() {
super.init(frame: .zero) super.init()
model = LineModel(type: .secondary) viewModel = LineModel(type: .secondary)
setStyle(.secondary)
} }
public override init(frame: CGRect) { public override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
model = LineModel(type: .secondary) viewModel = LineModel(type: .secondary)
setStyle(.secondary)
} }
public required init?(coder: NSCoder) { public required init?(coder: NSCoder) {
super.init(coder: coder) super.init(coder: coder)
model = LineModel(type: .secondary) viewModel = LineModel(type: .secondary)
setStyle(.secondary)
}
public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.init(model: model, delegateObject, additionalData)
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Methods // MARK: - Methods
//-------------------------------------------------- //--------------------------------------------------
open func shouldBeVisible() -> Bool {
open func setStyle(_ style: LineModel.Style) { guard let type = viewModel?.type else { return false }
lineModel?.type = style return type != .none
backgroundColor = lineModel?.backgroundColor?.uiColor
updateLineConstraints(constant: lineModel?.thickness ?? 1)
} }
open func shouldBeVisible() -> Bool { open func setStyle(_ style: LineModel.Style) {
guard let type = lineModel?.type else { return false } viewModel.type = style
return type != .none update(viewModel: viewModel)
}
open func addLine(to view: UIView, edge: UIRectEdge, useMargin: Bool) {
view.addSubview(self)
NSLayoutConstraint.activate(
Array(
NSLayoutConstraint.pinView(toSuperview: self,
useMargins: useMargin,
pinTop: edge != .bottom,
pinBottom: edge != .top,
pinLeft: edge != .right,
pinRight: edge != .left).values
)
)
}
open override func draw(_ rect: CGRect) {
guard viewModel.type != .none else { return }
super.draw(rect)
}
//--------------------------------------------------
// MARK: - VDSMoleculeViewProtocol
//--------------------------------------------------
open func viewModelDidUpdate() {
surface = viewModel.surface
style = VDS.Line.Style(rawValue: viewModel.type.rawValue) ?? .primary
orientation = viewModel.orientation
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - MoleculeViewProtocol // MARK: - MoleculeViewProtocol
//-------------------------------------------------- //--------------------------------------------------
public func updateView(_ size: CGFloat) {
open func addLine(to view: UIView, edge: UIRectEdge, useMargin: Bool) { setNeedsDisplay()
view.addSubview(self)
NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: self, useMargins: useMargin, pinTop: edge != .bottom, pinBottom: edge != .top, pinLeft: edge != .right, pinRight: edge != .left).values))
} }
open override func setupView() { public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
super.setupView() return 1
heightConstraint = heightAnchor.constraint(equalToConstant: 1)
heightConstraint?.isActive = true
widthConstraint = widthAnchor.constraint(equalToConstant: 1)
widthConstraint?.isActive = false
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
if let lineModel = model as? LineModel {
setStyle(lineModel.type)
}
}
open override func reset() {
setStyle(.secondary)
}
public override static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return (model as? LineModel)?.thickness ?? 1
} }
} }
//--------------------------------------------------
// MARK: - MVMCoreUIViewConstrainingProtocol
//--------------------------------------------------
extension Line: MVMCoreUIViewConstrainingProtocol { extension Line: MVMCoreUIViewConstrainingProtocol {
open func needsToBeConstrained() -> Bool { open func needsToBeConstrained() -> Bool {

View File

@ -8,8 +8,9 @@
import UIKit import UIKit
import VDSColorTokens import VDSColorTokens
import VDS
@objcMembers public class LineModel: MoleculeModelProtocol { public class LineModel: MoleculeModelProtocol, Invertable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Enums // MARK: - Enums
//-------------------------------------------------- //--------------------------------------------------
@ -30,12 +31,12 @@ import VDSColorTokens
/** /**
The style of the line: The style of the line:
- secondary (1 height, silver) - secondary (VDS Secondary)
- primary (1 height, black) - primary (VDS Primary)
- standard (1 height, silver) - deprecated - standard (VDS Secondary) - deprecated
- thin (1 height, black) - deprecated - thin (VDS Primar) - deprecated
- medium (2 height, black) - medium (VDS Primar)
- heavy (4 height, black) - heavy (VDS Primar)
- none (hidden) - none (hidden)
*/ */
public enum Style: String, Codable { public enum Style: String, Codable {
@ -54,53 +55,14 @@ import VDSColorTokens
public static var identifier: String = "line" public static var identifier: String = "line"
public var id: String = UUID().uuidString public var id: String = UUID().uuidString
public var backgroundColor: Color?
public var type: Style = .secondary public var type: Style = .secondary
public var frequency: Frequency? = .allExceptTop public var frequency: Frequency? = .allExceptTop
//TODO: use color insted of backgroundColor. Needs server changes
// public var color: Color?
private var _backgroundColor: Color?
public var backgroundColor: Color? {
get {
if let backgroundColor = _backgroundColor { return backgroundColor }
if inverted {
if type == .secondary || type == .standard { return Color(uiColor: VDSColor.paletteGray20) }
return Color(uiColor: VDSColor.elementsPrimaryOndark)
}
if type == .secondary || type == .standard { return Color(uiColor: VDSColor.paletteGray85) }
return Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
set {
_backgroundColor = newValue
}
}
private var _thickness: CGFloat?
public var thickness: CGFloat {
get {
if let thickness = _thickness { return thickness }
switch type {
case .heavy:
return 4
case .medium:
return 2
case .none:
return 0
default:
return 1
}
}
set {
_thickness = newValue
}
}
public var inverted: Bool = false public var inverted: Bool = false
// Use this to show vertical line public var orientation: VDS.Line.Orientation = .horizontal
// Default is false
public var useVerticalLine: Bool?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializer // MARK: - Initializer
@ -108,13 +70,11 @@ import VDSColorTokens
public init(type: Style) { public init(type: Style) {
self.type = type self.type = type
self.useVerticalLine = false
} }
public init(verticalLineOf type: Style, backgroundColor: Color? = nil) { public init(verticalLineOf type: Style) {
self.type = type self.type = type
self.backgroundColor = backgroundColor orientation = .vertical
self.useVerticalLine = true
} }
//-------------------------------------------------- //--------------------------------------------------
@ -125,13 +85,10 @@ import VDSColorTokens
case id case id
case moleculeName case moleculeName
case type case type
case backgroundColor
case backgroundColor_inverted
case color
case frequency case frequency
case inverted case inverted
case useVerticalLine case useVerticalLine
case thickness case orientation
} }
//-------------------------------------------------- //--------------------------------------------------
@ -155,9 +112,12 @@ import VDSColorTokens
self.inverted = inverted self.inverted = inverted
} }
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) /// adding code to look for the old useVerticalLine or the new orientation
useVerticalLine = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalLine) if let useVerticalLine = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalLine) {
_thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness) orientation = useVerticalLine ? .vertical : .horizontal
} else if let orientation = try typeContainer.decodeIfPresent(VDS.Line.Orientation.self, forKey: .orientation) {
self.orientation = orientation
}
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -167,8 +127,6 @@ import VDSColorTokens
try container.encode(type, forKey: .type) try container.encode(type, forKey: .type)
try container.encode(inverted, forKey: .inverted) try container.encode(inverted, forKey: .inverted)
try container.encodeIfPresent(frequency, forKey: .frequency) try container.encodeIfPresent(frequency, forKey: .frequency)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor) try container.encode(orientation == .vertical, forKey: .useVerticalLine)
try container.encodeIfPresent(useVerticalLine, forKey: .useVerticalLine)
try container.encodeIfPresent(_thickness, forKey: .thickness)
} }
} }

View File

@ -50,14 +50,13 @@ open class Tilelet: VDS.Tilelet, VDSMoleculeViewProtocol{
//setup action //setup action
if let action = viewModel.action { if let action = viewModel.action {
//add the subscriber //add the subscriber
onClickSubscriber = publisher(for: .touchUpInside) onClick = { [weak self] control in
.sink {[weak self] control in guard let self, let viewModel = self.viewModel else { return }
guard let self else { return } MVMCoreUIActionHandler.performActionUnstructured(with: action,
MVMCoreUIActionHandler.performActionUnstructured(with: action, sourceModel: viewModel,
sourceModel: self.viewModel, additionalData: self.additionalData,
additionalData: self.additionalData, delegateObject: self.delegateObject)
delegateObject: self.delegateObject) }
}
} }
} }

View File

@ -16,3 +16,11 @@ extension Icon.Size: Codable {}
extension TileContainer.BackgroundColor: Codable {} extension TileContainer.BackgroundColor: Codable {}
extension TileContainer.Padding: Codable {} extension TileContainer.Padding: Codable {}
extension TileContainer.AspectRatio: Codable {} extension TileContainer.AspectRatio: Codable {}
extension TextLink.Size: Codable {}
extension VDS.Line.Style: Codable {}
extension VDS.Line.Orientation: Codable {}
extension Use: Codable {}
extension VDS.Button.Size: RawRepresentableCodable {
public static var mapping: [String : VDS.Button.Size] { ["standard": .large, "tiny": .small] }
public static var defaultValue: VDS.Button.Size? { nil }
}

View File

@ -42,6 +42,13 @@ import Foundation
return Stack<StackModel>.createStack(with: [headline, horizontalStack], spacing: 8) return Stack<StackModel>.createStack(with: [headline, horizontalStack], spacing: 8)
}() }()
//-------------------------------------------------------
// MARK: - Constraints
//-------------------------------------------------------
public var verticalLine1HeightConstraint: NSLayoutConstraint?
public var verticalLine2HeightConstraint: NSLayoutConstraint?
//------------------------------------------------------- //-------------------------------------------------------
// MARK: - Lifecycle // MARK: - Lifecycle
//------------------------------------------------------- //-------------------------------------------------------
@ -52,10 +59,9 @@ import Foundation
body2.lineBreakMode = .byTruncatingTail body2.lineBreakMode = .byTruncatingTail
body3.lineBreakMode = .byTruncatingTail body3.lineBreakMode = .byTruncatingTail
verticalLine1.widthConstraint?.isActive = true // setup lines
verticalLine1.backgroundColor = .mvmBlack verticalLine1.orientation = .vertical
verticalLine2.widthConstraint?.isActive = true verticalLine2.orientation = .vertical
verticalLine2.backgroundColor = .mvmBlack
addMolecule(stack) addMolecule(stack)
stack.restack() stack.restack()
@ -80,13 +86,13 @@ import Foundation
} }
open func setLineHeight() { open func setLineHeight() {
verticalLine1.heightConstraint?.isActive = false verticalLine1HeightConstraint?.isActive = false
verticalLine1.heightConstraint = verticalLine1.heightAnchor.constraint(equalTo: body2.heightAnchor, multiplier: 1) verticalLine1HeightConstraint = verticalLine1.heightAnchor.constraint(equalTo: body2.heightAnchor, multiplier: 1)
verticalLine1.heightConstraint?.isActive = true verticalLine1HeightConstraint?.isActive = true
verticalLine2.heightConstraint?.isActive = false verticalLine2HeightConstraint?.isActive = false
verticalLine2.heightConstraint = verticalLine2.heightAnchor.constraint(equalTo: body3.heightAnchor, multiplier: 1) verticalLine2HeightConstraint = verticalLine2.heightAnchor.constraint(equalTo: body3.heightAnchor, multiplier: 1)
verticalLine2.heightConstraint?.isActive = true verticalLine2HeightConstraint?.isActive = true
} }
//---------------------------------------------------- //----------------------------------------------------

View File

@ -42,7 +42,7 @@ public class ListDeviceComplexButtonMediumModel: ListItemModel, MoleculeModelPro
override public func setDefaults() { override public func setDefaults() {
super.setDefaults() super.setDefaults()
button.size = .tiny button.size = .small
button.style = .secondary button.style = .secondary
} }

View File

@ -42,7 +42,7 @@ public class ListDeviceComplexButtonSmallModel: ListItemModel, MoleculeModelProt
override public func setDefaults() { override public func setDefaults() {
super.setDefaults() super.setDefaults()
button.size = .tiny button.size = .small
button.style = .secondary button.style = .secondary
} }

View File

@ -7,7 +7,7 @@
// //
@objcMembers open class ListProgressBarThin: TableViewCell { open class ListProgressBarThin: TableViewCell {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Outlets // MARK: - Outlets
//-------------------------------------------------- //--------------------------------------------------
@ -15,7 +15,11 @@
public let progressBar = ProgressBar() public let progressBar = ProgressBar()
public let leftHeadline = Label(fontStyle: .BoldBodySmall) public let leftHeadline = Label(fontStyle: .BoldBodySmall)
public let leftBody = Label(fontStyle: .BoldBodySmall) public let leftBody = Label(fontStyle: .BoldBodySmall)
public let rightBar = Line() public let rightBar: DataLine = {
var line = DataLine()
line.heightConstraint.constant = 2
return line
}()
public let rightLabel = Label(fontStyle: .BoldBodySmall) public let rightLabel = Label(fontStyle: .BoldBodySmall)
private let barStackItem: StackItem private let barStackItem: StackItem
private let rightLabelStackItem: StackItem private let rightLabelStackItem: StackItem
@ -102,7 +106,6 @@
leftHeadline.styleB1(true) leftHeadline.styleB1(true)
leftBody.styleB2(true) leftBody.styleB2(true)
rightLabel.styleB2(true) rightLabel.styleB2(true)
rightBar.setStyle(.medium)
} }
//------------------------------------------------------ //------------------------------------------------------

View File

@ -16,14 +16,14 @@ public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol {
public var progressBar: ProgressBarModel public var progressBar: ProgressBarModel
public var leftHeadline: LabelModel public var leftHeadline: LabelModel
public var leftBody: LabelModel? public var leftBody: LabelModel?
public var rightBar: LineModel public var rightBar: DataLineModel
public var rightLabel: LabelModel public var rightLabel: LabelModel
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(progressBar: ProgressBarModel, leftHeadline: LabelModel, leftBody: LabelModel? = nil, rightBar: LineModel, rightLabel: LabelModel) { public init(progressBar: ProgressBarModel, leftHeadline: LabelModel, leftBody: LabelModel? = nil, rightBar: DataLineModel, rightLabel: LabelModel) {
self.progressBar = progressBar self.progressBar = progressBar
self.leftHeadline = leftHeadline self.leftHeadline = leftHeadline
self.leftBody = leftBody self.leftBody = leftBody
@ -39,8 +39,6 @@ public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol {
override public func setDefaults() { override public func setDefaults() {
super.setDefaults() super.setDefaults()
rightBar.type = .medium
if rightBar.backgroundColor == nil { if rightBar.backgroundColor == nil {
rightBar.backgroundColor = Color(uiColor: .gray) rightBar.backgroundColor = Color(uiColor: .gray)
} }
@ -74,7 +72,7 @@ public class ListProgressBarThinModel: ListItemModel, MoleculeModelProtocol {
progressBar = try typeContainer.decode(ProgressBarModel.self, forKey:.progressBar) progressBar = try typeContainer.decode(ProgressBarModel.self, forKey:.progressBar)
leftHeadline = try typeContainer.decode(LabelModel.self, forKey: .leftHeadline) leftHeadline = try typeContainer.decode(LabelModel.self, forKey: .leftHeadline)
leftBody = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .leftBody) leftBody = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .leftBody)
rightBar = try typeContainer.decode(LineModel.self, forKey: .rightBar) rightBar = try typeContainer.decode(DataLineModel.self, forKey: .rightBar)
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
try super.init(from: decoder) try super.init(from: decoder)
} }

View File

@ -11,25 +11,25 @@
// MARK: - Outlets // MARK: - Outlets
//-------------------------------------------------- //--------------------------------------------------
public let heart = Heart() public let badge = Badge()
public let leftHeadline = Label(fontStyle: .BoldBodySmall) public let leftHeadline = Label(fontStyle: .BoldTitleSmall)
public let leftBody = Label(fontStyle: .RegularBodySmall) public let leftBody = Label(fontStyle: .RegularMicro)
public let leftSubBody = Label(fontStyle: .RegularBodySmall) public let leftSubBody = Label(fontStyle: .RegularBodySmall)
public let rightLabel = Label(fontStyle: .RegularBodySmall) public let rightLabel = Label(fontStyle: .RegularBodySmall)
private lazy var rightLabelStackItem: StackItem = { public var model: ListStoreLocatorModel?
StackItem(andContain: rightLabel)
}()
public lazy var horizontalStack: Stack<StackModel> = { public lazy var horizontalStack: Stack<StackModel> = {
return Stack<StackModel>(with: StackModel(molecules: [StackItemModel(horizontalAlignment: .fill), return Stack<StackModel>(with: StackModel(molecules: [StackItemModel(horizontalAlignment: .fill),
StackItemModel(horizontalAlignment: .fill), StackItemModel(horizontalAlignment: .trailing, verticalAlignment: .center)],
StackItemModel(horizontalAlignment: .trailing)], axis: .horizontal, spacing: Padding.Two), stackItems: [StackItem(andContain: stack), StackItem(andContain: rightLabel)])
axis: .horizontal, spacing: Padding.Two), stackItems: [StackItem(andContain: leftHeadline), StackItem(andContain: heart), rightLabelStackItem])
}() }()
public lazy var stack: Stack<StackModel> = { public lazy var stack: Stack<StackModel> = {
return Stack<StackModel>.createStack(with: [horizontalStack, leftBody, leftSubBody], axis: .vertical, spacing: 0) return Stack<StackModel>(with: .init(molecules: [StackItemModel(horizontalAlignment: .leading),
}() StackItemModel(horizontalAlignment: .fill), StackItemModel(horizontalAlignment: .fill), StackItemModel(horizontalAlignment: .fill)],
public var sizeObject: MFSizeObject? = MFSizeObject(standardSize: 12, standardiPadPortraitSize: 18) axis: .vertical, spacing: Padding.One), stackItems: [StackItem(andContain: badge), StackItem(andContain: leftHeadline), StackItem(andContain: leftBody), StackItem(andContain: leftSubBody)])
}()
//------------------------------------------------------- //-------------------------------------------------------
// MARK: - Lifecycle // MARK: - Lifecycle
@ -39,16 +39,10 @@
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal) rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal)
addMolecule(stack) addMolecule(horizontalStack)
stack.restack() stack.restack()
horizontalStack.restack() horizontalStack.restack()
} leftSubBody.textColor = UIColor.mfTextLightGray()
public override func updateView(_ size: CGFloat) {
super.updateView(size)
if let dimension = sizeObject?.getValueBased(onSize: size) {
heart.widthConstraint?.constant = dimension
}
} }
//------------------------------------------------------ //------------------------------------------------------
@ -56,104 +50,38 @@
//------------------------------------------------------ //------------------------------------------------------
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
guard let model = model as? ListStoreLocatorModel else { return } guard let model = model as? ListStoreLocatorModel else { return }
horizontalStack.updateContainedMolecules(with: [model.leftHeadline, model.heart, model.rightLabel], delegateObject, additionalData) stack.updateContainedMolecules(with: [model.badge, model.leftHeadline, model.leftBody, model.leftSubBody], delegateObject, additionalData)
leftBody.set(with: model.leftBody, delegateObject, additionalData) rightLabel.set(with: model.rightLabel, delegateObject, additionalData)
leftSubBody.set(with: model.leftSubBody, delegateObject, additionalData) self.model = model
updateAccessibilityLabel() updateAccessibilityLabel()
} }
open override func alignAccessoryToHero() -> CGPoint? {
let heroCenter = super.alignAccessoryToHero()
if let heroCenter = heroCenter {
let convertedPoint = horizontalStack.convert(heroCenter, from: self)
rightLabelStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - horizontalStack.bounds.midY
}
return heroCenter
}
public override func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
if listItemModel?.action != nil {
super.didSelectCell(at: index, delegateObject: delegateObject, additionalData: additionalData)
} else {
heart.tapAction()
updateAccessibilityLabel()
}
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 120 } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 120 }
open override func reset() { open override func reset() {
super.reset() super.reset()
leftHeadline.setFontStyle(.BoldBodySmall) leftHeadline.setFontStyle(.BoldTitleSmall)
leftBody.setFontStyle(.RegularBodySmall) leftBody.setFontStyle(.RegularMicro)
leftSubBody.setFontStyle(.RegularBodySmall) leftSubBody.setFontStyle(.RegularBodySmall)
rightLabel.setFontStyle(.RegularBodySmall) rightLabel.setFontStyle(.RegularBodySmall)
leftSubBody.textColor = UIColor.mfTextLightGray()
} }
//--------------------------------------------------
// MARK: - Accessibility
//--------------------------------------------------
func getAccessibilityMessage() -> String? {
var message = ""
heart.updateAccessibilityLabel()
if let leftHeadlineText = leftHeadline.text, !leftHeadlineText.isEmpty {
message += leftHeadlineText + ", "
}
if let leftBodyText = leftBody.text, !leftBodyText.isEmpty {
message += leftBodyText + ", "
}
if let leftSubBodyText = leftSubBody.text, !leftSubBodyText.isEmpty {
message += leftSubBodyText + ", "
}
if let rightLabelText = rightLabel.text, !rightLabelText.isEmpty {
message += rightLabelText
}
return message.count > 0 ? message : nil
}
func updateAccessibilityLabel() {
let hasHeart = !(horizontalStack.stackModel?.molecules[1].gone ?? true)
if let accessoryView = accessoryView,
hasHeart {
// Both accessory and heart actions.
isAccessibilityElement = false
accessoryView.accessibilityLabel = getAccessibilityMessage()
accessibilityElements = [accessoryView, heart]
} else {
// Make whole cell focusable if no action.
isAccessibilityElement = true
var message = getAccessibilityMessage()
if hasHeart {
accessibilityHint = heart.accessibilityHint
if let heartLabel = heart.accessibilityLabel {
message = (message ?? "") + ", " + heartLabel
}
} else {
accessibilityHint = nil
}
accessibilityLabel = message
}
}
// Ensures voice over does not read "selected" after user triggers action on cell.
override public var accessibilityTraits: UIAccessibilityTraits { override public var accessibilityTraits: UIAccessibilityTraits {
get { get {
if (accessoryView != nil) { if (accessoryView != nil) {
return .button return .button
} else if (!(horizontalStack.stackModel?.molecules[1].gone ?? true)) {
return heart.accessibilityTraits
} else { } else {
return .none return .none
} }
} }
set { } set { }
} }
func updateAccessibilityLabel() {
isAccessibilityElement = true
let message = [model?.badge?.text, model?.leftHeadline.text, model?.leftBody.text, model?.leftSubBody.text, model?.rightLabel.text].compactMap { $0 }.joined(separator: ", ")
accessibilityLabel = message
}
} }

View File

@ -12,7 +12,7 @@ public class ListStoreLocatorModel: ListItemModel, MoleculeModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
public static var identifier = "listStoreLocator" public static var identifier = "listStoreLocator"
public var heart: HeartModel? public var badge: BadgeModel?
public var leftHeadline: LabelModel public var leftHeadline: LabelModel
public var leftBody: LabelModel public var leftBody: LabelModel
public var leftSubBody: LabelModel public var leftSubBody: LabelModel
@ -22,8 +22,8 @@ public class ListStoreLocatorModel: ListItemModel, MoleculeModelProtocol {
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(heart: HeartModel?, leftHeadline: LabelModel, leftBody: LabelModel, leftSubBody: LabelModel, rightLabel: LabelModel) { public init(badge: BadgeModel?, leftHeadline: LabelModel, leftBody: LabelModel, leftSubBody: LabelModel, rightLabel: LabelModel) {
self.heart = heart self.badge = badge
self.leftHeadline = leftHeadline self.leftHeadline = leftHeadline
self.leftBody = leftBody self.leftBody = leftBody
self.leftSubBody = leftSubBody self.leftSubBody = leftSubBody
@ -49,7 +49,7 @@ public class ListStoreLocatorModel: ListItemModel, MoleculeModelProtocol {
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case heart case badge
case leftHeadline case leftHeadline
case leftBody case leftBody
case leftSubBody case leftSubBody
@ -62,7 +62,7 @@ public class ListStoreLocatorModel: ListItemModel, MoleculeModelProtocol {
public required init(from decoder: Decoder) throws { public required init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
heart = try typeContainer.decodeIfPresent(HeartModel.self, forKey:.heart) badge = try typeContainer.decodeIfPresent(BadgeModel.self, forKey:.badge)
leftHeadline = try typeContainer.decode(LabelModel.self, forKey: .leftHeadline) leftHeadline = try typeContainer.decode(LabelModel.self, forKey: .leftHeadline)
leftBody = try typeContainer.decode(LabelModel.self, forKey: .leftBody) leftBody = try typeContainer.decode(LabelModel.self, forKey: .leftBody)
leftSubBody = try typeContainer.decode(LabelModel.self, forKey: .leftSubBody) leftSubBody = try typeContainer.decode(LabelModel.self, forKey: .leftSubBody)
@ -74,7 +74,7 @@ public class ListStoreLocatorModel: ListItemModel, MoleculeModelProtocol {
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(heart, forKey: .heart) try container.encodeIfPresent(badge, forKey: .badge)
try container.encode(leftHeadline, forKey: .leftHeadline) try container.encode(leftHeadline, forKey: .leftHeadline)
try container.encode(leftBody, forKey: .leftBody) try container.encode(leftBody, forKey: .leftBody)
try container.encode(leftSubBody, forKey: .leftSubBody) try container.encode(leftSubBody, forKey: .leftSubBody)

View File

@ -32,7 +32,7 @@ public class ListRightVariableButtonAllTextAndLinksModel: ListItemModel, Molecul
override public func setDefaults() { override public func setDefaults() {
super.setDefaults() super.setDefaults()
self.button.size = .tiny self.button.size = .small
self.button.style = .secondary self.button.style = .secondary
} }

View File

@ -6,15 +6,26 @@
// Copyright © 2020 Verizon Wireless. All rights reserved. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
open class DataLine: View {
@objcMembers open class ListRightVariableTotalData: TableViewCell { lazy var heightConstraint = heightAnchor.constraint(equalToConstant: 4)
lazy var widthConstraint = widthAnchor.constraint(equalToConstant: 20)
open override func setupView() {
super.setupView()
heightConstraint.isActive = true
widthConstraint.isActive = true
}
}
open class ListRightVariableTotalData: TableViewCell {
//----------------------------------------------------- //-----------------------------------------------------
// MARK: - Outlets // MARK: - Outlets
//----------------------------------------------------- //-----------------------------------------------------
public let leftLabel = Label(fontStyle: .BoldBodySmall) public let leftLabel = Label(fontStyle: .BoldBodySmall)
public let rightLabel = Label(fontStyle: .RegularBodySmall) public let rightLabel = Label(fontStyle: .RegularBodySmall)
public let bar = Line() public let bar = DataLine()
//----------------------------------------------------- //-----------------------------------------------------
// MARK: - Properties // MARK: - Properties
@ -44,8 +55,6 @@
override open func setupView() { override open func setupView() {
super.setupView() super.setupView()
bar.setStyle(.heavy)
bar.widthAnchor.constraint(equalToConstant: 20).isActive = true
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
addMolecule(stack) addMolecule(stack)
stack.restack() stack.restack()
@ -74,7 +83,6 @@
super.reset() super.reset()
leftLabel.setFontStyle(.BoldBodySmall) leftLabel.setFontStyle(.BoldBodySmall)
rightLabel.setFontStyle(.RegularBodySmall) rightLabel.setFontStyle(.RegularBodySmall)
bar.setStyle(.heavy)
} }
//-------------------------------------------------- //--------------------------------------------------

View File

@ -6,8 +6,18 @@
// Copyright © 2020 Verizon Wireless. All rights reserved. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
public struct DataLineModel: Codable, MoleculeModelProtocol {
public var id: String = UUID().uuidString
public static var identifier: String = "line"
public var backgroundColor: Color?
private enum CodingKeys: String, CodingKey {
case backgroundColor
}
}
public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtocol { public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -15,7 +25,7 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc
public static var identifier: String = "listRVLine" public static var identifier: String = "listRVLine"
public var leftLabel: LabelModel public var leftLabel: LabelModel
public var rightLabel: LabelModel public var rightLabel: LabelModel
public var bar: LineModel public var bar: DataLineModel
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Method // MARK: - Method
@ -24,8 +34,6 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc
override public func setDefaults() { override public func setDefaults() {
super.setDefaults() super.setDefaults()
rightLabel.hero = 0 rightLabel.hero = 0
bar.type = .heavy
if bar.backgroundColor == nil { if bar.backgroundColor == nil {
bar.backgroundColor = Color(uiColor: .mvmBlue) bar.backgroundColor = Color(uiColor: .mvmBlue)
} }
@ -35,7 +43,7 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(leftLabel: LabelModel, rightlabel:LabelModel, bar: LineModel){ public init(leftLabel: LabelModel, rightlabel:LabelModel, bar: DataLineModel) {
self.leftLabel = leftLabel self.leftLabel = leftLabel
self.rightLabel = rightlabel self.rightLabel = rightlabel
self.bar = bar self.bar = bar
@ -46,7 +54,7 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc
// MARK: - Keys // MARK: - Keys
//-------------------------------------------------- //--------------------------------------------------
private enum CodingKeys: String, CodingKey{ private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case leftLabel case leftLabel
case rightLabel case rightLabel
@ -61,7 +69,7 @@ public class ListRightVariableTotalDataModel: ListItemModel, MoleculeModelProtoc
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel)
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
bar = try typeContainer.decode(LineModel.self, forKey: .bar) bar = try typeContainer.decode(DataLineModel.self, forKey: .bar)
try super.init(from: decoder) try super.init(from: decoder)
} }

View File

@ -24,5 +24,14 @@
if bottomPadding == nil { if bottomPadding == nil {
bottomPadding = PaddingDefaultVerticalSpacing bottomPadding = PaddingDefaultVerticalSpacing
} }
guard !MVMCoreGetterUtility.isOnIPad(),
horizontalAlignment == nil else { return }
if let _ = molecule as? ButtonModel {
horizontalAlignment = .fill
} else if let model = molecule as? TwoButtonViewModel,
model.primaryButton == nil || model.secondaryButton == nil {
horizontalAlignment = .fill
}
} }
} }

View File

@ -50,7 +50,7 @@ import VDSColorTokens
setItems(tabs, animated: false) setItems(tabs, animated: false)
selectedItem = tabs[model.selectedTab] selectedItem = tabs[model.selectedTab]
guard let lineModel = line.lineModel else { return } guard let lineModel = line.viewModel else { return }
lineModel.inverted = model.style == .dark lineModel.inverted = model.style == .dark
line.set(with: lineModel, delegateObject, additionalData) line.set(with: lineModel, delegateObject, additionalData)
} }

View File

@ -174,7 +174,7 @@ import VDSColorTokens
self.additionalData = additionalData self.additionalData = additionalData
selectedIndex = tabsModel?.selectedIndex ?? 0 selectedIndex = tabsModel?.selectedIndex ?? 0
selectionLine.backgroundColor = tabsModel?.selectedBarColor.uiColor selectionLine.backgroundColor = tabsModel?.selectedBarColor.uiColor
let lineModel = bottomLine.lineModel ?? LineModel(type: .secondary) let lineModel = bottomLine.viewModel ?? LineModel(type: .secondary)
lineModel.inverted = tabsModel?.style == .dark lineModel.inverted = tabsModel?.style == .dark
bottomLine.set(with: lineModel, delegateObject, additionalData) bottomLine.set(with: lineModel, delegateObject, additionalData)
reloadData() reloadData()

View File

@ -7,7 +7,7 @@
// //
import UIKit import UIKit
import VDS
@objcMembers open class TwoButtonView: View, MVMCoreUIViewConstrainingProtocol { @objcMembers open class TwoButtonView: View, MVMCoreUIViewConstrainingProtocol {
//-------------------------------------------------- //--------------------------------------------------
@ -29,9 +29,8 @@ import UIKit
//-------------------------------------------------- //--------------------------------------------------
public func setDefaultAppearance() { public func setDefaultAppearance() {
primaryButton.use = .primary
primaryButton.stylePrimary() secondaryButton.use = .secondary
secondaryButton.styleSecondary()
} }
open override func updateView(_ size: CGFloat) { open override func updateView(_ size: CGFloat) {

View File

@ -7,7 +7,7 @@
// //
import UIKit import UIKit
import VDS
public class TwoButtonViewModel: ParentMoleculeModelProtocol { public class TwoButtonViewModel: ParentMoleculeModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
@ -56,13 +56,13 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol {
//set context value for 'primary' style to be set for the primaryButton in case the //set context value for 'primary' style to be set for the primaryButton in case the
//property is not returned in the JSON and once decoded, this value is removed from the context //property is not returned in the JSON and once decoded, this value is removed from the context
try decoder.setContext(value: Styler.Button.Style.primary, for: "style") { try decoder.setContext(value: Use.primary, for: "style") {
self.primaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .primaryButton) self.primaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .primaryButton)
} }
//set context value for 'secondary' style to be set for the primaryButton in case the //set context value for 'secondary' style to be set for the primaryButton in case the
//property is not returned in the JSON and once decoded, this value is removed from the context //property is not returned in the JSON and once decoded, this value is removed from the context
try decoder.setContext(value: Styler.Button.Style.secondary, for: "style") { try decoder.setContext(value: Use.secondary, for: "style") {
self.secondaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .secondaryButton) self.secondaryButton = try typeContainer.decodeMoleculeIfPresent(codingKey: .secondaryButton)
} }
} }

View File

@ -89,15 +89,13 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol {
} }
} }
button?.size = .tiny button?.size = .small
button?.style = .secondary button?.style = .secondary
switch style { switch style {
case .error, .warning: case .error, .warning:
button?.enabledTextColor = Color(uiColor: .mvmBlack) button?.inverted = false
button?.enabledBorderColor = Color(uiColor: .mvmBlack)
default: default:
button?.enabledTextColor = Color(uiColor: .mvmWhite) button?.inverted = true
button?.enabledBorderColor = Color(uiColor: .mvmWhite)
} }
if closeButton?.color == nil { if closeButton?.color == nil {

View File

@ -15,7 +15,7 @@ import Foundation
public let headline = Label(fontStyle: .BoldBodySmall) public let headline = Label(fontStyle: .BoldBodySmall)
public let body = Label(fontStyle: .RegularBodySmall) public let body = Label(fontStyle: .RegularBodySmall)
public let button = PillButton(asPrimaryButton: false, makeTiny: true) public let button = PillButton()
public let closeButton = NotificationXButton() public let closeButton = NotificationXButton()
public var labelStack: Stack<StackModel>! public var labelStack: Stack<StackModel>!
public var horizontalStack: Stack<StackModel>! public var horizontalStack: Stack<StackModel>!

View File

@ -54,7 +54,7 @@ public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtoc
image.height = BGImageHeadlineBodyButton.heightConstant image.height = BGImageHeadlineBodyButton.heightConstant
} }
button?.size = .tiny button?.size = .small
button?.style = .secondary button?.style = .secondary
} }

View File

@ -64,7 +64,7 @@
headlineBody.headlineLabel.font = Styler.Font.BoldTitleMedium.getFont() headlineBody.headlineLabel.font = Styler.Font.BoldTitleMedium.getFont()
headlineBody.messageLabel.font = Styler.Font.RegularMicro.getFont() headlineBody.messageLabel.font = Styler.Font.RegularMicro.getFont()
button.styleSecondary() button.use = .secondary
button.isHidden = false button.isHidden = false
buttonHeadlinePadding = PaddingTwo buttonHeadlinePadding = PaddingTwo
} }

View File

@ -38,7 +38,7 @@ public class HeadlineBodyButtonModel: MoleculeModelProtocol {
/// Defaults to set /// Defaults to set
public func setDefaults() { public func setDefaults() {
button.size = .tiny button.size = .small
button.style = .secondary button.style = .secondary
} }

View File

@ -372,7 +372,9 @@ open class Carousel: View {
self.carouselAccessibilityElement = carouselAccessibilityElement self.carouselAccessibilityElement = carouselAccessibilityElement
} }
if let currentCell = collectionView.cellForItem(at: IndexPath(row: currentIndex, section: 0)) { if let currentCell = collectionView.cellForItem(at: IndexPath(row: currentIndex, section: 0)), let pagingView = self.pagingView {
_accessibilityElements = [currentCell, carouselAccessibilityElement, pagingView]
} else if let currentCell = collectionView.cellForItem(at: IndexPath(row: currentIndex, section: 0)) {
_accessibilityElements = [currentCell, carouselAccessibilityElement] _accessibilityElements = [currentCell, carouselAccessibilityElement]
} else { } else {
_accessibilityElements = [carouselAccessibilityElement] _accessibilityElements = [carouselAccessibilityElement]
@ -384,7 +386,7 @@ open class Carousel: View {
extension Carousel: UICollectionViewDelegateFlowLayout { extension Carousel: UICollectionViewDelegateFlowLayout {
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let itemWidth = collectionView.bounds.width * itemWidthPercent let itemWidth = (collectionView.bounds.width - collectionView.contentInset.left - collectionView.contentInset.right) * itemWidthPercent
return CGSize(width: itemWidth, height: collectionView.bounds.height) return CGSize(width: itemWidth, height: collectionView.bounds.height)
} }

View File

@ -0,0 +1,18 @@
//
// VDS-Interpreters.swift
// MVMCoreUI
//
// Created by Matt Bruce on 9/20/23.
// Copyright © 2023 Verizon Wireless. All rights reserved.
//
import Foundation
import VDS
public protocol Invertable {
var inverted: Bool { get set }
}
extension Invertable {
public var surface: Surface { return inverted ? .dark : .light }
}

View File

@ -28,5 +28,9 @@ extension VDSMoleculeViewProtocol {
viewModel = castedModel viewModel = castedModel
viewModelDidUpdate() viewModelDidUpdate()
} }
public func update(viewModel: ViewModel){
set(with: viewModel, delegateObject, additionalData)
}
} }

View File

@ -82,13 +82,6 @@ public extension UINavigationController {
} }
} }
/// Returns a ShadowImage based on the line property of NavigationItemModelProtocol
func getNavigationBarShadowImage(for navigationItemModel: NavigationItemModelProtocol) -> UIImage? {
guard let thickness = navigationItemModel.line?.thickness,
let backgroundColor = navigationItemModel.line?.backgroundColor else { return nil }
return backgroundColor.uiColor.image(CGSize(width: thickness, height: thickness))
}
/// Convenience function for setting the navigation bar ui /// Convenience function for setting the navigation bar ui
@MainActor @MainActor
func setNavigationBarUI(with model: NavigationItemModelProtocol) { func setNavigationBarUI(with model: NavigationItemModelProtocol) {
@ -105,24 +98,30 @@ public extension UINavigationController {
appearance.backgroundColor = backgroundColor appearance.backgroundColor = backgroundColor
appearance.titleTextAttributes.updateValue(tint, forKey: .foregroundColor) appearance.titleTextAttributes.updateValue(tint, forKey: .foregroundColor)
appearance.titlePositionAdjustment = model.titleOffset ?? .zero appearance.titlePositionAdjustment = model.titleOffset ?? .zero
if let type = model.line?.type, appearance.setShadow(for: model.line)
type != .none,
let color = model.line?.backgroundColor {
appearance.shadowColor = color.uiColor
} else {
appearance.shadowColor = .clear
}
appearance.shadowImage = getNavigationBarShadowImage(for: model)?.withRenderingMode(.alwaysTemplate)
navigationBar.standardAppearance = appearance navigationBar.standardAppearance = appearance
navigationBar.scrollEdgeAppearance = appearance navigationBar.scrollEdgeAppearance = appearance
setNavigationBarHidden(model.hidden, animated: true) setNavigationBarHidden(model.hidden, animated: true)
} }
@MainActor @objc @MainActor
func getViewController() -> UIViewController? { func getViewController() -> UIViewController? {
guard let topViewController = getViewControllers().last, guard let topViewController = getViewControllers().last,
let viewController = MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController) else { return nil } let viewController = MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController) else { return nil }
return viewController return viewController
} }
} }
public extension UINavigationBarAppearance {
func setShadow(for model: LineModel?) {
let model = model ?? LineModel(type: .secondary)
let line = Line(model: model, nil, nil)
if line.shouldBeVisible() {
shadowColor = line.lineColor
} else {
shadowColor = .clear
}
shadowImage = line.lineColor.image(CGSize(width: line.lineWidth, height: line.lineWidth)).withRenderingMode(.alwaysTemplate)
}
}

View File

@ -125,13 +125,14 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
/// Hides/Shows the navigation bar for the page. /// Hides/Shows the navigation bar for the page.
open func hideNavigationBarLine(_ isHidden: Bool) { open func hideNavigationBarLine(_ isHidden: Bool) {
guard self == navigationController?.topViewController else { return } guard self == navigationController?.topViewController else { return }
var color = UIColor.clear var model: LineModel?
if !isHidden, if isHidden {
let backgroundColor = (getCurrentViewController() as? PageProtocol)?.pageModel?.navigationBar?.line?.backgroundColor?.uiColor { model = LineModel(type: .none)
color = backgroundColor } else if let lineModel = (getCurrentViewController() as? PageProtocol)?.pageModel?.navigationBar?.line {
model = lineModel
} }
navigationController?.navigationBar.standardAppearance.shadowColor = color navigationController?.navigationBar.standardAppearance.setShadow(for: model)
navigationController?.navigationBar.scrollEdgeAppearance?.shadowColor = color navigationController?.navigationBar.scrollEdgeAppearance?.setShadow(for: model)
} }
open override func updateViews() { open override func updateViews() {

View File

@ -72,6 +72,7 @@ open class CoreUIModelMapping: ModelMapping {
ModelRegistry.register(handler: LoadingSpinner.self, for: LoadingSpinnerModel.self) ModelRegistry.register(handler: LoadingSpinner.self, for: LoadingSpinnerModel.self)
ModelRegistry.register(handler: Video.self, for: VideoModel.self) ModelRegistry.register(handler: Video.self, for: VideoModel.self)
ModelRegistry.register(handler: Tilelet.self, for: TileletModel.self) ModelRegistry.register(handler: Tilelet.self, for: TileletModel.self)
ModelRegistry.register(handler: Badge.self, for: BadgeModel.self)
// MARK:- Horizontal Combination Molecules // MARK:- Horizontal Combination Molecules
ModelRegistry.register(handler: StringAndMoleculeView.self, for: StringAndMoleculeModel.self) ModelRegistry.register(handler: StringAndMoleculeView.self, for: StringAndMoleculeModel.self)

View File

@ -159,42 +159,6 @@ open class Styler {
} }
} }
public enum Button {
public enum Style: String, Codable {
case primary
case secondary
}
///MVA 3.0 - Button sizes are standard(default size), small, Tiny. Tiny button has been depricated as of Rebranding 3.0.
public enum Size: String, Codable {
case standard
case small
case tiny
func getHeight() -> CGFloat {
switch self {
case .standard:
return 44
case .small:
return 32
case .tiny:
return 20
}
}
func minimumWidth() -> CGFloat {
switch self {
case .standard:
return 76
case .small:
return 0
case .tiny:
return 49
}
}
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Functions // MARK: - Functions
//-------------------------------------------------- //--------------------------------------------------

View File

@ -57,9 +57,10 @@ public extension MVMCoreUIUtility {
return findViews(by: type, views: queue) + matching return findViews(by: type, views: queue) + matching
} }
@MainActor
static func visibleNavigationBarStlye() -> NavigationItemStyle? { static func visibleNavigationBarStlye() -> NavigationItemStyle? {
if let vc = MVMCoreUIUtility.getCurrentVisibleController(), if let navController = NavigationController.navigationController(),
let navController = NavigationController.navigationController(), let vc = navController.getViewController(),
let navigationBar = navController.getNavigationModel(from: vc) as? NavigationItemModel { let navigationBar = navController.getNavigationModel(from: vc) as? NavigationItemModel {
return navigationBar.style return navigationBar.style
} }

View File

@ -0,0 +1,35 @@
//
// RawRepresentableCodable.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 9/14/23.
// Copyright © 2023 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol RawRepresentableCodable: RawRepresentable, Codable where RawValue: Hashable & Decodable {
static var mapping: [RawValue: Self] { get }
static var defaultValue: Self? { get }
}
public enum RawRepresentableCodableError: Swift.Error {
case invalid(value: String)
}
extension RawRepresentableCodable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let rawValue = try container.decode(RawValue.self)
if let found = Self(rawValue: rawValue) {
self = found
} else if let found = Self.mapping[rawValue] {
self = found
} else if let defaultValue = Self.defaultValue {
self = defaultValue
} else {
throw RawRepresentableCodableError.invalid(value: "\(rawValue)")
}
}
}