Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/vds_ios.git into feature/inputField

# Conflicts:
#	VDS/Components/Notification/Notification.swift
#	VDS/Components/TextFields/InputField/InputField.swift

Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
Matt Bruce 2024-04-29 16:30:25 -05:00
commit accd264595
22 changed files with 81 additions and 28 deletions

View File

@ -1377,7 +1377,7 @@
BUILD_LIBRARY_FOR_DISTRIBUTION = YES; BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
CODE_SIGN_IDENTITY = ""; CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 59; CURRENT_PROJECT_VERSION = 60;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
@ -1414,7 +1414,7 @@
BUILD_LIBRARY_FOR_DISTRIBUTION = YES; BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
CODE_SIGN_IDENTITY = ""; CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 59; CURRENT_PROJECT_VERSION = 60;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;

View File

@ -114,16 +114,16 @@ open class SelectorBase: Control, SelectorControlable {
accessibilityTraits = .button accessibilityTraits = .button
} }
/// Used to make changes to the View based off a change events or from local properties.
open override func updateView() { open override func updateView() {
super.updateView() super.updateView()
setNeedsLayout() setNeedsLayout()
layoutIfNeeded() layoutIfNeeded()
} }
/// Used to update any Accessibility properties.ß /// Used to update any Accessibility properties.ß
open override func updateAccessibility() { open override func updateAccessibility() {
super.updateAccessibility() super.updateAccessibility()
accessibilityLabel = "\(Self.self)\(showError ? ", error" : "")"
} }
/// This will change the state of the Selector and execute the actionBlock if provided. /// This will change the state of the Selector and execute the actionBlock if provided.

View File

@ -192,7 +192,7 @@ open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable,
/// Used to update any Accessibility properties. /// Used to update any Accessibility properties.
open override func updateAccessibility() { open override func updateAccessibility() {
super.updateAccessibility() super.updateAccessibility()
setAccessibilityLabel(for: [label, childLabel, errorLabel]) setAccessibilityLabel(for: [selectorView, label, childLabel, errorLabel])
} }
/// Resets to default settings. /// Resets to default settings.

View File

@ -344,7 +344,6 @@ open class BadgeIndicator: View {
label.isEnabled = isEnabled label.isEnabled = isEnabled
label.sizeToFit() label.sizeToFit()
setNeedsLayout() setNeedsLayout()
layoutIfNeeded()
} }
open override func updateAccessibility() { open override func updateAccessibility() {

View File

@ -84,7 +84,7 @@ final class BreadcrumbCellItem: UICollectionViewCell {
separator.textColor = textColorConfiguration.getColor(surface) separator.textColor = textColorConfiguration.getColor(surface)
separator.isHidden = hideSlash separator.isHidden = hideSlash
self.breadCrumbItem = breadCrumbItem self.breadCrumbItem = breadCrumbItem
layoutIfNeeded() setNeedsLayout()
} }
} }

View File

@ -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. /// 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 = "Checkbox"
backgroundColorConfiguration.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .selected) backgroundColorConfiguration.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .selected)
backgroundColorConfiguration.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: [.selected, .highlighted]) backgroundColorConfiguration.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: [.selected, .highlighted])
@ -71,7 +70,7 @@ open class Checkbox: SelectorBase {
isSelected.toggle() isSelected.toggle()
sendActions(for: .valueChanged) sendActions(for: .valueChanged)
} }
open override func layoutSubviews() { open override func layoutSubviews() {
super.layoutSubviews() super.layoutSubviews()

View File

@ -230,7 +230,6 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
setNeedsDisplay() setNeedsDisplay()
setNeedsLayout() setNeedsLayout()
layoutIfNeeded()
} }
open func updateAccessibility() { open func updateAccessibility() {

View File

@ -264,8 +264,6 @@ open class Notification: View {
isAccessibilityElement = false isAccessibilityElement = false
accessibilityElements = [closeButton, typeIcon, titleLabel, subTitleLabel, buttonGroup] accessibilityElements = [closeButton, typeIcon, titleLabel, subTitleLabel, buttonGroup]
closeButton.accessibilityTraits = [.button] closeButton.accessibilityTraits = [.button]
closeButton.accessibilityLabel = "Close Notification"
} }
/// Resets to default settings. /// Resets to default settings.
@ -325,7 +323,6 @@ open class Notification: View {
let iconColor = surface == .dark ? VDSColor.paletteWhite : VDSColor.paletteBlack let iconColor = surface == .dark ? VDSColor.paletteWhite : VDSColor.paletteBlack
typeIcon.name = style.iconName typeIcon.name = style.iconName
typeIcon.color = iconColor typeIcon.color = iconColor
typeIcon.accessibilityLabel = style.accessibleText
closeButton.color = iconColor closeButton.color = iconColor
closeButton.isHidden = hideCloseButton closeButton.isHidden = hideCloseButton
} }
@ -374,6 +371,12 @@ open class Notification: View {
} }
} }
open override func updateAccessibility() {
super.updateAccessibility()
closeButton.accessibilityLabel = "Close Notification"
typeIcon.accessibilityLabel = style.accessibleText
}
private func setConstraints() { private func setConstraints() {
labelViewAndButtonViewConstraint?.deactivate() labelViewAndButtonViewConstraint?.deactivate()
labelViewBottomConstraint?.deactivate() labelViewBottomConstraint?.deactivate()

View File

@ -174,7 +174,7 @@ open class Pagination: View {
let isNextAction = sender == nextButton let isNextAction = sender == nextButton
_selectedPageIndex = if isNextAction { _selectedPageIndex + 1 } else { _selectedPageIndex - 1 } _selectedPageIndex = if isNextAction { _selectedPageIndex + 1 } else { _selectedPageIndex - 1 }
updateSelection() 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 } guard let self else { return }
UIAccessibility.post(notification: .announcement, argument: "Page \(self.selectedPage) of \(self.total) selected") UIAccessibility.post(notification: .announcement, argument: "Page \(self.selectedPage) of \(self.total) selected")
} }

View File

@ -78,6 +78,11 @@ open class PaginationButton: ButtonBase {
tintColor = color tintColor = color
super.updateView() super.updateView()
} }
open override func accessibilityActivate() -> Bool {
sendActions(for: .touchUpInside)
return true
}
} }
extension PaginationButton { extension PaginationButton {

View File

@ -54,6 +54,8 @@ open class RadioBoxGroup: SelectorGroupBase<RadioBoxItem>, SelectorGroupSingleSe
$0.inputId = model.inputId $0.inputId = model.inputId
$0.hiddenValue = model.value $0.hiddenValue = model.value
$0.isSelected = model.selected $0.isSelected = model.selected
$0.strikethrough = model.strikethrough
$0.strikethroughAccessibilityText = model.strikethroughAccessibileText
} }
} }
} }
@ -120,12 +122,14 @@ extension RadioBoxGroup {
/// Array of LabelAttributeModel objects used in rendering the subTextRight. /// Array of LabelAttributeModel objects used in rendering the subTextRight.
public var subTextRightAttributes: [any LabelAttributeModel]? public var subTextRightAttributes: [any LabelAttributeModel]?
public var selected: Bool 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, public init(disabled: Bool, surface: Surface = .light, inputId: String? = nil, value: AnyHashable? = nil,
text: String = "", textAttributes: [any LabelAttributeModel]? = nil, text: String = "", textAttributes: [any LabelAttributeModel]? = nil,
subText: String? = nil, subTextAttributes: [any LabelAttributeModel]? = nil, subText: String? = nil, subTextAttributes: [any LabelAttributeModel]? = nil,
subTextRight: String? = nil, subTextRightAttributes: [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.disabled = disabled
self.surface = surface self.surface = surface
self.inputId = inputId self.inputId = inputId
@ -138,6 +142,8 @@ extension RadioBoxGroup {
self.subTextRightAttributes = subTextRightAttributes self.subTextRightAttributes = subTextRightAttributes
self.selected = selected self.selected = selected
self.accessibileText = accessibileText self.accessibileText = accessibileText
self.strikethrough = strikethrough
self.strikethroughAccessibileText = strikethroughAccessibileText
} }
public init() { public init() {

View File

@ -38,7 +38,7 @@ open class RadioBoxItem: Control, Changeable, FormFieldable {
$0.alignment = .top $0.alignment = .top
$0.distribution = .fill $0.distribution = .fill
$0.axis = .horizontal $0.axis = .horizontal
$0.spacing = 12 $0.spacing = VDSLayout.space3X
} }
private var selectorLeftLabelStackView = UIStackView().with { private var selectorLeftLabelStackView = UIStackView().with {
@ -123,6 +123,8 @@ open class RadioBoxItem: Control, Changeable, FormFieldable {
/// If provided, the radio box will be rendered to show the option with a strikethrough. /// If provided, the radio box will be rendered to show the option with a strikethrough.
open var strikethrough: Bool = false { didSet { setNeedsUpdate() } } open var strikethrough: Bool = false { didSet { setNeedsUpdate() } }
open var strikethroughAccessibilityText: String = "not available" { didSet { setNeedsUpdate() } }
open var inputId: String? { didSet { setNeedsUpdate() } } open var inputId: String? { didSet { setNeedsUpdate() } }
open var value: AnyHashable? { hiddenValue } open var value: AnyHashable? { hiddenValue }
@ -185,7 +187,7 @@ open class RadioBoxItem: Control, Changeable, FormFieldable {
.pinTrailing(0, .defaultHigh) .pinTrailing(0, .defaultHigh)
.pinBottom(0, .defaultHigh) .pinBottom(0, .defaultHigh)
selectorStackView.pinToSuperView(.uniform(16)) selectorStackView.pinToSuperView(.uniform(VDSLayout.space3X))
} }
/// Resets to default settings. /// Resets to default settings.
@ -233,15 +235,13 @@ open class RadioBoxItem: Control, Changeable, FormFieldable {
updateLabels() updateLabels()
setNeedsLayout() setNeedsLayout()
layoutIfNeeded()
} }
/// Used to update any Accessibility properties. /// Used to update any Accessibility properties.
open override func updateAccessibility() { open override func updateAccessibility() {
super.updateAccessibility() super.updateAccessibility()
if accessibilityLabel == nil { setAccessibilityLabel(for: [textLabel, subTextLabel, subTextRightLabel])
setAccessibilityLabel(for: [textLabel, subTextLabel, subTextRightLabel]) accessibilityValue = strikethrough ? strikethroughAccessibilityText : nil
}
} }
//-------------------------------------------------- //--------------------------------------------------

View File

@ -172,7 +172,6 @@ extension Tabs {
label.textAlignment = textAlignment.value label.textAlignment = textAlignment.value
label.textColorConfiguration = textColorConfiguration.eraseToAnyColorable() label.textColorConfiguration = textColorConfiguration.eraseToAnyColorable()
setNeedsLayout() setNeedsLayout()
layoutIfNeeded()
} }
/// Used to update any Accessibility properties. /// Used to update any Accessibility properties.

View File

@ -135,6 +135,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
open var errorLabel = Label().with { open var errorLabel = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical) $0.setContentCompressionResistancePriority(.required, for: .vertical)
$0.textStyle = .bodySmall $0.textStyle = .bodySmall
$0.accessibilityValue = "error"
} }
open var helperLabel = Label().with { open var helperLabel = Label().with {

View File

@ -144,7 +144,8 @@ open class InputField: EntryFieldBase, UITextFieldDelegate {
/// 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
@ -335,6 +336,26 @@ open class InputField: EntryFieldBase, UITextFieldDelegate {
tooltipModel = toolTipModel tooltipModel = toolTipModel
} }
/// Used to update any Accessibility properties.
open override func updateAccessibility() {
super.updateAccessibility()
textField.accessibilityLabel = showError ? "error" : nil
if showError {
accessibilityElements = [titleLabel, textField, statusIcon, 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()
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Password // MARK: - Password
//-------------------------------------------------- //--------------------------------------------------

View File

@ -225,6 +225,7 @@ open class TextArea: EntryFieldBase {
/// Used to update any Accessibility properties. /// Used to update any Accessibility properties.
open override func updateAccessibility() { open override func updateAccessibility() {
super.updateAccessibility() super.updateAccessibility()
textView.accessibilityLabel = showError ? "error" : nil
if showError { if showError {
accessibilityElements = [titleLabel, textView, statusIcon, errorLabel, helperLabel] accessibilityElements = [titleLabel, textView, statusIcon, errorLabel, helperLabel]
} else { } else {
@ -232,6 +233,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 // MARK: - Private Methods
//-------------------------------------------------- //--------------------------------------------------

View File

@ -147,5 +147,6 @@ open class TextView: UITextView, ViewProtocol {
attributedText = nil attributedText = nil
} }
} }
} }

View File

@ -329,12 +329,14 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
widthConstraint?.isActive = false widthConstraint?.isActive = false
heightConstraint?.isActive = false heightConstraint?.isActive = false
} }
applyBackgroundEffects()
if showDropShadow, surface == .light { if showDropShadow, surface == .light {
addDropShadow(dropShadowConfiguration) addDropShadow(dropShadowConfiguration)
} else { } else {
removeDropShadows() removeDropShadows()
} }
applyBackgroundEffects()
} }
/// Used to update frames for the added CAlayers to our view /// Used to update frames for the added CAlayers to our view

View File

@ -403,7 +403,7 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
if width != nil && (aspectRatio != .none || height != nil) { if width != nil && (aspectRatio != .none || height != nil) {
updateTextPositionAlignment() updateTextPositionAlignment()
} }
layoutIfNeeded() setNeedsLayout()
} }
/// Used to update any Accessibility properties. /// Used to update any Accessibility properties.

View File

@ -227,7 +227,6 @@ open class ToggleView: Control, Changeable, FormFieldable {
knobTrailingConstraint?.isActive = true knobTrailingConstraint?.isActive = true
knobLeadingConstraint?.isActive = true knobLeadingConstraint?.isActive = true
setNeedsLayout() setNeedsLayout()
layoutIfNeeded()
} }
private func updateToggle() { private func updateToggle() {

View File

@ -8,7 +8,7 @@
import Foundation import Foundation
extension DispatchQueue { extension DispatchQueue {
private static var _onceTracker = [String]() private static var _onceTracker = Set<String>()
public class func once( public class func once(
file: String = #file, file: String = #file,
@ -31,12 +31,17 @@ extension DispatchQueue {
token: String, token: String,
block: () -> Void block: () -> Void
) { ) {
// Peek ahead to avoid the intersection.
guard !_onceTracker.contains(token) else { return }
objc_sync_enter(self) objc_sync_enter(self)
defer { objc_sync_exit(self) } defer { objc_sync_exit(self) }
// Double check we are the first in the critical section.
guard !_onceTracker.contains(token) else { return } guard !_onceTracker.contains(token) else { return }
_onceTracker.append(token) // Execute.
_onceTracker.insert(token)
block() block()
} }
} }

View File

@ -3,6 +3,10 @@
- CXTDT-544442 - Button Icon - Selected state needs to allow custom color - CXTDT-544442 - Button Icon - Selected state needs to allow custom color
- CXTDT-546821 - TextArea - Accessibility - input field is not receiving swipe focus - 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-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 1.0.59
---------------- ----------------