Merge branch 'develop' into feature/monarch
This commit is contained in:
commit
fa35654ebe
@ -140,6 +140,7 @@
|
|||||||
EAB5FEF829393A7200998C17 /* ButtonGroupConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB5FEF729393A7200998C17 /* ButtonGroupConstants.swift */; };
|
EAB5FEF829393A7200998C17 /* ButtonGroupConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB5FEF729393A7200998C17 /* ButtonGroupConstants.swift */; };
|
||||||
EAB5FF0129424ACB00998C17 /* UIControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB5FF0029424ACB00998C17 /* UIControl.swift */; };
|
EAB5FF0129424ACB00998C17 /* UIControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB5FF0029424ACB00998C17 /* UIControl.swift */; };
|
||||||
EABFEB642A26473700C4C106 /* NSAttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFEB632A26473700C4C106 /* NSAttributedString.swift */; };
|
EABFEB642A26473700C4C106 /* NSAttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFEB632A26473700C4C106 /* NSAttributedString.swift */; };
|
||||||
|
EAC58BFD2BE935C300BA39FA /* TitleLockupTextColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC58BFC2BE935C300BA39FA /* TitleLockupTextColor.swift */; };
|
||||||
EAC71A1D2A2E155A00E47A9F /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC71A1C2A2E155A00E47A9F /* Checkbox.swift */; };
|
EAC71A1D2A2E155A00E47A9F /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC71A1C2A2E155A00E47A9F /* Checkbox.swift */; };
|
||||||
EAC71A1F2A2E173D00E47A9F /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC71A1E2A2E173D00E47A9F /* RadioButton.swift */; };
|
EAC71A1F2A2E173D00E47A9F /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC71A1E2A2E173D00E47A9F /* RadioButton.swift */; };
|
||||||
EAC846F3294B95CE00F685BA /* ButtonGroupCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC846F2294B95CE00F685BA /* ButtonGroupCollectionViewCell.swift */; };
|
EAC846F3294B95CE00F685BA /* ButtonGroupCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC846F2294B95CE00F685BA /* ButtonGroupCollectionViewCell.swift */; };
|
||||||
@ -336,6 +337,7 @@
|
|||||||
EAB5FEF729393A7200998C17 /* ButtonGroupConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupConstants.swift; sourceTree = "<group>"; };
|
EAB5FEF729393A7200998C17 /* ButtonGroupConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupConstants.swift; sourceTree = "<group>"; };
|
||||||
EAB5FF0029424ACB00998C17 /* UIControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIControl.swift; sourceTree = "<group>"; };
|
EAB5FF0029424ACB00998C17 /* UIControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIControl.swift; sourceTree = "<group>"; };
|
||||||
EABFEB632A26473700C4C106 /* NSAttributedString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSAttributedString.swift; sourceTree = "<group>"; };
|
EABFEB632A26473700C4C106 /* NSAttributedString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSAttributedString.swift; sourceTree = "<group>"; };
|
||||||
|
EAC58BFC2BE935C300BA39FA /* TitleLockupTextColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupTextColor.swift; sourceTree = "<group>"; };
|
||||||
EAC71A1C2A2E155A00E47A9F /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = "<group>"; };
|
EAC71A1C2A2E155A00E47A9F /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = "<group>"; };
|
||||||
EAC71A1E2A2E173D00E47A9F /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = "<group>"; };
|
EAC71A1E2A2E173D00E47A9F /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = "<group>"; };
|
||||||
EAC846F2294B95CE00F685BA /* ButtonGroupCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupCollectionViewCell.swift; sourceTree = "<group>"; };
|
EAC846F2294B95CE00F685BA /* ButtonGroupCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||||
@ -771,12 +773,13 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
EA5E30522950DDA60082B959 /* TitleLockup.swift */,
|
EA5E30522950DDA60082B959 /* TitleLockup.swift */,
|
||||||
|
EAEEECAC2B1FC1A600531FC2 /* TitleLockupChangeLog.txt */,
|
||||||
EA985BEF2968A93600F2FF2E /* TitleLockupEyebrowModel.swift */,
|
EA985BEF2968A93600F2FF2E /* TitleLockupEyebrowModel.swift */,
|
||||||
EA985BED2968A92400F2FF2E /* TitleLockupSubTitleModel.swift */,
|
EA985BED2968A92400F2FF2E /* TitleLockupSubTitleModel.swift */,
|
||||||
EA985BEB2968A91200F2FF2E /* TitleLockupTitleModel.swift */,
|
EA985BEB2968A91200F2FF2E /* TitleLockupTitleModel.swift */,
|
||||||
|
EAC58BFC2BE935C300BA39FA /* TitleLockupTextColor.swift */,
|
||||||
EA985BF12968B5BB00F2FF2E /* TitleLockupTextStyle.swift */,
|
EA985BF12968B5BB00F2FF2E /* TitleLockupTextStyle.swift */,
|
||||||
EA513A942A4E1F82002A4DFF /* TitleLockupStyleConfiguration.swift */,
|
EA513A942A4E1F82002A4DFF /* TitleLockupStyleConfiguration.swift */,
|
||||||
EAEEECAC2B1FC1A600531FC2 /* TitleLockupChangeLog.txt */,
|
|
||||||
);
|
);
|
||||||
path = TitleLockup;
|
path = TitleLockup;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1147,6 +1150,7 @@
|
|||||||
EA0D1C412A6AD61C00E5C127 /* Typography+Additional.swift in Sources */,
|
EA0D1C412A6AD61C00E5C127 /* Typography+Additional.swift in Sources */,
|
||||||
EAC925842911C63100091998 /* Colorable.swift in Sources */,
|
EAC925842911C63100091998 /* Colorable.swift in Sources */,
|
||||||
18B463A42BBD3C46005C4528 /* DropdownOptionModel.swift in Sources */,
|
18B463A42BBD3C46005C4528 /* DropdownOptionModel.swift in Sources */,
|
||||||
|
EAC58BFD2BE935C300BA39FA /* TitleLockupTextColor.swift in Sources */,
|
||||||
EAACB89A2B927108006A3869 /* Valuing.swift in Sources */,
|
EAACB89A2B927108006A3869 /* Valuing.swift in Sources */,
|
||||||
EAE785312BA0A438009428EA /* UIImage+Helper.swift in Sources */,
|
EAE785312BA0A438009428EA /* UIImage+Helper.swift in Sources */,
|
||||||
EAB5FEF5292D371F00998C17 /* ButtonBase.swift in Sources */,
|
EAB5FEF5292D371F00998C17 /* ButtonBase.swift in Sources */,
|
||||||
|
|||||||
@ -210,6 +210,7 @@ open class BadgeIndicator: View {
|
|||||||
/// The Container's height.
|
/// The Container's height.
|
||||||
open var height: CGFloat? { didSet { setNeedsUpdate() } }
|
open var height: CGFloat? { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
|
open var accessibilityText: String? { didSet { setNeedsUpdate() } }
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Private Properties
|
// MARK: - Private Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -348,7 +349,9 @@ open class BadgeIndicator: View {
|
|||||||
|
|
||||||
open override func updateAccessibility() {
|
open override func updateAccessibility() {
|
||||||
super.updateAccessibility()
|
super.updateAccessibility()
|
||||||
if kind == .numbered {
|
if let accessibilityText {
|
||||||
|
accessibilityLabel = accessibilityText
|
||||||
|
} else if kind == .numbered {
|
||||||
accessibilityLabel = label.text
|
accessibilityLabel = label.text
|
||||||
} else {
|
} else {
|
||||||
accessibilityLabel = "Simple"
|
accessibilityLabel = "Simple"
|
||||||
|
|||||||
@ -102,8 +102,6 @@ open class DropdownSelect: EntryFieldBase {
|
|||||||
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
|
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
|
||||||
open override func setup() {
|
open override func setup() {
|
||||||
super.setup()
|
super.setup()
|
||||||
|
|
||||||
accessibilityLabel = "Dropdown Select"
|
|
||||||
|
|
||||||
// stackview for controls in EntryFieldBase.controlContainerView
|
// stackview for controls in EntryFieldBase.controlContainerView
|
||||||
let controlStackView = UIStackView().with {
|
let controlStackView = UIStackView().with {
|
||||||
@ -118,6 +116,10 @@ open class DropdownSelect: EntryFieldBase {
|
|||||||
controlStackView.addArrangedSubview(inlineDisplayLabel)
|
controlStackView.addArrangedSubview(inlineDisplayLabel)
|
||||||
controlStackView.addArrangedSubview(selectedOptionLabel)
|
controlStackView.addArrangedSubview(selectedOptionLabel)
|
||||||
|
|
||||||
|
containerStackView.isAccessibilityElement = true
|
||||||
|
containerStackView.accessibilityLabel = "Dropdown Select"
|
||||||
|
inlineDisplayLabel.isAccessibilityElement = true
|
||||||
|
|
||||||
controlStackView.setCustomSpacing(0, after: dropdownField)
|
controlStackView.setCustomSpacing(0, after: dropdownField)
|
||||||
controlStackView.setCustomSpacing(VDSLayout.space1X, after: inlineDisplayLabel)
|
controlStackView.setCustomSpacing(VDSLayout.space1X, after: inlineDisplayLabel)
|
||||||
controlStackView.setCustomSpacing(VDSLayout.space3X, after: selectedOptionLabel)
|
controlStackView.setCustomSpacing(VDSLayout.space3X, after: selectedOptionLabel)
|
||||||
@ -245,9 +247,41 @@ open class DropdownSelect: EntryFieldBase {
|
|||||||
statusIcon.color = iconColorConfiguration.getColor(self)
|
statusIcon.color = iconColorConfiguration.getColor(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override func updateAccessibility() {
|
||||||
|
super.updateAccessibility()
|
||||||
|
var selectedOption = selectedOptionLabel.text ?? ""
|
||||||
|
containerStackView.accessibilityLabel = "Dropdown Select, \(selectedOption) \(isReadOnly ? ", read only" : "")"
|
||||||
|
containerStackView.accessibilityHint = isReadOnly || !isEnabled ? "" : "Double tap to open."
|
||||||
|
}
|
||||||
|
|
||||||
|
open override var accessibilityElements: [Any]? {
|
||||||
|
get {
|
||||||
|
var elements = [Any]()
|
||||||
|
elements.append(contentsOf: [titleLabel, containerStackView])
|
||||||
|
|
||||||
|
if showError {
|
||||||
|
elements.append(statusIcon)
|
||||||
|
if let errorText, !errorText.isEmpty {
|
||||||
|
elements.append(errorLabel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let helperText, !helperText.isEmpty {
|
||||||
|
elements.append(helperLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
return elements
|
||||||
|
}
|
||||||
|
|
||||||
|
set { super.accessibilityElements = newValue }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@objc open func pickerDoneClicked() {
|
@objc open func pickerDoneClicked() {
|
||||||
optionsPicker.isHidden = true
|
optionsPicker.isHidden = true
|
||||||
dropdownField.resignFirstResponder()
|
dropdownField.resignFirstResponder()
|
||||||
|
setNeedsUpdate()
|
||||||
|
UIAccessibility.post(notification: .layoutChanged, argument: containerStackView)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,6 +292,7 @@ extension DropdownSelect: UIPickerViewDelegate, UIPickerViewDataSource {
|
|||||||
|
|
||||||
internal func launchPicker() {
|
internal func launchPicker() {
|
||||||
if optionsPicker.isHidden {
|
if optionsPicker.isHidden {
|
||||||
|
UIAccessibility.post(notification: .layoutChanged, argument: optionsPicker)
|
||||||
dropdownField.becomeFirstResponder()
|
dropdownField.becomeFirstResponder()
|
||||||
} else {
|
} else {
|
||||||
dropdownField.resignFirstResponder()
|
dropdownField.resignFirstResponder()
|
||||||
|
|||||||
@ -544,6 +544,7 @@ open class ButtonIcon: Control, Changeable {
|
|||||||
badgeIndicator.horizontalPadding = badgeIndicatorModel.horizontalPadding
|
badgeIndicator.horizontalPadding = badgeIndicatorModel.horizontalPadding
|
||||||
badgeIndicator.hideDot = badgeIndicatorModel.hideDot
|
badgeIndicator.hideDot = badgeIndicatorModel.hideDot
|
||||||
badgeIndicator.hideBorder = badgeIndicatorModel.hideBorder
|
badgeIndicator.hideBorder = badgeIndicatorModel.hideBorder
|
||||||
|
badgeIndicator.accessibilityText = badgeIndicatorModel.accessibilityText
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateExpandDirectionalConstraints() {
|
private func updateExpandDirectionalConstraints() {
|
||||||
|
|||||||
@ -46,6 +46,9 @@ extension ButtonIcon {
|
|||||||
/// Trailing Text height that will be used for the badge indicator.
|
/// Trailing Text height that will be used for the badge indicator.
|
||||||
public var trailingText: String?
|
public var trailingText: String?
|
||||||
|
|
||||||
|
/// Accessibliity Text
|
||||||
|
public var accessibilityText: String?
|
||||||
|
|
||||||
/// Dot Size that will be used for the badge indicator.
|
/// Dot Size that will be used for the badge indicator.
|
||||||
public var dotSize: CGFloat?
|
public var dotSize: CGFloat?
|
||||||
|
|
||||||
@ -61,7 +64,7 @@ extension ButtonIcon {
|
|||||||
/// Hide Border that will be used for the badge indicator.
|
/// Hide Border that will be used for the badge indicator.
|
||||||
public var hideBorder: Bool = false
|
public var hideBorder: Bool = false
|
||||||
|
|
||||||
public init(kind: BadgeIndicator.Kind = .simple, fillColor: BadgeIndicator.FillColor = .red, expandDirection: ExpandDirection = .right, size: BadgeIndicator.Size = .xxlarge, maximumDigits: BadgeIndicator.MaximumDigits = .two, width: CGFloat? = nil, height: CGFloat? = nil, number: Int? = nil, leadingCharacter: String? = "", trailingText: String? = "", dotSize: CGFloat? = nil, verticalPadding: CGFloat? = nil, horizontalPadding: CGFloat? = nil, hideDot: Bool = false, hideBorder: Bool = false) {
|
public init(kind: BadgeIndicator.Kind = .simple, fillColor: BadgeIndicator.FillColor = .red, expandDirection: ExpandDirection = .right, size: BadgeIndicator.Size = .xxlarge, maximumDigits: BadgeIndicator.MaximumDigits = .two, width: CGFloat? = nil, height: CGFloat? = nil, number: Int? = nil, leadingCharacter: String? = "", trailingText: String? = "", accessibilityText: String? = nil, dotSize: CGFloat? = nil, verticalPadding: CGFloat? = nil, horizontalPadding: CGFloat? = nil, hideDot: Bool = false, hideBorder: Bool = false) {
|
||||||
self.kind = kind
|
self.kind = kind
|
||||||
self.fillColor = fillColor
|
self.fillColor = fillColor
|
||||||
self.expandDirection = expandDirection
|
self.expandDirection = expandDirection
|
||||||
@ -70,6 +73,7 @@ extension ButtonIcon {
|
|||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
self.number = number
|
self.number = number
|
||||||
|
self.accessibilityText = accessibilityText
|
||||||
self.leadingCharacter = leadingCharacter
|
self.leadingCharacter = leadingCharacter
|
||||||
self.trailingText = trailingText
|
self.trailingText = trailingText
|
||||||
self.dotSize = dotSize
|
self.dotSize = dotSize
|
||||||
|
|||||||
@ -77,7 +77,7 @@ public class TooltipLabelAttribute: ActionLabelAttributeModel, TooltipLaunchable
|
|||||||
self.subscriber = subscriber
|
self.subscriber = subscriber
|
||||||
self.surface = surface
|
self.surface = surface
|
||||||
self.model = model
|
self.model = model
|
||||||
self.accessibleText = accessibleText
|
self.accessibleText = accessibleText ?? model.accessibleText
|
||||||
self.presenter = presenter
|
self.presenter = presenter
|
||||||
|
|
||||||
//create the tooltip click event
|
//create the tooltip click event
|
||||||
|
|||||||
@ -104,6 +104,7 @@ open class Notification: View {
|
|||||||
open var typeIcon = Icon().with {
|
open var typeIcon = Icon().with {
|
||||||
$0.name = .infoBold
|
$0.name = .infoBold
|
||||||
$0.size = UIDevice.isIPad ? .medium : .small
|
$0.size = UIDevice.isIPad ? .medium : .small
|
||||||
|
$0.accessibilityTraits.remove(.image)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Icon used for the close.
|
/// Icon used for the close.
|
||||||
|
|||||||
@ -207,7 +207,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
|
|||||||
open override func setup() {
|
open override func setup() {
|
||||||
super.setup()
|
super.setup()
|
||||||
|
|
||||||
isAccessibilityElement = true
|
isAccessibilityElement = false
|
||||||
addSubview(stackView)
|
addSubview(stackView)
|
||||||
|
|
||||||
//create the wrapping view
|
//create the wrapping view
|
||||||
|
|||||||
@ -148,7 +148,6 @@ open class InputField: EntryFieldBase {
|
|||||||
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
|
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
|
||||||
open override func setup() {
|
open override func setup() {
|
||||||
super.setup()
|
super.setup()
|
||||||
isAccessibilityElement = false
|
|
||||||
|
|
||||||
minWidthConstraint = containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: 0)
|
minWidthConstraint = containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: 0)
|
||||||
minWidthConstraint?.isActive = true
|
minWidthConstraint?.isActive = true
|
||||||
@ -166,11 +165,12 @@ open class InputField: EntryFieldBase {
|
|||||||
controlStackView.addArrangedSubview(textField)
|
controlStackView.addArrangedSubview(textField)
|
||||||
|
|
||||||
textField.heightAnchor.constraint(equalToConstant: 20).isActive = true
|
textField.heightAnchor.constraint(equalToConstant: 20).isActive = true
|
||||||
|
textField.delegate = self
|
||||||
textField
|
textField
|
||||||
.textPublisher
|
.textPublisher
|
||||||
.sink { [weak self] newText in
|
.sink { [weak self] newText in
|
||||||
print("textPublisher newText: \(newText)")
|
print("textPublisher newText: \(newText)")
|
||||||
self?.text = newText
|
self?.process(text: newText)
|
||||||
self?.validate()
|
self?.validate()
|
||||||
self?.sendActions(for: .valueChanged)
|
self?.sendActions(for: .valueChanged)
|
||||||
}.store(in: &subscribers)
|
}.store(in: &subscribers)
|
||||||
@ -281,6 +281,7 @@ open class InputField: EntryFieldBase {
|
|||||||
var toolTipModel: Tooltip.TooltipModel? = tooltipModel
|
var toolTipModel: Tooltip.TooltipModel? = tooltipModel
|
||||||
var isSecureTextEntry = false
|
var isSecureTextEntry = false
|
||||||
var rules = [AnyRule<String>]()
|
var rules = [AnyRule<String>]()
|
||||||
|
var placeholderText: String?
|
||||||
|
|
||||||
if self.isRequired {
|
if self.isRequired {
|
||||||
let rule = RequiredRule()
|
let rule = RequiredRule()
|
||||||
@ -327,6 +328,7 @@ open class InputField: EntryFieldBase {
|
|||||||
|
|
||||||
case .date:
|
case .date:
|
||||||
minWidth = 114.0
|
minWidth = 114.0
|
||||||
|
placeholderText = dateFormat.placeholderText
|
||||||
|
|
||||||
case .securityCode:
|
case .securityCode:
|
||||||
minWidth = 88.0
|
minWidth = 88.0
|
||||||
@ -365,6 +367,9 @@ open class InputField: EntryFieldBase {
|
|||||||
minWidthConstraint?.isActive = true
|
minWidthConstraint?.isActive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//placeholder
|
||||||
|
textField.placeholder = placeholderText
|
||||||
|
|
||||||
//tooltip
|
//tooltip
|
||||||
tooltipModel = toolTipModel
|
tooltipModel = toolTipModel
|
||||||
}
|
}
|
||||||
@ -373,11 +378,29 @@ open class InputField: EntryFieldBase {
|
|||||||
open override func updateAccessibility() {
|
open override func updateAccessibility() {
|
||||||
super.updateAccessibility()
|
super.updateAccessibility()
|
||||||
textField.accessibilityLabel = showError ? "error" : nil
|
textField.accessibilityLabel = showError ? "error" : nil
|
||||||
if showError {
|
}
|
||||||
accessibilityElements = [titleLabel, textField, statusIcon, errorLabel, helperLabel]
|
|
||||||
} else {
|
open override var accessibilityElements: [Any]? {
|
||||||
accessibilityElements = [titleLabel, textField, helperLabel]
|
get {
|
||||||
|
var elements = [Any]()
|
||||||
|
elements.append(contentsOf: [titleLabel, textField])
|
||||||
|
if showError {
|
||||||
|
elements.append(statusIcon)
|
||||||
|
if let errorText, !errorText.isEmpty {
|
||||||
|
elements.append(errorLabel)
|
||||||
|
}
|
||||||
|
} else if showSuccess, let successText, !successText.isEmpty {
|
||||||
|
elements.append(successLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let helperText, !helperText.isEmpty {
|
||||||
|
elements.append(helperLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
return elements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set { super.accessibilityElements = newValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
open override var canBecomeFirstResponder: Bool { true }
|
open override var canBecomeFirstResponder: Bool { true }
|
||||||
@ -404,6 +427,47 @@ open class InputField: EntryFieldBase {
|
|||||||
|
|
||||||
open var hidePasswordButtonText: String = "Hide" { didSet { setNeedsUpdate() } }
|
open var hidePasswordButtonText: String = "Hide" { didSet { setNeedsUpdate() } }
|
||||||
open var showPasswordButtonText: String = "Show" { didSet { setNeedsUpdate() } }
|
open var showPasswordButtonText: String = "Show" { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Date
|
||||||
|
//--------------------------------------------------
|
||||||
|
open var dateFormat: DateFormat = .mmddyy { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension InputField: UITextFieldDelegate {
|
||||||
|
public func process(text changedText: String) {
|
||||||
|
var newText: String = changedText
|
||||||
|
switch fieldType {
|
||||||
|
case .date:
|
||||||
|
guard newText.count <= dateFormat.maxLength else { return }
|
||||||
|
let numericText = newText.compactMap { $0.isNumber ? $0 : nil }
|
||||||
|
var formattedText = ""
|
||||||
|
|
||||||
|
for (index, char) in numericText.enumerated() {
|
||||||
|
if (index == 2 || (index == 4 && (dateFormat != .mmyy))) && index < dateFormat.maxLength {
|
||||||
|
formattedText += "/"
|
||||||
|
}
|
||||||
|
formattedText.append(char)
|
||||||
|
}
|
||||||
|
newText = formattedText
|
||||||
|
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||||
|
switch fieldType {
|
||||||
|
case .date:
|
||||||
|
// Allow only numbers and limit the length of text.
|
||||||
|
let allowedCharacters = CharacterSet.decimalDigits
|
||||||
|
let characterSet = CharacterSet(charactersIn: string)
|
||||||
|
return allowedCharacters.isSuperset(of: characterSet) && ((textField.text?.count ?? 0) + string.count - range.length) <= dateFormat.maxLength
|
||||||
|
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension InputField.FieldType {
|
extension InputField.FieldType {
|
||||||
@ -425,3 +489,36 @@ extension InputField.FieldType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension InputField {
|
||||||
|
public enum DateFormat: String, CaseIterable {
|
||||||
|
case mmyy
|
||||||
|
case mmddyy
|
||||||
|
case mmddyyyy
|
||||||
|
|
||||||
|
public var placeholderText: String {
|
||||||
|
switch self {
|
||||||
|
case .mmyy: "MM/YY"
|
||||||
|
case .mmddyy: "MM/DD/YY"
|
||||||
|
case .mmddyyyy: "MM/DD/YYYY"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var formatString: String {
|
||||||
|
switch self {
|
||||||
|
case .mmyy: "MM/yy"
|
||||||
|
case .mmddyy: "MM/dd/yy"
|
||||||
|
case .mmddyyyy: "MM/dd/yyyy"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var maxLength: Int {
|
||||||
|
switch self {
|
||||||
|
case .mmyy: 5
|
||||||
|
case .mmddyy: 8
|
||||||
|
case .mmddyyyy: 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -10,6 +10,25 @@ import UIKit
|
|||||||
|
|
||||||
@objc(VDSTextField)
|
@objc(VDSTextField)
|
||||||
open class TextField: UITextField {
|
open class TextField: UITextField {
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initializers
|
||||||
|
//--------------------------------------------------
|
||||||
|
required public init() {
|
||||||
|
super.init(frame: .zero)
|
||||||
|
initialSetup()
|
||||||
|
}
|
||||||
|
|
||||||
|
public override init(frame: CGRect) {
|
||||||
|
super.init(frame: .zero)
|
||||||
|
initialSetup()
|
||||||
|
}
|
||||||
|
|
||||||
|
public required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
initialSetup()
|
||||||
|
}
|
||||||
|
|
||||||
var horizontalPadding: CGFloat = 0
|
var horizontalPadding: CGFloat = 0
|
||||||
|
|
||||||
open override func textRect(forBounds bounds: CGRect) -> CGRect {
|
open override func textRect(forBounds bounds: CGRect) -> CGRect {
|
||||||
@ -35,6 +54,25 @@ open class TextField: UITextField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open func initialSetup() {
|
||||||
|
let doneToolbar: UIToolbar = UIToolbar()
|
||||||
|
doneToolbar.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
doneToolbar.barStyle = .default
|
||||||
|
|
||||||
|
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
|
||||||
|
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.doneButtonAction))
|
||||||
|
done.accessibilityHint = "Double tap to finish editing."
|
||||||
|
doneToolbar.items = [flexSpace, done]
|
||||||
|
doneToolbar.sizeToFit()
|
||||||
|
|
||||||
|
inputAccessoryView = doneToolbar
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func doneButtonAction() {
|
||||||
|
// Resigns the first responder status when 'Done' is tapped
|
||||||
|
resignFirstResponder()
|
||||||
|
}
|
||||||
|
|
||||||
open override func becomeFirstResponder() -> Bool {
|
open override func becomeFirstResponder() -> Bool {
|
||||||
let success = super.becomeFirstResponder()
|
let success = super.becomeFirstResponder()
|
||||||
if isSecureTextEntry, let text {
|
if isSecureTextEntry, let text {
|
||||||
|
|||||||
@ -161,7 +161,6 @@ open class TextArea: EntryFieldBase {
|
|||||||
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
|
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
|
||||||
open override func setup() {
|
open override func setup() {
|
||||||
super.setup()
|
super.setup()
|
||||||
isAccessibilityElement = false
|
|
||||||
containerStackView.pinToSuperView(.uniform(VDSFormControls.spaceInset))
|
containerStackView.pinToSuperView(.uniform(VDSFormControls.spaceInset))
|
||||||
minWidthConstraint = containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: containerSize.width)
|
minWidthConstraint = containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: containerSize.width)
|
||||||
minWidthConstraint?.isActive = true
|
minWidthConstraint?.isActive = true
|
||||||
@ -264,13 +263,31 @@ open class TextArea: EntryFieldBase {
|
|||||||
open override func updateAccessibility() {
|
open override func updateAccessibility() {
|
||||||
super.updateAccessibility()
|
super.updateAccessibility()
|
||||||
textView.accessibilityLabel = showError ? "error" : nil
|
textView.accessibilityLabel = showError ? "error" : nil
|
||||||
if showError {
|
|
||||||
accessibilityElements = [titleLabel, textView, statusIcon, errorLabel, helperLabel]
|
|
||||||
} else {
|
|
||||||
accessibilityElements = [titleLabel, textView, helperLabel]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override var accessibilityElements: [Any]? {
|
||||||
|
get {
|
||||||
|
var elements = [Any]()
|
||||||
|
elements.append(contentsOf: [titleLabel, textView])
|
||||||
|
|
||||||
|
if showError {
|
||||||
|
elements.append(statusIcon)
|
||||||
|
if let errorText, !errorText.isEmpty {
|
||||||
|
elements.append(errorLabel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let helperText, !helperText.isEmpty {
|
||||||
|
elements.append(helperLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
return elements
|
||||||
|
}
|
||||||
|
|
||||||
|
set { super.accessibilityElements = newValue }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
open override var canBecomeFirstResponder: Bool { true }
|
open override var canBecomeFirstResponder: Bool { true }
|
||||||
|
|
||||||
open override func resignFirstResponder() -> Bool {
|
open override func resignFirstResponder() -> Bool {
|
||||||
|
|||||||
@ -97,7 +97,6 @@ open class TextView: UITextView, ViewProtocol {
|
|||||||
initialSetupPerformed = true
|
initialSetupPerformed = true
|
||||||
backgroundColor = .clear
|
backgroundColor = .clear
|
||||||
translatesAutoresizingMaskIntoConstraints = false
|
translatesAutoresizingMaskIntoConstraints = false
|
||||||
accessibilityCustomActions = []
|
|
||||||
setup()
|
setup()
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
@ -106,8 +105,25 @@ open class TextView: UITextView, ViewProtocol {
|
|||||||
|
|
||||||
open func setup() {
|
open func setup() {
|
||||||
translatesAutoresizingMaskIntoConstraints = false
|
translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
let doneToolbar: UIToolbar = UIToolbar()
|
||||||
|
doneToolbar.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
doneToolbar.barStyle = .default
|
||||||
|
|
||||||
|
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
|
||||||
|
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.doneButtonAction))
|
||||||
|
done.accessibilityHint = "Double tap to finish editing."
|
||||||
|
doneToolbar.items = [flexSpace, done]
|
||||||
|
doneToolbar.sizeToFit()
|
||||||
|
|
||||||
|
inputAccessoryView = doneToolbar
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func doneButtonAction() {
|
||||||
|
// Resigns the first responder status when 'Done' is tapped
|
||||||
|
resignFirstResponder()
|
||||||
|
}
|
||||||
|
|
||||||
open func updateView() {
|
open func updateView() {
|
||||||
updateLabel()
|
updateLabel()
|
||||||
}
|
}
|
||||||
@ -118,7 +134,6 @@ open class TextView: UITextView, ViewProtocol {
|
|||||||
shouldUpdateView = false
|
shouldUpdateView = false
|
||||||
surface = .light
|
surface = .light
|
||||||
text = nil
|
text = nil
|
||||||
accessibilityCustomActions = []
|
|
||||||
shouldUpdateView = true
|
shouldUpdateView = true
|
||||||
setNeedsUpdate()
|
setNeedsUpdate()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,7 +69,7 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
|
|||||||
case secondary
|
case secondary
|
||||||
case white
|
case white
|
||||||
case black
|
case black
|
||||||
case custom(String)
|
case custom(UIColor)
|
||||||
|
|
||||||
private var reflectedValue: String { String(reflecting: self) }
|
private var reflectedValue: String { String(reflecting: self) }
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
|
|||||||
/// Enum used to describe the background effect choices used for this component.
|
/// Enum used to describe the background effect choices used for this component.
|
||||||
public enum BackgroundEffect {
|
public enum BackgroundEffect {
|
||||||
case transparency
|
case transparency
|
||||||
case gradient(String, String)
|
case gradient(UIColor, UIColor)
|
||||||
case none
|
case none
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
|
|||||||
open var aspectRatio: AspectRatio = .ratio1x1 { didSet { setNeedsUpdate() } }
|
open var aspectRatio: AspectRatio = .ratio1x1 { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
/// Sets the background color for the component.
|
/// Sets the background color for the component.
|
||||||
open var color: BackgroundColor = .secondary { didSet { setNeedsUpdate() } }
|
open var color: BackgroundColor? { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
/// Sets the background effect for the component.
|
/// Sets the background effect for the component.
|
||||||
open var backgroundEffect: BackgroundEffect = .none { didSet { setNeedsUpdate() } }
|
open var backgroundEffect: BackgroundEffect = .none { didSet { setNeedsUpdate() } }
|
||||||
@ -188,14 +188,14 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
|
|||||||
// MARK: - Configuration
|
// MARK: - Configuration
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
private let cornerRadius = VDSFormControls.borderRadius * 2
|
private let cornerRadius = VDSFormControls.borderRadius * 2
|
||||||
private var backgroundColorConfiguration = BackgroundColorConfiguration()
|
internal var backgroundColorConfiguration = BackgroundColorConfiguration()
|
||||||
private let dropShadowConfiguration = DropShadowConfiguration().with {
|
private let dropShadowConfiguration = DropShadowConfiguration().with {
|
||||||
$0.shadowColorConfiguration = SurfaceColorConfiguration().with {
|
$0.shadowColorConfiguration = SurfaceColorConfiguration().with {
|
||||||
$0.lightColor = VDSColor.elementsPrimaryOnlight
|
$0.lightColor = VDSColor.elementsPrimaryOnlight
|
||||||
}.eraseToAnyColorable()
|
}.eraseToAnyColorable()
|
||||||
$0.shadowOffsetConfiguration = .init(.init(width: 0, height: 6), .zero)
|
$0.shadowOffsetConfiguration = .init(.init(width: 0, height: 6), .zero)
|
||||||
$0.shadowRadiusConfiguration = .init(3.0, 0.0)
|
$0.shadowRadiusConfiguration = .init(8.0, 0.0)
|
||||||
$0.shadowOpacityConfiguration = .init(0.01, 0.0)
|
$0.shadowOpacityConfiguration = .init(0.1, 0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var borderColorConfiguration = SurfaceColorConfiguration().with {
|
private var borderColorConfiguration = SurfaceColorConfiguration().with {
|
||||||
@ -329,7 +329,7 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
|
|||||||
}
|
}
|
||||||
|
|
||||||
applyBackgroundEffects()
|
applyBackgroundEffects()
|
||||||
|
|
||||||
if showDropShadow, surface == .light {
|
if showDropShadow, surface == .light {
|
||||||
addDropShadow(dropShadowConfiguration)
|
addDropShadow(dropShadowConfiguration)
|
||||||
} else {
|
} else {
|
||||||
@ -395,7 +395,7 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
|
|||||||
removeGradientLayer()
|
removeGradientLayer()
|
||||||
case .gradient(let firstColor, let secondColor):
|
case .gradient(let firstColor, let secondColor):
|
||||||
alphaConfiguration = 1.0
|
alphaConfiguration = 1.0
|
||||||
addGradientLayer(with: UIColor(hexString: firstColor), secondColor: UIColor(hexString: secondColor))
|
addGradientLayer(with: firstColor, secondColor: secondColor)
|
||||||
backgroundImageView.isHidden = true
|
backgroundImageView.isHidden = true
|
||||||
backgroundImageView.alpha = 1.0
|
backgroundImageView.alpha = 1.0
|
||||||
case .none:
|
case .none:
|
||||||
@ -461,17 +461,22 @@ extension TileContainerBase {
|
|||||||
required init() { }
|
required init() { }
|
||||||
|
|
||||||
func getColor(_ object: ObjectType) -> UIColor {
|
func getColor(_ object: ObjectType) -> UIColor {
|
||||||
switch object.color {
|
guard let color = object.color else {
|
||||||
|
let config = object.surface == .light ? blackColorConfig : whiteColorConfig
|
||||||
|
return config.getColor(object.surface)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch color {
|
||||||
case .primary:
|
case .primary:
|
||||||
primaryColorConfig.getColor(object.surface)
|
return primaryColorConfig.getColor(object.surface)
|
||||||
case .secondary:
|
case .secondary:
|
||||||
secondaryColorConfig.getColor(object.surface)
|
return secondaryColorConfig.getColor(object.surface)
|
||||||
case .white:
|
case .white:
|
||||||
whiteColorConfig.getColor(object.surface)
|
return whiteColorConfig.getColor(object.surface)
|
||||||
case .black:
|
case .black:
|
||||||
blackColorConfig.getColor(object.surface)
|
return blackColorConfig.getColor(object.surface)
|
||||||
case .custom(let hexCode):
|
case .custom(let color):
|
||||||
UIColor(hexString: hexCode)
|
return color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,6 +102,10 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
|
|||||||
$0.backgroundColor = .clear
|
$0.backgroundColor = .clear
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var backgroundColorSurface: Surface {
|
||||||
|
backgroundColorConfiguration.getColor(self).surface
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Public Properties
|
// MARK: - Public Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -444,7 +448,7 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
|
|||||||
badge.text = badgeModel.text
|
badge.text = badgeModel.text
|
||||||
badge.fillColor = badgeModel.fillColor
|
badge.fillColor = badgeModel.fillColor
|
||||||
badge.numberOfLines = badgeModel.numberOfLines
|
badge.numberOfLines = badgeModel.numberOfLines
|
||||||
badge.surface = badgeModel.surface
|
badge.surface = backgroundColorSurface
|
||||||
badge.maxWidth = badgeModel.maxWidth
|
badge.maxWidth = badgeModel.maxWidth
|
||||||
badgeLabelHeightGreaterThanConstraint?.constant = badge.label.minimumLineHeight
|
badgeLabelHeightGreaterThanConstraint?.constant = badge.label.minimumLineHeight
|
||||||
if badgeContainerView.superview == nil {
|
if badgeContainerView.superview == nil {
|
||||||
@ -474,7 +478,7 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
|
|||||||
|
|
||||||
if showTitleLockup {
|
if showTitleLockup {
|
||||||
//flip the surface for the titleLockup
|
//flip the surface for the titleLockup
|
||||||
titleLockup.surface = color == .black ? Surface.dark : Surface.light
|
titleLockup.surface = backgroundColorSurface
|
||||||
|
|
||||||
//titleLockup
|
//titleLockup
|
||||||
if let textWidth {
|
if let textWidth {
|
||||||
@ -529,14 +533,14 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
|
|||||||
if let descriptiveIconModel {
|
if let descriptiveIconModel {
|
||||||
descriptiveIcon.name = descriptiveIconModel.name
|
descriptiveIcon.name = descriptiveIconModel.name
|
||||||
descriptiveIcon.size = descriptiveIconModel.size
|
descriptiveIcon.size = descriptiveIconModel.size
|
||||||
descriptiveIcon.surface = descriptiveIconModel.surface
|
descriptiveIcon.surface = backgroundColorSurface
|
||||||
descriptiveIcon.accessibilityLabel = descriptiveIconModel.accessibleText
|
descriptiveIcon.accessibilityLabel = descriptiveIconModel.accessibleText
|
||||||
showIconContainerView = true
|
showIconContainerView = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if let directionalIconModel {
|
if let directionalIconModel {
|
||||||
directionalIcon.size = directionalIconModel.size
|
directionalIcon.size = directionalIconModel.size
|
||||||
directionalIcon.surface = directionalIconModel.surface
|
directionalIcon.surface = backgroundColorSurface
|
||||||
directionalIcon.accessibilityLabel = "Right arrow"
|
directionalIcon.accessibilityLabel = "Right arrow"
|
||||||
showIconContainerView = true
|
showIconContainerView = true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,8 +36,8 @@ extension Tilelet {
|
|||||||
public var textAttributes: [any LabelAttributeModel]?
|
public var textAttributes: [any LabelAttributeModel]?
|
||||||
|
|
||||||
/// Text color that will be used for the subTitle label.
|
/// Text color that will be used for the subTitle label.
|
||||||
public var textColor: Use = .primary
|
public var textColor: TitleLockup.TextColor
|
||||||
|
|
||||||
/// LineBreakMode used in Badge label.
|
/// LineBreakMode used in Badge label.
|
||||||
public var lineBreakMode: NSLineBreakMode
|
public var lineBreakMode: NSLineBreakMode
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ extension Tilelet {
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
public init(text: String,
|
public init(text: String,
|
||||||
otherStandardStyle: OtherStandardStyle = .bodySmall,
|
otherStandardStyle: OtherStandardStyle = .bodySmall,
|
||||||
textColor: Use = .primary,
|
textColor: TitleLockup.TextColor = .primary,
|
||||||
textAttributes: [any LabelAttributeModel]? = nil,
|
textAttributes: [any LabelAttributeModel]? = nil,
|
||||||
lineBreakMode: NSLineBreakMode = .byTruncatingTail) {
|
lineBreakMode: NSLineBreakMode = .byTruncatingTail) {
|
||||||
self.text = text
|
self.text = text
|
||||||
@ -64,7 +64,8 @@ extension Tilelet {
|
|||||||
TitleLockup.SubTitleModel(text: text,
|
TitleLockup.SubTitleModel(text: text,
|
||||||
otherStandardStyle: otherStandardStyle.value,
|
otherStandardStyle: otherStandardStyle.value,
|
||||||
textColor: textColor,
|
textColor: textColor,
|
||||||
textAttributes: textAttributes, lineBreakMode: lineBreakMode)
|
textAttributes: textAttributes,
|
||||||
|
lineBreakMode: lineBreakMode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,9 @@ extension Tilelet {
|
|||||||
/// Text that will be used for the title label.
|
/// Text that will be used for the title label.
|
||||||
public var text: String = ""
|
public var text: String = ""
|
||||||
|
|
||||||
|
/// TextColor that will be used for the title label.
|
||||||
|
public var textColor: TitleLockup.TitleTextColor
|
||||||
|
|
||||||
/// Used in combination with standardStyle to set the textStyle that will be used for the title label.
|
/// Used in combination with standardStyle to set the textStyle that will be used for the title label.
|
||||||
public var isBold: Bool = false
|
public var isBold: Bool = false
|
||||||
/// Text attributes that will be used for the title label.
|
/// Text attributes that will be used for the title label.
|
||||||
@ -47,11 +50,13 @@ extension Tilelet {
|
|||||||
// MARK: - Initializers
|
// MARK: - Initializers
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
public init(text: String,
|
public init(text: String,
|
||||||
|
textColor: TitleLockup.TitleTextColor = .primary,
|
||||||
textAttributes: [any LabelAttributeModel]? = nil,
|
textAttributes: [any LabelAttributeModel]? = nil,
|
||||||
isBold: Bool = true,
|
isBold: Bool = true,
|
||||||
standardStyle: StandardStyle = .titleSmall,
|
standardStyle: StandardStyle = .titleSmall,
|
||||||
lineBreakMode: NSLineBreakMode = .byTruncatingTail) {
|
lineBreakMode: NSLineBreakMode = .byTruncatingTail) {
|
||||||
self.text = text
|
self.text = text
|
||||||
|
self.textColor = textColor
|
||||||
self.textAttributes = textAttributes
|
self.textAttributes = textAttributes
|
||||||
self.standardStyle = standardStyle
|
self.standardStyle = standardStyle
|
||||||
self.isBold = isBold
|
self.isBold = isBold
|
||||||
@ -64,8 +69,11 @@ extension Tilelet {
|
|||||||
/// Converts this type of model to a TitleLockup.TitleModel.
|
/// Converts this type of model to a TitleLockup.TitleModel.
|
||||||
public func toTitleLockupTitleModel() -> TitleLockup.TitleModel {
|
public func toTitleLockupTitleModel() -> TitleLockup.TitleModel {
|
||||||
TitleLockup.TitleModel(text: text,
|
TitleLockup.TitleModel(text: text,
|
||||||
|
textColor: textColor,
|
||||||
textAttributes: textAttributes,
|
textAttributes: textAttributes,
|
||||||
isBold: isBold, standardStyle: standardStyle.value, lineBreakMode: lineBreakMode)
|
isBold: isBold,
|
||||||
|
standardStyle: standardStyle.value,
|
||||||
|
lineBreakMode: lineBreakMode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,9 @@ extension Tilelet {
|
|||||||
/// Text that will be used for the eyebrow label.
|
/// Text that will be used for the eyebrow label.
|
||||||
public var text: String = ""
|
public var text: String = ""
|
||||||
|
|
||||||
|
/// Text color that will be used for the eyebrow label
|
||||||
|
public var textColor: TitleLockup.TextColor
|
||||||
|
|
||||||
/// Used in combination with standardStyle to set the textStyle that will be used for the eyebrow label.
|
/// Used in combination with standardStyle to set the textStyle that will be used for the eyebrow label.
|
||||||
public var isBold: Bool = false
|
public var isBold: Bool = false
|
||||||
/// Text attributes that will be used for the eyebrow label.
|
/// Text attributes that will be used for the eyebrow label.
|
||||||
@ -33,11 +36,13 @@ extension Tilelet {
|
|||||||
// MARK: - Initializers
|
// MARK: - Initializers
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
public init(text: String,
|
public init(text: String,
|
||||||
|
textColor: TitleLockup.TextColor = .primary,
|
||||||
textAttributes: [any LabelAttributeModel]? = nil,
|
textAttributes: [any LabelAttributeModel]? = nil,
|
||||||
isBold: Bool = true,
|
isBold: Bool = true,
|
||||||
standardStyle: Tilelet.SubTitleModel.OtherStandardStyle = .bodySmall,
|
standardStyle: Tilelet.SubTitleModel.OtherStandardStyle = .bodySmall,
|
||||||
lineBreakMode: NSLineBreakMode = .byTruncatingTail) {
|
lineBreakMode: NSLineBreakMode = .byTruncatingTail) {
|
||||||
self.text = text
|
self.text = text
|
||||||
|
self.textColor = textColor
|
||||||
self.textAttributes = textAttributes
|
self.textAttributes = textAttributes
|
||||||
self.standardStyle = standardStyle
|
self.standardStyle = standardStyle
|
||||||
self.isBold = isBold
|
self.isBold = isBold
|
||||||
@ -49,7 +54,11 @@ extension Tilelet {
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
/// Converts this type of model to a TitleLockup.TitleModel.
|
/// Converts this type of model to a TitleLockup.TitleModel.
|
||||||
public func toTitleLockupEyebrowModel() -> TitleLockup.EyebrowModel {
|
public func toTitleLockupEyebrowModel() -> TitleLockup.EyebrowModel {
|
||||||
TitleLockup.EyebrowModel(text: text, isBold: isBold, standardStyle: standardStyle.value, textAttributes: textAttributes)
|
TitleLockup.EyebrowModel(text: text,
|
||||||
|
textColor: textColor,
|
||||||
|
isBold: isBold,
|
||||||
|
standardStyle: standardStyle.value,
|
||||||
|
textAttributes: textAttributes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -258,22 +258,10 @@ open class TitleLockup: View {
|
|||||||
bottomSpacing: VDSLayout.space6X)
|
bottomSpacing: VDSLayout.space6X)
|
||||||
]),
|
]),
|
||||||
])
|
])
|
||||||
|
|
||||||
private var textColorSecondaryConfiguration = SurfaceColorConfiguration(VDSColor.elementsSecondaryOnlight , VDSColor.elementsSecondaryOnlight).eraseToAnyColorable()
|
|
||||||
|
|
||||||
private var textColorPrimaryConfiguration = SurfaceColorConfiguration(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark).eraseToAnyColorable()
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Overrides
|
// MARK: - Overrides
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
|
|
||||||
open override func setup() {
|
|
||||||
super.setup()
|
|
||||||
|
|
||||||
titleLabel.textColorConfiguration = textColorPrimaryConfiguration
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
open override func updateAccessibility() {
|
open override func updateAccessibility() {
|
||||||
super.updateAccessibility()
|
super.updateAccessibility()
|
||||||
var elements = [Any]()
|
var elements = [Any]()
|
||||||
@ -330,6 +318,7 @@ open class TitleLockup: View {
|
|||||||
if let eyebrowModel, !eyebrowModel.text.isEmpty {
|
if let eyebrowModel, !eyebrowModel.text.isEmpty {
|
||||||
eyebrowLabel.textAlignment = allLabelsTextAlignment
|
eyebrowLabel.textAlignment = allLabelsTextAlignment
|
||||||
eyebrowLabel.text = eyebrowModel.text
|
eyebrowLabel.text = eyebrowModel.text
|
||||||
|
eyebrowLabel.textColorConfiguration = eyebrowModel.textColor.configuration
|
||||||
eyebrowLabel.attributes = eyebrowModel.textAttributes
|
eyebrowLabel.attributes = eyebrowModel.textAttributes
|
||||||
eyebrowLabel.numberOfLines = eyebrowModel.numberOfLines
|
eyebrowLabel.numberOfLines = eyebrowModel.numberOfLines
|
||||||
eyebrowLabel.surface = surface
|
eyebrowLabel.surface = surface
|
||||||
@ -339,15 +328,12 @@ open class TitleLockup: View {
|
|||||||
//When uniform size is true and the title is bold,
|
//When uniform size is true and the title is bold,
|
||||||
//the eyebrow is always regular weight and the secondary color.
|
//the eyebrow is always regular weight and the secondary color.
|
||||||
eyebrowLabel.textStyle = otherStandardStyle.value.regular
|
eyebrowLabel.textStyle = otherStandardStyle.value.regular
|
||||||
eyebrowLabel.textColorConfiguration = textColorSecondaryConfiguration
|
|
||||||
} else {
|
} else {
|
||||||
//When uniform size is true and the title is regular weight
|
//When uniform size is true and the title is regular weight
|
||||||
//the eyebrow is always bold and uses the primary color.
|
//the eyebrow is always bold and uses the primary color.
|
||||||
eyebrowLabel.textStyle = otherStandardStyle.value.bold
|
eyebrowLabel.textStyle = otherStandardStyle.value.bold
|
||||||
eyebrowLabel.textColorConfiguration = textColorPrimaryConfiguration
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
eyebrowLabel.textColorConfiguration = textColorPrimaryConfiguration
|
|
||||||
eyebrowLabel.textStyle = eyebrowModel.isBold ? otherStandardStyle.value.bold : otherStandardStyle.value.regular
|
eyebrowLabel.textStyle = eyebrowModel.isBold ? otherStandardStyle.value.bold : otherStandardStyle.value.regular
|
||||||
}
|
}
|
||||||
addSubview(eyebrowLabel)
|
addSubview(eyebrowLabel)
|
||||||
@ -363,6 +349,7 @@ open class TitleLockup: View {
|
|||||||
if let titleModel, !titleModel.text.isEmpty {
|
if let titleModel, !titleModel.text.isEmpty {
|
||||||
titleLabel.textAlignment = allLabelsTextAlignment
|
titleLabel.textAlignment = allLabelsTextAlignment
|
||||||
titleLabel.textStyle = titleModel.textStyle
|
titleLabel.textStyle = titleModel.textStyle
|
||||||
|
titleLabel.textColorConfiguration = titleModel.textColor.configuration
|
||||||
titleLabel.text = titleModel.text
|
titleLabel.text = titleModel.text
|
||||||
titleLabel.attributes = titleModel.textAttributes
|
titleLabel.attributes = titleModel.textAttributes
|
||||||
titleLabel.numberOfLines = titleModel.numberOfLines
|
titleLabel.numberOfLines = titleModel.numberOfLines
|
||||||
@ -381,7 +368,7 @@ open class TitleLockup: View {
|
|||||||
if let subTitleModel, !subTitleModel.text.isEmpty {
|
if let subTitleModel, !subTitleModel.text.isEmpty {
|
||||||
subTitleLabel.textAlignment = allLabelsTextAlignment
|
subTitleLabel.textAlignment = allLabelsTextAlignment
|
||||||
subTitleLabel.textStyle = otherStandardStyle.value.regular
|
subTitleLabel.textStyle = otherStandardStyle.value.regular
|
||||||
subTitleLabel.textColorConfiguration = subTitleModel.textColor == .secondary ? textColorSecondaryConfiguration : textColorPrimaryConfiguration
|
subTitleLabel.textColorConfiguration = subTitleModel.textColor.configuration
|
||||||
subTitleLabel.text = subTitleModel.text
|
subTitleLabel.text = subTitleModel.text
|
||||||
subTitleLabel.attributes = subTitleModel.textAttributes
|
subTitleLabel.attributes = subTitleModel.textAttributes
|
||||||
subTitleLabel.numberOfLines = subTitleModel.numberOfLines
|
subTitleLabel.numberOfLines = subTitleModel.numberOfLines
|
||||||
|
|||||||
@ -13,6 +13,9 @@ extension TitleLockup {
|
|||||||
/// Text that will be used for the eyebrow label.
|
/// Text that will be used for the eyebrow label.
|
||||||
public var text: String
|
public var text: String
|
||||||
|
|
||||||
|
/// Text color that will be used for the eyebrow label
|
||||||
|
public var textColor: TextColor
|
||||||
|
|
||||||
/// Used in combination with standardStyle to set the textStyle that will be used for the eyebrow label.
|
/// Used in combination with standardStyle to set the textStyle that will be used for the eyebrow label.
|
||||||
public var isBold: Bool
|
public var isBold: Bool
|
||||||
|
|
||||||
@ -26,11 +29,13 @@ extension TitleLockup {
|
|||||||
public var numberOfLines: Int
|
public var numberOfLines: Int
|
||||||
|
|
||||||
public init(text: String,
|
public init(text: String,
|
||||||
|
textColor: TextColor = .primary,
|
||||||
isBold: Bool = true,
|
isBold: Bool = true,
|
||||||
standardStyle: OtherStandardStyle = .bodyLarge,
|
standardStyle: OtherStandardStyle = .bodyLarge,
|
||||||
textAttributes: [any LabelAttributeModel]? = nil,
|
textAttributes: [any LabelAttributeModel]? = nil,
|
||||||
numberOfLines: Int = 0) {
|
numberOfLines: Int = 0) {
|
||||||
self.text = text
|
self.text = text
|
||||||
|
self.textColor = textColor
|
||||||
self.isBold = isBold
|
self.isBold = isBold
|
||||||
self.standardStyle = standardStyle
|
self.standardStyle = standardStyle
|
||||||
self.textAttributes = textAttributes
|
self.textAttributes = textAttributes
|
||||||
@ -41,3 +46,4 @@ extension TitleLockup {
|
|||||||
public var textStyle: TextStyle { isBold ? standardStyle.value.bold : standardStyle.value.regular }
|
public var textStyle: TextStyle { isBold ? standardStyle.value.bold : standardStyle.value.regular }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ extension TitleLockup {
|
|||||||
public var otherStandardStyle: OtherStandardStyle
|
public var otherStandardStyle: OtherStandardStyle
|
||||||
|
|
||||||
/// Text color used in the subtitle label.
|
/// Text color used in the subtitle label.
|
||||||
public var textColor: Use
|
public var textColor: TextColor
|
||||||
|
|
||||||
/// Array of LabelAttributeModel objects used in rendering the text in the subtitle label.
|
/// Array of LabelAttributeModel objects used in rendering the text in the subtitle label.
|
||||||
public var textAttributes: [any LabelAttributeModel]?
|
public var textAttributes: [any LabelAttributeModel]?
|
||||||
@ -31,7 +31,7 @@ extension TitleLockup {
|
|||||||
|
|
||||||
public init(text: String,
|
public init(text: String,
|
||||||
otherStandardStyle: OtherStandardStyle = .bodyLarge,
|
otherStandardStyle: OtherStandardStyle = .bodyLarge,
|
||||||
textColor: Use = .primary,
|
textColor: TextColor = .primary,
|
||||||
textAttributes: [any LabelAttributeModel]? = nil,
|
textAttributes: [any LabelAttributeModel]? = nil,
|
||||||
numberOfLines: Int = 0,
|
numberOfLines: Int = 0,
|
||||||
lineBreakMode: NSLineBreakMode = .byWordWrapping) {
|
lineBreakMode: NSLineBreakMode = .byWordWrapping) {
|
||||||
|
|||||||
59
VDS/Components/TitleLockup/TitleLockupTextColor.swift
Normal file
59
VDS/Components/TitleLockup/TitleLockupTextColor.swift
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// TitleLockupTextColor.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 5/6/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import VDSTokens
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension TitleLockup {
|
||||||
|
private static var textColorSecondaryConfiguration = SurfaceColorConfiguration(VDSColor.elementsSecondaryOnlight , VDSColor.elementsSecondaryOnlight).eraseToAnyColorable()
|
||||||
|
|
||||||
|
private static var textColorPrimaryConfiguration = SurfaceColorConfiguration(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark).eraseToAnyColorable()
|
||||||
|
|
||||||
|
public enum TextColor: Equatable {
|
||||||
|
case primary
|
||||||
|
case secondary
|
||||||
|
case custom(UIColor, UIColor)
|
||||||
|
|
||||||
|
private var reflectedValue: String { String(reflecting: self) }
|
||||||
|
|
||||||
|
public static func == (lhs: Self, rhs: Self) -> Bool {
|
||||||
|
lhs.reflectedValue == rhs.reflectedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
public var configuration: AnyColorable {
|
||||||
|
switch self {
|
||||||
|
case .primary:
|
||||||
|
TitleLockup.textColorPrimaryConfiguration
|
||||||
|
case .secondary:
|
||||||
|
TitleLockup.textColorSecondaryConfiguration
|
||||||
|
case .custom(let lightColor, let darkColor):
|
||||||
|
SurfaceColorConfiguration(lightColor, darkColor).eraseToAnyColorable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TitleTextColor: Equatable {
|
||||||
|
case primary
|
||||||
|
case custom(UIColor, UIColor)
|
||||||
|
|
||||||
|
private var reflectedValue: String { String(reflecting: self) }
|
||||||
|
|
||||||
|
public static func == (lhs: Self, rhs: Self) -> Bool {
|
||||||
|
lhs.reflectedValue == rhs.reflectedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
public var configuration: AnyColorable {
|
||||||
|
switch self {
|
||||||
|
case .primary:
|
||||||
|
TitleLockup.textColorPrimaryConfiguration
|
||||||
|
case .custom(let lightColor, let darkColor):
|
||||||
|
SurfaceColorConfiguration(lightColor, darkColor).eraseToAnyColorable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -14,7 +14,10 @@ extension TitleLockup {
|
|||||||
/// Text that will be used for the title label.
|
/// Text that will be used for the title label.
|
||||||
public var text: String
|
public var text: String
|
||||||
|
|
||||||
/// Array of LabelAttributeModel objects used in rendering the text.
|
/// Text color that will be used for the eyebrow label
|
||||||
|
public var textColor: TitleTextColor
|
||||||
|
|
||||||
|
/// Array of LabelAttributeModel objects used in rendering the text.
|
||||||
public var textAttributes: [any LabelAttributeModel]?
|
public var textAttributes: [any LabelAttributeModel]?
|
||||||
|
|
||||||
/// Used in combination with standardStyle to set the textStyle that will be used for the title label.
|
/// Used in combination with standardStyle to set the textStyle that will be used for the title label.
|
||||||
@ -30,12 +33,14 @@ extension TitleLockup {
|
|||||||
public var lineBreakMode: NSLineBreakMode
|
public var lineBreakMode: NSLineBreakMode
|
||||||
|
|
||||||
public init(text: String,
|
public init(text: String,
|
||||||
|
textColor: TitleTextColor = .primary,
|
||||||
textAttributes: [any LabelAttributeModel]? = nil,
|
textAttributes: [any LabelAttributeModel]? = nil,
|
||||||
isBold: Bool = true,
|
isBold: Bool = true,
|
||||||
standardStyle: TitleStandardStyle = .featureXSmall,
|
standardStyle: TitleStandardStyle = .featureXSmall,
|
||||||
numberOfLines: Int = 0,
|
numberOfLines: Int = 0,
|
||||||
lineBreakMode: NSLineBreakMode = .byTruncatingTail) {
|
lineBreakMode: NSLineBreakMode = .byTruncatingTail) {
|
||||||
self.text = text
|
self.text = text
|
||||||
|
self.textColor = textColor
|
||||||
self.isBold = isBold
|
self.isBold = isBold
|
||||||
self.textAttributes = textAttributes
|
self.textAttributes = textAttributes
|
||||||
self.standardStyle = standardStyle
|
self.standardStyle = standardStyle
|
||||||
|
|||||||
@ -48,7 +48,6 @@ open class TooltipDialog: View, UIScrollViewDelegate {
|
|||||||
|
|
||||||
lazy var primaryAccessibilityElement = UIAccessibilityElement(accessibilityContainer: self).with {
|
lazy var primaryAccessibilityElement = UIAccessibilityElement(accessibilityContainer: self).with {
|
||||||
$0.accessibilityLabel = "Modal"
|
$0.accessibilityLabel = "Modal"
|
||||||
$0.accessibilityFrameInContainerSpace = .init(origin: .zero, size: .init(width: fullWidth, height: VDSLayout.space1X))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -222,7 +221,8 @@ open class TooltipDialog: View, UIScrollViewDelegate {
|
|||||||
super.updateAccessibility()
|
super.updateAccessibility()
|
||||||
|
|
||||||
primaryAccessibilityElement.accessibilityHint = "Double tap on the \(tooltipModel.closeButtonText) button to close."
|
primaryAccessibilityElement.accessibilityHint = "Double tap on the \(tooltipModel.closeButtonText) button to close."
|
||||||
|
primaryAccessibilityElement.accessibilityFrameInContainerSpace = .init(origin: .zero, size: frame.size)
|
||||||
|
|
||||||
var elements: [Any] = [primaryAccessibilityElement]
|
var elements: [Any] = [primaryAccessibilityElement]
|
||||||
contentStackView.arrangedSubviews.forEach{ elements.append($0) }
|
contentStackView.arrangedSubviews.forEach{ elements.append($0) }
|
||||||
elements.append(closeButton)
|
elements.append(closeButton)
|
||||||
|
|||||||
@ -17,16 +17,19 @@ extension Tooltip {
|
|||||||
public var title: String?
|
public var title: String?
|
||||||
public var content: String?
|
public var content: String?
|
||||||
public var contentView: UIView?
|
public var contentView: UIView?
|
||||||
|
public var accessibleText: String?
|
||||||
public var contentViewAlignment: UIStackView.Alignment?
|
public var contentViewAlignment: UIStackView.Alignment?
|
||||||
public init(closeButtonText: String = "Close",
|
public init(closeButtonText: String = "Close",
|
||||||
title: String? = nil,
|
title: String? = nil,
|
||||||
content: String? = nil,
|
content: String? = nil,
|
||||||
contentView: UIView? = nil,
|
contentView: UIView? = nil,
|
||||||
|
accessibleText: String? = "Tooltip",
|
||||||
contentViewAlignment: UIStackView.Alignment = .leading) {
|
contentViewAlignment: UIStackView.Alignment = .leading) {
|
||||||
self.closeButtonText = closeButtonText
|
self.closeButtonText = closeButtonText
|
||||||
self.title = title
|
self.title = title
|
||||||
self.content = content
|
self.content = content
|
||||||
self.contentView = contentView
|
self.contentView = contentView
|
||||||
|
self.accessibleText = accessibleText
|
||||||
self.contentViewAlignment = contentViewAlignment
|
self.contentViewAlignment = contentViewAlignment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -176,4 +176,10 @@ extension UIColor {
|
|||||||
guard let found else { return nil}
|
guard let found else { return nil}
|
||||||
return found
|
return found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var surface: Surface {
|
||||||
|
var greyScale: CGFloat = 0
|
||||||
|
getWhite(&greyScale, alpha: nil)
|
||||||
|
return greyScale < 0.5 ? .dark : .light
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,8 @@
|
|||||||
|
1.0.62
|
||||||
|
----------------
|
||||||
|
- CXTDT-546824 - Notification - Accessibility - Redundant text is provided for the notification icon.
|
||||||
|
- CXTDT-553663 - DropdownSelect - Accessibility - 5 issues
|
||||||
|
|
||||||
1.0.61
|
1.0.61
|
||||||
----------------
|
----------------
|
||||||
- CXTDT-552068 - Text Area - Text padding
|
- CXTDT-552068 - Text Area - Text padding
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user