From 592d2c1f1f0ee5d99aeffc26c716cdc2b73f360c Mon Sep 17 00:00:00 2001 From: Vasavi Kanamarlapudi Date: Wed, 21 Aug 2024 13:39:35 +0530 Subject: [PATCH 01/18] Digital ACT-191 CXTDT-603719 defect: Added fix for pagination caret icon --- VDS/Components/Carousel/Carousel.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/VDS/Components/Carousel/Carousel.swift b/VDS/Components/Carousel/Carousel.swift index 9e14d3d3..e1f32532 100644 --- a/VDS/Components/Carousel/Carousel.swift +++ b/VDS/Components/Carousel/Carousel.swift @@ -162,19 +162,19 @@ open class Carousel: View { /// Previous button to show previous slide. private var previousButton = ButtonIcon().with { $0.kind = .lowContrast - $0.iconName = .leftCaret + $0.iconName = .paginationLeftCaret $0.iconOffset = .init(x: -2, y: 0) $0.customContainerSize = UIDevice.isIPad ? 40 : 28 - $0.icon.customSize = UIDevice.isIPad ? 16 : 12 + $0.customIconSize = UIDevice.isIPad ? 16 : 12 } /// Next button to show next slide. private var nextButton = ButtonIcon().with { $0.kind = .lowContrast - $0.iconName = .rightCaret + $0.iconName = .paginationRightCaret $0.iconOffset = .init(x: 2, y: 0) $0.customContainerSize = UIDevice.isIPad ? 40 : 28 - $0.icon.customSize = UIDevice.isIPad ? 16 : 12 + $0.customIconSize = UIDevice.isIPad ? 16 : 12 } /// A publisher for when moving the carousel. Passes parameters selectedGroupIndex (position). From 030ebdf897cec630bebcae3ea25d53ce8c4b22f2 Mon Sep 17 00:00:00 2001 From: Vasavi Kanamarlapudi Date: Wed, 21 Aug 2024 13:42:48 +0530 Subject: [PATCH 02/18] added release note --- VDS/SupportingFiles/ReleaseNotes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/VDS/SupportingFiles/ReleaseNotes.txt b/VDS/SupportingFiles/ReleaseNotes.txt index c201359e..6d5b4db6 100644 --- a/VDS/SupportingFiles/ReleaseNotes.txt +++ b/VDS/SupportingFiles/ReleaseNotes.txt @@ -3,6 +3,7 @@ - CXTDT-597984 - Table - Text wrap - CXTDT-586372 - Table - Stripes defect - CXTDT-586383 - Table - Line style +- CXTDT-603719 - Carousel - Pagination caret icon 1.0.72 ---------------- From 7536774c0fd0cd27aacefea8c88b01113b17cf9f Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 15:32:20 -0500 Subject: [PATCH 03/18] fixed bug in checkbox getting crushed. Signed-off-by: Matt Bruce --- VDS/BaseClasses/Selector/SelectorBase.swift | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/VDS/BaseClasses/Selector/SelectorBase.swift b/VDS/BaseClasses/Selector/SelectorBase.swift index 6af003fd..fe5cb8fc 100644 --- a/VDS/BaseClasses/Selector/SelectorBase.swift +++ b/VDS/BaseClasses/Selector/SelectorBase.swift @@ -84,9 +84,6 @@ open class SelectorBase: Control, SelectorControlable { open var selectorColorConfiguration = ControlColorConfiguration() { didSet { setNeedsUpdate() } } - /// The natural size for the receiving view, considering only properties of the view itself. - open override var intrinsicContentSize: CGSize { size } - //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- @@ -106,6 +103,16 @@ open class SelectorBase: Control, SelectorControlable { super.setup() isAccessibilityElement = true accessibilityTraits = .button + + let layoutGuide = UILayoutGuide() + addLayoutGuide(layoutGuide) + layoutGuide + .pinTop(0) + .pinLeading(0) + .pinTrailing(0, .defaultHigh) + .pinBottom(0, .defaultHigh) + .width(size.width) + .height(size.height) } open override func setDefaults() { From 012d6b3daf097ff4d23352e7cb87ef88489fed51 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 16:14:21 -0500 Subject: [PATCH 04/18] deleted protocol no longer used Signed-off-by: Matt Bruce --- VDS.xcodeproj/project.pbxproj | 4 ---- VDS/Protocols/Disabling.swift | 14 -------------- 2 files changed, 18 deletions(-) delete mode 100644 VDS/Protocols/Disabling.swift diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index 3e5d50bc..fc3417d2 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -70,7 +70,6 @@ EA33617C288B19210071C351 /* VDSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA33617B288B19210071C351 /* VDSTests.swift */; }; EA33617D288B19210071C351 /* VDS.h in Headers */ = {isa = PBXBuildFile; fileRef = EA33616F288B19200071C351 /* VDS.h */; settings = {ATTRIBUTES = (Public, ); }; }; EA3361A8288B23300071C351 /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA3361A7288B23300071C351 /* UIColor.swift */; }; - EA3361AA288B25E40071C351 /* Disabling.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA3361A9288B25E40071C351 /* Disabling.swift */; }; EA3361AF288B26310071C351 /* FormFieldable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA3361AE288B26310071C351 /* FormFieldable.swift */; }; EA3361B6288B2A410071C351 /* Control.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA3361B5288B2A410071C351 /* Control.swift */; }; EA3361B8288B2AAA0071C351 /* ViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA3361B7288B2AAA0071C351 /* ViewProtocol.swift */; }; @@ -290,7 +289,6 @@ EA336176288B19210071C351 /* VDSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = VDSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; EA33617B288B19210071C351 /* VDSTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VDSTests.swift; sourceTree = ""; }; EA3361A7288B23300071C351 /* UIColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = ""; }; - EA3361A9288B25E40071C351 /* Disabling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Disabling.swift; sourceTree = ""; }; EA3361AE288B26310071C351 /* FormFieldable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormFieldable.swift; sourceTree = ""; }; EA3361B5288B2A410071C351 /* Control.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Control.swift; sourceTree = ""; }; EA3361B7288B2AAA0071C351 /* ViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewProtocol.swift; sourceTree = ""; }; @@ -771,7 +769,6 @@ EAF1FE9829D4850E00101452 /* Clickable.swift */, EAA5EEDF28F49DB3003B3210 /* Colorable.swift */, EAACB8972B92706F006A3869 /* DefaultValuing.swift */, - EA3361A9288B25E40071C351 /* Disabling.swift */, 71BFA7092B7F70E6000DCE33 /* DropShadowable.swift */, EAF978202A99035B00C2FEA9 /* Enabling.swift */, EA5E305929510F8B0082B959 /* EnumSubset.swift */, @@ -1406,7 +1403,6 @@ EAB5FF0129424ACB00998C17 /* UIControl.swift in Sources */, EA985BF5296C60C000F2FF2E /* Icon.swift in Sources */, 1842B1E32BECF0A20021AFCA /* CalendarFooterReusableView.swift in Sources */, - EA3361AA288B25E40071C351 /* Disabling.swift in Sources */, EA3361B6288B2A410071C351 /* Control.swift in Sources */, EAC58C122BED0DDD00BA39FA /* Text.swift in Sources */, 5F21D7BF28DCEB3D003E7CD6 /* Useable.swift in Sources */, diff --git a/VDS/Protocols/Disabling.swift b/VDS/Protocols/Disabling.swift deleted file mode 100644 index 12b938a7..00000000 --- a/VDS/Protocols/Disabling.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// Disabling.swift -// VDS -// -// Created by Matt Bruce on 7/22/22. -// - -import Foundation - -///// Any object that can be disabled, which may change the appearance -//public protocol Disabling { -// /// Whether this object is disabled or not -// var disabled: Bool { get set } -//} From 29714501cc157de3fba274154e3cf2bc21a03901 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 16:14:43 -0500 Subject: [PATCH 05/18] removed disabled form the code Signed-off-by: Matt Bruce --- VDS/Components/Checkbox/CheckboxGroup.swift | 12 ++++++------ VDS/Components/RadioBox/RadioBoxGroup.swift | 12 ++++++------ VDS/Components/RadioButton/RadioButtonGroup.swift | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/VDS/Components/Checkbox/CheckboxGroup.swift b/VDS/Components/Checkbox/CheckboxGroup.swift index 8268f90f..199d9701 100644 --- a/VDS/Components/Checkbox/CheckboxGroup.swift +++ b/VDS/Components/Checkbox/CheckboxGroup.swift @@ -44,7 +44,7 @@ open class CheckboxGroup: SelectorGroupBase, SelectorGroupMultiSel if let selectorModels { items = selectorModels.enumerated().map { index, model in return CheckboxItem().with { - $0.isEnabled = !model.disabled + $0.isEnabled = model.enabled $0.surface = model.surface $0.inputId = model.inputId $0.hiddenValue = model.value @@ -110,8 +110,8 @@ open class CheckboxGroup: SelectorGroupBase, SelectorGroupMultiSel extension CheckboxGroup { public struct CheckboxItemModel : Surfaceable, Initable, Errorable { - /// Whether this object is disabled or not - public var disabled: Bool + /// Whether this object is enabled or not + public var enabled: Bool /// Current Surface and this is used to pass down to child objects that implement Surfacable public var surface: Surface public var inputId: String? @@ -128,8 +128,8 @@ extension CheckboxGroup { public var showError: Bool public var errorText: String? - public init(disabled: Bool, surface: Surface = .light, inputId: String? = nil, value: AnyHashable? = nil, accessibileText: String? = nil, labelText: String? = nil, labelTextAttributes: [any LabelAttributeModel]? = nil, childText: String? = nil, childTextAttributes: [any LabelAttributeModel]? = nil, selected: Bool = false, showError: Bool = false, errorText: String? = nil) { - self.disabled = disabled + public init(enabled: Bool, surface: Surface = .light, inputId: String? = nil, value: AnyHashable? = nil, accessibileText: String? = nil, labelText: String? = nil, labelTextAttributes: [any LabelAttributeModel]? = nil, childText: String? = nil, childTextAttributes: [any LabelAttributeModel]? = nil, selected: Bool = false, showError: Bool = false, errorText: String? = nil) { + self.enabled = enabled self.surface = surface self.inputId = inputId self.value = value @@ -144,7 +144,7 @@ extension CheckboxGroup { } public init() { - self.init(disabled: false) + self.init(enabled: false) } } diff --git a/VDS/Components/RadioBox/RadioBoxGroup.swift b/VDS/Components/RadioBox/RadioBoxGroup.swift index 000e3433..425a416b 100644 --- a/VDS/Components/RadioBox/RadioBoxGroup.swift +++ b/VDS/Components/RadioBox/RadioBoxGroup.swift @@ -49,7 +49,7 @@ open class RadioBoxGroup: SelectorGroupBase, SelectorGroupSingleSe $0.subTextAttributes = model.subTextAttributes $0.subTextRight = model.subTextRight $0.subTextRightAttributes = model.subTextRightAttributes - $0.isEnabled = !model.disabled + $0.isEnabled = model.enabled $0.inputId = model.inputId $0.hiddenValue = model.value $0.isSelected = model.selected @@ -114,8 +114,8 @@ open class RadioBoxGroup: SelectorGroupBase, SelectorGroupSingleSe extension RadioBoxGroup { public struct RadioBoxItemModel: Surfaceable, Initable, FormFieldable { - /// Whether this object is disabled or not - public var disabled: Bool + /// Whether this object is enabled or not + public var enabled: Bool /// Current Surface and this is used to pass down to child objects that implement Surfacable public var surface: Surface public var inputId: String? @@ -134,12 +134,12 @@ extension RadioBoxGroup { public var strikethrough: Bool = false public var strikethroughAccessibileText: String - public init(disabled: Bool, surface: Surface = .light, inputId: String? = nil, value: String? = nil, + public init(enabled: Bool, surface: Surface = .light, inputId: String? = nil, value: String? = nil, text: String = "", textAttributes: [any LabelAttributeModel]? = nil, subText: String? = nil, subTextAttributes: [any LabelAttributeModel]? = nil, subTextRight: String? = nil, subTextRightAttributes: [any LabelAttributeModel]? = nil, selected: Bool = false, errorText: String? = nil, accessibileText: String? = nil, strikethrough: Bool = false, strikethroughAccessibileText: String = "not available") { - self.disabled = disabled + self.enabled = enabled self.surface = surface self.inputId = inputId self.value = value @@ -156,7 +156,7 @@ extension RadioBoxGroup { } public init() { - self.init(disabled: false) + self.init(enabled: false) } } } diff --git a/VDS/Components/RadioButton/RadioButtonGroup.swift b/VDS/Components/RadioButton/RadioButtonGroup.swift index 5d323997..0cccbe06 100644 --- a/VDS/Components/RadioButton/RadioButtonGroup.swift +++ b/VDS/Components/RadioButton/RadioButtonGroup.swift @@ -43,7 +43,7 @@ open class RadioButtonGroup: SelectorGroupBase, SelectorGroupSi if let selectorModels { items = selectorModels.enumerated().map { index, model in return RadioButtonItem().with { - $0.isEnabled = !model.disabled + $0.isEnabled = model.enabled $0.surface = model.surface $0.inputId = model.inputId $0.hiddenValue = model.value @@ -105,8 +105,8 @@ open class RadioButtonGroup: SelectorGroupBase, SelectorGroupSi extension RadioButtonGroup { public struct RadioButtonItemModel: Surfaceable, Initable, FormFieldable, Errorable { - /// Whether this object is disabled or not - public var disabled: Bool + /// Whether this object is enabled or not + public var enabled: Bool /// Current Surface and this is used to pass down to child objects that implement Surfacable public var surface: Surface public var inputId: String? @@ -123,8 +123,8 @@ extension RadioButtonGroup { public var showError: Bool public var errorText: String? - public init(disabled: Bool, surface: Surface = .light, inputId: String? = nil, value: AnyHashable? = nil, accessibileText: String? = nil, labelText: String? = nil, labelTextAttributes: [any LabelAttributeModel]? = nil, childText: String? = nil, childTextAttributes: [any LabelAttributeModel]? = nil, selected: Bool = false, showError: Bool = false, errorText: String? = nil) { - self.disabled = disabled + public init(enabled: Bool, surface: Surface = .light, inputId: String? = nil, value: AnyHashable? = nil, accessibileText: String? = nil, labelText: String? = nil, labelTextAttributes: [any LabelAttributeModel]? = nil, childText: String? = nil, childTextAttributes: [any LabelAttributeModel]? = nil, selected: Bool = false, showError: Bool = false, errorText: String? = nil) { + self.enabled = enabled self.surface = surface self.inputId = inputId self.value = value @@ -139,7 +139,7 @@ extension RadioButtonGroup { } public init() { - self.init(disabled: false) + self.init(enabled: false) } } } From b9ae68ab206748f2458e81a488b405040de61a3c Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 16:24:40 -0500 Subject: [PATCH 06/18] default enabled = true Signed-off-by: Matt Bruce --- VDS/Components/Checkbox/CheckboxGroup.swift | 2 +- VDS/Components/RadioBox/RadioBoxGroup.swift | 2 +- VDS/Components/RadioButton/RadioButtonGroup.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VDS/Components/Checkbox/CheckboxGroup.swift b/VDS/Components/Checkbox/CheckboxGroup.swift index 199d9701..f2a62efa 100644 --- a/VDS/Components/Checkbox/CheckboxGroup.swift +++ b/VDS/Components/Checkbox/CheckboxGroup.swift @@ -144,7 +144,7 @@ extension CheckboxGroup { } public init() { - self.init(enabled: false) + self.init(enabled: true) } } diff --git a/VDS/Components/RadioBox/RadioBoxGroup.swift b/VDS/Components/RadioBox/RadioBoxGroup.swift index 425a416b..3b17d7d8 100644 --- a/VDS/Components/RadioBox/RadioBoxGroup.swift +++ b/VDS/Components/RadioBox/RadioBoxGroup.swift @@ -156,7 +156,7 @@ extension RadioBoxGroup { } public init() { - self.init(enabled: false) + self.init(enabled: true) } } } diff --git a/VDS/Components/RadioButton/RadioButtonGroup.swift b/VDS/Components/RadioButton/RadioButtonGroup.swift index 0cccbe06..8bde87de 100644 --- a/VDS/Components/RadioButton/RadioButtonGroup.swift +++ b/VDS/Components/RadioButton/RadioButtonGroup.swift @@ -139,7 +139,7 @@ extension RadioButtonGroup { } public init() { - self.init(enabled: false) + self.init(enabled: true) } } } From d336b8dfda6a0e40572816b37be3394d7b2c66df Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 15:11:12 -0500 Subject: [PATCH 07/18] trying to deal with rendering issues Signed-off-by: Matt Bruce --- VDS/BaseClasses/Selector/SelectorBase.swift | 4 +++- VDS/BaseClasses/Selector/SelectorGroupBase.swift | 3 ++- VDS/BaseClasses/Selector/SelectorItemBase.swift | 3 ++- VDS/Components/RadioBox/RadioBoxItem.swift | 3 ++- VDS/Protocols/ViewProtocol.swift | 11 +++++++++++ 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/VDS/BaseClasses/Selector/SelectorBase.swift b/VDS/BaseClasses/Selector/SelectorBase.swift index 6af003fd..2d12cf07 100644 --- a/VDS/BaseClasses/Selector/SelectorBase.swift +++ b/VDS/BaseClasses/Selector/SelectorBase.swift @@ -30,7 +30,9 @@ public protocol SelectorControlable: Control, Changeable { /// Base Class used to build out a Selector control. @objcMembers @objc(VDSSelectorBase) -open class SelectorBase: Control, SelectorControlable { +open class SelectorBase: Control, SelectorControlable, ParentViewProtocol { + public var children: [any ViewProtocol] { [selectorView] } + //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- diff --git a/VDS/BaseClasses/Selector/SelectorGroupBase.swift b/VDS/BaseClasses/Selector/SelectorGroupBase.swift index e04b5e5a..ebb0512b 100644 --- a/VDS/BaseClasses/Selector/SelectorGroupBase.swift +++ b/VDS/BaseClasses/Selector/SelectorGroupBase.swift @@ -39,7 +39,8 @@ extension SelectorGroupSingleSelect { } /// Base Class used for any Grouped Form Control of a Selector Type. -open class SelectorGroupBase: Control, SelectorGroup, Changeable { +open class SelectorGroupBase: Control, SelectorGroup, Changeable, ParentViewProtocol { + public var children: [any ViewProtocol] { items } //-------------------------------------------------- // MARK: - Private Properties diff --git a/VDS/BaseClasses/Selector/SelectorItemBase.swift b/VDS/BaseClasses/Selector/SelectorItemBase.swift index ea037771..d2ccc293 100644 --- a/VDS/BaseClasses/Selector/SelectorItemBase.swift +++ b/VDS/BaseClasses/Selector/SelectorItemBase.swift @@ -11,7 +11,8 @@ import Combine import VDSCoreTokens /// Base Class used to build out a SelectorControlable control. -open class SelectorItemBase: Control, Errorable, Changeable, Groupable { +open class SelectorItemBase: Control, Errorable, Changeable, Groupable, ParentViewProtocol { + public var children: [any ViewProtocol] { [label, childLabel, errorLabel, selectorView] } //-------------------------------------------------- // MARK: - Initializers diff --git a/VDS/Components/RadioBox/RadioBoxItem.swift b/VDS/Components/RadioBox/RadioBoxItem.swift index a5ca1d8b..b8530363 100644 --- a/VDS/Components/RadioBox/RadioBoxItem.swift +++ b/VDS/Components/RadioBox/RadioBoxItem.swift @@ -14,7 +14,8 @@ import VDSCoreTokens /// that are used within a ``RadioBoxGroup``. @objcMembers @objc(VDSRadioBoxItem) -open class RadioBoxItem: Control, Changeable, FormFieldable, Groupable { +open class RadioBoxItem: Control, Changeable, FormFieldable, Groupable, ParentViewProtocol { + public var children: [any ViewProtocol] { [textLabel, subTextLabel, subTextRightLabel, selectorView] } //-------------------------------------------------- // MARK: - Initializers diff --git a/VDS/Protocols/ViewProtocol.swift b/VDS/Protocols/ViewProtocol.swift index 9a509dc1..b282062a 100644 --- a/VDS/Protocols/ViewProtocol.swift +++ b/VDS/Protocols/ViewProtocol.swift @@ -9,6 +9,10 @@ import Foundation import UIKit import Combine +public protocol ParentViewProtocol { + var children: [any ViewProtocol] { get } +} + public protocol ViewProtocol: AnyObject, Initable, Resettable, Enabling, Surfaceable, AccessibilityUpdatable { /// Set of Subscribers for any Publishers for this Control. var subscribers: Set { get set } @@ -38,8 +42,15 @@ extension ViewProtocol { public func setNeedsUpdate() { if shouldUpdateView { shouldUpdateView = false + //let parent = self as? ParentViewProtocol + //parent?.children.forEach{ $0.shouldUpdateView = false } updateView() updateAccessibility() +// parent?.children.forEach{ +// $0.updateView() +// $0.updateAccessibility() +// $0.shouldUpdateView = true +// } shouldUpdateView = true } } From c41599578a99d1b58022473602c3852fbf7ecf27 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 16:03:47 -0500 Subject: [PATCH 08/18] added ParentViewProtocol to views and updated children Signed-off-by: Matt Bruce --- VDS/BaseClasses/Selector/SelectorBase.swift | 3 ++- VDS/BaseClasses/Selector/SelectorGroupBase.swift | 3 ++- VDS/BaseClasses/Selector/SelectorItemBase.swift | 5 +++-- VDS/Components/Badge/Badge.swift | 4 +++- VDS/Components/BadgeIndicator/BadgeIndicator.swift | 4 +++- VDS/Components/Breadcrumbs/Breadcrumbs.swift | 4 +++- VDS/Components/DatePicker/DatePicker.swift | 6 ++++++ VDS/Components/DropdownSelect/DropdownSelect.swift | 2 +- VDS/Components/Icon/ButtonIcon/ButtonIcon.swift | 4 +++- VDS/Components/InputStepper/InputStepper.swift | 6 ++++++ VDS/Components/Notification/Notification.swift | 4 +++- VDS/Components/PriceLockup/PriceLockup.swift | 3 ++- VDS/Components/RadioBox/RadioBoxItem.swift | 3 ++- VDS/Components/Tabs/Tabs.swift | 4 +++- VDS/Components/TextFields/EntryFieldBase.swift | 4 +++- VDS/Components/TileContainer/TileContainer.swift | 10 +++++----- VDS/Components/Tilelet/Tilelet.swift | 4 +++- VDS/Components/TitleLockup/TitleLockup.swift | 4 +++- VDS/Components/Toggle/Toggle.swift | 4 +++- VDS/Components/Tooltip/TooltipDialog.swift | 4 +++- VDS/Protocols/ViewProtocol.swift | 14 +++++++------- 21 files changed, 69 insertions(+), 30 deletions(-) diff --git a/VDS/BaseClasses/Selector/SelectorBase.swift b/VDS/BaseClasses/Selector/SelectorBase.swift index 2d12cf07..97e72afd 100644 --- a/VDS/BaseClasses/Selector/SelectorBase.swift +++ b/VDS/BaseClasses/Selector/SelectorBase.swift @@ -31,7 +31,6 @@ public protocol SelectorControlable: Control, Changeable { @objcMembers @objc(VDSSelectorBase) open class SelectorBase: Control, SelectorControlable, ParentViewProtocol { - public var children: [any ViewProtocol] { [selectorView] } //-------------------------------------------------- // MARK: - Initializers @@ -51,6 +50,8 @@ open class SelectorBase: Control, SelectorControlable, ParentViewProtocol { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [selectorView] } + open var onChangeSubscriber: AnyCancellable? open var size = CGSize(width: 20, height: 20) { didSet { setNeedsUpdate() } } diff --git a/VDS/BaseClasses/Selector/SelectorGroupBase.swift b/VDS/BaseClasses/Selector/SelectorGroupBase.swift index ebb0512b..63556c95 100644 --- a/VDS/BaseClasses/Selector/SelectorGroupBase.swift +++ b/VDS/BaseClasses/Selector/SelectorGroupBase.swift @@ -40,7 +40,6 @@ extension SelectorGroupSingleSelect { /// Base Class used for any Grouped Form Control of a Selector Type. open class SelectorGroupBase: Control, SelectorGroup, Changeable, ParentViewProtocol { - public var children: [any ViewProtocol] { items } //-------------------------------------------------- // MARK: - Private Properties @@ -58,6 +57,8 @@ open class SelectorGroupBase: Control, SelectorGrou //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { items } + /// Array of the HandlerType registered. /// Array of HandlerType that the user will have the ability to select from. open var items: [SelectorItemType] = [] { diff --git a/VDS/BaseClasses/Selector/SelectorItemBase.swift b/VDS/BaseClasses/Selector/SelectorItemBase.swift index d2ccc293..321df2a8 100644 --- a/VDS/BaseClasses/Selector/SelectorItemBase.swift +++ b/VDS/BaseClasses/Selector/SelectorItemBase.swift @@ -12,7 +12,6 @@ import VDSCoreTokens /// Base Class used to build out a SelectorControlable control. open class SelectorItemBase: Control, Errorable, Changeable, Groupable, ParentViewProtocol { - public var children: [any ViewProtocol] { [label, childLabel, errorLabel, selectorView] } //-------------------------------------------------- // MARK: - Initializers @@ -62,7 +61,9 @@ open class SelectorItemBase: Control, Errorable, Changea //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- - open var onChangeSubscriber: AnyCancellable? + open var children: [any ViewProtocol] { [label, childLabel, errorLabel, selectorView] } + + open var onChangeSubscriber: AnyCancellable? /// Label used to render labelText. open var label = Label().with { diff --git a/VDS/Components/Badge/Badge.swift b/VDS/Components/Badge/Badge.swift index 1c47133f..19c40bbc 100644 --- a/VDS/Components/Badge/Badge.swift +++ b/VDS/Components/Badge/Badge.swift @@ -17,7 +17,7 @@ import Combine /// to its parent this object will stretch to the parent's width. @objcMembers @objc(VDSBadge) -open class Badge: View { +open class Badge: View, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -45,6 +45,8 @@ open class Badge: View { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [label] } + /// Label used to render text open var label = Label().with { $0.isAccessibilityElement = false diff --git a/VDS/Components/BadgeIndicator/BadgeIndicator.swift b/VDS/Components/BadgeIndicator/BadgeIndicator.swift index daecddf4..403c7d46 100644 --- a/VDS/Components/BadgeIndicator/BadgeIndicator.swift +++ b/VDS/Components/BadgeIndicator/BadgeIndicator.swift @@ -13,7 +13,7 @@ import Combine /// A badge indicator is a visual label used to convey status or highlight supplemental information. @objcMembers @objc(VDSBadgeIndicator) -open class BadgeIndicator: View { +open class BadgeIndicator: View, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -135,6 +135,8 @@ open class BadgeIndicator: View { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [label, badgeView] } + /// Label used for the numeric kind. open var label = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) diff --git a/VDS/Components/Breadcrumbs/Breadcrumbs.swift b/VDS/Components/Breadcrumbs/Breadcrumbs.swift index 808b5548..938a22a4 100644 --- a/VDS/Components/Breadcrumbs/Breadcrumbs.swift +++ b/VDS/Components/Breadcrumbs/Breadcrumbs.swift @@ -15,11 +15,13 @@ import Combine /// Breadcrumbs are secondary navigation that use a hierarchy of internal links to tell customers where they are in an experience. Each breadcrumb links to its respective page, except for that of current page. @objcMembers @objc(VDSBreadcrumbs) -open class Breadcrumbs: View { +open class Breadcrumbs: View, ParentViewProtocol { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { breadcrumbs } + /// Array of ``BreadcrumbItem`` views for the Breadcrumbs. open var breadcrumbs: [BreadcrumbItem] = [] { didSet { setNeedsUpdate() } } diff --git a/VDS/Components/DatePicker/DatePicker.swift b/VDS/Components/DatePicker/DatePicker.swift index e9137ad9..bd53a2a2 100644 --- a/VDS/Components/DatePicker/DatePicker.swift +++ b/VDS/Components/DatePicker/DatePicker.swift @@ -94,6 +94,12 @@ open class DatePicker: EntryFieldBase { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open override var children: [any ViewProtocol] { + var current = super.children + current.append(selectedDateLabel) + return current + } + open var calendarIcon = Icon().with { $0.name = .calendar $0.size = .medium diff --git a/VDS/Components/DropdownSelect/DropdownSelect.swift b/VDS/Components/DropdownSelect/DropdownSelect.swift index 2c243a26..98a5a61f 100644 --- a/VDS/Components/DropdownSelect/DropdownSelect.swift +++ b/VDS/Components/DropdownSelect/DropdownSelect.swift @@ -31,7 +31,7 @@ open class DropdownSelect: EntryFieldBase { //-------------------------------------------------- // MARK: - Public Properties - //-------------------------------------------------- + //-------------------------------------------------- /// If true, the label will be displayed inside the dropdown containerView. Otherwise, the label will be above the dropdown containerView like a normal text input. open var showInlineLabel: Bool = false { didSet { setNeedsUpdate() }} diff --git a/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift b/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift index b6b51601..92be222d 100644 --- a/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift +++ b/VDS/Components/Icon/ButtonIcon/ButtonIcon.swift @@ -14,7 +14,7 @@ import Combine /// It usually represents a supplementary or utilitarian action. A button icon can stand alone, but often /// exists in a group when there are several actions that can be performed. @objc(VDSButtonIcon) -open class ButtonIcon: Control, Changeable { +open class ButtonIcon: Control, Changeable, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -109,6 +109,8 @@ open class ButtonIcon: Control, Changeable { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [icon] } + public var onChangeSubscriber: AnyCancellable? ///Badge Indicator object used to render for the ButtonIcon. diff --git a/VDS/Components/InputStepper/InputStepper.swift b/VDS/Components/InputStepper/InputStepper.swift index 6c44b58f..1323bd25 100644 --- a/VDS/Components/InputStepper/InputStepper.swift +++ b/VDS/Components/InputStepper/InputStepper.swift @@ -70,6 +70,12 @@ open class InputStepper: EntryFieldBase { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open override var children: [any ViewProtocol] { + var current = super.children + current.append(contentsOf: [decrementButton, incrementButton, textLabel]) + return current + } + /// If there is a width that is larger than this size's minimumWidth, the input stepper will resize to this width. open var controlWidth: ControlWidth? { get { _controlWidth } diff --git a/VDS/Components/Notification/Notification.swift b/VDS/Components/Notification/Notification.swift index 59d2b78f..0fb05caa 100644 --- a/VDS/Components/Notification/Notification.swift +++ b/VDS/Components/Notification/Notification.swift @@ -16,7 +16,7 @@ import Combine /// experience-wide. @objcMembers @objc(VDSNotification) -open class Notification: View { +open class Notification: View, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -101,6 +101,8 @@ open class Notification: View { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [typeIcon, closeButton, titleLabel, subTitleLabel, primaryButton, secondaryButton] } + /// Icon used for denoting type. open var typeIcon = Icon().with { $0.name = .infoBold diff --git a/VDS/Components/PriceLockup/PriceLockup.swift b/VDS/Components/PriceLockup/PriceLockup.swift index 990e5b76..d36fe7ee 100644 --- a/VDS/Components/PriceLockup/PriceLockup.swift +++ b/VDS/Components/PriceLockup/PriceLockup.swift @@ -11,7 +11,7 @@ import VDSCoreTokens @objcMembers @objc(VDSPriceLockup) -open class PriceLockup: View { +open class PriceLockup: View, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -90,6 +90,7 @@ open class PriceLockup: View { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [priceLockupLabel] } /// If true, the component will render as bold. open var bold: Bool = false { didSet { setNeedsUpdate() } } diff --git a/VDS/Components/RadioBox/RadioBoxItem.swift b/VDS/Components/RadioBox/RadioBoxItem.swift index b8530363..695b1261 100644 --- a/VDS/Components/RadioBox/RadioBoxItem.swift +++ b/VDS/Components/RadioBox/RadioBoxItem.swift @@ -15,7 +15,6 @@ import VDSCoreTokens @objcMembers @objc(VDSRadioBoxItem) open class RadioBoxItem: Control, Changeable, FormFieldable, Groupable, ParentViewProtocol { - public var children: [any ViewProtocol] { [textLabel, subTextLabel, subTextRightLabel, selectorView] } //-------------------------------------------------- // MARK: - Initializers @@ -54,6 +53,8 @@ open class RadioBoxItem: Control, Changeable, FormFieldable, Groupable, ParentVi //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [textLabel, subTextLabel, subTextRightLabel, selectorView] } + open var onChangeSubscriber: AnyCancellable? /// Label used to render the text. diff --git a/VDS/Components/Tabs/Tabs.swift b/VDS/Components/Tabs/Tabs.swift index ac9e7269..fe967338 100644 --- a/VDS/Components/Tabs/Tabs.swift +++ b/VDS/Components/Tabs/Tabs.swift @@ -12,7 +12,7 @@ import VDSCoreTokens /// Tabs are organizational components that group content and allow customers to navigate its display. Use them to separate content when the content is related but doesn’t need to be compared. @objcMembers @objc(VDSTabs) -open class Tabs: View { +open class Tabs: View, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -84,6 +84,8 @@ open class Tabs: View { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { tabViews } + /// A callback when the selectedIndex changes. Passes parameters (tabIndex). open var onTabDidSelect: ((Int) -> Void)? diff --git a/VDS/Components/TextFields/EntryFieldBase.swift b/VDS/Components/TextFields/EntryFieldBase.swift index 0a815e08..8d4aeadc 100644 --- a/VDS/Components/TextFields/EntryFieldBase.swift +++ b/VDS/Components/TextFields/EntryFieldBase.swift @@ -11,7 +11,7 @@ import VDSCoreTokens import Combine /// Base Class used to build out a Input controls. -open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable { +open class EntryFieldBase: Control, Changeable, FormFieldInternalValidatable, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- @@ -155,6 +155,8 @@ open class EntryFieldBase: Control, Changeable, FormFieldInternalVali //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [titleLabel, helperLabel, errorLabel, statusIcon] } + /// This is the view that will be wrapped with the border for userInteraction. /// The only subview of this view is the fieldStackView open var containerView = View().with { diff --git a/VDS/Components/TileContainer/TileContainer.swift b/VDS/Components/TileContainer/TileContainer.swift index b00d0388..6c695112 100644 --- a/VDS/Components/TileContainer/TileContainer.swift +++ b/VDS/Components/TileContainer/TileContainer.swift @@ -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 @@ -122,7 +122,7 @@ open class TileContainerBase: View where //-------------------------------------------------- // MARK: - Public Properties - //-------------------------------------------------- + //-------------------------------------------------- /// This takes an image source url and applies it as a background image. open var backgroundImage: UIImage? { didSet { setNeedsUpdate() } } @@ -340,21 +340,21 @@ open class TileContainerBase: View where open override func touchesBegan(_ touches: Set, with event: UIEvent?) { super.touchesBegan(touches, with: event) - if let onClickSubscriber { + if onClickSubscriber != nil { isHighlighted = true } } open override func touchesEnded(_ touches: Set, with event: UIEvent?) { super.touchesEnded(touches, with: event) - if let onClickSubscriber { + if onClickSubscriber != nil { isHighlighted = false } } open override func touchesCancelled(_ touches: Set, with event: UIEvent?) { super.touchesCancelled(touches, with: event) - if let onClickSubscriber { + if onClickSubscriber != nil { isHighlighted = false } } diff --git a/VDS/Components/Tilelet/Tilelet.swift b/VDS/Components/Tilelet/Tilelet.swift index cb154056..3a6e0150 100644 --- a/VDS/Components/Tilelet/Tilelet.swift +++ b/VDS/Components/Tilelet/Tilelet.swift @@ -17,7 +17,7 @@ import Combine /// function. @objcMembers @objc(VDSTilelet) -open class Tilelet: TileContainerBase { +open class Tilelet: TileContainerBase, ParentViewProtocol { /// Enum used to describe the padding choices used for this component. public enum Padding: String, DefaultValuing, Valuing, CaseIterable { @@ -110,6 +110,8 @@ open class Tilelet: TileContainerBase { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [badge, titleLockup, descriptiveIcon, directionalIcon] } + /// Title lockup positioned in the contentView. open var titleLockup = TitleLockup().with { $0.standardStyleConfiguration = .init(styleConfigurations: [ diff --git a/VDS/Components/TitleLockup/TitleLockup.swift b/VDS/Components/TitleLockup/TitleLockup.swift index 1711939c..ad56813b 100644 --- a/VDS/Components/TitleLockup/TitleLockup.swift +++ b/VDS/Components/TitleLockup/TitleLockup.swift @@ -14,7 +14,7 @@ import Combine /// with approved built in text size configurations. @objcMembers @objc(VDSTitleLockup) -open class TitleLockup: View { +open class TitleLockup: View, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -62,6 +62,8 @@ open class TitleLockup: View { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [eyebrowLabel, titleLabel, subTitleLabel] } + /// Aligns TitleLockup's subcomponent's text open var textAlignment: TextAlignment = .left { didSet { setNeedsUpdate() } } diff --git a/VDS/Components/Toggle/Toggle.swift b/VDS/Components/Toggle/Toggle.swift index 304b18ce..8c11004b 100644 --- a/VDS/Components/Toggle/Toggle.swift +++ b/VDS/Components/Toggle/Toggle.swift @@ -14,7 +14,7 @@ import Combine /// or turn off a single option, setting or function. @objcMembers @objc(VDSToggle) -open class Toggle: Control, Changeable, FormFieldable { +open class Toggle: Control, Changeable, FormFieldable, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -90,6 +90,8 @@ open class Toggle: Control, Changeable, FormFieldable { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [toggleView, label] } + open var onChangeSubscriber: AnyCancellable? /// Actual toggle used in this component. diff --git a/VDS/Components/Tooltip/TooltipDialog.swift b/VDS/Components/Tooltip/TooltipDialog.swift index bb6b5653..bbccb8f5 100644 --- a/VDS/Components/Tooltip/TooltipDialog.swift +++ b/VDS/Components/Tooltip/TooltipDialog.swift @@ -11,7 +11,7 @@ import VDSCoreTokens @objcMembers @objc(VDSTooltipDialog) -open class TooltipDialog: View, UIScrollViewDelegate { +open class TooltipDialog: View, UIScrollViewDelegate, ParentViewProtocol { //-------------------------------------------------- // MARK: - Initializers @@ -55,6 +55,8 @@ open class TooltipDialog: View, UIScrollViewDelegate { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + open var children: [any ViewProtocol] { [titleLabel, contentLabel] } + open var tooltipModel = Tooltip.TooltipModel() { didSet { setNeedsUpdate() } } open var titleLabel = Label().with { label in diff --git a/VDS/Protocols/ViewProtocol.swift b/VDS/Protocols/ViewProtocol.swift index b282062a..e38d5df4 100644 --- a/VDS/Protocols/ViewProtocol.swift +++ b/VDS/Protocols/ViewProtocol.swift @@ -42,15 +42,15 @@ extension ViewProtocol { public func setNeedsUpdate() { if shouldUpdateView { shouldUpdateView = false - //let parent = self as? ParentViewProtocol - //parent?.children.forEach{ $0.shouldUpdateView = false } + let parent = self as? ParentViewProtocol + parent?.children.forEach{ $0.shouldUpdateView = false } updateView() updateAccessibility() -// parent?.children.forEach{ -// $0.updateView() -// $0.updateAccessibility() -// $0.shouldUpdateView = true -// } + parent?.children.forEach{ + $0.updateView() + $0.updateAccessibility() + $0.shouldUpdateView = true + } shouldUpdateView = true } } From 952d688cc2729fa8f16710bc5668b743e4eda0fe Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 23 Aug 2024 08:35:36 -0500 Subject: [PATCH 09/18] updated with traversal Signed-off-by: Matt Bruce --- VDS/Protocols/ViewProtocol.swift | 34 ++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/VDS/Protocols/ViewProtocol.swift b/VDS/Protocols/ViewProtocol.swift index e38d5df4..4eb091b1 100644 --- a/VDS/Protocols/ViewProtocol.swift +++ b/VDS/Protocols/ViewProtocol.swift @@ -9,10 +9,28 @@ import Foundation import UIKit import Combine -public protocol ParentViewProtocol { +public protocol ParentViewProtocol: ViewProtocol { var children: [any ViewProtocol] { get } } +extension ParentViewProtocol { + public func getAllChildren() -> [any ViewProtocol] { + var allChildren = [any ViewProtocol]() + + func traverse(view: any ViewProtocol) { + if let parentView = view as? any ParentViewProtocol { + for child in parentView.children { + allChildren.append(child) + traverse(view: child) + } + } + } + + traverse(view: self) + return children + } +} + public protocol ViewProtocol: AnyObject, Initable, Resettable, Enabling, Surfaceable, AccessibilityUpdatable { /// Set of Subscribers for any Publishers for this Control. var subscribers: Set { get set } @@ -42,11 +60,19 @@ extension ViewProtocol { public func setNeedsUpdate() { if shouldUpdateView { shouldUpdateView = false - let parent = self as? ParentViewProtocol - parent?.children.forEach{ $0.shouldUpdateView = false } + + //see if this is a view that has children + let parent = self as? any ParentViewProtocol + let children = parent?.getAllChildren() + //if so turn off the shouldUpdate to keep UI + //from blocking + children?.forEach{ $0.shouldUpdateView = false } + updateView() updateAccessibility() - parent?.children.forEach{ + + //if so turn on + children?.forEach{ $0.updateView() $0.updateAccessibility() $0.shouldUpdateView = true From b3f602087d3c9691ec3efcce9d24def3713e797d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 23 Aug 2024 08:39:18 -0500 Subject: [PATCH 10/18] refactored into a new file with traversal Signed-off-by: Matt Bruce --- VDS.xcodeproj/project.pbxproj | 4 +++ VDS/Protocols/ParentViewProtocol.swift | 37 ++++++++++++++++++++++++++ VDS/Protocols/ViewProtocol.swift | 22 --------------- 3 files changed, 41 insertions(+), 22 deletions(-) create mode 100644 VDS/Protocols/ParentViewProtocol.swift diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index fc3417d2..34b75bda 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -101,6 +101,7 @@ EA6642952BCEBF9500D81DC4 /* TextLinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6642942BCEBF9500D81DC4 /* TextLinkModel.swift */; }; EA6F330E2B911E9000BACAB9 /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6F330D2B911E9000BACAB9 /* TextView.swift */; }; EA78C7962C00CAC200430AD1 /* Groupable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA78C7952C00CAC200430AD1 /* Groupable.swift */; }; + EA7AE5592C78C7D000107C74 /* ParentViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE5582C78C7D000107C74 /* ParentViewProtocol.swift */; }; EA81410B2A0E8E3C004F60D2 /* ButtonIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA81410A2A0E8E3C004F60D2 /* ButtonIcon.swift */; }; EA8141102A127066004F60D2 /* UIColor+VDSColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA81410F2A127066004F60D2 /* UIColor+VDSColor.swift */; }; EA89200428AECF4B006B9984 /* UITextField+Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA89200328AECF4B006B9984 /* UITextField+Publisher.swift */; }; @@ -323,6 +324,7 @@ EA78C7952C00CAC200430AD1 /* Groupable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Groupable.swift; sourceTree = ""; }; EA78C7A12C0E63D200430AD1 /* vds-dev.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "vds-dev.xcconfig"; sourceTree = ""; }; EA78C7A22C0E63DD00430AD1 /* vds.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = vds.xcconfig; sourceTree = ""; }; + EA7AE5582C78C7D000107C74 /* ParentViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParentViewProtocol.swift; sourceTree = ""; }; EA81410A2A0E8E3C004F60D2 /* ButtonIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIcon.swift; sourceTree = ""; }; EA81410F2A127066004F60D2 /* UIColor+VDSColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+VDSColor.swift"; sourceTree = ""; }; EA89200328AECF4B006B9984 /* UITextField+Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextField+Publisher.swift"; sourceTree = ""; }; @@ -777,6 +779,7 @@ EA78C7952C00CAC200430AD1 /* Groupable.swift */, EA33624628931B050071C351 /* Initable.swift */, EA471F392A95587500CE9E58 /* LayoutConstraintable.swift */, + EA7AE5582C78C7D000107C74 /* ParentViewProtocol.swift */, EA985C7C297DAED300F2FF2E /* Primitive.swift */, EAF7F0A5289B0CE000B287F5 /* Resetable.swift */, EA3361C8289054C50071C351 /* Surfaceable.swift */, @@ -1335,6 +1338,7 @@ EAF7F0A4289B017C00B287F5 /* LabelAttributeModel.swift in Sources */, EA0B18022A9E236900F2D0CD /* SelectorGroupBase.swift in Sources */, EA5F86D02A1F936100BC83E4 /* TabsContainer.swift in Sources */, + EA7AE5592C78C7D000107C74 /* ParentViewProtocol.swift in Sources */, EAF7F0B1289B177F00B287F5 /* ColorLabelAttribute.swift in Sources */, EAC9258F2911C9DE00091998 /* EntryFieldBase.swift in Sources */, 18B9763F2C11BA4A009271DF /* CarouselPaginationModel.swift in Sources */, diff --git a/VDS/Protocols/ParentViewProtocol.swift b/VDS/Protocols/ParentViewProtocol.swift new file mode 100644 index 00000000..b4c07863 --- /dev/null +++ b/VDS/Protocols/ParentViewProtocol.swift @@ -0,0 +1,37 @@ +// +// ParentViewProtocol.swift +// VDS +// +// Created by Matt Bruce on 8/23/24. +// + +import Foundation + + +/// This is used in a View or Control to denote subviews of the ViewProtocol +/// type, more or less for composite views/controls. +public protocol ParentViewProtocol: ViewProtocol { + var children: [any ViewProtocol] { get } +} + +extension ParentViewProtocol { + + /// This will get all of the children for yourself as well as all + /// of the children within the full tree hierarchy. + /// - Returns: All children within the hierachy + public func getAllChildren() -> [any ViewProtocol] { + var allChildren = [any ViewProtocol]() + + func traverse(view: any ViewProtocol) { + if let parentView = view as? any ParentViewProtocol { + for child in parentView.children { + allChildren.append(child) + traverse(view: child) + } + } + } + + traverse(view: self) + return children + } +} diff --git a/VDS/Protocols/ViewProtocol.swift b/VDS/Protocols/ViewProtocol.swift index 4eb091b1..6d3dc4f3 100644 --- a/VDS/Protocols/ViewProtocol.swift +++ b/VDS/Protocols/ViewProtocol.swift @@ -9,28 +9,6 @@ import Foundation import UIKit import Combine -public protocol ParentViewProtocol: ViewProtocol { - var children: [any ViewProtocol] { get } -} - -extension ParentViewProtocol { - public func getAllChildren() -> [any ViewProtocol] { - var allChildren = [any ViewProtocol]() - - func traverse(view: any ViewProtocol) { - if let parentView = view as? any ParentViewProtocol { - for child in parentView.children { - allChildren.append(child) - traverse(view: child) - } - } - } - - traverse(view: self) - return children - } -} - public protocol ViewProtocol: AnyObject, Initable, Resettable, Enabling, Surfaceable, AccessibilityUpdatable { /// Set of Subscribers for any Publishers for this Control. var subscribers: Set { get set } From aa013f62e3657e6135a73638759cfd686adf182a Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 26 Aug 2024 09:03:17 -0500 Subject: [PATCH 11/18] added equatable to structs Signed-off-by: Matt Bruce --- .../Breadcrumbs/BreadcrumbItemModel.swift | 8 ++++++-- .../Calendar/CalendarIndicatorModel.swift | 2 +- .../Carousel/CarouselPaginationModel.swift | 2 +- .../Carousel/CarouselSlotAlignmentModel.swift | 2 +- VDS/Components/Checkbox/CheckboxGroup.swift | 19 +++++++++++++++++-- .../DatePicker/DatePickerCalendarModel.swift | 2 +- .../DropdownSelect/DropdownOptionModel.swift | 2 +- .../ButtonIconBadgeIndicatorModel.swift | 2 +- VDS/Components/Icon/IconName.swift | 2 +- .../NotificationButtonModel.swift | 6 +++++- VDS/Components/RadioBox/RadioBoxGroup.swift | 19 ++++++++++++++++++- .../RadioButton/RadioButtonGroup.swift | 17 ++++++++++++++++- VDS/Components/Table/TableItemModel.swift | 2 +- VDS/Components/Table/TableRowModel.swift | 2 +- VDS/Components/Tabs/TabModel.swift | 7 ++++++- .../TileContainer/TileContainer.swift | 17 ++++++++++++++++- .../Tilelet/TileletBadgeModel.swift | 2 +- .../Tilelet/TileletIconModels.swift | 4 ++-- .../Tilelet/TileletSubTitleModel.swift | 10 +++++++++- .../Tilelet/TileletTitleModel.swift | 11 ++++++++++- .../Tilelet/TiletEyebrowModel.swift | 11 ++++++++++- .../TitleLockup/TitleLockupEyebrowModel.swift | 11 ++++++++++- .../TitleLockupSubTitleModel.swift | 8 ++++++++ .../TitleLockup/TitleLockupTitleModel.swift | 11 ++++++++++- VDS/Components/Tooltip/TooltipModel.swift | 2 +- 25 files changed, 154 insertions(+), 27 deletions(-) diff --git a/VDS/Components/Breadcrumbs/BreadcrumbItemModel.swift b/VDS/Components/Breadcrumbs/BreadcrumbItemModel.swift index 2c73f24f..be4419cc 100644 --- a/VDS/Components/Breadcrumbs/BreadcrumbItemModel.swift +++ b/VDS/Components/Breadcrumbs/BreadcrumbItemModel.swift @@ -8,8 +8,7 @@ import Foundation extension Breadcrumbs { - public struct BreadcrumbItemModel { - + public struct BreadcrumbItemModel: Equatable { ///Text that goes in the breadcrumb item public var text: String @@ -24,5 +23,10 @@ extension Breadcrumbs { self.selected = selected self.onClick = onClick } + + public static func == (lhs: Breadcrumbs.BreadcrumbItemModel, rhs: Breadcrumbs.BreadcrumbItemModel) -> Bool { + lhs.text == rhs.text + && lhs.selected == rhs.selected + } } } diff --git a/VDS/Components/Calendar/CalendarIndicatorModel.swift b/VDS/Components/Calendar/CalendarIndicatorModel.swift index 04ad9714..185af749 100644 --- a/VDS/Components/Calendar/CalendarIndicatorModel.swift +++ b/VDS/Components/Calendar/CalendarIndicatorModel.swift @@ -9,7 +9,7 @@ import Foundation /// Custom data type for indicators prop extension CalendarBase { - public struct CalendarIndicatorModel { + public struct CalendarIndicatorModel: Equatable { /// Text that shown to an indicator for legend public var label: String diff --git a/VDS/Components/Carousel/CarouselPaginationModel.swift b/VDS/Components/Carousel/CarouselPaginationModel.swift index ab85d6a4..67ba5052 100644 --- a/VDS/Components/Carousel/CarouselPaginationModel.swift +++ b/VDS/Components/Carousel/CarouselPaginationModel.swift @@ -10,7 +10,7 @@ import UIKit /// Custom data type for pagination prop for 'Carousel' component. extension Carousel { - public struct CarouselPaginationModel { + public struct CarouselPaginationModel: Equatable { /// Pagination supports Button icon property 'kind'. public var kind: ButtonIcon.Kind diff --git a/VDS/Components/Carousel/CarouselSlotAlignmentModel.swift b/VDS/Components/Carousel/CarouselSlotAlignmentModel.swift index ee1d491b..9774baa2 100644 --- a/VDS/Components/Carousel/CarouselSlotAlignmentModel.swift +++ b/VDS/Components/Carousel/CarouselSlotAlignmentModel.swift @@ -11,7 +11,7 @@ import Foundation extension Carousel { /// Used only when slot content have different heights or widths. - public struct CarouselSlotAlignmentModel { + public struct CarouselSlotAlignmentModel: Equatable { /// Used for vertical alignment of slot alignment. public var vertical: Carousel.Vertical diff --git a/VDS/Components/Checkbox/CheckboxGroup.swift b/VDS/Components/Checkbox/CheckboxGroup.swift index f2a62efa..9967bcd0 100644 --- a/VDS/Components/Checkbox/CheckboxGroup.swift +++ b/VDS/Components/Checkbox/CheckboxGroup.swift @@ -108,8 +108,8 @@ open class CheckboxGroup: SelectorGroupBase, SelectorGroupMultiSel } extension CheckboxGroup { - public struct CheckboxItemModel : Surfaceable, Initable, Errorable { - + public struct CheckboxItemModel : Surfaceable, Initable, Errorable, Equatable { + /// Whether this object is enabled or not public var enabled: Bool /// Current Surface and this is used to pass down to child objects that implement Surfacable @@ -146,6 +146,21 @@ extension CheckboxGroup { public init() { self.init(enabled: true) } + + public static func == (lhs: CheckboxGroup.CheckboxItemModel, rhs: CheckboxGroup.CheckboxItemModel) -> Bool { + lhs.enabled == rhs.enabled + && lhs.surface == rhs.surface + && lhs.inputId == rhs.inputId + && lhs.value == rhs.value + && lhs.accessibileText == rhs.accessibileText + && lhs.labelText == rhs.labelText + && lhs.labelTextAttributes == rhs.labelTextAttributes + && lhs.childText == rhs.childText + && lhs.childTextAttributes == rhs.childTextAttributes + && lhs.selected == rhs.selected + && lhs.showError == rhs.showError + && lhs.errorText == rhs.errorText + } } } diff --git a/VDS/Components/DatePicker/DatePickerCalendarModel.swift b/VDS/Components/DatePicker/DatePickerCalendarModel.swift index da18ab2f..84a392ad 100644 --- a/VDS/Components/DatePicker/DatePickerCalendarModel.swift +++ b/VDS/Components/DatePicker/DatePickerCalendarModel.swift @@ -9,7 +9,7 @@ import Foundation import UIKit extension DatePicker { - public struct CalendarModel { + public struct CalendarModel: Equatable { /// If set to true, the calendar will not have a border. public let hideContainerBorder: Bool diff --git a/VDS/Components/DropdownSelect/DropdownOptionModel.swift b/VDS/Components/DropdownSelect/DropdownOptionModel.swift index c82519eb..76ac8f5d 100644 --- a/VDS/Components/DropdownSelect/DropdownOptionModel.swift +++ b/VDS/Components/DropdownSelect/DropdownOptionModel.swift @@ -8,7 +8,7 @@ import Foundation extension DropdownSelect { - public struct DropdownOptionModel { + public struct DropdownOptionModel: Equatable { /// Text that goes as option to DropdownSelect public var text: String diff --git a/VDS/Components/Icon/ButtonIcon/ButtonIconBadgeIndicatorModel.swift b/VDS/Components/Icon/ButtonIcon/ButtonIconBadgeIndicatorModel.swift index 28d731b0..f683ebf4 100644 --- a/VDS/Components/Icon/ButtonIcon/ButtonIconBadgeIndicatorModel.swift +++ b/VDS/Components/Icon/ButtonIcon/ButtonIconBadgeIndicatorModel.swift @@ -10,7 +10,7 @@ import Foundation extension ButtonIcon { //Model that represents the options available for the Badge Indicator - public struct BadgeIndicatorModel { + public struct BadgeIndicatorModel: Equatable { /// Enum used to describe the badge indicator direction of icon button determining the expand direction. public enum ExpandDirection: String, CaseIterable { case right, center, left diff --git a/VDS/Components/Icon/IconName.swift b/VDS/Components/Icon/IconName.swift index c3943d64..a6e951df 100644 --- a/VDS/Components/Icon/IconName.swift +++ b/VDS/Components/Icon/IconName.swift @@ -24,7 +24,7 @@ extension Icon { /// let icon = Icon() /// icon.name = .foo /// ``` - public struct Name: RawRepresentable { + public struct Name: RawRepresentable, Equatable { public typealias RawValue = String public var rawValue: String diff --git a/VDS/Components/Notification/NotificationButtonModel.swift b/VDS/Components/Notification/NotificationButtonModel.swift index 6876aa7c..c714dbd7 100644 --- a/VDS/Components/Notification/NotificationButtonModel.swift +++ b/VDS/Components/Notification/NotificationButtonModel.swift @@ -8,12 +8,16 @@ import Foundation extension Notification { - public struct ButtonModel { + public struct ButtonModel: Equatable { public var text: String public var onClick: (Button) -> () public init(text: String, onClick: @escaping (Button) -> Void) { self.text = text self.onClick = onClick } + + public static func == (lhs: Notification.ButtonModel, rhs: Notification.ButtonModel) -> Bool { + lhs.text == rhs.text + } } } diff --git a/VDS/Components/RadioBox/RadioBoxGroup.swift b/VDS/Components/RadioBox/RadioBoxGroup.swift index 3b17d7d8..484b213f 100644 --- a/VDS/Components/RadioBox/RadioBoxGroup.swift +++ b/VDS/Components/RadioBox/RadioBoxGroup.swift @@ -113,7 +113,7 @@ open class RadioBoxGroup: SelectorGroupBase, SelectorGroupSingleSe } extension RadioBoxGroup { - public struct RadioBoxItemModel: Surfaceable, Initable, FormFieldable { + public struct RadioBoxItemModel: Surfaceable, Initable, FormFieldable, Equatable { /// Whether this object is enabled or not public var enabled: Bool /// Current Surface and this is used to pass down to child objects that implement Surfacable @@ -158,5 +158,22 @@ extension RadioBoxGroup { public init() { self.init(enabled: true) } + + public static func == (lhs: RadioBoxGroup.RadioBoxItemModel, rhs: RadioBoxGroup.RadioBoxItemModel) -> Bool { + lhs.enabled == rhs.enabled + && lhs.surface == rhs.surface + && lhs.inputId == rhs.inputId + && lhs.value == rhs.value + && lhs.accessibileText == rhs.accessibileText + && lhs.text == rhs.text + && lhs.textAttributes == rhs.textAttributes + && lhs.subText == rhs.subText + && lhs.subTextAttributes == rhs.subTextAttributes + && lhs.subTextRight == rhs.subTextRight + && lhs.subTextRightAttributes == rhs.subTextRightAttributes + && lhs.selected == rhs.selected + && lhs.strikethrough == rhs.strikethrough + && lhs.strikethroughAccessibileText == rhs.strikethroughAccessibileText + } } } diff --git a/VDS/Components/RadioButton/RadioButtonGroup.swift b/VDS/Components/RadioButton/RadioButtonGroup.swift index 8bde87de..bbd23209 100644 --- a/VDS/Components/RadioButton/RadioButtonGroup.swift +++ b/VDS/Components/RadioButton/RadioButtonGroup.swift @@ -103,7 +103,7 @@ open class RadioButtonGroup: SelectorGroupBase, SelectorGroupSi } extension RadioButtonGroup { - public struct RadioButtonItemModel: Surfaceable, Initable, FormFieldable, Errorable { + public struct RadioButtonItemModel: Surfaceable, Initable, FormFieldable, Errorable, Equatable { /// Whether this object is enabled or not public var enabled: Bool @@ -141,5 +141,20 @@ extension RadioButtonGroup { public init() { self.init(enabled: true) } + + public static func == (lhs: RadioButtonGroup.RadioButtonItemModel, rhs: RadioButtonGroup.RadioButtonItemModel) -> Bool { + lhs.enabled == rhs.enabled + && lhs.surface == rhs.surface + && lhs.inputId == rhs.inputId + && lhs.value == rhs.value + && lhs.accessibileText == rhs.accessibileText + && lhs.labelText == rhs.labelText + && lhs.labelTextAttributes == rhs.labelTextAttributes + && lhs.childText == rhs.childText + && lhs.childTextAttributes == rhs.childTextAttributes + && lhs.selected == rhs.selected + && lhs.showError == rhs.showError + && lhs.errorText == rhs.errorText + } } } diff --git a/VDS/Components/Table/TableItemModel.swift b/VDS/Components/Table/TableItemModel.swift index 47a8e3f2..4725ad73 100644 --- a/VDS/Components/Table/TableItemModel.swift +++ b/VDS/Components/Table/TableItemModel.swift @@ -10,7 +10,7 @@ import UIKit import VDSCoreTokens /// Model that represent the content of each cell of Table component -public struct TableItemModel { +public struct TableItemModel: Equatable { public let defaultHeight: CGFloat = 50.0 diff --git a/VDS/Components/Table/TableRowModel.swift b/VDS/Components/Table/TableRowModel.swift index 22f428ce..d9472372 100644 --- a/VDS/Components/Table/TableRowModel.swift +++ b/VDS/Components/Table/TableRowModel.swift @@ -7,7 +7,7 @@ import Foundation -public struct TableRowModel { +public struct TableRowModel: Equatable { public var columns: [TableItemModel] diff --git a/VDS/Components/Tabs/TabModel.swift b/VDS/Components/Tabs/TabModel.swift index 02f5bd43..959569a0 100644 --- a/VDS/Components/Tabs/TabModel.swift +++ b/VDS/Components/Tabs/TabModel.swift @@ -8,7 +8,7 @@ import Foundation extension Tabs { - public struct TabModel { + public struct TabModel: Equatable { ///Text that goes in the Tab public var text: String @@ -24,5 +24,10 @@ extension Tabs { self.onClick = onClick self.width = width } + + public static func == (lhs: Tabs.TabModel, rhs: Tabs.TabModel) -> Bool { + lhs.text == rhs.text + && lhs.width == rhs.width + } } } diff --git a/VDS/Components/TileContainer/TileContainer.swift b/VDS/Components/TileContainer/TileContainer.swift index 6c695112..c464d2b7 100644 --- a/VDS/Components/TileContainer/TileContainer.swift +++ b/VDS/Components/TileContainer/TileContainer.swift @@ -82,10 +82,25 @@ open class TileContainerBase: View where } /// Enum used to describe the background effect choices used for this component. - public enum BackgroundEffect { + public enum BackgroundEffect: Equatable { case transparency case gradient(UIColor, UIColor) case none + + public static func == (lhs: TileContainerBase.BackgroundEffect, rhs: TileContainerBase.BackgroundEffect) -> Bool { + lhs.description == lhs.description + } + + public var description: String { + switch self { + case .transparency: + "transparency" + case .gradient(let first, let second): + "gradient(\(first), \(second)" + case .none: + "none" + } + } } /// Enum used to describe the aspect ratios used for this component. diff --git a/VDS/Components/Tilelet/TileletBadgeModel.swift b/VDS/Components/Tilelet/TileletBadgeModel.swift index 9dbd03fe..90c523da 100644 --- a/VDS/Components/Tilelet/TileletBadgeModel.swift +++ b/VDS/Components/Tilelet/TileletBadgeModel.swift @@ -11,7 +11,7 @@ import UIKit extension Tilelet { /// Model that represents the options available for the badge. - public struct BadgeModel { + public struct BadgeModel: Equatable { /// Text that will be used for the badge. public var text: String = "" diff --git a/VDS/Components/Tilelet/TileletIconModels.swift b/VDS/Components/Tilelet/TileletIconModels.swift index 03b2d225..c30f0937 100644 --- a/VDS/Components/Tilelet/TileletIconModels.swift +++ b/VDS/Components/Tilelet/TileletIconModels.swift @@ -32,7 +32,7 @@ extension Tilelet { } /// Model that represents the options available for the descriptive icon. - public struct DescriptiveIcon { + public struct DescriptiveIcon: Equatable { /// A representation that will be used to render the icon with corresponding name. public var name: Icon.Name @@ -58,7 +58,7 @@ extension Tilelet { } /// Model that represents the options available for the directional icon. - public struct DirectionalIcon { + public struct DirectionalIcon: Equatable { public enum IconType: String, CaseIterable { case rightArrow case externalLink diff --git a/VDS/Components/Tilelet/TileletSubTitleModel.swift b/VDS/Components/Tilelet/TileletSubTitleModel.swift index 4c48cc3a..9850209c 100644 --- a/VDS/Components/Tilelet/TileletSubTitleModel.swift +++ b/VDS/Components/Tilelet/TileletSubTitleModel.swift @@ -10,7 +10,7 @@ import UIKit extension Tilelet { /// Model that represents the options available for the sub title label. - public struct SubTitleModel { + public struct SubTitleModel: Equatable { //-------------------------------------------------- // MARK: - Enums //-------------------------------------------------- @@ -67,5 +67,13 @@ extension Tilelet { textAttributes: textAttributes, lineBreakMode: lineBreakMode) } + + public static func == (lhs: Tilelet.SubTitleModel, rhs: Tilelet.SubTitleModel) -> Bool { + lhs.text == rhs.text + && lhs.textColor == rhs.textColor + && lhs.otherStandardStyle == rhs.otherStandardStyle + && lhs.textAttributes == rhs.textAttributes + && lhs.lineBreakMode == rhs.lineBreakMode + } } } diff --git a/VDS/Components/Tilelet/TileletTitleModel.swift b/VDS/Components/Tilelet/TileletTitleModel.swift index b9bc7bbe..877463c6 100644 --- a/VDS/Components/Tilelet/TileletTitleModel.swift +++ b/VDS/Components/Tilelet/TileletTitleModel.swift @@ -10,7 +10,7 @@ import UIKit extension Tilelet { /// Model that represents the options available for the title label. - public struct TitleModel { + public struct TitleModel: Equatable { //-------------------------------------------------- // MARK: - Enums //-------------------------------------------------- @@ -75,5 +75,14 @@ extension Tilelet { standardStyle: standardStyle.value, lineBreakMode: lineBreakMode) } + + public static func == (lhs: Tilelet.TitleModel, rhs: Tilelet.TitleModel) -> Bool { + lhs.text == rhs.text + && lhs.textColor == rhs.textColor + && lhs.isBold == rhs.isBold + && lhs.textAttributes == rhs.textAttributes + && lhs.standardStyle == rhs.standardStyle + && lhs.lineBreakMode == rhs.lineBreakMode + } } } diff --git a/VDS/Components/Tilelet/TiletEyebrowModel.swift b/VDS/Components/Tilelet/TiletEyebrowModel.swift index 3d22ab74..3c771d56 100644 --- a/VDS/Components/Tilelet/TiletEyebrowModel.swift +++ b/VDS/Components/Tilelet/TiletEyebrowModel.swift @@ -11,7 +11,7 @@ import UIKit extension Tilelet { /// Model that represents the options available for the eyebrow label. - public struct EyebrowModel { + public struct EyebrowModel: Equatable { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- @@ -60,5 +60,14 @@ extension Tilelet { standardStyle: standardStyle.value, textAttributes: textAttributes) } + + public static func == (lhs: Tilelet.EyebrowModel, rhs: Tilelet.EyebrowModel) -> Bool { + lhs.text == rhs.text + && lhs.textColor == rhs.textColor + && lhs.isBold == rhs.isBold + && lhs.textAttributes == rhs.textAttributes + && lhs.standardStyle == rhs.standardStyle + && lhs.lineBreakMode == rhs.lineBreakMode + } } } diff --git a/VDS/Components/TitleLockup/TitleLockupEyebrowModel.swift b/VDS/Components/TitleLockup/TitleLockupEyebrowModel.swift index 1139a6ee..d789205f 100644 --- a/VDS/Components/TitleLockup/TitleLockupEyebrowModel.swift +++ b/VDS/Components/TitleLockup/TitleLockupEyebrowModel.swift @@ -9,7 +9,7 @@ import Foundation extension TitleLockup { /// Model that represents the options available for the eyebrow label. - public struct EyebrowModel { + public struct EyebrowModel: Equatable { /// Text that will be used for the eyebrow label. public var text: String @@ -44,6 +44,15 @@ extension TitleLockup { /// Text style that will be used for the eyebrow label. public var textStyle: TextStyle { isBold ? standardStyle.value.bold : standardStyle.value.regular } + + public static func == (lhs: TitleLockup.EyebrowModel, rhs: TitleLockup.EyebrowModel) -> Bool { + lhs.text == rhs.text + && lhs.textColor == rhs.textColor + && lhs.isBold == rhs.isBold + && lhs.standardStyle == rhs.standardStyle + && lhs.textAttributes == rhs.textAttributes + && lhs.numberOfLines == rhs.numberOfLines + } } } diff --git a/VDS/Components/TitleLockup/TitleLockupSubTitleModel.swift b/VDS/Components/TitleLockup/TitleLockupSubTitleModel.swift index 7dcbfb85..fefb384e 100644 --- a/VDS/Components/TitleLockup/TitleLockupSubTitleModel.swift +++ b/VDS/Components/TitleLockup/TitleLockupSubTitleModel.swift @@ -46,6 +46,14 @@ extension TitleLockup { /// TextStyle used to render the text. public var textStyle: TextStyle { otherStandardStyle.value.regular } + public static func == (lhs: TitleLockup.SubTitleModel, rhs: TitleLockup.SubTitleModel) -> Bool { + lhs.text == rhs.text + && lhs.textColor == rhs.textColor + && lhs.otherStandardStyle == rhs.otherStandardStyle + && lhs.textAttributes == rhs.textAttributes + && lhs.lineBreakMode == rhs.lineBreakMode + && lhs.numberOfLines == rhs.numberOfLines + } } } diff --git a/VDS/Components/TitleLockup/TitleLockupTitleModel.swift b/VDS/Components/TitleLockup/TitleLockupTitleModel.swift index 2d7f7405..2dc431ed 100644 --- a/VDS/Components/TitleLockup/TitleLockupTitleModel.swift +++ b/VDS/Components/TitleLockup/TitleLockupTitleModel.swift @@ -10,7 +10,7 @@ import UIKit extension TitleLockup { /// Model that represents the options available for the sub title label. - public struct TitleModel { + public struct TitleModel: Equatable { /// Text that will be used for the title label. public var text: String @@ -51,5 +51,14 @@ extension TitleLockup { /// TextStyle used to render the text. public var textStyle: TextStyle { isBold ? standardStyle.value.bold : standardStyle.value.regular } + public static func == (lhs: TitleLockup.TitleModel, rhs: TitleLockup.TitleModel) -> Bool { + lhs.text == rhs.text + && lhs.textColor == rhs.textColor + && lhs.isBold == rhs.isBold + && lhs.standardStyle == rhs.standardStyle + && lhs.textAttributes == rhs.textAttributes + && lhs.numberOfLines == rhs.numberOfLines + && lhs.lineBreakMode == rhs.lineBreakMode + } } } diff --git a/VDS/Components/Tooltip/TooltipModel.swift b/VDS/Components/Tooltip/TooltipModel.swift index 461fda66..9c3e1576 100644 --- a/VDS/Components/Tooltip/TooltipModel.swift +++ b/VDS/Components/Tooltip/TooltipModel.swift @@ -11,7 +11,7 @@ import UIKit extension Tooltip { /// Model used to represent the tooltip. - public struct TooltipModel { + public struct TooltipModel: Equatable { /// Current Surface and this is used to pass down to child objects that implement Surfacable public var closeButtonText: String public var title: String? From 1f2637ed0408846fa7bddf1664a74471de341648 Mon Sep 17 00:00:00 2001 From: Vasavi Kanamarlapudi Date: Tue, 27 Aug 2024 11:54:41 +0530 Subject: [PATCH 12/18] refactoring Carousel to use a UICollectionView --- VDS.xcodeproj/project.pbxproj | 4 + VDS/Components/Carousel/Carousel.swift | 157 ++++++++---------- .../Carousel/CarouselSlotCell.swift | 90 ++++++++++ 3 files changed, 159 insertions(+), 92 deletions(-) create mode 100644 VDS/Components/Carousel/CarouselSlotCell.swift diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index fc3417d2..10858c07 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -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 */; }; + 183B16F32C78CF7C00BA6A10 /* CarouselSlotCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 183B16F22C78CF7C00BA6A10 /* CarouselSlotCell.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 */; }; @@ -215,6 +216,7 @@ 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 = ""; }; + 183B16F22C78CF7C00BA6A10 /* CarouselSlotCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselSlotCell.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 = ""; }; @@ -522,6 +524,7 @@ isa = PBXGroup; children = ( 18AE874F2C06FDA60075F181 /* Carousel.swift */, + 183B16F22C78CF7C00BA6A10 /* CarouselSlotCell.swift */, 18B9763E2C11BA4A009271DF /* CarouselPaginationModel.swift */, 18B42AC52C09D197008D6262 /* CarouselSlotAlignmentModel.swift */, 18AE87532C06FE610075F181 /* CarouselChangeLog.txt */, @@ -1396,6 +1399,7 @@ EA985BF02968A93600F2FF2E /* TitleLockupEyebrowModel.swift in Sources */, EA5E30532950DDA60082B959 /* TitleLockup.swift in Sources */, EAD062B02A3B873E0015965D /* BadgeIndicator.swift in Sources */, + 183B16F32C78CF7C00BA6A10 /* CarouselSlotCell.swift in Sources */, 44A952DD2BE3DA820009F874 /* TableFlowLayout.swift in Sources */, EAA5EEB528ECBFB4003B3210 /* ImageLabelAttribute.swift in Sources */, 18792A902B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift in Sources */, diff --git a/VDS/Components/Carousel/Carousel.swift b/VDS/Components/Carousel/Carousel.swift index 9e14d3d3..926df9f4 100644 --- a/VDS/Components/Carousel/Carousel.swift +++ b/VDS/Components/Carousel/Carousel.swift @@ -154,10 +154,21 @@ open class Carousel: View { $0.backgroundColor = .clear } - private var scrollView = UIScrollView().with { - $0.translatesAutoresizingMaskIntoConstraints = false - $0.backgroundColor = .clear - } + private lazy var collectionView: UICollectionView = { + let layout = UICollectionViewFlowLayout() + layout.scrollDirection = .horizontal + let collectionView = UICollectionView(frame: frame, collectionViewLayout: layout) + collectionView.isScrollEnabled = true + collectionView.translatesAutoresizingMaskIntoConstraints = false + collectionView.delegate = self + collectionView.dataSource = self + collectionView.showsHorizontalScrollIndicator = false + collectionView.showsVerticalScrollIndicator = false + collectionView.backgroundColor = .clear + collectionView.register(CarouselSlotCell.self, + forCellWithReuseIdentifier: CarouselSlotCell.identifier) + return collectionView + }() /// Previous button to show previous slide. private var previousButton = ButtonIcon().with { @@ -215,9 +226,9 @@ open class Carousel: View { containerView.addSubview(contentStackView) // Add scrollview - scrollContainerView.addSubview(scrollView) - scrollView.pinToSuperView() - + scrollContainerView.addSubview(collectionView) + collectionView.pinToSuperView() + // Add pagination button icons scrollContainerView.addSubview(previousButton) previousButton @@ -259,14 +270,24 @@ open class Carousel: View { /// Used to make changes to the View based off a change events or from local properties. open override func updateView() { super.updateView() + updateScrollbar() + updateCarousel() + collectionView.reloadData() + } + //-------------------------------------------------- + // MARK: - Private Methods + //-------------------------------------------------- + private func updateScrollbar() { carouselScrollBar.numberOfSlides = views.count carouselScrollBar.layout = layout if (carouselScrollBar.position == 0 || carouselScrollBar.position > carouselScrollBar.numberOfSlides) { carouselScrollBar.position = 1 } carouselScrollBar.isHidden = (totalPositions() <= 1) ? true : false - + } + + private func updateCarousel() { // Mobile/Tablet layouts without peek - must show pagination controls. // If peek is ‘none’, pagination controls should show. So set to persistent. if peek == .none { @@ -284,12 +305,9 @@ open class Carousel: View { } updatePaginationControls() - addCarouselSlots() + updateContainerHeight() } - - //-------------------------------------------------- - // MARK: - Private Methods - //-------------------------------------------------- + private func addlisteners() { nextButton.onClick = { _ in self.nextButtonClick() } previousButton.onClick = { _ in self.previousButtonClick() } @@ -365,47 +383,13 @@ open class Carousel: View { return height } - // Add carousel slots and load data if any - private func addCarouselSlots() { + // update carousel size and load data if any + private func updateContainerHeight() { getSlotWidth() if containerView.frame.size.width > 0 { containerViewHeightConstraint?.isActive = false containerStackHeightConstraint?.isActive = false let slotHeight = fetchCarouselHeight() - - // Perform a loop to iterate each subView - scrollView.subviews.forEach { subView in - // Removing subView from its parent view - subView.removeFromSuperview() - } - - // Add carousel items - if views.count > 0 { - var xPos = 0.0 - for index in 0...views.count - 1 { - - // Add Carousel Slot - let carouselSlot = View().with { - $0.clipsToBounds = true - } - scrollView.addSubview(carouselSlot) - scrollView.delegate = self - - carouselSlot - .pinTop() - .pinBottom() - .pinLeading(xPos) - .width(minimumSlotWidth) - .height(slotHeight) - xPos = xPos + minimumSlotWidth + gutter.value - - let component = views[index] - carouselSlot.addSubview(component) - setSlotAlignment(contentView: component) - } - scrollView.contentSize = CGSize(width: xPos - gutter.value, height: slotHeight) - } - let containerHeight = slotHeight + scrollbarTopSpace + containerSize.height if carouselScrollBar.isHidden { containerStackHeightConstraint = contentStackView.heightAnchor.constraint(equalToConstant: slotHeight) @@ -419,43 +403,6 @@ open class Carousel: View { } } - // Set slot alignment if provided. Used only when slot content have different heights or widths. - private func setSlotAlignment(contentView: UIView) { - switch slotAlignment?.vertical { - case .top: - contentView - .pinTop() - .pinBottomLessThanOrEqualTo() - case .middle: - contentView - .pinTopGreaterThanOrEqualTo() - .pinBottomLessThanOrEqualTo() - .pinCenterY() - case .bottom: - contentView - .pinTopGreaterThanOrEqualTo() - .pinBottom() - default: break - } - - switch slotAlignment?.horizontal { - case .left: - contentView - .pinLeading() - .pinTrailingLessThanOrEqualTo() - case .center: - contentView - .pinLeadingGreaterThanOrEqualTo() - .pinTrailingLessThanOrEqualTo() - .pinCenterX() - case .right: - contentView - .pinLeadingGreaterThanOrEqualTo() - .pinTrailing() - default: break - } - } - // Get the slot width relative to the peak private func getSlotWidth() { let actualWidth = containerView.frame.size.width @@ -505,7 +452,7 @@ open class Carousel: View { } private func updateScrollbarPosition(targetContentOffsetXPos:CGFloat) { - let scrollContentSizeWidth = scrollView.contentSize.width + let scrollContentSizeWidth = collectionView.contentSize.width let totalPositions = totalPositions() let layoutSpace = Int (floor( Double(scrollContentSizeWidth / Double(totalPositions)))) let remindSpace = Int(targetContentOffsetXPos) % layoutSpace @@ -515,10 +462,11 @@ open class Carousel: View { updateScrollPosition(position: contentPos, callbackText: "ScrollViewMoved") } - // Update scrollview offset relative to scrollbar thumb position + // Update collectionview offset relative to scrollbar thumb position private func updateScrollPosition(position: Int, callbackText: String) { if carouselScrollBar.numberOfSlides > 0 { - let scrollContentSizeWidth = scrollView.contentSize.width + let scrollContentSizeWidth = collectionView.contentSize.width + let totalPositions = totalPositions() var xPos = 0.0 if position == 1 { @@ -536,8 +484,8 @@ open class Carousel: View { } } carouselScrollBar.scrubberId = position+1 - let yPos = scrollView.contentOffset.y - scrollView.setContentOffset(CGPoint(x: xPos, y: yPos), animated: true) + let yPos = collectionView.contentOffset.y + collectionView.setContentOffset(CGPoint(x: xPos, y: yPos), animated: true) showPaginationControls() groupIndex = position-1 onChangePublisher.send(groupIndex) @@ -557,5 +505,30 @@ extension Carousel: UIScrollViewDelegate { public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { updateScrollbarPosition(targetContentOffsetXPos: targetContentOffset.pointee.x) } - +} +extension Carousel: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { + //-------------------------------------------------- + // MARK: - UICollectionView Delegate & Datasource + //-------------------------------------------------- + public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + views.count + } + + public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CarouselSlotCell.identifier, for: indexPath) as? CarouselSlotCell else { return UICollectionViewCell() } + cell.contentView.subviews.forEach { $0.removeFromSuperview() } + let component = views[indexPath.row] + cell.update(with: component, slotAlignment: slotAlignment, surface: surface) + cell.layoutIfNeeded() + return cell + } + + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { + return gutter.value + } + + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + return CGSize(width: minimumSlotWidth, height: fetchCarouselHeight()) + } + } diff --git a/VDS/Components/Carousel/CarouselSlotCell.swift b/VDS/Components/Carousel/CarouselSlotCell.swift new file mode 100644 index 00000000..11807747 --- /dev/null +++ b/VDS/Components/Carousel/CarouselSlotCell.swift @@ -0,0 +1,90 @@ +// +// CarouselSlotCell.swift +// VDS +// +// Created by Kanamarlapudi, Vasavi on 23/08/24. +// + +import Foundation +import UIKit + +final class CarouselSlotCell: UICollectionViewCell { + + ///Identifier for the Calendar Date Cell. + static let identifier: String = String(describing: CarouselSlotCell.self) + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + override init(frame: CGRect) { + super.init(frame: frame) + setUp() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setUp() + } + + //-------------------------------------------------- + // MARK: - Private Properties + //-------------------------------------------------- + private var surface: Surface = .light + + //-------------------------------------------------- + // MARK: - Private Methods + //-------------------------------------------------- + + /// Configuring the cell with default setup. + private func setUp() { + isAccessibilityElement = true + } + + /// Updating UI based on data along with surface. + func update(with component: UIView, slotAlignment: Carousel.CarouselSlotAlignmentModel?, surface: Surface) { + self.surface = surface + contentView.addSubview(component) + if var surfacedView = component as? Surfaceable { + surfacedView.surface = surface + } + setSlotAlignment(alignment: slotAlignment, contentView: component) + } + + // Set slot alignment if provided. Used only when slot content have different heights or widths. + private func setSlotAlignment(alignment: Carousel.CarouselSlotAlignmentModel?, contentView: UIView) { + switch alignment?.vertical { + case .top: + contentView + .pinTop() + .pinBottomLessThanOrEqualTo() + case .middle: + contentView + .pinTopGreaterThanOrEqualTo() + .pinBottomLessThanOrEqualTo() + .pinCenterY() + case .bottom: + contentView + .pinTopGreaterThanOrEqualTo() + .pinBottom() + default: break + } + + switch alignment?.horizontal { + case .left: + contentView + .pinLeading() + .pinTrailingLessThanOrEqualTo() + case .center: + contentView + .pinLeadingGreaterThanOrEqualTo() + .pinTrailingLessThanOrEqualTo() + .pinCenterX() + case .right: + contentView + .pinLeadingGreaterThanOrEqualTo() + .pinTrailing() + default: break + } + } + +} From 31f01773c4395e7e67b86f00977e90fa78a27ae8 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 27 Aug 2024 11:44:10 -0500 Subject: [PATCH 13/18] added borders to the cells for carousel Signed-off-by: Matt Bruce --- VDS/Components/Carousel/Carousel.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/VDS/Components/Carousel/Carousel.swift b/VDS/Components/Carousel/Carousel.swift index debe9042..a2dd4d7d 100644 --- a/VDS/Components/Carousel/Carousel.swift +++ b/VDS/Components/Carousel/Carousel.swift @@ -520,6 +520,11 @@ extension Carousel: UICollectionViewDelegate, UICollectionViewDataSource, UIColl let component = views[indexPath.row] cell.update(with: component, slotAlignment: slotAlignment, surface: surface) cell.layoutIfNeeded() + if hasDebugBorder { + cell.addDebugBorder() + } else { + cell.removeDebugBorder() + } return cell } From ad6291af30122316d42cc54f0d06d3cf45316fda Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 27 Aug 2024 11:56:19 -0500 Subject: [PATCH 14/18] force component to redraw Signed-off-by: Matt Bruce --- VDS/Components/Carousel/Carousel.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/VDS/Components/Carousel/Carousel.swift b/VDS/Components/Carousel/Carousel.swift index a2dd4d7d..b344ad9a 100644 --- a/VDS/Components/Carousel/Carousel.swift +++ b/VDS/Components/Carousel/Carousel.swift @@ -520,6 +520,7 @@ extension Carousel: UICollectionViewDelegate, UICollectionViewDataSource, UIColl let component = views[indexPath.row] cell.update(with: component, slotAlignment: slotAlignment, surface: surface) cell.layoutIfNeeded() + component.setNeedsLayout() if hasDebugBorder { cell.addDebugBorder() } else { From 35036ca8044d68886e477aff5e571245de16f125 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 27 Aug 2024 13:31:48 -0500 Subject: [PATCH 15/18] more updates on carousel Signed-off-by: Matt Bruce --- VDS/Components/Carousel/Carousel.swift | 4 ++-- VDS/Components/Carousel/CarouselSlotCell.swift | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/VDS/Components/Carousel/Carousel.swift b/VDS/Components/Carousel/Carousel.swift index b344ad9a..dc1ef104 100644 --- a/VDS/Components/Carousel/Carousel.swift +++ b/VDS/Components/Carousel/Carousel.swift @@ -272,6 +272,7 @@ open class Carousel: View { super.updateView() updateScrollbar() updateCarousel() + collectionView.collectionViewLayout.invalidateLayout() collectionView.reloadData() } @@ -516,11 +517,10 @@ extension Carousel: UICollectionViewDelegate, UICollectionViewDataSource, UIColl public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CarouselSlotCell.identifier, for: indexPath) as? CarouselSlotCell else { return UICollectionViewCell() } - cell.contentView.subviews.forEach { $0.removeFromSuperview() } let component = views[indexPath.row] cell.update(with: component, slotAlignment: slotAlignment, surface: surface) cell.layoutIfNeeded() - component.setNeedsLayout() + //component.setNeedsLayout() if hasDebugBorder { cell.addDebugBorder() } else { diff --git a/VDS/Components/Carousel/CarouselSlotCell.swift b/VDS/Components/Carousel/CarouselSlotCell.swift index 11807747..d47a2595 100644 --- a/VDS/Components/Carousel/CarouselSlotCell.swift +++ b/VDS/Components/Carousel/CarouselSlotCell.swift @@ -25,11 +25,6 @@ final class CarouselSlotCell: UICollectionViewCell { super.init(coder: coder) setUp() } - - //-------------------------------------------------- - // MARK: - Private Properties - //-------------------------------------------------- - private var surface: Surface = .light //-------------------------------------------------- // MARK: - Private Methods @@ -42,7 +37,7 @@ final class CarouselSlotCell: UICollectionViewCell { /// Updating UI based on data along with surface. func update(with component: UIView, slotAlignment: Carousel.CarouselSlotAlignmentModel?, surface: Surface) { - self.surface = surface + contentView.subviews.forEach { $0.removeFromSuperview() } contentView.addSubview(component) if var surfacedView = component as? Surfaceable { surfacedView.surface = surface From c76d3e7b760390470a107027fd55f2ffa407e696 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 27 Aug 2024 14:04:41 -0500 Subject: [PATCH 16/18] updated Pagination to a Control Signed-off-by: Matt Bruce --- VDS/Components/Pagination/Pagination.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/VDS/Components/Pagination/Pagination.swift b/VDS/Components/Pagination/Pagination.swift index cf4f9183..50684e7e 100644 --- a/VDS/Components/Pagination/Pagination.swift +++ b/VDS/Components/Pagination/Pagination.swift @@ -13,7 +13,7 @@ import Combine ///Pagination is a control that enables customers to navigate multiple pages of content by selecting either a specific page or the next or previous set of four pages. @objcMembers @objc(VDSPagination) -open class Pagination: View { +open class Pagination: Control, Changeable { //-------------------------------------------------- // MARK: - Private Properties @@ -52,6 +52,8 @@ open class Pagination: View { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + public var onChangeSubscriber: AnyCancellable? + ///Previous button to select previous page public let previousButton: PaginationButton = .init(type: .previous) ///Next button to select next page @@ -195,6 +197,8 @@ open class Pagination: View { let isNextAction = sender == nextButton _selectedPageIndex = if isNextAction { _selectedPageIndex + 1 } else { _selectedPageIndex - 1 } updateSelection() + onPageDidSelect?(selectedPage) + sendActions(for: .valueChanged) DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in guard let self else { return } UIAccessibility.post(notification: .announcement, argument: paginationDescription) @@ -250,6 +254,7 @@ extension Pagination: UICollectionViewDelegate, UICollectionViewDataSource, UICo _selectedPageIndex = indexPath.row updateSelection() onPageDidSelect?(selectedPage) + sendActions(for: .valueChanged) } } From 296703076e8a22ebb85d05886ffe7a3432e0ddaf Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 27 Aug 2024 14:28:51 -0500 Subject: [PATCH 17/18] updated from Control to View and add publisher Signed-off-by: Matt Bruce --- VDS/Components/Pagination/Pagination.swift | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/VDS/Components/Pagination/Pagination.swift b/VDS/Components/Pagination/Pagination.swift index 50684e7e..00892fe3 100644 --- a/VDS/Components/Pagination/Pagination.swift +++ b/VDS/Components/Pagination/Pagination.swift @@ -13,11 +13,13 @@ import Combine ///Pagination is a control that enables customers to navigate multiple pages of content by selecting either a specific page or the next or previous set of four pages. @objcMembers @objc(VDSPagination) -open class Pagination: Control, Changeable { +open class Pagination: View { //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- + private let pageChangedSubject = PassthroughSubject() + ///Maximum component width private let maxWidth: CGFloat = 288.0 ///Collectionview width anchor @@ -52,8 +54,8 @@ open class Pagination: Control, Changeable { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- - public var onChangeSubscriber: AnyCancellable? - + public var pageChangedPublisher: AnyPublisher { pageChangedSubject.eraseToAnyPublisher() } + ///Previous button to select previous page public let previousButton: PaginationButton = .init(type: .previous) ///Next button to select next page @@ -147,6 +149,11 @@ open class Pagination: Control, Changeable { .sink { [weak self] value in self?.collectionViewWidthAnchor?.constant = value //As cell width is dynamic i.e cell may contain 2 or 3 or 4 charcters. Make sure that all the visible cells are displayed. }.store(in: &subscribers) + + pageChangedPublisher.sink { [weak self] control in + guard let self else { return } + onPageDidSelect?(control.selectedPage) + }.store(in: &subscribers) } open override func setDefaults() { @@ -197,8 +204,7 @@ open class Pagination: Control, Changeable { let isNextAction = sender == nextButton _selectedPageIndex = if isNextAction { _selectedPageIndex + 1 } else { _selectedPageIndex - 1 } updateSelection() - onPageDidSelect?(selectedPage) - sendActions(for: .valueChanged) + pageChangedSubject.send(self) DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in guard let self else { return } UIAccessibility.post(notification: .announcement, argument: paginationDescription) @@ -253,8 +259,7 @@ extension Pagination: UICollectionViewDelegate, UICollectionViewDataSource, UICo guard _selectedPageIndex != indexPath.row else { return } _selectedPageIndex = indexPath.row updateSelection() - onPageDidSelect?(selectedPage) - sendActions(for: .valueChanged) + pageChangedSubject.send(self) } } From 2365f8dbf40162c638aca5de5071ab73c3a7a7f8 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 27 Aug 2024 14:57:20 -0500 Subject: [PATCH 18/18] updated version Signed-off-by: Matt Bruce --- VDS.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index ee29c530..3da4fb0d 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -1593,7 +1593,7 @@ BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 72; + CURRENT_PROJECT_VERSION = 73; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1631,7 +1631,7 @@ BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 72; + CURRENT_PROJECT_VERSION = 73; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1;