// // PickerBase.swift // VDSSample // // Created by Matt Bruce on 8/1/22. // import Foundation import UIKit import VDS import Combine public struct PickerType : RawRepresentable, Equatable, Hashable { public var rawValue: String public init(_ rawValue: String) { self.rawValue = rawValue } public init(rawValue: String) { self.rawValue = rawValue } public static var surface = PickerType(rawValue: "surface") public static var textPosition = PickerType(rawValue: "textPosition") public static var textSize = PickerType(rawValue: "textSize") public static var fontCategory = PickerType(rawValue: "fontCategory") } public protocol PickerViewable: UIPickerViewDataSource, UIPickerViewDelegate, Hashable { associatedtype EnumType: RawRepresentable var items: [EnumType] { get set } var onPickerDidSelect: ((EnumType) -> Void)? { get set } var scrollToBottom: (()->Void)? { get set } } public class PickerSelectorView: UIStackView, PickerViewable { private weak var picker: UIPickerView? fileprivate var selectedIndex = 0 private var subscribers = Set() private var label = Label().with { $0.typograpicalStyle = .BodyLarge } private var button = Button().with { instance in instance.size = .small instance.use = .secondary instance.text = "Select" } public var text: String = "" { didSet { label.text = text } } public var items: [EnumType] { didSet { selectedIndex = 0 } } public var onPickerDidSelect: ((EnumType) -> Void)? public var scrollToBottom: (()->Void)? public init(title: String, picker: UIPickerView? = nil, items: [EnumType]) { self.picker = picker self.items = items super.init(frame: .zero) self.axis = .horizontal self.distribution = .fillEqually self.alignment = .fill label.text = title addArrangedSubview(label) addArrangedSubview(button) button .publisher(for: .touchUpInside) .sink { [weak self] _ in self?.picker?.delegate = self self?.picker?.dataSource = self self?.picker?.reloadAllComponents() self?.picker?.selectRow(self?.selectedIndex ?? 0, inComponent: 0, animated: false) self?.picker?.isHidden = false self?.scrollToBottom?() }.store(in: &subscribers) } public required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } public func numberOfComponents(in pickerView: UIPickerView) -> Int { 1 } public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { items.count + 1 } public func pickerView( _ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { guard row - 1 >= 0 else { return } selectedIndex = row onPickerDidSelect?(items[row-1]) text = "\(items[row-1].rawValue)" pickerView.isHidden = true } public func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView { var label = UILabel() if let v = view as? UILabel { label = v } label.font = TypographicalStyle.TitleMedium.font label.text = title(for: row) label.textAlignment = .center return label } private func title(for row: Int) -> String { guard row > 0, let item = items[row-1].rawValue as? String else { return "" } return item } } public class SurfacePickerSelectorView: PickerSelectorView{ init(picker: UIPickerView? = nil){ super.init(title: "light", picker: picker, items: [.light, .dark]) } required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } public class TextPositionPickerSelectorView: PickerSelectorView{ init(picker: UIPickerView? = nil){ super.init(title: "left", picker: picker, items: [.left, .right]) } required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } public class TextSizePickerSelectorView: PickerSelectorView{ init(title: String, picker: UIPickerView? = nil){ super.init(title: title, picker: picker, items: [.small, .large]) } required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } public class FontCategoryPickerSelectorView: PickerSelectorView{ init(title: String, picker: UIPickerView? = nil){ super.init(title: title, picker: picker, items: TypographicalStyle.FontCategory.allCases) } required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }