Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/vds_ios.git into refactor/selector-accessibility

# Conflicts:
#	VDS/Components/DatePicker/DatePicker.swift

Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
Matt Bruce 2024-06-18 14:39:30 -05:00
commit 18b2415143
81 changed files with 321 additions and 422 deletions

View File

@ -39,6 +39,7 @@
71FC86E02B973AE500700965 /* DropShadowConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71FC86DF2B973AE500700965 /* DropShadowConfiguration.swift */; };
71FC86E22B97483000700965 /* Clamping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71FC86E12B97483000700965 /* Clamping.swift */; };
71FC86E42B9841AC00700965 /* PaginationFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71FC86E32B9841AC00700965 /* PaginationFlowLayout.swift */; };
AF1CEFE42BEA736A0001F9A5 /* VDSCoreTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF1CEFE32BEA736A0001F9A5 /* VDSCoreTokens.xcframework */; };
EA0B18022A9E236900F2D0CD /* SelectorGroupBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18012A9E236900F2D0CD /* SelectorGroupBase.swift */; };
EA0B18052A9E2D2D00F2D0CD /* SelectorBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18032A9E2D2D00F2D0CD /* SelectorBase.swift */; };
EA0B18062A9E2D2D00F2D0CD /* SelectorItemBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18042A9E2D2D00F2D0CD /* SelectorItemBase.swift */; };
@ -51,7 +52,6 @@
EA0D1C412A6AD61C00E5C127 /* Typography+Additional.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0D1C402A6AD61C00E5C127 /* Typography+Additional.swift */; };
EA0D1C452A6AD73000E5C127 /* RawRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0D1C442A6AD73000E5C127 /* RawRepresentable.swift */; };
EA0FC2C62914222900DF80B4 /* ButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0FC2C52914222900DF80B4 /* ButtonGroup.swift */; };
EA21C5DB2B600EDE00CFC139 /* VDSTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA21C5DA2B600EDD00CFC139 /* VDSTokens.xcframework */; };
EA297A5529FB07760031ED56 /* TooltipLabelAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA297A5429FB07760031ED56 /* TooltipLabelAttribute.swift */; };
EA297A5729FB0A360031ED56 /* AppleGuidelinesTouchable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA297A5629FB0A360031ED56 /* AppleGuidelinesTouchable.swift */; };
EA2DC9B02BE175BA004F58C5 /* RequiredRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA2DC9AF2BE175BA004F58C5 /* RequiredRule.swift */; };
@ -246,6 +246,7 @@
71FC86DF2B973AE500700965 /* DropShadowConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropShadowConfiguration.swift; sourceTree = "<group>"; };
71FC86E12B97483000700965 /* Clamping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Clamping.swift; sourceTree = "<group>"; };
71FC86E32B9841AC00700965 /* PaginationFlowLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationFlowLayout.swift; sourceTree = "<group>"; };
AF1CEFE32BEA736A0001F9A5 /* VDSCoreTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSCoreTokens.xcframework; path = ../SharedFrameworks/VDSCoreTokens.xcframework; sourceTree = "<group>"; };
EA0B18012A9E236900F2D0CD /* SelectorGroupBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorGroupBase.swift; sourceTree = "<group>"; };
EA0B18032A9E2D2D00F2D0CD /* SelectorBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorBase.swift; sourceTree = "<group>"; };
EA0B18042A9E2D2D00F2D0CD /* SelectorItemBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorItemBase.swift; sourceTree = "<group>"; };
@ -420,7 +421,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
EA21C5DB2B600EDE00CFC139 /* VDSTokens.xcframework in Frameworks */,
AF1CEFE42BEA736A0001F9A5 /* VDSCoreTokens.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -636,6 +637,7 @@
EA33618D288B1C0C0071C351 /* Frameworks */ = {
isa = PBXGroup;
children = (
AF1CEFE32BEA736A0001F9A5 /* VDSCoreTokens.xcframework */,
EA21C5DA2B600EDD00CFC139 /* VDSTokens.xcframework */,
);
name = Frameworks;
@ -1521,7 +1523,7 @@
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 66;
CURRENT_PROJECT_VERSION = 67;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
@ -1559,7 +1561,7 @@
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 66;
CURRENT_PROJECT_VERSION = 67;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;

View File

@ -8,7 +8,7 @@
import Foundation
import UIKit
import Combine
import VDSTokens
import VDSCoreTokens
public protocol SelectorControlable: Control, Changeable {
/// Whether not to show the error.

View File

@ -8,7 +8,7 @@
import Foundation
import UIKit
import Combine
import VDSTokens
import VDSCoreTokens
public protocol SelectorGroup {
associatedtype SelectorItemType: Control

View File

@ -8,7 +8,7 @@
import Foundation
import UIKit
import Combine
import VDSTokens
import VDSCoreTokens
/// Base Class used to build out a SelectorControlable control.
open class SelectorItemBase<Selector: SelectorControlable>: Control, Errorable, Changeable, Groupable {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A badge is a visual label used to convey status or highlight supplemental information.

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A badge indicator is a visual label used to convey status or highlight supplemental information.

View File

@ -6,7 +6,7 @@
//
import UIKit
import VDSTokens
import VDSCoreTokens
///This is customised view for Breadcrumb cell item
final class BreadcrumbCellItem: UICollectionViewCell {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A Breadcrumb Item contains href(link) and selected flag.

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A Breadcrumbs contains BreadcrumbItems.

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A button is an interactive element that triggers an action. Buttons are prominent and attention-getting, with more visual emphasis than any of the Text Link components. For this reason, buttons are best suited for critical and driving actions. This class can be used within a ``ButtonGroup``.

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// Base class used for UIButton type classes.

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A button group contains combinations of related CTAs including ``Button``, ``TextLink``, and ``TextLinkCaret``. This group component controls a combination's orientation, spacing, size and allowable size pairings.

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A text link is an interactive element that navigates a customer to pages within an experience, like a Bill details page, or triggers a secondary action,

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A text link caret is an interactive element that always brings a customer to another page. It's used for navigation,

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A calendar is a monthly view that lets customers select a single date.
@ -160,7 +160,7 @@ open class CalendarBase: Control, Changeable {
if (minDate <= maxDate) {
// Check if current date falls between min & max dates.
let fallsBetween = displayDate.isBetweeen(date: minDate, andDate: maxDate)
displayDate = fallsBetween ? displayDate : minDate
displayDate = fallsBetween ? displayDate : (displayDate.monthInt == minDate.monthInt) ? minDate : maxDate
fetchDates(with: displayDate)
}
containerView.backgroundColor = transparentBackground ? .clear : backgroundColorConfiguration.getColor(self)
@ -201,7 +201,7 @@ open class CalendarBase: Control, Changeable {
}
}
updateViewConstraints()
}
}
func updateViewConstraints() {
collectionView.reloadData()
@ -331,38 +331,28 @@ extension CalendarBase: UICollectionViewDelegate, UICollectionViewDataSource, UI
}
}
public func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool {
if let cell = collectionView.cellForItem(at: indexPath) as? CalendarDateViewCell {
let isEnabled: Bool = cell.isDateEnabled()
if isEnabled {
cell.activeModeStart()
}
}
return true
}
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// reload selected index, if it is in enabled state.
if let cell = collectionView.cellForItem(at: indexPath) as? CalendarDateViewCell {
let isEnabled: Bool = cell.isDateEnabled()
if isEnabled {
cell.activeModeEnd()
// Callback to pass selected date if it is enabled only.
selectedDate = dates[indexPath.row]
sendActions(for: .valueChanged)
displayDate = selectedDate
var reloadIndexPaths = [indexPath]
// If an cell is already selected, then it needs to be deselected.
// Add its index path to the array of index paths to be reloaded.
if let deselectIndexPath = selectedIndexPath {
reloadIndexPaths.append(deselectIndexPath)
let hasDate: Bool = cell.hasText()
if hasDate {
let isEnabled: Bool = cell.isDateEnabled()
if isEnabled {
// Callback to pass selected date if it is enabled only.
selectedDate = dates[indexPath.row]
sendActions(for: .valueChanged)
displayDate = selectedDate
var reloadIndexPaths = [indexPath]
// If an cell is already selected, then it needs to be deselected.
// Add its index path to the array of index paths to be reloaded.
if let deselectIndexPath = selectedIndexPath {
reloadIndexPaths.append(deselectIndexPath)
}
collectionView.reloadItems(at: reloadIndexPaths)
}
collectionView.reloadItems(at: reloadIndexPaths)
}
}
}

View File

@ -6,7 +6,7 @@
//
import UIKit
import VDSTokens
import VDSCoreTokens
final class CalendarDateViewCell: UICollectionViewCell {
@ -41,6 +41,21 @@ final class CalendarDateViewCell: UICollectionViewCell {
$0.textStyle = .bodySmall
}
override var isHighlighted: Bool {
didSet{
if self.isHighlighted && hasText() && isDateEnabled() {
self.contentView.layer.borderColor = activeBorderColorConfiguration.getColor(surface).cgColor
self.contentView.layer.borderWidth = VDSFormControls.borderWidth
self.contentView.layer.cornerRadius = VDSFormControls.borderRadius
} else {
self.contentView.layer.borderColor = nil
self.contentView.layer.borderWidth = 0
self.contentView.layer.cornerRadius = 0
}
}
}
private var isEnabled = false
private lazy var shapeLayer = CAShapeLayer()
private var surface: Surface = .light
private let selectedTextColorConfiguration = SurfaceColorConfiguration(VDSColor.elementsPrimaryInverseOnlight, VDSColor.elementsPrimaryInverseOndark)
@ -120,20 +135,21 @@ final class CalendarDateViewCell: UICollectionViewCell {
}
}
// update text color, bg color, corner radius.
if numberLabel.text == selectedDate.getDay()
&& selectedDate.monthInt == displayDate.monthInt
&& selectedDate.yearInt == displayDate.yearInt
&& numberLabel.isEnabled {
numberLabel.textColor = selectedTextColorConfiguration.getColor(surface)
layer.backgroundColor = selectedBackgroundColor.getColor(surface).cgColor
layer.cornerRadius = VDSFormControls.borderRadius
} else {
numberLabel.textColor = unselectedTextColorConfiguration.getColor(surface)
layer.backgroundColor = nil
layer.cornerRadius = 0
// Set selected/unselected state text color, bg color, corner radius if cell is in enabled state.
if isEnabled {
if numberLabel.text == selectedDate.getDay()
&& selectedDate.monthInt == displayDate.monthInt
&& selectedDate.yearInt == displayDate.yearInt {
numberLabel.textColor = selectedTextColorConfiguration.getColor(surface)
layer.backgroundColor = selectedBackgroundColor.getColor(surface).cgColor
layer.cornerRadius = VDSFormControls.borderRadius
} else {
numberLabel.textColor = unselectedTextColorConfiguration.getColor(surface)
layer.backgroundColor = nil
layer.cornerRadius = 0
}
}
// add indicators.
@ -155,26 +171,18 @@ final class CalendarDateViewCell: UICollectionViewCell {
numberLabel.textStyle = .bodySmall
}
}
func hasText() -> Bool {
return !numberLabel.text.isEmpty
}
// returns cell enabled state.
func isDateEnabled() -> Bool {
return numberLabel.isEnabled
}
func activeModeStart() {
numberLabel.layer.borderColor = activeBorderColorConfiguration.getColor(surface).cgColor
numberLabel.layer.borderWidth = VDSFormControls.borderWidth
numberLabel.layer.cornerRadius = VDSFormControls.borderRadius
}
func activeModeEnd() {
numberLabel.layer.borderColor = nil
numberLabel.layer.borderWidth = 0
numberLabel.layer.cornerRadius = 0
return isEnabled
}
func disableLabel(with surface: Surface) {
numberLabel.isEnabled = false
isEnabled = false
numberLabel.textColor = disabledTextColorConfiguration.getColor(surface)
layer.backgroundColor = disabledBackgroundColor.getColor(surface).cgColor
}
@ -183,7 +191,7 @@ final class CalendarDateViewCell: UICollectionViewCell {
for x in 0...activeDates.count-1 {
if activeDates[x].monthInt == displayDate.monthInt && activeDates[x].yearInt == displayDate.yearInt {
if let day:Int = Int(numberLabel.text), day == activeDates[x].dayInt {
numberLabel.isEnabled = true
isEnabled = true
}
}
}
@ -194,7 +202,7 @@ final class CalendarDateViewCell: UICollectionViewCell {
if activeDates.count > 0 && inactiveDates.count == 0 {
showActiveDates(with: displayDate, activeDates: activeDates, inactiveDates: inactiveDates)
} else {
numberLabel.isEnabled = true
isEnabled = true
}
}
@ -204,7 +212,7 @@ final class CalendarDateViewCell: UICollectionViewCell {
disableLabel(with: surface)
showActiveDates(with: displayDate, activeDates: activeDates, inactiveDates: inactiveDates)
} else {
numberLabel.isEnabled = true
isEnabled = true
}
}
@ -213,7 +221,7 @@ final class CalendarDateViewCell: UICollectionViewCell {
if let day = Int(numberLabel.text), day < minDate.dayInt {
disableLabel(with: surface)
} else {
numberLabel.isEnabled = false
isEnabled = false
handleActiveDates(with: displayDate, activeDates: activeDates, inactiveDates: inactiveDates)
}
}
@ -223,7 +231,7 @@ final class CalendarDateViewCell: UICollectionViewCell {
if let day = Int(numberLabel.text), day > maxDate.dayInt {
disableLabel(with: surface)
} else {
numberLabel.isEnabled = false
isEnabled = false
handleActiveDates(with: displayDate, activeDates: activeDates, inactiveDates: inactiveDates)
}
}
@ -233,7 +241,7 @@ final class CalendarDateViewCell: UICollectionViewCell {
if let day = Int(numberLabel.text), day < minDate.dayInt || day > maxDate.dayInt {
disableLabel(with: surface)
} else {
numberLabel.isEnabled = false
isEnabled = false
handleActiveDates(with: displayDate, activeDates: activeDates, inactiveDates: inactiveDates)
}
}

View File

@ -6,7 +6,7 @@
//
import UIKit
import VDSTokens
import VDSCoreTokens
/// Footer view to show indicators data.
class CalendarFooterReusableView: UICollectionReusableView {
@ -224,7 +224,7 @@ private class LegendCollectionViewCell: UICollectionViewCell {
title.text = text
title.textColor = textColorConfiguration.getColor(surface)
legendIndicator.backgroundColor = drawSemiCircle ? .clear : (clearFullcircle ? .clear : color)
legendIndicator.backgroundColor = drawSemiCircle ? .clear : (clearFullcircle ? .clear : indicatorColorConfiguration.getColor(surface))
legendIndicator.layer.borderColor = indicatorColorConfiguration.getColor(surface).cgColor
self.layoutIfNeeded()
@ -239,7 +239,7 @@ private class LegendCollectionViewCell: UICollectionViewCell {
path.addArc(withCenter: center, radius: center.x, startAngle: 2 * .pi, endAngle: .pi, clockwise: true)
path.close()
shapeLayer.path = path.cgPath
shapeLayer.fillColor = color.cgColor
shapeLayer.fillColor = indicatorColorConfiguration.getColor(surface).cgColor
guard legendIndicator.layer.sublayers?.contains(shapeLayer) ?? true else { return }
legendIndicator.layer.addSublayer(shapeLayer)

View File

@ -6,7 +6,7 @@
//
import UIKit
import VDSTokens
import VDSCoreTokens
/// Header view to display month and year along with days of week.
class CalendarHeaderReusableView: UICollectionReusableView {
@ -68,16 +68,16 @@ class CalendarHeaderReusableView: UICollectionReusableView {
$0.kind = .ghost
$0.iconName = .leftCaret
$0.iconOffset = .init(x: -2, y: 0)
$0.icon.size = .small
$0.size = .small
$0.customContainerSize = 40
$0.icon.customSize = 16
}
internal var nextButton = ButtonIcon().with {
$0.kind = .ghost
$0.iconName = .rightCaret
$0.iconOffset = .init(x: 2, y: 0)
$0.icon.size = .small
$0.size = .small
$0.customContainerSize = 40
$0.icon.customSize = 16
}
internal var headerTitle = Label().with {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A carousel scrollbar is a control that allows to navigate between items in a carousel.

View File

@ -8,7 +8,7 @@
import Foundation
import UIKit
import Combine
import VDSTokens
import VDSCoreTokens
/// Checkboxes are a multi-select component through which a customer indicates a choice. This is also used within
/// ``CheckboxItem`` and ``CheckboxGroup``

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
/// When the choice has multiple options, use a checkbox group. For example, use a checkbox group when
/// asking a customer which attributes they would like to filter their search by. This uses ``CheckboxItem``

View File

@ -1,6 +1,6 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A dropdown select is an expandable menu of predefined options that allows a customer to make a single selection.
@ -101,13 +101,11 @@ open class DatePicker: EntryFieldBase, DatePickerViewControllerDelegate, UIPopov
open override func setup() {
super.setup()
fieldStackView.isAccessibilityElement = true
// setting color config
selectedDateLabel.textColorConfiguration = primaryColorConfiguration.eraseToAnyColorable()
// tap gesture
fieldStackView
containerView
.publisher(for: UITapGestureRecognizer())
.sink { [weak self] _ in
guard let self else { return }
@ -142,14 +140,7 @@ open class DatePicker: EntryFieldBase, DatePickerViewControllerDelegate, UIPopov
selectedDateLabel.isEnabled = isEnabled
calendarIcon.color = iconColorConfiguration.getColor(self)
}
open override func updateAccessibility() {
super.updateAccessibility()
fieldStackView.accessibilityLabel = "Date Picker, \(accessibilityLabelText)"
fieldStackView.accessibilityHint = isReadOnly || !isEnabled ? "" : "Double tap to open."
fieldStackView.accessibilityValue = value
}
/// Resets to default settings.
open override func reset() {
super.reset()
@ -182,7 +173,7 @@ open class DatePicker: EntryFieldBase, DatePickerViewControllerDelegate, UIPopov
controller.dismiss(animated: true) { [weak self] in
guard let self else { return }
self.sendActions(for: .valueChanged)
UIAccessibility.post(notification: .layoutChanged, argument: self.fieldStackView)
UIAccessibility.post(notification: .layoutChanged, argument: self.containerView)
}
}

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A dropdown select is an expandable menu of predefined options that allows a customer to make a single selection.
@ -66,6 +66,8 @@ open class DropdownSelect: EntryFieldBase {
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
internal override var responder: UIResponder? { dropdownField }
internal var minWidthDefault = 66.0
internal var minWidthInlineLabel = 102.0
internal override var minWidth: CGFloat { showInlineLabel ? minWidthInlineLabel : minWidthDefault }
@ -131,7 +133,6 @@ open class DropdownSelect: EntryFieldBase {
open override func setup() {
super.setup()
fieldStackView.isAccessibilityElement = true
inlineDisplayLabel.isAccessibilityElement = true
dropdownField.width(0)
@ -276,57 +277,11 @@ open class DropdownSelect: EntryFieldBase {
statusIcon.color = iconColorConfiguration.getColor(self)
}
open override func updateAccessibility() {
super.updateAccessibility()
fieldStackView.accessibilityLabel = "Dropdown Select, \(accessibilityLabelText)"
fieldStackView.accessibilityHint = isReadOnly || !isEnabled ? "" : "Double tap to open."
fieldStackView.accessibilityValue = value
}
open override var accessibilityElements: [Any]? {
get {
var elements = [Any]()
elements.append(contentsOf: [titleLabel, fieldStackView])
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() {
optionsPicker.isHidden = true
dropdownField.resignFirstResponder()
setNeedsUpdate()
UIAccessibility.post(notification: .layoutChanged, argument: fieldStackView)
}
open override var canBecomeFirstResponder: Bool {
return dropdownField.canBecomeFirstResponder
}
open override func becomeFirstResponder() -> Bool {
return dropdownField.becomeFirstResponder()
}
open override var canResignFirstResponder: Bool {
return dropdownField.canResignFirstResponder
}
open override func resignFirstResponder() -> Bool {
return dropdownField.resignFirstResponder()
UIAccessibility.post(notification: .layoutChanged, argument: containerView)
}
}
@ -337,8 +292,8 @@ extension DropdownSelect: UIPickerViewDelegate, UIPickerViewDataSource {
internal func launchPicker() {
if optionsPicker.isHidden {
UIAccessibility.post(notification: .layoutChanged, argument: optionsPicker)
dropdownField.becomeFirstResponder()
UIAccessibility.post(notification: .layoutChanged, argument: optionsPicker)
} else {
dropdownField.resignFirstResponder()
}

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A button icon is an interactive element that visually communicates the action it triggers via an icon.
@ -143,10 +143,7 @@ open class ButtonIcon: Control, Changeable {
/// Sets the size of button icon and icon.
open var size: Size = .large { didSet { setNeedsUpdate() } }
/// Sets the size of button icon and icon.
open var customSize: Int? { didSet { setNeedsUpdate() } }
/// If provided, the button icon will have a box shadow.
open var floating: Bool = false { didSet { setNeedsUpdate() } }
@ -169,10 +166,20 @@ open class ButtonIcon: Control, Changeable {
setNeedsUpdate()
}
}
/// 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() } }
/// Sets a custom size of button icon container.
open var customContainerSize: Int? { didSet { setNeedsUpdate() } }
/// Sets a custom size of the icon.
open var customIconSize: Int? { didSet { setNeedsUpdate() } }
/// Sets a custom badgeIndicator offset
open var customBadgeIndicatorOffset: CGPoint? { didSet { setNeedsUpdate() } }
//--------------------------------------------------
// MARK: - Configuration
//--------------------------------------------------
@ -444,8 +451,11 @@ open class ButtonIcon: Control, Changeable {
icon.name = currentIconName
let color = iconColorConfiguration.getColor(self)
icon.color = color
icon.size = iconSize
icon.customSize = customSize
if let customIconSize {
icon.customSize = customIconSize
} else {
icon.size = iconSize
}
icon.isEnabled = isEnabled
} else {
icon.reset()
@ -480,8 +490,8 @@ open class ButtonIcon: Control, Changeable {
//updating current container size
var iconLayoutSize = size.containerSize
if let customSize {
iconLayoutSize = CGFloat(customSize)
if let customContainerSize {
iconLayoutSize = CGFloat(customContainerSize)
}
// check to see if this is fitToIcon
if fitToIcon && kind == .ghost {
@ -503,10 +513,11 @@ open class ButtonIcon: Control, Changeable {
layer.borderWidth = 0
}
badgeIndicatorCenterXConstraint?.constant = badgeIndicatorOffset.x + badgeIndicatorDefaultSize.width/2
badgeIndicatorCenterYConstraint?.constant = badgeIndicatorOffset.y + badgeIndicatorDefaultSize.height/2
badgeIndicatorLeadingConstraint?.constant = badgeIndicatorOffset.x
badgeIndicatorTrailingConstraint?.constant = badgeIndicatorOffset.x + badgeIndicatorDefaultSize.width
let offSet = customBadgeIndicatorOffset ?? badgeIndicatorOffset
badgeIndicatorCenterXConstraint?.constant = offSet.x + badgeIndicatorDefaultSize.width/2
badgeIndicatorCenterYConstraint?.constant = offSet.y + badgeIndicatorDefaultSize.height/2
badgeIndicatorLeadingConstraint?.constant = offSet.x
badgeIndicatorTrailingConstraint?.constant = offSet.x + badgeIndicatorDefaultSize.width
if showBadgeIndicator {
updateExpandDirectionalConstraints()

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// An icon is a graphical element that conveys information at a glance. It helps orient

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
extension Icon {

View File

@ -8,7 +8,7 @@
import Foundation
import UIKit
import Combine
import VDSTokens
import VDSCoreTokens
public class TooltipLabelAttribute: ActionLabelAttributeModel, TooltipLaunchable {
public var id = UUID()

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// Label is a standard view used to draw text with applying Typography through ``TextStyle`` as well
@ -206,7 +206,7 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
}.store(in: &subscribers)
backgroundColor = .clear
numberOfLines = 0
lineBreakMode = .byWordWrapping
lineBreakMode = .byTruncatingTail
translatesAutoresizingMaskIntoConstraints = false
accessibilityCustomActions = []
isAccessibilityElement = true

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
/// A line visually separates content sections or elements in lists, tables and layouts to indicate content hierarchy.
@objc(VDSLine)

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
/// A loader is an indicator that uses animation to show customers that there is an indefinite amount of wait time while a task is ongoing, e.g. a page is loading, a form is being submitted. The component disappears when the task is complete.

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
/// ViewController to show the Loader, this will be presented using the LoaderLaunchable Protocl.
open class LoaderViewController: UIViewController, Surfaceable {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// Notifications are prominent, attention-getting banners that provide information

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
///Pagination is a control that enables customers to navigate multiple pages of content by selecting either a specific page or the next or previous set of four pages.

View File

@ -6,7 +6,7 @@
//
import UIKit
import VDSTokens
import VDSCoreTokens
///This is customised button for Pagination view
@objc(PaginationButton)

View File

@ -6,7 +6,7 @@
//
import UIKit
import VDSTokens
import VDSCoreTokens
///This is customised view for Pagination cell item
final class PaginationCellItem: UICollectionViewCell {

View File

@ -6,7 +6,7 @@
//
import Foundation
import VDSTokens
import VDSCoreTokens
import UIKit
///Customised flow layout for Pagination view

View File

@ -8,7 +8,7 @@
import Foundation
import UIKit
import Combine
import VDSTokens
import VDSCoreTokens
/// Radio boxes are single-select components through which a customer indicates a choice
/// that are used within a ``RadioBoxGroup``.

View File

@ -8,7 +8,7 @@
import Foundation
import UIKit
import Combine
import VDSTokens
import VDSCoreTokens
/// Radio buttons are single-select components through which a customer indicates a choice.
/// They must always be paired with one or more ``RadioButtonItem`` within a ``RadioButtonGroup``.

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
///Table is view composed of rows and columns, which takes any view into each cell and resizes based on the highest cell height.
@objc(VDSTable)

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
final class TableCellItem: UICollectionViewCell {

View File

@ -6,7 +6,7 @@
//
import UIKit
import VDSTokens
import VDSCoreTokens
protocol TableCollectionViewLayoutDataDelegate: AnyObject {
func collectionView(_ collectionView: UICollectionView, dataForItemAt indexPath: IndexPath) -> TableItemModel

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
/// Model that represent the content of each cell of Table component
public struct TableItemModel {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
extension Tabs {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
/// Tabs are organizational components that group content and allow customers to navigate its display. Use them to separate content when the content is related but doesnt need to be compared.
@objc(VDSTabs)
@ -267,6 +267,8 @@ open class Tabs: View {
}
}
}
accessibilityElements = tabViews
setNeedsUpdate()
scrollToSelectedIndex(animated: false)
}

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// Base Class used to build out a Input controls.
@ -40,6 +40,8 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
internal var responder: UIResponder? { return nil }
internal let mainStackView = UIStackView().with {
$0.axis = .vertical
$0.alignment = .fill
@ -95,6 +97,7 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
internal var containerView: UIView = {
return UIView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.isAccessibilityElement = true
}
}()
@ -243,7 +246,8 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
open var accessibilityLabelText: String {
var accessibilityLabels = [String]()
if let text = titleLabel.text {
if let text = titleLabel.text?.trimmingCharacters(in: .whitespaces) {
accessibilityLabels.append(text)
}
if isReadOnly {
@ -255,9 +259,14 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
if let errorText, showError {
accessibilityLabels.append("error, \(errorText)")
}
accessibilityLabels.append("\(Self.self)")
return accessibilityLabels.joined(separator: ", ")
}
open var accessibilityHintText: String = "Double tap to open"
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
@ -360,6 +369,22 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
isReadOnly = false
onChange = nil
}
open override var canBecomeFirstResponder: Bool {
responder?.canBecomeFirstResponder ?? super.canBecomeFirstResponder
}
open override func becomeFirstResponder() -> Bool {
responder?.becomeFirstResponder() ?? super.becomeFirstResponder()
}
open override var canResignFirstResponder: Bool {
responder?.canResignFirstResponder ?? super.canResignFirstResponder
}
open override func resignFirstResponder() -> Bool {
responder?.resignFirstResponder() ?? super.resignFirstResponder()
}
//--------------------------------------------------
// MARK: - Public Methods
@ -447,6 +472,35 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable {
}
}
open override func updateAccessibility() {
super.updateAccessibility()
containerView.accessibilityLabel = accessibilityLabelText
containerView.accessibilityHint = isReadOnly || !isEnabled ? "" : accessibilityHintText
containerView.accessibilityValue = value
}
open override var accessibilityElements: [Any]? {
get {
var elements = [Any]()
elements.append(contentsOf: [titleLabel, containerView])
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 }
}
//--------------------------------------------------
// MARK: - Private Methods
//--------------------------------------------------

View File

@ -216,9 +216,12 @@ extension InputField {
return false
}
// Set the value to the rawNumber, if you don't the onChange will trigger
value = rawNumber
// Set the formatted text
textField.text = formattedNumber
// Calculate the new cursor position
if let newPosition = textField.cursorPosition(range: range,
replacementString: string,
@ -227,9 +230,6 @@ extension InputField {
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
}
// if all passes, then set the number1
value = rawNumber
// Prevent the default behavior
return false
}
@ -252,11 +252,20 @@ extension InputField {
internal func maskCreditCardNumber(_ cardType: CreditCardType, number: String) -> String {
// Mask the first 12 characters if the length is 16
let rawNumber = number.filter { $0.isNumber }
guard rawNumber.count == cardType.maxLength else { return formatCreditCardNumber(cardType, number: number) }
let count = rawNumber.count
let min = cardType.minLength
let max = cardType.maxLength
var shouldFormat: Bool = false
if min == max {
shouldFormat = true
} else {
shouldFormat = count >= min && count <= max
}
guard shouldFormat else { return formatCreditCardNumber(cardType, number: number) }
let lastFourDigits = rawNumber.suffix(4)
let maskedSection = String(repeating: "", count: 12)
let formattedMaskSection = String.format(maskedSection, indices: cardType.separatorIndices(rawNumber.count), with: " ")
return formattedMaskSection + " " + lastFourDigits
let maskedSection = String(repeating: "", count: number.count - lastFourDigits.count)
let formattedMaskSection = String.format(maskedSection + lastFourDigits, indices: cardType.separatorIndices(rawNumber.count), with: " ")
return formattedMaskSection
}
}
}

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
extension InputField {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
extension InputField {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// An input field is an input wherein a customer enters information. They typically appear in forms.
@ -34,6 +34,8 @@ open class InputField: EntryFieldBase {
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
internal override var responder: UIResponder? { textField }
internal override var containerBackgroundColor: UIColor {
if showSuccess {
return backgroundColorConfiguration.getColor(self)
@ -102,6 +104,7 @@ open class InputField: EntryFieldBase {
open var textField = TextField().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.textStyle = TextStyle.bodyLarge
$0.isAccessibilityElement = false
}
/// Color configuration for the textField.
@ -181,6 +184,8 @@ open class InputField: EntryFieldBase {
/// 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()
accessibilityHintText = "Double tap to edit"
textField.heightAnchor.constraint(equalToConstant: 20).isActive = true
textField.delegate = self
bottomContainerStackView.insertArrangedSubview(successLabel, at: 0)
@ -227,13 +232,7 @@ open class InputField: EntryFieldBase {
textField.isEnabled = isEnabled
textField.isUserInteractionEnabled = isEnabled && !isReadOnly
}
open override func updateAccessibility() {
super.updateAccessibility()
textField.accessibilityLabel = accessibilityLabelText
textField.accessibilityHint = isReadOnly || !isEnabled ? "" : "Double tap to open."
}
open override func updateErrorLabel() {
super.updateErrorLabel()
@ -264,7 +263,7 @@ open class InputField: EntryFieldBase {
open override var accessibilityElements: [Any]? {
get {
var elements = [Any]()
elements.append(contentsOf: [titleLabel, textField])
elements.append(contentsOf: [titleLabel, containerView])
if showError {
elements.append(statusIcon)
if let errorText, !errorText.isEmpty {
@ -283,22 +282,6 @@ open class InputField: EntryFieldBase {
set { super.accessibilityElements = newValue }
}
open override var canBecomeFirstResponder: Bool {
return textField.canBecomeFirstResponder
}
open override func becomeFirstResponder() -> Bool {
return textField.becomeFirstResponder()
}
open override var canResignFirstResponder: Bool {
return textField.canResignFirstResponder
}
open override func resignFirstResponder() -> Bool {
return textField.resignFirstResponder()
}
}
extension InputField: UITextFieldDelegate {
@ -311,6 +294,7 @@ extension InputField: UITextFieldDelegate {
public func textFieldDidEndEditing(_ textField: UITextField) {
fieldType.handler().textFieldDidEndEditing(self, textField: textField)
validate()
UIAccessibility.post(notification: .layoutChanged, argument: self.containerView)
}
public func textFieldDidChangeSelection(_ textField: UITextField) {

View File

@ -8,7 +8,7 @@
import Foundation
import UIKit
import Combine
import VDSTokens
import VDSCoreTokens
@objc(VDSTextField)
open class TextField: UITextField, ViewProtocol, Errorable {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A text area is an input wherein a customer enters long-form information.
@ -32,6 +32,8 @@ open class TextArea: EntryFieldBase {
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
internal override var responder: UIResponder? { textView }
internal var textViewHeightConstraint: NSLayoutConstraint?
internal var inputFieldStackView: UIStackView = {
@ -42,14 +44,14 @@ open class TextArea: EntryFieldBase {
$0.spacing = VDSLayout.space3X
}
}()
open var characterCounterLabel = Label().with {
$0.setContentCompressionResistancePriority(.required, for: .vertical)
$0.textStyle = .bodySmall
$0.textAlignment = .right
$0.numberOfLines = 1
}
open var minHeight: Height = .twoX { didSet { setNeedsUpdate() } }
//--------------------------------------------------
@ -101,13 +103,15 @@ open class TextArea: EntryFieldBase {
open override var value: String? {
return textView.text
}
/// UITextView shown in the TextArea.
open var textView = TextView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.sizeToFit()
$0.isScrollEnabled = false
$0.isAccessibilityElement = false
$0.isScrollEnabled = true
$0.textContainerInset = .zero
$0.autocorrectionType = .no
$0.textContainer.lineFragmentPadding = 0
}
@ -137,10 +141,8 @@ open class TextArea: EntryFieldBase {
/// 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()
fieldStackView.pinToSuperView(.uniform(VDSFormControls.spaceInset))
textView.isScrollEnabled = true
textView.autocorrectionType = .no
accessibilityHintText = "Double tap to edit"
//events
textView
@ -159,6 +161,7 @@ open class TextArea: EntryFieldBase {
.publisher(for: .editingDidEnd)
.sink { [weak self] _ in
self?.validate()
UIAccessibility.post(notification: .layoutChanged, argument: self?.containerView)
}.store(in: &subscribers)
textViewHeightConstraint = textView.heightAnchor.constraint(greaterThanOrEqualToConstant: containerSize.height)
@ -192,13 +195,7 @@ open class TextArea: EntryFieldBase {
characterCounterLabel.surface = surface
highlightCharacterOverflow()
}
open override func updateAccessibility() {
super.updateAccessibility()
textView.accessibilityLabel = accessibilityLabelText
textView.accessibilityHint = isReadOnly || !isEnabled ? "" : "Double tap to open."
}
override func updateRules() {
super.updateRules()
@ -222,46 +219,7 @@ open class TextArea: EntryFieldBase {
stackView.addArrangedSubview(characterCounterLabel)
return stackView
}
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 {
return textView.canBecomeFirstResponder
}
open override func becomeFirstResponder() -> Bool {
return textView.becomeFirstResponder()
}
open override var canResignFirstResponder: Bool {
return textView.canResignFirstResponder
}
open override func resignFirstResponder() -> Bool {
return textView.resignFirstResponder()
}
//--------------------------------------------------
// MARK: - Private Methods
//--------------------------------------------------

View File

@ -8,7 +8,7 @@
import Foundation
import UIKit
import Combine
import VDSTokens
import VDSCoreTokens
@objc(VDSTextView)
open class TextView: UITextView, ViewProtocol, Errorable {

View File

@ -6,7 +6,7 @@
//
import Foundation
import VDSTokens
import VDSCoreTokens
import UIKit
import Combine
@ -69,6 +69,7 @@ open class TileContainerBase<PaddingType: DefaultValuing>: Control where Padding
case secondary
case white
case black
case token(UIColor.VDSColor)
case custom(UIColor)
private var reflectedValue: String { String(reflecting: self) }
@ -484,6 +485,8 @@ extension TileContainerBase {
return whiteColorConfig.getColor(object.surface)
case .black:
return blackColorConfig.getColor(object.surface)
case .token(let vdsColor):
return vdsColor.uiColor
case .custom(let color):
return color
}

View File

@ -7,7 +7,7 @@
import Foundation
import Foundation
import VDSTokens
import VDSCoreTokens
import UIKit
import Combine

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
extension Tilelet {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// Title Lockup ensures the readability of words on the screen

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
extension TitleLockup {

View File

@ -6,7 +6,7 @@
//
import Foundation
import VDSTokens
import VDSCoreTokens
import UIKit
extension TitleLockup {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A toggle is a control that lets customers instantly turn on

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A toggle is a control that lets customers instantly turn on

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
import Combine
/// A tooltip is an overlay that clarifies another component or content

View File

@ -8,7 +8,7 @@
import Foundation
import UIKit
import Combine
import VDSTokens
import VDSCoreTokens
open class TooltipAlertViewController: UIViewController, Surfaceable {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
open class TooltipDialog: View, UIScrollViewDelegate {

View File

@ -6,7 +6,7 @@
//
import Foundation
import VDSTokens
import VDSCoreTokens
import UIKit
extension UIColor {
@ -47,6 +47,7 @@ extension UIColor {
case paletteGreen61
case paletteGreen36
case paletteGreen26
case paletteGreen22
case paletteGreen15
case paletteGreen10
case palettePink87
@ -59,6 +60,16 @@ extension UIColor {
case palettePurple60
case palettePurple39
case palettePurple20
case paletteMonarchred
case paletteStone
case paletteNeonyellow
case paletteCoral
case paletteWarmgray95
case paletteWarmgray84
case paletteWarmgray64
case paletteWarmgray41
case paletteWarmgray20
case paletteWarmgray11
case backgroundPrimaryLight
case backgroundPrimaryDark
case backgroundPrimaryInverseLight
@ -145,15 +156,15 @@ extension UIColor {
case badgesBackgroundWhiteOndark
case badgesBackgroundBlackOnlight
case badgesBackgroundBlackOndark
/// Map each color name to its corresponding UIColor object.
public var uiColor: UIColor {
do {
let color = try VDSTokens.VDSColor.getTokenByString(tokenName: "VDSColor.\(rawValue)")
let color = try VDSCoreTokens.VDSColor.getTokenByString(tokenName: "VDSColor.\(rawValue)")
return color
} catch {
print(error)
return VDSTokens.VDSColor.paletteBlack
return VDSCoreTokens.VDSColor.paletteBlack
}
}
}

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
extension UIColor {
//--------------------------------------------------

View File

@ -56,8 +56,9 @@ extension UIView {
for subview in view.subviews {
if subview.isAccessibilityElement && subview.isVisibleOnScreen {
elements.append(subview)
} else {
elements.append(contentsOf: gatherAccessibilityElements(from: subview))
}
elements.append(contentsOf: gatherAccessibilityElements(from: subview))
}
return elements

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
//--------------------------------------------------
// MARK: - Debug Borders

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
extension UIView {
public func constraint(with identifier: String) -> NSLayoutConstraint? {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
public protocol LayoutConstraintable {
var superview: UIView? { get }

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
/// The background tint that the component will be placed on. This will automatically adjust other elements as needed and takes "light" or "dark"
public enum Surface: String, Equatable {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
/// Enum to describe types of use.
public enum Use: String, Equatable {

View File

@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "discover.svg",
"filename" : "Discover-02.svg",
"idiom" : "universal"
}
],

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,49 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 20">
<g>
<path fill="#231F20" d="M1.447,7.449H0v5.067h1.447c0.763,0,1.324-0.184,1.806-0.587c0.579-0.482,0.921-1.201,0.921-1.946
C4.164,8.492,3.051,7.449,1.447,7.449z M2.604,11.254c-0.307,0.281-0.71,0.403-1.35,0.403H0.991V8.308h0.263
c0.64,0,1.026,0.114,1.35,0.412c0.342,0.307,0.544,0.772,0.544,1.262C3.147,10.465,2.946,10.947,2.604,11.254z"/>
<rect id="XMLID_422_" x="4.62" y="7.449" fill="#231F20" width="0.991" height="5.067"/>
<path id="XMLID_421_" fill="#231F20" d="M8.022,9.395c-0.596-0.219-0.763-0.368-0.763-0.64c0-0.316,0.307-0.561,0.736-0.561
c0.298,0,0.535,0.123,0.798,0.412l0.517-0.675C8.89,7.563,8.381,7.37,7.82,7.37c-0.894,0-1.578,0.622-1.578,1.447
c0,0.701,0.316,1.052,1.245,1.385c0.386,0.14,0.587,0.228,0.684,0.289c0.202,0.132,0.298,0.316,0.298,0.526
c0,0.412-0.324,0.71-0.763,0.71c-0.473,0-0.85-0.237-1.078-0.675l-0.64,0.614c0.456,0.666,0.999,0.964,1.753,0.964
c1.026,0,1.745-0.684,1.745-1.666C9.486,10.167,9.153,9.807,8.022,9.395z"/>
<path id="XMLID_420_" fill="#231F20" d="M9.793,9.982c0,1.49,1.166,2.639,2.674,2.639c0.421,0,0.789-0.088,1.236-0.298v-1.166
c-0.395,0.395-0.745,0.552-1.192,0.552c-0.991,0-1.701-0.719-1.701-1.745c0-0.973,0.728-1.736,1.657-1.736
c0.473,0,0.824,0.167,1.236,0.57V7.633c-0.43-0.219-0.789-0.307-1.219-0.307C10.994,7.335,9.793,8.51,9.793,9.982z"/>
<polygon id="XMLID_419_" fill="#231F20" points="21.532,10.85 20.182,7.449 19.104,7.449 21.26,12.648 21.786,12.648 23.978,7.449
22.908,7.449 "/>
<polygon id="XMLID_418_" fill="#231F20" points="24.425,12.516 27.222,12.516 27.222,11.657 25.407,11.657 25.407,10.289
27.152,10.289 27.152,9.43 25.407,9.43 25.407,8.308 27.222,8.308 27.222,7.449 24.425,7.449 "/>
<path fill="#231F20" d="M31.132,8.948c0-0.947-0.649-1.499-1.788-1.499h-1.464v5.067h0.991v-2.034h0.132l1.368,2.034h1.219
l-1.596-2.13C30.72,10.228,31.132,9.719,31.132,8.948z M29.151,9.781h-0.289V8.247h0.307c0.614,0,0.947,0.254,0.947,0.754
C30.115,9.509,29.782,9.781,29.151,9.781z"/>
<linearGradient id="XMLID_2_" gradientUnits="userSpaceOnUse" x1="18.0982" y1="592.1596" x2="16.2331" y2="589.2393" gradientTransform="matrix(1 0 0 1 0 -580)">
<stop offset="0" stop-color="#F89F20"/>
<stop offset="0.2502" stop-color="#F79A20"/>
<stop offset="0.5331" stop-color="#F68D20"/>
<stop offset="0.6196" stop-color="#F58720"/>
<stop offset="0.7232" stop-color="#F48120"/>
<stop offset="1" stop-color="#F37521"/>
</linearGradient>
<circle id="XMLID_415_" fill="url(#XMLID_2_)" cx="16.719" cy="10" r="2.692"/>
<linearGradient id="XMLID_3_" gradientUnits="userSpaceOnUse" x1="17.8034" y1="592.1198" x2="15.0775" y2="586.7917" gradientTransform="matrix(1 0 0 1 0 -580)">
<stop offset="0" stop-color="#F58720"/>
<stop offset="0.3587" stop-color="#E16F27"/>
<stop offset="0.703" stop-color="#D4602C"/>
<stop offset="0.9816" stop-color="#D05B2E"/>
</linearGradient>
<circle id="XMLID_414_" opacity="0.65" fill="url(#XMLID_3_)" cx="16.719" cy="10" r="2.692"/>
<g id="XMLID_430_">
<path fill="#231F20" d="M31.763,7.642c0-0.088-0.061-0.14-0.167-0.14h-0.14v0.447h0.105V7.773l0.123,0.175h0.132l-0.149-0.184
C31.728,7.747,31.763,7.703,31.763,7.642z M31.579,7.703h-0.018V7.589h0.018c0.053,0,0.079,0.018,0.079,0.061
C31.658,7.685,31.632,7.703,31.579,7.703z"/>
<path fill="#231F20" d="M31.614,7.335c-0.219,0-0.386,0.175-0.386,0.386c0,0.219,0.175,0.386,0.386,0.386
c0.21,0,0.386-0.175,0.386-0.386C32,7.51,31.825,7.335,31.614,7.335z M31.614,8.045c-0.167,0-0.307-0.14-0.307-0.316
c0-0.175,0.14-0.316,0.307-0.316c0.167,0,0.307,0.149,0.307,0.316C31.921,7.905,31.781,8.045,31.614,8.045z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "jcb.svg",
"filename" : "jcb-emblem-logo.svg",
"idiom" : "universal"
}
],

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="_レイヤー_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34 26.19"><path d="M34,20.91c0,2.91-2.37,5.28-5.28,5.28H0V5.28C0,2.37,2.37,0,5.28,0h28.72V20.91Z" fill="#fff"/><path d="M24.65,15.55h2.18l.27-.02c.42-.08,.77-.46,.77-.98s-.35-.87-.77-.98l-.27-.02h-2.18v2Z" fill="#469b23"/><path d="M26.58,1.77c-2.08,0-3.78,1.68-3.78,3.78v3.93h5.34c.12,0,.27,0,.37,.02,1.21,.06,2.1,.69,2.1,1.77,0,.85-.6,1.58-1.72,1.72v.04c1.23,.08,2.16,.77,2.16,1.83,0,1.14-1.04,1.89-2.41,1.89h-5.86v7.69h5.55c2.08,0,3.78-1.68,3.78-3.78V1.77h-5.53Z" fill="#469b23"/><path d="M27.6,11.51c0-.5-.35-.83-.77-.89l-.21-.02h-1.97v1.83h1.97l.21-.02c.42-.06,.77-.39,.77-.89Z" fill="#469b23"/><path d="M5.67,1.77c-2.08,0-3.78,1.68-3.78,3.78V14.88c1.06,.52,2.16,.85,3.26,.85,1.31,0,2.02-.79,2.02-1.87v-4.41h3.24v4.39c0,1.7-1.06,3.1-4.66,3.1-2.18,0-3.89-.48-3.89-.48v7.96H7.42c2.08,0,3.78-1.68,3.78-3.78V1.77H5.67Z" fill="#0c2c84"/><path d="M16.13,1.77c-2.08,0-3.78,1.68-3.78,3.78v4.95c.96-.81,2.62-1.33,5.3-1.21,1.43,.06,2.97,.46,2.97,.46v1.6c-.77-.39-1.68-.75-2.87-.83-2.04-.15-3.26,.85-3.26,2.6s1.23,2.76,3.26,2.6c1.18-.08,2.1-.46,2.87-.83v1.6s-1.52,.39-2.97,.46c-2.68,.12-4.34-.39-5.3-1.21v8.73h5.55c2.08,0,3.78-1.68,3.78-3.78V1.77h-5.55Z" fill="#d7182a"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,51 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 20">
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-856.4599" y1="503.2267" x2="-855.8029" y2="503.2267" gradientTransform="matrix(12.5258 0 0 -12.5258 10748.9648 6314.5825)">
<stop offset="0" stop-color="#007940"/>
<stop offset="0.229" stop-color="#00873F"/>
<stop offset="0.743" stop-color="#40A737"/>
<stop offset="1" stop-color="#5CB531"/>
</linearGradient>
<path fill="url(#SVGID_1_)" d="M22.7,12.1h1.9c0.1,0,0.2,0,0.2,0c0.4-0.1,0.7-0.4,0.7-0.9c0-0.4-0.3-0.8-0.7-0.9c-0.1,0-0.2,0-0.2,0h-1.9
V12.1z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-856.4599" y1="503.3283" x2="-855.8034" y2="503.3283" gradientTransform="matrix(12.5258 0 0 -12.5258 10748.9648 6314.5825)">
<stop offset="0" stop-color="#007940"/>
<stop offset="0.229" stop-color="#00873F"/>
<stop offset="0.743" stop-color="#40A737"/>
<stop offset="1" stop-color="#5CB531"/>
</linearGradient>
<path fill="url(#SVGID_2_)" d="M24.5,0c-1.8,0-3.3,1.5-3.3,3.3v3.5h4.7c0.1,0,0.2,0,0.3,0C27.2,6.9,28,7.4,28,8.4c0,0.8-0.5,1.4-1.5,1.5v0
c1.1,0.1,1.9,0.7,1.9,1.6c0,1-0.9,1.7-2.1,1.7h-5.2V20H26c1.8,0,3.3-1.5,3.3-3.3V0L24.5,0z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-856.4599" y1="503.4401" x2="-855.8029" y2="503.4401" gradientTransform="matrix(12.5258 0 0 -12.5258 10748.9648 6314.5825)">
<stop offset="0" stop-color="#007940"/>
<stop offset="0.229" stop-color="#00873F"/>
<stop offset="0.743" stop-color="#40A737"/>
<stop offset="1" stop-color="#5CB531"/>
</linearGradient>
<path fill="url(#SVGID_3_)" d="M25.3,8.6c0-0.4-0.3-0.7-0.7-0.8c0,0-0.1,0-0.2,0h-1.7v1.6h1.7c0.1,0,0.2,0,0.2,0C25,9.3,25.3,9,25.3,8.6
L25.3,8.6z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-857.9309" y1="503.329" x2="-857.2637" y2="503.329" gradientTransform="matrix(12.5258 0 0 -12.5258 10748.9648 6314.5825)">
<stop offset="0" stop-color="#1F286F"/>
<stop offset="0.475" stop-color="#004E94"/>
<stop offset="0.826" stop-color="#0066B1"/>
<stop offset="1" stop-color="#006FBC"/>
</linearGradient>
<path fill="url(#SVGID_4_)" d="M6,0C4.2,0,2.7,1.5,2.7,3.3v8.2c0.9,0.5,1.9,0.8,2.9,0.8c1.2,0,1.8-0.7,1.8-1.6V6.8h2.9v3.9
c0,1.5-0.9,2.7-4.1,2.7c-1.9,0-3.4-0.4-3.4-0.4v7h4.9c1.8,0,3.3-1.5,3.3-3.3V0L6,0z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="-857.1989" y1="503.3275" x2="-856.5508" y2="503.3275" gradientTransform="matrix(12.5258 0 0 -12.5258 10748.9648 6314.5825)">
<stop offset="0" stop-color="#6C2C2F"/>
<stop offset="0.173" stop-color="#882730"/>
<stop offset="0.573" stop-color="#BE1833"/>
<stop offset="0.859" stop-color="#DC0436"/>
<stop offset="1" stop-color="#E60039"/>
</linearGradient>
<path fill="url(#SVGID_5_)" d="M15.2,0c-1.8,0-3.3,1.5-3.3,3.3v4.4c0.8-0.7,2.3-1.2,4.7-1.1C17.8,6.7,19.2,7,19.2,7v1.4
c-0.7-0.3-1.5-0.7-2.5-0.7c-1.8-0.1-2.9,0.8-2.9,2.3c0,1.6,1.1,2.4,2.9,2.3c1-0.1,1.8-0.4,2.5-0.7V13c0,0-1.3,0.3-2.6,0.4
c-2.4,0.1-3.8-0.3-4.7-1.1V20h4.9c1.8,0,3.3-1.5,3.3-3.3V0L15.2,0z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -1,19 +1,37 @@
1.0.67
----------------
- CXTDT-568463 - Calendar - On long press, hover randomizes
- CXTDT-568412 - Calendar - Incorrect side nav icon size
- CXTDT-568422 - Calendar - DarkMode Legend icon fill using Light mode color
- CXTDT-553663 - DropdownSelect - Accessibility - has popup
- CXTDT-565796 - DropdownSelect - Accessibility
- CXTDT-560458 - Dropdown/TextArea - Different voiceover
- CXTDT-565106 - InputField - CreditCard - Icons
- CXTDT-546821 - TextArea - Accessibility
- CXTDT-560823 - TextArea - Accessibility
1.0.66
----------------
- ONEAPP-6325 - Table - Development finished
- CXTDT-565087 - InputField - Text - OnDark colors
- CXTDT-565112 - InputField - Credit Card icons
- CXTDT-565117 - InputField - Overflow not clipped
- CXTDT-565105 - InputField - Date - Typeover text not working
- CXTDT-565115 - InputField - CreditCard - China UnionPay does not allow longer numbers
- CXTDT-560823 TextArea Accessibility Labels/Error/ReadyOnly/Disabled
- CXTDT-553663 - DropdownSelect Accessibility
- CXTDT-544662 - Breadcrumbs - Text Wrapping
- CXTDT-568398 - Calendar - Saturday missing (on smaller screen size devices)
- CXTDT-568402 - Calendar - Extra row (on smaller screen size devices)
- CXTDT-568409 - Calendar - Width control missing
- CXTDT-568419 - Calendar - When hideContainerBorder=true, corner radius disappears
- CXTDT-568413 - Calendar - Missing option for Transparent Background
- CXTDT-553663 - DropdownSelect Accessibility
- CXTDT-565796 - DropdownSelect Accessibility
- CXTDT-560458 - DropdownSelect - Accessibility
- CXTDT-565087 - InputField - Text - OnDark colors
- CXTDT-565112 - InputField - Credit Card icons
- CXTDT-565117 - InputField - Overflow not clipped
- CXTDT-565105 - InputField - Date - Typeover text not working
- CXTDT-565106 - InputField - CreditCard - Incorrect generic card icon color
- CXTDT-565115 - InputField - CreditCard - China UnionPay does not allow longer numbers
- CXTDT-560823 TextArea Accessibility Labels/Error/ReadyOnly/Disabled
- CXTDT-552060 - TextArea - Placeholder text
- CXTDT-565164 TileContainer Voiceover reads extra text “Accessible”
- CXTDT-552834 TileContainer Voice over is not rendering the information present within the tile container when it receives focus in clickable state.
1.0.65
----------------

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
//MARK: Definitions
extension TextStyle {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
//MARK: Alignments
extension TextStyle {

View File

@ -7,7 +7,7 @@
import Foundation
import UIKit
import VDSTokens
import VDSCoreTokens
/// This is the Definition that will determine how the Text is drawn