Merge branch 'refactor/enabling' into 'develop'
fix for button See merge request BPHV_MIPS/vds_ios!103
This commit is contained in:
commit
53c2a63dbb
@ -48,6 +48,7 @@
|
|||||||
EA33623E2892EE950071C351 /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA33623D2892EE950071C351 /* UIDevice.swift */; };
|
EA33623E2892EE950071C351 /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA33623D2892EE950071C351 /* UIDevice.swift */; };
|
||||||
EA3362402892EF6C0071C351 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA33623F2892EF6B0071C351 /* Label.swift */; };
|
EA3362402892EF6C0071C351 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA33623F2892EF6B0071C351 /* Label.swift */; };
|
||||||
EA33624728931B050071C351 /* Initable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA33624628931B050071C351 /* Initable.swift */; };
|
EA33624728931B050071C351 /* Initable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA33624628931B050071C351 /* Initable.swift */; };
|
||||||
|
EA471F3A2A95587500CE9E58 /* LayoutConstraintable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA471F392A95587500CE9E58 /* LayoutConstraintable.swift */; };
|
||||||
EA4DB18528CA967F00103EE3 /* SelectorGroupHandlerBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4DB18428CA967F00103EE3 /* SelectorGroupHandlerBase.swift */; };
|
EA4DB18528CA967F00103EE3 /* SelectorGroupHandlerBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4DB18428CA967F00103EE3 /* SelectorGroupHandlerBase.swift */; };
|
||||||
EA4DB2FD28D3D0CA00103EE3 /* AnyEquatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4DB2FC28D3D0CA00103EE3 /* AnyEquatable.swift */; };
|
EA4DB2FD28D3D0CA00103EE3 /* AnyEquatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4DB2FC28D3D0CA00103EE3 /* AnyEquatable.swift */; };
|
||||||
EA4DB30228DCBCA500103EE3 /* Badge.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4DB30128DCBCA500103EE3 /* Badge.swift */; };
|
EA4DB30228DCBCA500103EE3 /* Badge.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4DB30128DCBCA500103EE3 /* Badge.swift */; };
|
||||||
@ -139,6 +140,7 @@
|
|||||||
EAF7F0B9289C139800B287F5 /* ColorConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0B8289C139800B287F5 /* ColorConfiguration.swift */; };
|
EAF7F0B9289C139800B287F5 /* ColorConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0B8289C139800B287F5 /* ColorConfiguration.swift */; };
|
||||||
EAF7F11728A1475A00B287F5 /* RadioButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F11528A1475A00B287F5 /* RadioButtonItem.swift */; };
|
EAF7F11728A1475A00B287F5 /* RadioButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F11528A1475A00B287F5 /* RadioButtonItem.swift */; };
|
||||||
EAF7F13328A2A16500B287F5 /* AttachmentLabelAttributeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F13228A2A16500B287F5 /* AttachmentLabelAttributeModel.swift */; };
|
EAF7F13328A2A16500B287F5 /* AttachmentLabelAttributeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F13228A2A16500B287F5 /* AttachmentLabelAttributeModel.swift */; };
|
||||||
|
EAF978212A99035B00C2FEA9 /* Enabling.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF978202A99035B00C2FEA9 /* Enabling.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@ -194,6 +196,7 @@
|
|||||||
EA33623D2892EE950071C351 /* UIDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIDevice.swift; sourceTree = "<group>"; };
|
EA33623D2892EE950071C351 /* UIDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIDevice.swift; sourceTree = "<group>"; };
|
||||||
EA33623F2892EF6B0071C351 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
|
EA33623F2892EF6B0071C351 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
|
||||||
EA33624628931B050071C351 /* Initable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Initable.swift; sourceTree = "<group>"; };
|
EA33624628931B050071C351 /* Initable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Initable.swift; sourceTree = "<group>"; };
|
||||||
|
EA471F392A95587500CE9E58 /* LayoutConstraintable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutConstraintable.swift; sourceTree = "<group>"; };
|
||||||
EA4DB18428CA967F00103EE3 /* SelectorGroupHandlerBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectorGroupHandlerBase.swift; sourceTree = "<group>"; };
|
EA4DB18428CA967F00103EE3 /* SelectorGroupHandlerBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectorGroupHandlerBase.swift; sourceTree = "<group>"; };
|
||||||
EA4DB2FC28D3D0CA00103EE3 /* AnyEquatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyEquatable.swift; sourceTree = "<group>"; };
|
EA4DB2FC28D3D0CA00103EE3 /* AnyEquatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyEquatable.swift; sourceTree = "<group>"; };
|
||||||
EA4DB30128DCBCA500103EE3 /* Badge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Badge.swift; sourceTree = "<group>"; };
|
EA4DB30128DCBCA500103EE3 /* Badge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Badge.swift; sourceTree = "<group>"; };
|
||||||
@ -285,6 +288,7 @@
|
|||||||
EAF7F0B8289C139800B287F5 /* ColorConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorConfiguration.swift; sourceTree = "<group>"; };
|
EAF7F0B8289C139800B287F5 /* ColorConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorConfiguration.swift; sourceTree = "<group>"; };
|
||||||
EAF7F11528A1475A00B287F5 /* RadioButtonItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioButtonItem.swift; sourceTree = "<group>"; };
|
EAF7F11528A1475A00B287F5 /* RadioButtonItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioButtonItem.swift; sourceTree = "<group>"; };
|
||||||
EAF7F13228A2A16500B287F5 /* AttachmentLabelAttributeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentLabelAttributeModel.swift; sourceTree = "<group>"; };
|
EAF7F13228A2A16500B287F5 /* AttachmentLabelAttributeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentLabelAttributeModel.swift; sourceTree = "<group>"; };
|
||||||
|
EAF978202A99035B00C2FEA9 /* Enabling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Enabling.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -487,10 +491,12 @@
|
|||||||
EAF1FE9829D4850E00101452 /* Clickable.swift */,
|
EAF1FE9829D4850E00101452 /* Clickable.swift */,
|
||||||
EAA5EEDF28F49DB3003B3210 /* Colorable.swift */,
|
EAA5EEDF28F49DB3003B3210 /* Colorable.swift */,
|
||||||
EA3361A9288B25E40071C351 /* Disabling.swift */,
|
EA3361A9288B25E40071C351 /* Disabling.swift */,
|
||||||
|
EAF978202A99035B00C2FEA9 /* Enabling.swift */,
|
||||||
EA5E305929510F8B0082B959 /* EnumSubset.swift */,
|
EA5E305929510F8B0082B959 /* EnumSubset.swift */,
|
||||||
EAF7F0A1289AFB3900B287F5 /* Errorable.swift */,
|
EAF7F0A1289AFB3900B287F5 /* Errorable.swift */,
|
||||||
EA3361AE288B26310071C351 /* FormFieldable.swift */,
|
EA3361AE288B26310071C351 /* FormFieldable.swift */,
|
||||||
EA33624628931B050071C351 /* Initable.swift */,
|
EA33624628931B050071C351 /* Initable.swift */,
|
||||||
|
EA471F392A95587500CE9E58 /* LayoutConstraintable.swift */,
|
||||||
EA985C7C297DAED300F2FF2E /* Primitive.swift */,
|
EA985C7C297DAED300F2FF2E /* Primitive.swift */,
|
||||||
EAF7F0A5289B0CE000B287F5 /* Resetable.swift */,
|
EAF7F0A5289B0CE000B287F5 /* Resetable.swift */,
|
||||||
EA3361C8289054C50071C351 /* Surfaceable.swift */,
|
EA3361C8289054C50071C351 /* Surfaceable.swift */,
|
||||||
@ -963,6 +969,7 @@
|
|||||||
EA0D1C372A681CCE00E5C127 /* ToggleView.swift in Sources */,
|
EA0D1C372A681CCE00E5C127 /* ToggleView.swift in Sources */,
|
||||||
EAF7F0B9289C139800B287F5 /* ColorConfiguration.swift in Sources */,
|
EAF7F0B9289C139800B287F5 /* ColorConfiguration.swift in Sources */,
|
||||||
EA3361BD288B2C760071C351 /* TypeAlias.swift in Sources */,
|
EA3361BD288B2C760071C351 /* TypeAlias.swift in Sources */,
|
||||||
|
EA471F3A2A95587500CE9E58 /* LayoutConstraintable.swift in Sources */,
|
||||||
EAB1D2CF28ABEF2B00DAE764 /* Typography.swift in Sources */,
|
EAB1D2CF28ABEF2B00DAE764 /* Typography.swift in Sources */,
|
||||||
EA0D1C3B2A6AD51B00E5C127 /* Typogprahy+Styles.swift in Sources */,
|
EA0D1C3B2A6AD51B00E5C127 /* Typogprahy+Styles.swift in Sources */,
|
||||||
EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */,
|
EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */,
|
||||||
@ -977,6 +984,7 @@
|
|||||||
EA3361AF288B26310071C351 /* FormFieldable.swift in Sources */,
|
EA3361AF288B26310071C351 /* FormFieldable.swift in Sources */,
|
||||||
EA513A952A4E1F82002A4DFF /* TitleLockupStyleConfiguration.swift in Sources */,
|
EA513A952A4E1F82002A4DFF /* TitleLockupStyleConfiguration.swift in Sources */,
|
||||||
44604AD729CE196600E62B51 /* Line.swift in Sources */,
|
44604AD729CE196600E62B51 /* Line.swift in Sources */,
|
||||||
|
EAF978212A99035B00C2FEA9 /* Enabling.swift in Sources */,
|
||||||
EA5E3058295105A40082B959 /* Tilelet.swift in Sources */,
|
EA5E3058295105A40082B959 /* Tilelet.swift in Sources */,
|
||||||
EA89201528B56CF4006B9984 /* RadioBoxGroup.swift in Sources */,
|
EA89201528B56CF4006B9984 /* RadioBoxGroup.swift in Sources */,
|
||||||
EA985C1D296CD13600F2FF2E /* BundleManager.swift in Sources */,
|
EA985C1D296CD13600F2FF2E /* BundleManager.swift in Sources */,
|
||||||
@ -1167,7 +1175,7 @@
|
|||||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||||
CODE_SIGN_IDENTITY = "";
|
CODE_SIGN_IDENTITY = "";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 39;
|
CURRENT_PROJECT_VERSION = 40;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = "";
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
@ -1204,7 +1212,7 @@
|
|||||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||||
CODE_SIGN_IDENTITY = "";
|
CODE_SIGN_IDENTITY = "";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 39;
|
CURRENT_PROJECT_VERSION = 40;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = "";
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
|
|||||||
@ -9,6 +9,14 @@ import Foundation
|
|||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
|
|
||||||
|
public func DebugLog(_ message: String, file: String = #file, line: Int = #line, function: String = #function) {
|
||||||
|
#if DEBUG
|
||||||
|
let path = (file as NSString).lastPathComponent
|
||||||
|
// using print because NSLog crashes when passing certain optionals
|
||||||
|
print("[\(path)] \(function) [Line \(line)] : \(message)")
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/// Bundle Manager keeps all bundles together for ease of use for searching within any of them for a specific asset
|
/// Bundle Manager keeps all bundles together for ease of use for searching within any of them for a specific asset
|
||||||
public class BundleManager {
|
public class BundleManager {
|
||||||
public static var shared = BundleManager()
|
public static var shared = BundleManager()
|
||||||
|
|||||||
@ -143,7 +143,7 @@ public class ControlColorConfiguration: KeyColorConfigurable {
|
|||||||
///Meant to be used with any object that implements Surfaceable and Disabling. More than likely this is any View.
|
///Meant to be used with any object that implements Surfaceable and Disabling. More than likely this is any View.
|
||||||
public class ViewColorConfiguration: KeyColorConfigurable {
|
public class ViewColorConfiguration: KeyColorConfigurable {
|
||||||
public typealias KeyType = Bool
|
public typealias KeyType = Bool
|
||||||
public typealias ObjectType = Surfaceable & Disabling
|
public typealias ObjectType = Surfaceable & Enabling
|
||||||
public var keyColors: [KeyColorConfiguration<KeyType>] = []
|
public var keyColors: [KeyColorConfiguration<KeyType>] = []
|
||||||
|
|
||||||
public required init() { }
|
public required init() { }
|
||||||
@ -161,7 +161,7 @@ public class ViewColorConfiguration: KeyColorConfigurable {
|
|||||||
/// - Parameter object: Object that implements Surfaceable and Disabling
|
/// - Parameter object: Object that implements Surfaceable and Disabling
|
||||||
/// - Returns: UIColor correspoding to either true/false for the disabled state and surface
|
/// - Returns: UIColor correspoding to either true/false for the disabled state and surface
|
||||||
public func getColor(_ object: ObjectType) -> UIColor {
|
public func getColor(_ object: ObjectType) -> UIColor {
|
||||||
if let keyColor = keyColors.first(where: {$0.key == object.disabled }) {
|
if let keyColor = keyColors.first(where: {$0.key == !object.isEnabled }) {
|
||||||
return keyColor.surfaceConfig.getColor(object)
|
return keyColor.surfaceConfig.getColor(object)
|
||||||
} else {
|
} else {
|
||||||
return .clear //default
|
return .clear //default
|
||||||
|
|||||||
@ -40,19 +40,12 @@ open class Control: UIControl, ViewProtocol, UserInfoable, Clickable {
|
|||||||
/// Current Surface and this is used to pass down to child objects that implement Surfacable
|
/// Current Surface and this is used to pass down to child objects that implement Surfacable
|
||||||
open var surface: Surface = .light { didSet { setNeedsUpdate() } }
|
open var surface: Surface = .light { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
/// Whether this object is disabled or not
|
|
||||||
open var disabled: Bool {
|
|
||||||
get { !isEnabled }
|
|
||||||
set {
|
|
||||||
if !isEnabled != newValue {
|
|
||||||
isEnabled = !newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether the Control is selected or not.
|
/// Whether the Control is selected or not.
|
||||||
open override var isSelected: Bool { didSet { setNeedsUpdate() } }
|
open override var isSelected: Bool { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
|
/// Whether the Control can handle the isHighlighted state.
|
||||||
|
open var canHighlight: Bool = true
|
||||||
|
|
||||||
open var touchUpInsideCount: Int = 0
|
open var touchUpInsideCount: Int = 0
|
||||||
|
|
||||||
var isHighlightAnimating = false
|
var isHighlightAnimating = false
|
||||||
@ -60,7 +53,7 @@ open class Control: UIControl, ViewProtocol, UserInfoable, Clickable {
|
|||||||
/// Whether the Control is highlighted or not..
|
/// Whether the Control is highlighted or not..
|
||||||
open override var isHighlighted: Bool {
|
open override var isHighlighted: Bool {
|
||||||
didSet {
|
didSet {
|
||||||
if isHighlightAnimating == false && touchUpInsideCount > 0 {
|
if canHighlight && isHighlightAnimating == false && touchUpInsideCount > 0 {
|
||||||
isHighlightAnimating = true
|
isHighlightAnimating = true
|
||||||
UIView.animate(withDuration: 0.1, animations: { [weak self] in
|
UIView.animate(withDuration: 0.1, animations: { [weak self] in
|
||||||
self?.setNeedsUpdate()
|
self?.setNeedsUpdate()
|
||||||
@ -76,7 +69,12 @@ open class Control: UIControl, ViewProtocol, UserInfoable, Clickable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the Control is enabled or not.
|
/// Whether the Control is enabled or not.
|
||||||
open override var isEnabled: Bool { didSet { setNeedsUpdate(); isUserInteractionEnabled = isEnabled } }
|
open override var isEnabled: Bool {
|
||||||
|
didSet {
|
||||||
|
setNeedsUpdate()
|
||||||
|
//isUserInteractionEnabled = isEnabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializers
|
// MARK: - Initializers
|
||||||
@ -137,7 +135,7 @@ open class Control: UIControl, ViewProtocol, UserInfoable, Clickable {
|
|||||||
open func reset() {
|
open func reset() {
|
||||||
backgroundColor = .clear
|
backgroundColor = .clear
|
||||||
surface = .light
|
surface = .light
|
||||||
disabled = false
|
isEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -27,13 +27,11 @@ open class SelectorGroupHandlerBase<HandlerType: Control>: Control, Changeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this object is disabled or not
|
/// Whether this object is enabled or not
|
||||||
override open var disabled: Bool {
|
override open var isEnabled: Bool {
|
||||||
didSet {
|
didSet {
|
||||||
selectorViews.forEach { handler in
|
selectorViews.forEach { $0.isEnabled = isEnabled }
|
||||||
handler.disabled = disabled
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,7 @@ open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable,
|
|||||||
// MARK: - Private Properties
|
// MARK: - Private Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
private var shouldShowError: Bool {
|
private var shouldShowError: Bool {
|
||||||
guard showError && !disabled && errorText?.isEmpty == false else { return false }
|
guard showError && isEnabled && errorText?.isEmpty == false else { return false }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable,
|
|||||||
selectorView.showError = showError
|
selectorView.showError = showError
|
||||||
selectorView.isSelected = isSelected
|
selectorView.isSelected = isSelected
|
||||||
selectorView.isHighlighted = isHighlighted
|
selectorView.isHighlighted = isHighlighted
|
||||||
selectorView.disabled = disabled
|
selectorView.isEnabled = isEnabled
|
||||||
selectorView.surface = surface
|
selectorView.surface = surface
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +237,7 @@ open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable,
|
|||||||
//top label
|
//top label
|
||||||
if let labelText {
|
if let labelText {
|
||||||
label.surface = surface
|
label.surface = surface
|
||||||
label.disabled = disabled
|
label.isEnabled = isEnabled
|
||||||
label.attributes = labelTextAttributes
|
label.attributes = labelTextAttributes
|
||||||
label.text = labelText
|
label.text = labelText
|
||||||
label.isHidden = false
|
label.isHidden = false
|
||||||
@ -252,7 +252,7 @@ open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable,
|
|||||||
if let childText {
|
if let childText {
|
||||||
childLabel.text = childText
|
childLabel.text = childText
|
||||||
childLabel.surface = surface
|
childLabel.surface = surface
|
||||||
childLabel.disabled = disabled
|
childLabel.isEnabled = isEnabled
|
||||||
childLabel.attributes = childTextAttributes
|
childLabel.attributes = childTextAttributes
|
||||||
childLabel.isHidden = false
|
childLabel.isHidden = false
|
||||||
|
|
||||||
@ -276,7 +276,7 @@ open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable,
|
|||||||
if let errorText, shouldShowError {
|
if let errorText, shouldShowError {
|
||||||
errorLabel.text = errorText
|
errorLabel.text = errorText
|
||||||
errorLabel.surface = surface
|
errorLabel.surface = surface
|
||||||
errorLabel.disabled = disabled
|
errorLabel.isEnabled = isEnabled
|
||||||
mainStackView.spacing = 8
|
mainStackView.spacing = 8
|
||||||
errorLabel.isHidden = false
|
errorLabel.isHidden = false
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -33,18 +33,8 @@ open class View: UIView, ViewProtocol, UserInfoable {
|
|||||||
/// Current Surface and this is used to pass down to child objects that implement Surfacable
|
/// Current Surface and this is used to pass down to child objects that implement Surfacable
|
||||||
open var surface: Surface = .light { didSet { setNeedsUpdate() } }
|
open var surface: Surface = .light { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
/// Whether this object is disabled or not.
|
|
||||||
open var disabled: Bool {
|
|
||||||
get { !isEnabled }
|
|
||||||
set {
|
|
||||||
if !isEnabled != newValue {
|
|
||||||
isEnabled = !newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether the View is enabled or not.
|
/// Whether the View is enabled or not.
|
||||||
open var isEnabled: Bool = true { didSet { setNeedsUpdate(); isUserInteractionEnabled = isEnabled } }
|
open var isEnabled: Bool = true { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializers
|
// MARK: - Initializers
|
||||||
@ -101,7 +91,7 @@ open class View: UIView, ViewProtocol, UserInfoable {
|
|||||||
open func reset() {
|
open func reset() {
|
||||||
backgroundColor = .clear
|
backgroundColor = .clear
|
||||||
surface = .light
|
surface = .light
|
||||||
disabled = false
|
isEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,9 +27,11 @@ open class Badge: View {
|
|||||||
|
|
||||||
/// Label used to render text
|
/// Label used to render text
|
||||||
open var label = Label().with {
|
open var label = Label().with {
|
||||||
$0.setContentCompressionResistancePriority(.required, for: .vertical)
|
|
||||||
$0.adjustsFontSizeToFitWidth = false
|
|
||||||
$0.lineBreakMode = .byTruncatingTail
|
$0.lineBreakMode = .byTruncatingTail
|
||||||
|
$0.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||||
|
$0.setContentHuggingPriority(.defaultHigh, for: .vertical)
|
||||||
|
$0.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||||
|
$0.setContentHuggingPriority(.defaultHigh, for: .horizontal)
|
||||||
$0.textPosition = .left
|
$0.textPosition = .left
|
||||||
$0.textStyle = .boldBodySmall
|
$0.textStyle = .boldBodySmall
|
||||||
}
|
}
|
||||||
@ -37,7 +39,7 @@ open class Badge: View {
|
|||||||
/// This will render the badges fill color based on the available options.
|
/// This will render the badges fill color based on the available options.
|
||||||
/// When used in conjunction with the surface prop, this fill color will change its tint automatically based on a light or dark surface.
|
/// When used in conjunction with the surface prop, this fill color will change its tint automatically based on a light or dark surface.
|
||||||
open var fillColor: FillColor = .red { didSet { setNeedsUpdate() }}
|
open var fillColor: FillColor = .red { didSet { setNeedsUpdate() }}
|
||||||
|
|
||||||
/// The text that will be shown in the label.
|
/// The text that will be shown in the label.
|
||||||
open var text: String = "" { didSet { setNeedsUpdate() }}
|
open var text: String = "" { didSet { setNeedsUpdate() }}
|
||||||
|
|
||||||
@ -46,16 +48,27 @@ open class Badge: View {
|
|||||||
|
|
||||||
/// This will restrict the badge height to a specific number of lines. If the text overflows the allowable space, ellipsis will show.
|
/// This will restrict the badge height to a specific number of lines. If the text overflows the allowable space, ellipsis will show.
|
||||||
open var numberOfLines: Int = 1 { didSet { setNeedsUpdate() }}
|
open var numberOfLines: Int = 1 { didSet { setNeedsUpdate() }}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Constraints
|
// MARK: - Constraints
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
private var maxWidthConstraint: NSLayoutConstraint?
|
private var maxWidthConstraint: NSLayoutConstraint?
|
||||||
private var minWidthConstraint: NSLayoutConstraint?
|
|
||||||
|
private func updateMaxWidth() {
|
||||||
|
maxWidthConstraint?.isActive = false
|
||||||
|
guard let maxWidth, maxWidth > minWidth else { return }
|
||||||
|
maxWidthConstraint?.constant = maxWidth
|
||||||
|
maxWidthConstraint?.isActive = true
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Configuration
|
// MARK: - Configuration
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
private var minWidth: CGFloat = 23.0
|
||||||
|
private var labelInset: UIEdgeInsets = .init(top: 2,
|
||||||
|
left: VDSLayout.Spacing.space1X.value,
|
||||||
|
bottom: 2,
|
||||||
|
right: VDSLayout.Spacing.space1X.value)
|
||||||
|
|
||||||
/// ColorConfiguration that is mapped to the 'fillColor' for the surface.
|
/// ColorConfiguration that is mapped to the 'fillColor' for the surface.
|
||||||
private var backgroundColorConfiguration: AnyColorable = {
|
private var backgroundColorConfiguration: AnyColorable = {
|
||||||
@ -96,23 +109,23 @@ open class Badge: View {
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Lifecycle
|
// MARK: - Lifecycle
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
open override func setup() {
|
open override func setup() {
|
||||||
super.setup()
|
super.setup()
|
||||||
|
|
||||||
accessibilityElements = [label]
|
accessibilityElements = [label]
|
||||||
layer.cornerRadius = 2
|
layer.cornerRadius = 2
|
||||||
|
|
||||||
addSubview(label)
|
addSubview(label)
|
||||||
label.pinToSuperView(.init(top: 2,
|
|
||||||
left: VDSLayout.Spacing.space1X.value,
|
|
||||||
bottom: 2,
|
|
||||||
right: VDSLayout.Spacing.space1X.value))
|
|
||||||
|
|
||||||
maxWidthConstraint = label.widthAnchor.constraint(lessThanOrEqualToConstant: 100)
|
label
|
||||||
minWidthConstraint = label.widthAnchor.constraint(greaterThanOrEqualToConstant: 23)
|
.pinTop(labelInset.top)
|
||||||
minWidthConstraint?.isActive = true
|
.pinLeading(labelInset.left)
|
||||||
|
.pinTrailing(labelInset.right)
|
||||||
|
.pinBottom(labelInset.bottom, .defaultHigh)
|
||||||
|
|
||||||
|
label.widthGreaterThanEqualTo(constant: minWidth)
|
||||||
|
maxWidthConstraint = label.widthLessThanEqualTo(constant: 0).with { $0.isActive = false }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resets to default settings.
|
/// Resets to default settings.
|
||||||
@ -136,20 +149,14 @@ open class Badge: View {
|
|||||||
super.updateView()
|
super.updateView()
|
||||||
|
|
||||||
updateTextColorConfig()
|
updateTextColorConfig()
|
||||||
|
updateMaxWidth()
|
||||||
backgroundColor = backgroundColorConfiguration.getColor(self)
|
|
||||||
|
|
||||||
|
backgroundColor = backgroundColorConfiguration.getColor(self)
|
||||||
|
|
||||||
label.textColorConfiguration = textColorConfiguration.eraseToAnyColorable()
|
label.textColorConfiguration = textColorConfiguration.eraseToAnyColorable()
|
||||||
label.numberOfLines = numberOfLines
|
label.numberOfLines = numberOfLines
|
||||||
label.text = text
|
label.text = text
|
||||||
label.surface = surface
|
label.surface = surface
|
||||||
label.disabled = disabled
|
label.isEnabled = isEnabled
|
||||||
|
|
||||||
if let maxWidth = maxWidth, let minWidth = minWidthConstraint?.constant, maxWidth > minWidth {
|
|
||||||
maxWidthConstraint?.constant = maxWidth
|
|
||||||
maxWidthConstraint?.isActive = true
|
|
||||||
} else {
|
|
||||||
maxWidthConstraint?.isActive = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -258,19 +258,12 @@ open class BadgeIndicator: View {
|
|||||||
badgeView.addSubview(label)
|
badgeView.addSubview(label)
|
||||||
accessibilityElements = [label]
|
accessibilityElements = [label]
|
||||||
|
|
||||||
heightConstraint = badgeView.heightAnchor.constraint(greaterThanOrEqualToConstant: badgeSize)
|
heightConstraint = badgeView.heightGreaterThanEqualTo(constant: badgeSize)
|
||||||
heightConstraint?.isActive = true
|
widthConstraint = badgeView.widthGreaterThanEqualTo(constant: badgeSize)
|
||||||
|
|
||||||
widthConstraint = badgeView.widthAnchor.constraint(greaterThanOrEqualToConstant: badgeSize)
|
|
||||||
widthConstraint?.isActive = true
|
|
||||||
|
|
||||||
//we are insetting the padding to compensate for the border
|
//we are insetting the padding to compensate for the border
|
||||||
NSLayoutConstraint.activate([
|
badgeView.pinToSuperView(.init(top: borderWidth, left: borderWidth, bottom: borderWidth, right: borderWidth))
|
||||||
badgeView.topAnchor.constraint(equalTo: topAnchor, constant: borderWidth),
|
|
||||||
badgeView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -borderWidth),
|
|
||||||
badgeView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: borderWidth),
|
|
||||||
badgeView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -borderWidth)])
|
|
||||||
|
|
||||||
labelContraints.topConstraint = label.pinTopGreaterThanOrEqualTo(anchor: badgeView.topAnchor)
|
labelContraints.topConstraint = label.pinTopGreaterThanOrEqualTo(anchor: badgeView.topAnchor)
|
||||||
labelContraints.bottomConstraint = label.pinBottomGreaterThanOrEqualTo(anchor: badgeView.bottomAnchor)
|
labelContraints.bottomConstraint = label.pinBottomGreaterThanOrEqualTo(anchor: badgeView.bottomAnchor)
|
||||||
labelContraints.leadingConstraint = label.pinLeadingGreaterThanOrEqualTo(anchor: badgeView.leadingAnchor)
|
labelContraints.leadingConstraint = label.pinLeadingGreaterThanOrEqualTo(anchor: badgeView.leadingAnchor)
|
||||||
@ -348,7 +341,7 @@ open class BadgeIndicator: View {
|
|||||||
label.textColorConfiguration = textColorConfiguration.eraseToAnyColorable()
|
label.textColorConfiguration = textColorConfiguration.eraseToAnyColorable()
|
||||||
label.text = getText()
|
label.text = getText()
|
||||||
label.surface = surface
|
label.surface = surface
|
||||||
label.disabled = disabled
|
label.isEnabled = isEnabled
|
||||||
label.sizeToFit()
|
label.sizeToFit()
|
||||||
setNeedsLayout()
|
setNeedsLayout()
|
||||||
layoutIfNeeded()
|
layoutIfNeeded()
|
||||||
|
|||||||
@ -22,9 +22,6 @@ open class Button: ButtonBase, Useable {
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Private Properties
|
// MARK: - Private Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
private var minWidthConstraint: NSLayoutConstraint?
|
|
||||||
private var widthConstraint: NSLayoutConstraint?
|
|
||||||
private var heightConstraint: NSLayoutConstraint?
|
|
||||||
private var initialSetupPerformed = false
|
private var initialSetupPerformed = false
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -36,7 +33,18 @@ open class Button: ButtonBase, Useable {
|
|||||||
|
|
||||||
open var size: ButtonSize = .large { didSet { setNeedsUpdate() }}
|
open var size: ButtonSize = .large { didSet { setNeedsUpdate() }}
|
||||||
|
|
||||||
open var width: CGFloat? { didSet { setNeedsUpdate() }}
|
private var _width: CGFloat? = nil
|
||||||
|
open var width: CGFloat? {
|
||||||
|
get { _width }
|
||||||
|
set {
|
||||||
|
if let newValue, newValue > size.minimumWidth {
|
||||||
|
_width = newValue
|
||||||
|
} else {
|
||||||
|
_width = nil
|
||||||
|
}
|
||||||
|
setNeedsUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
open override var textColor: UIColor {
|
open override var textColor: UIColor {
|
||||||
textColorConfiguration.getColor(self)
|
textColorConfiguration.getColor(self)
|
||||||
@ -120,14 +128,6 @@ open class Button: ButtonBase, Useable {
|
|||||||
super.setup()
|
super.setup()
|
||||||
isAccessibilityElement = true
|
isAccessibilityElement = true
|
||||||
accessibilityTraits = .button
|
accessibilityTraits = .button
|
||||||
|
|
||||||
//only 1 of the 2 widths can be on at the same time
|
|
||||||
widthConstraint = widthAnchor.constraint(equalToConstant: 0)
|
|
||||||
minWidthConstraint = widthAnchor.constraint(greaterThanOrEqualToConstant: size.minimumWidth)
|
|
||||||
|
|
||||||
//height
|
|
||||||
heightConstraint = heightAnchor.constraint(equalToConstant: 0)
|
|
||||||
heightConstraint?.isActive = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resets to default settings.
|
/// Resets to default settings.
|
||||||
@ -145,7 +145,12 @@ open class Button: ButtonBase, Useable {
|
|||||||
// MARK: - Overrides
|
// MARK: - Overrides
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
open override var intrinsicContentSize: CGSize {
|
open override var intrinsicContentSize: CGSize {
|
||||||
guard let width, width > 0 else { return super.intrinsicContentSize }
|
guard let width, width > 0 else {
|
||||||
|
var superSize = super.intrinsicContentSize
|
||||||
|
superSize.height = size.height
|
||||||
|
return superSize
|
||||||
|
}
|
||||||
|
|
||||||
return CGSize(width: width > size.minimumWidth ? width : size.minimumWidth, height: size.height)
|
return CGSize(width: width > size.minimumWidth ? width : size.minimumWidth, height: size.height)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,9 +161,7 @@ open class Button: ButtonBase, Useable {
|
|||||||
let bgColor = backgroundColorConfiguration.getColor(self)
|
let bgColor = backgroundColorConfiguration.getColor(self)
|
||||||
let borderColor = borderColorConfiguration.getColor(self)
|
let borderColor = borderColorConfiguration.getColor(self)
|
||||||
let borderWidth = use == .secondary ? VDSFormControls.widthBorder : 0.0
|
let borderWidth = use == .secondary ? VDSFormControls.widthBorder : 0.0
|
||||||
let buttonHeight = size.height
|
|
||||||
let cornerRadius = size.cornerRadius
|
let cornerRadius = size.cornerRadius
|
||||||
let minWidth = size.minimumWidth
|
|
||||||
let edgeInsets = size.edgeInsets
|
let edgeInsets = size.edgeInsets
|
||||||
|
|
||||||
backgroundColor = bgColor
|
backgroundColor = bgColor
|
||||||
@ -166,18 +169,8 @@ open class Button: ButtonBase, Useable {
|
|||||||
layer.cornerRadius = cornerRadius
|
layer.cornerRadius = cornerRadius
|
||||||
layer.borderWidth = borderWidth
|
layer.borderWidth = borderWidth
|
||||||
contentEdgeInsets = edgeInsets
|
contentEdgeInsets = edgeInsets
|
||||||
|
|
||||||
minWidthConstraint?.constant = minWidth
|
invalidateIntrinsicContentSize()
|
||||||
heightConstraint?.constant = buttonHeight
|
|
||||||
|
|
||||||
if let width, width > minWidth {
|
|
||||||
widthConstraint?.constant = width
|
|
||||||
widthConstraint?.isActive = true
|
|
||||||
minWidthConstraint?.isActive = false
|
|
||||||
} else {
|
|
||||||
widthConstraint?.isActive = false
|
|
||||||
minWidthConstraint?.isActive = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import VDSColorTokens
|
|||||||
import VDSFormControlsTokens
|
import VDSFormControlsTokens
|
||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
public protocol Buttonable: UIControl, Surfaceable, Disabling {
|
public protocol Buttonable: UIControl, Surfaceable, Enabling {
|
||||||
var availableSizes: [ButtonSize] { get }
|
var availableSizes: [ButtonSize] { get }
|
||||||
var text: String? { get set }
|
var text: String? { get set }
|
||||||
var intrinsicContentSize: CGSize { get }
|
var intrinsicContentSize: CGSize { get }
|
||||||
@ -83,19 +83,9 @@ open class ButtonBase: UIButton, Buttonable, ViewProtocol, UserInfoable, Clickab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this object is disabled or not
|
|
||||||
open var disabled: Bool {
|
|
||||||
get { !isEnabled }
|
|
||||||
set {
|
|
||||||
if !isEnabled != newValue {
|
|
||||||
isEnabled = !newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether the Control is enabled or not.
|
/// Whether the Control is enabled or not.
|
||||||
open override var isEnabled: Bool { didSet { setNeedsUpdate(); isUserInteractionEnabled = isEnabled } }
|
open override var isEnabled: Bool { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
open var textStyle: TextStyle { .defaultStyle }
|
open var textStyle: TextStyle { .defaultStyle }
|
||||||
|
|
||||||
@ -144,7 +134,7 @@ open class ButtonBase: UIButton, Buttonable, ViewProtocol, UserInfoable, Clickab
|
|||||||
open func reset() {
|
open func reset() {
|
||||||
shouldUpdateView = false
|
shouldUpdateView = false
|
||||||
surface = .light
|
surface = .light
|
||||||
disabled = false
|
isEnabled = true
|
||||||
text = nil
|
text = nil
|
||||||
accessibilityCustomActions = []
|
accessibilityCustomActions = []
|
||||||
shouldUpdateView = true
|
shouldUpdateView = true
|
||||||
|
|||||||
@ -93,13 +93,10 @@ open class ButtonGroup: View, UICollectionViewDataSource, UICollectionViewDelega
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Overrides
|
// MARK: - Overrides
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
/// Whether this object is disabled or not
|
/// Whether this object is enabled or not
|
||||||
override open var disabled: Bool {
|
override open var isEnabled: Bool {
|
||||||
didSet {
|
didSet {
|
||||||
buttons.forEach { button in
|
buttons.forEach { $0.isEnabled = isEnabled }
|
||||||
var b = button
|
|
||||||
b.disabled = disabled
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,12 +127,13 @@ open class ButtonGroup: View, UICollectionViewDataSource, UICollectionViewDelega
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Public Functions
|
// MARK: - Public Functions
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
open override func setup() {
|
open override func setup() {
|
||||||
super.setup()
|
super.setup()
|
||||||
addSubview(collectionView)
|
addSubview(collectionView)
|
||||||
collectionView.pinToSuperView()
|
collectionView.pinToSuperView()
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Overrides
|
// MARK: - Overrides
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -150,11 +148,12 @@ open class ButtonGroup: View, UICollectionViewDataSource, UICollectionViewDelega
|
|||||||
open override func layoutSubviews() {
|
open override func layoutSubviews() {
|
||||||
super.layoutSubviews()
|
super.layoutSubviews()
|
||||||
// Accounts for any collection size changes
|
// Accounts for any collection size changes
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
guard let self else { return }
|
||||||
self.collectionView.collectionViewLayout.invalidateLayout()
|
self.collectionView.collectionViewLayout.invalidateLayout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - UICollectionViewDataSource
|
// MARK: - UICollectionViewDataSource
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -195,5 +194,4 @@ open class ButtonGroup: View, UICollectionViewDataSource, UICollectionViewDelega
|
|||||||
public func collectionView(_ collectionView: UICollectionView, buttonableAtIndexPath indexPath: IndexPath) -> Buttonable {
|
public func collectionView(_ collectionView: UICollectionView, buttonableAtIndexPath indexPath: IndexPath) -> Buttonable {
|
||||||
buttons[indexPath.row]
|
buttons[indexPath.row]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,10 @@ open class TextLink: ButtonBase {
|
|||||||
// MARK: - Private Properties
|
// MARK: - Private Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
private var lineHeightConstraint: NSLayoutConstraint?
|
private var lineHeightConstraint: NSLayoutConstraint?
|
||||||
|
|
||||||
|
private var line = UIView().with {
|
||||||
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
@ -64,10 +68,6 @@ open class TextLink: ButtonBase {
|
|||||||
super.init(coder: coder)
|
super.init(coder: coder)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var line = UIView().with {
|
|
||||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Public Functions
|
// MARK: - Public Functions
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -75,15 +75,15 @@ open class TextLink: ButtonBase {
|
|||||||
super.setup()
|
super.setup()
|
||||||
isAccessibilityElement = true
|
isAccessibilityElement = true
|
||||||
accessibilityTraits = .link
|
accessibilityTraits = .link
|
||||||
|
|
||||||
if let titleLabel {
|
if let titleLabel {
|
||||||
addSubview(line)
|
addSubview(line)
|
||||||
line.pinLeading(titleLabel.leadingAnchor)
|
line.pinLeading(titleLabel.leadingAnchor)
|
||||||
line.pinTrailing(titleLabel.trailingAnchor)
|
line.pinTrailing(titleLabel.trailingAnchor)
|
||||||
line.pinTop(titleLabel.bottomAnchor)
|
line.pinTop(titleLabel.bottomAnchor)
|
||||||
line.pinBottom(bottomAnchor)
|
line.pinBottom(bottomAnchor, 0, .defaultHigh)
|
||||||
lineHeightConstraint = line.heightAnchor.constraint(equalToConstant: 1.0)
|
lineHeightConstraint = line.height(constant: 1)
|
||||||
lineHeightConstraint?.isActive = true
|
lineHeightConstraint?.isActive = true
|
||||||
titleLabel.debugBorder(show: true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ open class TextLink: ButtonBase {
|
|||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
shouldUpdateView = false
|
||||||
text = nil
|
text = nil
|
||||||
size = .large
|
size = .large
|
||||||
accessibilityCustomActions = []
|
accessibilityCustomActions = []
|
||||||
isAccessibilityElement = true
|
isAccessibilityElement = true
|
||||||
accessibilityTraits = .link
|
accessibilityTraits = .link
|
||||||
|
|||||||
@ -119,7 +119,7 @@ extension TextLinkCaret {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setAttribute(on attributedString: NSMutableAttributedString) {
|
func setAttribute(on attributedString: NSMutableAttributedString) {
|
||||||
let imageAttr = ImageLabelAttribute(location: location, imageName: "\(position.rawValue)-caret-bold", frame: .init(x: 0, y: 0, width: caretSize.width, height: caretSize.height), tintColor: tintColor)
|
let imageAttr = ImageLabelAttribute(location: location, imageName: "\(position.rawValue)-caret-bold", frame: .init(x: 0, y: 0, width: caretSize.width, height: caretSize.height), tintColor: tintColor, accessibleText: "Caret")
|
||||||
let spacer = NSAttributedString.spacer(for: spacerWidth)
|
let spacer = NSAttributedString.spacer(for: spacerWidth)
|
||||||
|
|
||||||
guard let image = try? imageAttr.getAttachment() else { return }
|
guard let image = try? imageAttr.getAttachment() else { return }
|
||||||
|
|||||||
@ -99,7 +99,7 @@ open class Checkbox: SelectorBase {
|
|||||||
|
|
||||||
shapeLayer?.removeAllAnimations()
|
shapeLayer?.removeAllAnimations()
|
||||||
|
|
||||||
if isAnimated && !disabled && !isHighlighted {
|
if isAnimated && isEnabled && !isHighlighted {
|
||||||
let animateStrokeEnd = CABasicAnimation(keyPath: "strokeEnd")
|
let animateStrokeEnd = CABasicAnimation(keyPath: "strokeEnd")
|
||||||
animateStrokeEnd.timingFunction = CAMediaTimingFunction(name: .linear)
|
animateStrokeEnd.timingFunction = CAMediaTimingFunction(name: .linear)
|
||||||
animateStrokeEnd.duration = 0.3
|
animateStrokeEnd.duration = 0.3
|
||||||
|
|||||||
@ -40,7 +40,7 @@ open class CheckboxGroup: SelectorGroupHandlerBase<CheckboxItem> {
|
|||||||
if let selectorModels {
|
if let selectorModels {
|
||||||
selectorViews = selectorModels.enumerated().map { index, model in
|
selectorViews = selectorModels.enumerated().map { index, model in
|
||||||
return CheckboxItem().with {
|
return CheckboxItem().with {
|
||||||
$0.disabled = model.disabled
|
$0.isEnabled = !model.disabled
|
||||||
$0.surface = model.surface
|
$0.surface = model.surface
|
||||||
$0.inputId = model.inputId
|
$0.inputId = model.inputId
|
||||||
$0.value = model.value
|
$0.value = model.value
|
||||||
@ -110,7 +110,7 @@ open class CheckboxGroup: SelectorGroupHandlerBase<CheckboxItem> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension CheckboxGroup {
|
extension CheckboxGroup {
|
||||||
public struct CheckboxModel : Surfaceable, Disabling, Initable, FormFieldable, Errorable {
|
public struct CheckboxModel : Surfaceable, Initable, FormFieldable, Errorable {
|
||||||
|
|
||||||
/// Whether this object is disabled or not
|
/// Whether this object is disabled or not
|
||||||
public var disabled: Bool
|
public var disabled: Bool
|
||||||
|
|||||||
@ -235,22 +235,17 @@ open class ButtonIcon: Control {
|
|||||||
addSubview(icon)
|
addSubview(icon)
|
||||||
|
|
||||||
//determines the height/width of the icon
|
//determines the height/width of the icon
|
||||||
layoutGuideWidthConstraint = iconLayoutGuide.widthAnchor.constraint(equalToConstant: size.containerSize)
|
layoutGuideWidthConstraint = iconLayoutGuide.width(constant: size.containerSize)
|
||||||
layoutGuideHeightConstraint = iconLayoutGuide.heightAnchor.constraint(equalToConstant: size.containerSize)
|
layoutGuideHeightConstraint = iconLayoutGuide.height(constant: size.containerSize)
|
||||||
|
|
||||||
|
//pin layout guide
|
||||||
|
iconLayoutGuide.pinToSuperView()
|
||||||
|
|
||||||
//determines the center point of the icon
|
//determines the center point of the icon
|
||||||
centerXConstraint = icon.centerXAnchor.constraint(equalTo: iconLayoutGuide.centerXAnchor, constant: 0)
|
centerXConstraint = icon.centerXAnchor.constraint(equalTo: iconLayoutGuide.centerXAnchor, constant: 0)
|
||||||
|
centerXConstraint?.activate()
|
||||||
centerYConstraint = icon.centerYAnchor.constraint(equalTo: iconLayoutGuide.centerYAnchor, constant: 0)
|
centerYConstraint = icon.centerYAnchor.constraint(equalTo: iconLayoutGuide.centerYAnchor, constant: 0)
|
||||||
|
centerYConstraint?.activate()
|
||||||
//activate the constraints
|
|
||||||
NSLayoutConstraint.activate([layoutGuideWidthConstraint!,
|
|
||||||
layoutGuideHeightConstraint!,
|
|
||||||
centerXConstraint!,
|
|
||||||
centerYConstraint!,
|
|
||||||
iconLayoutGuide.topAnchor.constraint(equalTo: topAnchor),
|
|
||||||
iconLayoutGuide.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
||||||
iconLayoutGuide.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
||||||
iconLayoutGuide.trailingAnchor.constraint(equalTo: trailingAnchor)])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resets to default settings.
|
/// Resets to default settings.
|
||||||
|
|||||||
@ -16,8 +16,10 @@ open class Icon: View {
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Private Properties
|
// MARK: - Private Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
private var widthConstraint: NSLayoutConstraint?
|
private var dimensions: CGSize {
|
||||||
private var heightConstraint: NSLayoutConstraint?
|
guard let customSize else { return size.dimensions }
|
||||||
|
return .init(width: customSize, height: customSize)
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Public Properties
|
// MARK: - Public Properties
|
||||||
@ -42,20 +44,20 @@ open class Icon: View {
|
|||||||
|
|
||||||
//functions
|
//functions
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Lifecycle
|
// MARK: - Overrides
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
open override func setup() {
|
open override func setup() {
|
||||||
super.setup()
|
super.setup()
|
||||||
|
|
||||||
|
setContentCompressionResistancePriority(.required, for: .vertical)
|
||||||
|
setContentHuggingPriority(.required, for: .vertical)
|
||||||
|
setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||||
|
setContentHuggingPriority(.required, for: .horizontal)
|
||||||
|
|
||||||
addSubview(imageView)
|
addSubview(imageView)
|
||||||
imageView.pinToSuperView()
|
imageView.pinToSuperView()
|
||||||
|
|
||||||
heightConstraint = imageView.heightAnchor.constraint(equalToConstant: size.dimensions.height)
|
|
||||||
heightConstraint?.isActive = true
|
|
||||||
widthConstraint = imageView.widthAnchor.constraint(equalToConstant: size.dimensions.width)
|
|
||||||
widthConstraint?.isActive = true
|
|
||||||
|
|
||||||
backgroundColor = .clear
|
backgroundColor = .clear
|
||||||
|
|
||||||
isAccessibilityElement = true
|
isAccessibilityElement = true
|
||||||
@ -68,6 +70,10 @@ open class Icon: View {
|
|||||||
color = VDSColor.paletteBlack
|
color = VDSColor.paletteBlack
|
||||||
imageView.image = nil
|
imageView.image = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override var intrinsicContentSize: CGSize {
|
||||||
|
dimensions
|
||||||
|
}
|
||||||
|
|
||||||
/// Function used to make changes to the View based off a change events or from local properties.
|
/// Function used to make changes to the View based off a change events or from local properties.
|
||||||
open override func updateView() {
|
open override func updateView() {
|
||||||
@ -81,17 +87,7 @@ open class Icon: View {
|
|||||||
} else if surface == .light && color == VDSColor.paletteBlack {
|
} else if surface == .light && color == VDSColor.paletteBlack {
|
||||||
imageColor = VDSColor.elementsPrimaryOnlight
|
imageColor = VDSColor.elementsPrimaryOnlight
|
||||||
}
|
}
|
||||||
|
|
||||||
//set the icon dimensions
|
|
||||||
var dimensions = size.dimensions
|
|
||||||
|
|
||||||
if let customSize {
|
|
||||||
dimensions = .init(width: customSize, height: customSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
heightConstraint?.constant = dimensions.height
|
|
||||||
widthConstraint?.constant = dimensions.width
|
|
||||||
|
|
||||||
//get the image name
|
//get the image name
|
||||||
//set the image
|
//set the image
|
||||||
if let name, let image = getImage(for: name.rawValue) {
|
if let name, let image = getImage(for: name.rawValue) {
|
||||||
@ -99,8 +95,10 @@ open class Icon: View {
|
|||||||
} else {
|
} else {
|
||||||
imageView.image = nil
|
imageView.image = nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
invalidateIntrinsicContentSize()
|
||||||
|
}
|
||||||
|
|
||||||
private func getImage(for imageName: String) -> UIImage? {
|
private func getImage(for imageName: String) -> UIImage? {
|
||||||
|
|
||||||
return BundleManager.shared.image(for: imageName)
|
return BundleManager.shared.image(for: imageName)
|
||||||
|
|||||||
@ -38,18 +38,17 @@ public struct ActionLabelAttribute: ActionLabelAttributeModel {
|
|||||||
public var length: Int
|
public var length: Int
|
||||||
public var shouldUnderline: Bool
|
public var shouldUnderline: Bool
|
||||||
public var accessibleText: String?
|
public var accessibleText: String?
|
||||||
public var action: PassthroughSubject<Void, Never>
|
public var action = PassthroughSubject<Void, Never>()
|
||||||
public var subscriber: AnyCancellable?
|
public var subscriber: AnyCancellable?
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializer
|
// MARK: - Initializer
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public init(location: Int, length: Int, shouldUnderline: Bool = true, accessibleText: String? = nil, action: PassthroughSubject<Void, Never> = .init() ) {
|
public init(location: Int, length: Int, shouldUnderline: Bool = true, accessibleText: String? = nil) {
|
||||||
self.location = location
|
self.location = location
|
||||||
self.length = length
|
self.length = length
|
||||||
self.shouldUnderline = shouldUnderline
|
self.shouldUnderline = shouldUnderline
|
||||||
self.accessibleText = accessibleText
|
self.accessibleText = accessibleText
|
||||||
self.action = action
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
@ -67,3 +66,19 @@ public struct ActionLabelAttribute: ActionLabelAttributeModel {
|
|||||||
extension NSAttributedString.Key {
|
extension NSAttributedString.Key {
|
||||||
public static let action = NSAttributedString.Key(rawValue: "action")
|
public static let action = NSAttributedString.Key(rawValue: "action")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
public func nsRange(of text: String) -> NSRange? {
|
||||||
|
guard let found = range(of: text) else { return nil }
|
||||||
|
return NSRange(found, in: self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension ActionLabelAttribute {
|
||||||
|
|
||||||
|
public init? (text: String, linkText: String, accessibleText: String? = nil) {
|
||||||
|
guard let range = text.nsRange(of: linkText) else { return nil }
|
||||||
|
self.init(location: range.location, length: range.length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -28,7 +28,8 @@ public struct ImageLabelAttribute: AttachmentLabelAttributeModel {
|
|||||||
public var image: UIImage?
|
public var image: UIImage?
|
||||||
public var frame: CGRect?
|
public var frame: CGRect?
|
||||||
public var tintColor: UIColor?
|
public var tintColor: UIColor?
|
||||||
|
public var accessibleText: String?
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Equatable
|
// MARK: - Equatable
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -40,11 +41,27 @@ public struct ImageLabelAttribute: AttachmentLabelAttributeModel {
|
|||||||
return id == equatable.id && range == equatable.range && imageName == equatable.imageName
|
return id == equatable.id && range == equatable.range && imageName == equatable.imageName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(id: UUID = UUID(), location: Int, imageName: String? = nil, image: UIImage? = nil, frame: CGRect? = nil, tintColor: UIColor? = nil, accessibleText: String? = nil) {
|
||||||
|
self.id = id
|
||||||
|
self.location = location
|
||||||
|
self.imageName = imageName
|
||||||
|
self.image = image
|
||||||
|
self.frame = frame
|
||||||
|
self.tintColor = tintColor
|
||||||
|
self.accessibleText = accessibleText
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Private Functions
|
// MARK: - Private Functions
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
private func imageAttachment(image: UIImage) -> NSTextAttachment {
|
private func imageAttachment(image: UIImage) -> NSTextAttachment {
|
||||||
let attachment = NSTextAttachment()
|
let attachment = NSTextAttachment()
|
||||||
|
if let accessibleText {
|
||||||
|
attachment.accessibilityLabel = accessibleText
|
||||||
|
attachment.isAccessibilityElement = true
|
||||||
|
} else {
|
||||||
|
attachment.isAccessibilityElement = false
|
||||||
|
}
|
||||||
attachment.image = tintColor != nil ? image.withTintColor(tintColor!) : image
|
attachment.image = tintColor != nil ? image.withTintColor(tintColor!) : image
|
||||||
if let frame {
|
if let frame {
|
||||||
attachment.bounds = frame
|
attachment.bounds = frame
|
||||||
|
|||||||
@ -68,9 +68,8 @@ public class TooltipLabelAttribute: ActionLabelAttributeModel, TooltipLaunchable
|
|||||||
addHandler(on: attributedString)
|
addHandler(on: attributedString)
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(id: UUID = UUID(), action: PassthroughSubject<Void, Never> = PassthroughSubject<Void, Never>(), subscriber: AnyCancellable? = nil, surface: Surface, accessibleText: String? = nil, closeButtonText: String = "Close", title: String? = nil, content: String? = nil, contentView: UIView? = nil, presenter: UIView? = nil) {
|
public init(id: UUID = UUID(), subscriber: AnyCancellable? = nil, surface: Surface, accessibleText: String? = nil, closeButtonText: String = "Close", title: String? = nil, content: String? = nil, contentView: UIView? = nil, presenter: UIView? = nil) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.action = action
|
|
||||||
self.subscriber = subscriber
|
self.subscriber = subscriber
|
||||||
self.surface = surface
|
self.surface = surface
|
||||||
self.accessibleText = accessibleText
|
self.accessibleText = accessibleText
|
||||||
|
|||||||
@ -44,25 +44,19 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
|
|||||||
|
|
||||||
open var userInfo = [String: Primitive]()
|
open var userInfo = [String: Primitive]()
|
||||||
|
|
||||||
|
open override var numberOfLines: Int { didSet { setNeedsUpdate() }}
|
||||||
|
|
||||||
|
open override var lineBreakMode: NSLineBreakMode { didSet { setNeedsUpdate() }}
|
||||||
|
|
||||||
override open var text: String? {
|
override open var text: String? {
|
||||||
didSet {
|
didSet {
|
||||||
attributes = nil
|
attributes = nil
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this object is disabled or not
|
|
||||||
open var disabled: Bool {
|
|
||||||
get { !isEnabled }
|
|
||||||
set {
|
|
||||||
if !isEnabled != newValue {
|
|
||||||
isEnabled = !newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether the View is enabled or not.
|
/// Whether the View is enabled or not.
|
||||||
open override var isEnabled: Bool { didSet { setNeedsUpdate(); isUserInteractionEnabled = isEnabled } }
|
open override var isEnabled: Bool { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Configuration Properties
|
// MARK: - Configuration Properties
|
||||||
@ -119,7 +113,7 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
|
|||||||
open func reset() {
|
open func reset() {
|
||||||
shouldUpdateView = false
|
shouldUpdateView = false
|
||||||
surface = .light
|
surface = .light
|
||||||
disabled = false
|
isEnabled = true
|
||||||
attributes = nil
|
attributes = nil
|
||||||
textStyle = .defaultStyle
|
textStyle = .defaultStyle
|
||||||
textPosition = .left
|
textPosition = .left
|
||||||
|
|||||||
@ -19,15 +19,16 @@ open class Line: View {
|
|||||||
case primary, secondary
|
case primary, secondary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum Orientation: String, CaseIterable {
|
||||||
|
case horizontal, vertical
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Public Properties
|
// MARK: - Public Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
open var lineView = UIView().with {
|
|
||||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
}
|
|
||||||
|
|
||||||
open var style: Style = .primary { didSet { setNeedsUpdate() } }
|
open var style: Style = .primary { didSet { setNeedsUpdate() } }
|
||||||
|
open var orientation: Orientation = .horizontal { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Configuration
|
// MARK: - Configuration
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -37,29 +38,37 @@ open class Line: View {
|
|||||||
config.setSurfaceColors(VDSColor.elementsLowcontrastOnlight, VDSColor.elementsLowcontrastOndark, forKey: .secondary)
|
config.setSurfaceColors(VDSColor.elementsLowcontrastOnlight, VDSColor.elementsLowcontrastOndark, forKey: .secondary)
|
||||||
return config.eraseToAnyColorable()
|
return config.eraseToAnyColorable()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Lifecycle
|
// MARK: - Overrides
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
open override func setup() {
|
open override var intrinsicContentSize: CGSize {
|
||||||
super.setup()
|
if orientation == .vertical {
|
||||||
|
return .init(width: 1, height: bounds.height)
|
||||||
addSubview(lineView)
|
} else {
|
||||||
lineView.height(1)
|
return .init(width: bounds.width, height: 1)
|
||||||
lineView.pinToSuperView()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resets to default settings.
|
/// Resets to default settings.
|
||||||
open override func reset() {
|
open override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
style = .primary
|
style = .primary
|
||||||
|
orientation = .horizontal
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func setup() {
|
||||||
|
super.setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function used to make changes to the View based off a change events or from local properties.
|
/// Function used to make changes to the View based off a change events or from local properties.
|
||||||
open override func updateView() {
|
open override func updateView() {
|
||||||
super.updateView()
|
super.updateView()
|
||||||
|
|
||||||
lineView.backgroundColor = lineViewColorConfiguration.getColor(self)
|
backgroundColor = lineViewColorConfiguration.getColor(self)
|
||||||
|
|
||||||
|
invalidateIntrinsicContentSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,14 @@ open class Loader: View {
|
|||||||
open var isActive: Bool = true { didSet { setNeedsUpdate() } }
|
open var isActive: Bool = true { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
/// The Int used to determine the height and width of the Loader
|
/// The Int used to determine the height and width of the Loader
|
||||||
open var size: Int = 40 { didSet { setNeedsUpdate() } }
|
open var size: Int = 40 {
|
||||||
|
didSet {
|
||||||
|
setNeedsUpdate();
|
||||||
|
invalidateIntrinsicContentSize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open override var intrinsicContentSize: CGSize { .init(width: size, height: size) }
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Lifecycle
|
// MARK: - Lifecycle
|
||||||
@ -36,13 +43,15 @@ open class Loader: View {
|
|||||||
super.setup()
|
super.setup()
|
||||||
addSubview(icon)
|
addSubview(icon)
|
||||||
|
|
||||||
|
icon
|
||||||
|
.pinTopGreaterThanOrEqualTo()
|
||||||
|
.pinLeadingGreaterThanOrEqualTo()
|
||||||
|
.pinTrailingLessThanOrEqualTo()
|
||||||
|
.pinBottomLessThanOrEqualTo()
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
icon.centerXAnchor.constraint(equalTo: centerXAnchor),
|
icon.centerXAnchor.constraint(equalTo: centerXAnchor),
|
||||||
icon.centerYAnchor.constraint(equalTo: centerYAnchor),
|
icon.centerYAnchor.constraint(equalTo: centerYAnchor)
|
||||||
icon.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor),
|
|
||||||
icon.trailingAnchor.constraint(lessThanOrEqualTo: trailingAnchor),
|
|
||||||
icon.topAnchor.constraint(greaterThanOrEqualTo: topAnchor),
|
|
||||||
icon.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor)
|
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,7 +43,7 @@ open class RadioBoxGroup: SelectorGroupSelectedHandlerBase<RadioBoxItem> {
|
|||||||
$0.subTextAttributes = model.subTextAttributes
|
$0.subTextAttributes = model.subTextAttributes
|
||||||
$0.subTextRight = model.subText
|
$0.subTextRight = model.subText
|
||||||
$0.subTextRightAttributes = model.subTextAttributes
|
$0.subTextRightAttributes = model.subTextAttributes
|
||||||
$0.disabled = model.disabled
|
$0.isEnabled = !model.disabled
|
||||||
$0.inputId = model.inputId
|
$0.inputId = model.inputId
|
||||||
$0.isSelected = model.selected
|
$0.isSelected = model.selected
|
||||||
}
|
}
|
||||||
@ -106,7 +106,7 @@ open class RadioBoxGroup: SelectorGroupSelectedHandlerBase<RadioBoxItem> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension RadioBoxGroup {
|
extension RadioBoxGroup {
|
||||||
public struct RadioBoxModel: Surfaceable, Initable, Disabling, FormFieldable {
|
public struct RadioBoxModel: Surfaceable, Initable, FormFieldable {
|
||||||
/// Whether this object is disabled or not
|
/// Whether this object is disabled or not
|
||||||
public var disabled: Bool
|
public var disabled: Bool
|
||||||
/// Current Surface and this is used to pass down to child objects that implement Surfacable
|
/// Current Surface and this is used to pass down to child objects that implement Surfacable
|
||||||
|
|||||||
@ -187,14 +187,14 @@ open class RadioBoxItem: Control, Changeable {
|
|||||||
//text label
|
//text label
|
||||||
textLabel.text = text
|
textLabel.text = text
|
||||||
textLabel.surface = surface
|
textLabel.surface = surface
|
||||||
textLabel.disabled = disabled
|
textLabel.isEnabled = isEnabled
|
||||||
textLabel.attributes = textAttributes
|
textLabel.attributes = textAttributes
|
||||||
|
|
||||||
//subText label
|
//subText label
|
||||||
if let subText {
|
if let subText {
|
||||||
subTextLabel.text = subText
|
subTextLabel.text = subText
|
||||||
subTextLabel.surface = surface
|
subTextLabel.surface = surface
|
||||||
subTextLabel.disabled = disabled
|
subTextLabel.isEnabled = isEnabled
|
||||||
subTextLabel.attributes = subTextAttributes
|
subTextLabel.attributes = subTextAttributes
|
||||||
subTextLabel.isHidden = false
|
subTextLabel.isHidden = false
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ open class RadioBoxItem: Control, Changeable {
|
|||||||
if let subTextRight {
|
if let subTextRight {
|
||||||
subTextRightLabel.text = subTextRight
|
subTextRightLabel.text = subTextRight
|
||||||
subTextRightLabel.surface = surface
|
subTextRightLabel.surface = surface
|
||||||
subTextRightLabel.disabled = disabled
|
subTextRightLabel.isEnabled = isEnabled
|
||||||
subTextRightLabel.attributes = subTextRightAttributes
|
subTextRightLabel.attributes = subTextRightAttributes
|
||||||
subTextRightLabel.isHidden = false
|
subTextRightLabel.isHidden = false
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@ open class RadioButtonGroup: SelectorGroupSelectedHandlerBase<RadioButtonItem> {
|
|||||||
if let selectorModels {
|
if let selectorModels {
|
||||||
selectorViews = selectorModels.enumerated().map { index, model in
|
selectorViews = selectorModels.enumerated().map { index, model in
|
||||||
return RadioButtonItem().with {
|
return RadioButtonItem().with {
|
||||||
$0.disabled = model.disabled
|
$0.isEnabled = !model.disabled
|
||||||
$0.surface = model.surface
|
$0.surface = model.surface
|
||||||
$0.inputId = model.inputId
|
$0.inputId = model.inputId
|
||||||
$0.value = model.value
|
$0.value = model.value
|
||||||
@ -114,7 +114,7 @@ open class RadioButtonGroup: SelectorGroupSelectedHandlerBase<RadioButtonItem> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension RadioButtonGroup {
|
extension RadioButtonGroup {
|
||||||
public struct RadioButtonModel: Surfaceable, Disabling, Initable, FormFieldable, Errorable {
|
public struct RadioButtonModel: Surfaceable, Initable, FormFieldable, Errorable {
|
||||||
|
|
||||||
/// Whether this object is disabled or not
|
/// Whether this object is disabled or not
|
||||||
public var disabled: Bool
|
public var disabled: Bool
|
||||||
|
|||||||
@ -176,13 +176,13 @@ open class RadioSwatch: Control {
|
|||||||
var fillColorBackground: UIColor = .clear
|
var fillColorBackground: UIColor = .clear
|
||||||
|
|
||||||
if let fillImage {
|
if let fillImage {
|
||||||
fillView.image = disabled ? fillImage.image(alpha: disabledAlpha) : fillImage
|
fillView.image = !isEnabled ? fillImage.image(alpha: disabledAlpha) : fillImage
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fillView.image = nil
|
fillView.image = nil
|
||||||
if let primary = primaryColor, let secondary = secondaryColor {
|
if let primary = primaryColor, let secondary = secondaryColor {
|
||||||
let firstColor = disabled ? primary.withAlphaComponent(disabledAlpha) : primary
|
let firstColor = !isEnabled ? primary.withAlphaComponent(disabledAlpha) : primary
|
||||||
let secondColor = disabled ? secondary.withAlphaComponent(disabledAlpha) : secondary
|
let secondColor = !isEnabled ? secondary.withAlphaComponent(disabledAlpha) : secondary
|
||||||
let gradient = CAGradientLayer()
|
let gradient = CAGradientLayer()
|
||||||
gradientLayer = gradient
|
gradientLayer = gradient
|
||||||
gradient.frame = fillView.bounds
|
gradient.frame = fillView.bounds
|
||||||
@ -195,7 +195,7 @@ open class RadioSwatch: Control {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fillView.backgroundColor = disabled ? fillColorBackground.withAlphaComponent(disabledAlpha) : fillColorBackground
|
fillView.backgroundColor = !isEnabled ? fillColorBackground.withAlphaComponent(disabledAlpha) : fillColorBackground
|
||||||
fillView.layer.borderColor = fillBorderColor.cgColor
|
fillView.layer.borderColor = fillBorderColor.cgColor
|
||||||
fillView.layer.cornerRadius = fillView.bounds.width * 0.5
|
fillView.layer.cornerRadius = fillView.bounds.width * 0.5
|
||||||
fillView.layer.borderWidth = selectorBorderWidth
|
fillView.layer.borderWidth = selectorBorderWidth
|
||||||
|
|||||||
@ -32,7 +32,7 @@ open class RadioSwatchGroup: SelectorGroupSelectedHandlerBase<RadioSwatch>, UICo
|
|||||||
$0.primaryColor = model.primaryColor
|
$0.primaryColor = model.primaryColor
|
||||||
$0.secondaryColor = model.secondaryColor
|
$0.secondaryColor = model.secondaryColor
|
||||||
$0.strikethrough = model.strikethrough
|
$0.strikethrough = model.strikethrough
|
||||||
$0.disabled = model.disabled
|
$0.isEnabled = !model.disabled
|
||||||
$0.surface = model.surface
|
$0.surface = model.surface
|
||||||
$0.inputId = model.inputId
|
$0.inputId = model.inputId
|
||||||
$0.value = model.value
|
$0.value = model.value
|
||||||
@ -71,15 +71,15 @@ open class RadioSwatchGroup: SelectorGroupSelectedHandlerBase<RadioSwatch>, UICo
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Overrides
|
// MARK: - Overrides
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
/// Whether this object is disabled or not
|
/// Whether this object is disabled or not
|
||||||
override public var disabled: Bool {
|
override public var isEnabled: Bool {
|
||||||
didSet {
|
didSet {
|
||||||
for selector in selectorViews {
|
selectorViews.forEach { $0.isEnabled = isEnabled }
|
||||||
selector.disabled = disabled
|
|
||||||
}
|
|
||||||
collectionView.reloadData()
|
collectionView.reloadData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Current Surface and this is used to pass down to child objects that implement Surfacable
|
/// Current Surface and this is used to pass down to child objects that implement Surfacable
|
||||||
override public var surface: Surface {
|
override public var surface: Surface {
|
||||||
didSet {
|
didSet {
|
||||||
@ -132,7 +132,7 @@ open class RadioSwatchGroup: SelectorGroupSelectedHandlerBase<RadioSwatch>, UICo
|
|||||||
label.textStyle = .bodySmall
|
label.textStyle = .bodySmall
|
||||||
label.text = selectedHandler?.text ?? " "
|
label.text = selectedHandler?.text ?? " "
|
||||||
label.surface = surface
|
label.surface = surface
|
||||||
label.disabled = disabled
|
label.isEnabled = isEnabled
|
||||||
collectionView.reloadData()
|
collectionView.reloadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ open class RadioSwatchGroup: SelectorGroupSelectedHandlerBase<RadioSwatch>, UICo
|
|||||||
// MARK: - UICollectionViewDelegate
|
// MARK: - UICollectionViewDelegate
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
open func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
|
open func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
|
||||||
return !selectorViews[indexPath.row].disabled
|
return selectorViews[indexPath.row].isEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||||
@ -193,7 +193,7 @@ open class RadioSwatchGroup: SelectorGroupSelectedHandlerBase<RadioSwatch>, UICo
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension RadioSwatchGroup {
|
extension RadioSwatchGroup {
|
||||||
public struct RadioSwatchModel: Surfaceable, Disabling, Initable {
|
public struct RadioSwatchModel: Surfaceable, Initable {
|
||||||
/// Whether this object is disabled or not
|
/// Whether this object is disabled or not
|
||||||
public var disabled: Bool = false
|
public var disabled: Bool = false
|
||||||
/// Current Surface and this is used to pass down to child objects that implement Surfacable
|
/// Current Surface and this is used to pass down to child objects that implement Surfacable
|
||||||
|
|||||||
@ -95,12 +95,11 @@ extension Tabs {
|
|||||||
|
|
||||||
private let layoutGuide = UILayoutGuide()
|
private let layoutGuide = UILayoutGuide()
|
||||||
|
|
||||||
private var widthConstraint: NSLayoutConstraint? {
|
private func updateWidth() {
|
||||||
if let width, orientation == .vertical {
|
labelWidthConstraint?.isActive = false
|
||||||
return layoutGuide.widthAnchor.constraint(equalToConstant: width)
|
guard let width, width > minWidth else { return }
|
||||||
} else {
|
labelWidthConstraint?.constant = width
|
||||||
return layoutGuide.widthAnchor.constraint(greaterThanOrEqualToConstant: minWidth)
|
labelWidthConstraint?.isActive = true
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -124,27 +123,26 @@ extension Tabs {
|
|||||||
|
|
||||||
open override func setup() {
|
open override func setup() {
|
||||||
super.setup()
|
super.setup()
|
||||||
|
|
||||||
|
canHighlight = false
|
||||||
|
|
||||||
addLayoutGuide(layoutGuide)
|
addLayoutGuide(layoutGuide)
|
||||||
addSubview(label)
|
addSubview(label)
|
||||||
accessibilityTraits = .button
|
accessibilityTraits = .button
|
||||||
isAccessibilityElement = true
|
isAccessibilityElement = true
|
||||||
|
|
||||||
//activate the constraints
|
//pin layoutguide
|
||||||
NSLayoutConstraint.activate([layoutGuide.topAnchor.constraint(equalTo: topAnchor),
|
layoutGuide.pinToSuperView()
|
||||||
layoutGuide.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
||||||
layoutGuide.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
||||||
layoutGuide.trailingAnchor.constraint(equalTo: trailingAnchor)])
|
|
||||||
|
|
||||||
|
//pin trailing
|
||||||
label.pinTrailing(layoutGuide.trailingAnchor)
|
label.pinTrailing(layoutGuide.trailingAnchor)
|
||||||
|
|
||||||
labelTopConstraint = label.topAnchor.constraint(equalTo: layoutGuide.topAnchor)
|
//setup constraints
|
||||||
labelTopConstraint?.isActive = true
|
labelWidthConstraint = layoutGuide.width(constant: 0).with { $0.isActive = false }
|
||||||
|
layoutGuide.widthGreaterThanEqualTo(minWidth)
|
||||||
labelBottomConstraint = label.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor)
|
labelTopConstraint = label.pinTop(anchor: layoutGuide.topAnchor)
|
||||||
labelBottomConstraint?.isActive = true
|
labelLeadingConstraint = label.pinLeading(anchor: layoutGuide.leadingAnchor)
|
||||||
|
labelBottomConstraint = label.pinBottom(anchor: layoutGuide.bottomAnchor, priority: .defaultHigh)
|
||||||
labelLeadingConstraint = label.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor)
|
|
||||||
labelLeadingConstraint?.isActive = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function used to make changes to the View based off a change events or from local properties.
|
/// Function used to make changes to the View based off a change events or from local properties.
|
||||||
@ -156,9 +154,7 @@ extension Tabs {
|
|||||||
accessibilityIdentifier = "VDSTab:\(text)"
|
accessibilityIdentifier = "VDSTab:\(text)"
|
||||||
|
|
||||||
//constaints
|
//constaints
|
||||||
labelWidthConstraint?.isActive = false
|
updateWidth()
|
||||||
labelWidthConstraint = widthConstraint
|
|
||||||
labelWidthConstraint?.isActive = true
|
|
||||||
labelLeadingConstraint?.constant = leadingSpace
|
labelLeadingConstraint?.constant = leadingSpace
|
||||||
labelTopConstraint?.constant = otherSpace
|
labelTopConstraint?.constant = otherSpace
|
||||||
labelBottomConstraint?.constant = -otherSpace
|
labelBottomConstraint?.constant = -otherSpace
|
||||||
@ -169,7 +165,6 @@ extension Tabs {
|
|||||||
label.textStyle = textStyle
|
label.textStyle = textStyle
|
||||||
label.textPosition = textPosition
|
label.textPosition = textPosition
|
||||||
label.textColorConfiguration = textColorConfiguration.eraseToAnyColorable()
|
label.textColorConfiguration = textColorConfiguration.eraseToAnyColorable()
|
||||||
|
|
||||||
setNeedsLayout()
|
setNeedsLayout()
|
||||||
layoutIfNeeded()
|
layoutIfNeeded()
|
||||||
|
|
||||||
|
|||||||
@ -144,6 +144,10 @@ open class Tabs: View {
|
|||||||
orientation == .horizontal && fillContainer ? .center : .left
|
orientation == .horizontal && fillContainer ? .center : .left
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var applyOverflow: Bool {
|
||||||
|
orientation == .horizontal && overflow == .scroll && !fillContainer
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializers
|
// MARK: - Initializers
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -187,20 +191,20 @@ open class Tabs: View {
|
|||||||
|
|
||||||
contentView.heightAnchor.constraint(equalTo: scrollView.heightAnchor).isActive = true
|
contentView.heightAnchor.constraint(equalTo: scrollView.heightAnchor).isActive = true
|
||||||
|
|
||||||
borderlineViewWidthConstraint = borderlineView.widthAnchor.constraint(equalToConstant: 0)
|
borderlineViewWidthConstraint = borderlineView.width(constant: 0)
|
||||||
borderlineViewHeightConstraint = borderlineView.heightAnchor.constraint(equalToConstant: 0)
|
borderlineViewHeightConstraint = borderlineView.height(constant: 0)
|
||||||
|
|
||||||
borderlineViewLeadingConstraint = borderlineView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor)
|
borderlineViewLeadingConstraint = borderlineView.pinLeading(anchor: contentView.leadingAnchor)
|
||||||
borderlineViewTrailingConstraint = borderlineView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor)
|
borderlineViewTrailingConstraint = borderlineView.pinTrailing(anchor: contentView.trailingAnchor)
|
||||||
borderlineViewTopConstraint = borderlineView.topAnchor.constraint(equalTo: contentView.topAnchor)
|
borderlineViewTopConstraint = borderlineView.pinTop(anchor: contentView.topAnchor)
|
||||||
borderlineViewBottomConstraint = borderlineView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
|
borderlineViewBottomConstraint = borderlineView.pinBottom(anchor: contentView.bottomAnchor)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function used to make changes to the View based off a change events or from local properties.
|
/// Function used to make changes to the View based off a change events or from local properties.
|
||||||
open override func updateView() {
|
open override func updateView() {
|
||||||
super.updateView()
|
super.updateView()
|
||||||
|
|
||||||
updateStackView()
|
updateStackView()
|
||||||
updateTabs()
|
updateTabs()
|
||||||
updateContentView()
|
updateContentView()
|
||||||
@ -258,7 +262,9 @@ open class Tabs: View {
|
|||||||
|
|
||||||
/// Updates the Tab individual views from local properties.
|
/// Updates the Tab individual views from local properties.
|
||||||
private func updateTabs() {
|
private func updateTabs() {
|
||||||
|
let numberOfLines = applyOverflow ? 1 : 0
|
||||||
for (index, tabItem) in tabViews.enumerated() {
|
for (index, tabItem) in tabViews.enumerated() {
|
||||||
|
tabItem.label.numberOfLines = numberOfLines
|
||||||
tabItem.size = size
|
tabItem.size = size
|
||||||
tabItem.isSelected = selectedIndex == index
|
tabItem.isSelected = selectedIndex == index
|
||||||
tabItem.index = index
|
tabItem.index = index
|
||||||
@ -277,10 +283,10 @@ open class Tabs: View {
|
|||||||
contentViewWidthConstraint?.isActive = false
|
contentViewWidthConstraint?.isActive = false
|
||||||
|
|
||||||
// Apply overflow
|
// Apply overflow
|
||||||
if orientation == .horizontal && overflow == .scroll && !fillContainer {
|
if applyOverflow {
|
||||||
let contentWidth = tabStackView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).width
|
|
||||||
contentViewWidthConstraint = nil
|
contentViewWidthConstraint = nil
|
||||||
scrollView.contentSize = CGSize(width: contentWidth, height: scrollView.bounds.height)
|
scrollView.contentSize = CGSize(width: tabStackView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).width,
|
||||||
|
height: scrollView.bounds.height)
|
||||||
} else {
|
} else {
|
||||||
contentViewWidthConstraint = contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
|
contentViewWidthConstraint = contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
|
||||||
scrollView.contentSize = bounds.size
|
scrollView.contentSize = bounds.size
|
||||||
@ -294,6 +300,11 @@ open class Tabs: View {
|
|||||||
scrollToSelectedIndex(animated: true)
|
scrollToSelectedIndex(animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override func layoutSubviews() {
|
||||||
|
super.layoutSubviews()
|
||||||
|
updateContentView()
|
||||||
|
}
|
||||||
|
|
||||||
//update layout for borderline
|
//update layout for borderline
|
||||||
private func updateBorderline() {
|
private func updateBorderline() {
|
||||||
//borderLine
|
//borderLine
|
||||||
|
|||||||
@ -132,12 +132,7 @@ open class TabsContainer: View {
|
|||||||
stackView.addArrangedSubview(tabMenu)
|
stackView.addArrangedSubview(tabMenu)
|
||||||
stackView.addArrangedSubview(contentView)
|
stackView.addArrangedSubview(contentView)
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
tabMenuLayoutGuide.pinToSuperView()
|
||||||
tabMenuLayoutGuide.topAnchor.constraint(equalTo: topAnchor),
|
|
||||||
tabMenuLayoutGuide.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
||||||
tabMenuLayoutGuide.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
||||||
tabMenuLayoutGuide.trailingAnchor.constraint(equalTo: trailingAnchor)
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function used to make changes to the View based off a change events or from local properties.
|
/// Function used to make changes to the View based off a change events or from local properties.
|
||||||
@ -168,7 +163,7 @@ open class TabsContainer: View {
|
|||||||
contentViewWidthConstraint?.isActive = true
|
contentViewWidthConstraint?.isActive = true
|
||||||
|
|
||||||
tabMenu.surface = surface
|
tabMenu.surface = surface
|
||||||
tabMenu.disabled = disabled
|
tabMenu.isEnabled = isEnabled
|
||||||
tabMenu.orientation = orientation
|
tabMenu.orientation = orientation
|
||||||
tabMenu.borderLine = borderLine
|
tabMenu.borderLine = borderLine
|
||||||
tabMenu.fillContainer = fillContainer
|
tabMenu.fillContainer = fillContainer
|
||||||
|
|||||||
@ -283,7 +283,7 @@ open class EntryField: Control, Changeable {
|
|||||||
|
|
||||||
//dealing with the "Optional" addition to the text
|
//dealing with the "Optional" addition to the text
|
||||||
if let oldText = updatedLabelText, !required, !oldText.hasSuffix("Optional") {
|
if let oldText = updatedLabelText, !required, !oldText.hasSuffix("Optional") {
|
||||||
if !disabled {
|
if isEnabled {
|
||||||
let optionColorAttr = ColorLabelAttribute(location: oldText.count + 2,
|
let optionColorAttr = ColorLabelAttribute(location: oldText.count + 2,
|
||||||
length: 8,
|
length: 8,
|
||||||
color: VDSColor.elementsSecondaryOnlight)
|
color: VDSColor.elementsSecondaryOnlight)
|
||||||
@ -301,20 +301,19 @@ open class EntryField: Control, Changeable {
|
|||||||
titleLabel.text = updatedLabelText
|
titleLabel.text = updatedLabelText
|
||||||
titleLabel.attributes = attributes
|
titleLabel.attributes = attributes
|
||||||
titleLabel.surface = surface
|
titleLabel.surface = surface
|
||||||
titleLabel.disabled = disabled
|
titleLabel.isEnabled = isEnabled
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open func updateErrorLabel(){
|
open func updateErrorLabel(){
|
||||||
if showError, let errorText {
|
if showError, let errorText {
|
||||||
errorLabel.text = errorText
|
errorLabel.text = errorText
|
||||||
errorLabel.surface = surface
|
errorLabel.surface = surface
|
||||||
errorLabel.disabled = disabled
|
errorLabel.isEnabled = isEnabled
|
||||||
errorLabel.isHidden = false
|
errorLabel.isHidden = false
|
||||||
icon.name = .error
|
icon.name = .error
|
||||||
icon.color = VDSColor.paletteBlack
|
icon.color = VDSColor.paletteBlack
|
||||||
icon.surface = surface
|
icon.surface = surface
|
||||||
icon.isHidden = disabled
|
icon.isHidden = !isEnabled
|
||||||
} else {
|
} else {
|
||||||
icon.isHidden = true
|
icon.isHidden = true
|
||||||
errorLabel.isHidden = true
|
errorLabel.isHidden = true
|
||||||
@ -326,7 +325,7 @@ open class EntryField: Control, Changeable {
|
|||||||
if let helperText {
|
if let helperText {
|
||||||
helperLabel.text = helperText
|
helperLabel.text = helperText
|
||||||
helperLabel.surface = surface
|
helperLabel.surface = surface
|
||||||
helperLabel.disabled = disabled
|
helperLabel.isEnabled = isEnabled
|
||||||
helperLabel.isHidden = false
|
helperLabel.isHidden = false
|
||||||
} else {
|
} else {
|
||||||
helperLabel.isHidden = true
|
helperLabel.isHidden = true
|
||||||
|
|||||||
@ -165,7 +165,7 @@ open class InputField: EntryField, UITextFieldDelegate {
|
|||||||
open override func updateView() {
|
open override func updateView() {
|
||||||
super.updateView()
|
super.updateView()
|
||||||
|
|
||||||
textField.isEnabled = !disabled
|
textField.isEnabled = isEnabled
|
||||||
textField.textColor = textFieldTextColorConfiguration.getColor(self)
|
textField.textColor = textFieldTextColorConfiguration.getColor(self)
|
||||||
|
|
||||||
//show error or success
|
//show error or success
|
||||||
@ -175,13 +175,13 @@ open class InputField: EntryField, UITextFieldDelegate {
|
|||||||
} else if showSuccess, let successText {
|
} else if showSuccess, let successText {
|
||||||
successLabel.text = successText
|
successLabel.text = successText
|
||||||
successLabel.surface = surface
|
successLabel.surface = surface
|
||||||
successLabel.disabled = disabled
|
successLabel.isEnabled = isEnabled
|
||||||
successLabel.isHidden = false
|
successLabel.isHidden = false
|
||||||
errorLabel.isHidden = true
|
errorLabel.isHidden = true
|
||||||
icon.name = .checkmarkAlt
|
icon.name = .checkmarkAlt
|
||||||
icon.color = VDSColor.paletteBlack
|
icon.color = VDSColor.paletteBlack
|
||||||
icon.surface = surface
|
icon.surface = surface
|
||||||
icon.isHidden = disabled
|
icon.isHidden = !isEnabled
|
||||||
} else {
|
} else {
|
||||||
icon.isHidden = true
|
icon.isHidden = true
|
||||||
successLabel.isHidden = true
|
successLabel.isHidden = true
|
||||||
|
|||||||
@ -95,7 +95,7 @@ open class TextArea: EntryField {
|
|||||||
open override func updateView() {
|
open override func updateView() {
|
||||||
super.updateView()
|
super.updateView()
|
||||||
|
|
||||||
textView.isEditable = !disabled
|
textView.isEditable = isEnabled
|
||||||
textView.textColor = textViewTextColorConfiguration.getColor(self)
|
textView.textColor = textViewTextColorConfiguration.getColor(self)
|
||||||
|
|
||||||
//set the width constraints
|
//set the width constraints
|
||||||
|
|||||||
@ -168,14 +168,10 @@ open class TileContainer: Control {
|
|||||||
|
|
||||||
containerView.backgroundColor = .clear
|
containerView.backgroundColor = .clear
|
||||||
|
|
||||||
containerTopConstraint = containerView.topAnchor.constraint(equalTo: topAnchor, constant: padding.value)
|
containerTopConstraint = containerView.pinTop(anchor: topAnchor, constant: padding.value)
|
||||||
containerTopConstraint?.isActive = true
|
containerBottomConstraint = containerView.pinBottom(anchor: bottomAnchor, constant: padding.value)
|
||||||
containerBottomConstraint = containerView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: padding.value)
|
containerLeadingConstraint = containerView.pinLeading(anchor: leadingAnchor, constant: padding.value)
|
||||||
containerBottomConstraint?.isActive = true
|
containerTrailingConstraint = containerView.pinTrailing(anchor: trailingAnchor, constant: padding.value)
|
||||||
containerLeadingConstraint = containerView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding.value)
|
|
||||||
containerLeadingConstraint?.isActive = true
|
|
||||||
containerTrailingConstraint = containerView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: padding.value)
|
|
||||||
containerTrailingConstraint?.isActive = true
|
|
||||||
|
|
||||||
highlightView.pinToSuperView()
|
highlightView.pinToSuperView()
|
||||||
highlightView.isHidden = true
|
highlightView.isHidden = true
|
||||||
|
|||||||
@ -43,7 +43,7 @@ open class TitleLockup: View {
|
|||||||
private var stackView = UIStackView().with {
|
private var stackView = UIStackView().with {
|
||||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||||
$0.axis = .vertical
|
$0.axis = .vertical
|
||||||
$0.distribution = .fill
|
$0.distribution = .fillProportionally
|
||||||
}
|
}
|
||||||
|
|
||||||
private var otherStandardStyle: OtherStandardStyle {
|
private var otherStandardStyle: OtherStandardStyle {
|
||||||
@ -269,8 +269,11 @@ open class TitleLockup: View {
|
|||||||
stackView.addArrangedSubview(subTitleLabel)
|
stackView.addArrangedSubview(subTitleLabel)
|
||||||
|
|
||||||
//pin stackview to edges
|
//pin stackview to edges
|
||||||
stackView.pinToSuperView()
|
stackView
|
||||||
|
.pinTop()
|
||||||
|
.pinLeading()
|
||||||
|
.pinTrailing()
|
||||||
|
.pinBottom(0, .defaultHigh)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resets to default settings.
|
/// Resets to default settings.
|
||||||
@ -311,7 +314,6 @@ open class TitleLockup: View {
|
|||||||
eyebrowLabel.attributes = eyebrowModel.textAttributes
|
eyebrowLabel.attributes = eyebrowModel.textAttributes
|
||||||
eyebrowLabel.numberOfLines = eyebrowModel.numberOfLines
|
eyebrowLabel.numberOfLines = eyebrowModel.numberOfLines
|
||||||
eyebrowLabel.surface = surface
|
eyebrowLabel.surface = surface
|
||||||
|
|
||||||
//When uniform size is true
|
//When uniform size is true
|
||||||
if let titleModel, isUniformSize {
|
if let titleModel, isUniformSize {
|
||||||
if titleModel.isBold {
|
if titleModel.isBold {
|
||||||
@ -329,8 +331,6 @@ open class TitleLockup: View {
|
|||||||
eyebrowLabel.textColorConfiguration = textColorPrimaryConfiguration
|
eyebrowLabel.textColorConfiguration = textColorPrimaryConfiguration
|
||||||
eyebrowLabel.textStyle = eyebrowModel.isBold ? otherStandardStyle.value.bold : otherStandardStyle.value.regular
|
eyebrowLabel.textStyle = eyebrowModel.isBold ? otherStandardStyle.value.bold : otherStandardStyle.value.regular
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
eyebrowLabel.reset()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let titleModel, !titleModel.text.isEmpty {
|
if let titleModel, !titleModel.text.isEmpty {
|
||||||
@ -341,8 +341,6 @@ open class TitleLockup: View {
|
|||||||
titleLabel.attributes = titleModel.textAttributes
|
titleLabel.attributes = titleModel.textAttributes
|
||||||
titleLabel.numberOfLines = titleModel.numberOfLines
|
titleLabel.numberOfLines = titleModel.numberOfLines
|
||||||
titleLabel.surface = surface
|
titleLabel.surface = surface
|
||||||
} else {
|
|
||||||
titleLabel.reset()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let subTitleModel, !subTitleModel.text.isEmpty {
|
if let subTitleModel, !subTitleModel.text.isEmpty {
|
||||||
@ -354,8 +352,6 @@ open class TitleLockup: View {
|
|||||||
subTitleLabel.attributes = subTitleModel.textAttributes
|
subTitleLabel.attributes = subTitleModel.textAttributes
|
||||||
subTitleLabel.numberOfLines = subTitleModel.numberOfLines
|
subTitleLabel.numberOfLines = subTitleModel.numberOfLines
|
||||||
subTitleLabel.surface = surface
|
subTitleLabel.surface = surface
|
||||||
} else {
|
|
||||||
subTitleLabel.reset()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//if both first 2 rows not empty set spacing
|
//if both first 2 rows not empty set spacing
|
||||||
@ -376,5 +372,5 @@ open class TitleLockup: View {
|
|||||||
eyebrowLabel.isHidden = eyebrowTextIsEmpty
|
eyebrowLabel.isHidden = eyebrowTextIsEmpty
|
||||||
titleLabel.isHidden = titleTextIsEmpty
|
titleLabel.isHidden = titleTextIsEmpty
|
||||||
subTitleLabel.isHidden = subTitleTextIsEmpty
|
subTitleLabel.isHidden = subTitleTextIsEmpty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -86,6 +86,7 @@ open class Toggle: Control, Changeable {
|
|||||||
open var toggleView = ToggleView().with {
|
open var toggleView = ToggleView().with {
|
||||||
$0.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
|
$0.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
|
||||||
$0.isUserInteractionEnabled = false
|
$0.isUserInteractionEnabled = false
|
||||||
|
$0.isAccessibilityElement = false
|
||||||
}
|
}
|
||||||
|
|
||||||
open var label = Label().with {
|
open var label = Label().with {
|
||||||
@ -140,34 +141,35 @@ open class Toggle: Control, Changeable {
|
|||||||
|
|
||||||
open override func setup() {
|
open override func setup() {
|
||||||
super.setup()
|
super.setup()
|
||||||
|
|
||||||
|
canHighlight = false
|
||||||
isAccessibilityElement = true
|
isAccessibilityElement = true
|
||||||
accessibilityTraits = .button
|
accessibilityTraits = .button
|
||||||
addSubview(label)
|
addSubview(label)
|
||||||
addSubview(toggleView)
|
addSubview(toggleView)
|
||||||
|
|
||||||
let heightEqual = heightAnchor.constraint(equalToConstant: toggleContainerSize.height)
|
label.widthLessThanEqualTo(labelMaxWidth)
|
||||||
heightEqual.priority = .defaultLow
|
|
||||||
|
|
||||||
let heightGreater = heightAnchor.constraint(greaterThanOrEqualToConstant: toggleContainerSize.height)
|
|
||||||
heightGreater.priority = .defaultHigh
|
|
||||||
|
|
||||||
// Set up initial constraints for label and switch
|
// Set up initial constraints for label and switch
|
||||||
toggleView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
|
toggleView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
|
||||||
|
|
||||||
labelConstraints = [
|
labelConstraints = [
|
||||||
heightEqual, heightGreater,
|
height(constant: toggleContainerSize.height, priority: .defaultLow),
|
||||||
label.widthAnchor.constraint(lessThanOrEqualToConstant: labelMaxWidth),
|
heightGreaterThanEqualTo(constant: toggleContainerSize.height, priority: .defaultHigh),
|
||||||
label.topAnchor.constraint(equalTo: topAnchor),
|
label.topAnchor.constraint(equalTo: topAnchor),
|
||||||
label.bottomAnchor.constraint(equalTo: bottomAnchor),
|
label.bottomAnchor.constraint(equalTo: bottomAnchor),
|
||||||
]
|
]
|
||||||
|
|
||||||
leftConstraints = [
|
leftConstraints = [
|
||||||
toggleView.leadingAnchor.constraint(equalTo: label.trailingAnchor, constant: spacingBetween)
|
toggleView.leadingAnchor.constraint(equalTo: label.trailingAnchor, constant: spacingBetween),
|
||||||
|
label.leadingAnchor.constraint(equalTo: leadingAnchor),
|
||||||
|
toggleView.trailingAnchor.constraint(equalTo: trailingAnchor)
|
||||||
]
|
]
|
||||||
|
|
||||||
rightConstraints = [
|
rightConstraints = [
|
||||||
label.leadingAnchor.constraint(equalTo: toggleView.trailingAnchor, constant: spacingBetween)
|
toggleView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
||||||
|
label.leadingAnchor.constraint(equalTo: toggleView.trailingAnchor, constant: spacingBetween),
|
||||||
|
label.trailingAnchor.constraint(lessThanOrEqualTo: trailingAnchor)
|
||||||
]
|
]
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -177,6 +179,7 @@ open class Toggle: Control, Changeable {
|
|||||||
super.reset()
|
super.reset()
|
||||||
shouldUpdateView = false
|
shouldUpdateView = false
|
||||||
label.reset()
|
label.reset()
|
||||||
|
isEnabled = true
|
||||||
isOn = false
|
isOn = false
|
||||||
isAnimated = true
|
isAnimated = true
|
||||||
showText = false
|
showText = false
|
||||||
@ -197,7 +200,7 @@ open class Toggle: Control, Changeable {
|
|||||||
|
|
||||||
updateLabel()
|
updateLabel()
|
||||||
toggleView.surface = surface
|
toggleView.surface = surface
|
||||||
toggleView.disabled = disabled
|
toggleView.isEnabled = isEnabled
|
||||||
toggleView.isOn = isOn
|
toggleView.isOn = isOn
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,6 +226,7 @@ open class Toggle: Control, Changeable {
|
|||||||
private var showLabel: Bool {
|
private var showLabel: Bool {
|
||||||
showText && !statusText.isEmpty
|
showText && !statusText.isEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateLabel() {
|
private func updateLabel() {
|
||||||
label.isHidden = !showLabel
|
label.isHidden = !showLabel
|
||||||
|
|
||||||
@ -231,7 +235,7 @@ open class Toggle: Control, Changeable {
|
|||||||
label.textStyle = textStyle
|
label.textStyle = textStyle
|
||||||
label.text = statusText
|
label.text = statusText
|
||||||
label.surface = surface
|
label.surface = surface
|
||||||
label.disabled = disabled
|
label.isEnabled = isEnabled
|
||||||
switch textPosition {
|
switch textPosition {
|
||||||
case .left:
|
case .left:
|
||||||
NSLayoutConstraint.deactivate(rightConstraints)
|
NSLayoutConstraint.deactivate(rightConstraints)
|
||||||
@ -246,7 +250,6 @@ open class Toggle: Control, Changeable {
|
|||||||
NSLayoutConstraint.deactivate(rightConstraints)
|
NSLayoutConstraint.deactivate(rightConstraints)
|
||||||
NSLayoutConstraint.deactivate(labelConstraints)
|
NSLayoutConstraint.deactivate(labelConstraints)
|
||||||
}
|
}
|
||||||
invalidateIntrinsicContentSize()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -117,19 +117,22 @@ open class ToggleView: Control, Changeable {
|
|||||||
|
|
||||||
isAccessibilityElement = true
|
isAccessibilityElement = true
|
||||||
accessibilityTraits = .button
|
accessibilityTraits = .button
|
||||||
|
|
||||||
addSubview(toggleView)
|
addSubview(toggleView)
|
||||||
toggleView.addSubview(knobView)
|
toggleView.addSubview(knobView)
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
toggleView.pinToSuperView()
|
||||||
toggleView.widthAnchor.constraint(equalToConstant: toggleSize.width),
|
|
||||||
toggleView.heightAnchor.constraint(equalToConstant: toggleSize.height),
|
toggleView
|
||||||
toggleView.centerYAnchor.constraint(equalTo: centerYAnchor),
|
.width(toggleSize.width)
|
||||||
knobView.heightAnchor.constraint(equalToConstant: knobSize.height),
|
.height(toggleSize.height)
|
||||||
knobView.widthAnchor.constraint(equalToConstant: knobSize.width),
|
|
||||||
knobView.centerYAnchor.constraint(equalTo: toggleView.centerYAnchor),
|
knobView
|
||||||
knobView.topAnchor.constraint(greaterThanOrEqualTo: toggleView.topAnchor)
|
.pinTopGreaterThanOrEqualTo()
|
||||||
])
|
.width(knobSize.width)
|
||||||
|
.height(knobSize.height)
|
||||||
|
|
||||||
|
knobView.centerYAnchor.constraint(equalTo: toggleView.centerYAnchor).activate()
|
||||||
|
|
||||||
// Set cornerRadius
|
// Set cornerRadius
|
||||||
knobView.layer.cornerRadius = knobSize.height / 2.0
|
knobView.layer.cornerRadius = knobSize.height / 2.0
|
||||||
@ -145,20 +148,7 @@ open class ToggleView: Control, Changeable {
|
|||||||
// Update shadow layers frames to match the view's bounds
|
// Update shadow layers frames to match the view's bounds
|
||||||
knobView.layer.insertSublayer(shadowLayer1, at: 0)
|
knobView.layer.insertSublayer(shadowLayer1, at: 0)
|
||||||
knobView.layer.insertSublayer(shadowLayer2, at: 0)
|
knobView.layer.insertSublayer(shadowLayer2, at: 0)
|
||||||
|
|
||||||
let shadowColor = VDSColor.paletteBlack.cgColor
|
|
||||||
shadowLayer1.cornerRadius = knobView.layer.cornerRadius
|
|
||||||
shadowLayer1.shadowColor = shadowColor
|
|
||||||
shadowLayer1.shadowOpacity = 0.24
|
|
||||||
shadowLayer1.shadowOffset = .init(width: 0, height: 1)
|
|
||||||
shadowLayer1.shadowRadius = 5.0
|
|
||||||
|
|
||||||
shadowLayer2.cornerRadius = knobView.layer.cornerRadius
|
|
||||||
shadowLayer2.shadowColor = shadowColor
|
|
||||||
shadowLayer2.shadowOpacity = 0.08
|
|
||||||
shadowLayer2.shadowOffset = .init(width: 0, height: 2)
|
|
||||||
shadowLayer2.shadowRadius = 2.0
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resets to default settings.
|
/// Resets to default settings.
|
||||||
@ -225,7 +215,7 @@ open class ToggleView: Control, Changeable {
|
|||||||
shadowLayer1.backgroundColor = knobColor.cgColor
|
shadowLayer1.backgroundColor = knobColor.cgColor
|
||||||
shadowLayer2.backgroundColor = knobColor.cgColor
|
shadowLayer2.backgroundColor = knobColor.cgColor
|
||||||
|
|
||||||
if disabled || !isAnimated {
|
if !isEnabled || !isAnimated {
|
||||||
toggleView.backgroundColor = toggleColor
|
toggleView.backgroundColor = toggleColor
|
||||||
knobView.backgroundColor = knobColor
|
knobView.backgroundColor = knobColor
|
||||||
constrainKnob()
|
constrainKnob()
|
||||||
@ -246,6 +236,19 @@ open class ToggleView: Control, Changeable {
|
|||||||
|
|
||||||
shadowLayer1.frame = knobView.bounds
|
shadowLayer1.frame = knobView.bounds
|
||||||
shadowLayer2.frame = knobView.bounds
|
shadowLayer2.frame = knobView.bounds
|
||||||
|
|
||||||
|
let shadowColor = isEnabled ? VDSColor.paletteBlack.cgColor : VDSColor.paletteGray95.cgColor
|
||||||
|
shadowLayer1.cornerRadius = knobView.layer.cornerRadius
|
||||||
|
shadowLayer1.shadowColor = shadowColor
|
||||||
|
shadowLayer1.shadowOpacity = isEnabled ? 0.24 : 0.1
|
||||||
|
shadowLayer1.shadowOffset = .init(width: 0, height: 1)
|
||||||
|
shadowLayer1.shadowRadius = isEnabled ? 5.0 : 10.0
|
||||||
|
|
||||||
|
shadowLayer2.cornerRadius = knobView.layer.cornerRadius
|
||||||
|
shadowLayer2.shadowColor = shadowColor
|
||||||
|
shadowLayer2.shadowOpacity = isEnabled ? 0.08 : 0.04
|
||||||
|
shadowLayer2.shadowOffset = .init(width: 0, height: 2)
|
||||||
|
shadowLayer2.shadowRadius = 2.0
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,10 +38,10 @@ open class Tooltip: Control, TooltipLaunchable {
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Public Properties
|
// MARK: - Public Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
open var imageView = UIImageView().with {
|
open var icon = Icon().with {
|
||||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
$0.name = .info
|
||||||
$0.contentMode = .scaleAspectFill
|
$0.size = .small
|
||||||
$0.clipsToBounds = true
|
$0.isUserInteractionEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
open var closeButtonText: String = "Close" { didSet { setNeedsUpdate() }}
|
open var closeButtonText: String = "Close" { didSet { setNeedsUpdate() }}
|
||||||
@ -111,18 +111,8 @@ open class Tooltip: Control, TooltipLaunchable {
|
|||||||
open override func setup() {
|
open override func setup() {
|
||||||
super.setup()
|
super.setup()
|
||||||
|
|
||||||
if let image = BundleManager.shared.image(for: "info") {
|
addSubview(icon)
|
||||||
infoImage = image
|
icon.pinToSuperView()
|
||||||
}
|
|
||||||
|
|
||||||
addSubview(imageView)
|
|
||||||
|
|
||||||
imageView.pinToSuperView()
|
|
||||||
heightConstraint = imageView.heightAnchor.constraint(equalToConstant: size.value.dimensions.height)
|
|
||||||
heightConstraint?.isActive = true
|
|
||||||
widthConstraint = imageView.widthAnchor.constraint(equalToConstant: size.value.dimensions.width)
|
|
||||||
widthConstraint?.isActive = true
|
|
||||||
|
|
||||||
backgroundColor = .clear
|
backgroundColor = .clear
|
||||||
|
|
||||||
isAccessibilityElement = true
|
isAccessibilityElement = true
|
||||||
@ -149,7 +139,6 @@ open class Tooltip: Control, TooltipLaunchable {
|
|||||||
content = ""
|
content = ""
|
||||||
fillColor = .primary
|
fillColor = .primary
|
||||||
closeButtonText = "Close"
|
closeButtonText = "Close"
|
||||||
imageView.image = nil
|
|
||||||
shouldUpdateView = true
|
shouldUpdateView = true
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
@ -157,15 +146,12 @@ open class Tooltip: Control, TooltipLaunchable {
|
|||||||
/// Function used to make changes to the View based off a change events or from local properties.
|
/// Function used to make changes to the View based off a change events or from local properties.
|
||||||
open override func updateView() {
|
open override func updateView() {
|
||||||
super.updateView()
|
super.updateView()
|
||||||
|
|
||||||
//set the dimensions
|
//get the size
|
||||||
let dimensions = size.value.dimensions
|
icon.size = size.value
|
||||||
heightConstraint?.constant = dimensions.height
|
|
||||||
widthConstraint?.constant = dimensions.width
|
|
||||||
|
|
||||||
//get the color for the image
|
//get the color for the image
|
||||||
let imageColor = iconColorConfiguration.getColor(self)
|
icon.color = iconColorConfiguration.getColor(self)
|
||||||
imageView.image = infoImage.withTintColor(imageColor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func updateAccessibility() {
|
open override func updateAccessibility() {
|
||||||
|
|||||||
@ -71,8 +71,8 @@ open class TrailingTooltipLabel: View, TooltipLaunchable {
|
|||||||
label.textPosition = labelTextPosition
|
label.textPosition = labelTextPosition
|
||||||
label.attributes = labelAttributes
|
label.attributes = labelAttributes
|
||||||
label.surface = surface
|
label.surface = surface
|
||||||
label.disabled = disabled
|
label.isEnabled = isEnabled
|
||||||
|
|
||||||
//add tooltip
|
//add tooltip
|
||||||
if let labelText, !labelText.isEmpty {
|
if let labelText, !labelText.isEmpty {
|
||||||
label.addTooltip(model: .init(surface: surface, closeButtonText: tooltipCloseButtonText, title: tooltipTitle, content: tooltipContent, contentView: tooltipContentView))
|
label.addTooltip(model: .init(surface: surface, closeButtonText: tooltipCloseButtonText, title: tooltipTitle, content: tooltipContent, contentView: tooltipContentView))
|
||||||
|
|||||||
@ -10,466 +10,11 @@ import UIKit
|
|||||||
import VDSFormControlsTokens
|
import VDSFormControlsTokens
|
||||||
|
|
||||||
extension UIView {
|
extension UIView {
|
||||||
|
|
||||||
public func constraint(with identifier: String) -> NSLayoutConstraint? {
|
public func constraint(with identifier: String) -> NSLayoutConstraint? {
|
||||||
return constraints.first { $0.identifier == identifier }
|
return constraints.first { $0.identifier == identifier }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
// MARK: - Pinning
|
|
||||||
//--------------------------------------------------
|
|
||||||
extension UIView {
|
|
||||||
@discardableResult
|
|
||||||
/// Pins each to the all 4 anchor points to a view.
|
|
||||||
/// - Parameters:
|
|
||||||
/// - view: View that you will be pinned within.
|
|
||||||
/// - edges: Insets for each side.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pin(_ view: UIView, with edges: UIEdgeInsets = UIEdgeInsets.zero) -> Self {
|
|
||||||
pinLeading(view.leadingAnchor, edges.left)
|
|
||||||
pinTrailing(view.trailingAnchor, edges.right)
|
|
||||||
pinTop(view.topAnchor, edges.top)
|
|
||||||
pinBottom(view.bottomAnchor, edges.bottom)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
|
|
||||||
/// Pins each to the all 4 anchor points to the view you are set within.
|
|
||||||
/// - Parameter edges: Insets for each side.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinToSuperView(_ edges: UIEdgeInsets = UIEdgeInsets.zero) -> Self {
|
|
||||||
if let superview {
|
|
||||||
pin(superview, with: edges)
|
|
||||||
}
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
// MARK: - HeightAnchor
|
|
||||||
//--------------------------------------------------
|
|
||||||
extension UIView {
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a heightAnchor.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func height(_ constant: CGFloat) -> Self {
|
|
||||||
height(constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a heightAnchor where the height constant passed in using a greaterThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func heightGreaterThanEqualTo(_ constant: CGFloat) -> Self {
|
|
||||||
heightGreaterThanEqualTo(constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a heightAnchor where the height constant passed in using a lessThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func heightLessThanEqualTo(_ constant: CGFloat) -> Self {
|
|
||||||
heightLessThanEqualTo(constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a heightAnchor for the constant passed into the method.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func height(constant: CGFloat) -> NSLayoutConstraint {
|
|
||||||
heightAnchor.constraint(equalToConstant: constant).activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a heightAnchor where the constant passed in using a greaterThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func heightGreaterThanEqualTo(constant: CGFloat) -> NSLayoutConstraint {
|
|
||||||
heightAnchor.constraint(greaterThanOrEqualToConstant: constant).activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a heightAnchor where the constant passed in using a lessThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func heightLessThanEqualTo(constant: CGFloat) -> NSLayoutConstraint {
|
|
||||||
heightAnchor.constraint(lessThanOrEqualToConstant: constant).activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
// MARK: - WidthAnchor
|
|
||||||
//--------------------------------------------------
|
|
||||||
extension UIView {
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a widthAnchor.
|
|
||||||
/// - Parameter constant: Width Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func width(_ constant: CGFloat) -> Self {
|
|
||||||
width(constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a widthAnchor where the constant passed in using a greaterThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func widthGreaterThanEqualTo(_ constant: CGFloat) -> Self {
|
|
||||||
widthGreaterThanEqualTo(constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a widthAnchor where the constant passed in using a lessThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func widthLessThanEqualTo(_ constant: CGFloat) -> Self {
|
|
||||||
widthLessThanEqualTo(constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a widthAnchor for the constant passed into the method.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func width(constant: CGFloat) -> NSLayoutConstraint {
|
|
||||||
widthAnchor.constraint(equalToConstant: constant).activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a widthAnchor with the constant passed in using a greaterThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func widthGreaterThanEqualTo(constant: CGFloat) -> NSLayoutConstraint {
|
|
||||||
widthAnchor.constraint(greaterThanOrEqualToConstant: constant).activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a widthAnchor with the constant passed in using a lessThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func widthLessThanEqualTo(constant: CGFloat) -> NSLayoutConstraint {
|
|
||||||
widthAnchor.constraint(lessThanOrEqualToConstant: constant).activate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
// MARK: - TopAnchor
|
|
||||||
//--------------------------------------------------
|
|
||||||
extension UIView {
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a topAnchor.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinTop(_ constant: CGFloat = 0.0) -> Self {
|
|
||||||
return pinTop(nil, constant)
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a topAnchor to a specific YAxisAnchor.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the topAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinTop(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
|
||||||
pinTop(anchor: anchor, constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a topAnchor to a specific YAxisAnchor passed in using a lessThanOrEqualTo Constraint
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the topAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinTopLessThanOrEqualTo(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
|
||||||
pinTopLessThanOrEqualTo(anchor: anchor, constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a topAnchor to a specific YAxisAnchor passed in using a greaterThanOrEqualTo Constraint
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the topAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinTopGreaterThanOrEqualTo(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
|
||||||
pinTopGreaterThanOrEqualTo(anchor: anchor, constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a topAnchor for the constant passed into the method.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the topAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func pinTop(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? {
|
|
||||||
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.topAnchor
|
|
||||||
guard let found else { return nil }
|
|
||||||
return topAnchor.constraint(equalTo: found, constant: constant).activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a topAnchor with the constant passed in using a lessThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the topAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func pinTopLessThanOrEqualTo(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? {
|
|
||||||
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.topAnchor
|
|
||||||
guard let found else { return nil }
|
|
||||||
return topAnchor.constraint(lessThanOrEqualTo: found, constant: constant).activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a topAnchor with the constant passed in using a greaterThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the topAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func pinTopGreaterThanOrEqualTo(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? {
|
|
||||||
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.topAnchor
|
|
||||||
guard let found else { return nil }
|
|
||||||
return topAnchor.constraint(greaterThanOrEqualTo: found, constant: constant).activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
// MARK: - BottomAnchor
|
|
||||||
//--------------------------------------------------
|
|
||||||
extension UIView {
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a bottomAnchor.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinBottom(_ constant: CGFloat = 0.0) -> Self {
|
|
||||||
return pinBottom(nil, constant)
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a bottomAnchor to a specific YAxisAnchor.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the bottomAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinBottom(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
|
||||||
pinBottom(anchor: anchor, constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a bottomAnchor to a specific YAxisAnchor passed in using a lessThanOrEqualTo Constraint
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the bottomAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinBottomLessThanOrEqualTo(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
|
||||||
pinBottomLessThanOrEqualTo(anchor: anchor, constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a bottomAnchor to a specific YAxisAnchor passed in using a greaterThanOrEqualTo Constraint
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the bottomAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinBottomGreaterThanOrEqualTo(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
|
||||||
pinBottomGreaterThanOrEqualTo(anchor: anchor, constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a bottomAnchor for the constant passed into the method.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the bottomAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func pinBottom(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? {
|
|
||||||
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.bottomAnchor
|
|
||||||
guard let found else { return nil }
|
|
||||||
return bottomAnchor.constraint(equalTo: found, constant: -constant).activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a bottomAnchor with the constant passed in using a lessThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the bottomAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func pinBottomLessThanOrEqualTo(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? {
|
|
||||||
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.bottomAnchor
|
|
||||||
guard let found else { return nil }
|
|
||||||
return bottomAnchor.constraint(lessThanOrEqualTo: found, constant: -constant).activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a bottomAnchor with the constant passed in using a greaterThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the bottomAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func pinBottomGreaterThanOrEqualTo(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? {
|
|
||||||
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.bottomAnchor
|
|
||||||
guard let found else { return nil }
|
|
||||||
return bottomAnchor.constraint(greaterThanOrEqualTo: found, constant: -constant).activate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
// MARK: - LeadingAnchor
|
|
||||||
//--------------------------------------------------
|
|
||||||
extension UIView {
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a leadingAnchor.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinLeading(_ constant: CGFloat = 0.0) -> Self {
|
|
||||||
return pinLeading(nil, constant)
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a leadingAnchor to a specific XAxisAnchor.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the leadingAnchor.
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinLeading(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
|
||||||
pinLeading(anchor: anchor, constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a leadingAnchor to a specific XAxisAnchor passed in using a greaterThanOrEqualTo Constraint
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the leadingAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinLeadingLessThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
|
||||||
pinLeadingLessThanOrEqualTo(anchor: anchor, constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a leadingAnchor to a specific XAxisAnchor passed in using a greaterThanOrEqualTo Constraint
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the leadingAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinLeadingGreaterThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
|
||||||
pinLeadingGreaterThanOrEqualTo(anchor: anchor, constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a leadingAnchor for the constant passed into the method.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the leadingAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func pinLeading(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? {
|
|
||||||
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.leadingAnchor
|
|
||||||
guard let found else { return nil }
|
|
||||||
return leadingAnchor.constraint(equalTo: found, constant: constant).activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a leadingAnchor with the constant passed in using a lessThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the leadingAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func pinLeadingLessThanOrEqualTo(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? {
|
|
||||||
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.leadingAnchor
|
|
||||||
guard let found else { return nil }
|
|
||||||
return leadingAnchor.constraint(lessThanOrEqualTo: found, constant: constant).activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a leadingAnchor with the constant passed in using a greaterThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the leadingAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func pinLeadingGreaterThanOrEqualTo(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? {
|
|
||||||
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.leadingAnchor
|
|
||||||
guard let found else { return nil }
|
|
||||||
return leadingAnchor.constraint(greaterThanOrEqualTo: found, constant: constant).activate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
// MARK: - TrailingAnchor
|
|
||||||
//--------------------------------------------------
|
|
||||||
extension UIView {
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a trailingAnchor.
|
|
||||||
/// - Parameter constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinTrailing(_ constant: CGFloat = 0.0) -> Self {
|
|
||||||
pinTrailing(nil, constant)
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a trailingAnchor to a specific XAxisAnchor.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the trailingAnchor.
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinTrailing(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
|
||||||
pinTrailing(anchor: anchor, constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a trailingAnchor to a specific XAxisAnchor passed in using a lessThanOrEqualTo Constraint
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the trailingAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinTrailingLessThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
|
||||||
pinTrailingLessThanOrEqualTo(anchor: anchor, constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a trailingAnchor to a specific XAxisAnchor passed in using a greaterThanOrEqualTo Constraint
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the trailingAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: Yourself.
|
|
||||||
public func pinTrailingGreaterThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
|
||||||
pinTrailingGreaterThanOrEqualTo(anchor: anchor, constant: constant)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a trailingAnchor for the constant passed into the method.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the trailingAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func pinTrailing(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? {
|
|
||||||
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.trailingAnchor
|
|
||||||
guard let found else { return nil }
|
|
||||||
return trailingAnchor.constraint(equalTo: found, constant: -constant).activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a trailingAnchor with the constant passed in using a lessThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the trailingAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func pinTrailingLessThanOrEqualTo(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? {
|
|
||||||
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.trailingAnchor
|
|
||||||
guard let found else { return nil }
|
|
||||||
return trailingAnchor.constraint(lessThanOrEqualTo: found, constant: -constant).activate()
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
/// Adds a trailingAnchor with the constant passed in using a greaterThanOrEqualTo Constraint.
|
|
||||||
/// - Parameter anchor:The anchor in which to attach the trailingAnchor
|
|
||||||
/// - constant: Constant size.
|
|
||||||
/// - Returns: The Constraint that was created.
|
|
||||||
public func pinTrailingGreaterThanOrEqualTo(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0) -> NSLayoutConstraint? {
|
|
||||||
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.trailingAnchor
|
|
||||||
guard let found else { return nil }
|
|
||||||
return trailingAnchor.constraint(greaterThanOrEqualTo: found, constant: -constant).activate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension NSLayoutConstraint {
|
extension NSLayoutConstraint {
|
||||||
|
|
||||||
@discardableResult
|
@discardableResult
|
||||||
|
|||||||
@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
/// Any object that can be disabled, which may change the appearance
|
///// Any object that can be disabled, which may change the appearance
|
||||||
public protocol Disabling {
|
//public protocol Disabling {
|
||||||
/// Whether this object is disabled or not
|
// /// Whether this object is disabled or not
|
||||||
var disabled: Bool { get set }
|
// var disabled: Bool { get set }
|
||||||
}
|
//}
|
||||||
|
|||||||
14
VDS/Protocols/Enabling.swift
Normal file
14
VDS/Protocols/Enabling.swift
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// Enabling.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 8/25/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
/// Any object that can be Enabled, which may change the appearance
|
||||||
|
public protocol Enabling {
|
||||||
|
/// Whether this object is enabled or not
|
||||||
|
var isEnabled: Bool { get set }
|
||||||
|
}
|
||||||
490
VDS/Protocols/LayoutConstraintable.swift
Normal file
490
VDS/Protocols/LayoutConstraintable.swift
Normal file
@ -0,0 +1,490 @@
|
|||||||
|
//
|
||||||
|
// LayoutConstraintable.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 8/22/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import VDSFormControlsTokens
|
||||||
|
|
||||||
|
public protocol LayoutConstraintable {
|
||||||
|
var superview: UIView? { get }
|
||||||
|
|
||||||
|
var leadingAnchor: NSLayoutXAxisAnchor { get }
|
||||||
|
var trailingAnchor: NSLayoutXAxisAnchor { get }
|
||||||
|
var topAnchor: NSLayoutYAxisAnchor { get }
|
||||||
|
var bottomAnchor: NSLayoutYAxisAnchor { get }
|
||||||
|
|
||||||
|
var widthAnchor: NSLayoutDimension { get }
|
||||||
|
var heightAnchor: NSLayoutDimension { get }
|
||||||
|
|
||||||
|
var centerXAnchor: NSLayoutXAxisAnchor { get }
|
||||||
|
var centerYAnchor: NSLayoutYAxisAnchor { get }
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Pinning
|
||||||
|
//--------------------------------------------------
|
||||||
|
extension LayoutConstraintable {
|
||||||
|
@discardableResult
|
||||||
|
/// Pins each to the all 4 anchor points to a view.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - view: View that you will be pinned within.
|
||||||
|
/// - edges: Insets for each side.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pin(_ view: UIView, with edges: UIEdgeInsets = UIEdgeInsets.zero) -> Self {
|
||||||
|
pinLeading(view.leadingAnchor, edges.left)
|
||||||
|
pinTrailing(view.trailingAnchor, edges.right)
|
||||||
|
pinTop(view.topAnchor, edges.top)
|
||||||
|
pinBottom(view.bottomAnchor, edges.bottom)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
|
||||||
|
/// Pins each to the all 4 anchor points to the view you are set within.
|
||||||
|
/// - Parameter edges: Insets for each side.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinToSuperView(_ edges: UIEdgeInsets = UIEdgeInsets.zero) -> Self {
|
||||||
|
if let superview {
|
||||||
|
pin(superview, with: edges)
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - HeightAnchor
|
||||||
|
//--------------------------------------------------
|
||||||
|
extension LayoutConstraintable {
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a heightAnchor.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func height(_ constant: CGFloat, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
height(constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a heightAnchor where the height constant passed in using a greaterThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func heightGreaterThanEqualTo(_ constant: CGFloat, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
heightGreaterThanEqualTo(constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a heightAnchor where the height constant passed in using a lessThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func heightLessThanEqualTo(_ constant: CGFloat, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
heightLessThanEqualTo(constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a heightAnchor for the constant passed into the method.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func height(constant: CGFloat, priority: UILayoutPriority = .required) -> NSLayoutConstraint {
|
||||||
|
heightAnchor.constraint(equalToConstant: constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a heightAnchor where the constant passed in using a greaterThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func heightGreaterThanEqualTo(constant: CGFloat, priority: UILayoutPriority = .required) -> NSLayoutConstraint {
|
||||||
|
heightAnchor.constraint(greaterThanOrEqualToConstant: constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a heightAnchor where the constant passed in using a lessThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func heightLessThanEqualTo(constant: CGFloat, priority: UILayoutPriority = .required) -> NSLayoutConstraint {
|
||||||
|
heightAnchor.constraint(lessThanOrEqualToConstant: constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - WidthAnchor
|
||||||
|
//--------------------------------------------------
|
||||||
|
extension LayoutConstraintable {
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a widthAnchor.
|
||||||
|
/// - Parameter constant: Width Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func width(_ constant: CGFloat, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
width(constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a widthAnchor where the constant passed in using a greaterThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func widthGreaterThanEqualTo(_ constant: CGFloat, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
widthGreaterThanEqualTo(constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a widthAnchor where the constant passed in using a lessThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func widthLessThanEqualTo(_ constant: CGFloat, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
widthLessThanEqualTo(constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a widthAnchor for the constant passed into the method.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func width(constant: CGFloat, priority: UILayoutPriority = .required) -> NSLayoutConstraint {
|
||||||
|
widthAnchor.constraint(equalToConstant: constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a widthAnchor with the constant passed in using a greaterThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func widthGreaterThanEqualTo(constant: CGFloat, priority: UILayoutPriority = .required) -> NSLayoutConstraint {
|
||||||
|
widthAnchor.constraint(greaterThanOrEqualToConstant: constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a widthAnchor with the constant passed in using a lessThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func widthLessThanEqualTo(constant: CGFloat, priority: UILayoutPriority = .required) -> NSLayoutConstraint {
|
||||||
|
widthAnchor.constraint(lessThanOrEqualToConstant: constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - TopAnchor
|
||||||
|
//--------------------------------------------------
|
||||||
|
extension LayoutConstraintable {
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a topAnchor.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinTop(_ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
return pinTop(nil, constant, priority)
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a topAnchor to a specific YAxisAnchor.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the topAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinTop(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinTop(anchor: anchor, constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a topAnchor to a specific YAxisAnchor passed in using a lessThanOrEqualTo Constraint
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the topAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinTopLessThanOrEqualTo(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinTopLessThanOrEqualTo(anchor: anchor, constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a topAnchor to a specific YAxisAnchor passed in using a greaterThanOrEqualTo Constraint
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the topAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinTopGreaterThanOrEqualTo(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinTopGreaterThanOrEqualTo(anchor: anchor, constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a topAnchor for the constant passed into the method.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the topAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinTop(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.topAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return topAnchor.constraint(equalTo: found, constant: constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a topAnchor with the constant passed in using a lessThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the topAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinTopLessThanOrEqualTo(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.topAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return topAnchor.constraint(lessThanOrEqualTo: found, constant: constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a topAnchor with the constant passed in using a greaterThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the topAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinTopGreaterThanOrEqualTo(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.topAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return topAnchor.constraint(greaterThanOrEqualTo: found, constant: constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - BottomAnchor
|
||||||
|
//--------------------------------------------------
|
||||||
|
extension LayoutConstraintable {
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a bottomAnchor.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinBottom(_ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
return pinBottom(nil, constant, priority)
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a bottomAnchor to a specific YAxisAnchor.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the bottomAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinBottom(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinBottom(anchor: anchor, constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a bottomAnchor to a specific YAxisAnchor passed in using a lessThanOrEqualTo Constraint
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the bottomAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinBottomLessThanOrEqualTo(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinBottomLessThanOrEqualTo(anchor: anchor, constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a bottomAnchor to a specific YAxisAnchor passed in using a greaterThanOrEqualTo Constraint
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the bottomAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinBottomGreaterThanOrEqualTo(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinBottomGreaterThanOrEqualTo(anchor: anchor, constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a bottomAnchor for the constant passed into the method.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the bottomAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinBottom(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.bottomAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return bottomAnchor.constraint(equalTo: found, constant: -constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a bottomAnchor with the constant passed in using a lessThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the bottomAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinBottomLessThanOrEqualTo(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.bottomAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return bottomAnchor.constraint(lessThanOrEqualTo: found, constant: -constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a bottomAnchor with the constant passed in using a greaterThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the bottomAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinBottomGreaterThanOrEqualTo(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.bottomAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return bottomAnchor.constraint(greaterThanOrEqualTo: found, constant: -constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - LeadingAnchor
|
||||||
|
//--------------------------------------------------
|
||||||
|
extension LayoutConstraintable {
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a leadingAnchor.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinLeading(_ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
return pinLeading(nil, constant, priority)
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a leadingAnchor to a specific XAxisAnchor.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the leadingAnchor.
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinLeading(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinLeading(anchor: anchor, constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a leadingAnchor to a specific XAxisAnchor passed in using a greaterThanOrEqualTo Constraint
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the leadingAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinLeadingLessThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinLeadingLessThanOrEqualTo(anchor: anchor, constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a leadingAnchor to a specific XAxisAnchor passed in using a greaterThanOrEqualTo Constraint
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the leadingAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinLeadingGreaterThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinLeadingGreaterThanOrEqualTo(anchor: anchor, constant: constant, priority: priority)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a leadingAnchor for the constant passed into the method.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the leadingAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinLeading(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.leadingAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return leadingAnchor.constraint(equalTo: found, constant: constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a leadingAnchor with the constant passed in using a lessThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the leadingAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinLeadingLessThanOrEqualTo(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.leadingAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return leadingAnchor.constraint(lessThanOrEqualTo: found, constant: constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a leadingAnchor with the constant passed in using a greaterThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the leadingAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinLeadingGreaterThanOrEqualTo(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.leadingAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return leadingAnchor.constraint(greaterThanOrEqualTo: found, constant: constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - TrailingAnchor
|
||||||
|
//--------------------------------------------------
|
||||||
|
extension LayoutConstraintable {
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a trailingAnchor.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinTrailing(_ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinTrailing(nil, constant)
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a trailingAnchor to a specific XAxisAnchor.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the trailingAnchor.
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinTrailing(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinTrailing(anchor: anchor, constant: constant)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a trailingAnchor to a specific XAxisAnchor passed in using a lessThanOrEqualTo Constraint
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the trailingAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinTrailingLessThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinTrailingLessThanOrEqualTo(anchor: anchor, constant: constant)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a trailingAnchor to a specific XAxisAnchor passed in using a greaterThanOrEqualTo Constraint
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the trailingAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinTrailingGreaterThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
||||||
|
pinTrailingGreaterThanOrEqualTo(anchor: anchor, constant: constant)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a trailingAnchor for the constant passed into the method.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the trailingAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinTrailing(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.trailingAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return trailingAnchor.constraint(equalTo: found, constant: -constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a trailingAnchor with the constant passed in using a lessThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the trailingAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinTrailingLessThanOrEqualTo(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.trailingAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return trailingAnchor.constraint(lessThanOrEqualTo: found, constant: -constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a trailingAnchor with the constant passed in using a greaterThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the trailingAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinTrailingGreaterThanOrEqualTo(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.trailingAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return trailingAnchor.constraint(greaterThanOrEqualTo: found, constant: -constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Implementations
|
||||||
|
//--------------------------------------------------
|
||||||
|
extension UIView: LayoutConstraintable {}
|
||||||
|
extension UILayoutGuide: LayoutConstraintable {
|
||||||
|
public var superview: UIView? {
|
||||||
|
owningView
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,7 +9,7 @@ import Foundation
|
|||||||
import UIKit
|
import UIKit
|
||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
public protocol ViewProtocol: AnyObject, Initable, Resettable, Disabling, Surfaceable {
|
public protocol ViewProtocol: AnyObject, Initable, Resettable, Enabling, Surfaceable {
|
||||||
/// Set of Subscribers for any Publishers for this Control.
|
/// Set of Subscribers for any Publishers for this Control.
|
||||||
var subscribers: Set<AnyCancellable> { get set }
|
var subscribers: Set<AnyCancellable> { get set }
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,9 @@
|
|||||||
|
1.0.40
|
||||||
|
=======
|
||||||
|
- Refactored a bit of code to remove "disabled" and move to "isEnabled" Apple Standard.
|
||||||
|
- Fixed Layout Constraint issues
|
||||||
|
- Added fixes for Accessibility
|
||||||
|
|
||||||
1.0.39
|
1.0.39
|
||||||
=======
|
=======
|
||||||
- CXTDT-423141 - Tabs - Selected Tab dark mode text color
|
- CXTDT-423141 - Tabs - Selected Tab dark mode text color
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user