Digital ACT-191 ONEAPP-10586 story: added footnote group and updating with footnote items
This commit is contained in:
parent
73caedce5f
commit
a0b139b0af
@ -11,6 +11,7 @@
|
||||
180636C92C29B0DF00C92D86 /* InputStepperLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 180636C82C29B0DF00C92D86 /* InputStepperLog.txt */; };
|
||||
1808BEBC2BA41C3200129230 /* CarouselScrollbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */; };
|
||||
1832AC572BA0791D008AE476 /* BreadcrumbCellItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1832AC562BA0791D008AE476 /* BreadcrumbCellItem.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 */; };
|
||||
@ -218,6 +219,7 @@
|
||||
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>"; };
|
||||
1832AC562BA0791D008AE476 /* BreadcrumbCellItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbCellItem.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>"; };
|
||||
@ -502,6 +504,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
18926F5A2C7616A500C55BF6 /* Footnote.swift */,
|
||||
183B16F62C80B32200BA6A10 /* FootnoteGroup.swift */,
|
||||
18926F5C2C7616C600C55BF6 /* FootnoteChangeLog.txt */,
|
||||
);
|
||||
path = Footnote;
|
||||
@ -1291,6 +1294,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 */,
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import VDSCoreTokens
|
||||
import Combine
|
||||
|
||||
/// 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.
|
||||
@ -120,7 +119,7 @@ open class Footnote: View {
|
||||
|
||||
open var tooltipModel: Tooltip.TooltipModel? { didSet { setNeedsUpdate() } }
|
||||
|
||||
/// Any percentage or pixel value and cannot exceed container size..
|
||||
/// 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 }
|
||||
@ -143,6 +142,9 @@ open class Footnote: View {
|
||||
}
|
||||
}
|
||||
|
||||
/// To set the widest symbol width from the symbol container in the group.
|
||||
open var symbolWiderWidth: CGFloat = 0 { didSet { setNeedsUpdate() } }
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Private Properties
|
||||
//--------------------------------------------------
|
||||
@ -167,12 +169,22 @@ open class Footnote: View {
|
||||
$0.isAccessibilityElement = true
|
||||
$0.lineBreakMode = .byWordWrapping
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Configuration Properties
|
||||
//--------------------------------------------------
|
||||
internal var maxWidth: CGFloat { 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?
|
||||
internal var trailingEqualsConstraint: NSLayoutConstraint?
|
||||
internal var trailingLessThanEqualsConstraint: NSLayoutConstraint?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Overrides
|
||||
//--------------------------------------------------
|
||||
@ -183,7 +195,12 @@ open class Footnote: View {
|
||||
|
||||
// add footnote item stackview.
|
||||
addSubview(itemStackView)
|
||||
itemStackView.pinToSuperView()
|
||||
itemStackView.pinTop().pinBottom().pinLeading()
|
||||
trailingEqualsConstraint = itemStackView.pinTrailing(anchor: trailingAnchor)
|
||||
|
||||
// width constraints
|
||||
itemWidthConstraint = itemStackView.widthAnchor.constraint(equalToConstant: 0).deactivate()
|
||||
trailingLessThanEqualsConstraint = itemStackView.pinTrailingLessThanOrEqualTo(anchor: trailingAnchor)?.deactivate()
|
||||
|
||||
// add symbol label, text label to stack.
|
||||
itemStackView.addArrangedSubview(symbolLabel)
|
||||
@ -192,7 +209,6 @@ open class Footnote: View {
|
||||
|
||||
symbolWidthConstraint = symbolLabel.widthAnchor.constraint(greaterThanOrEqualToConstant: 0)
|
||||
symbolWidthConstraint?.isActive = true
|
||||
|
||||
}
|
||||
|
||||
open override func setDefaults() {
|
||||
@ -221,8 +237,13 @@ open class Footnote: View {
|
||||
symbolLabel.textStyle = size.textStyle.regular
|
||||
symbolLabel.surface = surface
|
||||
|
||||
// Update symbolLabel width as per updated text size
|
||||
symbolWidthConstraint = symbolLabel.widthAnchor.constraint(equalToConstant: symbolLabel.intrinsicContentSize.width)
|
||||
//Set width to the symbol label
|
||||
if symbolWiderWidth > 0 {
|
||||
// Set the widest symbol width from the symbol container in the group.
|
||||
symbolWidthConstraint = symbolLabel.widthAnchor.constraint(equalToConstant: symbolWiderWidth)
|
||||
} else {
|
||||
symbolWidthConstraint = symbolLabel.widthAnchor.constraint(equalToConstant: symbolLabel.intrinsicContentSize.width)
|
||||
}
|
||||
symbolWidthConstraint?.isActive = true
|
||||
|
||||
// Update textLabel
|
||||
@ -237,5 +258,33 @@ open class Footnote: View {
|
||||
attributes.append(TooltipLabelAttribute(surface: surface, model: tooltipModel, presenter: self))
|
||||
textLabel.attributes = attributes
|
||||
}
|
||||
|
||||
updateContainerWidth()
|
||||
}
|
||||
|
||||
/// 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:
|
||||
newWidth = maxWidth
|
||||
}
|
||||
itemWidthConstraint?.deactivate()
|
||||
trailingLessThanEqualsConstraint?.deactivate()
|
||||
trailingEqualsConstraint?.deactivate()
|
||||
|
||||
if newWidth > minWidth && newWidth < maxWidth {
|
||||
itemWidthConstraint?.constant = newWidth
|
||||
itemWidthConstraint?.activate()
|
||||
trailingLessThanEqualsConstraint?.activate()
|
||||
} else {
|
||||
trailingEqualsConstraint?.activate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
180
VDS/Components/Footnote/FootnoteGroup.swift
Normal file
180
VDS/Components/Footnote/FootnoteGroup.swift
Normal file
@ -0,0 +1,180 @@
|
||||
//
|
||||
// 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: [Footnote] = [] { 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
|
||||
}
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Private Properties
|
||||
//--------------------------------------------------
|
||||
private var _width: Width? = nil
|
||||
|
||||
private lazy var stackView = UIStackView().with {
|
||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||
$0.axis = .vertical
|
||||
$0.alignment = .top
|
||||
$0.distribution = .fill
|
||||
$0.spacing = VDSLayout.space3X
|
||||
$0.backgroundColor = .clear
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Configuration Properties
|
||||
//--------------------------------------------------
|
||||
internal var maxWidth: CGFloat { frame.size.width }
|
||||
internal var minWidth: CGFloat { containerSize.width }
|
||||
internal var containerSize: CGSize { CGSize(width: 55, height: 44) }
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
//--------------------------------------------------
|
||||
internal var widthConstraint: NSLayoutConstraint?
|
||||
internal var trailingEqualsConstraint: NSLayoutConstraint?
|
||||
internal var trailingLessThanEqualsConstraint: 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.pinTop().pinBottom().pinLeading()
|
||||
trailingEqualsConstraint = stackView.pinTrailing(anchor: trailingAnchor)
|
||||
|
||||
// width constraints
|
||||
trailingLessThanEqualsConstraint = stackView.pinTrailingLessThanOrEqualTo(anchor: trailingAnchor)?.deactivate()
|
||||
widthConstraint = stackView.widthAnchor.constraint(equalToConstant: 0).deactivate()
|
||||
}
|
||||
|
||||
open override func setDefaults() {
|
||||
super.setDefaults()
|
||||
width = nil
|
||||
footnoteitems = []
|
||||
}
|
||||
|
||||
/// Resets to default settings.
|
||||
open override func 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()
|
||||
updateContainerWidth()
|
||||
|
||||
// symbol containers are as wide as the widest symbol container in the group.
|
||||
var symbolMaxWidth = 0.0
|
||||
if footnoteitems.count > 0 {
|
||||
for index in 0...footnoteitems.count - 1 {
|
||||
let footnote: Footnote = footnoteitems[index]
|
||||
let separatorWidth = Label().with { $0.text = footnote.symbolType.text; $0.sizeToFit() }.intrinsicContentSize.width
|
||||
symbolMaxWidth = separatorWidth > symbolMaxWidth ? separatorWidth : symbolMaxWidth
|
||||
}
|
||||
}
|
||||
|
||||
stackView.subviews.forEach{$0.removeFromSuperview()}
|
||||
// add symbol label, text label to stack.
|
||||
if footnoteitems.count > 0 {
|
||||
for index in 0...footnoteitems.count - 1 {
|
||||
let footnote: Footnote = footnoteitems[index]
|
||||
footnote.symbolWiderWidth = 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:
|
||||
newWidth = maxWidth
|
||||
}
|
||||
|
||||
widthConstraint?.deactivate()
|
||||
trailingLessThanEqualsConstraint?.deactivate()
|
||||
trailingEqualsConstraint?.deactivate()
|
||||
|
||||
if newWidth > minWidth && newWidth < maxWidth {
|
||||
widthConstraint?.constant = newWidth
|
||||
widthConstraint?.activate()
|
||||
trailingLessThanEqualsConstraint?.activate()
|
||||
} else {
|
||||
trailingEqualsConstraint?.activate()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,6 +33,7 @@ Using the system allows designers and developers to collaborate more easily and
|
||||
- ``CheckboxGroup``
|
||||
- ``DropdownSelect``
|
||||
- ``Footnote``
|
||||
- ``FootnoteGroup``
|
||||
- ``Icon``
|
||||
- ``InputStepper``
|
||||
- ``InputField``
|
||||
|
||||
Loading…
Reference in New Issue
Block a user