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

This commit is contained in:
Matt Bruce 2024-06-03 08:53:51 -05:00
commit 9ff45a73af
11 changed files with 128 additions and 126 deletions

View File

@ -1515,7 +1515,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 = 64; CURRENT_PROJECT_VERSION = 65;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
@ -1552,7 +1552,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 = 64; CURRENT_PROJECT_VERSION = 65;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;

View File

@ -161,7 +161,8 @@ open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable,
/// 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()
selectorView.isAccessibilityElement = false
isAccessibilityElement = true isAccessibilityElement = true
accessibilityTraits = .button accessibilityTraits = .button
addSubview(mainStackView) addSubview(mainStackView)

View File

@ -13,78 +13,14 @@ final class BreadcrumbCellItem: UICollectionViewCell {
///Identifier for the BreadcrumbCellItem ///Identifier for the BreadcrumbCellItem
static let identifier: String = String(describing: BreadcrumbCellItem.self) static let identifier: String = String(describing: BreadcrumbCellItem.self)
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
internal var stackView: UIStackView = {
return UIStackView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.axis = .horizontal
$0.distribution = .fill
$0.alignment = .fill
$0.spacing = VDSLayout.space1X
$0.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
$0.setContentHuggingPriority(.defaultHigh, for: .horizontal)
}
}()
internal var breadCrumbItem: BreadcrumbItem?
///separator label
private var separator: Label = Label().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.textAlignment = .left
$0.numberOfLines = 1
$0.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
$0.setContentHuggingPriority(.defaultHigh, for: .horizontal)
$0.text = "/"
}
private let textColorConfiguration = SurfaceColorConfiguration(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark)
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
override init(frame: CGRect) {
super.init(frame: frame)
setUp()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setUp()
}
///Configuring the cell with default setup
private func setUp() {
separator.textColorConfiguration = textColorConfiguration.eraseToAnyColorable()
contentView.addSubview(stackView)
stackView.pinToSuperView()
separator.backgroundColor = .clear
}
///Updating the breadCrumbItem and UI based on the selected flag along with the surface ///Updating the breadCrumbItem and UI based on the selected flag along with the surface
func update(surface: Surface, hideSlash: Bool, breadCrumbItem: BreadcrumbItem) { func update(breadCrumbItem: BreadcrumbItem) {
//update surface contentView.subviews.forEach{$0.removeFromSuperview()}
separator.surface = surface contentView.addSubview(breadCrumbItem)
breadCrumbItem.surface = surface breadCrumbItem.pinToSuperView()
breadCrumbItem.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) breadCrumbItem.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
breadCrumbItem.setContentHuggingPriority(.defaultLow, for: .horizontal) breadCrumbItem.setContentHuggingPriority(.defaultLow, for: .horizontal)
//remove previous views
stackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
//add to stack
stackView.addArrangedSubview(separator)
stackView.addArrangedSubview(breadCrumbItem)
stackView.setCustomSpacing(VDSLayout.space1X, after: separator)
//update separator
separator.textColor = textColorConfiguration.getColor(surface)
separator.isHidden = hideSlash
self.breadCrumbItem = breadCrumbItem
setNeedsLayout()
} }
} }

View File

@ -42,23 +42,28 @@ open class BreadcrumbItem: ButtonBase {
textColorConfiguration.getColor(self) textColorConfiguration.getColor(self)
} }
/// The natural size for the receiving view, considering only properties of the view itself. /// Determines if a slash is predended or not.
open override var intrinsicContentSize: CGSize { open var hideSlash: Bool = false { didSet { setNeedsUpdate() } }
guard let titleLabel else { return super.intrinsicContentSize }
// Calculate the titleLabel's intrinsic content size private var slashText = "/ "
let labelSize = titleLabel.sizeThatFits(CGSize(width: self.frame.width, height: CGFloat.greatestFiniteMagnitude))
// Adjust the size if needed (add any additional padding if your design requires) open override var textAttributes: [any LabelAttributeModel]? {
let adjustedSize = CGSize(width: labelSize.width + contentEdgeInsets.left + contentEdgeInsets.right, hideSlash
height: labelSize.height + contentEdgeInsets.top + contentEdgeInsets.bottom) ? nil
return adjustedSize : [ColorLabelAttribute(location: 0,
length: 1,
color: surface == .light ? VDSColor.elementsPrimaryOnlight : VDSColor.elementsPrimaryOndark),
TextStyleLabelAttribute(location: 0,
length: 1,
textStyle: .bodySmall)
]
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Private Properties // MARK: - Private Properties
//-------------------------------------------------- //--------------------------------------------------
private var textColorConfiguration = ControlColorConfiguration().with { private var textColorConfiguration = ControlColorConfiguration().with {
$0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal) $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal)
$0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .disabled)
$0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .highlighted) $0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .highlighted)
$0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .selected) $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .selected)
} }
@ -69,15 +74,51 @@ open class BreadcrumbItem: ButtonBase {
/// 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()
titleLabel?.numberOfLines = 0
titleLabel?.lineBreakMode = .byWordWrapping
contentHorizontalAlignment = .left
isAccessibilityElement = true isAccessibilityElement = true
accessibilityTraits = .link accessibilityTraits = .link
contentHorizontalAlignment = .leading
} }
/// Used to make changes to the View based off a change events or from local properties. /// Used to make changes to the View based off a change events or from local properties.
open override func updateView() { open override func updateView() {
//always call last so the label is rendered
super.updateView() //clear the arrays holding actions
accessibilityCustomActions = []
if let text, !text.isEmpty {
var updatedText = text
if updatedText.hasPrefix(slashText) && hideSlash {
updatedText = String(updatedText.dropFirst(slashText.count))
} else if !hideSlash, !updatedText.hasPrefix(slashText) {
updatedText = slashText + updatedText
}
//create the primary string
let mutableText = NSMutableAttributedString.mutableText(for: updatedText,
textStyle: textStyle,
useScaledFont: useScaledFont,
textColor: textColor,
alignment: titleLabel?.textAlignment ?? .center,
lineBreakMode: titleLabel?.lineBreakMode ?? .byTruncatingTail)
//apply any attributes
if let attributes = textAttributes {
mutableText.apply(attributes: attributes)
}
//set the attributed text
setAttributedTitle(mutableText, for: .normal)
setAttributedTitle(mutableText, for: .highlighted)
invalidateIntrinsicContentSize()
} else {
setAttributedTitle(nil, for: .normal)
setAttributedTitle(nil, for: .highlighted)
titleLabel?.text = nil
}
} }

View File

@ -12,9 +12,6 @@ extension Breadcrumbs {
///Text that goes in the breadcrumb item ///Text that goes in the breadcrumb item
public var text: String public var text: String
/// Whether the Item can be clicked.
public var enabled: Bool
/// The Breadcrumb link to links to its respective page. /// The Breadcrumb link to links to its respective page.
public var selected: Bool public var selected: Bool
@ -22,9 +19,8 @@ extension Breadcrumbs {
///Click event when you click on a breadcrumb item ///Click event when you click on a breadcrumb item
public var onClick: ((BreadcrumbItem) -> Void)? public var onClick: ((BreadcrumbItem) -> Void)?
public init(text: String, enabeled: Bool = true, selected: Bool = false, onClick: ((BreadcrumbItem) -> Void)? = nil) { public init(text: String, selected: Bool = false, onClick: ((BreadcrumbItem) -> Void)? = nil) {
self.text = text self.text = text
self.enabled = enabeled
self.selected = selected self.selected = selected
self.onClick = onClick self.onClick = onClick
} }

View File

@ -32,13 +32,6 @@ open class Breadcrumbs: View {
} }
} }
/// Current Surface and this is used to pass down to child objects that implement Surfacable
override open var surface: Surface {
didSet {
breadcrumbs.forEach { $0.surface = surface }
}
}
open override var accessibilityElements: [Any]? { open override var accessibilityElements: [Any]? {
get { get {
return [containerView, breadcrumbs] return [containerView, breadcrumbs]
@ -99,7 +92,6 @@ open class Breadcrumbs: View {
breadcrumbs = breadcrumbModels.compactMap({ model in breadcrumbs = breadcrumbModels.compactMap({ model in
let breadcrumbItem = BreadcrumbItem() let breadcrumbItem = BreadcrumbItem()
breadcrumbItem.text = model.text breadcrumbItem.text = model.text
breadcrumbItem.isEnabled = model.enabled
breadcrumbItem.isSelected = model.selected breadcrumbItem.isSelected = model.selected
breadcrumbItem.onClick = { [weak self] breadcrumb in breadcrumbItem.onClick = { [weak self] breadcrumb in
guard let self, breadcrumb.isEnabled else { return } guard let self, breadcrumb.isEnabled else { return }
@ -166,17 +158,22 @@ extension Breadcrumbs: UICollectionViewDelegate, UICollectionViewDataSource, But
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: BreadcrumbCellItem.identifier, for: indexPath) as? BreadcrumbCellItem else { return UICollectionViewCell() } guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: BreadcrumbCellItem.identifier, for: indexPath) as? BreadcrumbCellItem else { return UICollectionViewCell() }
let hideSlash = indexPath.row == 0 let breadcrumb = breadcrumbs[indexPath.row]
cell.update(surface: surface, hideSlash: hideSlash, breadCrumbItem: breadcrumbs[indexPath.row]) breadcrumb.hideSlash = breadcrumb == breadcrumbs.first
breadcrumb.surface = surface
cell.update(breadCrumbItem: breadcrumb)
return cell return cell
} }
public func collectionView(_ collectionView: UICollectionView, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize { public func collectionView(_ collectionView: UICollectionView, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
let breadcrumb = breadcrumbs[indexPath.row] let breadcrumb = breadcrumbs[indexPath.row]
let intrinsicSize = breadcrumb.intrinsicContentSize breadcrumb.hideSlash = breadcrumb == breadcrumbs.first
let separatorFullWidth: CGFloat = indexPath.row == 0 ? 0 : VDSLayout.space1X + separatorWidth
let cellwidth = intrinsicSize.width + separatorFullWidth let maxWidth = frame.width
return .init(width: min(cellwidth, collectionView.frame.width), height: intrinsicSize.height) let intrinsicSize = breadcrumb.titleLabel!.sizeThatFits(.init(width: maxWidth, height: CGFloat.greatestFiniteMagnitude))
let cellwidth = min(maxWidth, intrinsicSize.width)
return .init(width: cellwidth, height: intrinsicSize.height)
} }
public func collectionView(_ collectionView: UICollectionView, buttonBaseAtIndexPath indexPath: IndexPath) -> ButtonBase { public func collectionView(_ collectionView: UICollectionView, buttonBaseAtIndexPath indexPath: IndexPath) -> ButtonBase {

View File

@ -243,6 +243,11 @@ open class RadioBoxItem: Control, Changeable, FormFieldable, Groupable {
open override func updateAccessibility() { open override func updateAccessibility() {
super.updateAccessibility() super.updateAccessibility()
setAccessibilityLabel(for: [textLabel, subTextLabel, subTextRightLabel]) setAccessibilityLabel(for: [textLabel, subTextLabel, subTextRightLabel])
if let currentAccessibilityLabel = accessibilityLabel {
accessibilityLabel = "Radiobox, \(currentAccessibilityLabel)"
} else {
accessibilityLabel = "Radiobox"
}
if let accessibilityValueText { if let accessibilityValueText {
accessibilityValue = strikethrough accessibilityValue = strikethrough
? "\(strikethroughAccessibilityText), \(accessibilityValueText)" ? "\(strikethroughAccessibilityText), \(accessibilityValueText)"

View File

@ -108,7 +108,7 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
$0.clipsToBounds = true $0.clipsToBounds = true
} }
private var containerView = View() internal var containerView = View()
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Public Properties // MARK: - Public Properties
@ -342,9 +342,6 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
containerView.isAccessibilityElement = onClickSubscriber != nil containerView.isAccessibilityElement = onClickSubscriber != nil
containerView.accessibilityHint = "Double tap to open." containerView.accessibilityHint = "Double tap to open."
containerView.accessibilityLabel = nil containerView.accessibilityLabel = nil
if let views = accessibilityElements?.compactMap({ $0 as? UIView }), !views.isEmpty {
containerView.setAccessibilityLabel(for: views)
}
} }
open override var accessibilityElements: [Any]? { open override var accessibilityElements: [Any]? {
@ -358,10 +355,18 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
} }
items.append(containerView) items.append(containerView)
} }
items.append(contentsOf: contentView.subviews.filter({ $0.isAccessibilityElement == true }))
let elements = gatherAccessibilityElements(from: contentView)
let views = elements.compactMap({ $0 as? UIView })
//update accessibilityLabel
containerView.setAccessibilityLabel(for: views)
//append all children that are accessible
items.append(contentsOf: elements)
return items return items
} }
set {} set {}
} }

View File

@ -415,29 +415,37 @@ open class Tilelet: TileContainerBase<Tilelet.Padding> {
/// Used to update any Accessibility properties. /// Used to update any Accessibility properties.
open override var accessibilityElements: [Any]? { open override var accessibilityElements: [Any]? {
get { get {
var elements = [Any]() var views = [UIView]()
if let superElements = super.accessibilityElements {
elements.append(contentsOf: superElements) // grab the available views in order
}
if badgeModel != nil { if badgeModel != nil {
elements.append(badge) views.append(badge)
} }
if titleModel != nil || subTitleModel != nil || eyebrowModel != nil { if titleModel != nil || subTitleModel != nil || eyebrowModel != nil {
elements.append(titleLockup) views.append(titleLockup)
} }
if descriptiveIconModel != nil {
elements.append(descriptiveIcon) containerView.setAccessibilityLabel(for: views)
// get the views to return
var items = [Any]()
if containerView.isAccessibilityElement {
if !accessibilityTraits.contains(.button) && !accessibilityTraits.contains(.link) {
containerView.accessibilityTraits = .button
} else {
containerView.accessibilityTraits = accessibilityTraits
}
items.append(containerView)
} }
if directionalIconModel != nil {
elements.append(directionalIcon) //append all other accessible views to traverse
} items.append(contentsOf: views)
return elements
return items
} }
set {} set {}
} }
//-------------------------------------------------- //--------------------------------------------------

View File

@ -50,4 +50,16 @@ extension UIView {
return isIntersecting return isIntersecting
} }
public func gatherAccessibilityElements(from view: UIView) -> [Any] {
var elements: [Any] = []
for subview in view.subviews {
if subview.isAccessibilityElement && subview.isVisibleOnScreen {
elements.append(subview)
}
elements.append(contentsOf: gatherAccessibilityElements(from: subview))
}
return elements
}
} }

View File

@ -7,6 +7,7 @@
- CXTDT-563189 - Dropdown Select Readonly Border color - CXTDT-563189 - Dropdown Select Readonly Border color
- CXTDT-555854 - Dropdown Select - spacing issues - CXTDT-555854 - Dropdown Select - spacing issues
- CXTDT-563194 - Dropdown Select - missing transparentBackground option - CXTDT-563194 - Dropdown Select - missing transparentBackground option
- CXTDT-552834 TileContainer Voice over is not rendering the information.
1.0.64 1.0.64
---------------- ----------------