From d93925b503d1fc56405ad7a0868a4dcf2618c44c Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 7 Mar 2024 14:59:20 -0600 Subject: [PATCH 01/43] fixed issues with BadgeIndicator Values on the custom styles Signed-off-by: Matt Bruce --- .../BadgeIndicator/BadgeIndicator.swift | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/VDS/Components/BadgeIndicator/BadgeIndicator.swift b/VDS/Components/BadgeIndicator/BadgeIndicator.swift index 45432458..bcacfe84 100644 --- a/VDS/Components/BadgeIndicator/BadgeIndicator.swift +++ b/VDS/Components/BadgeIndicator/BadgeIndicator.swift @@ -84,47 +84,59 @@ open class BadgeIndicator: View { /// Dynamic TextStyle for the size. public var textStyle: TextStyle { - let style = TextStyle.bodySmall + var font: Font = .edsRegular var pointSize: CGFloat = VDSTypography.fontSizeBody12 var letterSpacing: CGFloat = 0.0 + var lineHeight: CGFloat = 0.0 + var edgeInsets: UIEdgeInsets = .zero + switch self { case .xxlarge: pointSize = VDSTypography.fontSizeTitle24 letterSpacing = VDSTypography.letterSpacingWide - + lineHeight = VDSTypography.lineHeightTitle24 + case .xlarge: pointSize = VDSTypography.fontSizeTitle20 + lineHeight = VDSTypography.lineHeightTitle20 case .large: pointSize = VDSTypography.fontSizeBody16 letterSpacing = VDSTypography.letterSpacingWide + lineHeight = VDSTypography.lineHeightBody16 case .medium: pointSize = VDSTypography.fontSizeBody14 letterSpacing = VDSTypography.letterSpacingWide + lineHeight = 14.0 + case .small: + font = .etxRegular pointSize = VDSTypography.fontSizeBody12 + lineHeight = 12.0 } + return TextStyle(rawValue: "\(self.rawValue)BadgeIndicator", - fontFace: style.fontFace, + fontFace: font, pointSize: pointSize, - lineHeight: 0, - letterSpacing: letterSpacing) + lineHeight: lineHeight, + letterSpacing: letterSpacing, + edgeInsets: edgeInsets) } //EdgeInsets for the label. public var edgeInset: UIEdgeInsets { - var horizontalPadding: CGFloat = VDSLayout.Spacing.space1X.value - let verticalPadding: CGFloat = 0 + var horizontalPadding: CGFloat = 0.0 + let verticalPadding: CGFloat = 2.0 switch self { case .xxlarge: horizontalPadding = VDSLayout.Spacing.space2X.value - case .xlarge, .large,.medium: + case .xlarge, .large, .medium: horizontalPadding = 6.0 case .small: - break + horizontalPadding = VDSLayout.Spacing.space1X.value } return .axis(horizontal: horizontalPadding, vertical: verticalPadding) } @@ -345,6 +357,7 @@ open class BadgeIndicator: View { label.sizeToFit() setNeedsLayout() layoutIfNeeded() + label.debugBorder(color: .green) } open override func layoutSubviews() { From 0dec879785b69b59d91075b4a65f8e197df64c59 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 27 Mar 2024 15:55:59 -0500 Subject: [PATCH 02/43] updated release notes and version Signed-off-by: Matt Bruce --- VDS.xcodeproj/project.pbxproj | 30 ++++++++++++++-------------- VDS/SupportingFiles/ReleaseNotes.txt | 8 ++++++++ 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index 580022a0..681d16b5 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -7,11 +7,11 @@ objects = { /* Begin PBXBuildFile section */ + 1808BEBC2BA41C3200129230 /* CarouselScrollbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */; }; + 1808BEC02BA456B700129230 /* CarouselScrollbarChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */; }; 1832AC572BA0791D008AE476 /* BreadcrumbCellItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1832AC562BA0791D008AE476 /* BreadcrumbCellItem.swift */; }; 18450CF12BA1B19C009FDF2A /* BreadcrumbsChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 18450CF02BA1B19C009FDF2A /* BreadcrumbsChangeLog.txt */; }; 1855EC662BAABF2A002ACAC2 /* BreadcrumbItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1855EC652BAABF2A002ACAC2 /* BreadcrumbItemModel.swift */; }; - 1808BEBC2BA41C3200129230 /* CarouselScrollbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */; }; - 1808BEC02BA456B700129230 /* CarouselScrollbarChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */; }; 186B2A8A2B88DA7F001AB71F /* TextAreaChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 186B2A892B88DA7F001AB71F /* TextAreaChangeLog.txt */; }; 18792A902B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */; }; 18A65A022B96E848006602CC /* Breadcrumbs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A65A012B96E848006602CC /* Breadcrumbs.swift */; }; @@ -196,11 +196,11 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselScrollbar.swift; sourceTree = ""; }; + 1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CarouselScrollbarChangeLog.txt; sourceTree = ""; }; 1832AC562BA0791D008AE476 /* BreadcrumbCellItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbCellItem.swift; sourceTree = ""; }; 18450CF02BA1B19C009FDF2A /* BreadcrumbsChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = BreadcrumbsChangeLog.txt; sourceTree = ""; }; 1855EC652BAABF2A002ACAC2 /* BreadcrumbItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbItemModel.swift; sourceTree = ""; }; - 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselScrollbar.swift; sourceTree = ""; }; - 1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CarouselScrollbarChangeLog.txt; sourceTree = ""; }; 186B2A892B88DA7F001AB71F /* TextAreaChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TextAreaChangeLog.txt; sourceTree = ""; }; 18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIconBadgeIndicatorModel.swift; sourceTree = ""; }; 18A65A012B96E848006602CC /* Breadcrumbs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Breadcrumbs.swift; sourceTree = ""; }; @@ -398,6 +398,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 1808BEBA2BA41B1D00129230 /* CarouselScrollbar */ = { + isa = PBXGroup; + children = ( + 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */, + 1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */, + ); + path = CarouselScrollbar; + sourceTree = ""; + }; 18A65A002B96E7E1006602CC /* Breadcrumbs */ = { isa = PBXGroup; children = ( @@ -410,15 +419,6 @@ path = Breadcrumbs; sourceTree = ""; }; - 1808BEBA2BA41B1D00129230 /* CarouselScrollbar */ = { - isa = PBXGroup; - children = ( - 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */, - 1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */, - ); - path = CarouselScrollbar; - sourceTree = ""; - }; 445BA07629C07ABA0036A7C5 /* Notification */ = { isa = PBXGroup; children = ( @@ -1369,7 +1369,7 @@ BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 55; + CURRENT_PROJECT_VERSION = 56; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1406,7 +1406,7 @@ BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 55; + CURRENT_PROJECT_VERSION = 56; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; diff --git a/VDS/SupportingFiles/ReleaseNotes.txt b/VDS/SupportingFiles/ReleaseNotes.txt index e1cd12fd..d1ad181e 100644 --- a/VDS/SupportingFiles/ReleaseNotes.txt +++ b/VDS/SupportingFiles/ReleaseNotes.txt @@ -1,3 +1,11 @@ +1.0.56 +---------------- +- ONEAPP-7190 - Breadcrumbs - Finished Development +- ONEAPP-6830 - CarouselScrollbar - Finished Development +- ONEAPP-6978 - Pagination - Finished Development +- ONEAPP-6984 - Tilelet - Finished Development +- ONEAPP-6682 - TextArea - Finished Development + 1.0.55 ---------------- - ONEAPP-6305 - BadgeIndicator - Finished Development From 880245d94e6fd2fcb149f19fc8f6f01f8750ac27 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 28 Mar 2024 09:23:06 -0500 Subject: [PATCH 03/43] updated accessibility for ButtonIcon Signed-off-by: Matt Bruce --- VDS/Components/Icon/ButtonIcon/ButtonIcon.swift | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift b/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift index 65968214..738881e3 100644 --- a/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift +++ b/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift @@ -108,7 +108,10 @@ open class ButtonIcon: Control, Changeable, FormFieldable { open var badgeIndicatorModel: BadgeIndicatorModel? { didSet { setNeedsUpdate() } } /// Icon object used to render out the Icon for this ButtonIcon. - open var icon = Icon().with { $0.isUserInteractionEnabled = false } + open var icon = Icon().with { + $0.isUserInteractionEnabled = false + $0.accessibilityTraits = .button + } /// Determines the type of button based on the contrast. open var kind: Kind = .ghost { didSet { setNeedsUpdate() } } @@ -342,9 +345,8 @@ open class ButtonIcon: Control, Changeable, FormFieldable { /// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations. open override func setup() { super.setup() - isAccessibilityElement = true - accessibilityTraits = .button - accessibilityElements = [badgeIndicator] + isAccessibilityElement = false + accessibilityElements = [icon, badgeIndicator] //create a layoutGuide for the icon to key off of let iconLayoutGuide = UILayoutGuide() From d1a320d44bce2c5fddc54c617b88276d076a5c83 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 28 Mar 2024 09:23:26 -0500 Subject: [PATCH 04/43] refactored out broken accessibility for notification Signed-off-by: Matt Bruce --- VDS/Components/Notification/Notification.swift | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/VDS/Components/Notification/Notification.swift b/VDS/Components/Notification/Notification.swift index cc011249..7dd36b4c 100644 --- a/VDS/Components/Notification/Notification.swift +++ b/VDS/Components/Notification/Notification.swift @@ -247,6 +247,11 @@ open class Notification: View { subTitleLabel.textColorConfiguration = textColorConfiguration.eraseToAnyColorable() //TODO: Need to add setup animation for displaying the Notification view for iOS. + isAccessibilityElement = false + accessibilityElements = [closeButton, typeIcon, titleLabel, subTitleLabel, buttonGroup] + closeButton.accessibilityTraits = [.button] + closeButton.accessibilityLabel = "Close Notification" + } /// Resets to default settings. @@ -298,17 +303,7 @@ open class Notification: View { super.layoutSubviews() layer.cornerRadius = UIScreen.main.bounds.width == bounds.width ? 0 : 4.0 } - - ///Updating the accessiblity values i.e elements, label, value other items for the component. - open override func updateAccessibility() { - super.updateAccessibility() - accessibilityElements = [closeButton, typeIcon, titleLabel, subTitleLabel, buttonGroup] - typeIcon.accessibilityLabel = style.rawValue - typeIcon.imageView.image?.isAccessibilityElement = false - closeButton.accessibilityTraits = [.button] - closeButton.accessibilityLabel = "Close Notification" - } - + //-------------------------------------------------- // MARK: - Private Methods //-------------------------------------------------- From 7be09ebb8a14db3c5ff24fd45b50cef0572e6cc2 Mon Sep 17 00:00:00 2001 From: vasavk Date: Tue, 2 Apr 2024 10:40:18 +0530 Subject: [PATCH 05/43] Digital ACT-191 ONEAPP-7135 story: added new page --- VDS.xcodeproj/project.pbxproj | 38 ++++++++++++------- .../DropdownSelect/DropdownSelect.swift | 32 ++++++++++++++++ 2 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 VDS/Components/DropdownSelect/DropdownSelect.swift diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index 580022a0..7bf3c054 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -7,12 +7,13 @@ objects = { /* Begin PBXBuildFile section */ + 1808BEBC2BA41C3200129230 /* CarouselScrollbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */; }; + 1808BEC02BA456B700129230 /* CarouselScrollbarChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */; }; 1832AC572BA0791D008AE476 /* BreadcrumbCellItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1832AC562BA0791D008AE476 /* BreadcrumbCellItem.swift */; }; 18450CF12BA1B19C009FDF2A /* BreadcrumbsChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 18450CF02BA1B19C009FDF2A /* BreadcrumbsChangeLog.txt */; }; 1855EC662BAABF2A002ACAC2 /* BreadcrumbItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1855EC652BAABF2A002ACAC2 /* BreadcrumbItemModel.swift */; }; - 1808BEBC2BA41C3200129230 /* CarouselScrollbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */; }; - 1808BEC02BA456B700129230 /* CarouselScrollbarChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */; }; 186B2A8A2B88DA7F001AB71F /* TextAreaChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 186B2A892B88DA7F001AB71F /* TextAreaChangeLog.txt */; }; + 186D13CB2BBA8B1500986B53 /* DropdownSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 186D13CA2BBA8B1500986B53 /* DropdownSelect.swift */; }; 18792A902B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */; }; 18A65A022B96E848006602CC /* Breadcrumbs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A65A012B96E848006602CC /* Breadcrumbs.swift */; }; 18A65A042B96F050006602CC /* BreadcrumbItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A65A032B96F050006602CC /* BreadcrumbItem.swift */; }; @@ -196,12 +197,13 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselScrollbar.swift; sourceTree = ""; }; + 1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CarouselScrollbarChangeLog.txt; sourceTree = ""; }; 1832AC562BA0791D008AE476 /* BreadcrumbCellItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbCellItem.swift; sourceTree = ""; }; 18450CF02BA1B19C009FDF2A /* BreadcrumbsChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = BreadcrumbsChangeLog.txt; sourceTree = ""; }; 1855EC652BAABF2A002ACAC2 /* BreadcrumbItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbItemModel.swift; sourceTree = ""; }; - 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselScrollbar.swift; sourceTree = ""; }; - 1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CarouselScrollbarChangeLog.txt; sourceTree = ""; }; 186B2A892B88DA7F001AB71F /* TextAreaChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TextAreaChangeLog.txt; sourceTree = ""; }; + 186D13CA2BBA8B1500986B53 /* DropdownSelect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropdownSelect.swift; sourceTree = ""; }; 18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIconBadgeIndicatorModel.swift; sourceTree = ""; }; 18A65A012B96E848006602CC /* Breadcrumbs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Breadcrumbs.swift; sourceTree = ""; }; 18A65A032B96F050006602CC /* BreadcrumbItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbItem.swift; sourceTree = ""; }; @@ -398,6 +400,23 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 1808BEBA2BA41B1D00129230 /* CarouselScrollbar */ = { + isa = PBXGroup; + children = ( + 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */, + 1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */, + ); + path = CarouselScrollbar; + sourceTree = ""; + }; + 186D13C92BBA8A3500986B53 /* DropdownSelect */ = { + isa = PBXGroup; + children = ( + 186D13CA2BBA8B1500986B53 /* DropdownSelect.swift */, + ); + path = DropdownSelect; + sourceTree = ""; + }; 18A65A002B96E7E1006602CC /* Breadcrumbs */ = { isa = PBXGroup; children = ( @@ -410,15 +429,6 @@ path = Breadcrumbs; sourceTree = ""; }; - 1808BEBA2BA41B1D00129230 /* CarouselScrollbar */ = { - isa = PBXGroup; - children = ( - 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */, - 1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */, - ); - path = CarouselScrollbar; - sourceTree = ""; - }; 445BA07629C07ABA0036A7C5 /* Notification */ = { isa = PBXGroup; children = ( @@ -569,6 +579,7 @@ EA0FC2BE2912D18200DF80B4 /* Buttons */, 1808BEBA2BA41B1D00129230 /* CarouselScrollbar */, EAF7F092289985E200B287F5 /* Checkbox */, + 186D13C92BBA8A3500986B53 /* DropdownSelect */, EA985BF3296C609E00F2FF2E /* Icon */, EA3362412892EF700071C351 /* Label */, 44604AD529CE195300E62B51 /* Line */, @@ -1180,6 +1191,7 @@ 1808BEBC2BA41C3200129230 /* CarouselScrollbar.swift in Sources */, EAF978212A99035B00C2FEA9 /* Enabling.swift in Sources */, EA5E3058295105A40082B959 /* Tilelet.swift in Sources */, + 186D13CB2BBA8B1500986B53 /* DropdownSelect.swift in Sources */, EA89201528B56CF4006B9984 /* RadioBoxGroup.swift in Sources */, EA0B180A2AA78F9000F2D0CD /* UIEdgeInsets.swift in Sources */, EA985C1D296CD13600F2FF2E /* BundleManager.swift in Sources */, diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift new file mode 100644 index 00000000..35c48a4f --- /dev/null +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -0,0 +1,32 @@ +// +// DropdownSelect.swift +// VDS +// +// Created by Kanamarlapudi, Vasavi on 28/03/24. +// + +import Foundation +import UIKit +import VDSColorTokens +import VDSFormControlsTokens +import Combine + +@objc(VDSDropdownSelect) +open class DropdownSelect: Control { + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + required public init() { + super.init(frame: .zero) + } + + public override init(frame: CGRect) { + super.init(frame: .zero) + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + } + +} From 847f74f6597409b19c7a44f8458581c20e0d3da5 Mon Sep 17 00:00:00 2001 From: vasavk Date: Tue, 2 Apr 2024 10:44:20 +0530 Subject: [PATCH 06/43] Digital ACT-191 ONEAPP-7135 story: added DropdownSelect to VDS.md --- VDS/VDS.docc/VDS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/VDS/VDS.docc/VDS.md b/VDS/VDS.docc/VDS.md index 63956f83..607e09f5 100755 --- a/VDS/VDS.docc/VDS.md +++ b/VDS/VDS.docc/VDS.md @@ -29,6 +29,7 @@ Using the system allows designers and developers to collaborate more easily and - ``Checkbox`` - ``CheckboxItem`` - ``CheckboxGroup`` +- ``DropdownSelect`` - ``Icon`` - ``InputField`` - ``Label`` From 530a6786d8fd842da8363373687f4abcec53af3e Mon Sep 17 00:00:00 2001 From: vasavk Date: Tue, 2 Apr 2024 14:37:02 +0530 Subject: [PATCH 07/43] Digital ACT-191 ONEAPP-7135 story: design changes --- .../DropdownSelect/DropdownSelect.swift | 439 ++++++++++++++++++ 1 file changed, 439 insertions(+) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index 35c48a4f..d7613f94 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -11,6 +11,7 @@ import VDSColorTokens import VDSFormControlsTokens import Combine +/// A dropdown select is an expandable menu of predefined options that allows a customer to make a single selection. @objc(VDSDropdownSelect) open class DropdownSelect: Control { @@ -29,4 +30,442 @@ open class DropdownSelect: Control { super.init(coder: coder) } + //-------------------------------------------------- + // MARK: - Public Properties + //-------------------------------------------------- + + ///Boolean value that determines if component should show the error state/error message. + open var error: Bool = false { didSet { setNeedsUpdate() }} + + /// Message displayed when there is an error. + open var errorText: String? { didSet { setNeedsUpdate() }} + + /// If provided, will be used as text for the helper label. + open var helperText: String? { didSet { setNeedsUpdate() }} + + /// used if the component is enabled or not. + open override var isEnabled: Bool { didSet { setNeedsUpdate() }} + + /// If true, the label will be displayed inside the dropdown container. Otherwise, the label will be above the dropdown container like a normal text input. + open var inlineLabel: Bool = false { didSet { setNeedsUpdate() }} + + /// If provided, will be used as context for the label on the input field. + open var label: String? { didSet { setNeedsUpdate() }} + + /// Not allowed the user interaction to select/change input if it is true. + open var readOnly: Bool = false { didSet { setNeedsUpdate() }} + + /// Used to show optional indicator for the label. + open var required: Bool = false { didSet { setNeedsUpdate() }} + + /// Allows unique ID to be passed to the element. + open var selectId: String? { didSet { setNeedsUpdate() }} + + // TO DO: either have model or individual title and content. + /// Config object for tooltip option, is optional. + open var tooltipModel: Tooltip.TooltipModel? { didSet { setNeedsUpdate() } } + + /// Used to set tooltip title. + open var tooltipTitle: String { + get { return _tooltipTitle } + set { + _tooltipTitle = newValue + updateTooltip() + setNeedsUpdate() + } + } + + /// Used to set tooltip content. + open var tooltipContent: String { + get { return _tooltipContent } + set { + _tooltipContent = newValue + updateTooltip() + setNeedsUpdate() + } + } + + /// If provided, will render with trnasparent background. + open var transparentBackground: Bool = false { didSet { setNeedsUpdate() }} + + /// Used to set width for the Dropdown Select. + open var width: Int? { didSet { setNeedsUpdate() }} + + // TO DO: create model for options + open var options: [String]? { didSet { setNeedsUpdate() }} + + ///Boolean or a Function that returns a boolean value that determines if component should show the error state/error message.Functon receives the 'event' object on input change. + open var showError: Bool = false { didSet { setNeedsUpdate() }} + + open override var state: UIControl.State { + get { + var state = super.state + if showError { + state.insert(.error) + } + return state + } + } + + //-------------------------------------------------- + // MARK: - Private Properties + //-------------------------------------------------- + internal var _tooltipTitle: String = "" + + internal var _tooltipContent: String = "" + + internal var minWidthDefault = 66.0 + internal var minWidthInlineLabel = 102.0 + + var stackView: UIStackView = UIStackView().with { + $0.translatesAutoresizingMaskIntoConstraints = false + $0.axis = .vertical + } + + private var eyebrowLabel = TrailingTooltipLabel().with { + $0.setContentCompressionResistancePriority(.required, for: .vertical) + $0.labelTextAlignment = .left + $0.labelTextStyle = .bodySmall + } + + var container: UIView = UIView().with { + $0.translatesAutoresizingMaskIntoConstraints = false + } + + var containerStack: UIStackView = UIStackView().with { + $0.translatesAutoresizingMaskIntoConstraints = false + $0.axis = .horizontal + $0.spacing = VDSFormControls.spaceInset + } + + private var dropdownField = UITextField().with { + $0.translatesAutoresizingMaskIntoConstraints = false + $0.tintColor = UIColor.clear + $0.font = TextStyle.bodyLarge.font + } + + private var inlineDisplayLabel = Label().with { + $0.textAlignment = .left + $0.textStyle = .boldBodyLarge + $0.sizeToFit() + } + + private var selectedOptionLabel = Label().with { + $0.setContentCompressionResistancePriority(.required, for: .vertical) + $0.textAlignment = .left + $0.textStyle = .bodyLarge + } + + private var icon: Icon = Icon().with { + $0.size = .medium + $0.name = Icon.Name(name: "down-caret") + } + + private var errorLabel = Label().with { + $0.setContentCompressionResistancePriority(.required, for: .vertical) + $0.textAlignment = .left + $0.textStyle = .bodySmall + } + + private var helperLabel = Label().with { + $0.setContentCompressionResistancePriority(.required, for: .vertical) + $0.textAlignment = .left + $0.textStyle = .bodySmall + } + + private var optionsPicker = UIPickerView() + + //-------------------------------------------------- + // MARK: - Constraints + //-------------------------------------------------- + internal var widthConstraint: NSLayoutConstraint? + internal var inlineWidthConstraint: NSLayoutConstraint? + + //-------------------------------------------------- + // MARK: - Configuration Properties + //-------------------------------------------------- + internal var containerSize: CGSize { CGSize(width: 45, height: 44) } + + /// Color configuration for error icon. + internal let primaryColorConfig = ViewColorConfiguration().with { + $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) + $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) + } + + internal let secondaryColorConfig = ViewColorConfiguration().with { + $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) + $0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark, forDisabled: false) + } + + internal var backgroundColorConfiguration = ControlColorConfiguration().with { + $0.setSurfaceColors(VDSFormControlsColor.backgroundOnlight, VDSFormControlsColor.backgroundOndark, forState: .normal) + $0.setSurfaceColors(VDSFormControlsColor.backgroundOnlight, VDSFormControlsColor.backgroundOndark, forState: .disabled) + $0.setSurfaceColors(VDSColor.feedbackErrorBackgroundOnlight, VDSColor.feedbackErrorBackgroundOndark, forState: .error) + } + + internal var containerBorderColorConfiguration = ControlColorConfiguration().with { + $0.setSurfaceColors(VDSFormControlsColor.borderOnlight, VDSFormControlsColor.borderOnlight, forState: .normal) + $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled) + $0.setSurfaceColors(VDSColor.feedbackErrorOnlight, VDSColor.feedbackErrorOndark, forState: .error) + } + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + + /// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations. + open override func setup() { + super.setup() + + isAccessibilityElement = true + accessibilityLabel = "Dropdown Select" + + addSubview(stackView) + + container.addSubview(containerStack) + stackView.heightAnchor.constraint(greaterThanOrEqualToConstant: containerSize.height).isActive = true + + dropdownField.width(0) + + let spacing = VDSFormControls.spaceInset + containerStack.pinToSuperView(.init(top: spacing, left: spacing, bottom: spacing, right: spacing)) + containerStack.addArrangedSubview(dropdownField) + containerStack.addArrangedSubview(inlineDisplayLabel) + containerStack.addArrangedSubview(selectedOptionLabel) + containerStack.addArrangedSubview(icon) + + containerStack.setCustomSpacing(0, after: dropdownField) + containerStack.setCustomSpacing(VDSLayout.Spacing.space1X.value, after: inlineDisplayLabel) + containerStack.setCustomSpacing(VDSLayout.Spacing.space3X.value, after: selectedOptionLabel) + + stackView.addArrangedSubview(eyebrowLabel) + stackView.addArrangedSubview(container) + stackView.addArrangedSubview(errorLabel) + stackView.addArrangedSubview(helperLabel) + + stackView.setCustomSpacing(4, after: eyebrowLabel) + stackView.setCustomSpacing(8, after: container) + stackView.setCustomSpacing(8, after: errorLabel) + + stackView.pinToSuperView() + inlineWidthConstraint = inlineDisplayLabel.widthAnchor.constraint(equalToConstant: 0) + inlineWidthConstraint?.isActive = true + + widthConstraint = stackView.widthAnchor.constraint(greaterThanOrEqualToConstant: minWidthDefault) + widthConstraint?.isActive = true + + eyebrowLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() + errorLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() + helperLabel.textColorConfiguration = secondaryColorConfig.eraseToAnyColorable() + inlineDisplayLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() + + optionsPicker.delegate = self + optionsPicker.dataSource = self + + optionsPicker.isHidden = true + + dropdownField.inputView = optionsPicker + dropdownField.inputAccessoryView = toolBarForPicker() + + containerStack.publisher(for: UITapGestureRecognizer()).sink { [weak self] _ in + self?.launchPicker() + }.store(in: &subscribers) + } + + open override func reset() { + super.reset() + + eyebrowLabel.reset() + inlineDisplayLabel.reset() + selectedOptionLabel.reset() + errorLabel.reset() + helperLabel.reset() + + eyebrowLabel.labelTextAlignment = .left + eyebrowLabel.labelTextStyle = .bodySmall + inlineDisplayLabel.textStyle = .boldBodyLarge + inlineDisplayLabel.textAlignment = .left + selectedOptionLabel.textStyle = .bodyLarge + selectedOptionLabel.textAlignment = .left + errorLabel.textAlignment = .left + errorLabel.textStyle = .bodySmall + helperLabel.textAlignment = .left + helperLabel.textStyle = .bodySmall + tooltipModel = nil + tooltipTitle = "" + tooltipContent = "" + label = nil + errorText = nil + error = false + isEnabled = false + readOnly = false + inlineLabel = false + helperText = nil + transparentBackground = false + required = false + options = [] + } + + open override func updateView() { + container.backgroundColor = backgroundColorConfiguration.getColor(self) + container.layer.borderColor = containerBorderColorConfiguration.getColor(self).cgColor + container.layer.borderWidth = VDSFormControls.widthBorder + container.layer.cornerRadius = VDSFormControls.borderradius + + updateTitleLabel() + updateInlineLabel() + updateErrorLabel() + updateHelperLabel() + + selectedOptionLabel.surface = surface + backgroundColor = surface.color + } + + /// Used to update any Accessibility properties. + open override func updateAccessibility() { + super.updateAccessibility() + if showError { + setAccessibilityLabel(for: [eyebrowLabel, selectedOptionLabel, errorLabel, helperLabel]) + } else { + setAccessibilityLabel(for: [eyebrowLabel, selectedOptionLabel, helperLabel]) + } + } + + open func updateTitleLabel() { + + var attributes: [any LabelAttributeModel] = [] + var updatedLabelText = label + + updatedLabelText = inlineLabel ? "" : updatedLabelText + + if let oldText = updatedLabelText, !required, !oldText.hasSuffix("Optional") { + let optionColorAttr = ColorLabelAttribute(location: oldText.count + 2, + length: 8, + color: secondaryColorConfig.getColor(self)) + + updatedLabelText = "\(oldText) Optional" + attributes.append(optionColorAttr) + } + +// updateTooltip() + if let tooltipModel { + attributes.append(TooltipLabelAttribute(surface: surface, model: tooltipModel, presenter: self)) + } + + eyebrowLabel.labelText = updatedLabelText + eyebrowLabel.labelAttributes = attributes + eyebrowLabel.tooltipModel = tooltipModel + eyebrowLabel.surface = surface + eyebrowLabel.isEnabled = isEnabled + + } + + //-------------------------------------------------- + // MARK: - Public Methods + //-------------------------------------------------- + + open func updateInlineLabel() { + + ///Minimum width with inline text as per design + widthConstraint?.constant = inlineLabel ? minWidthInlineLabel : minWidthDefault + widthConstraint?.isActive = true + +// inlineDisplayLabel.text = inlineLabel ? (label!.isEmpty ? ((label ?? "") + ":") : label) : "" + inlineDisplayLabel.text = inlineLabel ? label : "" + inlineDisplayLabel.surface = surface + inlineWidthConstraint?.constant = inlineDisplayLabel.intrinsicContentSize.width + inlineWidthConstraint?.isActive = !inlineLabel + } + + open func updateSelectedOptionLabel(text: String? = nil) { + selectedOptionLabel.text = text ?? "" + } + + open func updateErrorLabel(){ + if showError, let errorText { + errorLabel.text = errorText + errorLabel.surface = surface + errorLabel.isEnabled = isEnabled + errorLabel.isHidden = false + icon.name = .error + icon.size = .medium + icon.color = .black + icon.surface = surface + } else { + icon.name = Icon.Name(name: "down-caret") + icon.surface = surface + errorLabel.isHidden = true + } + } + + open func updateHelperLabel(){ + + if let helperText { + helperLabel.text = helperText + helperLabel.surface = surface + helperLabel.isEnabled = isEnabled + helperLabel.isHidden = false + } else { + helperLabel.isHidden = true + } + } + + @objc open func pickerDoneClicked() { + dropdownField.resignFirstResponder() + } + + //-------------------------------------------------- + // MARK: - Private Methods + //-------------------------------------------------- + + private func toolBarForPicker() -> UIToolbar { + + let inputToolbar: UIToolbar = UIToolbar() + inputToolbar.barStyle = .default + inputToolbar.isTranslucent = true + + let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(pickerDoneClicked)) + let flexibleSpaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) + + inputToolbar.setItems([flexibleSpaceButton, doneButton], animated: false) + inputToolbar.isUserInteractionEnabled = true + inputToolbar.sizeToFit() + return inputToolbar + } + + func updateTooltip() { + self.tooltipModel = .init(title: tooltipTitle, content: tooltipContent) + } + + +} + +extension DropdownSelect: UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate { + + func launchPicker() { + if optionsPicker.isHidden { + dropdownField.becomeFirstResponder() + } else { + dropdownField.resignFirstResponder() + } + optionsPicker.isHidden = !optionsPicker.isHidden + } + + public func numberOfComponents(in pickerView: UIPickerView) -> Int { + return 1 + } + + public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { + return options?.count ?? 0 + } + + public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { + guard let options, options.count > row else { return nil } + return options[row] + } + + public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { + guard let options, options.count > row else { return } + updateSelectedOptionLabel(text: options[row]) + } } From a6f03e3e1e449b5d2867cdc445983adc162ec722 Mon Sep 17 00:00:00 2001 From: vasavk Date: Tue, 2 Apr 2024 18:20:02 +0530 Subject: [PATCH 08/43] Digital ACT-191 ONEAPP-7135 story: using tooltip model --- .../DropdownSelect/DropdownSelect.swift | 191 +++++++----------- 1 file changed, 77 insertions(+), 114 deletions(-) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index d7613f94..826f768e 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -34,69 +34,48 @@ open class DropdownSelect: Control { // MARK: - Public Properties //-------------------------------------------------- - ///Boolean value that determines if component should show the error state/error message. + /// Boolean value that determines if component should show the error state/error message. open var error: Bool = false { didSet { setNeedsUpdate() }} - + /// Message displayed when there is an error. open var errorText: String? { didSet { setNeedsUpdate() }} - + /// If provided, will be used as text for the helper label. open var helperText: String? { didSet { setNeedsUpdate() }} - - /// used if the component is enabled or not. + + /// Used if the component is enabled or not. open override var isEnabled: Bool { didSet { setNeedsUpdate() }} - + /// If true, the label will be displayed inside the dropdown container. Otherwise, the label will be above the dropdown container like a normal text input. open var inlineLabel: Bool = false { didSet { setNeedsUpdate() }} - + /// If provided, will be used as context for the label on the input field. open var label: String? { didSet { setNeedsUpdate() }} /// Not allowed the user interaction to select/change input if it is true. open var readOnly: Bool = false { didSet { setNeedsUpdate() }} - + /// Used to show optional indicator for the label. open var required: Bool = false { didSet { setNeedsUpdate() }} - + /// Allows unique ID to be passed to the element. open var selectId: String? { didSet { setNeedsUpdate() }} - - // TO DO: either have model or individual title and content. + /// Config object for tooltip option, is optional. open var tooltipModel: Tooltip.TooltipModel? { didSet { setNeedsUpdate() } } - - /// Used to set tooltip title. - open var tooltipTitle: String { - get { return _tooltipTitle } - set { - _tooltipTitle = newValue - updateTooltip() - setNeedsUpdate() - } - } - /// Used to set tooltip content. - open var tooltipContent: String { - get { return _tooltipContent } - set { - _tooltipContent = newValue - updateTooltip() - setNeedsUpdate() - } - } - /// If provided, will render with trnasparent background. open var transparentBackground: Bool = false { didSet { setNeedsUpdate() }} /// Used to set width for the Dropdown Select. open var width: Int? { didSet { setNeedsUpdate() }} - - // TO DO: create model for options + + /// TO DO: create model for options open var options: [String]? { didSet { setNeedsUpdate() }} - ///Boolean or a Function that returns a boolean value that determines if component should show the error state/error message.Functon receives the 'event' object on input change. + /// Boolean value that determines if component should show the error state/error message. Functon receives the 'event' object on input change. open var showError: Bool = false { didSet { setNeedsUpdate() }} - + open override var state: UIControl.State { get { var state = super.state @@ -110,18 +89,14 @@ open class DropdownSelect: Control { //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- - internal var _tooltipTitle: String = "" - - internal var _tooltipContent: String = "" - internal var minWidthDefault = 66.0 internal var minWidthInlineLabel = 102.0 - + var stackView: UIStackView = UIStackView().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.axis = .vertical } - + private var eyebrowLabel = TrailingTooltipLabel().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) $0.labelTextAlignment = .left @@ -131,7 +106,7 @@ open class DropdownSelect: Control { var container: UIView = UIView().with { $0.translatesAutoresizingMaskIntoConstraints = false } - + var containerStack: UIStackView = UIStackView().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.axis = .horizontal @@ -143,7 +118,7 @@ open class DropdownSelect: Control { $0.tintColor = UIColor.clear $0.font = TextStyle.bodyLarge.font } - + private var inlineDisplayLabel = Label().with { $0.textAlignment = .left $0.textStyle = .boldBodyLarge @@ -155,12 +130,12 @@ open class DropdownSelect: Control { $0.textAlignment = .left $0.textStyle = .bodyLarge } - + private var icon: Icon = Icon().with { $0.size = .medium $0.name = Icon.Name(name: "down-caret") } - + private var errorLabel = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) $0.textAlignment = .left @@ -172,7 +147,7 @@ open class DropdownSelect: Control { $0.textAlignment = .left $0.textStyle = .bodySmall } - + private var optionsPicker = UIPickerView() //-------------------------------------------------- @@ -185,7 +160,7 @@ open class DropdownSelect: Control { // MARK: - Configuration Properties //-------------------------------------------------- internal var containerSize: CGSize { CGSize(width: 45, height: 44) } - + /// Color configuration for error icon. internal let primaryColorConfig = ViewColorConfiguration().with { $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) @@ -196,13 +171,13 @@ open class DropdownSelect: Control { $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) $0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark, forDisabled: false) } - + internal var backgroundColorConfiguration = ControlColorConfiguration().with { $0.setSurfaceColors(VDSFormControlsColor.backgroundOnlight, VDSFormControlsColor.backgroundOndark, forState: .normal) $0.setSurfaceColors(VDSFormControlsColor.backgroundOnlight, VDSFormControlsColor.backgroundOndark, forState: .disabled) $0.setSurfaceColors(VDSColor.feedbackErrorBackgroundOnlight, VDSColor.feedbackErrorBackgroundOndark, forState: .error) } - + internal var containerBorderColorConfiguration = ControlColorConfiguration().with { $0.setSurfaceColors(VDSFormControlsColor.borderOnlight, VDSFormControlsColor.borderOnlight, forState: .normal) $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled) @@ -210,16 +185,15 @@ open class DropdownSelect: Control { } //-------------------------------------------------- - // MARK: - Lifecycle + // MARK: - Overrides //-------------------------------------------------- - /// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations. open override func setup() { super.setup() - + isAccessibilityElement = true accessibilityLabel = "Dropdown Select" - + addSubview(stackView) container.addSubview(containerStack) @@ -227,6 +201,7 @@ open class DropdownSelect: Control { dropdownField.width(0) + // container stack let spacing = VDSFormControls.spaceInset containerStack.pinToSuperView(.init(top: spacing, left: spacing, bottom: spacing, right: spacing)) containerStack.addArrangedSubview(dropdownField) @@ -237,12 +212,13 @@ open class DropdownSelect: Control { containerStack.setCustomSpacing(0, after: dropdownField) containerStack.setCustomSpacing(VDSLayout.Spacing.space1X.value, after: inlineDisplayLabel) containerStack.setCustomSpacing(VDSLayout.Spacing.space3X.value, after: selectedOptionLabel) - + + // component stack stackView.addArrangedSubview(eyebrowLabel) stackView.addArrangedSubview(container) stackView.addArrangedSubview(errorLabel) stackView.addArrangedSubview(helperLabel) - + stackView.setCustomSpacing(4, after: eyebrowLabel) stackView.setCustomSpacing(8, after: container) stackView.setCustomSpacing(8, after: errorLabel) @@ -250,10 +226,10 @@ open class DropdownSelect: Control { stackView.pinToSuperView() inlineWidthConstraint = inlineDisplayLabel.widthAnchor.constraint(equalToConstant: 0) inlineWidthConstraint?.isActive = true - + widthConstraint = stackView.widthAnchor.constraint(greaterThanOrEqualToConstant: minWidthDefault) widthConstraint?.isActive = true - + eyebrowLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() errorLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() helperLabel.textColorConfiguration = secondaryColorConfig.eraseToAnyColorable() @@ -261,7 +237,7 @@ open class DropdownSelect: Control { optionsPicker.delegate = self optionsPicker.dataSource = self - + optionsPicker.isHidden = true dropdownField.inputView = optionsPicker @@ -272,40 +248,7 @@ open class DropdownSelect: Control { }.store(in: &subscribers) } - open override func reset() { - super.reset() - - eyebrowLabel.reset() - inlineDisplayLabel.reset() - selectedOptionLabel.reset() - errorLabel.reset() - helperLabel.reset() - - eyebrowLabel.labelTextAlignment = .left - eyebrowLabel.labelTextStyle = .bodySmall - inlineDisplayLabel.textStyle = .boldBodyLarge - inlineDisplayLabel.textAlignment = .left - selectedOptionLabel.textStyle = .bodyLarge - selectedOptionLabel.textAlignment = .left - errorLabel.textAlignment = .left - errorLabel.textStyle = .bodySmall - helperLabel.textAlignment = .left - helperLabel.textStyle = .bodySmall - tooltipModel = nil - tooltipTitle = "" - tooltipContent = "" - label = nil - errorText = nil - error = false - isEnabled = false - readOnly = false - inlineLabel = false - helperText = nil - transparentBackground = false - required = false - options = [] - } - + /// Used to make changes to the View based off a change events or from local properties. open override func updateView() { container.backgroundColor = backgroundColorConfiguration.getColor(self) container.layer.borderColor = containerBorderColorConfiguration.getColor(self).cgColor @@ -331,13 +274,46 @@ open class DropdownSelect: Control { } } + /// Resets to default settings. + open override func reset() { + super.reset() + + eyebrowLabel.reset() + inlineDisplayLabel.reset() + selectedOptionLabel.reset() + errorLabel.reset() + helperLabel.reset() + + eyebrowLabel.labelTextStyle = .bodySmall + inlineDisplayLabel.textStyle = .boldBodyLarge + selectedOptionLabel.textStyle = .bodyLarge + errorLabel.textStyle = .bodySmall + helperLabel.textStyle = .bodySmall + tooltipModel = nil + label = nil + errorText = nil + error = false + isEnabled = false + readOnly = false + inlineLabel = false + helperText = nil + transparentBackground = false + required = false + options = [] + } + + //-------------------------------------------------- + // MARK: - Public Methods + //-------------------------------------------------- + open func updateTitleLabel() { - + + //update the local vars for the label since we no long have a model var attributes: [any LabelAttributeModel] = [] var updatedLabelText = label updatedLabelText = inlineLabel ? "" : updatedLabelText - + if let oldText = updatedLabelText, !required, !oldText.hasSuffix("Optional") { let optionColorAttr = ColorLabelAttribute(location: oldText.count + 2, length: 8, @@ -347,30 +323,24 @@ open class DropdownSelect: Control { attributes.append(optionColorAttr) } -// updateTooltip() if let tooltipModel { attributes.append(TooltipLabelAttribute(surface: surface, model: tooltipModel, presenter: self)) } - + eyebrowLabel.labelText = updatedLabelText eyebrowLabel.labelAttributes = attributes eyebrowLabel.tooltipModel = tooltipModel eyebrowLabel.surface = surface eyebrowLabel.isEnabled = isEnabled - } - //-------------------------------------------------- - // MARK: - Public Methods - //-------------------------------------------------- - open func updateInlineLabel() { - + ///Minimum width with inline text as per design widthConstraint?.constant = inlineLabel ? minWidthInlineLabel : minWidthDefault widthConstraint?.isActive = true - -// inlineDisplayLabel.text = inlineLabel ? (label!.isEmpty ? ((label ?? "") + ":") : label) : "" + + // inlineDisplayLabel.text = inlineLabel ? (label!.isEmpty ? ((label ?? "") + ":") : label) : "" inlineDisplayLabel.text = inlineLabel ? label : "" inlineDisplayLabel.surface = surface inlineWidthConstraint?.constant = inlineDisplayLabel.intrinsicContentSize.width @@ -381,7 +351,7 @@ open class DropdownSelect: Control { selectedOptionLabel.text = text ?? "" } - open func updateErrorLabel(){ + open func updateErrorLabel() { if showError, let errorText { errorLabel.text = errorText errorLabel.surface = surface @@ -398,8 +368,7 @@ open class DropdownSelect: Control { } } - open func updateHelperLabel(){ - + open func updateHelperLabel() { if let helperText { helperLabel.text = helperText helperLabel.surface = surface @@ -426,18 +395,12 @@ open class DropdownSelect: Control { let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(pickerDoneClicked)) let flexibleSpaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) - + inputToolbar.setItems([flexibleSpaceButton, doneButton], animated: false) inputToolbar.isUserInteractionEnabled = true inputToolbar.sizeToFit() return inputToolbar } - - func updateTooltip() { - self.tooltipModel = .init(title: tooltipTitle, content: tooltipContent) - } - - } extension DropdownSelect: UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate { From ae86948502f8c67328924ae48acfa6413be6957a Mon Sep 17 00:00:00 2001 From: vasavk Date: Tue, 2 Apr 2024 18:27:15 +0530 Subject: [PATCH 09/43] Digital ACT-191 ONEAPP-7135 story: added change log for DropdownSelect --- VDS.xcodeproj/project.pbxproj | 4 ++ .../DropdownSelectChangeLog.txt | 45 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 VDS/Components/DropdownSelect/DropdownSelectChangeLog.txt diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index 7bf3c054..b071240b 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 1855EC662BAABF2A002ACAC2 /* BreadcrumbItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1855EC652BAABF2A002ACAC2 /* BreadcrumbItemModel.swift */; }; 186B2A8A2B88DA7F001AB71F /* TextAreaChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 186B2A892B88DA7F001AB71F /* TextAreaChangeLog.txt */; }; 186D13CB2BBA8B1500986B53 /* DropdownSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 186D13CA2BBA8B1500986B53 /* DropdownSelect.swift */; }; + 186D13CF2BBC36EF00986B53 /* DropdownSelectChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 186D13CE2BBC36EE00986B53 /* DropdownSelectChangeLog.txt */; }; 18792A902B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */; }; 18A65A022B96E848006602CC /* Breadcrumbs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A65A012B96E848006602CC /* Breadcrumbs.swift */; }; 18A65A042B96F050006602CC /* BreadcrumbItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A65A032B96F050006602CC /* BreadcrumbItem.swift */; }; @@ -204,6 +205,7 @@ 1855EC652BAABF2A002ACAC2 /* BreadcrumbItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbItemModel.swift; sourceTree = ""; }; 186B2A892B88DA7F001AB71F /* TextAreaChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TextAreaChangeLog.txt; sourceTree = ""; }; 186D13CA2BBA8B1500986B53 /* DropdownSelect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropdownSelect.swift; sourceTree = ""; }; + 186D13CE2BBC36EE00986B53 /* DropdownSelectChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = DropdownSelectChangeLog.txt; sourceTree = ""; }; 18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIconBadgeIndicatorModel.swift; sourceTree = ""; }; 18A65A012B96E848006602CC /* Breadcrumbs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Breadcrumbs.swift; sourceTree = ""; }; 18A65A032B96F050006602CC /* BreadcrumbItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbItem.swift; sourceTree = ""; }; @@ -413,6 +415,7 @@ isa = PBXGroup; children = ( 186D13CA2BBA8B1500986B53 /* DropdownSelect.swift */, + 186D13CE2BBC36EE00986B53 /* DropdownSelectChangeLog.txt */, ); path = DropdownSelect; sourceTree = ""; @@ -1069,6 +1072,7 @@ EAEEECA02B1F908200531FC2 /* BadgeIndicatorChangeLog.txt in Resources */, EAA5EEB928ECD24B003B3210 /* Icons.xcassets in Resources */, EAEEECA92B1F969700531FC2 /* TooltipChangeLog.txt in Resources */, + 186D13CF2BBC36EF00986B53 /* DropdownSelectChangeLog.txt in Resources */, EAEEEC9C2B1F8F0700531FC2 /* TextLinkCaretChangeLog.txt in Resources */, EAA5EEE428F5B855003B3210 /* VerizonNHGDS-Light.otf in Resources */, 71B5FCBB2B95A0CA00269BCC /* PaginationChangeLog.txt in Resources */, diff --git a/VDS/Components/DropdownSelect/DropdownSelectChangeLog.txt b/VDS/Components/DropdownSelect/DropdownSelectChangeLog.txt new file mode 100644 index 00000000..537b6532 --- /dev/null +++ b/VDS/Components/DropdownSelect/DropdownSelectChangeLog.txt @@ -0,0 +1,45 @@ +MM/DD/YYYY +---------------- +Initial Brand 3.0 handoff + +12/27/2021 +---------------- +- Removed Max Width, Increased Min width. +- Updated the tokens with FormControl tokens + +02/24/2022 +---------------- +- Replaced Error and Caret Down Non-Scaling icons with VDS Icon. + +05/02/2022 +---------------- +- Anatomy: Noted that Label and Inline Label are optional within the code + +07/27/2022 +---------------- +- Updated Dropdown Select Configurations to include Background Transparent Boolean. + +08/10/2022 +---------------- +- Updated surface prop from inverted to light and dark + +11/30/2022 +---------------- +- Added "(web only)" to any instance of "keyboard focus" + +12/13/2022 +---------------- +- Replaced form border and focus border pixel values and styles & spacing with tokens. + +01/19/2023 +---------------- +- Added Tooltip and Optional Indicator to Anatomy Updated Specs to use new SPEC Templates and SPEC DOC Components. +- Added “Option List” and artwork to Anatomy. + +04/12/2023 +---------------- +- Updated hex colors for updated feedback tokens in error states. + +12/27/23 +---------------- +- Removed Web/App Parity Discrepancies section From 7c5d52c276acce69ddd452d7aa895ea6bccc3be9 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 2 Apr 2024 11:38:01 -0500 Subject: [PATCH 10/43] updated the accessiblity in BadgeIndicator Signed-off-by: Matt Bruce --- VDS/Components/BadgeIndicator/BadgeIndicator.swift | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/VDS/Components/BadgeIndicator/BadgeIndicator.swift b/VDS/Components/BadgeIndicator/BadgeIndicator.swift index 45432458..f9d18301 100644 --- a/VDS/Components/BadgeIndicator/BadgeIndicator.swift +++ b/VDS/Components/BadgeIndicator/BadgeIndicator.swift @@ -268,10 +268,10 @@ open class BadgeIndicator: View { /// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations. open override func setup() { super.setup() - + isAccessibilityElement = true + addSubview(badgeView) badgeView.addSubview(label) - accessibilityElements = [label] heightConstraint = badgeView.heightGreaterThanEqualTo(constant: badgeSize) widthConstraint = badgeView.widthGreaterThanEqualTo(constant: badgeSize) @@ -347,6 +347,15 @@ open class BadgeIndicator: View { layoutIfNeeded() } + open override func updateAccessibility() { + super.updateAccessibility() + if kind == .numbered { + accessibilityLabel = label.text + } else { + accessibilityLabel = "Simple" + } + } + open override func layoutSubviews() { super.layoutSubviews() From ae08c06af78ed137ca1db3fc8324e125320fbb24 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 2 Apr 2024 15:51:25 -0500 Subject: [PATCH 11/43] maatched figma docs Signed-off-by: Matt Bruce --- VDS/Components/BadgeIndicator/BadgeIndicator.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/VDS/Components/BadgeIndicator/BadgeIndicator.swift b/VDS/Components/BadgeIndicator/BadgeIndicator.swift index bcacfe84..c0d3f680 100644 --- a/VDS/Components/BadgeIndicator/BadgeIndicator.swift +++ b/VDS/Components/BadgeIndicator/BadgeIndicator.swift @@ -93,7 +93,6 @@ open class BadgeIndicator: View { switch self { case .xxlarge: pointSize = VDSTypography.fontSizeTitle24 - letterSpacing = VDSTypography.letterSpacingWide lineHeight = VDSTypography.lineHeightTitle24 case .xlarge: From bc8df2d45f585f40ba4d99ce763e1ae9eaaec1dc Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 2 Apr 2024 15:56:07 -0500 Subject: [PATCH 12/43] remvoed debug Signed-off-by: Matt Bruce --- VDS/Components/BadgeIndicator/BadgeIndicator.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/VDS/Components/BadgeIndicator/BadgeIndicator.swift b/VDS/Components/BadgeIndicator/BadgeIndicator.swift index e3e186fa..57f7f34a 100644 --- a/VDS/Components/BadgeIndicator/BadgeIndicator.swift +++ b/VDS/Components/BadgeIndicator/BadgeIndicator.swift @@ -356,7 +356,6 @@ open class BadgeIndicator: View { label.sizeToFit() setNeedsLayout() layoutIfNeeded() - label.debugBorder(color: .green) } open override func updateAccessibility() { From c57c597427f9cbca3e3969dbd1b174fe7232af75 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 3 Apr 2024 13:46:27 -0500 Subject: [PATCH 13/43] removed lineHeight/verticalPadding from the sizes added new bezierPathBorder Signed-off-by: Matt Bruce --- .../BadgeIndicator/BadgeIndicator.swift | 21 +++------- VDS/Extensions/UIView+CALayer.swift | 41 +++++++++++++++++++ 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/VDS/Components/BadgeIndicator/BadgeIndicator.swift b/VDS/Components/BadgeIndicator/BadgeIndicator.swift index 57f7f34a..6547580c 100644 --- a/VDS/Components/BadgeIndicator/BadgeIndicator.swift +++ b/VDS/Components/BadgeIndicator/BadgeIndicator.swift @@ -87,47 +87,38 @@ open class BadgeIndicator: View { var font: Font = .edsRegular var pointSize: CGFloat = VDSTypography.fontSizeBody12 var letterSpacing: CGFloat = 0.0 - var lineHeight: CGFloat = 0.0 - var edgeInsets: UIEdgeInsets = .zero switch self { case .xxlarge: pointSize = VDSTypography.fontSizeTitle24 - lineHeight = VDSTypography.lineHeightTitle24 case .xlarge: pointSize = VDSTypography.fontSizeTitle20 - lineHeight = VDSTypography.lineHeightTitle20 case .large: pointSize = VDSTypography.fontSizeBody16 letterSpacing = VDSTypography.letterSpacingWide - lineHeight = VDSTypography.lineHeightBody16 case .medium: pointSize = VDSTypography.fontSizeBody14 letterSpacing = VDSTypography.letterSpacingWide - lineHeight = 14.0 case .small: font = .etxRegular pointSize = VDSTypography.fontSizeBody12 - lineHeight = 12.0 - } return TextStyle(rawValue: "\(self.rawValue)BadgeIndicator", fontFace: font, pointSize: pointSize, - lineHeight: lineHeight, - letterSpacing: letterSpacing, - edgeInsets: edgeInsets) + lineHeight: 0, + letterSpacing: letterSpacing) } //EdgeInsets for the label. public var edgeInset: UIEdgeInsets { var horizontalPadding: CGFloat = 0.0 - let verticalPadding: CGFloat = 2.0 + let verticalPadding: CGFloat = 0.0 switch self { case .xxlarge: @@ -376,10 +367,9 @@ open class BadgeIndicator: View { //border if hideBorder { - layer.borderWidth = 0 + removeBezierPathBorder() } else { - layer.borderWidth = borderWidth - layer.borderColor = borderColorConfiguration.getColor(surface).cgColor + bezierPathBorder(borderColorConfiguration.getColor(surface), width: borderWidth) } //dot @@ -464,5 +454,4 @@ open class BadgeIndicator: View { let maxNumber = Int(pow(10.0, Double(maxDigits))) - 1 return min(number, maxNumber) } - } diff --git a/VDS/Extensions/UIView+CALayer.swift b/VDS/Extensions/UIView+CALayer.swift index acc5ddab..2158b18e 100644 --- a/VDS/Extensions/UIView+CALayer.swift +++ b/VDS/Extensions/UIView+CALayer.swift @@ -148,3 +148,44 @@ extension UIView { } } } + +extension UIView { + + fileprivate var bezierPathIdentifier: String { return "bezierPathBorderLayer" } + + fileprivate var bezierPathBorder: CAShapeLayer? { + return (self.layer.sublayers?.filter({ (layer) -> Bool in + return layer.name == self.bezierPathIdentifier && (layer as? CAShapeLayer) != nil + }) as? [CAShapeLayer])?.first + } + + public func bezierPathBorder(_ color: UIColor = .white, width: CGFloat = 1) { + + var border = self.bezierPathBorder + let path = UIBezierPath(roundedRect: self.bounds, cornerRadius:self.layer.cornerRadius) + let mask = CAShapeLayer() + mask.path = path.cgPath + self.layer.mask = mask + + if (border == nil) { + border = CAShapeLayer() + border!.name = self.bezierPathIdentifier + self.layer.addSublayer(border!) + } + + border!.frame = self.bounds + let pathUsingCorrectInsetIfAny = + UIBezierPath(roundedRect: border!.bounds, cornerRadius:self.layer.cornerRadius) + + border!.path = pathUsingCorrectInsetIfAny.cgPath + border!.fillColor = UIColor.clear.cgColor + border!.strokeColor = color.cgColor + border!.lineWidth = width * 2 + } + + public func removeBezierPathBorder() { + self.layer.mask = nil + self.bezierPathBorder?.removeFromSuperlayer() + } + +} From aaad4ae699faea7a968098c9fca324ff75b56be1 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 3 Apr 2024 16:01:10 -0500 Subject: [PATCH 14/43] updated release notes Signed-off-by: Matt Bruce --- VDS/SupportingFiles/ReleaseNotes.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/VDS/SupportingFiles/ReleaseNotes.txt b/VDS/SupportingFiles/ReleaseNotes.txt index d1ad181e..94d304a7 100644 --- a/VDS/SupportingFiles/ReleaseNotes.txt +++ b/VDS/SupportingFiles/ReleaseNotes.txt @@ -1,3 +1,8 @@ +1.0.57 +---------------- +- CXTDT-540077 - BadgeIndicator Font +- CXTDT-540084 - BadgeIndicator Border + 1.0.56 ---------------- - ONEAPP-7190 - Breadcrumbs - Finished Development From 775d3ae709365faf5920931cb0ad9907b041f819 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 3 Apr 2024 16:06:23 -0500 Subject: [PATCH 15/43] updated version Signed-off-by: Matt Bruce --- VDS.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index 681d16b5..b103afc6 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -1369,7 +1369,7 @@ BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 56; + CURRENT_PROJECT_VERSION = 57; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1406,7 +1406,7 @@ BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 56; + CURRENT_PROJECT_VERSION = 57; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; From e3b6b832e29b57bf5704bf811e9e4c121d784d17 Mon Sep 17 00:00:00 2001 From: vasavk Date: Thu, 4 Apr 2024 11:31:38 +0530 Subject: [PATCH 16/43] Digital ACT-191 ONEAPP-7135 story: added model class for options, added callback method to pass selected option text, updating inlineDisplayLabel text if inlineLabel true --- VDS.xcodeproj/project.pbxproj | 4 ++ .../DropdownSelect/DropdownOptionModel.swift | 20 ++++++ .../DropdownSelect/DropdownSelect.swift | 72 +++++++++++-------- 3 files changed, 65 insertions(+), 31 deletions(-) create mode 100644 VDS/Components/DropdownSelect/DropdownOptionModel.swift diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index b071240b..d63b3cad 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ 18792A902B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */; }; 18A65A022B96E848006602CC /* Breadcrumbs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A65A012B96E848006602CC /* Breadcrumbs.swift */; }; 18A65A042B96F050006602CC /* BreadcrumbItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A65A032B96F050006602CC /* BreadcrumbItem.swift */; }; + 18B463A42BBD3C46005C4528 /* DropdownOptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B463A32BBD3C46005C4528 /* DropdownOptionModel.swift */; }; 18BDEE822B75316E00452358 /* ButtonIconChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */; }; 445BA07829C07B3D0036A7C5 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 445BA07729C07B3D0036A7C5 /* Notification.swift */; }; 44604AD429CE186A00E62B51 /* NotificationButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */; }; @@ -209,6 +210,7 @@ 18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIconBadgeIndicatorModel.swift; sourceTree = ""; }; 18A65A012B96E848006602CC /* Breadcrumbs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Breadcrumbs.swift; sourceTree = ""; }; 18A65A032B96F050006602CC /* BreadcrumbItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbItem.swift; sourceTree = ""; }; + 18B463A32BBD3C46005C4528 /* DropdownOptionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropdownOptionModel.swift; sourceTree = ""; }; 18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = ButtonIconChangeLog.txt; sourceTree = ""; }; 445BA07729C07B3D0036A7C5 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = ""; }; 44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationButtonModel.swift; sourceTree = ""; }; @@ -415,6 +417,7 @@ isa = PBXGroup; children = ( 186D13CA2BBA8B1500986B53 /* DropdownSelect.swift */, + 18B463A32BBD3C46005C4528 /* DropdownOptionModel.swift */, 186D13CE2BBC36EE00986B53 /* DropdownSelectChangeLog.txt */, ); path = DropdownSelect; @@ -1132,6 +1135,7 @@ EAF7F0AF289B144C00B287F5 /* UnderlineLabelAttribute.swift in Sources */, EA0D1C412A6AD61C00E5C127 /* Typography+Additional.swift in Sources */, EAC925842911C63100091998 /* Colorable.swift in Sources */, + 18B463A42BBD3C46005C4528 /* DropdownOptionModel.swift in Sources */, EAACB89A2B927108006A3869 /* Valuing.swift in Sources */, EAE785312BA0A438009428EA /* UIImage+Helper.swift in Sources */, EAB5FEF5292D371F00998C17 /* ButtonBase.swift in Sources */, diff --git a/VDS/Components/DropdownSelect/DropdownOptionModel.swift b/VDS/Components/DropdownSelect/DropdownOptionModel.swift new file mode 100644 index 00000000..ba7caa7f --- /dev/null +++ b/VDS/Components/DropdownSelect/DropdownOptionModel.swift @@ -0,0 +1,20 @@ +// +// DropdownOptionModel.swift +// VDS +// +// Created by Kanamarlapudi, Vasavi on 03/04/24. +// + +import Foundation + +extension DropdownSelect { + public struct DropdownOptionModel { + + /// Text that goes as option to DropdownSelect + public var text: String + + public init(text: String) { + self.text = text + } + } +} diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index 826f768e..f5ce15ef 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -68,10 +68,13 @@ open class DropdownSelect: Control { open var transparentBackground: Bool = false { didSet { setNeedsUpdate() }} /// Used to set width for the Dropdown Select. - open var width: Int? { didSet { setNeedsUpdate() }} + open var width: CGFloat? { didSet { setNeedsUpdate() } } + + /// Array of options to show + open var options: [DropdownOptionModel] = [] { didSet { setNeedsUpdate() }} - /// TO DO: create model for options - open var options: [String]? { didSet { setNeedsUpdate() }} + /// A callback when the selected option changes. Passes parameters (option). + open var onDropdownItemSelect: ((DropdownOptionModel) -> Void)? /// Boolean value that determines if component should show the error state/error message. Functon receives the 'event' object on input change. open var showError: Bool = false { didSet { setNeedsUpdate() }} @@ -159,7 +162,7 @@ open class DropdownSelect: Control { //-------------------------------------------------- // MARK: - Configuration Properties //-------------------------------------------------- - internal var containerSize: CGSize { CGSize(width: 45, height: 44) } + internal var containerSize: CGSize { CGSize(width: minWidthDefault, height: 44) } /// Color configuration for error icon. internal let primaryColorConfig = ViewColorConfiguration().with { @@ -187,6 +190,7 @@ open class DropdownSelect: Control { //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- + /// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations. open override func setup() { super.setup() @@ -194,16 +198,15 @@ open class DropdownSelect: Control { isAccessibilityElement = true accessibilityLabel = "Dropdown Select" + // stackview addSubview(stackView) - - container.addSubview(containerStack) stackView.heightAnchor.constraint(greaterThanOrEqualToConstant: containerSize.height).isActive = true - - dropdownField.width(0) - + // container stack + container.addSubview(containerStack) let spacing = VDSFormControls.spaceInset containerStack.pinToSuperView(.init(top: spacing, left: spacing, bottom: spacing, right: spacing)) + containerStack.addArrangedSubview(dropdownField) containerStack.addArrangedSubview(inlineDisplayLabel) containerStack.addArrangedSubview(selectedOptionLabel) @@ -212,8 +215,9 @@ open class DropdownSelect: Control { containerStack.setCustomSpacing(0, after: dropdownField) containerStack.setCustomSpacing(VDSLayout.Spacing.space1X.value, after: inlineDisplayLabel) containerStack.setCustomSpacing(VDSLayout.Spacing.space3X.value, after: selectedOptionLabel) - - // component stack + dropdownField.width(0) + + // component stackview subviews stackView.addArrangedSubview(eyebrowLabel) stackView.addArrangedSubview(container) stackView.addArrangedSubview(errorLabel) @@ -237,12 +241,9 @@ open class DropdownSelect: Control { optionsPicker.delegate = self optionsPicker.dataSource = self - optionsPicker.isHidden = true - dropdownField.inputView = optionsPicker dropdownField.inputAccessoryView = toolBarForPicker() - containerStack.publisher(for: UITapGestureRecognizer()).sink { [weak self] _ in self?.launchPicker() }.store(in: &subscribers) @@ -336,15 +337,20 @@ open class DropdownSelect: Control { open func updateInlineLabel() { - ///Minimum width with inline text as per design - widthConstraint?.constant = inlineLabel ? minWidthInlineLabel : minWidthDefault - widthConstraint?.isActive = true - - // inlineDisplayLabel.text = inlineLabel ? (label!.isEmpty ? ((label ?? "") + ":") : label) : "" - inlineDisplayLabel.text = inlineLabel ? label : "" + /// inline label text and selected option text separated by ':' + if let label, !label.isEmpty { + inlineDisplayLabel.text = inlineLabel ? (label + ":") : "" + } else { + inlineDisplayLabel.text = inlineLabel ? label : "" + } inlineDisplayLabel.surface = surface + + /// Minimum width with inline text as per design inlineWidthConstraint?.constant = inlineDisplayLabel.intrinsicContentSize.width inlineWidthConstraint?.isActive = !inlineLabel + widthConstraint?.constant = inlineLabel ? minWidthInlineLabel : minWidthDefault + widthConstraint?.isActive = true + } open func updateSelectedOptionLabel(text: String? = nil) { @@ -392,12 +398,12 @@ open class DropdownSelect: Control { let inputToolbar: UIToolbar = UIToolbar() inputToolbar.barStyle = .default inputToolbar.isTranslucent = true - - let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(pickerDoneClicked)) - let flexibleSpaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) - - inputToolbar.setItems([flexibleSpaceButton, doneButton], animated: false) - inputToolbar.isUserInteractionEnabled = true + + // add a done button to the toolbar + inputToolbar.items=[ + UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: self, action: nil), + UIBarButtonItem(title: "Done", style: UIBarButtonItem.Style.done, target: self, action: #selector(pickerDoneClicked)) + ] inputToolbar.sizeToFit() return inputToolbar } @@ -414,21 +420,25 @@ extension DropdownSelect: UIPickerViewDelegate, UIPickerViewDataSource, UITextFi optionsPicker.isHidden = !optionsPicker.isHidden } + //-------------------------------------------------- + // MARK: - UIPickerView Delegate & Datasource + //-------------------------------------------------- public func numberOfComponents(in pickerView: UIPickerView) -> Int { return 1 } public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { - return options?.count ?? 0 + return options.count } public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { - guard let options, options.count > row else { return nil } - return options[row] + guard options.count > row else { return nil } + return options[row].text } public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { - guard let options, options.count > row else { return } - updateSelectedOptionLabel(text: options[row]) + guard options.count > row else { return } + updateSelectedOptionLabel(text: options[row].text) + self.onDropdownItemSelect?(options[row]) } } From e5d8b12bd69e72d8665f2a1e50d8caf56d0b0e55 Mon Sep 17 00:00:00 2001 From: vasavk Date: Thu, 4 Apr 2024 11:40:07 +0530 Subject: [PATCH 17/43] Digital ACT-191 ONEAPP-7135 story: color configurations as per states --- .../DropdownSelect/DropdownSelect.swift | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index f5ce15ef..c70b531d 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -175,6 +175,12 @@ open class DropdownSelect: Control { $0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark, forDisabled: false) } + internal let iconColorConfig = ControlColorConfiguration().with { + $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal) + $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled) + $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .error) + } + internal var backgroundColorConfiguration = ControlColorConfiguration().with { $0.setSurfaceColors(VDSFormControlsColor.backgroundOnlight, VDSFormControlsColor.backgroundOndark, forState: .normal) $0.setSurfaceColors(VDSFormControlsColor.backgroundOnlight, VDSFormControlsColor.backgroundOndark, forState: .disabled) @@ -185,6 +191,16 @@ open class DropdownSelect: Control { $0.setSurfaceColors(VDSFormControlsColor.borderOnlight, VDSFormControlsColor.borderOnlight, forState: .normal) $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled) $0.setSurfaceColors(VDSColor.feedbackErrorOnlight, VDSColor.feedbackErrorOndark, forState: .error) + $0.setSurfaceColors(VDSFormControlsColor.borderHoverOnlight, VDSFormControlsColor.borderHoverOndark, forState: .focused) + } + + internal var errorBorderColorConfiguration = ControlColorConfiguration().with { + $0.setSurfaceColors(VDSColor.feedbackErrorOnlight, VDSColor.feedbackErrorOndark, forState: .error) + $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .focused) + } + + internal var readOnlyBorderColorConfiguration = ControlColorConfiguration().with { + $0.setSurfaceColors(VDSFormControlsColor.borderReadonlyOnlight, VDSFormControlsColor.borderReadonlyOndark, forState: .normal) } //-------------------------------------------------- @@ -238,6 +254,8 @@ open class DropdownSelect: Control { errorLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() helperLabel.textColorConfiguration = secondaryColorConfig.eraseToAnyColorable() inlineDisplayLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() + selectedOptionLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() + icon.color = iconColorConfig.getColor(self) optionsPicker.delegate = self optionsPicker.dataSource = self @@ -251,16 +269,20 @@ open class DropdownSelect: Control { /// Used to make changes to the View based off a change events or from local properties. open override func updateView() { + container.backgroundColor = backgroundColorConfiguration.getColor(self) - container.layer.borderColor = containerBorderColorConfiguration.getColor(self).cgColor container.layer.borderWidth = VDSFormControls.widthBorder container.layer.cornerRadius = VDSFormControls.borderradius + container.layer.borderColor = readOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : (showError ? errorBorderColorConfiguration.getColor(self).cgColor : containerBorderColorConfiguration.getColor(self).cgColor) + dropdownField.isUserInteractionEnabled = readOnly ? false : true updateTitleLabel() updateInlineLabel() updateErrorLabel() updateHelperLabel() - + if readOnly { + icon.name = nil + } selectedOptionLabel.surface = surface backgroundColor = surface.color } From 149fda901dade76e8d8fba89a2d37ece5a1ad93f Mon Sep 17 00:00:00 2001 From: vasavk Date: Thu, 4 Apr 2024 14:17:36 +0530 Subject: [PATCH 18/43] Digital ACT-191 ONEAPP-7135 story: Text Overflow handling, did set transparent background if is true --- VDS/Components/DropdownSelect/DropdownSelect.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index c70b531d..3e8aac32 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -132,6 +132,7 @@ open class DropdownSelect: Control { $0.setContentCompressionResistancePriority(.required, for: .vertical) $0.textAlignment = .left $0.textStyle = .bodyLarge + $0.lineBreakMode = .byCharWrapping } private var icon: Icon = Icon().with { @@ -275,7 +276,8 @@ open class DropdownSelect: Control { container.layer.cornerRadius = VDSFormControls.borderradius container.layer.borderColor = readOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : (showError ? errorBorderColorConfiguration.getColor(self).cgColor : containerBorderColorConfiguration.getColor(self).cgColor) dropdownField.isUserInteractionEnabled = readOnly ? false : true - + stackView.backgroundColor = transparentBackground ? .clear : surface.color + updateTitleLabel() updateInlineLabel() updateErrorLabel() From b56e45d41b0e5abef9d47d9a8ed3979f149d67bf Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 4 Apr 2024 15:12:26 -0500 Subject: [PATCH 19/43] removed logic since for tooltipattribute this will never pass. Signed-off-by: Matt Bruce --- VDS/Components/Label/Attributes/LabelAttributeModel.swift | 1 - VDS/Components/Label/Attributes/TooltipLabelAttribute.swift | 2 -- 2 files changed, 3 deletions(-) diff --git a/VDS/Components/Label/Attributes/LabelAttributeModel.swift b/VDS/Components/Label/Attributes/LabelAttributeModel.swift index 01dfec08..578a9e15 100644 --- a/VDS/Components/Label/Attributes/LabelAttributeModel.swift +++ b/VDS/Components/Label/Attributes/LabelAttributeModel.swift @@ -71,7 +71,6 @@ public extension NSAttributedString { extension NSMutableAttributedString { public func apply(attribute: any LabelAttributeModel) { - guard isValid(range: attribute.range) else { return } attribute.setAttribute(on: self) } diff --git a/VDS/Components/Label/Attributes/TooltipLabelAttribute.swift b/VDS/Components/Label/Attributes/TooltipLabelAttribute.swift index bd02cf87..fe1ca794 100644 --- a/VDS/Components/Label/Attributes/TooltipLabelAttribute.swift +++ b/VDS/Components/Label/Attributes/TooltipLabelAttribute.swift @@ -24,8 +24,6 @@ public class TooltipLabelAttribute: ActionLabelAttributeModel, TooltipLaunchable public var presenter: UIView? public func setAttribute(on attributedString: NSMutableAttributedString) { - guard isValidRange(on: attributedString) else { return } - //update the location location = attributedString.string.count - 1 From 791bfc8870e1eead1608a3dfd9e93f75674f0cad Mon Sep 17 00:00:00 2001 From: vasavk Date: Fri, 5 Apr 2024 12:44:11 +0530 Subject: [PATCH 20/43] Digital ACT-191 ONEAPP-7135 story: Inline Text label alignment changes --- .../DropdownSelect/DropdownSelect.swift | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index 3e8aac32..e9b29a76 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -125,6 +125,7 @@ open class DropdownSelect: Control { private var inlineDisplayLabel = Label().with { $0.textAlignment = .left $0.textStyle = .boldBodyLarge + $0.lineBreakMode = .byCharWrapping $0.sizeToFit() } @@ -157,15 +158,13 @@ open class DropdownSelect: Control { //-------------------------------------------------- // MARK: - Constraints //-------------------------------------------------- - internal var widthConstraint: NSLayoutConstraint? internal var inlineWidthConstraint: NSLayoutConstraint? - + //-------------------------------------------------- // MARK: - Configuration Properties //-------------------------------------------------- - internal var containerSize: CGSize { CGSize(width: minWidthDefault, height: 44) } + internal var containerSize: CGSize { CGSize(width: inlineLabel ? minWidthDefault : minWidthInlineLabel, height: 44) } - /// Color configuration for error icon. internal let primaryColorConfig = ViewColorConfiguration().with { $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) @@ -217,6 +216,7 @@ open class DropdownSelect: Control { // stackview addSubview(stackView) + stackView.pinToSuperView() stackView.heightAnchor.constraint(greaterThanOrEqualToConstant: containerSize.height).isActive = true // container stack @@ -233,6 +233,8 @@ open class DropdownSelect: Control { containerStack.setCustomSpacing(VDSLayout.Spacing.space1X.value, after: inlineDisplayLabel) containerStack.setCustomSpacing(VDSLayout.Spacing.space3X.value, after: selectedOptionLabel) dropdownField.width(0) + inlineWidthConstraint = inlineDisplayLabel.widthAnchor.constraint(greaterThanOrEqualToConstant: 0) + inlineWidthConstraint?.isActive = true // component stackview subviews stackView.addArrangedSubview(eyebrowLabel) @@ -244,13 +246,7 @@ open class DropdownSelect: Control { stackView.setCustomSpacing(8, after: container) stackView.setCustomSpacing(8, after: errorLabel) - stackView.pinToSuperView() - inlineWidthConstraint = inlineDisplayLabel.widthAnchor.constraint(equalToConstant: 0) - inlineWidthConstraint?.isActive = true - - widthConstraint = stackView.widthAnchor.constraint(greaterThanOrEqualToConstant: minWidthDefault) - widthConstraint?.isActive = true - + // setting color config eyebrowLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() errorLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() helperLabel.textColorConfiguration = secondaryColorConfig.eraseToAnyColorable() @@ -258,6 +254,7 @@ open class DropdownSelect: Control { selectedOptionLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() icon.color = iconColorConfig.getColor(self) + // Options PickerView optionsPicker.delegate = self optionsPicker.dataSource = self optionsPicker.isHidden = true @@ -361,6 +358,8 @@ open class DropdownSelect: Control { open func updateInlineLabel() { + inlineWidthConstraint?.isActive = false + /// inline label text and selected option text separated by ':' if let label, !label.isEmpty { inlineDisplayLabel.text = inlineLabel ? (label + ":") : "" @@ -369,12 +368,9 @@ open class DropdownSelect: Control { } inlineDisplayLabel.surface = surface - /// Minimum width with inline text as per design - inlineWidthConstraint?.constant = inlineDisplayLabel.intrinsicContentSize.width - inlineWidthConstraint?.isActive = !inlineLabel - widthConstraint?.constant = inlineLabel ? minWidthInlineLabel : minWidthDefault - widthConstraint?.isActive = true - + /// Update width as per updated text size + inlineWidthConstraint = inlineDisplayLabel.widthAnchor.constraint(equalToConstant: inlineDisplayLabel.intrinsicContentSize.width) + inlineWidthConstraint?.isActive = true } open func updateSelectedOptionLabel(text: String? = nil) { From 51d1ded4c8f6c658718536d0f39c04e3d1f3a882 Mon Sep 17 00:00:00 2001 From: vasavk Date: Fri, 5 Apr 2024 21:08:52 +0530 Subject: [PATCH 21/43] Digital ACT-191 ONEAPP-7135 story: updated variable name for error boolean --- .../DropdownSelect/DropdownSelect.swift | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index e9b29a76..76518c93 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -75,14 +75,11 @@ open class DropdownSelect: Control { /// A callback when the selected option changes. Passes parameters (option). open var onDropdownItemSelect: ((DropdownOptionModel) -> Void)? - - /// Boolean value that determines if component should show the error state/error message. Functon receives the 'event' object on input change. - open var showError: Bool = false { didSet { setNeedsUpdate() }} - + open override var state: UIControl.State { get { var state = super.state - if showError { + if error { state.insert(.error) } return state @@ -209,8 +206,7 @@ open class DropdownSelect: Control { /// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations. open override func setup() { - super.setup() - + super.setup() isAccessibilityElement = true accessibilityLabel = "Dropdown Select" @@ -271,7 +267,7 @@ open class DropdownSelect: Control { container.backgroundColor = backgroundColorConfiguration.getColor(self) container.layer.borderWidth = VDSFormControls.widthBorder container.layer.cornerRadius = VDSFormControls.borderradius - container.layer.borderColor = readOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : (showError ? errorBorderColorConfiguration.getColor(self).cgColor : containerBorderColorConfiguration.getColor(self).cgColor) + container.layer.borderColor = readOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : (error ? errorBorderColorConfiguration.getColor(self).cgColor : containerBorderColorConfiguration.getColor(self).cgColor) dropdownField.isUserInteractionEnabled = readOnly ? false : true stackView.backgroundColor = transparentBackground ? .clear : surface.color @@ -289,7 +285,7 @@ open class DropdownSelect: Control { /// Used to update any Accessibility properties. open override func updateAccessibility() { super.updateAccessibility() - if showError { + if error { setAccessibilityLabel(for: [eyebrowLabel, selectedOptionLabel, errorLabel, helperLabel]) } else { setAccessibilityLabel(for: [eyebrowLabel, selectedOptionLabel, helperLabel]) @@ -378,7 +374,7 @@ open class DropdownSelect: Control { } open func updateErrorLabel() { - if showError, let errorText { + if error, let errorText { errorLabel.text = errorText errorLabel.surface = surface errorLabel.isEnabled = isEnabled From 99d6878ed92cb8b88199a5b3b0415cd8dd8d4903 Mon Sep 17 00:00:00 2001 From: vasavk Date: Fri, 5 Apr 2024 21:14:23 +0530 Subject: [PATCH 22/43] Digital ACT-191 ONEAPP-7135 story: removed unnecessary code --- VDS/Components/DropdownSelect/DropdownSelect.swift | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index 76518c93..ec179700 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -281,17 +281,7 @@ open class DropdownSelect: Control { selectedOptionLabel.surface = surface backgroundColor = surface.color } - - /// Used to update any Accessibility properties. - open override func updateAccessibility() { - super.updateAccessibility() - if error { - setAccessibilityLabel(for: [eyebrowLabel, selectedOptionLabel, errorLabel, helperLabel]) - } else { - setAccessibilityLabel(for: [eyebrowLabel, selectedOptionLabel, helperLabel]) - } - } - + /// Resets to default settings. open override func reset() { super.reset() From d0f5f26e823077b0f6a4d86ab7216f73406118d4 Mon Sep 17 00:00:00 2001 From: vasavk Date: Fri, 5 Apr 2024 21:36:29 +0530 Subject: [PATCH 23/43] Digital ACT-191 ONEAPP-7135 story: allowed selectedID to update selected label text --- VDS/Components/DropdownSelect/DropdownSelect.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index ec179700..39f182ca 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -59,7 +59,7 @@ open class DropdownSelect: Control { open var required: Bool = false { didSet { setNeedsUpdate() }} /// Allows unique ID to be passed to the element. - open var selectId: String? { didSet { setNeedsUpdate() }} + open var selectId: Int? { didSet { setNeedsUpdate() }} /// Config object for tooltip option, is optional. open var tooltipModel: Tooltip.TooltipModel? { didSet { setNeedsUpdate() } } @@ -357,6 +357,10 @@ open class DropdownSelect: Control { /// Update width as per updated text size inlineWidthConstraint = inlineDisplayLabel.widthAnchor.constraint(equalToConstant: inlineDisplayLabel.intrinsicContentSize.width) inlineWidthConstraint?.isActive = true + + if let selectId, selectId < options.count { + updateSelectedOptionLabel(text: options[selectId].text) + } } open func updateSelectedOptionLabel(text: String? = nil) { @@ -392,6 +396,7 @@ open class DropdownSelect: Control { } @objc open func pickerDoneClicked() { + optionsPicker.isHidden = true dropdownField.resignFirstResponder() } From f3f71b4b10f82970443de1d90c62f95c533fced0 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 5 Apr 2024 14:09:10 -0500 Subject: [PATCH 24/43] CXTDT-542341 - disabled state color/borderWidth CXTDT-542333 - padding fix Signed-off-by: Matt Bruce --- VDS/Components/RadioBox/RadioBoxItem.swift | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/VDS/Components/RadioBox/RadioBoxItem.swift b/VDS/Components/RadioBox/RadioBoxItem.swift index cfeb54e6..ef9ee4fa 100644 --- a/VDS/Components/RadioBox/RadioBoxItem.swift +++ b/VDS/Components/RadioBox/RadioBoxItem.swift @@ -34,16 +34,10 @@ open class RadioBoxItem: Control, Changeable, FormFieldable { //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- - private var mainStackView = UIStackView().with { - $0.translatesAutoresizingMaskIntoConstraints = false - $0.alignment = .top - $0.axis = .vertical - $0.spacing = 0 - } - private var selectorStackView = UIStackView().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.alignment = .top + $0.distribution = .fill $0.axis = .horizontal $0.spacing = 12 } @@ -160,6 +154,7 @@ open class RadioBoxItem: Control, Changeable, FormFieldable { $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled) $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .selected) $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .highlighted) + $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: [.selected, .disabled]) } //-------------------------------------------------- @@ -182,10 +177,8 @@ open class RadioBoxItem: Control, Changeable, FormFieldable { addSubview(selectorView) selectorView.isUserInteractionEnabled = false - selectorView.addSubview(mainStackView) - - mainStackView.addArrangedSubview(selectorStackView) - + selectorView.addSubview(selectorStackView) + selectorStackView.addArrangedSubview(selectorLeftLabelStackView) selectorStackView.addArrangedSubview(subTextRightLabel) selectorLeftLabelStackView.addArrangedSubview(textLabel) @@ -197,7 +190,7 @@ open class RadioBoxItem: Control, Changeable, FormFieldable { .pinTrailing(0, .defaultHigh) .pinBottom(0, .defaultHigh) - mainStackView.pinToSuperView(.uniform(16)) + selectorStackView.pinToSuperView(.uniform(16)) } /// Resets to default settings. @@ -323,7 +316,7 @@ open class RadioBoxItem: Control, Changeable, FormFieldable { //get the colors let backgroundColor = backgroundColorConfiguration.getColor(self) let borderColor = borderColorConfiguration.getColor(self) - let borderWidth = isSelected || isHighlighted ? selectorBorderWidthSelected : selectorBorderWidth + let borderWidth = (isSelected || isHighlighted) && isEnabled ? selectorBorderWidthSelected : selectorBorderWidth selectorView.backgroundColor = backgroundColor selectorView.layer.borderColor = borderColor.cgColor From 0f7d50eca4462487957ee16e928726078d904266 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 5 Apr 2024 14:23:28 -0500 Subject: [PATCH 25/43] CXTDT-542295 - ButtonIcon - disabled accessibility state. Signed-off-by: Matt Bruce --- VDS/Components/Icon/ButtonIcon/ButtonIcon.swift | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift b/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift index 738881e3..37e50b08 100644 --- a/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift +++ b/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift @@ -432,6 +432,7 @@ open class ButtonIcon: Control, Changeable, FormFieldable { icon.color = color icon.size = size.value icon.customSize = customSize + icon.isEnabled = isEnabled } else { icon.reset() } @@ -502,7 +503,6 @@ open class ButtonIcon: Control, Changeable, FormFieldable { badgeIndicator.isHidden = true return } - badgeIndicator.surface = surface badgeIndicator.kind = badgeIndicatorModel.kind badgeIndicator.fillColor = badgeIndicatorModel.fillColor @@ -538,11 +538,6 @@ open class ButtonIcon: Control, Changeable, FormFieldable { } } - /// Used to update any Accessibility properties. - open override func updateAccessibility() { - super.updateAccessibility() - setAccessibilityLabel(for: [icon, badgeIndicator.label]) - } } // MARK: AppleGuidelinesTouchable From 40dbc51b75e360a62dd060dda5827eab70f3528b Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 5 Apr 2024 15:00:08 -0500 Subject: [PATCH 26/43] ONEAPP-6360 - Notification - Accessiblity issues Signed-off-by: Matt Bruce --- .../Notification/Notification.swift | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/VDS/Components/Notification/Notification.swift b/VDS/Components/Notification/Notification.swift index 7dd36b4c..7ed25962 100644 --- a/VDS/Components/Notification/Notification.swift +++ b/VDS/Components/Notification/Notification.swift @@ -39,18 +39,32 @@ open class Notification: View { public enum Style: String, CaseIterable { case info, success, warning, error - func iconName() -> Icon.Name { + var iconName: Icon.Name { switch self { case .info: - return .infoBold + .infoBold case .success: - return .checkmarkAltBold + .checkmarkAltBold case .warning: - return .warningBold + .warningBold case .error: - return .errorBold + .errorBold } } + + var accessibilityText: String { + switch self { + case .info: + "Information Message" + case .success: + "Success Message" + case .warning: + "Warning Message" + case .error: + "Catastrophic Warning Alert" + } + } + } //-------------------------------------------------- @@ -309,8 +323,9 @@ open class Notification: View { //-------------------------------------------------- private func updateIcons() { let iconColor = surface == .dark ? VDSColor.paletteWhite : VDSColor.paletteBlack - typeIcon.name = style.iconName() + typeIcon.name = style.iconName typeIcon.color = iconColor + typeIcon.accessibilityLabel = style.accessibilityText closeButton.color = iconColor closeButton.isHidden = hideCloseButton } From 629ff90a21ded87c4c43cad9505776831686bb63 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 5 Apr 2024 15:04:19 -0500 Subject: [PATCH 27/43] updated the release notes Signed-off-by: Matt Bruce --- VDS/SupportingFiles/ReleaseNotes.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/VDS/SupportingFiles/ReleaseNotes.txt b/VDS/SupportingFiles/ReleaseNotes.txt index 94d304a7..c62a7946 100644 --- a/VDS/SupportingFiles/ReleaseNotes.txt +++ b/VDS/SupportingFiles/ReleaseNotes.txt @@ -1,3 +1,10 @@ +1.0.58 +---------------- +- CXTDT-542341 - RadioButtonItem - disabled state color/borderWidth +- CXTDT-542333 - RadioButtonItem - padding fix +- CXTDT-542295 - ButtonIcon - Disabled state +- ONEAPP-6360 - Notification - Accessiblity issues + 1.0.57 ---------------- - CXTDT-540077 - BadgeIndicator Font From c0244a29d45d30279d255c4b95256bc5dc946368 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 5 Apr 2024 15:04:44 -0500 Subject: [PATCH 28/43] updated version Signed-off-by: Matt Bruce --- VDS.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index b103afc6..b583c220 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -1369,7 +1369,7 @@ BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 57; + CURRENT_PROJECT_VERSION = 58; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1406,7 +1406,7 @@ BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 57; + CURRENT_PROJECT_VERSION = 58; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; From f584ccd6bac63f48155fa241fc0a861c13522ef5 Mon Sep 17 00:00:00 2001 From: vasavk Date: Mon, 8 Apr 2024 16:22:01 +0530 Subject: [PATCH 29/43] Digital ACT-191 ONEAPP-7135 story: minor changes on noticed issues --- VDS/Components/DropdownSelect/DropdownSelect.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index 39f182ca..3b1549df 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -308,6 +308,7 @@ open class DropdownSelect: Control { transparentBackground = false required = false options = [] + selectId = 0 } //-------------------------------------------------- @@ -449,6 +450,7 @@ extension DropdownSelect: UIPickerViewDelegate, UIPickerViewDataSource, UITextFi public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { guard options.count > row else { return } + selectId = row updateSelectedOptionLabel(text: options[row].text) self.onDropdownItemSelect?(options[row]) } From 67c96ca74cfab7f840c06ca85a4a9ceaaaa6f603 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 8 Apr 2024 10:15:11 -0500 Subject: [PATCH 30/43] moved maxLength out of base Signed-off-by: Matt Bruce --- VDS/Components/TextFields/EntryFieldBase.swift | 5 +---- VDS/Components/TextFields/TextArea/TextArea.swift | 10 +++++++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/VDS/Components/TextFields/EntryFieldBase.swift b/VDS/Components/TextFields/EntryFieldBase.swift index 5d8957fe..ce76ea16 100644 --- a/VDS/Components/TextFields/EntryFieldBase.swift +++ b/VDS/Components/TextFields/EntryFieldBase.swift @@ -197,9 +197,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable { open var transparentBackground: Bool = false { didSet { setNeedsUpdate() } } open var width: CGFloat? { didSet { setNeedsUpdate() } } - - open var maxLength: Int? { didSet { setNeedsUpdate() } } - + open var inputId: String? { didSet { setNeedsUpdate() } } /// The text of this textField. @@ -308,7 +306,6 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable { tooltipModel = nil transparentBackground = false width = nil - maxLength = nil inputId = nil value = nil defaultValue = nil diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index b5fada0c..5ce47b1f 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -127,7 +127,15 @@ open class TextArea: EntryFieldBase { $0.isScrollEnabled = false } - open override var maxLength: Int? { willSet { countRule.maxLength = newValue }} + open var maxLength: Int? { + willSet { + countRule.maxLength = newValue + } + + didSet { + setNeedsUpdate() + } + } /// Color configuration for error icon. internal var iconColorConfiguration = ControlColorConfiguration().with { From 52eaed7be6b9d4df975695bd175f6a6bb3a83d3c Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 8 Apr 2024 10:50:24 -0500 Subject: [PATCH 31/43] added new iconNames Signed-off-by: Matt Bruce --- VDS/Components/Icon/IconName.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/VDS/Components/Icon/IconName.swift b/VDS/Components/Icon/IconName.swift index 1234df63..cfdf1cf2 100644 --- a/VDS/Components/Icon/IconName.swift +++ b/VDS/Components/Icon/IconName.swift @@ -51,6 +51,8 @@ extension Icon { public static let checkmark = Name(name: "checkmark") public static let checkmarkAlt = Name(name: "checkmark-alt") public static let close = Name(name: "close") + public static let downCaret = Name(name: "down-caret") + public static let downCaretBold = Name(name: "down-caret-bold") public static let error = Name(name: "error") public static let info = Name(name: "info") public static let multipleDocuments = Name(name: "multiple-documents") From fc6c398b3f6b13fd5cc70e3b4bdda77f1aa45182 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 8 Apr 2024 10:50:57 -0500 Subject: [PATCH 32/43] refactored to similar naming conventions for existing components Signed-off-by: Matt Bruce --- .../DropdownSelect/DropdownSelect.swift | 82 +++++++++---------- 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index 3b1549df..69f6d92a 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -35,22 +35,19 @@ open class DropdownSelect: Control { //-------------------------------------------------- /// Boolean value that determines if component should show the error state/error message. - open var error: Bool = false { didSet { setNeedsUpdate() }} + open var showError: Bool = false { didSet { setNeedsUpdate() }} /// Message displayed when there is an error. open var errorText: String? { didSet { setNeedsUpdate() }} /// If provided, will be used as text for the helper label. open var helperText: String? { didSet { setNeedsUpdate() }} - - /// Used if the component is enabled or not. - open override var isEnabled: Bool { didSet { setNeedsUpdate() }} - - /// If true, the label will be displayed inside the dropdown container. Otherwise, the label will be above the dropdown container like a normal text input. - open var inlineLabel: Bool = false { didSet { setNeedsUpdate() }} + + /// If true, the label will be displayed inside the dropdown containerView. Otherwise, the label will be above the dropdown containerView like a normal text input. + open var showInlineLabel: Bool = false { didSet { setNeedsUpdate() }} /// If provided, will be used as context for the label on the input field. - open var label: String? { didSet { setNeedsUpdate() }} + open var labelText: String? { didSet { setNeedsUpdate() }} /// Not allowed the user interaction to select/change input if it is true. open var readOnly: Bool = false { didSet { setNeedsUpdate() }} @@ -79,7 +76,7 @@ open class DropdownSelect: Control { open override var state: UIControl.State { get { var state = super.state - if error { + if showError { state.insert(.error) } return state @@ -97,13 +94,13 @@ open class DropdownSelect: Control { $0.axis = .vertical } - private var eyebrowLabel = TrailingTooltipLabel().with { + private var titleLabel = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) - $0.labelTextAlignment = .left - $0.labelTextStyle = .bodySmall + $0.textAlignment = .left + $0.textStyle = .bodySmall } - var container: UIView = UIView().with { + var containerView: UIView = UIView().with { $0.translatesAutoresizingMaskIntoConstraints = false } @@ -160,7 +157,7 @@ open class DropdownSelect: Control { //-------------------------------------------------- // MARK: - Configuration Properties //-------------------------------------------------- - internal var containerSize: CGSize { CGSize(width: inlineLabel ? minWidthDefault : minWidthInlineLabel, height: 44) } + internal var containerSize: CGSize { CGSize(width: showInlineLabel ? minWidthInlineLabel : width ?? minWidthDefault, height: 44) } internal let primaryColorConfig = ViewColorConfiguration().with { $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) @@ -215,8 +212,8 @@ open class DropdownSelect: Control { stackView.pinToSuperView() stackView.heightAnchor.constraint(greaterThanOrEqualToConstant: containerSize.height).isActive = true - // container stack - container.addSubview(containerStack) + // containerView stack + containerView.addSubview(containerStack) let spacing = VDSFormControls.spaceInset containerStack.pinToSuperView(.init(top: spacing, left: spacing, bottom: spacing, right: spacing)) @@ -233,17 +230,17 @@ open class DropdownSelect: Control { inlineWidthConstraint?.isActive = true // component stackview subviews - stackView.addArrangedSubview(eyebrowLabel) - stackView.addArrangedSubview(container) + stackView.addArrangedSubview(titleLabel) + stackView.addArrangedSubview(containerView) stackView.addArrangedSubview(errorLabel) stackView.addArrangedSubview(helperLabel) - stackView.setCustomSpacing(4, after: eyebrowLabel) - stackView.setCustomSpacing(8, after: container) + stackView.setCustomSpacing(4, after: titleLabel) + stackView.setCustomSpacing(8, after: containerView) stackView.setCustomSpacing(8, after: errorLabel) // setting color config - eyebrowLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() + titleLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() errorLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() helperLabel.textColorConfiguration = secondaryColorConfig.eraseToAnyColorable() inlineDisplayLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() @@ -264,10 +261,10 @@ open class DropdownSelect: Control { /// Used to make changes to the View based off a change events or from local properties. open override func updateView() { - container.backgroundColor = backgroundColorConfiguration.getColor(self) - container.layer.borderWidth = VDSFormControls.widthBorder - container.layer.cornerRadius = VDSFormControls.borderradius - container.layer.borderColor = readOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : (error ? errorBorderColorConfiguration.getColor(self).cgColor : containerBorderColorConfiguration.getColor(self).cgColor) + containerView.backgroundColor = backgroundColorConfiguration.getColor(self) + containerView.layer.borderWidth = VDSFormControls.widthBorder + containerView.layer.cornerRadius = VDSFormControls.borderradius + containerView.layer.borderColor = readOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : (showError ? errorBorderColorConfiguration.getColor(self).cgColor : containerBorderColorConfiguration.getColor(self).cgColor) dropdownField.isUserInteractionEnabled = readOnly ? false : true stackView.backgroundColor = transparentBackground ? .clear : surface.color @@ -286,24 +283,24 @@ open class DropdownSelect: Control { open override func reset() { super.reset() - eyebrowLabel.reset() + titleLabel.reset() inlineDisplayLabel.reset() selectedOptionLabel.reset() errorLabel.reset() helperLabel.reset() - eyebrowLabel.labelTextStyle = .bodySmall + titleLabel.textStyle = .bodySmall inlineDisplayLabel.textStyle = .boldBodyLarge selectedOptionLabel.textStyle = .bodyLarge errorLabel.textStyle = .bodySmall helperLabel.textStyle = .bodySmall tooltipModel = nil - label = nil + labelText = nil errorText = nil - error = false + showError = false isEnabled = false readOnly = false - inlineLabel = false + showInlineLabel = false helperText = nil transparentBackground = false required = false @@ -319,16 +316,16 @@ open class DropdownSelect: Control { //update the local vars for the label since we no long have a model var attributes: [any LabelAttributeModel] = [] - var updatedLabelText = label + var updatedLabelText = labelText - updatedLabelText = inlineLabel ? "" : updatedLabelText + updatedLabelText = showInlineLabel ? "" : updatedLabelText if let oldText = updatedLabelText, !required, !oldText.hasSuffix("Optional") { let optionColorAttr = ColorLabelAttribute(location: oldText.count + 2, length: 8, color: secondaryColorConfig.getColor(self)) - updatedLabelText = "\(oldText) Optional" + updatedLabelText = showInlineLabel ? "Optional" : "\(oldText) Optional" attributes.append(optionColorAttr) } @@ -336,11 +333,10 @@ open class DropdownSelect: Control { attributes.append(TooltipLabelAttribute(surface: surface, model: tooltipModel, presenter: self)) } - eyebrowLabel.labelText = updatedLabelText - eyebrowLabel.labelAttributes = attributes - eyebrowLabel.tooltipModel = tooltipModel - eyebrowLabel.surface = surface - eyebrowLabel.isEnabled = isEnabled + titleLabel.text = updatedLabelText + titleLabel.attributes = attributes + titleLabel.surface = surface + titleLabel.isEnabled = isEnabled } open func updateInlineLabel() { @@ -348,10 +344,10 @@ open class DropdownSelect: Control { inlineWidthConstraint?.isActive = false /// inline label text and selected option text separated by ':' - if let label, !label.isEmpty { - inlineDisplayLabel.text = inlineLabel ? (label + ":") : "" + if let labelText, !labelText.isEmpty { + inlineDisplayLabel.text = showInlineLabel ? (labelText + ":") : "" } else { - inlineDisplayLabel.text = inlineLabel ? label : "" + inlineDisplayLabel.text = showInlineLabel ? labelText : "" } inlineDisplayLabel.surface = surface @@ -369,7 +365,7 @@ open class DropdownSelect: Control { } open func updateErrorLabel() { - if error, let errorText { + if showError, let errorText { errorLabel.text = errorText errorLabel.surface = surface errorLabel.isEnabled = isEnabled @@ -379,7 +375,7 @@ open class DropdownSelect: Control { icon.color = .black icon.surface = surface } else { - icon.name = Icon.Name(name: "down-caret") + icon.name = .downCaret icon.surface = surface errorLabel.isHidden = true } From c0c666c2cb0aeeb4de7d8421c72aab20367e22ac Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 8 Apr 2024 11:11:12 -0500 Subject: [PATCH 33/43] fixed error/disabled border Signed-off-by: Matt Bruce --- .../DropdownSelect/DropdownSelect.swift | 16 +++++++--------- VDS/Components/TextFields/EntryFieldBase.swift | 3 ++- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index 69f6d92a..68e4fba4 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -181,18 +181,14 @@ open class DropdownSelect: Control { $0.setSurfaceColors(VDSColor.feedbackErrorBackgroundOnlight, VDSColor.feedbackErrorBackgroundOndark, forState: .error) } - internal var containerBorderColorConfiguration = ControlColorConfiguration().with { + internal var borderColorConfiguration = ControlColorConfiguration().with { $0.setSurfaceColors(VDSFormControlsColor.borderOnlight, VDSFormControlsColor.borderOnlight, forState: .normal) $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled) + $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: [.disabled,.error]) $0.setSurfaceColors(VDSColor.feedbackErrorOnlight, VDSColor.feedbackErrorOndark, forState: .error) $0.setSurfaceColors(VDSFormControlsColor.borderHoverOnlight, VDSFormControlsColor.borderHoverOndark, forState: .focused) } - - internal var errorBorderColorConfiguration = ControlColorConfiguration().with { - $0.setSurfaceColors(VDSColor.feedbackErrorOnlight, VDSColor.feedbackErrorOndark, forState: .error) - $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .focused) - } - + internal var readOnlyBorderColorConfiguration = ControlColorConfiguration().with { $0.setSurfaceColors(VDSFormControlsColor.borderReadonlyOnlight, VDSFormControlsColor.borderReadonlyOndark, forState: .normal) } @@ -264,7 +260,7 @@ open class DropdownSelect: Control { containerView.backgroundColor = backgroundColorConfiguration.getColor(self) containerView.layer.borderWidth = VDSFormControls.widthBorder containerView.layer.cornerRadius = VDSFormControls.borderradius - containerView.layer.borderColor = readOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : (showError ? errorBorderColorConfiguration.getColor(self).cgColor : containerBorderColorConfiguration.getColor(self).cgColor) + containerView.layer.borderColor = readOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : borderColorConfiguration.getColor(self).cgColor dropdownField.isUserInteractionEnabled = readOnly ? false : true stackView.backgroundColor = transparentBackground ? .clear : surface.color @@ -276,6 +272,7 @@ open class DropdownSelect: Control { icon.name = nil } selectedOptionLabel.surface = surface + selectedOptionLabel.isEnabled = isEnabled backgroundColor = surface.color } @@ -350,6 +347,7 @@ open class DropdownSelect: Control { inlineDisplayLabel.text = showInlineLabel ? labelText : "" } inlineDisplayLabel.surface = surface + inlineDisplayLabel.isEnabled = isEnabled /// Update width as per updated text size inlineWidthConstraint = inlineDisplayLabel.widthAnchor.constraint(equalToConstant: inlineDisplayLabel.intrinsicContentSize.width) @@ -372,13 +370,13 @@ open class DropdownSelect: Control { errorLabel.isHidden = false icon.name = .error icon.size = .medium - icon.color = .black icon.surface = surface } else { icon.name = .downCaret icon.surface = surface errorLabel.isHidden = true } + icon.color = titleLabel.textColorConfiguration.getColor(self) } open func updateHelperLabel() { diff --git a/VDS/Components/TextFields/EntryFieldBase.swift b/VDS/Components/TextFields/EntryFieldBase.swift index ce76ea16..f6bba297 100644 --- a/VDS/Components/TextFields/EntryFieldBase.swift +++ b/VDS/Components/TextFields/EntryFieldBase.swift @@ -110,6 +110,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable { $0.setSurfaceColors(VDSFormControlsColor.borderOnlight, VDSFormControlsColor.borderOndark, forState: .normal) $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled) $0.setSurfaceColors(VDSColor.feedbackErrorOnlight, VDSColor.feedbackErrorOndark, forState: .error) + $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: [.disabled,.error]) } internal var readOnlyBorderColorConfiguration = ControlColorConfiguration().with { @@ -332,7 +333,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable { //-------------------------------------------------- private func updateContainerView() { containerView.backgroundColor = backgroundColorConfiguration.getColor(self) - containerView.layer.borderColor = borderColorConfiguration.getColor(self).cgColor + containerView.layer.borderColor = readOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : borderColorConfiguration.getColor(self).cgColor containerView.layer.borderWidth = VDSFormControls.widthBorder containerView.layer.cornerRadius = VDSFormControls.borderradius } From e7220e67a393bac0937ee3ffbb7a70d6cba0a697 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 8 Apr 2024 11:26:09 -0500 Subject: [PATCH 34/43] put to public since all subcomponents are required to be accessible to devs. Signed-off-by: Matt Bruce --- .../DropdownSelect/DropdownSelect.swift | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index 68e4fba4..072a9846 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -93,13 +93,7 @@ open class DropdownSelect: Control { $0.translatesAutoresizingMaskIntoConstraints = false $0.axis = .vertical } - - private var titleLabel = Label().with { - $0.setContentCompressionResistancePriority(.required, for: .vertical) - $0.textAlignment = .left - $0.textStyle = .bodySmall - } - + var containerView: UIView = UIView().with { $0.translatesAutoresizingMaskIntoConstraints = false } @@ -110,44 +104,53 @@ open class DropdownSelect: Control { $0.spacing = VDSFormControls.spaceInset } - private var dropdownField = UITextField().with { - $0.translatesAutoresizingMaskIntoConstraints = false - $0.tintColor = UIColor.clear - $0.font = TextStyle.bodyLarge.font + //-------------------------------------------------- + // MARK: - Public Properties + //-------------------------------------------------- + open var titleLabel = Label().with { + $0.setContentCompressionResistancePriority(.required, for: .vertical) + $0.textAlignment = .left + $0.textStyle = .bodySmall } - private var inlineDisplayLabel = Label().with { + open var inlineDisplayLabel = Label().with { $0.textAlignment = .left $0.textStyle = .boldBodyLarge $0.lineBreakMode = .byCharWrapping $0.sizeToFit() } - private var selectedOptionLabel = Label().with { + open var selectedOptionLabel = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) $0.textAlignment = .left $0.textStyle = .bodyLarge $0.lineBreakMode = .byCharWrapping } - private var icon: Icon = Icon().with { + open var icon: Icon = Icon().with { $0.size = .medium $0.name = Icon.Name(name: "down-caret") } - private var errorLabel = Label().with { + open var errorLabel = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) $0.textAlignment = .left $0.textStyle = .bodySmall } - private var helperLabel = Label().with { + open var helperLabel = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) $0.textAlignment = .left $0.textStyle = .bodySmall } - private var optionsPicker = UIPickerView() + open var dropdownField = UITextField().with { + $0.translatesAutoresizingMaskIntoConstraints = false + $0.tintColor = UIColor.clear + $0.font = TextStyle.bodyLarge.font + } + + open var optionsPicker = UIPickerView() //-------------------------------------------------- // MARK: - Constraints @@ -376,7 +379,7 @@ open class DropdownSelect: Control { icon.surface = surface errorLabel.isHidden = true } - icon.color = titleLabel.textColorConfiguration.getColor(self) + icon.color = iconColorConfig.getColor(self) } open func updateHelperLabel() { From 7b722e4c7e63b8387651a48422610b84e7bcf482 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 9 Apr 2024 14:33:10 -0500 Subject: [PATCH 35/43] renamed Signed-off-by: Matt Bruce --- .../DropdownSelect/DropdownSelect.swift | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index 072a9846..55510dd4 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -98,7 +98,7 @@ open class DropdownSelect: Control { $0.translatesAutoresizingMaskIntoConstraints = false } - var containerStack: UIStackView = UIStackView().with { + var containerStackView: UIStackView = UIStackView().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.axis = .horizontal $0.spacing = VDSFormControls.spaceInset @@ -212,18 +212,18 @@ open class DropdownSelect: Control { stackView.heightAnchor.constraint(greaterThanOrEqualToConstant: containerSize.height).isActive = true // containerView stack - containerView.addSubview(containerStack) + containerView.addSubview(containerStackView) let spacing = VDSFormControls.spaceInset - containerStack.pinToSuperView(.init(top: spacing, left: spacing, bottom: spacing, right: spacing)) + containerStackView.pinToSuperView(.init(top: spacing, left: spacing, bottom: spacing, right: spacing)) - containerStack.addArrangedSubview(dropdownField) - containerStack.addArrangedSubview(inlineDisplayLabel) - containerStack.addArrangedSubview(selectedOptionLabel) - containerStack.addArrangedSubview(icon) + containerStackView.addArrangedSubview(dropdownField) + containerStackView.addArrangedSubview(inlineDisplayLabel) + containerStackView.addArrangedSubview(selectedOptionLabel) + containerStackView.addArrangedSubview(icon) - containerStack.setCustomSpacing(0, after: dropdownField) - containerStack.setCustomSpacing(VDSLayout.Spacing.space1X.value, after: inlineDisplayLabel) - containerStack.setCustomSpacing(VDSLayout.Spacing.space3X.value, after: selectedOptionLabel) + containerStackView.setCustomSpacing(0, after: dropdownField) + containerStackView.setCustomSpacing(VDSLayout.Spacing.space1X.value, after: inlineDisplayLabel) + containerStackView.setCustomSpacing(VDSLayout.Spacing.space3X.value, after: selectedOptionLabel) dropdownField.width(0) inlineWidthConstraint = inlineDisplayLabel.widthAnchor.constraint(greaterThanOrEqualToConstant: 0) inlineWidthConstraint?.isActive = true @@ -252,7 +252,7 @@ open class DropdownSelect: Control { optionsPicker.isHidden = true dropdownField.inputView = optionsPicker dropdownField.inputAccessoryView = toolBarForPicker() - containerStack.publisher(for: UITapGestureRecognizer()).sink { [weak self] _ in + containerStackView.publisher(for: UITapGestureRecognizer()).sink { [weak self] _ in self?.launchPicker() }.store(in: &subscribers) } From 7b9aa51d0a5b720a762415f6fe410b729485b8ce Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 9 Apr 2024 15:37:58 -0500 Subject: [PATCH 36/43] refactored out text of base class Signed-off-by: Matt Bruce --- .../TextFields/EntryFieldBase.swift | 21 ++----------------- .../TextFields/InputField/InputField.swift | 15 ++++++++++++- .../TextFields/TextArea/TextArea.swift | 15 ++++++++++++- 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/VDS/Components/TextFields/EntryFieldBase.swift b/VDS/Components/TextFields/EntryFieldBase.swift index f6bba297..c57a3432 100644 --- a/VDS/Components/TextFields/EntryFieldBase.swift +++ b/VDS/Components/TextFields/EntryFieldBase.swift @@ -186,13 +186,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable { setNeedsUpdate() } } - - /// Override this to conveniently get/set the textfield(s). - open var text: String? { - get { nil } - set { fatalError("You MUST override EntryField's 'text' variable in your subclass.") } - } - + open var tooltipModel: Tooltip.TooltipModel? { didSet { setNeedsUpdate() } } open var transparentBackground: Bool = false { didSet { setNeedsUpdate() } } @@ -201,18 +195,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable { open var inputId: String? { didSet { setNeedsUpdate() } } - /// The text of this textField. - private var _value: String? - open var value: String? { - get { _value } - set { - if let newValue, newValue != _value { - _value = newValue - text = newValue - } - setNeedsUpdate() - } - } + open var value: String? { didSet { setNeedsUpdate() } } open var defaultValue: AnyHashable? { didSet { setNeedsUpdate() } } diff --git a/VDS/Components/TextFields/InputField/InputField.swift b/VDS/Components/TextFields/InputField/InputField.swift index ebd76525..b739b577 100644 --- a/VDS/Components/TextFields/InputField/InputField.swift +++ b/VDS/Components/TextFields/InputField/InputField.swift @@ -79,7 +79,7 @@ open class InputField: EntryFieldBase, UITextFieldDelegate { open var fieldType: FieldType = .text { didSet { setNeedsUpdate() } } /// The text of this textField. - open override var text: String? { + open var text: String? { get { textField.text } set { if let newValue, newValue != text { @@ -89,6 +89,19 @@ open class InputField: EntryFieldBase, UITextFieldDelegate { setNeedsUpdate() } } + + /// The value of this textField. + private var _value: String? + open override var value: String? { + get { _value } + set { + if let newValue, newValue != _value { + _value = newValue + text = newValue + } + setNeedsUpdate() + } + } var _showError: Bool = false /// Whether not to show the error. diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index 5ce47b1f..ee09ecb3 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -108,7 +108,7 @@ open class TextArea: EntryFieldBase { /// The text of this textView private var _text: String? - open override var text: String? { + open var text: String? { get { textView.text } set { if let newValue, newValue != _text { @@ -119,6 +119,19 @@ open class TextArea: EntryFieldBase { setNeedsUpdate() } } + + /// The text of this textField. + private var _value: String? + open override var value: String? { + get { _value } + set { + if let newValue, newValue != _value { + _value = newValue + text = newValue + } + setNeedsUpdate() + } + } /// UITextView shown in the TextArea. open var textView = TextView().with { From 8311de540979e5991ba37ce989eea7de833b26a9 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 9 Apr 2024 15:38:10 -0500 Subject: [PATCH 37/43] added value in case there is a difference Signed-off-by: Matt Bruce --- VDS/Components/DropdownSelect/DropdownOptionModel.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/VDS/Components/DropdownSelect/DropdownOptionModel.swift b/VDS/Components/DropdownSelect/DropdownOptionModel.swift index ba7caa7f..c82519eb 100644 --- a/VDS/Components/DropdownSelect/DropdownOptionModel.swift +++ b/VDS/Components/DropdownSelect/DropdownOptionModel.swift @@ -12,9 +12,11 @@ extension DropdownSelect { /// Text that goes as option to DropdownSelect public var text: String + public var value: String - public init(text: String) { + public init(text: String, value: String? = nil) { self.text = text + self.value = value ?? text } } } From 4f0f611fb65ea3fa40b81ae012e0c6d1f3eb835a Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 9 Apr 2024 15:38:39 -0500 Subject: [PATCH 38/43] now subclassing EntryFieldBase Signed-off-by: Matt Bruce --- .../DropdownSelect/DropdownSelect.swift | 304 ++++-------------- 1 file changed, 67 insertions(+), 237 deletions(-) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index 55510dd4..94f7112d 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -13,8 +13,7 @@ import Combine /// A dropdown select is an expandable menu of predefined options that allows a customer to make a single selection. @objc(VDSDropdownSelect) -open class DropdownSelect: Control { - +open class DropdownSelect: EntryFieldBase { //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- @@ -33,86 +32,27 @@ open class DropdownSelect: Control { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- - - /// Boolean value that determines if component should show the error state/error message. - open var showError: Bool = false { didSet { setNeedsUpdate() }} - - /// Message displayed when there is an error. - open var errorText: String? { didSet { setNeedsUpdate() }} - - /// If provided, will be used as text for the helper label. - open var helperText: String? { didSet { setNeedsUpdate() }} - /// If true, the label will be displayed inside the dropdown containerView. Otherwise, the label will be above the dropdown containerView like a normal text input. open var showInlineLabel: Bool = false { didSet { setNeedsUpdate() }} - - /// If provided, will be used as context for the label on the input field. - open var labelText: String? { didSet { setNeedsUpdate() }} - - /// Not allowed the user interaction to select/change input if it is true. - open var readOnly: Bool = false { didSet { setNeedsUpdate() }} - - /// Used to show optional indicator for the label. - open var required: Bool = false { didSet { setNeedsUpdate() }} - + /// Allows unique ID to be passed to the element. open var selectId: Int? { didSet { setNeedsUpdate() }} - /// Config object for tooltip option, is optional. - open var tooltipModel: Tooltip.TooltipModel? { didSet { setNeedsUpdate() } } - - /// If provided, will render with trnasparent background. - open var transparentBackground: Bool = false { didSet { setNeedsUpdate() }} - - /// Used to set width for the Dropdown Select. - open var width: CGFloat? { didSet { setNeedsUpdate() } } - /// Array of options to show open var options: [DropdownOptionModel] = [] { didSet { setNeedsUpdate() }} /// A callback when the selected option changes. Passes parameters (option). open var onDropdownItemSelect: ((DropdownOptionModel) -> Void)? - open override var state: UIControl.State { - get { - var state = super.state - if showError { - state.insert(.error) - } - return state - } - } - //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- internal var minWidthDefault = 66.0 internal var minWidthInlineLabel = 102.0 - - var stackView: UIStackView = UIStackView().with { - $0.translatesAutoresizingMaskIntoConstraints = false - $0.axis = .vertical - } - - var containerView: UIView = UIView().with { - $0.translatesAutoresizingMaskIntoConstraints = false - } - - var containerStackView: UIStackView = UIStackView().with { - $0.translatesAutoresizingMaskIntoConstraints = false - $0.axis = .horizontal - $0.spacing = VDSFormControls.spaceInset - } - + //-------------------------------------------------- // MARK: - Public Properties - //-------------------------------------------------- - open var titleLabel = Label().with { - $0.setContentCompressionResistancePriority(.required, for: .vertical) - $0.textAlignment = .left - $0.textStyle = .bodySmall - } - + //-------------------------------------------------- open var inlineDisplayLabel = Label().with { $0.textAlignment = .left $0.textStyle = .boldBodyLarge @@ -126,24 +66,7 @@ open class DropdownSelect: Control { $0.textStyle = .bodyLarge $0.lineBreakMode = .byCharWrapping } - - open var icon: Icon = Icon().with { - $0.size = .medium - $0.name = Icon.Name(name: "down-caret") - } - - open var errorLabel = Label().with { - $0.setContentCompressionResistancePriority(.required, for: .vertical) - $0.textAlignment = .left - $0.textStyle = .bodySmall - } - - open var helperLabel = Label().with { - $0.setContentCompressionResistancePriority(.required, for: .vertical) - $0.textAlignment = .left - $0.textStyle = .bodySmall - } - + open var dropdownField = UITextField().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.tintColor = UIColor.clear @@ -160,42 +83,14 @@ open class DropdownSelect: Control { //-------------------------------------------------- // MARK: - Configuration Properties //-------------------------------------------------- - internal var containerSize: CGSize { CGSize(width: showInlineLabel ? minWidthInlineLabel : width ?? minWidthDefault, height: 44) } - - internal let primaryColorConfig = ViewColorConfiguration().with { - $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) - $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) - } - - internal let secondaryColorConfig = ViewColorConfiguration().with { - $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) - $0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark, forDisabled: false) - } - - internal let iconColorConfig = ControlColorConfiguration().with { + internal override var containerSize: CGSize { CGSize(width: showInlineLabel ? minWidthInlineLabel : width ?? minWidthDefault, height: 44) } + + internal let iconColorConfiguration = ControlColorConfiguration().with { $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal) $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled) $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .error) } - - internal var backgroundColorConfiguration = ControlColorConfiguration().with { - $0.setSurfaceColors(VDSFormControlsColor.backgroundOnlight, VDSFormControlsColor.backgroundOndark, forState: .normal) - $0.setSurfaceColors(VDSFormControlsColor.backgroundOnlight, VDSFormControlsColor.backgroundOndark, forState: .disabled) - $0.setSurfaceColors(VDSColor.feedbackErrorBackgroundOnlight, VDSColor.feedbackErrorBackgroundOndark, forState: .error) - } - - internal var borderColorConfiguration = ControlColorConfiguration().with { - $0.setSurfaceColors(VDSFormControlsColor.borderOnlight, VDSFormControlsColor.borderOnlight, forState: .normal) - $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled) - $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: [.disabled,.error]) - $0.setSurfaceColors(VDSColor.feedbackErrorOnlight, VDSColor.feedbackErrorOndark, forState: .error) - $0.setSurfaceColors(VDSFormControlsColor.borderHoverOnlight, VDSFormControlsColor.borderHoverOndark, forState: .focused) - } - - internal var readOnlyBorderColorConfiguration = ControlColorConfiguration().with { - $0.setSurfaceColors(VDSFormControlsColor.borderReadonlyOnlight, VDSFormControlsColor.borderReadonlyOndark, forState: .normal) - } - + //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- @@ -203,107 +98,78 @@ open class DropdownSelect: Control { /// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations. open override func setup() { super.setup() - isAccessibilityElement = true + accessibilityLabel = "Dropdown Select" - // stackview - addSubview(stackView) - stackView.pinToSuperView() - stackView.heightAnchor.constraint(greaterThanOrEqualToConstant: containerSize.height).isActive = true - - // containerView stack - containerView.addSubview(containerStackView) - let spacing = VDSFormControls.spaceInset - containerStackView.pinToSuperView(.init(top: spacing, left: spacing, bottom: spacing, right: spacing)) + // stackview for controls in EntryFieldBase.controlContainerView + let controlStackView = UIStackView().with { + $0.translatesAutoresizingMaskIntoConstraints = false + $0.axis = .horizontal + $0.spacing = VDSFormControls.spaceInset + } + controlContainerView.addSubview(controlStackView) + controlStackView.pinToSuperView() - containerStackView.addArrangedSubview(dropdownField) - containerStackView.addArrangedSubview(inlineDisplayLabel) - containerStackView.addArrangedSubview(selectedOptionLabel) - containerStackView.addArrangedSubview(icon) + controlStackView.addArrangedSubview(dropdownField) + controlStackView.addArrangedSubview(inlineDisplayLabel) + controlStackView.addArrangedSubview(selectedOptionLabel) - containerStackView.setCustomSpacing(0, after: dropdownField) - containerStackView.setCustomSpacing(VDSLayout.Spacing.space1X.value, after: inlineDisplayLabel) - containerStackView.setCustomSpacing(VDSLayout.Spacing.space3X.value, after: selectedOptionLabel) + controlStackView.setCustomSpacing(0, after: dropdownField) + controlStackView.setCustomSpacing(VDSLayout.Spacing.space1X.value, after: inlineDisplayLabel) + controlStackView.setCustomSpacing(VDSLayout.Spacing.space3X.value, after: selectedOptionLabel) dropdownField.width(0) inlineWidthConstraint = inlineDisplayLabel.widthAnchor.constraint(greaterThanOrEqualToConstant: 0) inlineWidthConstraint?.isActive = true - - // component stackview subviews - stackView.addArrangedSubview(titleLabel) - stackView.addArrangedSubview(containerView) - stackView.addArrangedSubview(errorLabel) - stackView.addArrangedSubview(helperLabel) - - stackView.setCustomSpacing(4, after: titleLabel) - stackView.setCustomSpacing(8, after: containerView) - stackView.setCustomSpacing(8, after: errorLabel) // setting color config - titleLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() - errorLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() - helperLabel.textColorConfiguration = secondaryColorConfig.eraseToAnyColorable() - inlineDisplayLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() - selectedOptionLabel.textColorConfiguration = primaryColorConfig.eraseToAnyColorable() - icon.color = iconColorConfig.getColor(self) + inlineDisplayLabel.textColorConfiguration = primaryColorConfiguration.eraseToAnyColorable() + selectedOptionLabel.textColorConfiguration = primaryColorConfiguration.eraseToAnyColorable() // Options PickerView optionsPicker.delegate = self optionsPicker.dataSource = self optionsPicker.isHidden = true dropdownField.inputView = optionsPicker - dropdownField.inputAccessoryView = toolBarForPicker() - containerStackView.publisher(for: UITapGestureRecognizer()).sink { [weak self] _ in - self?.launchPicker() - }.store(in: &subscribers) + dropdownField.inputAccessoryView = { + let inputToolbar = UIToolbar().with { + $0.barStyle = .default + $0.isTranslucent = true + $0.items=[ + UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: self, action: nil), + UIBarButtonItem(title: "Done", style: UIBarButtonItem.Style.done, target: self, action: #selector(pickerDoneClicked)) + ] + } + inputToolbar.sizeToFit() + return inputToolbar + }() + + // tap gesture + containerStackView + .publisher(for: UITapGestureRecognizer()) + .sink { [weak self] _ in + self?.launchPicker() + } + .store(in: &subscribers) } /// Used to make changes to the View based off a change events or from local properties. open override func updateView() { + super.updateView() - containerView.backgroundColor = backgroundColorConfiguration.getColor(self) - containerView.layer.borderWidth = VDSFormControls.widthBorder - containerView.layer.cornerRadius = VDSFormControls.borderradius - containerView.layer.borderColor = readOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : borderColorConfiguration.getColor(self).cgColor - dropdownField.isUserInteractionEnabled = readOnly ? false : true - stackView.backgroundColor = transparentBackground ? .clear : surface.color - - updateTitleLabel() updateInlineLabel() - updateErrorLabel() - updateHelperLabel() - if readOnly { - icon.name = nil - } + + dropdownField.isUserInteractionEnabled = readOnly ? false : true selectedOptionLabel.surface = surface selectedOptionLabel.isEnabled = isEnabled - backgroundColor = surface.color } /// Resets to default settings. open override func reset() { super.reset() - titleLabel.reset() - inlineDisplayLabel.reset() - selectedOptionLabel.reset() - errorLabel.reset() - helperLabel.reset() - - titleLabel.textStyle = .bodySmall inlineDisplayLabel.textStyle = .boldBodyLarge selectedOptionLabel.textStyle = .bodyLarge - errorLabel.textStyle = .bodySmall - helperLabel.textStyle = .bodySmall - tooltipModel = nil - labelText = nil - errorText = nil - showError = false - isEnabled = false - readOnly = false showInlineLabel = false - helperText = nil - transparentBackground = false - required = false options = [] selectId = 0 } @@ -312,7 +178,7 @@ open class DropdownSelect: Control { // MARK: - Public Methods //-------------------------------------------------- - open func updateTitleLabel() { + open override func updateTitleLabel() { //update the local vars for the label since we no long have a model var attributes: [any LabelAttributeModel] = [] @@ -323,7 +189,7 @@ open class DropdownSelect: Control { if let oldText = updatedLabelText, !required, !oldText.hasSuffix("Optional") { let optionColorAttr = ColorLabelAttribute(location: oldText.count + 2, length: 8, - color: secondaryColorConfig.getColor(self)) + color: secondaryColorConfiguration.getColor(self)) updatedLabelText = showInlineLabel ? "Optional" : "\(oldText) Optional" attributes.append(optionColorAttr) @@ -357,70 +223,37 @@ open class DropdownSelect: Control { inlineWidthConstraint?.isActive = true if let selectId, selectId < options.count { - updateSelectedOptionLabel(text: options[selectId].text) + updateSelectedOptionLabel(option: options[selectId]) } } - open func updateSelectedOptionLabel(text: String? = nil) { - selectedOptionLabel.text = text ?? "" + open func updateSelectedOptionLabel(option: DropdownOptionModel? = nil) { + selectedOptionLabel.text = option?.text ?? "" + value = option?.value } - open func updateErrorLabel() { - if showError, let errorText { - errorLabel.text = errorText - errorLabel.surface = surface - errorLabel.isEnabled = isEnabled - errorLabel.isHidden = false - icon.name = .error - icon.size = .medium - icon.surface = surface - } else { + open override func updateErrorLabel() { + super.updateErrorLabel() + if !showError && !hasInternalError { icon.name = .downCaret - icon.surface = surface - errorLabel.isHidden = true - } - icon.color = iconColorConfig.getColor(self) - } - - open func updateHelperLabel() { - if let helperText { - helperLabel.text = helperText - helperLabel.surface = surface - helperLabel.isEnabled = isEnabled - helperLabel.isHidden = false - } else { - helperLabel.isHidden = true } + icon.surface = surface + icon.isHidden = readOnly ? true : false + icon.color = iconColorConfiguration.getColor(self) } @objc open func pickerDoneClicked() { optionsPicker.isHidden = true dropdownField.resignFirstResponder() } - - //-------------------------------------------------- - // MARK: - Private Methods - //-------------------------------------------------- - - private func toolBarForPicker() -> UIToolbar { - - let inputToolbar: UIToolbar = UIToolbar() - inputToolbar.barStyle = .default - inputToolbar.isTranslucent = true - - // add a done button to the toolbar - inputToolbar.items=[ - UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: self, action: nil), - UIBarButtonItem(title: "Done", style: UIBarButtonItem.Style.done, target: self, action: #selector(pickerDoneClicked)) - ] - inputToolbar.sizeToFit() - return inputToolbar - } } -extension DropdownSelect: UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate { +//-------------------------------------------------- +// MARK: - UIPickerView Delegate & Datasource +//-------------------------------------------------- +extension DropdownSelect: UIPickerViewDelegate, UIPickerViewDataSource { - func launchPicker() { + internal func launchPicker() { if optionsPicker.isHidden { dropdownField.becomeFirstResponder() } else { @@ -429,9 +262,6 @@ extension DropdownSelect: UIPickerViewDelegate, UIPickerViewDataSource, UITextFi optionsPicker.isHidden = !optionsPicker.isHidden } - //-------------------------------------------------- - // MARK: - UIPickerView Delegate & Datasource - //-------------------------------------------------- public func numberOfComponents(in pickerView: UIPickerView) -> Int { return 1 } @@ -448,7 +278,7 @@ extension DropdownSelect: UIPickerViewDelegate, UIPickerViewDataSource, UITextFi public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { guard options.count > row else { return } selectId = row - updateSelectedOptionLabel(text: options[row].text) + updateSelectedOptionLabel(option: options[row]) self.onDropdownItemSelect?(options[row]) } } From a2f79fcee87d8d4381ff77be9c5a32fe34b7ec9d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 9 Apr 2024 16:11:52 -0500 Subject: [PATCH 39/43] refactored to put value and the valuechanged for the control Signed-off-by: Matt Bruce --- .../TextFields/EntryFieldBase.swift | 12 ++++++++++- .../TextFields/InputField/InputField.swift | 10 +++------- .../TextFields/TextArea/TextArea.swift | 20 +++++++------------ 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/VDS/Components/TextFields/EntryFieldBase.swift b/VDS/Components/TextFields/EntryFieldBase.swift index c57a3432..d2f3a6c7 100644 --- a/VDS/Components/TextFields/EntryFieldBase.swift +++ b/VDS/Components/TextFields/EntryFieldBase.swift @@ -195,7 +195,17 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable { open var inputId: String? { didSet { setNeedsUpdate() } } - open var value: String? { didSet { setNeedsUpdate() } } + /// The text of this textField. + internal var _value: String? + open var value: String? { + get { _value } + set { + if let newValue, newValue != _value { + _value = newValue + sendActions(for: .valueChanged) + } + } + } open var defaultValue: AnyHashable? { didSet { setNeedsUpdate() } } diff --git a/VDS/Components/TextFields/InputField/InputField.swift b/VDS/Components/TextFields/InputField/InputField.swift index b739b577..448dbbf1 100644 --- a/VDS/Components/TextFields/InputField/InputField.swift +++ b/VDS/Components/TextFields/InputField/InputField.swift @@ -91,15 +91,11 @@ open class InputField: EntryFieldBase, UITextFieldDelegate { } /// The value of this textField. - private var _value: String? open override var value: String? { - get { _value } - set { - if let newValue, newValue != _value { - _value = newValue - text = newValue + didSet { + if text != value { + text = value } - setNeedsUpdate() } } diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index ee09ecb3..3c1bbf56 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -105,14 +105,12 @@ open class TextArea: EntryFieldBase { } } } - - /// The text of this textView - private var _text: String? + + /// The text of this TextArea. open var text: String? { get { textView.text } set { - if let newValue, newValue != _text { - _text = newValue + if let newValue, newValue != text { textView.text = newValue value = newValue } @@ -120,16 +118,12 @@ open class TextArea: EntryFieldBase { } } - /// The text of this textField. - private var _value: String? + /// The value of this textField. open override var value: String? { - get { _value } - set { - if let newValue, newValue != _value { - _value = newValue - text = newValue + didSet { + if text != value { + text = value } - setNeedsUpdate() } } From b07c0108883e10cb347dc4074fe32411b9e461cc Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 9 Apr 2024 16:12:24 -0500 Subject: [PATCH 40/43] refactored naming Signed-off-by: Matt Bruce --- VDS/Components/DropdownSelect/DropdownSelect.swift | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index 94f7112d..a56eb783 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -38,11 +38,17 @@ open class DropdownSelect: EntryFieldBase { /// Allows unique ID to be passed to the element. open var selectId: Int? { didSet { setNeedsUpdate() }} + /// Current SelectedItem + open var selectedItem: DropdownOptionModel? { + guard let selectId else { return nil } + return options[selectId] + } + /// Array of options to show open var options: [DropdownOptionModel] = [] { didSet { setNeedsUpdate() }} /// A callback when the selected option changes. Passes parameters (option). - open var onDropdownItemSelect: ((DropdownOptionModel) -> Void)? + open var onItemSelected: ((Int, DropdownOptionModel) -> Void)? //-------------------------------------------------- // MARK: - Private Properties @@ -52,7 +58,7 @@ open class DropdownSelect: EntryFieldBase { //-------------------------------------------------- // MARK: - Public Properties - //-------------------------------------------------- + //-------------------------------------------------- open var inlineDisplayLabel = Label().with { $0.textAlignment = .left $0.textStyle = .boldBodyLarge @@ -171,7 +177,7 @@ open class DropdownSelect: EntryFieldBase { selectedOptionLabel.textStyle = .bodyLarge showInlineLabel = false options = [] - selectId = 0 + selectId = nil } //-------------------------------------------------- @@ -279,6 +285,6 @@ extension DropdownSelect: UIPickerViewDelegate, UIPickerViewDataSource { guard options.count > row else { return } selectId = row updateSelectedOptionLabel(option: options[row]) - self.onDropdownItemSelect?(options[row]) + self.onItemSelected?(row, options[row]) } } From 994feff20ee067b281b918e15808c9b16db4020d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 9 Apr 2024 16:19:11 -0500 Subject: [PATCH 41/43] fixed bug in InputField/TextArea after refactor Signed-off-by: Matt Bruce --- VDS/Components/TextFields/InputField/InputField.swift | 8 +++++--- VDS/Components/TextFields/TextArea/TextArea.swift | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/VDS/Components/TextFields/InputField/InputField.swift b/VDS/Components/TextFields/InputField/InputField.swift index 448dbbf1..b45500a0 100644 --- a/VDS/Components/TextFields/InputField/InputField.swift +++ b/VDS/Components/TextFields/InputField/InputField.swift @@ -78,11 +78,13 @@ open class InputField: EntryFieldBase, UITextFieldDelegate { /// Representing the type of input. open var fieldType: FieldType = .text { didSet { setNeedsUpdate() } } - /// The text of this textField. + /// The text of this TextField. + private var _text: String? open var text: String? { - get { textField.text } + get { _text } set { - if let newValue, newValue != text { + if let newValue, newValue != _text { + _text = newValue textField.text = newValue value = newValue } diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index 3c1bbf56..73a1e67c 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -107,10 +107,12 @@ open class TextArea: EntryFieldBase { } /// The text of this TextArea. + private var _text: String? open var text: String? { - get { textView.text } + get { _text } set { - if let newValue, newValue != text { + if let newValue, newValue != _text { + _text = newValue textView.text = newValue value = newValue } From 4e1cde192211c7461f7136501c01a723e68cb383 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 10 Apr 2024 14:58:32 -0500 Subject: [PATCH 42/43] fixed bug in attributed string creation Signed-off-by: Matt Bruce --- VDS/Extensions/NSAttributedString.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/VDS/Extensions/NSAttributedString.swift b/VDS/Extensions/NSAttributedString.swift index 4f758762..6d168182 100644 --- a/VDS/Extensions/NSAttributedString.swift +++ b/VDS/Extensions/NSAttributedString.swift @@ -68,9 +68,7 @@ extension NSMutableAttributedString { .paragraphStyle: paragraph] //set letterSpacing - if textStyle.letterSpacing > 0.0 { - attributes[.kern] = textStyle.letterSpacing - } + attributes[.kern] = textStyle.letterSpacing return NSMutableAttributedString(string: text, attributes: attributes) From aaf2ddc08bc155ccb72833dd31693ce890bee59a Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 10 Apr 2024 15:01:23 -0500 Subject: [PATCH 43/43] CXTDT-540077 - BadgeIndicator Font Signed-off-by: Matt Bruce --- VDS/SupportingFiles/ReleaseNotes.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/VDS/SupportingFiles/ReleaseNotes.txt b/VDS/SupportingFiles/ReleaseNotes.txt index c62a7946..62650dfc 100644 --- a/VDS/SupportingFiles/ReleaseNotes.txt +++ b/VDS/SupportingFiles/ReleaseNotes.txt @@ -1,3 +1,7 @@ +1.0.59 +---------------- +- CXTDT-540077 - BadgeIndicator Font + 1.0.58 ---------------- - CXTDT-542341 - RadioButtonItem - disabled state color/borderWidth