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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@
import Foundation import Foundation
import UIKit import UIKit
import VDSTokens import VDSCoreTokens
import Combine 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``. /// 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 Foundation
import UIKit import UIKit
import VDSTokens import VDSCoreTokens
import Combine import Combine
/// Base class used for UIButton type classes. /// Base class used for UIButton type classes.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@
import Foundation import Foundation
import UIKit import UIKit
import VDSTokens import VDSCoreTokens
/// When the choice has multiple options, use a checkbox group. For example, use a checkbox group when /// 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`` /// 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 Foundation
import UIKit import UIKit
import VDSTokens import VDSCoreTokens
import Combine import Combine
/// A dropdown select is an expandable menu of predefined options that allows a customer to make a single selection. /// 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() { open override func setup() {
super.setup() super.setup()
fieldStackView.isAccessibilityElement = true
// setting color config // setting color config
selectedDateLabel.textColorConfiguration = primaryColorConfiguration.eraseToAnyColorable() selectedDateLabel.textColorConfiguration = primaryColorConfiguration.eraseToAnyColorable()
// tap gesture // tap gesture
fieldStackView containerView
.publisher(for: UITapGestureRecognizer()) .publisher(for: UITapGestureRecognizer())
.sink { [weak self] _ in .sink { [weak self] _ in
guard let self else { return } guard let self else { return }
@ -142,14 +140,7 @@ open class DatePicker: EntryFieldBase, DatePickerViewControllerDelegate, UIPopov
selectedDateLabel.isEnabled = isEnabled selectedDateLabel.isEnabled = isEnabled
calendarIcon.color = iconColorConfiguration.getColor(self) 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. /// Resets to default settings.
open override func reset() { open override func reset() {
super.reset() super.reset()
@ -182,7 +173,7 @@ open class DatePicker: EntryFieldBase, DatePickerViewControllerDelegate, UIPopov
controller.dismiss(animated: true) { [weak self] in controller.dismiss(animated: true) { [weak self] in
guard let self else { return } guard let self else { return }
self.sendActions(for: .valueChanged) 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 Foundation
import UIKit import UIKit
import VDSTokens import VDSCoreTokens
import Combine import Combine
/// A dropdown select is an expandable menu of predefined options that allows a customer to make a single selection. /// 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 // MARK: - Private Properties
//-------------------------------------------------- //--------------------------------------------------
internal override var responder: UIResponder? { dropdownField }
internal var minWidthDefault = 66.0 internal var minWidthDefault = 66.0
internal var minWidthInlineLabel = 102.0 internal var minWidthInlineLabel = 102.0
internal override var minWidth: CGFloat { showInlineLabel ? minWidthInlineLabel : minWidthDefault } internal override var minWidth: CGFloat { showInlineLabel ? minWidthInlineLabel : minWidthDefault }
@ -131,7 +133,6 @@ open class DropdownSelect: EntryFieldBase {
open override func setup() { open override func setup() {
super.setup() super.setup()
fieldStackView.isAccessibilityElement = true
inlineDisplayLabel.isAccessibilityElement = true inlineDisplayLabel.isAccessibilityElement = true
dropdownField.width(0) dropdownField.width(0)
@ -276,57 +277,11 @@ open class DropdownSelect: EntryFieldBase {
statusIcon.color = iconColorConfiguration.getColor(self) 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() { @objc open func pickerDoneClicked() {
optionsPicker.isHidden = true optionsPicker.isHidden = true
dropdownField.resignFirstResponder() dropdownField.resignFirstResponder()
setNeedsUpdate() setNeedsUpdate()
UIAccessibility.post(notification: .layoutChanged, argument: fieldStackView) UIAccessibility.post(notification: .layoutChanged, argument: containerView)
}
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()
} }
} }
@ -337,8 +292,8 @@ extension DropdownSelect: UIPickerViewDelegate, UIPickerViewDataSource {
internal func launchPicker() { internal func launchPicker() {
if optionsPicker.isHidden { if optionsPicker.isHidden {
UIAccessibility.post(notification: .layoutChanged, argument: optionsPicker)
dropdownField.becomeFirstResponder() dropdownField.becomeFirstResponder()
UIAccessibility.post(notification: .layoutChanged, argument: optionsPicker)
} else { } else {
dropdownField.resignFirstResponder() dropdownField.resignFirstResponder()
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@
import Foundation import Foundation
import UIKit import UIKit
import VDSTokens import VDSCoreTokens
import Combine 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. ///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 UIKit
import VDSTokens import VDSCoreTokens
///This is customised button for Pagination view ///This is customised button for Pagination view
@objc(PaginationButton) @objc(PaginationButton)

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@
import Foundation import Foundation
import UIKit 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. ///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) @objc(VDSTable)

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@
import Foundation import Foundation
import UIKit 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. /// 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) @objc(VDSTabs)
@ -267,6 +267,8 @@ open class Tabs: View {
} }
} }
} }
accessibilityElements = tabViews
setNeedsUpdate() setNeedsUpdate()
scrollToSelectedIndex(animated: false) scrollToSelectedIndex(animated: false)
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@
import Foundation import Foundation
import UIKit 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" /// 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 { public enum Surface: String, Equatable {

View File

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

View File

@ -1,7 +1,7 @@
{ {
"images" : [ "images" : [
{ {
"filename" : "discover.svg", "filename" : "Discover-02.svg",
"idiom" : "universal" "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" : [ "images" : [
{ {
"filename" : "jcb.svg", "filename" : "jcb-emblem-logo.svg",
"idiom" : "universal" "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 1.0.66
---------------- ----------------
- ONEAPP-6325 - Table - Development finished - 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-544662 - Breadcrumbs - Text Wrapping
- CXTDT-568398 - Calendar - Saturday missing (on smaller screen size devices) - CXTDT-568398 - Calendar - Saturday missing (on smaller screen size devices)
- CXTDT-568402 - Calendar - Extra row (on smaller screen size devices) - CXTDT-568402 - Calendar - Extra row (on smaller screen size devices)
- CXTDT-568409 - Calendar - Width control missing - CXTDT-568409 - Calendar - Width control missing
- CXTDT-568419 - Calendar - When hideContainerBorder=true, corner radius disappears - CXTDT-568419 - Calendar - When hideContainerBorder=true, corner radius disappears
- CXTDT-568413 - Calendar - Missing option for Transparent Background - 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 1.0.65
---------------- ----------------

View File

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

View File

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

View File

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