Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/vds_ios into vasavk/modal

This commit is contained in:
Vasavi Kanamarlapudi 2024-09-20 12:46:28 +05:30
commit f868389cb8
6 changed files with 467 additions and 4 deletions

View File

@ -12,6 +12,7 @@
1808BEBC2BA41C3200129230 /* CarouselScrollbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */; };
1832AC572BA0791D008AE476 /* BreadcrumbCellItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1832AC562BA0791D008AE476 /* BreadcrumbCellItem.swift */; };
183B16F32C78CF7C00BA6A10 /* CarouselSlotCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 183B16F22C78CF7C00BA6A10 /* CarouselSlotCell.swift */; };
183B16F72C80B32200BA6A10 /* FootnoteGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 183B16F62C80B32200BA6A10 /* FootnoteGroup.swift */; };
184023452C61E7AD00A412C8 /* PriceLockup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 184023442C61E7AD00A412C8 /* PriceLockup.swift */; };
184023472C61E7EC00A412C8 /* PriceLockupChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 184023462C61E7EC00A412C8 /* PriceLockupChangeLog.txt */; };
1842B1DF2BECE28B0021AFCA /* CalendarDateViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1842B1DE2BECE28B0021AFCA /* CalendarDateViewCell.swift */; };
@ -20,6 +21,8 @@
1855EC662BAABF2A002ACAC2 /* BreadcrumbItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1855EC652BAABF2A002ACAC2 /* BreadcrumbItemModel.swift */; };
186D13CB2BBA8B1500986B53 /* DropdownSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 186D13CA2BBA8B1500986B53 /* DropdownSelect.swift */; };
18792A902B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */; };
18926F5B2C7616A500C55BF6 /* FootnoteItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18926F5A2C7616A500C55BF6 /* FootnoteItem.swift */; };
18926F5D2C7616C600C55BF6 /* FootnoteChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 18926F5C2C7616C600C55BF6 /* FootnoteChangeLog.txt */; };
18A3F12A2BD9298900498E4A /* Calendar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A3F1292BD9298900498E4A /* Calendar.swift */; };
18A65A022B96E848006602CC /* Breadcrumbs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A65A012B96E848006602CC /* Breadcrumbs.swift */; };
18A65A042B96F050006602CC /* BreadcrumbItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A65A032B96F050006602CC /* BreadcrumbItem.swift */; };
@ -218,6 +221,7 @@
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>"; };
183B16F22C78CF7C00BA6A10 /* CarouselSlotCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselSlotCell.swift; sourceTree = "<group>"; };
183B16F62C80B32200BA6A10 /* FootnoteGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FootnoteGroup.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>"; };
1842B1DE2BECE28B0021AFCA /* CalendarDateViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarDateViewCell.swift; sourceTree = "<group>"; };
@ -229,6 +233,8 @@
186D13CA2BBA8B1500986B53 /* DropdownSelect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropdownSelect.swift; sourceTree = "<group>"; };
186D13CE2BBC36EE00986B53 /* DropdownSelectChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = DropdownSelectChangeLog.txt; sourceTree = "<group>"; };
18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIconBadgeIndicatorModel.swift; sourceTree = "<group>"; };
18926F5A2C7616A500C55BF6 /* FootnoteItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FootnoteItem.swift; sourceTree = "<group>"; };
18926F5C2C7616C600C55BF6 /* FootnoteChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = FootnoteChangeLog.txt; sourceTree = "<group>"; };
18A3F1292BD9298900498E4A /* Calendar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Calendar.swift; sourceTree = "<group>"; };
18A65A012B96E848006602CC /* Breadcrumbs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Breadcrumbs.swift; sourceTree = "<group>"; };
18A65A032B96F050006602CC /* BreadcrumbItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbItem.swift; sourceTree = "<group>"; };
@ -496,6 +502,16 @@
path = DropdownSelect;
sourceTree = "<group>";
};
18926F592C76168300C55BF6 /* Footnote */ = {
isa = PBXGroup;
children = (
18926F5A2C7616A500C55BF6 /* FootnoteItem.swift */,
183B16F62C80B32200BA6A10 /* FootnoteGroup.swift */,
18926F5C2C7616C600C55BF6 /* FootnoteChangeLog.txt */,
);
path = Footnote;
sourceTree = "<group>";
};
18A3F1202BD8F5DE00498E4A /* Calendar */ = {
isa = PBXGroup;
children = (
@ -709,6 +725,7 @@
EAF7F092289985E200B287F5 /* Checkbox */,
EAC58C1F2BF127F000BA39FA /* DatePicker */,
186D13C92BBA8A3500986B53 /* DropdownSelect */,
18926F592C76168300C55BF6 /* Footnote */,
EA985BF3296C609E00F2FF2E /* Icon */,
180636C52C29B06200C92D86 /* InputStepper */,
EA3362412892EF700071C351 /* Label */,
@ -1215,6 +1232,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
18926F5D2C7616C600C55BF6 /* FootnoteChangeLog.txt in Resources */,
EA3362042891E14D0071C351 /* VerizonNHGeTX-Bold.otf in Resources */,
184023472C61E7EC00A412C8 /* PriceLockupChangeLog.txt in Resources */,
EA3362072891E14D0071C351 /* VerizonNHGeDS-Regular.otf in Resources */,
@ -1279,6 +1297,7 @@
EA3361C328902D960071C351 /* Toggle.swift in Sources */,
EAF7F0A0289AB7EC00B287F5 /* View.swift in Sources */,
EAC58C232BF2824200BA39FA /* DatePicker.swift in Sources */,
183B16F72C80B32200BA6A10 /* FootnoteGroup.swift in Sources */,
EA89201328B568D8006B9984 /* RadioBoxItem.swift in Sources */,
71FC86E42B9841AC00700965 /* PaginationFlowLayout.swift in Sources */,
EAC9258C2911C9DE00091998 /* InputField.swift in Sources */,
@ -1309,6 +1328,7 @@
18B463A42BBD3C46005C4528 /* DropdownOptionModel.swift in Sources */,
EAF2F4762C231EAA007BFEDC /* AccessibilityActionElement.swift in Sources */,
EAC58BFD2BE935C300BA39FA /* TitleLockupTextColor.swift in Sources */,
18926F5B2C7616A500C55BF6 /* FootnoteItem.swift in Sources */,
EAACB89A2B927108006A3869 /* Valuing.swift in Sources */,
EAE785312BA0A438009428EA /* UIImage+Helper.swift in Sources */,
EAF193422C134F3400C68D18 /* Table.swift in Sources */,

View File

@ -43,13 +43,14 @@ open class SelectorItemBase<Selector: SelectorBase>: Control, Errorable, Changea
private var mainStackView = UIStackView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.alignment = .top
$0.alignment = .fill
$0.axis = .vertical
}
private var selectorStackView = UIStackView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.alignment = .top
$0.alignment = .fill
$0.axis = .horizontal
}
@ -171,10 +172,16 @@ open class SelectorItemBase<Selector: SelectorBase>: Control, Errorable, Changea
isAccessibilityElement = false
addSubview(mainStackView)
mainStackView.isUserInteractionEnabled = false
//wrap the selectorView in a view that won't stretch it
//do this by not pinning the bottom
let selectorViewWrapper = UIView().with { $0.translatesAutoresizingMaskIntoConstraints = false }
selectorViewWrapper.addSubview(selectorView)
selectorView.pinTop().pinLeading().pinTrailing().pinBottomLessThanOrEqualTo()
mainStackView.isUserInteractionEnabled = false
mainStackView.addArrangedSubview(selectorStackView)
mainStackView.addArrangedSubview(errorLabel)
selectorStackView.addArrangedSubview(selectorView)
selectorStackView.addArrangedSubview(selectorViewWrapper)
selectorStackView.addArrangedSubview(selectorLabelStackView)
selectorLabelStackView.addArrangedSubview(label)
selectorLabelStackView.addArrangedSubview(childLabel)

View File

@ -0,0 +1,17 @@
MM/DD/YYYY
----------------
Initial Brand 3.0 handoff
12/18/2023
----------------
- New
12/28/2023
----------------
- hideSymbol updated to showSymbol and default set to True.
- Figma-only properties section added in Footnote Item Configurations section.
01/16/2024
----------------
- hideSymbol reverted to hideSymbol and default set to False.
- Figma-only properties section removed.

View File

@ -0,0 +1,160 @@
//
// FootnoteGroup.swift
// VDS
//
// Created by Kanamarlapudi, Vasavi on 29/08/24.
//
import Foundation
import UIKit
import VDSCoreTokens
/// This must always be paired with one or more ``Footnote`` in a FootnoteGroup.
@objcMembers
@objc(VDSFootnoteGroup)
open class FootnoteGroup: View {
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
required public init() {
super.init(frame: .zero)
}
public override init(frame: CGRect) {
super.init(frame: .zero)
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
}
//--------------------------------------------------
// MARK: - enums
//--------------------------------------------------
/// Enum used to describe the width of a fixed value or percentage of parent's width.
public enum Width {
case percentage(CGFloat)
case value(CGFloat)
}
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
/// Array of ``Footnote`` for the Footnote items.
open var footnoteItems: [FootnoteItem] = [] { didSet { updateFootnoteItems() } }
/// Any percentage or pixel value and cannot exceed container size.
/// If there is a width that is larger than container size, the footnote will resize to container's width.
open var width: Width? {
get { _width }
set {
if let newValue {
switch newValue {
case .percentage(let percentage):
if percentage <= 100.0 {
_width = newValue
}
case .value(let value):
if value > 0 {
_width = newValue
}
}
} else {
_width = nil
}
updateContainerWidth()
}
}
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
private var _width: Width? = nil
private lazy var stackView = UIStackView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.axis = .vertical
$0.distribution = .fill
$0.spacing = VDSLayout.space3X
$0.backgroundColor = .clear
}
//--------------------------------------------------
// MARK: - Configuration Properties
//--------------------------------------------------
internal var maxWidth: CGFloat { horizontalPinnedWidth() ?? (superview?.frame.size.width ?? frame.size.width) }
internal var minWidth: CGFloat { containerSize.width }
internal var containerSize: CGSize { CGSize(width: 55, height: 44) }
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
internal var widthConstraint: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
open override func setup() {
super.setup()
// add footnote item stackview.
addSubview(stackView)
stackView.pinToSuperView()
widthConstraint = widthAnchor.constraint(equalToConstant: 0).deactivate()
}
open override func setDefaults() {
super.setDefaults()
width = nil
footnoteItems = []
}
internal func updateFootnoteItems() {
// symbol containers are as wide as the widest symbol container in the group.
var symbolMaxWidth = 0.0
footnoteItems.forEach { footnote in
let separatorWidth = Label().with {
$0.text = footnote.symbolType
$0.textStyle = footnote.symbolLabel.textStyle
$0.sizeToFit()
}.intrinsicContentSize.width
symbolMaxWidth = max(separatorWidth, symbolMaxWidth)
}
stackView.removeArrangedSubviews()
// add symbol label, text label to stack.
footnoteItems.forEach { footnote in
footnote.symbolWidth = symbolMaxWidth
footnote.surface = surface
stackView.addArrangedSubview(footnote)
}
}
/// Update container width after updating content.
internal func updateContainerWidth() {
var newWidth = 0.0
switch width {
case .percentage(let percentage):
newWidth = max(maxWidth * ((percentage) / 100), minWidth)
case .value(let value):
newWidth = value > maxWidth ? maxWidth : value
case nil: break
}
widthConstraint?.deactivate()
if newWidth > minWidth && newWidth < maxWidth {
widthConstraint?.constant = newWidth
widthConstraint?.activate()
}
}
}

View File

@ -0,0 +1,257 @@
//
// Footnote.swift
// VDS
//
// Created by Kanamarlapudi, Vasavi on 21/08/24.
//
import Foundation
import UIKit
import VDSCoreTokens
/// A footnote is text that provides supporting details, legal copy and links to related content.
/// It exists at the bottom or "foot" of a page or section.
@objcMembers
@objc(VDSFootnoteItem)
open class FootnoteItem: View {
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
required public init() {
super.init(frame: .zero)
}
public override init(frame: CGRect) {
super.init(frame: .zero)
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
}
//--------------------------------------------------
// MARK: - enums
//--------------------------------------------------
/// Enum used to describe the kind of component.
public enum Kind: String, DefaultValuing, CaseIterable {
case primary, secondary
/// The default kind is 'primary'.
public static var defaultValue : Self { .secondary }
/// Color configuation to Symbol and Text relative to kind.
public var colorConfiguration: SurfaceColorConfiguration {
switch self {
case .primary:
return SurfaceColorConfiguration(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark)
case .secondary:
return SurfaceColorConfiguration(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark)
}
}
}
/// Enum that represents the size availble for component.
public enum Size: String, DefaultValuing, CaseIterable {
case micro
case small
case large
public static var defaultValue: Self { .micro }
/// TextStyle relative to Size.
public var textStyle: TextStyle.StandardStyle {
switch self {
case .micro:
return .micro
case .small:
return .bodySmall
case .large:
return .bodyLarge
}
}
}
/// Enum used to describe the width of a fixed value or percentage of parent's width.
public enum Width {
case percentage(CGFloat)
case value(CGFloat)
}
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
/// Color to the component. The default kind is Secondary.
open var kind: Kind = .defaultValue { didSet { setNeedsUpdate() } }
/// Size of the component. The default size is Micro.
open var size: Size = .defaultValue { didSet { setNeedsUpdate() } }
/// If hideSymbol true, the component will show text without symbol.
open var hideSymbol: Bool = false { didSet { setNeedsUpdate() } }
/// symbol type will be shown for the footnote item. The default symbolType is 'asterisk'.
open var symbolType: String = "*" { didSet { setNeedsUpdate() } }
/// Text of the footnote item.
open var text: String? { didSet { setNeedsUpdate() } }
open var tooltipModel: Tooltip.TooltipModel? { didSet { setNeedsUpdate() } }
/// Any percentage or pixel value and cannot exceed container size.
/// If there is a width that is larger than container size, the footnote will resize to container's width.
open var width: Width? {
get { _width }
set {
if let newValue {
switch newValue {
case .percentage(let percentage):
if percentage <= 100.0 {
_width = newValue
}
case .value(let value):
if value > 0 {
_width = newValue
}
}
} else {
_width = nil
}
updateContainerWidth()
}
}
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
private var _width: Width? = nil
/// To set the widest symbol width from the symbol container in the group.
internal var symbolWidth: CGFloat? { didSet { setNeedsUpdate() } }
private lazy var itemStackView = UIStackView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.axis = .horizontal
$0.alignment = .leading
$0.distribution = .fill
$0.spacing = VDSLayout.space1X
$0.backgroundColor = .clear
}
internal var symbolLabel = Label().with {
$0.isAccessibilityElement = true
$0.numberOfLines = 1
$0.sizeToFit()
}
internal var textLabel = Label().with {
$0.isAccessibilityElement = true
$0.lineBreakMode = .byWordWrapping
}
//--------------------------------------------------
// MARK: - Configuration Properties
//--------------------------------------------------
internal var maxWidth: CGFloat { horizontalPinnedWidth() ?? (superview?.frame.size.width ?? frame.size.width) }
internal var minWidth: CGFloat { containerSize.width }
internal var containerSize: CGSize { CGSize(width: 45, height: 44) }
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
internal var symbolWidthConstraint: NSLayoutConstraint?
internal var itemWidthConstraint: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
open override func setup() {
super.setup()
// add footnote item stackview.
addSubview(itemStackView)
itemStackView.pinToSuperView()
// width constraints
itemWidthConstraint = widthAnchor.constraint(equalToConstant: 0).deactivate()
// add symbol label, text label to stack.
itemStackView.addArrangedSubview(symbolLabel)
itemStackView.addArrangedSubview(textLabel)
itemStackView.setCustomSpacing(VDSLayout.space1X, after: symbolLabel)
symbolWidthConstraint = symbolLabel.widthAnchor.constraint(greaterThanOrEqualToConstant: 0)
symbolWidthConstraint?.isActive = true
}
open override func setDefaults() {
super.setDefaults()
hideSymbol = false
text = nil
tooltipModel = nil
width = nil
}
/// Resets to default settings.
open override func reset() {
symbolLabel.reset()
textLabel.reset()
super.reset()
}
/// Used to make changes to the View based off a change events or from local properties.
open override func updateView() {
super.updateView()
// Update symbolLabel
symbolLabel.text = symbolType
symbolLabel.isHidden = hideSymbol
symbolLabel.textColor = kind.colorConfiguration.getColor(self)
symbolLabel.textStyle = size.textStyle.regular
symbolLabel.surface = surface
//Set width to the symbol label
if let symbolWidth, symbolWidth > 0 {
// Set the widest symbol width from the symbol container in the group.
symbolWidthConstraint?.constant = symbolWidth
} else {
symbolWidthConstraint?.constant = symbolLabel.intrinsicContentSize.width
}
// Update textLabel
textLabel.text = text
textLabel.textColor = kind.colorConfiguration.getColor(self)
textLabel.textStyle = size.textStyle.regular
textLabel.surface = surface
// Set the textLabel attributes
if let tooltipModel {
var attributes: [any LabelAttributeModel] = []
attributes.append(TooltipLabelAttribute(surface: surface, model: tooltipModel, presenter: self))
textLabel.attributes = attributes
}
}
/// Update container width after updating content.
internal func updateContainerWidth() {
var newWidth = 0.0
switch width {
case .percentage(let percentage):
newWidth = max(maxWidth * ((percentage) / 100), minWidth)
case .value(let value):
newWidth = value > maxWidth ? maxWidth : value
case nil:
break
}
itemWidthConstraint?.deactivate()
if newWidth > minWidth && newWidth < maxWidth {
itemWidthConstraint?.constant = newWidth
itemWidthConstraint?.activate()
}
}
}

View File

@ -32,6 +32,8 @@ Using the system allows designers and developers to collaborate more easily and
- ``CheckboxItem``
- ``CheckboxGroup``
- ``DropdownSelect``
- ``FootnoteItem``
- ``FootnoteGroup``
- ``Icon``
- ``InputStepper``
- ``InputField``