// // CheckboxGroup.swift // VDS // // Created by Matt Bruce on 8/23/22. // import Foundation import UIKit @objc(VDSCheckboxGroup) open class CheckboxGroup: SelectorGroupHandlerBase { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- public var selectedHandlers: [CheckboxItem]? { let selected = selectorViews.filter{ $0.isSelected == true } guard selected.count > 0 else { return nil } return selected } public override var selectorViews: [CheckboxItem] { willSet { mainStackView.arrangedSubviews.forEach { $0.removeFromSuperview() } } didSet { for selector in selectorViews { selector.onClick = { [weak self] handler in self?.didSelect(handler) } mainStackView.addArrangedSubview(selector) } } } public var selectorModels: [CheckboxModel]? { didSet { if let selectorModels { selectorViews = selectorModels.enumerated().map { index, model in return CheckboxItem().with { $0.disabled = model.disabled $0.surface = model.surface $0.inputId = model.inputId $0.value = model.value $0.accessibilityLabel = model.accessibileText $0.accessibilityValue = "item \(index+1) of \(selectorModels.count)" $0.labelText = model.labelText $0.labelTextAttributes = model.labelTextAttributes $0.childText = model.childText $0.childTextAttributes = model.childTextAttributes $0.isSelected = model.selected $0.errorText = model.errorText $0.showError = model.showError } } } setNeedsUpdate() } } private var _showError: Bool = false public var showError: Bool { get { _showError } set { var newShowError = newValue let anySelected = selectorViews.filter { $0.isSelected == true }.count > 0 if anySelected && newShowError { newShowError = false } selectorViews.forEach { handler in handler.showError = newShowError } _showError = newShowError } } //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- private var mainStackView: UIStackView = { return UIStackView().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.alignment = .fill $0.distribution = .fill $0.axis = .vertical $0.spacing = VDSLayout.Spacing.space6X.value } }() //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- open override func setup() { super.setup() addSubview(mainStackView) mainStackView.pinToSuperView() } public override func didSelect(_ selectedControl: CheckboxItem) { selectedControl.toggle() if selectedControl.isSelected, showError{ showError.toggle() } valueChanged() } } extension CheckboxGroup { public struct CheckboxModel : Surfaceable, Disabling, Initable, FormFieldable, Errorable { public var disabled: Bool /// Current Surface and this is used to pass down to child objects that implement Surfacable public var surface: Surface public var inputId: String? public var value: AnyHashable? public var accessibileText: String? public var labelText: String? public var labelTextAttributes: [any LabelAttributeModel]? public var childText: String? public var childTextAttributes: [any LabelAttributeModel]? public var selected: Bool public var showError: Bool public var errorText: String? public init(disabled: Bool, surface: Surface = .light, inputId: String? = nil, value: AnyHashable? = nil, accessibileText: String? = nil, labelText: String? = nil, labelTextAttributes: [any LabelAttributeModel]? = nil, childText: String? = nil, childTextAttributes: [any LabelAttributeModel]? = nil, selected: Bool = false, showError: Bool = false, errorText: String? = nil) { self.disabled = disabled self.surface = surface self.inputId = inputId self.value = value self.accessibileText = accessibileText self.labelText = labelText self.labelTextAttributes = labelTextAttributes self.childText = childText self.childTextAttributes = childTextAttributes self.selected = selected self.showError = showError self.errorText = errorText } public init() { self.init(disabled: false) } } }