Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/vds_ios into feature/Table
This commit is contained in:
commit
a82550ed57
@ -1393,7 +1393,7 @@
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 59;
|
||||
CURRENT_PROJECT_VERSION = 60;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
@ -1430,7 +1430,7 @@
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 59;
|
||||
CURRENT_PROJECT_VERSION = 60;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
|
||||
@ -35,13 +35,7 @@ open class Control: UIControl, ViewProtocol, UserInfoable, Clickable {
|
||||
//--------------------------------------------------
|
||||
open var subscribers = Set<AnyCancellable>()
|
||||
|
||||
open var onClickSubscriber: AnyCancellable? {
|
||||
willSet {
|
||||
if let onClickSubscriber {
|
||||
onClickSubscriber.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
open var onClickSubscriber: AnyCancellable?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Private Properties
|
||||
@ -118,6 +112,8 @@ open class Control: UIControl, ViewProtocol, UserInfoable, Clickable {
|
||||
backgroundColor = .clear
|
||||
surface = .light
|
||||
isEnabled = true
|
||||
onClick = nil
|
||||
userInfo.removeAll()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -47,13 +47,7 @@ open class SelectorBase: Control, SelectorControlable {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
open var onChangeSubscriber: AnyCancellable? {
|
||||
willSet {
|
||||
if let onChangeSubscriber {
|
||||
onChangeSubscriber.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
open var onChangeSubscriber: AnyCancellable?
|
||||
|
||||
open var size = CGSize(width: 20, height: 20) { didSet { setNeedsUpdate() } }
|
||||
|
||||
@ -120,7 +114,6 @@ open class SelectorBase: Control, SelectorControlable {
|
||||
accessibilityTraits = .button
|
||||
}
|
||||
|
||||
/// Used to make changes to the View based off a change events or from local properties.
|
||||
open override func updateView() {
|
||||
super.updateView()
|
||||
setNeedsLayout()
|
||||
@ -130,9 +123,14 @@ open class SelectorBase: Control, SelectorControlable {
|
||||
/// Used to update any Accessibility properties.ß
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
accessibilityLabel = "\(Self.self)\(showError ? ", error" : "")"
|
||||
}
|
||||
|
||||
/// This will change the state of the Selector and execute the actionBlock if provided.
|
||||
open func toggle() { }
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
onChange = nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,13 +75,7 @@ open class SelectorGroupBase<SelectorItemType: Control>: Control, SelectorGroup,
|
||||
}
|
||||
}
|
||||
|
||||
open var onChangeSubscriber: AnyCancellable? {
|
||||
willSet {
|
||||
if let onChangeSubscriber {
|
||||
onChangeSubscriber.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
open var onChangeSubscriber: AnyCancellable?
|
||||
|
||||
/// Whether the Control is enabled or not.
|
||||
override open var isEnabled: Bool {
|
||||
@ -130,6 +124,7 @@ open class SelectorGroupBase<SelectorItemType: Control>: Control, SelectorGroup,
|
||||
/// Resets to default settings.
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
onChange = nil
|
||||
items.forEach{ $0.reset() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,13 +61,7 @@ open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable,
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
open var onChangeSubscriber: AnyCancellable? {
|
||||
willSet {
|
||||
if let onChangeSubscriber {
|
||||
onChangeSubscriber.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
open var onChangeSubscriber: AnyCancellable?
|
||||
|
||||
/// Label used to render labelText.
|
||||
open var label = Label().with {
|
||||
@ -196,7 +190,7 @@ open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable,
|
||||
/// Used to update any Accessibility properties.
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
setAccessibilityLabel(for: [label, childLabel, errorLabel])
|
||||
setAccessibilityLabel(for: [selectorView, label, childLabel, errorLabel])
|
||||
}
|
||||
|
||||
/// Resets to default settings.
|
||||
@ -223,6 +217,7 @@ open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable,
|
||||
value = nil
|
||||
isSelected = false
|
||||
|
||||
onChange = nil
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
@ -344,7 +344,6 @@ open class BadgeIndicator: View {
|
||||
label.isEnabled = isEnabled
|
||||
label.sizeToFit()
|
||||
setNeedsLayout()
|
||||
layoutIfNeeded()
|
||||
}
|
||||
|
||||
open override func updateAccessibility() {
|
||||
|
||||
@ -84,7 +84,7 @@ final class BreadcrumbCellItem: UICollectionViewCell {
|
||||
separator.textColor = textColorConfiguration.getColor(surface)
|
||||
separator.isHidden = hideSlash
|
||||
self.breadCrumbItem = breadCrumbItem
|
||||
layoutIfNeeded()
|
||||
setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -38,13 +38,7 @@ open class ButtonBase: UIButton, ViewProtocol, UserInfoable, Clickable {
|
||||
/// Set of Subscribers for any Publishers for this Control.
|
||||
open var subscribers = Set<AnyCancellable>()
|
||||
|
||||
open var onClickSubscriber: AnyCancellable? {
|
||||
willSet {
|
||||
if let onClickSubscriber {
|
||||
onClickSubscriber.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
open var onClickSubscriber: AnyCancellable?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Private Properties
|
||||
@ -140,6 +134,8 @@ open class ButtonBase: UIButton, ViewProtocol, UserInfoable, Clickable {
|
||||
isEnabled = true
|
||||
text = nil
|
||||
accessibilityCustomActions = []
|
||||
onClick = nil
|
||||
userInfo.removeAll()
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
@ -42,7 +42,6 @@ open class Checkbox: SelectorBase {
|
||||
/// 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()
|
||||
accessibilityLabel = "Checkbox"
|
||||
|
||||
backgroundColorConfiguration.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .selected)
|
||||
backgroundColorConfiguration.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: [.selected, .highlighted])
|
||||
|
||||
@ -109,6 +109,7 @@ open class ButtonIcon: Control, Changeable, FormFieldable {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
public var onChangeSubscriber: AnyCancellable?
|
||||
|
||||
///Badge Indicator object used to render for the ButtonIcon.
|
||||
open var badgeIndicator = BadgeIndicator().with {
|
||||
@ -172,8 +173,6 @@ open class ButtonIcon: Control, Changeable, FormFieldable {
|
||||
/// Used to move the icon inside the button in both x and y axis.
|
||||
open var iconOffset: CGPoint = .init(x: 0, y: 0) { didSet { setNeedsUpdate() } }
|
||||
|
||||
open var onChangeSubscriber: AnyCancellable?
|
||||
|
||||
open var inputId: String? { didSet { setNeedsUpdate() } }
|
||||
|
||||
open var value: AnyHashable? { didSet { setNeedsUpdate() } }
|
||||
@ -365,7 +364,6 @@ open class ButtonIcon: Control, Changeable, FormFieldable {
|
||||
open override func setup() {
|
||||
super.setup()
|
||||
isAccessibilityElement = false
|
||||
accessibilityElements = [icon, badgeIndicator]
|
||||
|
||||
//create a layoutGuide for the icon to key off of
|
||||
let iconLayoutGuide = UILayoutGuide()
|
||||
@ -436,6 +434,7 @@ open class ButtonIcon: Control, Changeable, FormFieldable {
|
||||
showBadgeIndicator = false
|
||||
selectable = false
|
||||
badgeIndicatorModel = nil
|
||||
onChange = nil
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
@ -459,6 +458,18 @@ open class ButtonIcon: Control, Changeable, FormFieldable {
|
||||
setNeedsLayout()
|
||||
}
|
||||
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
var elements = [Any]()
|
||||
if iconName != nil {
|
||||
elements.append(icon)
|
||||
}
|
||||
if badgeIndicatorModel != nil && showBadgeIndicator {
|
||||
elements.append(badgeIndicator)
|
||||
}
|
||||
accessibilityElements = elements.count > 0 ? elements : nil
|
||||
}
|
||||
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
|
||||
@ -31,12 +31,13 @@ public struct ColorLabelAttribute: LabelAttributeModel {
|
||||
}
|
||||
|
||||
public func setAttribute(on attributedString: NSMutableAttributedString) {
|
||||
guard isValidRange(on: attributedString) else { return }
|
||||
|
||||
var colorRange = range
|
||||
if length == 0 && location == 0 {
|
||||
colorRange = .init(location: location, length: attributedString.length)
|
||||
}
|
||||
|
||||
if !attributedString.isValid(range: colorRange) { return }
|
||||
|
||||
let attributeKey = isForegroundColor ? NSAttributedString.Key.foregroundColor : NSAttributedString.Key.backgroundColor
|
||||
attributedString.removeAttribute(attributeKey, range: colorRange)
|
||||
attributedString.addAttribute(attributeKey, value: color, range: colorRange)
|
||||
|
||||
@ -230,7 +230,6 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
|
||||
setNeedsDisplay()
|
||||
|
||||
setNeedsLayout()
|
||||
layoutIfNeeded()
|
||||
}
|
||||
|
||||
open func updateAccessibility() {
|
||||
|
||||
@ -264,8 +264,6 @@ open class Notification: View {
|
||||
isAccessibilityElement = false
|
||||
accessibilityElements = [closeButton, typeIcon, titleLabel, subTitleLabel, buttonGroup]
|
||||
closeButton.accessibilityTraits = [.button]
|
||||
closeButton.accessibilityLabel = "Close Notification"
|
||||
|
||||
}
|
||||
|
||||
/// Resets to default settings.
|
||||
@ -325,7 +323,6 @@ open class Notification: View {
|
||||
let iconColor = surface == .dark ? VDSColor.paletteWhite : VDSColor.paletteBlack
|
||||
typeIcon.name = style.iconName
|
||||
typeIcon.color = iconColor
|
||||
typeIcon.accessibilityLabel = style.accessibilityText
|
||||
closeButton.color = iconColor
|
||||
closeButton.isHidden = hideCloseButton
|
||||
}
|
||||
@ -374,6 +371,12 @@ open class Notification: View {
|
||||
}
|
||||
}
|
||||
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
closeButton.accessibilityLabel = "Close Notification"
|
||||
typeIcon.accessibilityLabel = style.accessibilityText
|
||||
}
|
||||
|
||||
private func setConstraints() {
|
||||
labelViewAndButtonViewConstraint?.deactivate()
|
||||
labelViewBottomConstraint?.deactivate()
|
||||
|
||||
@ -174,7 +174,7 @@ open class Pagination: View {
|
||||
let isNextAction = sender == nextButton
|
||||
_selectedPageIndex = if isNextAction { _selectedPageIndex + 1 } else { _selectedPageIndex - 1 }
|
||||
updateSelection()
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { [weak self] in
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
|
||||
guard let self else { return }
|
||||
UIAccessibility.post(notification: .announcement, argument: "Page \(self.selectedPage) of \(self.total) selected")
|
||||
}
|
||||
|
||||
@ -78,6 +78,11 @@ open class PaginationButton: ButtonBase {
|
||||
tintColor = color
|
||||
super.updateView()
|
||||
}
|
||||
|
||||
open override func accessibilityActivate() -> Bool {
|
||||
sendActions(for: .touchUpInside)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension PaginationButton {
|
||||
|
||||
@ -49,6 +49,8 @@ open class RadioBoxGroup: SelectorGroupBase<RadioBoxItem>, SelectorGroupSingleSe
|
||||
$0.isEnabled = !model.disabled
|
||||
$0.inputId = model.inputId
|
||||
$0.isSelected = model.selected
|
||||
$0.strikethrough = model.strikethrough
|
||||
$0.strikethroughAccessibilityText = model.strikethroughAccessibileText
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -115,12 +117,14 @@ extension RadioBoxGroup {
|
||||
/// Array of LabelAttributeModel objects used in rendering the subTextRight.
|
||||
public var subTextRightAttributes: [any LabelAttributeModel]?
|
||||
public var selected: Bool
|
||||
public var strikethrough: Bool = false
|
||||
public var strikethroughAccessibileText: String
|
||||
|
||||
public init(disabled: Bool, surface: Surface = .light, inputId: String? = nil, value: AnyHashable? = nil,
|
||||
text: String = "", textAttributes: [any LabelAttributeModel]? = nil,
|
||||
subText: String? = nil, subTextAttributes: [any LabelAttributeModel]? = nil,
|
||||
subTextRight: String? = nil, subTextRightAttributes: [any LabelAttributeModel]? = nil,
|
||||
selected: Bool = false, errorText: String? = nil, accessibileText: String? = nil) {
|
||||
selected: Bool = false, errorText: String? = nil, accessibileText: String? = nil, strikethrough: Bool = false, strikethroughAccessibileText: String = "not available") {
|
||||
self.disabled = disabled
|
||||
self.surface = surface
|
||||
self.inputId = inputId
|
||||
@ -133,6 +137,8 @@ extension RadioBoxGroup {
|
||||
self.subTextRightAttributes = subTextRightAttributes
|
||||
self.selected = selected
|
||||
self.accessibileText = accessibileText
|
||||
self.strikethrough = strikethrough
|
||||
self.strikethroughAccessibileText = strikethroughAccessibileText
|
||||
}
|
||||
|
||||
public init() {
|
||||
|
||||
@ -38,7 +38,7 @@ open class RadioBoxItem: Control, Changeable, FormFieldable {
|
||||
$0.alignment = .top
|
||||
$0.distribution = .fill
|
||||
$0.axis = .horizontal
|
||||
$0.spacing = 12
|
||||
$0.spacing = VDSLayout.space3X
|
||||
}
|
||||
|
||||
private var selectorLeftLabelStackView = UIStackView().with {
|
||||
@ -52,13 +52,7 @@ open class RadioBoxItem: Control, Changeable, FormFieldable {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
open var onChangeSubscriber: AnyCancellable? {
|
||||
willSet {
|
||||
if let onChangeSubscriber {
|
||||
onChangeSubscriber.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
open var onChangeSubscriber: AnyCancellable?
|
||||
|
||||
/// Label used to render the text.
|
||||
open var textLabel = Label().with {
|
||||
@ -129,6 +123,8 @@ open class RadioBoxItem: Control, Changeable, FormFieldable {
|
||||
/// If provided, the radio box will be rendered to show the option with a strikethrough.
|
||||
open var strikethrough: Bool = false { didSet { setNeedsUpdate() } }
|
||||
|
||||
open var strikethroughAccessibilityText: String = "not available" { didSet { setNeedsUpdate() } }
|
||||
|
||||
open var inputId: String? { didSet { setNeedsUpdate() } }
|
||||
|
||||
open var value: AnyHashable? { didSet { setNeedsUpdate() } }
|
||||
@ -189,7 +185,7 @@ open class RadioBoxItem: Control, Changeable, FormFieldable {
|
||||
.pinTrailing(0, .defaultHigh)
|
||||
.pinBottom(0, .defaultHigh)
|
||||
|
||||
selectorStackView.pinToSuperView(.uniform(16))
|
||||
selectorStackView.pinToSuperView(.uniform(VDSLayout.space3X))
|
||||
}
|
||||
|
||||
/// Resets to default settings.
|
||||
@ -218,6 +214,7 @@ open class RadioBoxItem: Control, Changeable, FormFieldable {
|
||||
value = nil
|
||||
|
||||
isSelected = false
|
||||
onChange = nil
|
||||
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
@ -236,15 +233,13 @@ open class RadioBoxItem: Control, Changeable, FormFieldable {
|
||||
|
||||
updateLabels()
|
||||
setNeedsLayout()
|
||||
layoutIfNeeded()
|
||||
}
|
||||
|
||||
/// Used to update any Accessibility properties.
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
if accessibilityLabel == nil {
|
||||
setAccessibilityLabel(for: [textLabel, subTextLabel, subTextRightLabel])
|
||||
}
|
||||
setAccessibilityLabel(for: [textLabel, subTextLabel, subTextRightLabel])
|
||||
accessibilityValue = strikethrough ? strikethroughAccessibilityText : nil
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -172,7 +172,6 @@ extension Tabs {
|
||||
label.textAlignment = textAlignment.value
|
||||
label.textColorConfiguration = textColorConfiguration.eraseToAnyColorable()
|
||||
setNeedsLayout()
|
||||
layoutIfNeeded()
|
||||
}
|
||||
|
||||
/// Used to update any Accessibility properties.
|
||||
|
||||
@ -119,13 +119,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
open var onChangeSubscriber: AnyCancellable? {
|
||||
willSet {
|
||||
if let onChangeSubscriber {
|
||||
onChangeSubscriber.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
open var onChangeSubscriber: AnyCancellable?
|
||||
|
||||
open var titleLabel = Label().with {
|
||||
$0.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
@ -135,6 +129,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
|
||||
open var errorLabel = Label().with {
|
||||
$0.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
$0.textStyle = .bodySmall
|
||||
$0.accessibilityValue = "error"
|
||||
}
|
||||
|
||||
open var helperLabel = Label().with {
|
||||
@ -304,6 +299,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
|
||||
defaultValue = nil
|
||||
required = false
|
||||
readOnly = false
|
||||
onChange = nil
|
||||
}
|
||||
|
||||
/// Used to make changes to the View based off a change events or from local properties.
|
||||
|
||||
@ -151,6 +151,7 @@ open class InputField: EntryFieldBase, UITextFieldDelegate {
|
||||
/// 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()
|
||||
isAccessibilityElement = false
|
||||
|
||||
minWidthConstraint = containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: 0)
|
||||
minWidthConstraint?.isActive = true
|
||||
@ -272,6 +273,25 @@ open class InputField: EntryFieldBase, UITextFieldDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to update any Accessibility properties.
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
textField.accessibilityLabel = showError ? "error" : nil
|
||||
if showError {
|
||||
accessibilityElements = [titleLabel, textField, icon, errorLabel, helperLabel]
|
||||
} else {
|
||||
accessibilityElements = [titleLabel, textField, helperLabel]
|
||||
}
|
||||
}
|
||||
|
||||
open override var canBecomeFirstResponder: Bool { true }
|
||||
|
||||
open override func resignFirstResponder() -> Bool {
|
||||
if textField.isFirstResponder {
|
||||
textField.resignFirstResponder()
|
||||
}
|
||||
return super.resignFirstResponder()
|
||||
}
|
||||
}
|
||||
|
||||
extension InputField.FieldType {
|
||||
|
||||
@ -239,6 +239,7 @@ open class TextArea: EntryFieldBase {
|
||||
/// Used to update any Accessibility properties.
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
textView.accessibilityLabel = showError ? "error" : nil
|
||||
if showError {
|
||||
accessibilityElements = [titleLabel, textView, icon, errorLabel, helperLabel]
|
||||
} else {
|
||||
@ -246,6 +247,15 @@ open class TextArea: EntryFieldBase {
|
||||
}
|
||||
}
|
||||
|
||||
open override var canBecomeFirstResponder: Bool { true }
|
||||
|
||||
open override func resignFirstResponder() -> Bool {
|
||||
if textView.isFirstResponder {
|
||||
textView.resignFirstResponder()
|
||||
}
|
||||
return super.resignFirstResponder()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Private Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -147,5 +147,6 @@ open class TextView: UITextView, ViewProtocol {
|
||||
attributedText = nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
import Foundation
|
||||
import VDSTokens
|
||||
import UIKit
|
||||
import Combine
|
||||
|
||||
@objc(VDSTileContainer)
|
||||
open class TileContainer: TileContainerBase<TileContainer.Padding> {
|
||||
@ -43,7 +44,6 @@ open class TileContainer: TileContainerBase<TileContainer.Padding> {
|
||||
}
|
||||
|
||||
open class TileContainerBase<PaddingType: DefaultValuing>: Control where PaddingType.ValueType == CGFloat {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
@ -111,6 +111,19 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
public override var onClickSubscriber: AnyCancellable? {
|
||||
didSet {
|
||||
if onClickSubscriber != nil {
|
||||
isAccessibilityElement = true
|
||||
accessibilityTraits = .link
|
||||
accessibilityHint = "Double tap to open."
|
||||
} else {
|
||||
isAccessibilityElement = false
|
||||
accessibilityTraits.remove(.link)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This takes an image source url and applies it as a background image.
|
||||
open var backgroundImage: UIImage? { didSet { setNeedsUpdate() } }
|
||||
|
||||
@ -171,7 +184,7 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
|
||||
open var showBorder: Bool = false { didSet { setNeedsUpdate() } }
|
||||
|
||||
/// Determines if there is a drop shadow or not.
|
||||
open var showDropShadows: Bool = false { didSet { setNeedsUpdate() } }
|
||||
open var showDropShadow: Bool = false { didSet { setNeedsUpdate() } }
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
@ -274,7 +287,7 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
|
||||
width = nil
|
||||
height = nil
|
||||
showBorder = false
|
||||
showDropShadows = false
|
||||
showDropShadow = false
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
@ -316,12 +329,14 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
|
||||
widthConstraint?.isActive = false
|
||||
heightConstraint?.isActive = false
|
||||
}
|
||||
if showDropShadows, surface == .light {
|
||||
|
||||
applyBackgroundEffects()
|
||||
|
||||
if showDropShadow, surface == .light {
|
||||
addDropShadow(dropShadowConfiguration)
|
||||
} else {
|
||||
removeDropShadows()
|
||||
}
|
||||
applyBackgroundEffects()
|
||||
}
|
||||
|
||||
/// Used to update frames for the added CAlayers to our view
|
||||
@ -337,6 +352,7 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
|
||||
|
||||
/// This will place a view within the contentView of this component.
|
||||
public func addContentView(_ view: UIView, shouldPin: Bool = true) {
|
||||
view.removeFromSuperview()
|
||||
containerView.addSubview(view)
|
||||
if shouldPin {
|
||||
view.pinToSuperView()
|
||||
|
||||
@ -105,12 +105,6 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
public override var onClickSubscriber: AnyCancellable? {
|
||||
didSet {
|
||||
isAccessibilityElement = onClickSubscriber != nil
|
||||
}
|
||||
}
|
||||
|
||||
/// Title lockup positioned in the contentView.
|
||||
open var titleLockup = TitleLockup().with {
|
||||
$0.standardStyleConfiguration = .init(styleConfigurations: [
|
||||
@ -305,9 +299,6 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
|
||||
color = .black
|
||||
addContentView(stackView)
|
||||
|
||||
accessibilityTraits = .link
|
||||
accessibilityElements = [badge, titleLockup, descriptiveIcon, directionalIcon]
|
||||
|
||||
//badge
|
||||
badgeContainerView.addSubview(badge)
|
||||
badge
|
||||
@ -412,12 +403,26 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
|
||||
if width != nil && (aspectRatio != .none || height != nil) {
|
||||
updateTextPositionAlignment()
|
||||
}
|
||||
layoutIfNeeded()
|
||||
setNeedsLayout()
|
||||
}
|
||||
|
||||
/// Used to update any Accessibility properties.
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
var elements = [Any]()
|
||||
if badgeModel != nil {
|
||||
elements.append(badge)
|
||||
}
|
||||
if titleModel != nil || subTitleModel != nil || eyebrowModel != nil {
|
||||
elements.append(titleLockup)
|
||||
}
|
||||
if descriptiveIconModel != nil {
|
||||
elements.append(descriptiveIcon)
|
||||
}
|
||||
if directionalIconModel != nil {
|
||||
elements.append(directionalIcon)
|
||||
}
|
||||
accessibilityElements = elements.count > 0 ? elements : nil
|
||||
|
||||
setAccessibilityLabel(for: [badge.label, titleLockup.eyebrowLabel, titleLockup.titleLabel, titleLockup.subTitleLabel])
|
||||
}
|
||||
|
||||
@ -272,7 +272,21 @@ open class TitleLockup: View {
|
||||
|
||||
titleLabel.textColorConfiguration = textColorPrimaryConfiguration
|
||||
|
||||
accessibilityElements = [eyebrowLabel, titleLabel, subTitleLabel]
|
||||
}
|
||||
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
var elements = [Any]()
|
||||
if eyebrowModel != nil {
|
||||
elements.append(eyebrowLabel)
|
||||
}
|
||||
if titleModel != nil {
|
||||
elements.append(titleLabel)
|
||||
}
|
||||
if subTitleModel != nil {
|
||||
elements.append(subTitleLabel)
|
||||
}
|
||||
accessibilityElements = elements.count > 0 ? elements : nil
|
||||
}
|
||||
|
||||
/// Resets to default settings.
|
||||
|
||||
@ -88,13 +88,7 @@ open class Toggle: Control, Changeable, FormFieldable {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
open var onChangeSubscriber: AnyCancellable? {
|
||||
willSet {
|
||||
if let onChangeSubscriber {
|
||||
onChangeSubscriber.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
open var onChangeSubscriber: AnyCancellable?
|
||||
|
||||
/// Actual toggle used in this component.
|
||||
open var toggleView = ToggleView().with {
|
||||
@ -231,6 +225,7 @@ open class Toggle: Control, Changeable, FormFieldable {
|
||||
textPosition = .left
|
||||
inputId = nil
|
||||
value = nil
|
||||
onChange = nil
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
|
||||
@ -166,6 +166,7 @@ open class ToggleView: Control, Changeable, FormFieldable {
|
||||
value = nil
|
||||
toggleView.backgroundColor = toggleColorConfiguration.getColor(self)
|
||||
knobView.backgroundColor = knobColorConfiguration.getColor(self)
|
||||
onChange = nil
|
||||
shouldUpdateView = true
|
||||
setNeedsUpdate()
|
||||
}
|
||||
@ -227,7 +228,6 @@ open class ToggleView: Control, Changeable, FormFieldable {
|
||||
knobTrailingConstraint?.isActive = true
|
||||
knobLeadingConstraint?.isActive = true
|
||||
setNeedsLayout()
|
||||
layoutIfNeeded()
|
||||
}
|
||||
|
||||
private func updateToggle() {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
import Foundation
|
||||
|
||||
extension DispatchQueue {
|
||||
private static var _onceTracker = [String]()
|
||||
private static var _onceTracker = Set<String>()
|
||||
|
||||
public class func once(
|
||||
file: String = #file,
|
||||
@ -31,12 +31,17 @@ extension DispatchQueue {
|
||||
token: String,
|
||||
block: () -> Void
|
||||
) {
|
||||
// Peek ahead to avoid the intersection.
|
||||
guard !_onceTracker.contains(token) else { return }
|
||||
|
||||
objc_sync_enter(self)
|
||||
defer { objc_sync_exit(self) }
|
||||
|
||||
// Double check we are the first in the critical section.
|
||||
guard !_onceTracker.contains(token) else { return }
|
||||
|
||||
_onceTracker.append(token)
|
||||
// Execute.
|
||||
_onceTracker.insert(token)
|
||||
block()
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,6 +26,8 @@ extension Changeable {
|
||||
.sink { c in
|
||||
newValue(c)
|
||||
}
|
||||
} else {
|
||||
onChangeSubscriber = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ extension Clickable {
|
||||
public var onClick: ((Self) -> ())? {
|
||||
get { return nil }
|
||||
set {
|
||||
onClickSubscriber?.cancel()
|
||||
if let newValue {
|
||||
onClickSubscriber = publisher(for: .touchUpInside)
|
||||
.sink { [weak self] c in
|
||||
@ -27,7 +28,6 @@ extension Clickable {
|
||||
newValue(c)
|
||||
}
|
||||
} else {
|
||||
onClickSubscriber?.cancel()
|
||||
onClickSubscriber = nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,10 @@
|
||||
- CXTDT-544442 - Button Icon - Selected state needs to allow custom color
|
||||
- CXTDT-546821 - TextArea - Accessibility - input field is not receiving swipe focus
|
||||
- CXTDT-547200 - Carousel scrollbar – Accessibility - The scrollbar is receiving right/ left swipe focus
|
||||
- CXTDT-549888 - Pagination - Accessibility - Next/Previous
|
||||
- CXTDT-542333 - RadioBox Padding
|
||||
- CXTDT-549901 - RadioBox strike through state
|
||||
- CXTDT-546824 - Notification - Accessibility - Improper label for close notification button & icon
|
||||
|
||||
1.0.59
|
||||
----------------
|
||||
|
||||
Loading…
Reference in New Issue
Block a user