Merge branch 'feature/Clickable' into feature/Notification

This commit is contained in:
Matt Bruce 2023-04-03 10:15:28 -05:00
commit 5227c5c527
10 changed files with 102 additions and 15 deletions

View File

@ -92,6 +92,7 @@
EAC9258F2911C9DE00091998 /* EntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC9258B2911C9DE00091998 /* EntryField.swift */; }; EAC9258F2911C9DE00091998 /* EntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC9258B2911C9DE00091998 /* EntryField.swift */; };
EAD8D2C128BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD8D2C028BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift */; }; EAD8D2C128BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD8D2C028BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift */; };
EAF1FE9929D4850E00101452 /* Clickable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF1FE9829D4850E00101452 /* Clickable.swift */; }; EAF1FE9929D4850E00101452 /* Clickable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF1FE9829D4850E00101452 /* Clickable.swift */; };
EAF1FE9B29DB1A6000101452 /* Changeable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF1FE9A29DB1A6000101452 /* Changeable.swift */; };
EAF7F0952899861000B287F5 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0932899861000B287F5 /* Checkbox.swift */; }; EAF7F0952899861000B287F5 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0932899861000B287F5 /* Checkbox.swift */; };
EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0992899B17200B287F5 /* CATransaction.swift */; }; EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0992899B17200B287F5 /* CATransaction.swift */; };
EAF7F09E289AAEC000B287F5 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F09D289AAEC000B287F5 /* Constants.swift */; }; EAF7F09E289AAEC000B287F5 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F09D289AAEC000B287F5 /* Constants.swift */; };
@ -208,6 +209,7 @@
EAC9258B2911C9DE00091998 /* EntryField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntryField.swift; sourceTree = "<group>"; }; EAC9258B2911C9DE00091998 /* EntryField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntryField.swift; sourceTree = "<group>"; };
EAD8D2C028BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIGestureRecognizer+Publisher.swift"; sourceTree = "<group>"; }; EAD8D2C028BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIGestureRecognizer+Publisher.swift"; sourceTree = "<group>"; };
EAF1FE9829D4850E00101452 /* Clickable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Clickable.swift; sourceTree = "<group>"; }; EAF1FE9829D4850E00101452 /* Clickable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Clickable.swift; sourceTree = "<group>"; };
EAF1FE9A29DB1A6000101452 /* Changeable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Changeable.swift; sourceTree = "<group>"; };
EAF7F0932899861000B287F5 /* Checkbox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = "<group>"; }; EAF7F0932899861000B287F5 /* Checkbox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = "<group>"; };
EAF7F0992899B17200B287F5 /* CATransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CATransaction.swift; sourceTree = "<group>"; }; EAF7F0992899B17200B287F5 /* CATransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CATransaction.swift; sourceTree = "<group>"; };
EAF7F09D289AAEC000B287F5 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; }; EAF7F09D289AAEC000B287F5 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
@ -412,6 +414,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
EA4DB2FC28D3D0CA00103EE3 /* AnyEquatable.swift */, EA4DB2FC28D3D0CA00103EE3 /* AnyEquatable.swift */,
EAF1FE9A29DB1A6000101452 /* Changeable.swift */,
EAF1FE9829D4850E00101452 /* Clickable.swift */, EAF1FE9829D4850E00101452 /* Clickable.swift */,
EAA5EEDF28F49DB3003B3210 /* Colorable.swift */, EAA5EEDF28F49DB3003B3210 /* Colorable.swift */,
EA3361A9288B25E40071C351 /* Disabling.swift */, EA3361A9288B25E40071C351 /* Disabling.swift */,
@ -818,6 +821,7 @@
EA3361BD288B2C760071C351 /* TypeAlias.swift in Sources */, EA3361BD288B2C760071C351 /* TypeAlias.swift in Sources */,
EAB1D2CF28ABEF2B00DAE764 /* Typography.swift in Sources */, EAB1D2CF28ABEF2B00DAE764 /* Typography.swift in Sources */,
EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */, EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */,
EAF1FE9B29DB1A6000101452 /* Changeable.swift in Sources */,
EAF7F0A2289AFB3900B287F5 /* Errorable.swift in Sources */, EAF7F0A2289AFB3900B287F5 /* Errorable.swift in Sources */,
EA985C7D297DAED300F2FF2E /* Primitive.swift in Sources */, EA985C7D297DAED300F2FF2E /* Primitive.swift in Sources */,
EAF1FE9929D4850E00101452 /* Clickable.swift in Sources */, EAF1FE9929D4850E00101452 /* Clickable.swift in Sources */,

View File

@ -7,14 +7,23 @@
import Foundation import Foundation
import UIKit import UIKit
import Combine
public class SelectorGroupHandlerBase<HandlerType: Control>: Control { public class SelectorGroupHandlerBase<HandlerType: Control>: Control, Changeable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Public Properties // MARK: - Public Properties
//-------------------------------------------------- //--------------------------------------------------
public var selectorViews: [HandlerType] = [] public var selectorViews: [HandlerType] = []
public var onChangeSubscriber: AnyCancellable? {
willSet {
if let onChangeSubscriber {
onChangeSubscriber.cancel()
}
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Overrides // MARK: - Overrides
//-------------------------------------------------- //--------------------------------------------------

View File

@ -7,13 +7,13 @@
import Foundation import Foundation
import UIKit import UIKit
import Combine
import VDSColorTokens import VDSColorTokens
import VDSFormControlsTokens 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``. /// 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(VDSCheckboxBase) @objc(VDSCheckboxBase)
open class Checkbox: Control, Errorable { open class Checkbox: Control, Errorable, Changeable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
@ -63,6 +63,14 @@ open class Checkbox: Control, Errorable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Public Properties // MARK: - Public Properties
//-------------------------------------------------- //--------------------------------------------------
public var onChangeSubscriber: AnyCancellable? {
willSet {
if let onChangeSubscriber {
onChangeSubscriber.cancel()
}
}
}
open var label = Label().with { open var label = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical) $0.setContentCompressionResistancePriority(.required, for: .vertical)
$0.textPosition = .left $0.textPosition = .left

View File

@ -7,12 +7,12 @@
import Foundation import Foundation
import UIKit import UIKit
import Combine
import VDSColorTokens import VDSColorTokens
import VDSFormControlsTokens import VDSFormControlsTokens
import Combine
@objc(VDSRadioBox) @objc(VDSRadioBox)
open class RadioBox: Control { open class RadioBox: Control, Changeable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
@ -56,6 +56,14 @@ open class RadioBox: Control {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Public Properties // MARK: - Public Properties
//-------------------------------------------------- //--------------------------------------------------
public var onChangeSubscriber: AnyCancellable? {
willSet {
if let onChangeSubscriber {
onChangeSubscriber.cancel()
}
}
}
open var textLabel = Label().with { open var textLabel = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical) $0.setContentCompressionResistancePriority(.required, for: .vertical)
$0.textPosition = .left $0.textPosition = .left

View File

@ -7,11 +7,12 @@
import Foundation import Foundation
import UIKit import UIKit
import Combine
import VDSColorTokens import VDSColorTokens
import VDSFormControlsTokens import VDSFormControlsTokens
@objc(VDSRadioButton) @objc(VDSRadioButton)
open class RadioButton: Control, Errorable { open class RadioButton: Control, Errorable, Changeable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
@ -61,6 +62,14 @@ open class RadioButton: Control, Errorable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Public Properties // MARK: - Public Properties
//-------------------------------------------------- //--------------------------------------------------
public var onChangeSubscriber: AnyCancellable? {
willSet {
if let onChangeSubscriber {
onChangeSubscriber.cancel()
}
}
}
open var label = Label().with { open var label = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical) $0.setContentCompressionResistancePriority(.required, for: .vertical)
$0.textPosition = .left $0.textPosition = .left

View File

@ -12,7 +12,7 @@ import VDSFormControlsTokens
import Combine import Combine
@objc(VDSEntryField) @objc(VDSEntryField)
open class EntryField: Control { open class EntryField: Control, Changeable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Enums // MARK: - Enums
//-------------------------------------------------- //--------------------------------------------------
@ -98,6 +98,14 @@ open class EntryField: Control {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Public Properties // MARK: - Public Properties
//-------------------------------------------------- //--------------------------------------------------
public var onChangeSubscriber: AnyCancellable? {
willSet {
if let onChangeSubscriber {
onChangeSubscriber.cancel()
}
}
}
open var titleLabel = Label().with { open var titleLabel = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical) $0.setContentCompressionResistancePriority(.required, for: .vertical)
$0.attributes = [] $0.attributes = []

View File

@ -18,7 +18,7 @@ import Combine
Knob: The circular indicator that slides on the container. Knob: The circular indicator that slides on the container.
*/ */
@objc(VDSToggle) @objc(VDSToggle)
open class Toggle: Control { open class Toggle: Control, Changeable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Enums // MARK: - Enums
//-------------------------------------------------- //--------------------------------------------------
@ -107,6 +107,14 @@ open class Toggle: Control {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Public Properties // MARK: - Public Properties
//-------------------------------------------------- //--------------------------------------------------
public var onChangeSubscriber: AnyCancellable? {
willSet {
if let onChangeSubscriber {
onChangeSubscriber.cancel()
}
}
}
open var label = Label().with { open var label = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical) $0.setContentCompressionResistancePriority(.required, for: .vertical)
} }

View File

@ -0,0 +1,31 @@
//
// Changeable.swift
// VDS
//
// Created by Matt Bruce on 4/3/23.
//
import Foundation
import UIKit
import Combine
public protocol Changeable: Handlerable where Self: UIControl {
var onChangeSubscriber: AnyCancellable? { get set }
}
extension Changeable {
public var onChange: ((Self) -> ())? {
get { return nil }
set {
if let newValue {
onChangeSubscriber = publisher(for: .valueChanged)
.sink { c in
newValue(c)
}
} else {
onChangeSubscriber?.cancel()
onChangeSubscriber = nil
}
}
}
}

View File

@ -15,13 +15,6 @@ public protocol Clickable: Handlerable where Self: UIControl {
} }
extension Clickable { extension Clickable {
public func addEvent(event: UIControl.Event, block: @escaping (Self)->()) {
publisher(for: event)
.sink(receiveValue: { c in
block(c)
}).store(in: &subscribers)
}
public var onClick: ((Self) -> ())? { public var onClick: ((Self) -> ())? {
get { return nil } get { return nil }
set { set {

View File

@ -34,3 +34,12 @@ extension Handlerable where Self: UIView {
subject.send() subject.send()
} }
} }
extension Handlerable where Self: UIControl {
public func addEvent(event: UIControl.Event, block: @escaping (Self)->()) {
publisher(for: event)
.sink(receiveValue: { c in
block(c)
}).store(in: &subscribers)
}
}