// // InputStepper.swift // VDS // // Created by Kanamarlapudi, Vasavi on 24/06/24. // import Foundation import UIKit import VDSCoreTokens import Combine /// A stepper is a two-segment control that people use to increase or decrease an incremental value. @objc(VDSInputStepper) open class InputStepper: EntryFieldBase { //-------------------------------------------------- // 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) } //-------------------------------------------------- // MARK: - Enums //-------------------------------------------------- /// Enum used to describe the control width of Input Stepper. public enum controlWidth: String, CaseIterable { case auto, value } /// Enum used to describe the size of Input Stepper. public enum Size: String, CaseIterable { case large, small } //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- /// Accepts a string or number value to control the width of input stepper to a fixed pixel or percentage value. open var controlWidth: CGFloat? { didSet { setNeedsUpdate() } } /// Maximum value of the input stepper, defaults to '99'. open var maxValue: Int? { get { return _maxValue } set { if let newValue, newValue < 100 && newValue > 0 { _maxValue = newValue } else { _maxValue = 99 } setNeedsUpdate() } } /// Minimum value of the input stepper, defaults to '0'. open var minValue: Int? { get { return _minValue } set { if let newValue, newValue >= 0 && newValue < 99 { _minValue = newValue } else { _minValue = 0 } setNeedsUpdate() } } /// The size of the input stepper. Defaults to 'large'. open var size: Size { get { return _size } set { _size = newValue setNeedsUpdate() } } /// Accepts any text or character to appear next to input stepper value. open var trailingText: String? { didSet { setNeedsUpdate() } } //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- internal var _maxValue: Int = 99 internal var _minValue: Int = 0 internal var _size: Size = .large private var stepperWidthConstraint: NSLayoutConstraint? private var stepperHeightConstraint: NSLayoutConstraint? //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- open override func initialSetup() { super.initialSetup() } open override func setup() { super.setup() isAccessibilityElement = false accessibilityLabel = "Input Stepper" containerView.isEnabled = false } open override func getFieldContainer() -> UIView { // stackview for controls in EntryFieldBase.controlContainerView let controlStackView = UIStackView().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.axis = .horizontal $0.spacing = VDSLayout.space3X $0.backgroundColor = .clear } let view = View().with { $0.clipsToBounds = true $0.backgroundColor = .clear } let controlView = View().with { $0.clipsToBounds = true $0.backgroundColor = .clear } let label = Label().with { $0.text = "Label" } let minusButton = ButtonIcon().with { $0.kind = .ghost $0.iconName = .leftCaret $0.iconOffset = .init(x: -2, y: 0) $0.customContainerSize = 40 $0.icon.customSize = 16 } let plusButton = ButtonIcon().with { $0.kind = .ghost $0.iconName = .rightCaret $0.iconOffset = .init(x: 2, y: 0) $0.customContainerSize = 40 $0.icon.customSize = 16 } controlStackView.addArrangedSubview(minusButton) controlStackView.addArrangedSubview(label) controlStackView.addArrangedSubview(plusButton) controlView.addSubview(controlStackView) controlStackView.pinToSuperView() view.addSubview(controlView) controlView.pinToSuperView() view.pinToSuperView() return view } open override func updateView() { super.updateView() updateContainerView(flag: false) } }