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