From 0158d2f5db51d57f944c118c8160098c6d6d1745 Mon Sep 17 00:00:00 2001 From: Vasavi Kanamarlapudi Date: Tue, 6 Aug 2024 11:05:35 +0530 Subject: [PATCH 01/14] Digital ACT-191 ONEAPP-9314 story: added new page --- VDS.xcodeproj/project.pbxproj | 16 ++++ VDS/Components/PriceLockup/PriceLockup.swift | 76 +++++++++++++++++++ .../PriceLockup/PriceLockupChangeLog.txt | 28 +++++++ VDS/VDS.docc/VDS.md | 1 + 4 files changed, 121 insertions(+) create mode 100644 VDS/Components/PriceLockup/PriceLockup.swift create mode 100644 VDS/Components/PriceLockup/PriceLockupChangeLog.txt diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index 230ce227..8a9cf9ed 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -9,6 +9,8 @@ /* Begin PBXBuildFile section */ 1808BEBC2BA41C3200129230 /* CarouselScrollbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */; }; 1832AC572BA0791D008AE476 /* BreadcrumbCellItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1832AC562BA0791D008AE476 /* BreadcrumbCellItem.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 */; }; 1842B1E12BECE7B70021AFCA /* CalendarHeaderReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1842B1E02BECE7B70021AFCA /* CalendarHeaderReusableView.swift */; }; 1842B1E32BECF0A20021AFCA /* CalendarFooterReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1842B1E22BECF0A10021AFCA /* CalendarFooterReusableView.swift */; }; @@ -210,6 +212,8 @@ 1808BEBB2BA41C3200129230 /* CarouselScrollbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselScrollbar.swift; sourceTree = ""; }; 1808BEBF2BA456B700129230 /* CarouselScrollbarChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CarouselScrollbarChangeLog.txt; sourceTree = ""; }; 1832AC562BA0791D008AE476 /* BreadcrumbCellItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbCellItem.swift; sourceTree = ""; }; + 184023442C61E7AD00A412C8 /* PriceLockup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriceLockup.swift; sourceTree = ""; }; + 184023462C61E7EC00A412C8 /* PriceLockupChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = PriceLockupChangeLog.txt; sourceTree = ""; }; 1842B1DE2BECE28B0021AFCA /* CalendarDateViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarDateViewCell.swift; sourceTree = ""; }; 1842B1E02BECE7B70021AFCA /* CalendarHeaderReusableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarHeaderReusableView.swift; sourceTree = ""; }; 1842B1E22BECF0A10021AFCA /* CalendarFooterReusableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarFooterReusableView.swift; sourceTree = ""; }; @@ -458,6 +462,15 @@ path = CarouselScrollbar; sourceTree = ""; }; + 184023432C61E78D00A412C8 /* PriceLockup */ = { + isa = PBXGroup; + children = ( + 184023442C61E7AD00A412C8 /* PriceLockup.swift */, + 184023462C61E7EC00A412C8 /* PriceLockupChangeLog.txt */, + ); + path = PriceLockup; + sourceTree = ""; + }; 186D13C92BBA8A3500986B53 /* DropdownSelect */ = { isa = PBXGroup; children = ( @@ -686,6 +699,7 @@ EAD0688C2A55F801002E3A2D /* Loader */, 445BA07629C07ABA0036A7C5 /* Notification */, 71B23C2B2B91FA510027F7D9 /* Pagination */, + 184023432C61E78D00A412C8 /* PriceLockup */, EA89200B28B530F0006B9984 /* RadioBox */, EAF7F11428A1470D00B287F5 /* RadioButton */, 440B84C82BD8E0CE004A732A /* Table */, @@ -1185,6 +1199,7 @@ buildActionMask = 2147483647; files = ( EA3362042891E14D0071C351 /* VerizonNHGeTX-Bold.otf in Resources */, + 184023472C61E7EC00A412C8 /* PriceLockupChangeLog.txt in Resources */, EA3362072891E14D0071C351 /* VerizonNHGeDS-Regular.otf in Resources */, EA3362062891E14D0071C351 /* VerizonNHGeTX-Regular.otf in Resources */, EA3362052891E14D0071C351 /* VerizonNHGeDS-Bold.otf in Resources */, @@ -1394,6 +1409,7 @@ EAC58C0E2BED021600BA39FA /* Password.swift in Sources */, EAF7F0AD289B142900B287F5 /* StrikeThroughLabelAttribute.swift in Sources */, EAB5FEF12927F4AA00998C17 /* SelfSizingCollectionView.swift in Sources */, + 184023452C61E7AD00A412C8 /* PriceLockup.swift in Sources */, EA3361B8288B2AAA0071C351 /* ViewProtocol.swift in Sources */, EA3361A8288B23300071C351 /* UIColor.swift in Sources */, EA2DC9B42BE2C6FE004F58C5 /* TextField.swift in Sources */, diff --git a/VDS/Components/PriceLockup/PriceLockup.swift b/VDS/Components/PriceLockup/PriceLockup.swift new file mode 100644 index 00000000..745dc3c0 --- /dev/null +++ b/VDS/Components/PriceLockup/PriceLockup.swift @@ -0,0 +1,76 @@ +// +// PriceLockup.swift +// VDS +// +// Created by Kanamarlapudi, Vasavi on 06/08/24. +// + +import Foundation +import UIKit +import VDSCoreTokens + +@objcMembers +@objc(VDSPriceLockup) +open class PriceLockup: 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 + //-------------------------------------------------- + + //-------------------------------------------------- + // MARK: - Public Properties + //-------------------------------------------------- + + //-------------------------------------------------- + // MARK: - Private Properties + //-------------------------------------------------- + + //-------------------------------------------------- + // MARK: - Configuration Properties + //-------------------------------------------------- + + //-------------------------------------------------- + // 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() + } + + /// Used to make changes to the View based off a change events or from local properties. + open override func updateView() { + super.updateView() + + } + + /// Resets to default settings. + open override func reset() { + super.reset() + shouldUpdateView = false + + shouldUpdateView = true + setNeedsUpdate() + } + + open override var accessibilityElements: [Any]? { + get { + return nil + } + set {} + } +} diff --git a/VDS/Components/PriceLockup/PriceLockupChangeLog.txt b/VDS/Components/PriceLockup/PriceLockupChangeLog.txt new file mode 100644 index 00000000..e06ee9f8 --- /dev/null +++ b/VDS/Components/PriceLockup/PriceLockupChangeLog.txt @@ -0,0 +1,28 @@ +MM/DD/YYYY +---------------- + +11/16/2023 +---------------- +- Added leadingText and trailingText to anatomy +- Added leadingText and trailingText props to configurations +- Added term prop to configurations +- Removed Suspended orange color and corresponding color tokens + +11/27/2023 +---------------- +- Removed “Delimiter” from Anatomy as “Term” includes both delimiter and term +- Added “Figma only” badge to leadingText and trailingText in Configurations +- Added superscript to “none” under term in Configurations +- Added Overflow section to Layout and spacing +- Updated Spacing to allow for leading and trailing text + +12/18/23 +---------------- +- Updated all pages with spec template updates from Doc Utility Expansion Pack +- Added Content props section to Config page + +1/15/24 +---------------- +- Clarified strikethrough does not apply to leading or trailing text +- Clarified and added to text overflow examples +- Correct Success to Savings in the configuration seciton diff --git a/VDS/VDS.docc/VDS.md b/VDS/VDS.docc/VDS.md index 6582ce4a..aa583ada 100755 --- a/VDS/VDS.docc/VDS.md +++ b/VDS/VDS.docc/VDS.md @@ -39,6 +39,7 @@ Using the system allows designers and developers to collaborate more easily and - ``Loader`` - ``Notification`` - ``Pagination`` +- ``PriceLockup`` - ``RadioBoxItem`` - ``RadioBoxGroup`` - ``RadioButton`` From 815024cc5ce56bc4db11bc8b531b04654916f9ff Mon Sep 17 00:00:00 2001 From: Vasavi Kanamarlapudi Date: Tue, 6 Aug 2024 14:35:12 +0530 Subject: [PATCH 02/14] Digital ACT-191 ONEAPP-9314 story: added public properties --- VDS/Components/PriceLockup/PriceLockup.swift | 75 +++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/VDS/Components/PriceLockup/PriceLockup.swift b/VDS/Components/PriceLockup/PriceLockup.swift index 745dc3c0..ef11a2cb 100644 --- a/VDS/Components/PriceLockup/PriceLockup.swift +++ b/VDS/Components/PriceLockup/PriceLockup.swift @@ -31,25 +31,96 @@ open class PriceLockup: View { //-------------------------------------------------- // MARK: - Enums //-------------------------------------------------- + /// Enum used to describe the kind of PriceLockup. + public enum Kind: String, CaseIterable { + case primary, secondary, savings + } + + /// Enum used to describe the term of PriceLockup. + public enum Term: String, CaseIterable { + case month, year, biennial, none + } + + /// Enum type describing size of PriceLockup. + public enum Size: String, CaseIterable { + case xxxsmall + case xxsmall + case xsmall + case small + case medium + case large + case xlarge + case xxlarge + } //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + /// If true, the component will render as bold. + open var bold: Bool = false { didSet { setNeedsUpdate() } } + + /// Currency - If hideCurrency true, the component will render without currency. + open var hideCurrency: Bool = false { didSet { setNeedsUpdate() } } + + /// Leading text for the component. + open var leadingText: String? { didSet { setNeedsUpdate() } } + + /// Value rendered for the component. + open var price: CGFloat? { didSet { setNeedsUpdate() } } + + /// Color to the component. The default kind is primary. + open var kind: Kind = .primary { didSet { setNeedsUpdate() } } + + /// Size of the component. It varies by size and viewport(mobile/Tablet). + /// The default size is medium with viewport mobile. + open var size: Size = .medium { didSet { setNeedsUpdate() } } + + /// If true, the component with a strikethrough. It applies only when uniformSize is true. + /// Does not apply a strikethrough format to leading and trailing text. + open var strikethrough: Bool = false { didSet { setNeedsUpdate() } } + + /// Term text for the component. Superscript placement can vary when term and delimeter are "none". + /// The default term is 'month'. + open var term: Term = .month { didSet { setNeedsUpdate() } } + + /// Trailing text for the component. + open var trailingText: String? { didSet { setNeedsUpdate() } } + + /// Superscript text for the component. + open var superscript: String? { didSet { setNeedsUpdate() } } + + /// If true, currency and value have the same font text style as delimeter, term label and superscript. + /// This will render the pricing and term sections as a uniform size. + open var uniformSize: Bool = false { didSet { setNeedsUpdate() } } + + //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- - + internal var containerView = View().with { + $0.clipsToBounds = true + } //-------------------------------------------------- // MARK: - Configuration Properties //-------------------------------------------------- - + internal var containerSize: CGSize { CGSize(width: 45, height: 44) } + //-------------------------------------------------- // 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() + addSubview(containerView) + containerView + .pinTop() + .pinBottom() + .pinLeadingGreaterThanOrEqualTo() + .pinTrailingLessThanOrEqualTo() + .height(containerSize.height) + + containerView.centerXAnchor.constraint(equalTo: centerXAnchor).activate() } /// Used to make changes to the View based off a change events or from local properties. From b1adbd7e0d0240eee87b3e3a98d2103a18c2d6a6 Mon Sep 17 00:00:00 2001 From: Vasavi Kanamarlapudi Date: Mon, 12 Aug 2024 15:45:18 +0530 Subject: [PATCH 03/14] Digital ACT-191 ONEAPP-9314 story: update text --- VDS/Components/PriceLockup/PriceLockup.swift | 75 ++++++++++++++++++-- 1 file changed, 70 insertions(+), 5 deletions(-) diff --git a/VDS/Components/PriceLockup/PriceLockup.swift b/VDS/Components/PriceLockup/PriceLockup.swift index ef11a2cb..e127fd9a 100644 --- a/VDS/Components/PriceLockup/PriceLockup.swift +++ b/VDS/Components/PriceLockup/PriceLockup.swift @@ -39,6 +39,23 @@ open class PriceLockup: View { /// Enum used to describe the term of PriceLockup. public enum Term: String, CaseIterable { case month, year, biennial, none + + /// The default term is 'month'. + public static var defaultValue : Self { .month } + + /// Text for this term of PriceLockup. + public var text: String { + switch self { + case .month: + return "mo" + case .year: + return "yr" + case .biennial: + return "biennial" + case .none: + return "" + } + } } /// Enum type describing size of PriceLockup. @@ -80,9 +97,9 @@ open class PriceLockup: View { /// Does not apply a strikethrough format to leading and trailing text. open var strikethrough: Bool = false { didSet { setNeedsUpdate() } } - /// Term text for the component. Superscript placement can vary when term and delimeter are "none". - /// The default term is 'month'. - open var term: Term = .month { didSet { setNeedsUpdate() } } + /// Term text for the component. The default term is 'month'. + /// Superscript placement can vary when term and delimeter are "none". + open var term: Term = Term.defaultValue { didSet { setNeedsUpdate() } } /// Trailing text for the component. open var trailingText: String? { didSet { setNeedsUpdate() } } @@ -101,11 +118,31 @@ open class PriceLockup: View { internal var containerView = View().with { $0.clipsToBounds = true } + + internal var label = Label().with { + $0.isAccessibilityElement = false + $0.lineBreakMode = .byWordWrapping + } + //-------------------------------------------------- // MARK: - Configuration Properties //-------------------------------------------------- internal var containerSize: CGSize { CGSize(width: 45, height: 44) } + private var kindColorConfiguration: AnyColorable { + switch kind { + case .primary: + return ControlColorConfiguration().with { + $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal)}.eraseToAnyColorable() + case .secondary: + return ControlColorConfiguration().with { + $0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark, forState: .normal)}.eraseToAnyColorable() + case .savings: + return ControlColorConfiguration().with { + $0.setSurfaceColors(VDSColor.paletteGreen26, VDSColor.paletteGreen36, forState: .normal)}.eraseToAnyColorable() + } + } + //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- @@ -121,19 +158,24 @@ open class PriceLockup: View { .height(containerSize.height) containerView.centerXAnchor.constraint(equalTo: centerXAnchor).activate() + + // Price lockup + containerView.addSubview(label) + label.pinToSuperView() + label.centerXAnchor.constraint(equalTo: centerXAnchor).activate() } /// Used to make changes to the View based off a change events or from local properties. open override func updateView() { super.updateView() - + label.text = fetchText() } /// Resets to default settings. open override func reset() { super.reset() shouldUpdateView = false - + label.reset() shouldUpdateView = true setNeedsUpdate() } @@ -144,4 +186,27 @@ open class PriceLockup: View { } set {} } + + //-------------------------------------------------- + // MARK: - Private Methods + //-------------------------------------------------- + open func fetchText() -> String { + var text : String = "" + let currency: String = hideCurrency ? "" : "$" + if let leadingStr = leadingText { + text = text + leadingStr + " " + } + if let value = price { + text = text + currency + "\(value)" + } + if term != .none { + text = text + "/" + term.text + } + if let trailingStr = trailingText { + text = text + " " + trailingStr + } + text = text + (superscript ?? "") + return text + + } } From 1bb54d174f8b849ad998b903e7ec7dd3772156a0 Mon Sep 17 00:00:00 2001 From: Vasavi Kanamarlapudi Date: Tue, 13 Aug 2024 15:37:02 +0530 Subject: [PATCH 04/14] Digital ACT-191 ONEAPP-9314 story: applying textstyle and color --- VDS/Components/PriceLockup/PriceLockup.swift | 124 +++++++++++++++++-- 1 file changed, 111 insertions(+), 13 deletions(-) diff --git a/VDS/Components/PriceLockup/PriceLockup.swift b/VDS/Components/PriceLockup/PriceLockup.swift index e127fd9a..3bac1779 100644 --- a/VDS/Components/PriceLockup/PriceLockup.swift +++ b/VDS/Components/PriceLockup/PriceLockup.swift @@ -68,6 +68,8 @@ open class PriceLockup: View { case large case xlarge case xxlarge + + public var defaultValue: Self { .medium } } //-------------------------------------------------- @@ -111,7 +113,6 @@ open class PriceLockup: View { /// This will render the pricing and term sections as a uniform size. open var uniformSize: Bool = false { didSet { setNeedsUpdate() } } - //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- @@ -124,25 +125,79 @@ open class PriceLockup: View { $0.lineBreakMode = .byWordWrapping } + internal var index = 0 + + internal var textContentType:TextContentType = .preDelimiter + enum TextContentType: String, CaseIterable { + case preDelimiter, postDelimiter + } + //-------------------------------------------------- // MARK: - Configuration Properties //-------------------------------------------------- internal var containerSize: CGSize { CGSize(width: 45, height: 44) } - private var kindColorConfiguration: AnyColorable { - switch kind { - case .primary: - return ControlColorConfiguration().with { - $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal)}.eraseToAnyColorable() - case .secondary: - return ControlColorConfiguration().with { - $0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark, forState: .normal)}.eraseToAnyColorable() - case .savings: - return ControlColorConfiguration().with { - $0.setSurfaceColors(VDSColor.paletteGreen26, VDSColor.paletteGreen36, forState: .normal)}.eraseToAnyColorable() + private var contentFontSize: VDS.TextStyle { + switch (size, textContentType) { + case (.xxxsmall, .preDelimiter), (.xxxsmall, .postDelimiter): + return TextStyle.micro + + case (.xxsmall, .preDelimiter), (.xxsmall, .postDelimiter): + return TextStyle.bodySmall + + case (.xsmall, .preDelimiter), (.xsmall, .postDelimiter): + return TextStyle.bodyMedium + + case (.small, .preDelimiter), (.small, .postDelimiter): + return TextStyle.bodyLarge + + case (.medium, .preDelimiter): + return UIDevice.isIPad ? TextStyle.titleSmall : TextStyle.titleMedium + + case (.medium, .postDelimiter): + return TextStyle.bodyLarge + + case (.large, .preDelimiter): + return UIDevice.isIPad ? TextStyle.titleMedium : TextStyle.titleLarge + + case (.large, .postDelimiter): + return UIDevice.isIPad ? TextStyle.titleSmall : TextStyle.titleMedium + + case (.xlarge, .preDelimiter): + return UIDevice.isIPad ? TextStyle.titleLarge : TextStyle.titleXLarge + + case (.xlarge, .postDelimiter): + return UIDevice.isIPad ? TextStyle.titleMedium : TextStyle.titleLarge + + case (.xxlarge, .preDelimiter): + return UIDevice.isIPad ? TextStyle.titleXLarge : TextStyle.featureSmall + + case (.xxlarge, .postDelimiter): + return UIDevice.isIPad ? TextStyle.titleLarge : TextStyle.titleXLarge } } + private var kindViewColorConfiguration: ViewColorConfiguration { + switch kind { + + case .primary: + return ViewColorConfiguration().with { + $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) + } + + case .secondary: + return ViewColorConfiguration().with { + $0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark, forDisabled: false) + } + case .savings: + return ViewColorConfiguration().with { + $0.setSurfaceColors(VDSColor.paletteGreen26, VDSColor.paletteGreen36, forDisabled: false) + } + } + } + + private var heightConstraint: NSLayoutConstraint? + //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- @@ -163,12 +218,51 @@ open class PriceLockup: View { containerView.addSubview(label) label.pinToSuperView() label.centerXAnchor.constraint(equalTo: centerXAnchor).activate() + heightConstraint = label.heightAnchor.constraint(equalToConstant: 0) + heightConstraint?.activate() + } + + func updateLabel() { + var attributes: [any LabelAttributeModel] = [] + let colorAttr = ColorLabelAttribute(location: 0, + length: label.text.count, + color: kindViewColorConfiguration.getColor(self)) + attributes.append(colorAttr) + if index > 0 { + textContentType = .preDelimiter + let textStyleAttr = TextStyleLabelAttribute(location: 0, + length: index, + textStyle: contentFontSize) + textContentType = .postDelimiter + let othertextStyleAttr = TextStyleLabelAttribute(location: index+1, + length: label.text.count-index-1, + textStyle: contentFontSize) + attributes.append(textStyleAttr) + attributes.append(othertextStyleAttr) + } + label.attributes = attributes } /// Used to make changes to the View based off a change events or from local properties. open override func updateView() { super.updateView() label.text = fetchText() + label.surface = surface + + // Set the attributed text + updateLabel() + + if uniformSize { + // currency and value have the same font text style as delimeter, term, trailing text and superscript. + textContentType = .postDelimiter + var uniformSizeAttributes: [any LabelAttributeModel]? { + [TextStyleLabelAttribute(location: 0, + length: label.text.count, + textStyle: contentFontSize)] + } + label.attributes = uniformSizeAttributes + } + } /// Resets to default settings. @@ -192,12 +286,16 @@ open class PriceLockup: View { //-------------------------------------------------- open func fetchText() -> String { var text : String = "" + index = 0 let currency: String = hideCurrency ? "" : "$" if let leadingStr = leadingText { text = text + leadingStr + " " + index = index + leadingStr.count + 1 } if let value = price { - text = text + currency + "\(value)" + let valueStr = "\(value)" + text = text + currency + valueStr + index = index + valueStr.count + 1 } if term != .none { text = text + "/" + term.text From 73db6dff2df9f5cb94bd27c90c81398a09ea810a Mon Sep 17 00:00:00 2001 From: Vasavi Kanamarlapudi Date: Wed, 14 Aug 2024 14:53:27 +0530 Subject: [PATCH 05/14] Digital ACT-191 ONEAPP-9314 story: update label with strikethrough if its enabled, and other minor changes --- VDS/Components/PriceLockup/PriceLockup.swift | 30 ++++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/VDS/Components/PriceLockup/PriceLockup.swift b/VDS/Components/PriceLockup/PriceLockup.swift index 3bac1779..6cda4cf4 100644 --- a/VDS/Components/PriceLockup/PriceLockup.swift +++ b/VDS/Components/PriceLockup/PriceLockup.swift @@ -121,11 +121,13 @@ open class PriceLockup: View { } internal var label = Label().with { - $0.isAccessibilityElement = false + $0.isAccessibilityElement = true $0.lineBreakMode = .byWordWrapping } internal var index = 0 + internal var strikethroughLocation = 0 + internal var strikethroughlength = 0 internal var textContentType:TextContentType = .preDelimiter enum TextContentType: String, CaseIterable { @@ -177,7 +179,7 @@ open class PriceLockup: View { } } - private var kindViewColorConfiguration: ViewColorConfiguration { + private var textColorConfiguration: ViewColorConfiguration { switch kind { case .primary: @@ -195,9 +197,7 @@ open class PriceLockup: View { } } } - - private var heightConstraint: NSLayoutConstraint? - + //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- @@ -218,15 +218,13 @@ open class PriceLockup: View { containerView.addSubview(label) label.pinToSuperView() label.centerXAnchor.constraint(equalTo: centerXAnchor).activate() - heightConstraint = label.heightAnchor.constraint(equalToConstant: 0) - heightConstraint?.activate() } func updateLabel() { var attributes: [any LabelAttributeModel] = [] let colorAttr = ColorLabelAttribute(location: 0, length: label.text.count, - color: kindViewColorConfiguration.getColor(self)) + color: textColorConfiguration.getColor(self)) attributes.append(colorAttr) if index > 0 { textContentType = .preDelimiter @@ -252,6 +250,18 @@ open class PriceLockup: View { // Set the attributed text updateLabel() + if strikethrough { + // strike applies only when uniformSize true. Does not apply a strikethrough format to leading, trailing, and superscript text. + textContentType = .postDelimiter + var strikethroughAttributes: [any LabelAttributeModel]? { + [TextStyleLabelAttribute(location: 0, + length: label.text.count, + textStyle: contentFontSize), + StrikeThroughLabelAttribute(location:strikethroughLocation, length: strikethroughlength)] + } + label.attributes = strikethroughAttributes + } + if uniformSize { // currency and value have the same font text style as delimeter, term, trailing text and superscript. textContentType = .postDelimiter @@ -262,7 +272,6 @@ open class PriceLockup: View { } label.attributes = uniformSizeAttributes } - } /// Resets to default settings. @@ -293,12 +302,15 @@ open class PriceLockup: View { index = index + leadingStr.count + 1 } if let value = price { + strikethroughLocation = index let valueStr = "\(value)" text = text + currency + valueStr index = index + valueStr.count + 1 + strikethroughlength = valueStr.count + 1 } if term != .none { text = text + "/" + term.text + strikethroughlength = strikethroughlength + term.text.count + 1 } if let trailingStr = trailingText { text = text + " " + trailingStr From 20c407f82af725d7dae03a224af8959bc55bcefe Mon Sep 17 00:00:00 2001 From: Vasavi Kanamarlapudi Date: Wed, 14 Aug 2024 15:27:47 +0530 Subject: [PATCH 06/14] Digital ACT-191 ONEAPP-9314 story: remove a decimal for price if decimal is 0 --- VDS/Components/PriceLockup/PriceLockup.swift | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/VDS/Components/PriceLockup/PriceLockup.swift b/VDS/Components/PriceLockup/PriceLockup.swift index 6cda4cf4..4d21b42c 100644 --- a/VDS/Components/PriceLockup/PriceLockup.swift +++ b/VDS/Components/PriceLockup/PriceLockup.swift @@ -86,7 +86,7 @@ open class PriceLockup: View { open var leadingText: String? { didSet { setNeedsUpdate() } } /// Value rendered for the component. - open var price: CGFloat? { didSet { setNeedsUpdate() } } + open var price: Float? { didSet { setNeedsUpdate() } } /// Color to the component. The default kind is primary. open var kind: Kind = .primary { didSet { setNeedsUpdate() } } @@ -197,7 +197,7 @@ open class PriceLockup: View { } } } - + //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- @@ -303,7 +303,7 @@ open class PriceLockup: View { } if let value = price { strikethroughLocation = index - let valueStr = "\(value)" + let valueStr = "\(value.clean)" text = text + currency + valueStr index = index + valueStr.count + 1 strikethroughlength = valueStr.count + 1 @@ -320,3 +320,10 @@ open class PriceLockup: View { } } + +extension Float { + // remove a decimal from a float if the decimal is equal to 0 + var clean: String { + return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self) + } +} From 8f7581d0d6bed9fea2f4b19bec560bc88a81302d Mon Sep 17 00:00:00 2001 From: Vasavi Kanamarlapudi Date: Thu, 15 Aug 2024 14:55:32 +0530 Subject: [PATCH 07/14] Digital ACT-191 ONEAPP-9314 story: refactored code --- VDS/Components/PriceLockup/PriceLockup.swift | 206 +++++++++---------- 1 file changed, 95 insertions(+), 111 deletions(-) diff --git a/VDS/Components/PriceLockup/PriceLockup.swift b/VDS/Components/PriceLockup/PriceLockup.swift index 4d21b42c..059a94a6 100644 --- a/VDS/Components/PriceLockup/PriceLockup.swift +++ b/VDS/Components/PriceLockup/PriceLockup.swift @@ -31,11 +31,6 @@ open class PriceLockup: View { //-------------------------------------------------- // MARK: - Enums //-------------------------------------------------- - /// Enum used to describe the kind of PriceLockup. - public enum Kind: String, CaseIterable { - case primary, secondary, savings - } - /// Enum used to describe the term of PriceLockup. public enum Term: String, CaseIterable { case month, year, biennial, none @@ -44,7 +39,7 @@ open class PriceLockup: View { public static var defaultValue : Self { .month } /// Text for this term of PriceLockup. - public var text: String { + public var type: String { switch self { case .month: return "mo" @@ -69,7 +64,30 @@ open class PriceLockup: View { case xlarge case xxlarge - public var defaultValue: Self { .medium } + public static var defaultValue: Self { .medium } + } + + /// Enum used to describe the kind of PriceLockup. + public enum Kind: String, CaseIterable { + case primary, secondary, savings + + /// The default kind is 'primary'. + public static var defaultValue : Self { .primary } + + /// Color configuation relative to kind. + public var colorConfiguration: ViewColorConfiguration { + switch self { + case .primary: + return ViewColorConfiguration().with { + $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false)} + case .secondary: + return ViewColorConfiguration().with { + $0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark, forDisabled: false)} + case .savings: + return ViewColorConfiguration().with { + $0.setSurfaceColors(VDSColor.paletteGreen26, VDSColor.paletteGreen36, forDisabled: false)} + } + } } //-------------------------------------------------- @@ -89,11 +107,11 @@ open class PriceLockup: View { open var price: Float? { didSet { setNeedsUpdate() } } /// Color to the component. The default kind is primary. - open var kind: Kind = .primary { didSet { setNeedsUpdate() } } + open var kind: Kind = Kind.defaultValue { didSet { setNeedsUpdate() } } /// Size of the component. It varies by size and viewport(mobile/Tablet). /// The default size is medium with viewport mobile. - open var size: Size = .medium { didSet { setNeedsUpdate() } } + open var size: Size = Size.defaultValue { didSet { setNeedsUpdate() } } /// If true, the component with a strikethrough. It applies only when uniformSize is true. /// Does not apply a strikethrough format to leading and trailing text. @@ -116,21 +134,17 @@ open class PriceLockup: View { //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- - internal var containerView = View().with { - $0.clipsToBounds = true - } - - internal var label = Label().with { + internal var priceLockupLabel = Label().with { $0.isAccessibilityElement = true $0.lineBreakMode = .byWordWrapping } - internal var index = 0 + internal var delimiterIndex = 0 internal var strikethroughLocation = 0 - internal var strikethroughlength = 0 + internal var strikethroughLength = 0 - internal var textContentType:TextContentType = .preDelimiter - enum TextContentType: String, CaseIterable { + internal var textPosition:TextPosition = .preDelimiter + enum TextPosition: String, CaseIterable { case preDelimiter, postDelimiter } @@ -139,8 +153,8 @@ open class PriceLockup: View { //-------------------------------------------------- internal var containerSize: CGSize { CGSize(width: 45, height: 44) } - private var contentFontSize: VDS.TextStyle { - switch (size, textContentType) { + private var sizeTextStyle: VDS.TextStyle { + switch (size, textPosition) { case (.xxxsmall, .preDelimiter), (.xxxsmall, .postDelimiter): return TextStyle.micro @@ -179,106 +193,34 @@ open class PriceLockup: View { } } - private var textColorConfiguration: ViewColorConfiguration { - switch kind { - - case .primary: - return ViewColorConfiguration().with { - $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) - } - - case .secondary: - return ViewColorConfiguration().with { - $0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark, forDisabled: false) - } - case .savings: - return ViewColorConfiguration().with { - $0.setSurfaceColors(VDSColor.paletteGreen26, VDSColor.paletteGreen36, forDisabled: false) - } - } - } - //-------------------------------------------------- // 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() - addSubview(containerView) - containerView - .pinTop() - .pinBottom() - .pinLeadingGreaterThanOrEqualTo() - .pinTrailingLessThanOrEqualTo() - .height(containerSize.height) - containerView.centerXAnchor.constraint(equalTo: centerXAnchor).activate() - - // Price lockup - containerView.addSubview(label) - label.pinToSuperView() - label.centerXAnchor.constraint(equalTo: centerXAnchor).activate() + // Price lockup label + addSubview(priceLockupLabel) + priceLockupLabel.pinToSuperView() } - - func updateLabel() { - var attributes: [any LabelAttributeModel] = [] - let colorAttr = ColorLabelAttribute(location: 0, - length: label.text.count, - color: textColorConfiguration.getColor(self)) - attributes.append(colorAttr) - if index > 0 { - textContentType = .preDelimiter - let textStyleAttr = TextStyleLabelAttribute(location: 0, - length: index, - textStyle: contentFontSize) - textContentType = .postDelimiter - let othertextStyleAttr = TextStyleLabelAttribute(location: index+1, - length: label.text.count-index-1, - textStyle: contentFontSize) - attributes.append(textStyleAttr) - attributes.append(othertextStyleAttr) - } - label.attributes = attributes - } - + /// Used to make changes to the View based off a change events or from local properties. open override func updateView() { super.updateView() - label.text = fetchText() - label.surface = surface + + priceLockupLabel.text = fetchText() + priceLockupLabel.surface = surface // Set the attributed text - updateLabel() - - if strikethrough { - // strike applies only when uniformSize true. Does not apply a strikethrough format to leading, trailing, and superscript text. - textContentType = .postDelimiter - var strikethroughAttributes: [any LabelAttributeModel]? { - [TextStyleLabelAttribute(location: 0, - length: label.text.count, - textStyle: contentFontSize), - StrikeThroughLabelAttribute(location:strikethroughLocation, length: strikethroughlength)] - } - label.attributes = strikethroughAttributes - } - - if uniformSize { - // currency and value have the same font text style as delimeter, term, trailing text and superscript. - textContentType = .postDelimiter - var uniformSizeAttributes: [any LabelAttributeModel]? { - [TextStyleLabelAttribute(location: 0, - length: label.text.count, - textStyle: contentFontSize)] - } - label.attributes = uniformSizeAttributes - } + updateLabelAttributes() } /// Resets to default settings. open override func reset() { super.reset() shouldUpdateView = false - label.reset() + priceLockupLabel.reset() shouldUpdateView = true setNeedsUpdate() } @@ -293,31 +235,73 @@ open class PriceLockup: View { //-------------------------------------------------- // MARK: - Private Methods //-------------------------------------------------- + func updateLabelAttributes() { + var attributes: [any LabelAttributeModel] = [] + attributes.append(ColorLabelAttribute(location: 0, + length: priceLockupLabel.text.count, + color: kind.colorConfiguration.getColor(self))) + textPosition = .postDelimiter + if strikethrough { + + // strike applies only when uniformSize true. Does not apply a strikethrough format to leading, trailing, and superscript text. + attributes.append(TextStyleLabelAttribute(location: 0, + length: priceLockupLabel.text.count, + textStyle: sizeTextStyle, + textPosition: .left)) + attributes.append(StrikeThroughLabelAttribute(location:strikethroughLocation, length: strikethroughLength)) + } else if uniformSize { + + // currency and value have the same font text style as delimeter, term, trailing text and superscript. + attributes.append(TextStyleLabelAttribute(location: 0, + length: priceLockupLabel.text.count, + textStyle: sizeTextStyle, + textPosition: .left)) + } else { + + // size updates relative to predelimiter, postdelimiter + if delimiterIndex > 0 { + textPosition = .preDelimiter + attributes.append(TextStyleLabelAttribute(location: 0, + length: delimiterIndex, + textStyle: sizeTextStyle, + textPosition: .left)) + + textPosition = .postDelimiter + attributes.append(TextStyleLabelAttribute(location: delimiterIndex, + length: priceLockupLabel.text.count-delimiterIndex, + textStyle: sizeTextStyle, + textPosition: .left)) + } + } + priceLockupLabel.attributes = attributes + } + open func fetchText() -> String { var text : String = "" - index = 0 + let space = " " + let delimiter = "/" + delimiterIndex = 0 let currency: String = hideCurrency ? "" : "$" if let leadingStr = leadingText { - text = text + leadingStr + " " - index = index + leadingStr.count + 1 + text = text + leadingStr + space + delimiterIndex = delimiterIndex + leadingStr.count + space.count } if let value = price { - strikethroughLocation = index + strikethroughLocation = delimiterIndex let valueStr = "\(value.clean)" text = text + currency + valueStr - index = index + valueStr.count + 1 - strikethroughlength = valueStr.count + 1 + delimiterIndex = delimiterIndex + valueStr.count + currency.count + strikethroughLength = valueStr.count + currency.count } if term != .none { - text = text + "/" + term.text - strikethroughlength = strikethroughlength + term.text.count + 1 + text = text + delimiter + term.type + strikethroughLength = strikethroughLength + delimiter.count + term.type.count } if let trailingStr = trailingText { - text = text + " " + trailingStr + text = text + space + trailingStr } text = text + (superscript ?? "") return text - } } From 7ae5f9853dc5a4f84091247c323b9fa5dc3dc659 Mon Sep 17 00:00:00 2001 From: Vasavi Kanamarlapudi Date: Thu, 15 Aug 2024 16:27:23 +0530 Subject: [PATCH 08/14] Digital ACT-191 ONEAPP-9314 story: bold configuration, refactored strikethrough --- VDS/Components/PriceLockup/PriceLockup.swift | 49 ++++++++++---------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/VDS/Components/PriceLockup/PriceLockup.swift b/VDS/Components/PriceLockup/PriceLockup.swift index 059a94a6..bde3123e 100644 --- a/VDS/Components/PriceLockup/PriceLockup.swift +++ b/VDS/Components/PriceLockup/PriceLockup.swift @@ -53,7 +53,7 @@ open class PriceLockup: View { } } - /// Enum type describing size of PriceLockup. + /// Enum that represents the size availble for PriceLockup. public enum Size: String, CaseIterable { case xxxsmall case xxsmall @@ -153,43 +153,43 @@ open class PriceLockup: View { //-------------------------------------------------- internal var containerSize: CGSize { CGSize(width: 45, height: 44) } - private var sizeTextStyle: VDS.TextStyle { + private var textStyle: TextStyle.StandardStyle { switch (size, textPosition) { case (.xxxsmall, .preDelimiter), (.xxxsmall, .postDelimiter): - return TextStyle.micro + return .micro case (.xxsmall, .preDelimiter), (.xxsmall, .postDelimiter): - return TextStyle.bodySmall + return .bodySmall case (.xsmall, .preDelimiter), (.xsmall, .postDelimiter): - return TextStyle.bodyMedium + return .bodyMedium case (.small, .preDelimiter), (.small, .postDelimiter): - return TextStyle.bodyLarge + return .bodyLarge case (.medium, .preDelimiter): - return UIDevice.isIPad ? TextStyle.titleSmall : TextStyle.titleMedium + return UIDevice.isIPad ? .titleSmall : .titleMedium case (.medium, .postDelimiter): - return TextStyle.bodyLarge + return .bodyLarge case (.large, .preDelimiter): - return UIDevice.isIPad ? TextStyle.titleMedium : TextStyle.titleLarge + return UIDevice.isIPad ? .titleMedium : .titleLarge case (.large, .postDelimiter): - return UIDevice.isIPad ? TextStyle.titleSmall : TextStyle.titleMedium + return UIDevice.isIPad ? .titleSmall : .titleMedium case (.xlarge, .preDelimiter): - return UIDevice.isIPad ? TextStyle.titleLarge : TextStyle.titleXLarge + return UIDevice.isIPad ? .titleLarge : .titleXLarge case (.xlarge, .postDelimiter): - return UIDevice.isIPad ? TextStyle.titleMedium : TextStyle.titleLarge + return UIDevice.isIPad ? .titleMedium : .titleLarge case (.xxlarge, .preDelimiter): - return UIDevice.isIPad ? TextStyle.titleXLarge : TextStyle.featureSmall + return UIDevice.isIPad ? .titleXLarge : .featureSmall case (.xxlarge, .postDelimiter): - return UIDevice.isIPad ? TextStyle.titleLarge : TextStyle.titleXLarge + return UIDevice.isIPad ? .titleLarge : .titleXLarge } } @@ -245,17 +245,17 @@ open class PriceLockup: View { // strike applies only when uniformSize true. Does not apply a strikethrough format to leading, trailing, and superscript text. attributes.append(TextStyleLabelAttribute(location: 0, - length: priceLockupLabel.text.count, - textStyle: sizeTextStyle, - textPosition: .left)) + length: priceLockupLabel.text.count, + textStyle: bold ? textStyle.bold : textStyle.regular, + textPosition: .left)) attributes.append(StrikeThroughLabelAttribute(location:strikethroughLocation, length: strikethroughLength)) } else if uniformSize { // currency and value have the same font text style as delimeter, term, trailing text and superscript. attributes.append(TextStyleLabelAttribute(location: 0, - length: priceLockupLabel.text.count, - textStyle: sizeTextStyle, - textPosition: .left)) + length: priceLockupLabel.text.count, + textStyle: bold ? textStyle.bold : textStyle.regular, + textPosition: .left)) } else { // size updates relative to predelimiter, postdelimiter @@ -263,13 +263,13 @@ open class PriceLockup: View { textPosition = .preDelimiter attributes.append(TextStyleLabelAttribute(location: 0, length: delimiterIndex, - textStyle: sizeTextStyle, + textStyle: bold ? textStyle.bold : textStyle.regular, textPosition: .left)) - + textPosition = .postDelimiter attributes.append(TextStyleLabelAttribute(location: delimiterIndex, length: priceLockupLabel.text.count-delimiterIndex, - textStyle: sizeTextStyle, + textStyle: bold ? textStyle.bold : textStyle.regular, textPosition: .left)) } } @@ -281,13 +281,14 @@ open class PriceLockup: View { let space = " " let delimiter = "/" delimiterIndex = 0 + strikethroughLength = 0 let currency: String = hideCurrency ? "" : "$" if let leadingStr = leadingText { text = text + leadingStr + space delimiterIndex = delimiterIndex + leadingStr.count + space.count } + strikethroughLocation = delimiterIndex if let value = price { - strikethroughLocation = delimiterIndex let valueStr = "\(value.clean)" text = text + currency + valueStr delimiterIndex = delimiterIndex + valueStr.count + currency.count From 01c05deebd685b3961e574f963fa5527bd70efa7 Mon Sep 17 00:00:00 2001 From: Vasavi Kanamarlapudi Date: Thu, 15 Aug 2024 16:37:01 +0530 Subject: [PATCH 09/14] Digital ACT-191 ONEAPP-9314 story: removed unused code --- VDS/Components/PriceLockup/PriceLockup.swift | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/VDS/Components/PriceLockup/PriceLockup.swift b/VDS/Components/PriceLockup/PriceLockup.swift index bde3123e..6f6b21b5 100644 --- a/VDS/Components/PriceLockup/PriceLockup.swift +++ b/VDS/Components/PriceLockup/PriceLockup.swift @@ -224,14 +224,7 @@ open class PriceLockup: View { shouldUpdateView = true setNeedsUpdate() } - - open override var accessibilityElements: [Any]? { - get { - return nil - } - set {} - } - + //-------------------------------------------------- // MARK: - Private Methods //-------------------------------------------------- From e5d9f77d3d1e652b8d77ad6090e6a9efc5507ca3 Mon Sep 17 00:00:00 2001 From: Vasavi Kanamarlapudi Date: Thu, 15 Aug 2024 16:55:55 +0530 Subject: [PATCH 10/14] Digital ACT-191 ONEAPP-9314 story: added missed comments --- VDS/Components/PriceLockup/PriceLockup.swift | 39 +++++++++++--------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/VDS/Components/PriceLockup/PriceLockup.swift b/VDS/Components/PriceLockup/PriceLockup.swift index 6f6b21b5..0c776377 100644 --- a/VDS/Components/PriceLockup/PriceLockup.swift +++ b/VDS/Components/PriceLockup/PriceLockup.swift @@ -99,24 +99,24 @@ open class PriceLockup: View { /// Currency - If hideCurrency true, the component will render without currency. open var hideCurrency: Bool = false { didSet { setNeedsUpdate() } } - + /// Leading text for the component. open var leadingText: String? { didSet { setNeedsUpdate() } } - + /// Value rendered for the component. open var price: Float? { didSet { setNeedsUpdate() } } /// Color to the component. The default kind is primary. open var kind: Kind = Kind.defaultValue { didSet { setNeedsUpdate() } } - + /// Size of the component. It varies by size and viewport(mobile/Tablet). /// The default size is medium with viewport mobile. open var size: Size = Size.defaultValue { didSet { setNeedsUpdate() } } - + /// If true, the component with a strikethrough. It applies only when uniformSize is true. /// Does not apply a strikethrough format to leading and trailing text. open var strikethrough: Bool = false { didSet { setNeedsUpdate() } } - + /// Term text for the component. The default term is 'month'. /// Superscript placement can vary when term and delimeter are "none". open var term: Term = Term.defaultValue { didSet { setNeedsUpdate() } } @@ -130,7 +130,7 @@ open class PriceLockup: View { /// If true, currency and value have the same font text style as delimeter, term label and superscript. /// This will render the pricing and term sections as a uniform size. open var uniformSize: Bool = false { didSet { setNeedsUpdate() } } - + //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- @@ -142,7 +142,7 @@ open class PriceLockup: View { internal var delimiterIndex = 0 internal var strikethroughLocation = 0 internal var strikethroughLength = 0 - + internal var textPosition:TextPosition = .preDelimiter enum TextPosition: String, CaseIterable { case preDelimiter, postDelimiter @@ -152,7 +152,8 @@ open class PriceLockup: View { // MARK: - Configuration Properties //-------------------------------------------------- internal var containerSize: CGSize { CGSize(width: 45, height: 44) } - + + // TextStyle for the size. private var textStyle: TextStyle.StandardStyle { switch (size, textPosition) { case (.xxxsmall, .preDelimiter), (.xxxsmall, .postDelimiter): @@ -175,19 +176,19 @@ open class PriceLockup: View { case (.large, .preDelimiter): return UIDevice.isIPad ? .titleMedium : .titleLarge - + case (.large, .postDelimiter): return UIDevice.isIPad ? .titleSmall : .titleMedium - + case (.xlarge, .preDelimiter): return UIDevice.isIPad ? .titleLarge : .titleXLarge - + case (.xlarge, .postDelimiter): return UIDevice.isIPad ? .titleMedium : .titleLarge - + case (.xxlarge, .preDelimiter): return UIDevice.isIPad ? .titleXLarge : .featureSmall - + case (.xxlarge, .postDelimiter): return UIDevice.isIPad ? .titleLarge : .titleXLarge } @@ -204,11 +205,11 @@ open class PriceLockup: View { addSubview(priceLockupLabel) priceLockupLabel.pinToSuperView() } - + /// Used to make changes to the View based off a change events or from local properties. open override func updateView() { super.updateView() - + priceLockupLabel.text = fetchText() priceLockupLabel.surface = surface @@ -224,10 +225,11 @@ open class PriceLockup: View { shouldUpdateView = true setNeedsUpdate() } - + //-------------------------------------------------- // MARK: - Private Methods //-------------------------------------------------- + // Update PriceLockup text attributes func updateLabelAttributes() { var attributes: [any LabelAttributeModel] = [] attributes.append(ColorLabelAttribute(location: 0, @@ -242,6 +244,7 @@ open class PriceLockup: View { textStyle: bold ? textStyle.bold : textStyle.regular, textPosition: .left)) attributes.append(StrikeThroughLabelAttribute(location:strikethroughLocation, length: strikethroughLength)) + } else if uniformSize { // currency and value have the same font text style as delimeter, term, trailing text and superscript. @@ -249,6 +252,7 @@ open class PriceLockup: View { length: priceLockupLabel.text.count, textStyle: bold ? textStyle.bold : textStyle.regular, textPosition: .left)) + } else { // size updates relative to predelimiter, postdelimiter @@ -269,6 +273,7 @@ open class PriceLockup: View { priceLockupLabel.attributes = attributes } + // Get text for PriceLockup. open func fetchText() -> String { var text : String = "" let space = " " @@ -302,6 +307,6 @@ open class PriceLockup: View { extension Float { // remove a decimal from a float if the decimal is equal to 0 var clean: String { - return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self) + return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self) } } From d0c40aaecaf3a4bf868f4a7c487b65f9c24ed43f Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 15 Aug 2024 15:41:46 -0500 Subject: [PATCH 11/14] refactored DefaultValuing to be its own thing Signed-off-by: Matt Bruce --- VDS/Protocols/DefaultValuing.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VDS/Protocols/DefaultValuing.swift b/VDS/Protocols/DefaultValuing.swift index ffeaf0eb..7d156053 100644 --- a/VDS/Protocols/DefaultValuing.swift +++ b/VDS/Protocols/DefaultValuing.swift @@ -7,6 +7,6 @@ import Foundation -public protocol DefaultValuing: Valuing { +public protocol DefaultValuing { static var defaultValue: Self { get } } From 393b791a40261af6045e2ad07d23234fe7615068 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 15 Aug 2024 15:42:10 -0500 Subject: [PATCH 12/14] refactored due to the DefaultValueing change Signed-off-by: Matt Bruce --- VDS/Components/TileContainer/TileContainer.swift | 4 ++-- VDS/Components/Tilelet/Tilelet.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VDS/Components/TileContainer/TileContainer.swift b/VDS/Components/TileContainer/TileContainer.swift index edb369dd..b00d0388 100644 --- a/VDS/Components/TileContainer/TileContainer.swift +++ b/VDS/Components/TileContainer/TileContainer.swift @@ -15,7 +15,7 @@ import Combine open class TileContainer: TileContainerBase { /// Enum used to describe the padding choices used for this component. - public enum Padding: DefaultValuing { + public enum Padding: DefaultValuing, Valuing { case padding3X case padding4X case padding6X @@ -44,7 +44,7 @@ open class TileContainer: TileContainerBase { } } -open class TileContainerBase: View where PaddingType.ValueType == CGFloat { +open class TileContainerBase: View where PaddingType.ValueType == CGFloat { //-------------------------------------------------- // MARK: - Initializers diff --git a/VDS/Components/Tilelet/Tilelet.swift b/VDS/Components/Tilelet/Tilelet.swift index 263d6b77..86dd346a 100644 --- a/VDS/Components/Tilelet/Tilelet.swift +++ b/VDS/Components/Tilelet/Tilelet.swift @@ -20,7 +20,7 @@ import Combine open class Tilelet: TileContainerBase { /// Enum used to describe the padding choices used for this component. - public enum Padding: String, DefaultValuing, CaseIterable { + public enum Padding: String, DefaultValuing, Valuing, CaseIterable { case small case large From a95499b18636377d05da84ba2711906b5b6736f5 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 15 Aug 2024 15:42:28 -0500 Subject: [PATCH 13/14] refactored due to the DefaultValuing update Signed-off-by: Matt Bruce --- VDS/Components/Carousel/Carousel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VDS/Components/Carousel/Carousel.swift b/VDS/Components/Carousel/Carousel.swift index f8d62520..9e14d3d3 100644 --- a/VDS/Components/Carousel/Carousel.swift +++ b/VDS/Components/Carousel/Carousel.swift @@ -58,7 +58,7 @@ open class Carousel: View { } /// Space between each tile. The default value will be 6X in tablet and 3X in mobile. - public enum Gutter: String, CaseIterable , DefaultValuing { + public enum Gutter: String, CaseIterable , DefaultValuing, Valuing { case gutter3X = "3X" case gutter6X = "6X" From 69cfb38149fa4ea439a5cca1e67e3184e4252b2b Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 15 Aug 2024 15:43:01 -0500 Subject: [PATCH 14/14] cleaned up code Signed-off-by: Matt Bruce --- VDS/Components/PriceLockup/PriceLockup.swift | 95 ++++++++++++-------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/VDS/Components/PriceLockup/PriceLockup.swift b/VDS/Components/PriceLockup/PriceLockup.swift index 0c776377..990e5b76 100644 --- a/VDS/Components/PriceLockup/PriceLockup.swift +++ b/VDS/Components/PriceLockup/PriceLockup.swift @@ -32,7 +32,7 @@ open class PriceLockup: View { // MARK: - Enums //-------------------------------------------------- /// Enum used to describe the term of PriceLockup. - public enum Term: String, CaseIterable { + public enum Term: String, DefaultValuing, CaseIterable { case month, year, biennial, none /// The default term is 'month'. @@ -54,38 +54,35 @@ open class PriceLockup: View { } /// Enum that represents the size availble for PriceLockup. - public enum Size: String, CaseIterable { - case xxxsmall - case xxsmall - case xsmall + public enum Size: String, DefaultValuing, CaseIterable { + case xxxsmall = "3XSmall" + case xxsmall = "2XSmall" + case xsmall = "XSmall" case small case medium case large - case xlarge - case xxlarge + case xlarge = "XLarge" + case xxlarge = "2XLarge" public static var defaultValue: Self { .medium } } /// Enum used to describe the kind of PriceLockup. - public enum Kind: String, CaseIterable { + public enum Kind: String, DefaultValuing, CaseIterable { case primary, secondary, savings /// The default kind is 'primary'. public static var defaultValue : Self { .primary } /// Color configuation relative to kind. - public var colorConfiguration: ViewColorConfiguration { + public var colorConfiguration: SurfaceColorConfiguration { switch self { case .primary: - return ViewColorConfiguration().with { - $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false)} + return SurfaceColorConfiguration(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark) case .secondary: - return ViewColorConfiguration().with { - $0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark, forDisabled: false)} + return SurfaceColorConfiguration(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark) case .savings: - return ViewColorConfiguration().with { - $0.setSurfaceColors(VDSColor.paletteGreen26, VDSColor.paletteGreen36, forDisabled: false)} + return SurfaceColorConfiguration(VDSColor.paletteGreen26, VDSColor.paletteGreen36) } } } @@ -107,11 +104,11 @@ open class PriceLockup: View { open var price: Float? { didSet { setNeedsUpdate() } } /// Color to the component. The default kind is primary. - open var kind: Kind = Kind.defaultValue { didSet { setNeedsUpdate() } } + open var kind: Kind = .defaultValue { didSet { setNeedsUpdate() } } /// Size of the component. It varies by size and viewport(mobile/Tablet). /// The default size is medium with viewport mobile. - open var size: Size = Size.defaultValue { didSet { setNeedsUpdate() } } + open var size: Size = .defaultValue { didSet { setNeedsUpdate() } } /// If true, the component with a strikethrough. It applies only when uniformSize is true. /// Does not apply a strikethrough format to leading and trailing text. @@ -119,7 +116,7 @@ open class PriceLockup: View { /// Term text for the component. The default term is 'month'. /// Superscript placement can vary when term and delimeter are "none". - open var term: Term = Term.defaultValue { didSet { setNeedsUpdate() } } + open var term: Term = .defaultValue { didSet { setNeedsUpdate() } } /// Trailing text for the component. open var trailingText: String? { didSet { setNeedsUpdate() } } @@ -210,20 +207,32 @@ open class PriceLockup: View { open override func updateView() { super.updateView() - priceLockupLabel.text = fetchText() + priceLockupLabel.text = formatText() priceLockupLabel.surface = surface // Set the attributed text updateLabelAttributes() } + open override func setDefaults() { + super.setDefaults() + bold = false + hideCurrency = false + leadingText = nil + price = nil + kind = .defaultValue + size = .defaultValue + strikethrough = false + term = .defaultValue + trailingText = nil + superscript = nil + uniformSize = false + } + /// Resets to default settings. open override func reset() { - super.reset() - shouldUpdateView = false priceLockupLabel.reset() - shouldUpdateView = true - setNeedsUpdate() + super.reset() } //-------------------------------------------------- @@ -274,32 +283,44 @@ open class PriceLockup: View { } // Get text for PriceLockup. - open func fetchText() -> String { + private func formatText() -> String { var text : String = "" let space = " " let delimiter = "/" delimiterIndex = 0 strikethroughLength = 0 let currency: String = hideCurrency ? "" : "$" - if let leadingStr = leadingText { - text = text + leadingStr + space - delimiterIndex = delimiterIndex + leadingStr.count + space.count + + if let leadingText { + text.append(leadingText) + text.append(space) + delimiterIndex = delimiterIndex + leadingText.count + space.count } + strikethroughLocation = delimiterIndex - if let value = price { - let valueStr = "\(value.clean)" - text = text + currency + valueStr - delimiterIndex = delimiterIndex + valueStr.count + currency.count - strikethroughLength = valueStr.count + currency.count + + if let price = price?.clean { + text.append(currency) + text.append(price) + delimiterIndex = delimiterIndex + price.count + currency.count + strikethroughLength = price.count + currency.count } + if term != .none { - text = text + delimiter + term.type + text.append(delimiter) + text.append(term.type) strikethroughLength = strikethroughLength + delimiter.count + term.type.count } - if let trailingStr = trailingText { - text = text + space + trailingStr + + if let trailingText { + text.append(space) + text.append(trailingText) } - text = text + (superscript ?? "") + + if let superscript { + text.append(superscript) + } + return text } } @@ -307,6 +328,6 @@ open class PriceLockup: View { extension Float { // remove a decimal from a float if the decimal is equal to 0 var clean: String { - return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self) + return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(describing: self) } }