Merge branch 'develop' into mbruce/bugfix

This commit is contained in:
Matt Bruce 2024-08-27 11:43:48 -05:00
commit 63499838c6
29 changed files with 318 additions and 123 deletions

View File

@ -11,6 +11,7 @@
180636C92C29B0DF00C92D86 /* InputStepperLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 180636C82C29B0DF00C92D86 /* InputStepperLog.txt */; }; 180636C92C29B0DF00C92D86 /* InputStepperLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 180636C82C29B0DF00C92D86 /* InputStepperLog.txt */; };
1808BEBC2BA41C3200129230 /* CarouselScrollbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */; }; 1808BEBC2BA41C3200129230 /* CarouselScrollbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */; };
1832AC572BA0791D008AE476 /* BreadcrumbCellItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1832AC562BA0791D008AE476 /* BreadcrumbCellItem.swift */; }; 1832AC572BA0791D008AE476 /* BreadcrumbCellItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1832AC562BA0791D008AE476 /* BreadcrumbCellItem.swift */; };
183B16F32C78CF7C00BA6A10 /* CarouselSlotCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 183B16F22C78CF7C00BA6A10 /* CarouselSlotCell.swift */; };
184023452C61E7AD00A412C8 /* PriceLockup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 184023442C61E7AD00A412C8 /* PriceLockup.swift */; }; 184023452C61E7AD00A412C8 /* PriceLockup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 184023442C61E7AD00A412C8 /* PriceLockup.swift */; };
184023472C61E7EC00A412C8 /* PriceLockupChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 184023462C61E7EC00A412C8 /* PriceLockupChangeLog.txt */; }; 184023472C61E7EC00A412C8 /* PriceLockupChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 184023462C61E7EC00A412C8 /* PriceLockupChangeLog.txt */; };
1842B1DF2BECE28B0021AFCA /* CalendarDateViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1842B1DE2BECE28B0021AFCA /* CalendarDateViewCell.swift */; }; 1842B1DF2BECE28B0021AFCA /* CalendarDateViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1842B1DE2BECE28B0021AFCA /* CalendarDateViewCell.swift */; };
@ -216,6 +217,7 @@
1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselScrollbar.swift; sourceTree = "<group>"; }; 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselScrollbar.swift; sourceTree = "<group>"; };
1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CarouselScrollbarChangeLog.txt; sourceTree = "<group>"; }; 1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CarouselScrollbarChangeLog.txt; sourceTree = "<group>"; };
1832AC562BA0791D008AE476 /* BreadcrumbCellItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbCellItem.swift; sourceTree = "<group>"; }; 1832AC562BA0791D008AE476 /* BreadcrumbCellItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbCellItem.swift; sourceTree = "<group>"; };
183B16F22C78CF7C00BA6A10 /* CarouselSlotCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselSlotCell.swift; sourceTree = "<group>"; };
184023442C61E7AD00A412C8 /* PriceLockup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriceLockup.swift; sourceTree = "<group>"; }; 184023442C61E7AD00A412C8 /* PriceLockup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriceLockup.swift; sourceTree = "<group>"; };
184023462C61E7EC00A412C8 /* PriceLockupChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = PriceLockupChangeLog.txt; sourceTree = "<group>"; }; 184023462C61E7EC00A412C8 /* PriceLockupChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = PriceLockupChangeLog.txt; sourceTree = "<group>"; };
1842B1DE2BECE28B0021AFCA /* CalendarDateViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarDateViewCell.swift; sourceTree = "<group>"; }; 1842B1DE2BECE28B0021AFCA /* CalendarDateViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarDateViewCell.swift; sourceTree = "<group>"; };
@ -524,6 +526,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
18AE874F2C06FDA60075F181 /* Carousel.swift */, 18AE874F2C06FDA60075F181 /* Carousel.swift */,
183B16F22C78CF7C00BA6A10 /* CarouselSlotCell.swift */,
18B9763E2C11BA4A009271DF /* CarouselPaginationModel.swift */, 18B9763E2C11BA4A009271DF /* CarouselPaginationModel.swift */,
18B42AC52C09D197008D6262 /* CarouselSlotAlignmentModel.swift */, 18B42AC52C09D197008D6262 /* CarouselSlotAlignmentModel.swift */,
18AE87532C06FE610075F181 /* CarouselChangeLog.txt */, 18AE87532C06FE610075F181 /* CarouselChangeLog.txt */,
@ -1400,6 +1403,7 @@
EA985BF02968A93600F2FF2E /* TitleLockupEyebrowModel.swift in Sources */, EA985BF02968A93600F2FF2E /* TitleLockupEyebrowModel.swift in Sources */,
EA5E30532950DDA60082B959 /* TitleLockup.swift in Sources */, EA5E30532950DDA60082B959 /* TitleLockup.swift in Sources */,
EAD062B02A3B873E0015965D /* BadgeIndicator.swift in Sources */, EAD062B02A3B873E0015965D /* BadgeIndicator.swift in Sources */,
183B16F32C78CF7C00BA6A10 /* CarouselSlotCell.swift in Sources */,
44A952DD2BE3DA820009F874 /* TableFlowLayout.swift in Sources */, 44A952DD2BE3DA820009F874 /* TableFlowLayout.swift in Sources */,
EAA5EEB528ECBFB4003B3210 /* ImageLabelAttribute.swift in Sources */, EAA5EEB528ECBFB4003B3210 /* ImageLabelAttribute.swift in Sources */,
18792A902B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift in Sources */, 18792A902B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift in Sources */,

View File

@ -8,8 +8,7 @@
import Foundation import Foundation
extension Breadcrumbs { extension Breadcrumbs {
public struct BreadcrumbItemModel { public struct BreadcrumbItemModel: Equatable {
///Text that goes in the breadcrumb item ///Text that goes in the breadcrumb item
public var text: String public var text: String
@ -24,5 +23,10 @@ extension Breadcrumbs {
self.selected = selected self.selected = selected
self.onClick = onClick self.onClick = onClick
} }
public static func == (lhs: Breadcrumbs.BreadcrumbItemModel, rhs: Breadcrumbs.BreadcrumbItemModel) -> Bool {
lhs.text == rhs.text
&& lhs.selected == rhs.selected
}
} }
} }

View File

@ -9,7 +9,7 @@ import Foundation
/// Custom data type for indicators prop /// Custom data type for indicators prop
extension CalendarBase { extension CalendarBase {
public struct CalendarIndicatorModel { public struct CalendarIndicatorModel: Equatable {
/// Text that shown to an indicator for legend /// Text that shown to an indicator for legend
public var label: String public var label: String

View File

@ -154,27 +154,38 @@ open class Carousel: View {
$0.backgroundColor = .clear $0.backgroundColor = .clear
} }
private var scrollView = UIScrollView().with { private lazy var collectionView: UICollectionView = {
$0.translatesAutoresizingMaskIntoConstraints = false let layout = UICollectionViewFlowLayout()
$0.backgroundColor = .clear layout.scrollDirection = .horizontal
} let collectionView = UICollectionView(frame: frame, collectionViewLayout: layout)
collectionView.isScrollEnabled = true
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.delegate = self
collectionView.dataSource = self
collectionView.showsHorizontalScrollIndicator = false
collectionView.showsVerticalScrollIndicator = false
collectionView.backgroundColor = .clear
collectionView.register(CarouselSlotCell.self,
forCellWithReuseIdentifier: CarouselSlotCell.identifier)
return collectionView
}()
/// Previous button to show previous slide. /// Previous button to show previous slide.
private var previousButton = ButtonIcon().with { private var previousButton = ButtonIcon().with {
$0.kind = .lowContrast $0.kind = .lowContrast
$0.iconName = .leftCaret $0.iconName = .paginationLeftCaret
$0.iconOffset = .init(x: -2, y: 0) $0.iconOffset = .init(x: -2, y: 0)
$0.customContainerSize = UIDevice.isIPad ? 40 : 28 $0.customContainerSize = UIDevice.isIPad ? 40 : 28
$0.icon.customSize = UIDevice.isIPad ? 16 : 12 $0.customIconSize = UIDevice.isIPad ? 16 : 12
} }
/// Next button to show next slide. /// Next button to show next slide.
private var nextButton = ButtonIcon().with { private var nextButton = ButtonIcon().with {
$0.kind = .lowContrast $0.kind = .lowContrast
$0.iconName = .rightCaret $0.iconName = .paginationRightCaret
$0.iconOffset = .init(x: 2, y: 0) $0.iconOffset = .init(x: 2, y: 0)
$0.customContainerSize = UIDevice.isIPad ? 40 : 28 $0.customContainerSize = UIDevice.isIPad ? 40 : 28
$0.icon.customSize = UIDevice.isIPad ? 16 : 12 $0.customIconSize = UIDevice.isIPad ? 16 : 12
} }
/// A publisher for when moving the carousel. Passes parameters selectedGroupIndex (position). /// A publisher for when moving the carousel. Passes parameters selectedGroupIndex (position).
@ -215,8 +226,8 @@ open class Carousel: View {
containerView.addSubview(contentStackView) containerView.addSubview(contentStackView)
// Add scrollview // Add scrollview
scrollContainerView.addSubview(scrollView) scrollContainerView.addSubview(collectionView)
scrollView.pinToSuperView() collectionView.pinToSuperView()
// Add pagination button icons // Add pagination button icons
scrollContainerView.addSubview(previousButton) scrollContainerView.addSubview(previousButton)
@ -259,14 +270,24 @@ open class Carousel: View {
/// Used to make changes to the View based off a change events or from local properties. /// Used to make changes to the View based off a change events or from local properties.
open override func updateView() { open override func updateView() {
super.updateView() super.updateView()
updateScrollbar()
updateCarousel()
collectionView.reloadData()
}
//--------------------------------------------------
// MARK: - Private Methods
//--------------------------------------------------
private func updateScrollbar() {
carouselScrollBar.numberOfSlides = views.count carouselScrollBar.numberOfSlides = views.count
carouselScrollBar.layout = layout carouselScrollBar.layout = layout
if (carouselScrollBar.position == 0 || carouselScrollBar.position > carouselScrollBar.numberOfSlides) { if (carouselScrollBar.position == 0 || carouselScrollBar.position > carouselScrollBar.numberOfSlides) {
carouselScrollBar.position = 1 carouselScrollBar.position = 1
} }
carouselScrollBar.isHidden = (totalPositions() <= 1) ? true : false carouselScrollBar.isHidden = (totalPositions() <= 1) ? true : false
}
private func updateCarousel() {
// Mobile/Tablet layouts without peek - must show pagination controls. // Mobile/Tablet layouts without peek - must show pagination controls.
// If peek is none, pagination controls should show. So set to persistent. // If peek is none, pagination controls should show. So set to persistent.
if peek == .none { if peek == .none {
@ -284,12 +305,9 @@ open class Carousel: View {
} }
updatePaginationControls() updatePaginationControls()
addCarouselSlots() updateContainerHeight()
} }
//--------------------------------------------------
// MARK: - Private Methods
//--------------------------------------------------
private func addlisteners() { private func addlisteners() {
nextButton.onClick = { _ in self.nextButtonClick() } nextButton.onClick = { _ in self.nextButtonClick() }
previousButton.onClick = { _ in self.previousButtonClick() } previousButton.onClick = { _ in self.previousButtonClick() }
@ -365,47 +383,13 @@ open class Carousel: View {
return height return height
} }
// Add carousel slots and load data if any // update carousel size and load data if any
private func addCarouselSlots() { private func updateContainerHeight() {
getSlotWidth() getSlotWidth()
if containerView.frame.size.width > 0 { if containerView.frame.size.width > 0 {
containerViewHeightConstraint?.isActive = false containerViewHeightConstraint?.isActive = false
containerStackHeightConstraint?.isActive = false containerStackHeightConstraint?.isActive = false
let slotHeight = fetchCarouselHeight() let slotHeight = fetchCarouselHeight()
// Perform a loop to iterate each subView
scrollView.subviews.forEach { subView in
// Removing subView from its parent view
subView.removeFromSuperview()
}
// Add carousel items
if views.count > 0 {
var xPos = 0.0
for index in 0...views.count - 1 {
// Add Carousel Slot
let carouselSlot = View().with {
$0.clipsToBounds = true
}
scrollView.addSubview(carouselSlot)
scrollView.delegate = self
carouselSlot
.pinTop()
.pinBottom()
.pinLeading(xPos)
.width(minimumSlotWidth)
.height(slotHeight)
xPos = xPos + minimumSlotWidth + gutter.value
let component = views[index]
carouselSlot.addSubview(component)
setSlotAlignment(contentView: component)
}
scrollView.contentSize = CGSize(width: xPos - gutter.value, height: slotHeight)
}
let containerHeight = slotHeight + scrollbarTopSpace + containerSize.height let containerHeight = slotHeight + scrollbarTopSpace + containerSize.height
if carouselScrollBar.isHidden { if carouselScrollBar.isHidden {
containerStackHeightConstraint = contentStackView.heightAnchor.constraint(equalToConstant: slotHeight) containerStackHeightConstraint = contentStackView.heightAnchor.constraint(equalToConstant: slotHeight)
@ -419,43 +403,6 @@ open class Carousel: View {
} }
} }
// Set slot alignment if provided. Used only when slot content have different heights or widths.
private func setSlotAlignment(contentView: UIView) {
switch slotAlignment?.vertical {
case .top:
contentView
.pinTop()
.pinBottomLessThanOrEqualTo()
case .middle:
contentView
.pinTopGreaterThanOrEqualTo()
.pinBottomLessThanOrEqualTo()
.pinCenterY()
case .bottom:
contentView
.pinTopGreaterThanOrEqualTo()
.pinBottom()
default: break
}
switch slotAlignment?.horizontal {
case .left:
contentView
.pinLeading()
.pinTrailingLessThanOrEqualTo()
case .center:
contentView
.pinLeadingGreaterThanOrEqualTo()
.pinTrailingLessThanOrEqualTo()
.pinCenterX()
case .right:
contentView
.pinLeadingGreaterThanOrEqualTo()
.pinTrailing()
default: break
}
}
// Get the slot width relative to the peak // Get the slot width relative to the peak
private func getSlotWidth() { private func getSlotWidth() {
let actualWidth = containerView.frame.size.width let actualWidth = containerView.frame.size.width
@ -505,7 +452,7 @@ open class Carousel: View {
} }
private func updateScrollbarPosition(targetContentOffsetXPos:CGFloat) { private func updateScrollbarPosition(targetContentOffsetXPos:CGFloat) {
let scrollContentSizeWidth = scrollView.contentSize.width let scrollContentSizeWidth = collectionView.contentSize.width
let totalPositions = totalPositions() let totalPositions = totalPositions()
let layoutSpace = Int (floor( Double(scrollContentSizeWidth / Double(totalPositions)))) let layoutSpace = Int (floor( Double(scrollContentSizeWidth / Double(totalPositions))))
let remindSpace = Int(targetContentOffsetXPos) % layoutSpace let remindSpace = Int(targetContentOffsetXPos) % layoutSpace
@ -515,10 +462,11 @@ open class Carousel: View {
updateScrollPosition(position: contentPos, callbackText: "ScrollViewMoved") updateScrollPosition(position: contentPos, callbackText: "ScrollViewMoved")
} }
// Update scrollview offset relative to scrollbar thumb position // Update collectionview offset relative to scrollbar thumb position
private func updateScrollPosition(position: Int, callbackText: String) { private func updateScrollPosition(position: Int, callbackText: String) {
if carouselScrollBar.numberOfSlides > 0 { if carouselScrollBar.numberOfSlides > 0 {
let scrollContentSizeWidth = scrollView.contentSize.width let scrollContentSizeWidth = collectionView.contentSize.width
let totalPositions = totalPositions() let totalPositions = totalPositions()
var xPos = 0.0 var xPos = 0.0
if position == 1 { if position == 1 {
@ -536,8 +484,8 @@ open class Carousel: View {
} }
} }
carouselScrollBar.scrubberId = position+1 carouselScrollBar.scrubberId = position+1
let yPos = scrollView.contentOffset.y let yPos = collectionView.contentOffset.y
scrollView.setContentOffset(CGPoint(x: xPos, y: yPos), animated: true) collectionView.setContentOffset(CGPoint(x: xPos, y: yPos), animated: true)
showPaginationControls() showPaginationControls()
groupIndex = position-1 groupIndex = position-1
onChangePublisher.send(groupIndex) onChangePublisher.send(groupIndex)
@ -557,5 +505,30 @@ extension Carousel: UIScrollViewDelegate {
public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
updateScrollbarPosition(targetContentOffsetXPos: targetContentOffset.pointee.x) updateScrollbarPosition(targetContentOffsetXPos: targetContentOffset.pointee.x)
} }
}
extension Carousel: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
//--------------------------------------------------
// MARK: - UICollectionView Delegate & Datasource
//--------------------------------------------------
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
views.count
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CarouselSlotCell.identifier, for: indexPath) as? CarouselSlotCell else { return UICollectionViewCell() }
cell.contentView.subviews.forEach { $0.removeFromSuperview() }
let component = views[indexPath.row]
cell.update(with: component, slotAlignment: slotAlignment, surface: surface)
cell.layoutIfNeeded()
return cell
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return gutter.value
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: minimumSlotWidth, height: fetchCarouselHeight())
}
} }

View File

@ -10,7 +10,7 @@ import UIKit
/// Custom data type for pagination prop for 'Carousel' component. /// Custom data type for pagination prop for 'Carousel' component.
extension Carousel { extension Carousel {
public struct CarouselPaginationModel { public struct CarouselPaginationModel: Equatable {
/// Pagination supports Button icon property 'kind'. /// Pagination supports Button icon property 'kind'.
public var kind: ButtonIcon.Kind public var kind: ButtonIcon.Kind

View File

@ -11,7 +11,7 @@ import Foundation
extension Carousel { extension Carousel {
/// Used only when slot content have different heights or widths. /// Used only when slot content have different heights or widths.
public struct CarouselSlotAlignmentModel { public struct CarouselSlotAlignmentModel: Equatable {
/// Used for vertical alignment of slot alignment. /// Used for vertical alignment of slot alignment.
public var vertical: Carousel.Vertical public var vertical: Carousel.Vertical

View File

@ -0,0 +1,90 @@
//
// CarouselSlotCell.swift
// VDS
//
// Created by Kanamarlapudi, Vasavi on 23/08/24.
//
import Foundation
import UIKit
final class CarouselSlotCell: UICollectionViewCell {
///Identifier for the Calendar Date Cell.
static let identifier: String = String(describing: CarouselSlotCell.self)
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
override init(frame: CGRect) {
super.init(frame: frame)
setUp()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setUp()
}
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
private var surface: Surface = .light
//--------------------------------------------------
// MARK: - Private Methods
//--------------------------------------------------
/// Configuring the cell with default setup.
private func setUp() {
isAccessibilityElement = true
}
/// Updating UI based on data along with surface.
func update(with component: UIView, slotAlignment: Carousel.CarouselSlotAlignmentModel?, surface: Surface) {
self.surface = surface
contentView.addSubview(component)
if var surfacedView = component as? Surfaceable {
surfacedView.surface = surface
}
setSlotAlignment(alignment: slotAlignment, contentView: component)
}
// Set slot alignment if provided. Used only when slot content have different heights or widths.
private func setSlotAlignment(alignment: Carousel.CarouselSlotAlignmentModel?, contentView: UIView) {
switch alignment?.vertical {
case .top:
contentView
.pinTop()
.pinBottomLessThanOrEqualTo()
case .middle:
contentView
.pinTopGreaterThanOrEqualTo()
.pinBottomLessThanOrEqualTo()
.pinCenterY()
case .bottom:
contentView
.pinTopGreaterThanOrEqualTo()
.pinBottom()
default: break
}
switch alignment?.horizontal {
case .left:
contentView
.pinLeading()
.pinTrailingLessThanOrEqualTo()
case .center:
contentView
.pinLeadingGreaterThanOrEqualTo()
.pinTrailingLessThanOrEqualTo()
.pinCenterX()
case .right:
contentView
.pinLeadingGreaterThanOrEqualTo()
.pinTrailing()
default: break
}
}
}

View File

@ -108,7 +108,7 @@ open class CheckboxGroup: SelectorGroupBase<CheckboxItem>, SelectorGroupMultiSel
} }
extension CheckboxGroup { extension CheckboxGroup {
public struct CheckboxItemModel : Surfaceable, Initable, Errorable { public struct CheckboxItemModel : Surfaceable, Initable, Errorable, Equatable {
/// Whether this object is enabled or not /// Whether this object is enabled or not
public var enabled: Bool public var enabled: Bool
@ -146,6 +146,21 @@ extension CheckboxGroup {
public init() { public init() {
self.init(enabled: true) self.init(enabled: true)
} }
public static func == (lhs: CheckboxGroup.CheckboxItemModel, rhs: CheckboxGroup.CheckboxItemModel) -> Bool {
lhs.enabled == rhs.enabled
&& lhs.surface == rhs.surface
&& lhs.inputId == rhs.inputId
&& lhs.value == rhs.value
&& lhs.accessibileText == rhs.accessibileText
&& lhs.labelText == rhs.labelText
&& lhs.labelTextAttributes == rhs.labelTextAttributes
&& lhs.childText == rhs.childText
&& lhs.childTextAttributes == rhs.childTextAttributes
&& lhs.selected == rhs.selected
&& lhs.showError == rhs.showError
&& lhs.errorText == rhs.errorText
}
} }
} }

View File

@ -9,7 +9,7 @@ import Foundation
import UIKit import UIKit
extension DatePicker { extension DatePicker {
public struct CalendarModel { public struct CalendarModel: Equatable {
/// If set to true, the calendar will not have a border. /// If set to true, the calendar will not have a border.
public let hideContainerBorder: Bool public let hideContainerBorder: Bool

View File

@ -8,7 +8,7 @@
import Foundation import Foundation
extension DropdownSelect { extension DropdownSelect {
public struct DropdownOptionModel { public struct DropdownOptionModel: Equatable {
/// Text that goes as option to DropdownSelect /// Text that goes as option to DropdownSelect
public var text: String public var text: String

View File

@ -10,7 +10,7 @@ import Foundation
extension ButtonIcon { extension ButtonIcon {
//Model that represents the options available for the Badge Indicator //Model that represents the options available for the Badge Indicator
public struct BadgeIndicatorModel { public struct BadgeIndicatorModel: Equatable {
/// Enum used to describe the badge indicator direction of icon button determining the expand direction. /// Enum used to describe the badge indicator direction of icon button determining the expand direction.
public enum ExpandDirection: String, CaseIterable { public enum ExpandDirection: String, CaseIterable {
case right, center, left case right, center, left

View File

@ -24,7 +24,7 @@ extension Icon {
/// let icon = Icon() /// let icon = Icon()
/// icon.name = .foo /// icon.name = .foo
/// ``` /// ```
public struct Name: RawRepresentable { public struct Name: RawRepresentable, Equatable {
public typealias RawValue = String public typealias RawValue = String
public var rawValue: String public var rawValue: String

View File

@ -8,12 +8,16 @@
import Foundation import Foundation
extension Notification { extension Notification {
public struct ButtonModel { public struct ButtonModel: Equatable {
public var text: String public var text: String
public var onClick: (Button) -> () public var onClick: (Button) -> ()
public init(text: String, onClick: @escaping (Button) -> Void) { public init(text: String, onClick: @escaping (Button) -> Void) {
self.text = text self.text = text
self.onClick = onClick self.onClick = onClick
} }
public static func == (lhs: Notification.ButtonModel, rhs: Notification.ButtonModel) -> Bool {
lhs.text == rhs.text
}
} }
} }

View File

@ -113,7 +113,7 @@ open class RadioBoxGroup: SelectorGroupBase<RadioBoxItem>, SelectorGroupSingleSe
} }
extension RadioBoxGroup { extension RadioBoxGroup {
public struct RadioBoxItemModel: Surfaceable, Initable, FormFieldable { public struct RadioBoxItemModel: Surfaceable, Initable, FormFieldable, Equatable {
/// Whether this object is enabled or not /// Whether this object is enabled or not
public var enabled: Bool public var enabled: Bool
/// Current Surface and this is used to pass down to child objects that implement Surfacable /// Current Surface and this is used to pass down to child objects that implement Surfacable
@ -158,5 +158,22 @@ extension RadioBoxGroup {
public init() { public init() {
self.init(enabled: true) self.init(enabled: true)
} }
public static func == (lhs: RadioBoxGroup.RadioBoxItemModel, rhs: RadioBoxGroup.RadioBoxItemModel) -> Bool {
lhs.enabled == rhs.enabled
&& lhs.surface == rhs.surface
&& lhs.inputId == rhs.inputId
&& lhs.value == rhs.value
&& lhs.accessibileText == rhs.accessibileText
&& lhs.text == rhs.text
&& lhs.textAttributes == rhs.textAttributes
&& lhs.subText == rhs.subText
&& lhs.subTextAttributes == rhs.subTextAttributes
&& lhs.subTextRight == rhs.subTextRight
&& lhs.subTextRightAttributes == rhs.subTextRightAttributes
&& lhs.selected == rhs.selected
&& lhs.strikethrough == rhs.strikethrough
&& lhs.strikethroughAccessibileText == rhs.strikethroughAccessibileText
}
} }
} }

View File

@ -103,7 +103,7 @@ open class RadioButtonGroup: SelectorGroupBase<RadioButtonItem>, SelectorGroupSi
} }
extension RadioButtonGroup { extension RadioButtonGroup {
public struct RadioButtonItemModel: Surfaceable, Initable, FormFieldable, Errorable { public struct RadioButtonItemModel: Surfaceable, Initable, FormFieldable, Errorable, Equatable {
/// Whether this object is enabled or not /// Whether this object is enabled or not
public var enabled: Bool public var enabled: Bool
@ -141,5 +141,20 @@ extension RadioButtonGroup {
public init() { public init() {
self.init(enabled: true) self.init(enabled: true)
} }
public static func == (lhs: RadioButtonGroup.RadioButtonItemModel, rhs: RadioButtonGroup.RadioButtonItemModel) -> Bool {
lhs.enabled == rhs.enabled
&& lhs.surface == rhs.surface
&& lhs.inputId == rhs.inputId
&& lhs.value == rhs.value
&& lhs.accessibileText == rhs.accessibileText
&& lhs.labelText == rhs.labelText
&& lhs.labelTextAttributes == rhs.labelTextAttributes
&& lhs.childText == rhs.childText
&& lhs.childTextAttributes == rhs.childTextAttributes
&& lhs.selected == rhs.selected
&& lhs.showError == rhs.showError
&& lhs.errorText == rhs.errorText
}
} }
} }

View File

@ -10,7 +10,7 @@ import UIKit
import VDSCoreTokens 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: Equatable {
public let defaultHeight: CGFloat = 50.0 public let defaultHeight: CGFloat = 50.0

View File

@ -7,7 +7,7 @@
import Foundation import Foundation
public struct TableRowModel { public struct TableRowModel: Equatable {
public var columns: [TableItemModel] public var columns: [TableItemModel]

View File

@ -8,7 +8,7 @@
import Foundation import Foundation
extension Tabs { extension Tabs {
public struct TabModel { public struct TabModel: Equatable {
///Text that goes in the Tab ///Text that goes in the Tab
public var text: String public var text: String
@ -24,5 +24,10 @@ extension Tabs {
self.onClick = onClick self.onClick = onClick
self.width = width self.width = width
} }
public static func == (lhs: Tabs.TabModel, rhs: Tabs.TabModel) -> Bool {
lhs.text == rhs.text
&& lhs.width == rhs.width
}
} }
} }

View File

@ -82,10 +82,25 @@ open class TileContainerBase<PaddingType: DefaultValuing & Valuing>: View where
} }
/// Enum used to describe the background effect choices used for this component. /// Enum used to describe the background effect choices used for this component.
public enum BackgroundEffect { public enum BackgroundEffect: Equatable {
case transparency case transparency
case gradient(UIColor, UIColor) case gradient(UIColor, UIColor)
case none case none
public static func == (lhs: TileContainerBase.BackgroundEffect, rhs: TileContainerBase.BackgroundEffect) -> Bool {
lhs.description == lhs.description
}
public var description: String {
switch self {
case .transparency:
"transparency"
case .gradient(let first, let second):
"gradient(\(first), \(second)"
case .none:
"none"
}
}
} }
/// Enum used to describe the aspect ratios used for this component. /// Enum used to describe the aspect ratios used for this component.

View File

@ -11,7 +11,7 @@ import UIKit
extension Tilelet { extension Tilelet {
/// Model that represents the options available for the badge. /// Model that represents the options available for the badge.
public struct BadgeModel { public struct BadgeModel: Equatable {
/// Text that will be used for the badge. /// Text that will be used for the badge.
public var text: String = "" public var text: String = ""

View File

@ -32,7 +32,7 @@ extension Tilelet {
} }
/// Model that represents the options available for the descriptive icon. /// Model that represents the options available for the descriptive icon.
public struct DescriptiveIcon { public struct DescriptiveIcon: Equatable {
/// A representation that will be used to render the icon with corresponding name. /// A representation that will be used to render the icon with corresponding name.
public var name: Icon.Name public var name: Icon.Name
@ -58,7 +58,7 @@ extension Tilelet {
} }
/// Model that represents the options available for the directional icon. /// Model that represents the options available for the directional icon.
public struct DirectionalIcon { public struct DirectionalIcon: Equatable {
public enum IconType: String, CaseIterable { public enum IconType: String, CaseIterable {
case rightArrow case rightArrow
case externalLink case externalLink

View File

@ -10,7 +10,7 @@ import UIKit
extension Tilelet { extension Tilelet {
/// Model that represents the options available for the sub title label. /// Model that represents the options available for the sub title label.
public struct SubTitleModel { public struct SubTitleModel: Equatable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Enums // MARK: - Enums
//-------------------------------------------------- //--------------------------------------------------
@ -67,5 +67,13 @@ extension Tilelet {
textAttributes: textAttributes, textAttributes: textAttributes,
lineBreakMode: lineBreakMode) lineBreakMode: lineBreakMode)
} }
public static func == (lhs: Tilelet.SubTitleModel, rhs: Tilelet.SubTitleModel) -> Bool {
lhs.text == rhs.text
&& lhs.textColor == rhs.textColor
&& lhs.otherStandardStyle == rhs.otherStandardStyle
&& lhs.textAttributes == rhs.textAttributes
&& lhs.lineBreakMode == rhs.lineBreakMode
}
} }
} }

View File

@ -10,7 +10,7 @@ import UIKit
extension Tilelet { extension Tilelet {
/// Model that represents the options available for the title label. /// Model that represents the options available for the title label.
public struct TitleModel { public struct TitleModel: Equatable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Enums // MARK: - Enums
//-------------------------------------------------- //--------------------------------------------------
@ -75,5 +75,14 @@ extension Tilelet {
standardStyle: standardStyle.value, standardStyle: standardStyle.value,
lineBreakMode: lineBreakMode) lineBreakMode: lineBreakMode)
} }
public static func == (lhs: Tilelet.TitleModel, rhs: Tilelet.TitleModel) -> Bool {
lhs.text == rhs.text
&& lhs.textColor == rhs.textColor
&& lhs.isBold == rhs.isBold
&& lhs.textAttributes == rhs.textAttributes
&& lhs.standardStyle == rhs.standardStyle
&& lhs.lineBreakMode == rhs.lineBreakMode
}
} }
} }

View File

@ -11,7 +11,7 @@ import UIKit
extension Tilelet { extension Tilelet {
/// Model that represents the options available for the eyebrow label. /// Model that represents the options available for the eyebrow label.
public struct EyebrowModel { public struct EyebrowModel: Equatable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Public Properties // MARK: - Public Properties
//-------------------------------------------------- //--------------------------------------------------
@ -60,5 +60,14 @@ extension Tilelet {
standardStyle: standardStyle.value, standardStyle: standardStyle.value,
textAttributes: textAttributes) textAttributes: textAttributes)
} }
public static func == (lhs: Tilelet.EyebrowModel, rhs: Tilelet.EyebrowModel) -> Bool {
lhs.text == rhs.text
&& lhs.textColor == rhs.textColor
&& lhs.isBold == rhs.isBold
&& lhs.textAttributes == rhs.textAttributes
&& lhs.standardStyle == rhs.standardStyle
&& lhs.lineBreakMode == rhs.lineBreakMode
}
} }
} }

View File

@ -9,7 +9,7 @@ import Foundation
extension TitleLockup { extension TitleLockup {
/// Model that represents the options available for the eyebrow label. /// Model that represents the options available for the eyebrow label.
public struct EyebrowModel { public struct EyebrowModel: Equatable {
/// Text that will be used for the eyebrow label. /// Text that will be used for the eyebrow label.
public var text: String public var text: String
@ -44,6 +44,15 @@ extension TitleLockup {
/// Text style that will be used for the eyebrow label. /// Text style that will be used for the eyebrow label.
public var textStyle: TextStyle { isBold ? standardStyle.value.bold : standardStyle.value.regular } public var textStyle: TextStyle { isBold ? standardStyle.value.bold : standardStyle.value.regular }
public static func == (lhs: TitleLockup.EyebrowModel, rhs: TitleLockup.EyebrowModel) -> Bool {
lhs.text == rhs.text
&& lhs.textColor == rhs.textColor
&& lhs.isBold == rhs.isBold
&& lhs.standardStyle == rhs.standardStyle
&& lhs.textAttributes == rhs.textAttributes
&& lhs.numberOfLines == rhs.numberOfLines
}
} }
} }

View File

@ -46,6 +46,14 @@ extension TitleLockup {
/// TextStyle used to render the text. /// TextStyle used to render the text.
public var textStyle: TextStyle { otherStandardStyle.value.regular } public var textStyle: TextStyle { otherStandardStyle.value.regular }
public static func == (lhs: TitleLockup.SubTitleModel, rhs: TitleLockup.SubTitleModel) -> Bool {
lhs.text == rhs.text
&& lhs.textColor == rhs.textColor
&& lhs.otherStandardStyle == rhs.otherStandardStyle
&& lhs.textAttributes == rhs.textAttributes
&& lhs.lineBreakMode == rhs.lineBreakMode
&& lhs.numberOfLines == rhs.numberOfLines
}
} }
} }

View File

@ -10,7 +10,7 @@ import UIKit
extension TitleLockup { extension TitleLockup {
/// Model that represents the options available for the sub title label. /// Model that represents the options available for the sub title label.
public struct TitleModel { public struct TitleModel: Equatable {
/// Text that will be used for the title label. /// Text that will be used for the title label.
public var text: String public var text: String
@ -51,5 +51,14 @@ extension TitleLockup {
/// TextStyle used to render the text. /// TextStyle used to render the text.
public var textStyle: TextStyle { isBold ? standardStyle.value.bold : standardStyle.value.regular } public var textStyle: TextStyle { isBold ? standardStyle.value.bold : standardStyle.value.regular }
public static func == (lhs: TitleLockup.TitleModel, rhs: TitleLockup.TitleModel) -> Bool {
lhs.text == rhs.text
&& lhs.textColor == rhs.textColor
&& lhs.isBold == rhs.isBold
&& lhs.standardStyle == rhs.standardStyle
&& lhs.textAttributes == rhs.textAttributes
&& lhs.numberOfLines == rhs.numberOfLines
&& lhs.lineBreakMode == rhs.lineBreakMode
}
} }
} }

View File

@ -11,7 +11,7 @@ import UIKit
extension Tooltip { extension Tooltip {
/// Model used to represent the tooltip. /// Model used to represent the tooltip.
public struct TooltipModel { public struct TooltipModel: Equatable {
/// Current Surface and this is used to pass down to child objects that implement Surfacable /// Current Surface and this is used to pass down to child objects that implement Surfacable
public var closeButtonText: String public var closeButtonText: String
public var title: String? public var title: String?

View File

@ -3,6 +3,7 @@
- CXTDT-597984 - Table - Text wrap - CXTDT-597984 - Table - Text wrap
- CXTDT-586372 - Table - Stripes defect - CXTDT-586372 - Table - Stripes defect
- CXTDT-586383 - Table - Line style - CXTDT-586383 - Table - Line style
- CXTDT-603719 - Carousel - Pagination caret icon
1.0.72 1.0.72
---------------- ----------------