updated control

and subcontrols

Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
Matt Bruce 2023-03-29 13:47:56 -05:00
parent 01725e634f
commit aa233515a5
13 changed files with 141 additions and 199 deletions

View File

@ -17,7 +17,7 @@ open class Control: UIControl, Handlerable, ViewProtocol, Resettable, UserInfoab
//--------------------------------------------------
public var subject = PassthroughSubject<Void, Never>()
public var subscribers = Set<AnyCancellable>()
open var onClickSubscriber: AnyCancellable? {
internal var onClickSubscriber: AnyCancellable? {
willSet {
if let onClickSubscriber {
onClickSubscriber.cancel()
@ -27,7 +27,7 @@ open class Control: UIControl, Handlerable, ViewProtocol, Resettable, UserInfoab
enabledHighlight = onClickSubscriber != nil
}
}
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
@ -109,7 +109,7 @@ open class Control: UIControl, Handlerable, ViewProtocol, Resettable, UserInfoab
sendActions(for: .touchUpInside)
return true
}
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------

View File

@ -12,22 +12,9 @@ import VDSFormControlsTokens
import Combine
/// Checkboxes are a multi-select component through which a customer indicates a choice. If a binary choice, the component is a checkbox. If the choice has multiple options, the component is a ``CheckboxGroup``.
@objc(VDSCheckbox)
public class Checkbox: CheckboxBase{}
@objc(VDSSoloCheckbox)
public class SoloCheckbox: CheckboxBase{
public override func initialSetup() {
super.initialSetup()
onClickSubscriber = publisher(for: .touchUpInside)
.sink { control in
control.toggle()
}
}
}
@objc(VDSCheckboxBase)
open class CheckboxBase: Control, Errorable {
open class Checkbox: Control, Errorable, Clickable {
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@ -76,6 +63,8 @@ open class CheckboxBase: Control, Errorable {
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
open var onClick: ((Checkbox) -> ())? { didSet { setupOnClick() }}
open var label = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical)
$0.textPosition = .left
@ -164,6 +153,13 @@ open class CheckboxBase: Control, Errorable {
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func initialSetup() {
super.initialSetup()
onClick = { control in
control.toggle()
}
}
open override func setup() {
super.setup()

View File

@ -9,31 +9,24 @@ import Foundation
import UIKit
@objc(VDSCheckboxGroup)
public class CheckboxGroup: CheckboxGroupBase<Checkbox> {
public override func didSelect(_ selectedControl: Checkbox) {
selectedControl.toggle()
if selectedControl.isSelected, showError{
showError.toggle()
}
valueChanged()
}
}
public class CheckboxGroupBase<HandlerType: CheckboxBase>: SelectorGroupHandlerBase<HandlerType> {
public class CheckboxGroup: SelectorGroupHandlerBase<Checkbox> {
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
public override var selectorViews: [HandlerType] {
public var selectedHandlers: [Checkbox]? {
let selected = selectorViews.filter{ $0.isSelected == true }
guard selected.count > 0 else { return nil }
return selected
}
public override var selectorViews: [Checkbox] {
didSet {
for selector in selectorViews {
if !mainStackView.arrangedSubviews.contains(selector) {
selector
.publisher(for: .touchUpInside)
.sink { [weak self] handler in
self?.didSelect(handler)
}.store(in: &subscribers)
selector.onClick = { [weak self] handler in
self?.didSelect(handler)
}
mainStackView.addArrangedSubview(selector)
}
}
@ -79,11 +72,13 @@ public class CheckboxGroupBase<HandlerType: CheckboxBase>: SelectorGroupHandlerB
mainStackView.pinToSuperView()
}
public var selectedHandlers: [HandlerType]? {
let selected = selectorViews.filter{ $0.isSelected == true }
guard selected.count > 0 else { return nil }
return selected
public override func didSelect(_ selectedControl: Checkbox) {
selectedControl.toggle()
if selectedControl.isSelected, showError{
showError.toggle()
}
valueChanged()
}
}

View File

@ -106,6 +106,8 @@ public class Notification: View {
$0.use = .secondary
}
open var onCloseClick: ((Notification)->())?
//--------------------------------------------------
// MARK: - Modal Properties
//--------------------------------------------------
@ -163,7 +165,8 @@ public class Notification: View {
mainStackView.addArrangedSubview(closeButton)
closeButton.publisher(for: UITapGestureRecognizer()).sink { [weak self] _ in
self?.didClickOnCloseButton()
guard let self else { return }
self.onCloseClick?(self)
}.store(in: &subscribers)
//labels
@ -227,22 +230,14 @@ public class Notification: View {
if let primaryButtonModel {
primaryButton.text = primaryButtonModel.text
primaryButton.surface = surface
primaryButton.onClickSubscriber = primaryButton
.publisher(for: .touchUpInside)
.sink(receiveValue: { button in
primaryButtonModel.onClick(button)
})
primaryButton.onClick = primaryButtonModel.onClick
buttons.append(primaryButton)
}
if let secondaryButtonModel {
secondaryButton.text = secondaryButtonModel.text
secondaryButton.surface = surface
secondaryButton.onClickSubscriber = secondaryButton
.publisher(for: .touchUpInside)
.sink(receiveValue: { button in
secondaryButtonModel.onClick(button)
})
secondaryButton.onClick = secondaryButtonModel.onClick
buttons.append(secondaryButton)
}
@ -260,9 +255,5 @@ public class Notification: View {
.pinTrailing()
}
}
func didClickOnCloseButton() {
print("Notification close button clicked!!!")
}
}

View File

@ -12,22 +12,8 @@ import VDSFormControlsTokens
import Combine
@objc(VDSRadioBox)
public class RadioBox: RadioBoxBase{}
@objc(VDSSoloRadioBox)
public class SoloRadioBox: RadioBoxBase{
open class RadioBox: Control, Clickable {
public override func initialSetup() {
super.initialSetup()
onClickSubscriber = publisher(for: .touchUpInside)
.sink { control in
control.toggle()
}
}
}
@objc(VDSRadioBoxBase)
open class RadioBoxBase: Control{
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@ -70,6 +56,8 @@ open class RadioBoxBase: Control{
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
open var onClick: ((RadioBox) -> ())? { didSet { setupOnClick() }}
open var textLabel = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical)
$0.textPosition = .left
@ -138,7 +126,13 @@ open class RadioBoxBase: Control{
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func initialSetup() {
super.initialSetup()
onClick = { control in
control.toggle()
}
}
open override func setup() {
super.setup()

View File

@ -9,30 +9,18 @@ import Foundation
import UIKit
@objc(VDSRadioBoxGroup)
public class RadioBoxGroup: RadioBoxGroupBase<RadioBox> {
public override func didSelect(_ selectedControl: RadioBox) {
let oldSelectedControl = selectorViews.filter { $0.isSelected == true }.first
oldSelectedControl?.toggle()
selectedControl.toggle()
valueChanged()
}
}
public class RadioBoxGroupBase<HandlerType: RadioBoxBase>: SelectorGroupSelectedHandlerBase<HandlerType> {
public class RadioBoxGroup: SelectorGroupSelectedHandlerBase<RadioBox> {
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
public override var selectorViews: [HandlerType] {
public override var selectorViews: [RadioBox] {
didSet {
for selector in selectorViews {
if !mainStackView.arrangedSubviews.contains(selector) {
selector
.publisher(for: .touchUpInside)
.sink { [weak self] handler in
self?.didSelect(handler)
}.store(in: &subscribers)
selector.onClick = { [weak self] handler in
self?.didSelect(handler)
}
mainStackView.addArrangedSubview(selector)
}
}
@ -84,4 +72,11 @@ public class RadioBoxGroupBase<HandlerType: RadioBoxBase>: SelectorGroupSelected
}
}.store(in: &subscribers)
}
open override func didSelect(_ selectedControl: RadioBox) {
let oldSelectedControl = selectorViews.filter { $0.isSelected == true }.first
oldSelectedControl?.toggle()
selectedControl.toggle()
valueChanged()
}
}

View File

@ -11,30 +11,8 @@ import VDSColorTokens
import VDSFormControlsTokens
@objc(VDSRadioButton)
public class RadioButton: RadioButtonBase {
//for groups allows "toggle"
open override func toggle() {
//removed error
if showError && isSelected == false {
showError.toggle()
}
isSelected.toggle()
}
}
@objc(VDSSoloRadioButton)
public class SoloRadioButton: RadioButtonBase {
public override func initialSetup() {
super.initialSetup()
onClickSubscriber = publisher(for: .touchUpInside)
.sink { control in
control.toggle()
}
}
}
@objc(VDSRadioButtonBase)
open class RadioButtonBase: Control, Errorable {
open class RadioButton: Control, Errorable, Clickable {
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@ -83,6 +61,8 @@ open class RadioButtonBase: Control, Errorable {
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
open var onClick: ((RadioButton) -> ())? { didSet { setupOnClick() } }
open var label = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical)
$0.textPosition = .left
@ -158,7 +138,13 @@ open class RadioButtonBase: Control, Errorable {
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func initialSetup() {
super.initialSetup()
onClick = { control in
control.toggle()
}
}
open override func setup() {
super.setup()

View File

@ -9,32 +9,18 @@ import Foundation
import UIKit
@objc(VDSRadioButtonGroup)
public class RadioButtonGroup: RadioButtonGroupBase<RadioButton> {
public override func didSelect(_ selectedControl: RadioButton) {
selectedHandler?.toggle()
selectedControl.toggle()
if showError {
showError = false
}
valueChanged()
}
}
public class RadioButtonGroupBase<HandlerType: RadioButtonBase>: SelectorGroupSelectedHandlerBase<HandlerType> {
public class RadioButtonGroup: SelectorGroupSelectedHandlerBase<RadioButton> {
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
public override var selectorViews: [HandlerType] {
public override var selectorViews: [RadioButton] {
didSet {
for selector in selectorViews {
if !mainStackView.arrangedSubviews.contains(selector) {
selector
.publisher(for: .touchUpInside)
.sink { [weak self] handler in
self?.didSelect(handler)
}.store(in: &subscribers)
selector.onClick = { [weak self] handler in
self?.didSelect(handler)
}
mainStackView.addArrangedSubview(selector)
}
}
@ -81,4 +67,22 @@ public class RadioButtonGroupBase<HandlerType: RadioButtonBase>: SelectorGroupSe
mainStackView.pinToSuperView()
}
public override func didSelect(_ selectedControl: RadioButton) {
if let selectedHandler {
updateToggle(selectedHandler)
}
updateToggle(selectedControl)
if showError {
showError = false
}
valueChanged()
}
private func updateToggle(_ radioButton: RadioButton) {
if radioButton.showError && radioButton.isSelected == false {
radioButton.showError.toggle()
}
radioButton.isSelected.toggle()
}
}

View File

@ -12,26 +12,7 @@ import VDSFormControlsTokens
import Combine
@objc(VDSRadioSwatch)
public class RadioSwatch: RadioSwatchBase{
//for groups allows "toggle"
open override func toggle() {
isSelected.toggle()
}
}
@objc(VDSSoloRadioSwatch)
public class SolorRadioSwatch: RadioSwatchBase{
public override func initialSetup() {
super.initialSetup()
onClickSubscriber = publisher(for: .touchUpInside)
.sink { control in
control.toggle()
}
}
}
@objc(VDSRadioSwatchBase)
open class RadioSwatchBase: Control {
open class RadioSwatch: Control, Clickable {
//--------------------------------------------------
// MARK: - Initializers
@ -51,6 +32,8 @@ open class RadioSwatchBase: Control {
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
open var onClick: ((RadioSwatch) -> ())? { didSet { setupOnClick() } }
public var selectorView = UIView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
}
@ -78,7 +61,13 @@ open class RadioSwatchBase: Control {
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func initialSetup() {
super.initialSetup()
onClick = { control in
control.toggle()
}
}
open override func setup() {
super.setup()

View File

@ -10,24 +10,12 @@ import UIKit
import Combine
@objc(VDSRadioSwatchGroup)
public class RadioSwatchGroup: RadioSwatchGroupBase<RadioSwatch> {
public override func didSelect(selector: RadioSwatch) {
selectedHandler?.toggle()
selector.toggle()
label.text = selector.text
didChange()
valueChanged()
}
}
public class RadioSwatchGroupBase<HandlerType: RadioSwatchBase>: SelectorGroupSelectedHandlerBase<HandlerType>, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate {
public class RadioSwatchGroup: SelectorGroupSelectedHandlerBase<RadioSwatch>, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate {
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
public override var selectorViews: [HandlerType] {
public override var selectorViews: [RadioSwatch] {
didSet {
collectionView.reloadData()
}
@ -160,18 +148,20 @@ public class RadioSwatchGroupBase<HandlerType: RadioSwatchBase>: SelectorGroupSe
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath)
let handler = selectorViews[indexPath.row]
handler.subscribers.forEach{ $0.cancel() }
handler.subscribers.removeAll()
handler.publisher(for: .touchUpInside).sink { [weak self] handler in
handler.onClick = { [weak self] handler in
self?.didSelect(selector: handler)
}.store(in: &handler.subscribers)
}
cell.subviews.forEach { $0.removeFromSuperview() }
cell.addSubview(handler)
handler.pinToSuperView()
return cell
}
open func didSelect(selector: HandlerType) {
fatalError("Must override didSelect")
public func didSelect(selector: RadioSwatch) {
selectedHandler?.toggle()
selector.toggle()
label.text = selector.text
didChange()
valueChanged()
}
}

View File

@ -11,7 +11,12 @@ import VDSFormControlsTokens
import UIKit
@objc(VDSTileContainer)
open class TileContainer: Control {
open class TileContainer: TileContainerBase, Clickable {
public var onClick: ((TileContainer) -> ())? { didSet { setupOnClick() } }
}
@objc(VDSTileContainerBase)
open class TileContainerBase: Control {
//--------------------------------------------------
// MARK: - Initializers
@ -310,13 +315,13 @@ open class TileContainer: Control {
}
}
extension TileContainer {
extension TileContainerBase {
class BackgroundColorConfiguration: ObjectColorable {
typealias ObjectType = TileContainer
typealias ObjectType = TileContainerBase
required init() { }
func getColor(_ object: TileContainer) -> UIColor {
func getColor(_ object: TileContainerBase) -> UIColor {
switch object.color {
case .white:

View File

@ -12,7 +12,8 @@ import UIKit
import Combine
@objc(VDSTilelet)
open class Tilelet: TileContainer {
open class Tilelet: TileContainerBase, Clickable {
//--------------------------------------------------
// MARK: - Enums
//--------------------------------------------------
@ -62,7 +63,9 @@ open class Tilelet: TileContainer {
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
open override var onClickSubscriber: AnyCancellable? {
open var onClick: ((Tilelet) -> ())? { didSet { setupOnClick() } }
internal override var onClickSubscriber: AnyCancellable? {
didSet {
isAccessibilityElement = onClickSubscriber != nil
}

View File

@ -18,18 +18,7 @@ import Combine
Knob: The circular indicator that slides on the container.
*/
@objc(VDSToggle)
public class Toggle: ToggleBase{
public override func initialSetup() {
super.initialSetup()
publisher(for: .touchUpInside)
.sink { control in
control.toggle()
}.store(in: &subscribers)
}
}
@objc(VDSToggleBase)
open class ToggleBase: Control {
open class Toggle: Control, Clickable {
//--------------------------------------------------
// MARK: - Enums
//--------------------------------------------------
@ -64,6 +53,7 @@ open class ToggleBase: Control {
// MARK: - Private Properties
//--------------------------------------------------
private var stackView = UIStackView().with {
$0.isUserInteractionEnabled = false
$0.translatesAutoresizingMaskIntoConstraints = false
$0.axis = .horizontal
$0.distribution = .fill
@ -81,6 +71,8 @@ open class ToggleBase: Control {
//--------------------------------------------------
// MARK: - Configuration Properties
//--------------------------------------------------
open var onClick: ((Toggle) -> ())? { didSet { setupOnClick() } }
// Sizes are from InVision design specs.
public let toggleSize = CGSize(width: 52, height: 24)
public let toggleContainerSize = CGSize(width: 52, height: 44)
@ -223,14 +215,16 @@ open class ToggleBase: Control {
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func initialSetup() {
super.initialSetup()
onClick = { control in
control.toggle()
}
}
open override func setup() {
super.setup()
//add tapGesture to self
publisher(for: UITapGestureRecognizer()).sink { [weak self] _ in
self?.sendActions(for: .touchUpInside)
}.store(in: &subscribers)
isAccessibilityElement = true
accessibilityTraits = .button
addSubview(stackView)
@ -288,7 +282,7 @@ open class ToggleBase: Control {
toggleView.backgroundColor = toggleColorConfiguration.getColor(self)
knobView.backgroundColor = knobColorConfiguration.getColor(self)
}
/// This will toggle the state of the Toggle and execute the actionBlock if provided.
open func toggle() {
isOn.toggle()