Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/vds_ios.git into feature/tileletEnhancements
# Conflicts: # VDS.xcodeproj/project.pbxproj Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
commit
1d23b9c8f2
@ -7,8 +7,13 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
1832AC572BA0791D008AE476 /* BreadcrumbCellItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1832AC562BA0791D008AE476 /* BreadcrumbCellItem.swift */; };
|
||||||
|
18450CF12BA1B19C009FDF2A /* BreadcrumbsChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 18450CF02BA1B19C009FDF2A /* BreadcrumbsChangeLog.txt */; };
|
||||||
|
1855EC662BAABF2A002ACAC2 /* BreadcrumbItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1855EC652BAABF2A002ACAC2 /* BreadcrumbItemModel.swift */; };
|
||||||
186B2A8A2B88DA7F001AB71F /* TextAreaChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 186B2A892B88DA7F001AB71F /* TextAreaChangeLog.txt */; };
|
186B2A8A2B88DA7F001AB71F /* TextAreaChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 186B2A892B88DA7F001AB71F /* TextAreaChangeLog.txt */; };
|
||||||
18792A902B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */; };
|
18792A902B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */; };
|
||||||
|
18A65A022B96E848006602CC /* Breadcrumbs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A65A012B96E848006602CC /* Breadcrumbs.swift */; };
|
||||||
|
18A65A042B96F050006602CC /* BreadcrumbItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A65A032B96F050006602CC /* BreadcrumbItem.swift */; };
|
||||||
18BDEE822B75316E00452358 /* ButtonIconChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */; };
|
18BDEE822B75316E00452358 /* ButtonIconChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */; };
|
||||||
445BA07829C07B3D0036A7C5 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 445BA07729C07B3D0036A7C5 /* Notification.swift */; };
|
445BA07829C07B3D0036A7C5 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 445BA07729C07B3D0036A7C5 /* Notification.swift */; };
|
||||||
44604AD429CE186A00E62B51 /* NotificationButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */; };
|
44604AD429CE186A00E62B51 /* NotificationButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */; };
|
||||||
@ -17,11 +22,18 @@
|
|||||||
5FC35BE328D51405004EBEAC /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC35BE228D51405004EBEAC /* Button.swift */; };
|
5FC35BE328D51405004EBEAC /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC35BE228D51405004EBEAC /* Button.swift */; };
|
||||||
710607952B91A99500F2863F /* TitleletChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 710607942B91A99500F2863F /* TitleletChangeLog.txt */; };
|
710607952B91A99500F2863F /* TitleletChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 710607942B91A99500F2863F /* TitleletChangeLog.txt */; };
|
||||||
7115BD3C2B84C0C200E0A610 /* TileContainerChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 7115BD3B2B84C0C200E0A610 /* TileContainerChangeLog.txt */; };
|
7115BD3C2B84C0C200E0A610 /* TileContainerChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 7115BD3B2B84C0C200E0A610 /* TileContainerChangeLog.txt */; };
|
||||||
|
71ACE89C2BA0451200FB6ADC /* PaginationContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71ACE89B2BA0451200FB6ADC /* PaginationContainer.swift */; };
|
||||||
|
71B23C2D2B91FA690027F7D9 /* Pagination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71B23C2C2B91FA690027F7D9 /* Pagination.swift */; };
|
||||||
|
71B5FCBB2B95A0CA00269BCC /* PaginationChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 71B5FCBA2B95A0CA00269BCC /* PaginationChangeLog.txt */; };
|
||||||
71ACE89E2BA1CC1700FB6ADC /* TiletEyebrowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71ACE89D2BA1CC1700FB6ADC /* TiletEyebrowModel.swift */; };
|
71ACE89E2BA1CC1700FB6ADC /* TiletEyebrowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71ACE89D2BA1CC1700FB6ADC /* TiletEyebrowModel.swift */; };
|
||||||
71BFA70A2B7F70E6000DCE33 /* DropShadowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BFA7092B7F70E6000DCE33 /* DropShadowable.swift */; };
|
71BFA70A2B7F70E6000DCE33 /* DropShadowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BFA7092B7F70E6000DCE33 /* DropShadowable.swift */; };
|
||||||
71C02B382B7BD98F00E93E66 /* NotificationChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 71C02B372B7BD98F00E93E66 /* NotificationChangeLog.txt */; };
|
71C02B382B7BD98F00E93E66 /* NotificationChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 71C02B372B7BD98F00E93E66 /* NotificationChangeLog.txt */; };
|
||||||
|
71FC86DA2B96F44C00700965 /* PaginationButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71FC86D92B96F44C00700965 /* PaginationButton.swift */; };
|
||||||
|
71FC86DC2B96F4C800700965 /* PaginationCellItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71FC86DB2B96F4C800700965 /* PaginationCellItem.swift */; };
|
||||||
71FC86DE2B9738B900700965 /* SurfaceConfigurationValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71FC86DD2B9738B900700965 /* SurfaceConfigurationValue.swift */; };
|
71FC86DE2B9738B900700965 /* SurfaceConfigurationValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71FC86DD2B9738B900700965 /* SurfaceConfigurationValue.swift */; };
|
||||||
71FC86E02B973AE500700965 /* DropShadowConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71FC86DF2B973AE500700965 /* DropShadowConfiguration.swift */; };
|
71FC86E02B973AE500700965 /* DropShadowConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71FC86DF2B973AE500700965 /* DropShadowConfiguration.swift */; };
|
||||||
|
71FC86E22B97483000700965 /* Clamping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71FC86E12B97483000700965 /* Clamping.swift */; };
|
||||||
|
71FC86E42B9841AC00700965 /* PaginationFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71FC86E32B9841AC00700965 /* PaginationFlowLayout.swift */; };
|
||||||
EA0B18022A9E236900F2D0CD /* SelectorGroupBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18012A9E236900F2D0CD /* SelectorGroupBase.swift */; };
|
EA0B18022A9E236900F2D0CD /* SelectorGroupBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18012A9E236900F2D0CD /* SelectorGroupBase.swift */; };
|
||||||
EA0B18052A9E2D2D00F2D0CD /* SelectorBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18032A9E2D2D00F2D0CD /* SelectorBase.swift */; };
|
EA0B18052A9E2D2D00F2D0CD /* SelectorBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18032A9E2D2D00F2D0CD /* SelectorBase.swift */; };
|
||||||
EA0B18062A9E2D2D00F2D0CD /* SelectorItemBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18042A9E2D2D00F2D0CD /* SelectorItemBase.swift */; };
|
EA0B18062A9E2D2D00F2D0CD /* SelectorItemBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0B18042A9E2D2D00F2D0CD /* SelectorItemBase.swift */; };
|
||||||
@ -153,6 +165,7 @@
|
|||||||
EAEEECAF2B1FC2BA00531FC2 /* ToggleViewChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = EAEEECAE2B1FC2BA00531FC2 /* ToggleViewChangeLog.txt */; };
|
EAEEECAF2B1FC2BA00531FC2 /* ToggleViewChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = EAEEECAE2B1FC2BA00531FC2 /* ToggleViewChangeLog.txt */; };
|
||||||
EAF1FE9929D4850E00101452 /* Clickable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF1FE9829D4850E00101452 /* Clickable.swift */; };
|
EAF1FE9929D4850E00101452 /* Clickable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF1FE9829D4850E00101452 /* Clickable.swift */; };
|
||||||
EAF1FE9B29DB1A6000101452 /* Changeable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF1FE9A29DB1A6000101452 /* Changeable.swift */; };
|
EAF1FE9B29DB1A6000101452 /* Changeable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF1FE9A29DB1A6000101452 /* Changeable.swift */; };
|
||||||
|
EAF4A6A12BAC8B94006BCC2C /* BreadcrumbsFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF4A6A02BAC8B94006BCC2C /* BreadcrumbsFlowLayout.swift */; };
|
||||||
EAF7F0952899861000B287F5 /* CheckboxItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0932899861000B287F5 /* CheckboxItem.swift */; };
|
EAF7F0952899861000B287F5 /* CheckboxItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0932899861000B287F5 /* CheckboxItem.swift */; };
|
||||||
EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0992899B17200B287F5 /* CATransaction.swift */; };
|
EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0992899B17200B287F5 /* CATransaction.swift */; };
|
||||||
EAF7F0A0289AB7EC00B287F5 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F09F289AB7EC00B287F5 /* View.swift */; };
|
EAF7F0A0289AB7EC00B287F5 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F09F289AB7EC00B287F5 /* View.swift */; };
|
||||||
@ -182,8 +195,13 @@
|
|||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
1832AC562BA0791D008AE476 /* BreadcrumbCellItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbCellItem.swift; sourceTree = "<group>"; };
|
||||||
|
18450CF02BA1B19C009FDF2A /* BreadcrumbsChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = BreadcrumbsChangeLog.txt; sourceTree = "<group>"; };
|
||||||
|
1855EC652BAABF2A002ACAC2 /* BreadcrumbItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbItemModel.swift; sourceTree = "<group>"; };
|
||||||
186B2A892B88DA7F001AB71F /* TextAreaChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TextAreaChangeLog.txt; sourceTree = "<group>"; };
|
186B2A892B88DA7F001AB71F /* TextAreaChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TextAreaChangeLog.txt; sourceTree = "<group>"; };
|
||||||
18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIconBadgeIndicatorModel.swift; sourceTree = "<group>"; };
|
18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIconBadgeIndicatorModel.swift; sourceTree = "<group>"; };
|
||||||
|
18A65A012B96E848006602CC /* Breadcrumbs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Breadcrumbs.swift; sourceTree = "<group>"; };
|
||||||
|
18A65A032B96F050006602CC /* BreadcrumbItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbItem.swift; sourceTree = "<group>"; };
|
||||||
18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = ButtonIconChangeLog.txt; sourceTree = "<group>"; };
|
18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = ButtonIconChangeLog.txt; sourceTree = "<group>"; };
|
||||||
445BA07729C07B3D0036A7C5 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
|
445BA07729C07B3D0036A7C5 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
|
||||||
44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationButtonModel.swift; sourceTree = "<group>"; };
|
44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationButtonModel.swift; sourceTree = "<group>"; };
|
||||||
@ -192,11 +210,18 @@
|
|||||||
5FC35BE228D51405004EBEAC /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = "<group>"; };
|
5FC35BE228D51405004EBEAC /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = "<group>"; };
|
||||||
710607942B91A99500F2863F /* TitleletChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TitleletChangeLog.txt; sourceTree = "<group>"; };
|
710607942B91A99500F2863F /* TitleletChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TitleletChangeLog.txt; sourceTree = "<group>"; };
|
||||||
7115BD3B2B84C0C200E0A610 /* TileContainerChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TileContainerChangeLog.txt; sourceTree = "<group>"; };
|
7115BD3B2B84C0C200E0A610 /* TileContainerChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TileContainerChangeLog.txt; sourceTree = "<group>"; };
|
||||||
|
71ACE89B2BA0451200FB6ADC /* PaginationContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationContainer.swift; sourceTree = "<group>"; };
|
||||||
|
71B23C2C2B91FA690027F7D9 /* Pagination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pagination.swift; sourceTree = "<group>"; };
|
||||||
|
71B5FCBA2B95A0CA00269BCC /* PaginationChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = PaginationChangeLog.txt; sourceTree = "<group>"; };
|
||||||
71ACE89D2BA1CC1700FB6ADC /* TiletEyebrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TiletEyebrowModel.swift; sourceTree = "<group>"; };
|
71ACE89D2BA1CC1700FB6ADC /* TiletEyebrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TiletEyebrowModel.swift; sourceTree = "<group>"; };
|
||||||
71BFA7092B7F70E6000DCE33 /* DropShadowable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropShadowable.swift; sourceTree = "<group>"; };
|
71BFA7092B7F70E6000DCE33 /* DropShadowable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropShadowable.swift; sourceTree = "<group>"; };
|
||||||
71C02B372B7BD98F00E93E66 /* NotificationChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = NotificationChangeLog.txt; sourceTree = "<group>"; };
|
71C02B372B7BD98F00E93E66 /* NotificationChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = NotificationChangeLog.txt; sourceTree = "<group>"; };
|
||||||
|
71FC86D92B96F44C00700965 /* PaginationButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationButton.swift; sourceTree = "<group>"; };
|
||||||
|
71FC86DB2B96F4C800700965 /* PaginationCellItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationCellItem.swift; sourceTree = "<group>"; };
|
||||||
71FC86DD2B9738B900700965 /* SurfaceConfigurationValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SurfaceConfigurationValue.swift; sourceTree = "<group>"; };
|
71FC86DD2B9738B900700965 /* SurfaceConfigurationValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SurfaceConfigurationValue.swift; sourceTree = "<group>"; };
|
||||||
71FC86DF2B973AE500700965 /* DropShadowConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropShadowConfiguration.swift; sourceTree = "<group>"; };
|
71FC86DF2B973AE500700965 /* DropShadowConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropShadowConfiguration.swift; sourceTree = "<group>"; };
|
||||||
|
71FC86E12B97483000700965 /* Clamping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Clamping.swift; sourceTree = "<group>"; };
|
||||||
|
71FC86E32B9841AC00700965 /* PaginationFlowLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationFlowLayout.swift; sourceTree = "<group>"; };
|
||||||
EA0B18012A9E236900F2D0CD /* SelectorGroupBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorGroupBase.swift; sourceTree = "<group>"; };
|
EA0B18012A9E236900F2D0CD /* SelectorGroupBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorGroupBase.swift; sourceTree = "<group>"; };
|
||||||
EA0B18032A9E2D2D00F2D0CD /* SelectorBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorBase.swift; sourceTree = "<group>"; };
|
EA0B18032A9E2D2D00F2D0CD /* SelectorBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorBase.swift; sourceTree = "<group>"; };
|
||||||
EA0B18042A9E2D2D00F2D0CD /* SelectorItemBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorItemBase.swift; sourceTree = "<group>"; };
|
EA0B18042A9E2D2D00F2D0CD /* SelectorItemBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorItemBase.swift; sourceTree = "<group>"; };
|
||||||
@ -330,6 +355,7 @@
|
|||||||
EAEEECAE2B1FC2BA00531FC2 /* ToggleViewChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = ToggleViewChangeLog.txt; sourceTree = "<group>"; };
|
EAEEECAE2B1FC2BA00531FC2 /* ToggleViewChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = ToggleViewChangeLog.txt; sourceTree = "<group>"; };
|
||||||
EAF1FE9829D4850E00101452 /* Clickable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Clickable.swift; sourceTree = "<group>"; };
|
EAF1FE9829D4850E00101452 /* Clickable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Clickable.swift; sourceTree = "<group>"; };
|
||||||
EAF1FE9A29DB1A6000101452 /* Changeable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Changeable.swift; sourceTree = "<group>"; };
|
EAF1FE9A29DB1A6000101452 /* Changeable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Changeable.swift; sourceTree = "<group>"; };
|
||||||
|
EAF4A6A02BAC8B94006BCC2C /* BreadcrumbsFlowLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbsFlowLayout.swift; sourceTree = "<group>"; };
|
||||||
EAF7F0932899861000B287F5 /* CheckboxItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxItem.swift; sourceTree = "<group>"; };
|
EAF7F0932899861000B287F5 /* CheckboxItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxItem.swift; sourceTree = "<group>"; };
|
||||||
EAF7F0992899B17200B287F5 /* CATransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CATransaction.swift; sourceTree = "<group>"; };
|
EAF7F0992899B17200B287F5 /* CATransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CATransaction.swift; sourceTree = "<group>"; };
|
||||||
EAF7F09F289AB7EC00B287F5 /* View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = "<group>"; };
|
EAF7F09F289AB7EC00B287F5 /* View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = "<group>"; };
|
||||||
@ -370,6 +396,19 @@
|
|||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
18A65A002B96E7E1006602CC /* Breadcrumbs */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
18A65A012B96E848006602CC /* Breadcrumbs.swift */,
|
||||||
|
EAF4A6A02BAC8B94006BCC2C /* BreadcrumbsFlowLayout.swift */,
|
||||||
|
18A65A032B96F050006602CC /* BreadcrumbItem.swift */,
|
||||||
|
1855EC652BAABF2A002ACAC2 /* BreadcrumbItemModel.swift */,
|
||||||
|
1832AC562BA0791D008AE476 /* BreadcrumbCellItem.swift */,
|
||||||
|
18450CF02BA1B19C009FDF2A /* BreadcrumbsChangeLog.txt */,
|
||||||
|
);
|
||||||
|
path = Breadcrumbs;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
445BA07629C07ABA0036A7C5 /* Notification */ = {
|
445BA07629C07ABA0036A7C5 /* Notification */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -398,6 +437,19 @@
|
|||||||
path = Button;
|
path = Button;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
71B23C2B2B91FA510027F7D9 /* Pagination */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
71B23C2C2B91FA690027F7D9 /* Pagination.swift */,
|
||||||
|
71ACE89B2BA0451200FB6ADC /* PaginationContainer.swift */,
|
||||||
|
71FC86D92B96F44C00700965 /* PaginationButton.swift */,
|
||||||
|
71FC86DB2B96F4C800700965 /* PaginationCellItem.swift */,
|
||||||
|
71FC86E32B9841AC00700965 /* PaginationFlowLayout.swift */,
|
||||||
|
71B5FCBA2B95A0CA00269BCC /* PaginationChangeLog.txt */,
|
||||||
|
);
|
||||||
|
path = Pagination;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
EA0B17FF2A9E21CA00F2D0CD /* Selector */ = {
|
EA0B17FF2A9E21CA00F2D0CD /* Selector */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -503,6 +555,7 @@
|
|||||||
children = (
|
children = (
|
||||||
EA4DB2FE28DCBC1900103EE3 /* Badge */,
|
EA4DB2FE28DCBC1900103EE3 /* Badge */,
|
||||||
EAD062AE2A3B87210015965D /* BadgeIndicator */,
|
EAD062AE2A3B87210015965D /* BadgeIndicator */,
|
||||||
|
18A65A002B96E7E1006602CC /* Breadcrumbs */,
|
||||||
EA0FC2BE2912D18200DF80B4 /* Buttons */,
|
EA0FC2BE2912D18200DF80B4 /* Buttons */,
|
||||||
EAF7F092289985E200B287F5 /* Checkbox */,
|
EAF7F092289985E200B287F5 /* Checkbox */,
|
||||||
EA985BF3296C609E00F2FF2E /* Icon */,
|
EA985BF3296C609E00F2FF2E /* Icon */,
|
||||||
@ -510,6 +563,7 @@
|
|||||||
44604AD529CE195300E62B51 /* Line */,
|
44604AD529CE195300E62B51 /* Line */,
|
||||||
EAD0688C2A55F801002E3A2D /* Loader */,
|
EAD0688C2A55F801002E3A2D /* Loader */,
|
||||||
445BA07629C07ABA0036A7C5 /* Notification */,
|
445BA07629C07ABA0036A7C5 /* Notification */,
|
||||||
|
71B23C2B2B91FA510027F7D9 /* Pagination */,
|
||||||
EA89200B28B530F0006B9984 /* RadioBox */,
|
EA89200B28B530F0006B9984 /* RadioBox */,
|
||||||
EAF7F11428A1470D00B287F5 /* RadioButton */,
|
EAF7F11428A1470D00B287F5 /* RadioButton */,
|
||||||
EA596ABB2A16B4D500300C4B /* Tabs */,
|
EA596ABB2A16B4D500300C4B /* Tabs */,
|
||||||
@ -600,6 +654,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
EA3361BC288B2C760071C351 /* TypeAlias.swift */,
|
EA3361BC288B2C760071C351 /* TypeAlias.swift */,
|
||||||
|
71FC86E12B97483000700965 /* Clamping.swift */,
|
||||||
71FC86DD2B9738B900700965 /* SurfaceConfigurationValue.swift */,
|
71FC86DD2B9738B900700965 /* SurfaceConfigurationValue.swift */,
|
||||||
71FC86DF2B973AE500700965 /* DropShadowConfiguration.swift */,
|
71FC86DF2B973AE500700965 /* DropShadowConfiguration.swift */,
|
||||||
);
|
);
|
||||||
@ -987,11 +1042,13 @@
|
|||||||
18BDEE822B75316E00452358 /* ButtonIconChangeLog.txt in Resources */,
|
18BDEE822B75316E00452358 /* ButtonIconChangeLog.txt in Resources */,
|
||||||
EA3362062891E14D0071C351 /* VerizonNHGeTX-Regular.otf in Resources */,
|
EA3362062891E14D0071C351 /* VerizonNHGeTX-Regular.otf in Resources */,
|
||||||
EA3362052891E14D0071C351 /* VerizonNHGeDS-Bold.otf in Resources */,
|
EA3362052891E14D0071C351 /* VerizonNHGeDS-Bold.otf in Resources */,
|
||||||
|
18450CF12BA1B19C009FDF2A /* BreadcrumbsChangeLog.txt in Resources */,
|
||||||
EAEEECA02B1F908200531FC2 /* BadgeIndicatorChangeLog.txt in Resources */,
|
EAEEECA02B1F908200531FC2 /* BadgeIndicatorChangeLog.txt in Resources */,
|
||||||
EAA5EEB928ECD24B003B3210 /* Icons.xcassets in Resources */,
|
EAA5EEB928ECD24B003B3210 /* Icons.xcassets in Resources */,
|
||||||
EAEEECA92B1F969700531FC2 /* TooltipChangeLog.txt in Resources */,
|
EAEEECA92B1F969700531FC2 /* TooltipChangeLog.txt in Resources */,
|
||||||
EAEEEC9C2B1F8F0700531FC2 /* TextLinkCaretChangeLog.txt in Resources */,
|
EAEEEC9C2B1F8F0700531FC2 /* TextLinkCaretChangeLog.txt in Resources */,
|
||||||
EAA5EEE428F5B855003B3210 /* VerizonNHGDS-Light.otf in Resources */,
|
EAA5EEE428F5B855003B3210 /* VerizonNHGDS-Light.otf in Resources */,
|
||||||
|
71B5FCBB2B95A0CA00269BCC /* PaginationChangeLog.txt in Resources */,
|
||||||
EAEEECAD2B1FC1A600531FC2 /* TitleLockupChangeLog.txt in Resources */,
|
EAEEECAD2B1FC1A600531FC2 /* TitleLockupChangeLog.txt in Resources */,
|
||||||
EAEEECAB2B1FBF2A00531FC2 /* ToggleChangeLog.txt in Resources */,
|
EAEEECAB2B1FBF2A00531FC2 /* ToggleChangeLog.txt in Resources */,
|
||||||
);
|
);
|
||||||
@ -1016,23 +1073,29 @@
|
|||||||
EAF7F0A6289B0CE000B287F5 /* Resetable.swift in Sources */,
|
EAF7F0A6289B0CE000B287F5 /* Resetable.swift in Sources */,
|
||||||
EA985C2D296F03FE00F2FF2E /* TileletIconModels.swift in Sources */,
|
EA985C2D296F03FE00F2FF2E /* TileletIconModels.swift in Sources */,
|
||||||
EA89200428AECF4B006B9984 /* UITextField+Publisher.swift in Sources */,
|
EA89200428AECF4B006B9984 /* UITextField+Publisher.swift in Sources */,
|
||||||
|
18A65A022B96E848006602CC /* Breadcrumbs.swift in Sources */,
|
||||||
EA0D1C3F2A6AD5E200E5C127 /* Typography+ContentSizeCategory.swift in Sources */,
|
EA0D1C3F2A6AD5E200E5C127 /* Typography+ContentSizeCategory.swift in Sources */,
|
||||||
EA5F86C82A1BD99100BC83E4 /* TabModel.swift in Sources */,
|
EA5F86C82A1BD99100BC83E4 /* TabModel.swift in Sources */,
|
||||||
EA0D1C432A6AD70900E5C127 /* VDSTypography.swift in Sources */,
|
EA0D1C432A6AD70900E5C127 /* VDSTypography.swift in Sources */,
|
||||||
EA297A5729FB0A360031ED56 /* AppleGuidelinesTouchable.swift in Sources */,
|
EA297A5729FB0A360031ED56 /* AppleGuidelinesTouchable.swift in Sources */,
|
||||||
|
1832AC572BA0791D008AE476 /* BreadcrumbCellItem.swift in Sources */,
|
||||||
EA3361C328902D960071C351 /* Toggle.swift in Sources */,
|
EA3361C328902D960071C351 /* Toggle.swift in Sources */,
|
||||||
EAF7F0A0289AB7EC00B287F5 /* View.swift in Sources */,
|
EAF7F0A0289AB7EC00B287F5 /* View.swift in Sources */,
|
||||||
EA89201328B568D8006B9984 /* RadioBoxItem.swift in Sources */,
|
EA89201328B568D8006B9984 /* RadioBoxItem.swift in Sources */,
|
||||||
|
71FC86E42B9841AC00700965 /* PaginationFlowLayout.swift in Sources */,
|
||||||
EAC9258C2911C9DE00091998 /* InputField.swift in Sources */,
|
EAC9258C2911C9DE00091998 /* InputField.swift in Sources */,
|
||||||
EA3362402892EF6C0071C351 /* Label.swift in Sources */,
|
EA3362402892EF6C0071C351 /* Label.swift in Sources */,
|
||||||
EAB2376229E9880400AABE9A /* TrailingTooltipLabel.swift in Sources */,
|
EAB2376229E9880400AABE9A /* TrailingTooltipLabel.swift in Sources */,
|
||||||
EAACB8982B92706F006A3869 /* DefaultValuing.swift in Sources */,
|
EAACB8982B92706F006A3869 /* DefaultValuing.swift in Sources */,
|
||||||
EAB2376A29E9E59100AABE9A /* TooltipLaunchable.swift in Sources */,
|
EAB2376A29E9E59100AABE9A /* TooltipLaunchable.swift in Sources */,
|
||||||
|
18A65A042B96F050006602CC /* BreadcrumbItem.swift in Sources */,
|
||||||
EAB2375D29E8789100AABE9A /* Tooltip.swift in Sources */,
|
EAB2375D29E8789100AABE9A /* Tooltip.swift in Sources */,
|
||||||
71BFA70A2B7F70E6000DCE33 /* DropShadowable.swift in Sources */,
|
71BFA70A2B7F70E6000DCE33 /* DropShadowable.swift in Sources */,
|
||||||
EA0D1C452A6AD73000E5C127 /* RawRepresentable.swift in Sources */,
|
EA0D1C452A6AD73000E5C127 /* RawRepresentable.swift in Sources */,
|
||||||
EA985C23296E033A00F2FF2E /* TextArea.swift in Sources */,
|
EA985C23296E033A00F2FF2E /* TextArea.swift in Sources */,
|
||||||
|
71FC86E22B97483000700965 /* Clamping.swift in Sources */,
|
||||||
EAF7F0B3289B1ADC00B287F5 /* ActionLabelAttribute.swift in Sources */,
|
EAF7F0B3289B1ADC00B287F5 /* ActionLabelAttribute.swift in Sources */,
|
||||||
|
1855EC662BAABF2A002ACAC2 /* BreadcrumbItemModel.swift in Sources */,
|
||||||
EAC925832911B35400091998 /* TextLinkCaret.swift in Sources */,
|
EAC925832911B35400091998 /* TextLinkCaret.swift in Sources */,
|
||||||
EA33622E2891EA3C0071C351 /* DispatchQueue+Once.swift in Sources */,
|
EA33622E2891EA3C0071C351 /* DispatchQueue+Once.swift in Sources */,
|
||||||
EA4DB2FD28D3D0CA00103EE3 /* AnyEquatable.swift in Sources */,
|
EA4DB2FD28D3D0CA00103EE3 /* AnyEquatable.swift in Sources */,
|
||||||
@ -1046,6 +1109,7 @@
|
|||||||
EAE785312BA0A438009428EA /* UIImage+Helper.swift in Sources */,
|
EAE785312BA0A438009428EA /* UIImage+Helper.swift in Sources */,
|
||||||
EAB5FEF5292D371F00998C17 /* ButtonBase.swift in Sources */,
|
EAB5FEF5292D371F00998C17 /* ButtonBase.swift in Sources */,
|
||||||
EA978EC5291D6AFE00ACC883 /* AnyLabelAttribute.swift in Sources */,
|
EA978EC5291D6AFE00ACC883 /* AnyLabelAttribute.swift in Sources */,
|
||||||
|
71ACE89C2BA0451200FB6ADC /* PaginationContainer.swift in Sources */,
|
||||||
EAC71A1F2A2E173D00E47A9F /* RadioButton.swift in Sources */,
|
EAC71A1F2A2E173D00E47A9F /* RadioButton.swift in Sources */,
|
||||||
EA33622C2891E73B0071C351 /* FontProtocol.swift in Sources */,
|
EA33622C2891E73B0071C351 /* FontProtocol.swift in Sources */,
|
||||||
EA596ABD2A16B4EC00300C4B /* Tab.swift in Sources */,
|
EA596ABD2A16B4EC00300C4B /* Tab.swift in Sources */,
|
||||||
@ -1054,6 +1118,7 @@
|
|||||||
EA985BEE2968A92400F2FF2E /* TitleLockupSubTitleModel.swift in Sources */,
|
EA985BEE2968A92400F2FF2E /* TitleLockupSubTitleModel.swift in Sources */,
|
||||||
EA985BF22968B5BB00F2FF2E /* TitleLockupTextStyle.swift in Sources */,
|
EA985BF22968B5BB00F2FF2E /* TitleLockupTextStyle.swift in Sources */,
|
||||||
EAB1D2CD28ABE76100DAE764 /* Withable.swift in Sources */,
|
EAB1D2CD28ABE76100DAE764 /* Withable.swift in Sources */,
|
||||||
|
71FC86DC2B96F4C800700965 /* PaginationCellItem.swift in Sources */,
|
||||||
EAC846F3294B95CE00F685BA /* ButtonGroupCollectionViewCell.swift in Sources */,
|
EAC846F3294B95CE00F685BA /* ButtonGroupCollectionViewCell.swift in Sources */,
|
||||||
EAF7F0952899861000B287F5 /* CheckboxItem.swift in Sources */,
|
EAF7F0952899861000B287F5 /* CheckboxItem.swift in Sources */,
|
||||||
EA985BE82968951C00F2FF2E /* TileletTitleModel.swift in Sources */,
|
EA985BE82968951C00F2FF2E /* TileletTitleModel.swift in Sources */,
|
||||||
@ -1071,13 +1136,16 @@
|
|||||||
EAC9258F2911C9DE00091998 /* EntryFieldBase.swift in Sources */,
|
EAC9258F2911C9DE00091998 /* EntryFieldBase.swift in Sources */,
|
||||||
EAB1D2EA28AE84AA00DAE764 /* UIControlPublisher.swift in Sources */,
|
EAB1D2EA28AE84AA00DAE764 /* UIControlPublisher.swift in Sources */,
|
||||||
EAD068922A560B65002E3A2D /* LoaderViewController.swift in Sources */,
|
EAD068922A560B65002E3A2D /* LoaderViewController.swift in Sources */,
|
||||||
|
71FC86DA2B96F44C00700965 /* PaginationButton.swift in Sources */,
|
||||||
EABFEB642A26473700C4C106 /* NSAttributedString.swift in Sources */,
|
EABFEB642A26473700C4C106 /* NSAttributedString.swift in Sources */,
|
||||||
EAF7F13328A2A16500B287F5 /* AttachmentLabelAttributeModel.swift in Sources */,
|
EAF7F13328A2A16500B287F5 /* AttachmentLabelAttributeModel.swift in Sources */,
|
||||||
|
EAF4A6A12BAC8B94006BCC2C /* BreadcrumbsFlowLayout.swift in Sources */,
|
||||||
EA0FC2C62914222900DF80B4 /* ButtonGroup.swift in Sources */,
|
EA0FC2C62914222900DF80B4 /* ButtonGroup.swift in Sources */,
|
||||||
EA89200628B526D6006B9984 /* CheckboxGroup.swift in Sources */,
|
EA89200628B526D6006B9984 /* CheckboxGroup.swift in Sources */,
|
||||||
EA8E40932A82889500934ED3 /* TooltipDialog.swift in Sources */,
|
EA8E40932A82889500934ED3 /* TooltipDialog.swift in Sources */,
|
||||||
44604AD429CE186A00E62B51 /* NotificationButtonModel.swift in Sources */,
|
44604AD429CE186A00E62B51 /* NotificationButtonModel.swift in Sources */,
|
||||||
EAD8D2C128BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift in Sources */,
|
EAD8D2C128BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift in Sources */,
|
||||||
|
71B23C2D2B91FA690027F7D9 /* Pagination.swift in Sources */,
|
||||||
EA0D1C372A681CCE00E5C127 /* ToggleView.swift in Sources */,
|
EA0D1C372A681CCE00E5C127 /* ToggleView.swift in Sources */,
|
||||||
EAF7F0B9289C139800B287F5 /* ColorConfiguration.swift in Sources */,
|
EAF7F0B9289C139800B287F5 /* ColorConfiguration.swift in Sources */,
|
||||||
EA3361BD288B2C760071C351 /* TypeAlias.swift in Sources */,
|
EA3361BD288B2C760071C351 /* TypeAlias.swift in Sources */,
|
||||||
|
|||||||
94
VDS/Components/Breadcrumbs/BreadcrumbCellItem.swift
Normal file
94
VDS/Components/Breadcrumbs/BreadcrumbCellItem.swift
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
//
|
||||||
|
// BreadcrumbCellItem.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Kanamarlapudi, Vasavi on 11/03/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import VDSColorTokens
|
||||||
|
|
||||||
|
///This is customised view for Breadcrumb cell item
|
||||||
|
final class BreadcrumbCellItem: UICollectionViewCell {
|
||||||
|
|
||||||
|
///Identifier for the BreadcrumbCellItem
|
||||||
|
static let identifier: String = String(describing: BreadcrumbCellItem.self)
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Private Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
internal var stackView: UIStackView = {
|
||||||
|
return UIStackView().with {
|
||||||
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
$0.axis = .horizontal
|
||||||
|
$0.distribution = .fill
|
||||||
|
$0.alignment = .fill
|
||||||
|
$0.spacing = VDSLayout.Spacing.space1X.value
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
internal var breadCrumbItem: BreadcrumbItem?
|
||||||
|
|
||||||
|
///separator label
|
||||||
|
private var separator: Label = Label().with {
|
||||||
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
$0.textAlignment = .left
|
||||||
|
$0.numberOfLines = 1
|
||||||
|
$0.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
|
||||||
|
$0.setContentHuggingPriority(.defaultHigh, for: .horizontal)
|
||||||
|
$0.text = "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
private let textColorConfiguration = SurfaceColorConfiguration(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark)
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initializers
|
||||||
|
//--------------------------------------------------
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
setUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
setUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
///Configuring the cell with default setup
|
||||||
|
private func setUp() {
|
||||||
|
separator.textColorConfiguration = textColorConfiguration.eraseToAnyColorable()
|
||||||
|
contentView.addSubview(stackView)
|
||||||
|
stackView.pinToSuperView()
|
||||||
|
separator.backgroundColor = .clear
|
||||||
|
}
|
||||||
|
|
||||||
|
///Updating the breadCrumbItem and UI based on the selected flag along with the surface
|
||||||
|
func update(surface: Surface, hideSlash: Bool, breadCrumbItem: BreadcrumbItem) {
|
||||||
|
//remove views from stack
|
||||||
|
separator.removeFromSuperview()
|
||||||
|
self.breadCrumbItem?.removeFromSuperview()
|
||||||
|
|
||||||
|
//update surface
|
||||||
|
separator.surface = surface
|
||||||
|
breadCrumbItem.surface = surface
|
||||||
|
|
||||||
|
//add to stack
|
||||||
|
stackView.addArrangedSubview(separator)
|
||||||
|
stackView.addArrangedSubview(breadCrumbItem)
|
||||||
|
stackView.setCustomSpacing(VDSLayout.Spacing.space1X.value, after: separator)
|
||||||
|
|
||||||
|
//update separator
|
||||||
|
separator.textColor = textColorConfiguration.getColor(surface)
|
||||||
|
separator.isHidden = hideSlash
|
||||||
|
|
||||||
|
self.breadCrumbItem = breadCrumbItem
|
||||||
|
layoutIfNeeded()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove views from StackView.
|
||||||
|
override func prepareForReuse() {
|
||||||
|
super.prepareForReuse()
|
||||||
|
separator.removeFromSuperview()
|
||||||
|
breadCrumbItem?.removeFromSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
89
VDS/Components/Breadcrumbs/BreadcrumbItem.swift
Normal file
89
VDS/Components/Breadcrumbs/BreadcrumbItem.swift
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
//
|
||||||
|
// BreadcrumbItem.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Kanamarlapudi, Vasavi on 05/03/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import VDSColorTokens
|
||||||
|
import VDSFormControlsTokens
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
/// A Breadcrumb Item contains href(link) and selected flag.
|
||||||
|
/// Breadcrumb links to its respective page if it is not disabled.
|
||||||
|
/// Breadcrumb contains text with a separator by default, highlights text in bold without a separator if selected.
|
||||||
|
@objc (VDSBreadcrumbItem)
|
||||||
|
open class BreadcrumbItem: ButtonBase {
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initializers
|
||||||
|
//--------------------------------------------------
|
||||||
|
required public init() {
|
||||||
|
super.init(frame: .zero)
|
||||||
|
}
|
||||||
|
|
||||||
|
public override init(frame: CGRect) {
|
||||||
|
super.init(frame: .zero)
|
||||||
|
}
|
||||||
|
|
||||||
|
public required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Public Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
/// TextStyle used on the titleLabel.
|
||||||
|
open override var textStyle: TextStyle { isSelected ? TextStyle.boldBodySmall : TextStyle.bodySmall }
|
||||||
|
|
||||||
|
/// UIColor used on the titleLabel text.
|
||||||
|
open override var textColor: UIColor {
|
||||||
|
textColorConfiguration.getColor(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The natural size for the receiving view, considering only properties of the view itself.
|
||||||
|
open override var intrinsicContentSize: CGSize {
|
||||||
|
return titleLabel?.intrinsicContentSize ?? super.intrinsicContentSize
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Private Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
private var textColorConfiguration = ControlColorConfiguration().with {
|
||||||
|
$0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal)
|
||||||
|
$0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .disabled)
|
||||||
|
$0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .highlighted)
|
||||||
|
$0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .selected)
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Overrides
|
||||||
|
//--------------------------------------------------
|
||||||
|
/// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations.
|
||||||
|
open override func setup() {
|
||||||
|
super.setup()
|
||||||
|
isAccessibilityElement = true
|
||||||
|
accessibilityTraits = .button
|
||||||
|
accessibilityLabel = "Breadcrumb"
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used to make changes to the View based off a change events or from local properties.
|
||||||
|
open override func updateView() {
|
||||||
|
//always call last so the label is rendered
|
||||||
|
super.updateView()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resets to default settings.
|
||||||
|
open override func reset() {
|
||||||
|
super.reset()
|
||||||
|
shouldUpdateView = false
|
||||||
|
text = nil
|
||||||
|
accessibilityCustomActions = []
|
||||||
|
isAccessibilityElement = true
|
||||||
|
accessibilityTraits = .button
|
||||||
|
shouldUpdateView = true
|
||||||
|
setNeedsUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
32
VDS/Components/Breadcrumbs/BreadcrumbItemModel.swift
Normal file
32
VDS/Components/Breadcrumbs/BreadcrumbItemModel.swift
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// BreadcrumbItemModel.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Kanamarlapudi, Vasavi on 20/03/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension Breadcrumbs {
|
||||||
|
public struct BreadcrumbItemModel {
|
||||||
|
|
||||||
|
///Text that goes in the breadcrumb item
|
||||||
|
public var text: String
|
||||||
|
|
||||||
|
/// Whether the Item can be clicked.
|
||||||
|
public var enabled: Bool
|
||||||
|
|
||||||
|
/// The Breadcrumb link to links to its respective page.
|
||||||
|
public var selected: Bool
|
||||||
|
|
||||||
|
///Click event when you click on a breadcrumb item
|
||||||
|
public var onClick: ((BreadcrumbItem) -> Void)?
|
||||||
|
|
||||||
|
public init(text: String, enabeled: Bool = true, selected: Bool = false, onClick: ((BreadcrumbItem) -> Void)? = nil) {
|
||||||
|
self.text = text
|
||||||
|
self.enabled = enabeled
|
||||||
|
self.selected = selected
|
||||||
|
self.onClick = onClick
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
154
VDS/Components/Breadcrumbs/Breadcrumbs.swift
Normal file
154
VDS/Components/Breadcrumbs/Breadcrumbs.swift
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
//
|
||||||
|
// Breadcrumbs.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Kanamarlapudi, Vasavi on 11/03/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import VDSColorTokens
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
/// A Breadcrumbs contains BreadcrumbItems.
|
||||||
|
/// It contains Breadcrumb Item Default, Breadcrumb Item Selected, Separator.
|
||||||
|
/// 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.
|
||||||
|
@objc(VDSBreadcrumbs)
|
||||||
|
open class Breadcrumbs: View {
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Public Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
/// Array of ``BreadcrumbItem`` views for the Breadcrumbs.
|
||||||
|
open var breadcrumbs: [BreadcrumbItem] = [] { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
|
/// Array of ``BreadcurmbItemModel`` you are wanting to show.
|
||||||
|
open var breadcrumbModels: [BreadcrumbItemModel] = [] { didSet { updateBreadcrumbItems() } }
|
||||||
|
|
||||||
|
/// Whether this object is enabled or not
|
||||||
|
override open var isEnabled: Bool {
|
||||||
|
didSet {
|
||||||
|
breadcrumbs.forEach { $0.isEnabled = isEnabled }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Current Surface and this is used to pass down to child objects that implement Surfacable
|
||||||
|
override open var surface: Surface {
|
||||||
|
didSet {
|
||||||
|
breadcrumbs.forEach { $0.surface = surface }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A callback when the selected item changes. Passes parameters (crumb).
|
||||||
|
open var onBreadcrumbDidSelect: ((BreadcrumbItem) -> Void)?
|
||||||
|
|
||||||
|
/// A callback when the Tab determine if a item should be selected.
|
||||||
|
open var onBreadcrumbShouldSelect:((BreadcrumbItem) -> Bool)?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Private Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
let layout: UICollectionViewFlowLayout = BreadcrumbsFlowLayout().with {
|
||||||
|
$0.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
|
||||||
|
$0.minimumInteritemSpacing = VDSLayout.Spacing.space1X.value
|
||||||
|
$0.minimumLineSpacing = VDSLayout.Spacing.space1X.value
|
||||||
|
$0.sectionInset = .zero
|
||||||
|
$0.scrollDirection = .vertical
|
||||||
|
}
|
||||||
|
|
||||||
|
///Collectionview to render Breadcrumb Items
|
||||||
|
private lazy var collectionView: SelfSizingCollectionView = {
|
||||||
|
let collectionView = SelfSizingCollectionView(frame: .zero, collectionViewLayout: layout)
|
||||||
|
collectionView.isScrollEnabled = false
|
||||||
|
collectionView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
collectionView.delegate = self
|
||||||
|
collectionView.dataSource = self
|
||||||
|
collectionView.showsHorizontalScrollIndicator = false
|
||||||
|
collectionView.showsVerticalScrollIndicator = false
|
||||||
|
collectionView.register(BreadcrumbCellItem.self, forCellWithReuseIdentifier: BreadcrumbCellItem.identifier)
|
||||||
|
collectionView.backgroundColor = .clear
|
||||||
|
return collectionView
|
||||||
|
}()
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Private Methods
|
||||||
|
//--------------------------------------------------
|
||||||
|
/// Removes all of the Breadcrumbs and creates new ones from the Breadcrumb Models property.
|
||||||
|
private func updateBreadcrumbItems() {
|
||||||
|
// Clear existing breadcrumbs
|
||||||
|
for breadcrumbItem in breadcrumbs {
|
||||||
|
breadcrumbItem.removeFromSuperview()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new breadcrumb items from the models
|
||||||
|
breadcrumbs = breadcrumbModels.compactMap({ model in
|
||||||
|
let breadcrumbItem = BreadcrumbItem()
|
||||||
|
breadcrumbItem.text = model.text
|
||||||
|
breadcrumbItem.isEnabled = model.enabled
|
||||||
|
breadcrumbItem.isSelected = model.selected
|
||||||
|
breadcrumbItem.onClick = { [weak self] breadcrumb in
|
||||||
|
guard let self, breadcrumb.isEnabled else { return }
|
||||||
|
if self.onBreadcrumbShouldSelect?(breadcrumb) ?? true {
|
||||||
|
model.onClick?(breadcrumb)
|
||||||
|
self.onBreadcrumbDidSelect?(breadcrumb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return breadcrumbItem
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------s--------
|
||||||
|
// MARK: - Overrides
|
||||||
|
//--------------------------------------------------
|
||||||
|
/// Executed on initialization for this View.
|
||||||
|
open override func initialSetup() {
|
||||||
|
super.initialSetup()
|
||||||
|
addSubview(collectionView)
|
||||||
|
collectionView.pinToSuperView()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resets to default settings.
|
||||||
|
open override func reset() {
|
||||||
|
super.reset()
|
||||||
|
shouldUpdateView = false
|
||||||
|
breadcrumbs.forEach { $0.reset() }
|
||||||
|
shouldUpdateView = true
|
||||||
|
setNeedsUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used to make changes to the View based off a change events or from local properties.
|
||||||
|
open override func updateView() {
|
||||||
|
super.updateView()
|
||||||
|
collectionView.reloadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func layoutSubviews() {
|
||||||
|
//Turn off the ability to execute updateView() in the super
|
||||||
|
//since we don't want an infinite loop
|
||||||
|
shouldUpdateView = false
|
||||||
|
super.layoutSubviews()
|
||||||
|
shouldUpdateView = true
|
||||||
|
|
||||||
|
// Accounts for any collection size changes
|
||||||
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
guard let self else { return }
|
||||||
|
self.collectionView.collectionViewLayout.invalidateLayout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Breadcrumbs: UICollectionViewDelegate, UICollectionViewDataSource {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - UICollectionView Delegate & Datasource
|
||||||
|
//--------------------------------------------------
|
||||||
|
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||||
|
breadcrumbs.count
|
||||||
|
}
|
||||||
|
|
||||||
|
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||||
|
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: BreadcrumbCellItem.identifier, for: indexPath) as? BreadcrumbCellItem else { return UICollectionViewCell() }
|
||||||
|
let hideSlash = indexPath.row == 0
|
||||||
|
cell.update(surface: surface, hideSlash: hideSlash, breadCrumbItem: breadcrumbs[indexPath.row])
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
36
VDS/Components/Breadcrumbs/BreadcrumbsChangeLog.txt
Normal file
36
VDS/Components/Breadcrumbs/BreadcrumbsChangeLog.txt
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
MM/DD/YYYY
|
||||||
|
----------------
|
||||||
|
- Initial Brand 3.0 handoff
|
||||||
|
|
||||||
|
12/17/2021
|
||||||
|
----------------
|
||||||
|
- Replaced focusring colors (previously interactive/onlight/ondark) with accessibility/onlight/ondark colors
|
||||||
|
- Updated focus border name (previously interactive.focusring.onlight) with focusring.onlight/ondark
|
||||||
|
|
||||||
|
2/28/2022
|
||||||
|
----------------
|
||||||
|
- Changed Last Breadcrumb Item to Selected Item
|
||||||
|
|
||||||
|
03/08/2022
|
||||||
|
----------------
|
||||||
|
- Added dev note for Active and Hover states.
|
||||||
|
|
||||||
|
08/04/2022
|
||||||
|
----------------
|
||||||
|
- Updated default and inverted prop to light and dark surface.
|
||||||
|
|
||||||
|
11/30/2022
|
||||||
|
----------------
|
||||||
|
- Added "(web only)" to any instance of "keyboard focus"
|
||||||
|
|
||||||
|
12/13/2022
|
||||||
|
----------------
|
||||||
|
- Replaced focus border pixel and style & spacing values with tokens.
|
||||||
|
|
||||||
|
01/03/2022
|
||||||
|
----------------
|
||||||
|
- Updated Specs to use new SPEC Templates and SPEC DOC Components.
|
||||||
|
|
||||||
|
01/06/2023
|
||||||
|
----------------
|
||||||
|
- Tweaked anatomy element naming to align with design doc and dev doc
|
||||||
31
VDS/Components/Breadcrumbs/BreadcrumbsFlowLayout.swift
Normal file
31
VDS/Components/Breadcrumbs/BreadcrumbsFlowLayout.swift
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// BreadcrumsFlowLayout.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 3/21/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class BreadcrumbsFlowLayout: UICollectionViewFlowLayout {
|
||||||
|
|
||||||
|
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
|
||||||
|
let attributes = super.layoutAttributesForElements(in: rect)
|
||||||
|
|
||||||
|
var leftMargin = sectionInset.left
|
||||||
|
var maxY: CGFloat = -1.0
|
||||||
|
attributes?.forEach { layoutAttribute in
|
||||||
|
if layoutAttribute.frame.origin.y >= maxY {
|
||||||
|
leftMargin = sectionInset.left
|
||||||
|
}
|
||||||
|
|
||||||
|
layoutAttribute.frame.origin.x = leftMargin
|
||||||
|
|
||||||
|
leftMargin += layoutAttribute.frame.width + minimumInteritemSpacing
|
||||||
|
maxY = max(layoutAttribute.frame.maxY , maxY)
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributes
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -97,6 +97,9 @@ open class ButtonBase: UIButton, ViewProtocol, UserInfoable, Clickable {
|
|||||||
/// Whether the Control is enabled or not.
|
/// Whether the Control is enabled or not.
|
||||||
open override var isEnabled: Bool { didSet { setNeedsUpdate() } }
|
open override var isEnabled: Bool { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
|
/// Whether the Control is selected or not.
|
||||||
|
open override var isSelected: Bool { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Lifecycle
|
// MARK: - Lifecycle
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -48,7 +48,6 @@ extension Icon {
|
|||||||
internal static let paginationRightCaret = Name(name: "pagination-right-caret")
|
internal static let paginationRightCaret = Name(name: "pagination-right-caret")
|
||||||
internal static let verizonUp = Name(name: "verizon-up")
|
internal static let verizonUp = Name(name: "verizon-up")
|
||||||
internal static let warningBold = Name(name: "warning-bold")
|
internal static let warningBold = Name(name: "warning-bold")
|
||||||
|
|
||||||
public static let checkmark = Name(name: "checkmark")
|
public static let checkmark = Name(name: "checkmark")
|
||||||
public static let checkmarkAlt = Name(name: "checkmark-alt")
|
public static let checkmarkAlt = Name(name: "checkmark-alt")
|
||||||
public static let close = Name(name: "close")
|
public static let close = Name(name: "close")
|
||||||
|
|||||||
@ -56,6 +56,8 @@ public struct ActionLabelAttribute: ActionLabelAttributeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func setAttribute(on attributedString: NSMutableAttributedString) {
|
public func setAttribute(on attributedString: NSMutableAttributedString) {
|
||||||
|
guard isValidRange(on: attributedString) else { return }
|
||||||
|
|
||||||
if(shouldUnderline){
|
if(shouldUnderline){
|
||||||
UnderlineLabelAttribute(location: location, length: length).setAttribute(on: attributedString)
|
UnderlineLabelAttribute(location: location, length: length).setAttribute(on: attributedString)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,8 @@ public protocol AttachmentLabelAttributeModel: LabelAttributeModel {
|
|||||||
|
|
||||||
extension AttachmentLabelAttributeModel {
|
extension AttachmentLabelAttributeModel {
|
||||||
public func setAttribute(on attributedString: NSMutableAttributedString) {
|
public func setAttribute(on attributedString: NSMutableAttributedString) {
|
||||||
|
guard isValidRange(on: attributedString) else { return }
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let mutableString = NSMutableAttributedString()
|
let mutableString = NSMutableAttributedString()
|
||||||
let attachment = try getAttachment()
|
let attachment = try getAttachment()
|
||||||
|
|||||||
@ -31,11 +31,21 @@ extension LabelAttributeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func isValidRange(on attributedString: NSMutableAttributedString) -> Bool {
|
public func isValidRange(on attributedString: NSMutableAttributedString) -> Bool {
|
||||||
range.location + range.length <= attributedString.string.count
|
attributedString.isValid(range: range)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension String {
|
||||||
|
func isValid(range: NSRange) -> Bool {
|
||||||
|
range.location >= 0 && range.length > 0 && range.location + range.length <= count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension NSAttributedString {
|
public extension NSAttributedString {
|
||||||
|
func isValid(range: NSRange) -> Bool {
|
||||||
|
range.location >= 0 && range.length > 0 && range.location + range.length <= length
|
||||||
|
}
|
||||||
|
|
||||||
func createAttributeModels() -> [(any LabelAttributeModel)] {
|
func createAttributeModels() -> [(any LabelAttributeModel)] {
|
||||||
var attributes: [any VDS.LabelAttributeModel] = []
|
var attributes: [any VDS.LabelAttributeModel] = []
|
||||||
enumerateAttributes(in: NSMakeRange(0, length)) { attributeMap, range, stop in
|
enumerateAttributes(in: NSMakeRange(0, length)) { attributeMap, range, stop in
|
||||||
@ -61,6 +71,7 @@ public extension NSAttributedString {
|
|||||||
|
|
||||||
extension NSMutableAttributedString {
|
extension NSMutableAttributedString {
|
||||||
public func apply(attribute: any LabelAttributeModel) {
|
public func apply(attribute: any LabelAttributeModel) {
|
||||||
|
guard isValid(range: attribute.range) else { return }
|
||||||
attribute.setAttribute(on: self)
|
attribute.setAttribute(on: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,9 @@ public class TooltipLabelAttribute: ActionLabelAttributeModel, TooltipLaunchable
|
|||||||
public var presenter: UIView?
|
public var presenter: UIView?
|
||||||
|
|
||||||
public func setAttribute(on attributedString: NSMutableAttributedString) {
|
public func setAttribute(on attributedString: NSMutableAttributedString) {
|
||||||
//update the location
|
guard isValidRange(on: attributedString) else { return }
|
||||||
|
|
||||||
|
//update the location
|
||||||
location = attributedString.string.count - 1
|
location = attributedString.string.count - 1
|
||||||
|
|
||||||
//set the default color off surface for text
|
//set the default color off surface for text
|
||||||
|
|||||||
@ -344,7 +344,7 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
|
|||||||
for attribute in attributes {
|
for attribute in attributes {
|
||||||
|
|
||||||
//see if the attribute is Actionable
|
//see if the attribute is Actionable
|
||||||
if let actionable = attribute as? any ActionLabelAttributeModel{
|
if let actionable = attribute as? any ActionLabelAttributeModel, mutableAttributedString.isValid(range: actionable.range) {
|
||||||
//create a accessibleAction
|
//create a accessibleAction
|
||||||
let customAccessibilityAction = customAccessibilityAction(text: mutableAttributedString.string, range: actionable.range, accessibleText: actionable.accessibleText)
|
let customAccessibilityAction = customAccessibilityAction(text: mutableAttributedString.string, range: actionable.range, accessibleText: actionable.accessibleText)
|
||||||
|
|
||||||
@ -379,7 +379,7 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
|
|||||||
|
|
||||||
guard let text = text, let attributedText else { return nil }
|
guard let text = text, let attributedText else { return nil }
|
||||||
|
|
||||||
let actionText = accessibleText ?? NSString(string:text).substring(with: range)
|
let actionText = accessibleText ?? (text.isValid(range: range) ? NSString(string:text).substring(with: range) : text)
|
||||||
|
|
||||||
// Calculate the frame of the substring
|
// Calculate the frame of the substring
|
||||||
let layoutManager = NSLayoutManager()
|
let layoutManager = NSLayoutManager()
|
||||||
|
|||||||
@ -53,11 +53,6 @@ open class Notification: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enum used to describe the orientation of Notification.
|
|
||||||
public enum Layout: String, CaseIterable {
|
|
||||||
case vertical, horizontal
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Private Properties
|
// MARK: - Private Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -80,19 +75,9 @@ open class Notification: View {
|
|||||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private var labelButtonViewSpacing: CGFloat {
|
private var labelButtonViewSpacing: CGFloat { UIDevice.isIPad ? 20 : 16 }
|
||||||
let spacing: CGFloat = UIDevice.isIPad ? 20 : 16
|
|
||||||
return switch layout {
|
|
||||||
case .vertical:
|
|
||||||
0
|
|
||||||
case .horizontal:
|
|
||||||
spacing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal var onCloseSubscriber: AnyCancellable?
|
internal var onCloseSubscriber: AnyCancellable?
|
||||||
|
|
||||||
private var maxWidthConstraint: NSLayoutConstraint?
|
|
||||||
|
|
||||||
private var leadingConstraint: NSLayoutConstraint?
|
private var leadingConstraint: NSLayoutConstraint?
|
||||||
|
|
||||||
@ -172,19 +157,6 @@ open class Notification: View {
|
|||||||
|
|
||||||
/// Add this attribute determine your type of Notification.
|
/// Add this attribute determine your type of Notification.
|
||||||
open var style: Style = .info { didSet { setNeedsUpdate()}}
|
open var style: Style = .info { didSet { setNeedsUpdate()}}
|
||||||
|
|
||||||
private var _layout: Layout = .vertical
|
|
||||||
|
|
||||||
/// Determines the orientation of buttons and text in the Notification.
|
|
||||||
open var layout: Layout {
|
|
||||||
set {
|
|
||||||
if !UIDevice.isIPad, newValue == .horizontal { return }
|
|
||||||
_layout = newValue
|
|
||||||
buttonGroup.alignment = _layout == .horizontal ? .center : .left
|
|
||||||
setNeedsUpdate()
|
|
||||||
}
|
|
||||||
get { _layout }
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Configuration
|
// MARK: - Configuration
|
||||||
@ -219,18 +191,11 @@ open class Notification: View {
|
|||||||
return 288
|
return 288
|
||||||
}
|
}
|
||||||
|
|
||||||
private var maxViewWidth: CGFloat {
|
|
||||||
return 1232
|
|
||||||
}
|
|
||||||
|
|
||||||
private var labelViewWidthConstraint: NSLayoutConstraint?
|
|
||||||
private var labelViewBottomConstraint: NSLayoutConstraint?
|
private var labelViewBottomConstraint: NSLayoutConstraint?
|
||||||
private var labelViewAndButtonViewConstraint: NSLayoutConstraint?
|
private var labelViewAndButtonViewConstraint: NSLayoutConstraint?
|
||||||
private var buttonViewTopConstraint: NSLayoutConstraint?
|
private var buttonViewTopConstraint: NSLayoutConstraint?
|
||||||
private var typeIconWidthConstraint: NSLayoutConstraint?
|
private var typeIconWidthConstraint: NSLayoutConstraint?
|
||||||
private var closeIconWidthConstraint: NSLayoutConstraint?
|
private var closeIconWidthConstraint: NSLayoutConstraint?
|
||||||
private var buttonGroupCenterYConstraint: NSLayoutConstraint?
|
|
||||||
private var buttonGroupBottomConstraint: NSLayoutConstraint?
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Overrides
|
// MARK: - Overrides
|
||||||
@ -255,21 +220,18 @@ open class Notification: View {
|
|||||||
mainStackView.heightAnchor.constraint(greaterThanOrEqualToConstant: minContentHeight),
|
mainStackView.heightAnchor.constraint(greaterThanOrEqualToConstant: minContentHeight),
|
||||||
layoutGuide.widthAnchor.constraint(greaterThanOrEqualToConstant: minViewWidth)
|
layoutGuide.widthAnchor.constraint(greaterThanOrEqualToConstant: minViewWidth)
|
||||||
])
|
])
|
||||||
maxWidthConstraint = layoutGuide.widthAnchor.constraint(lessThanOrEqualToConstant: maxViewWidth)
|
|
||||||
|
|
||||||
labelButtonView.addSubview(labelsView)
|
labelButtonView.addSubview(labelsView)
|
||||||
labelsView
|
labelsView
|
||||||
.pinTop()
|
.pinTop()
|
||||||
.pinLeading()
|
.pinLeading()
|
||||||
labelViewWidthConstraint = labelsView.widthAnchor.constraint(equalTo: labelButtonView.widthAnchor, multiplier: 1.0)
|
labelsView.widthAnchor.constraint(equalTo: labelButtonView.widthAnchor, multiplier: 1.0).activate()
|
||||||
labelViewWidthConstraint?.activate()
|
|
||||||
labelViewBottomConstraint = labelButtonView.bottomAnchor.constraint(equalTo: labelsView.bottomAnchor)
|
labelViewBottomConstraint = labelButtonView.bottomAnchor.constraint(equalTo: labelsView.bottomAnchor)
|
||||||
|
|
||||||
labelButtonView.addSubview(buttonGroup)
|
labelButtonView.addSubview(buttonGroup)
|
||||||
buttonGroup
|
buttonGroup
|
||||||
.pinTrailing()
|
.pinTrailing()
|
||||||
buttonGroupBottomConstraint = labelButtonView.bottomAnchor.constraint(equalTo: buttonGroup.bottomAnchor)
|
labelButtonView.bottomAnchor.constraint(equalTo: buttonGroup.bottomAnchor).activate()
|
||||||
buttonGroupCenterYConstraint = buttonGroup.centerYAnchor.constraint(equalTo: labelButtonView.centerYAnchor)
|
|
||||||
labelViewAndButtonViewConstraint = buttonGroup.topAnchor.constraint(equalTo: labelsView.bottomAnchor, constant: VDSLayout.Spacing.space3X.value)
|
labelViewAndButtonViewConstraint = buttonGroup.topAnchor.constraint(equalTo: labelsView.bottomAnchor, constant: VDSLayout.Spacing.space3X.value)
|
||||||
buttonGroup.widthAnchor.constraint(equalTo: labelsView.widthAnchor).activate()
|
buttonGroup.widthAnchor.constraint(equalTo: labelsView.widthAnchor).activate()
|
||||||
|
|
||||||
@ -314,7 +276,6 @@ open class Notification: View {
|
|||||||
closeButton.size = UIDevice.isIPad ? .medium : .small
|
closeButton.size = UIDevice.isIPad ? .medium : .small
|
||||||
closeButton.name = .close
|
closeButton.name = .close
|
||||||
|
|
||||||
layout = .vertical
|
|
||||||
hideCloseButton = false
|
hideCloseButton = false
|
||||||
|
|
||||||
shouldUpdateView = true
|
shouldUpdateView = true
|
||||||
@ -338,6 +299,16 @@ open class Notification: View {
|
|||||||
layer.cornerRadius = UIScreen.main.bounds.width == bounds.width ? 0 : 4.0
|
layer.cornerRadius = UIScreen.main.bounds.width == bounds.width ? 0 : 4.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Updating the accessiblity values i.e elements, label, value other items for the component.
|
||||||
|
open override func updateAccessibility() {
|
||||||
|
super.updateAccessibility()
|
||||||
|
accessibilityElements = [closeButton, typeIcon, titleLabel, subTitleLabel, buttonGroup]
|
||||||
|
typeIcon.accessibilityLabel = style.rawValue
|
||||||
|
typeIcon.imageView.image?.isAccessibilityElement = false
|
||||||
|
closeButton.accessibilityTraits = [.button]
|
||||||
|
closeButton.accessibilityLabel = "Close Notification"
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Private Methods
|
// MARK: - Private Methods
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -383,32 +354,21 @@ open class Notification: View {
|
|||||||
secondaryButton.onClick = secondaryButtonModel.onClick
|
secondaryButton.onClick = secondaryButtonModel.onClick
|
||||||
buttons.append(secondaryButton)
|
buttons.append(secondaryButton)
|
||||||
}
|
}
|
||||||
labelViewWidthConstraint?.deactivate()
|
|
||||||
if buttons.isEmpty {
|
if buttons.isEmpty {
|
||||||
buttonGroup.isHidden = true
|
buttonGroup.isHidden = true
|
||||||
labelViewWidthConstraint = labelsView.widthAnchor.constraint(equalTo: labelButtonView.widthAnchor)
|
|
||||||
buttonGroup.buttons.removeAll()
|
buttonGroup.buttons.removeAll()
|
||||||
} else {
|
} else {
|
||||||
labelsView.setCustomSpacing(VDSLayout.Spacing.space3X.value, after: subTitleLabel)
|
labelsView.setCustomSpacing(VDSLayout.Spacing.space3X.value, after: subTitleLabel)
|
||||||
buttonGroup.buttons = buttons
|
buttonGroup.buttons = buttons
|
||||||
buttonGroup.isHidden = false
|
buttonGroup.isHidden = false
|
||||||
labelViewWidthConstraint = labelsView.widthAnchor.constraint(equalTo: labelButtonView.widthAnchor, multiplier: layout == .vertical ? 1.0 : 0.5, constant: layout == .vertical ? 0 : -labelButtonViewSpacing)
|
|
||||||
}
|
}
|
||||||
labelViewWidthConstraint?.activate()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setConstraints() {
|
private func setConstraints() {
|
||||||
maxWidthConstraint?.deactivate()
|
|
||||||
labelViewAndButtonViewConstraint?.deactivate()
|
labelViewAndButtonViewConstraint?.deactivate()
|
||||||
labelViewBottomConstraint?.deactivate()
|
labelViewBottomConstraint?.deactivate()
|
||||||
buttonGroupCenterYConstraint?.deactivate()
|
labelViewAndButtonViewConstraint?.isActive = !buttonGroup.buttons.isEmpty
|
||||||
buttonGroupBottomConstraint?.deactivate()
|
labelViewBottomConstraint?.isActive = buttonGroup.buttons.isEmpty
|
||||||
maxWidthConstraint?.constant = maxViewWidth
|
|
||||||
maxWidthConstraint?.isActive = UIDevice.isIPad
|
|
||||||
labelViewAndButtonViewConstraint?.isActive = layout == .vertical && !buttonGroup.buttons.isEmpty
|
|
||||||
labelViewBottomConstraint?.isActive = layout == .horizontal || buttonGroup.buttons.isEmpty
|
|
||||||
buttonGroupCenterYConstraint?.isActive = layout == .horizontal
|
|
||||||
buttonGroupBottomConstraint?.isActive = layout == .vertical
|
|
||||||
typeIconWidthConstraint?.constant = typeIcon.size.dimensions.width
|
typeIconWidthConstraint?.constant = typeIcon.size.dimensions.width
|
||||||
closeIconWidthConstraint?.constant = closeButton.size.dimensions.width
|
closeIconWidthConstraint?.constant = closeButton.size.dimensions.width
|
||||||
}
|
}
|
||||||
|
|||||||
244
VDS/Components/Pagination/Pagination.swift
Normal file
244
VDS/Components/Pagination/Pagination.swift
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
//
|
||||||
|
// Pagination.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Bandaru, Krishna Kishore on 01/03/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import VDSColorTokens
|
||||||
|
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.
|
||||||
|
@objc(VDSPagination)
|
||||||
|
open class Pagination: View {
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Private Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
///Maximum component width
|
||||||
|
private let maxWidth: CGFloat = 288.0
|
||||||
|
///Collectionview width anchor
|
||||||
|
private var collectionViewWidthAnchor: NSLayoutConstraint?
|
||||||
|
///Collectionview container Center X constraint
|
||||||
|
private var collectionContainerViewCenterXConstraint: NSLayoutConstraint?
|
||||||
|
///Selected page index
|
||||||
|
private var _selectedPageIndex: Int = 0
|
||||||
|
///Custom flow layout defined for the Pagination
|
||||||
|
private let flowLayout = PaginationFlowLayout()
|
||||||
|
///A root view for the pagination
|
||||||
|
public let containerView: View = View().with {
|
||||||
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
}
|
||||||
|
///Collectionview to render pagination indexes
|
||||||
|
private lazy var collectionView: UICollectionView = {
|
||||||
|
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
|
||||||
|
collectionView.isScrollEnabled = false
|
||||||
|
collectionView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
collectionView.showsHorizontalScrollIndicator = false
|
||||||
|
collectionView.showsVerticalScrollIndicator = false
|
||||||
|
collectionView.isAccessibilityElement = true
|
||||||
|
collectionView.register(PaginationCellItem.self, forCellWithReuseIdentifier: PaginationCellItem.identifier)
|
||||||
|
collectionView.backgroundColor = .clear
|
||||||
|
collectionView.delegate = self
|
||||||
|
collectionView.dataSource = self
|
||||||
|
return collectionView
|
||||||
|
}()
|
||||||
|
///Container view to hold collectionview to render pagination indexes and to handler accessibility.
|
||||||
|
private let collectionContainerView = PaginationContainer()
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Public Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
///Previous button to select previous page
|
||||||
|
public let previousButton: PaginationButton = .init(type: .previous)
|
||||||
|
///Next button to select next page
|
||||||
|
public let nextButton: PaginationButton = .init(type: .next)
|
||||||
|
/// A callback when the page changes. Passes parameters (selectedPage).
|
||||||
|
public var onPageDidSelect: ((Int) -> Void)?
|
||||||
|
/// Total number of pages, allows limit ranging from 0 to 9999.
|
||||||
|
@Clamping(range: 0...9999)
|
||||||
|
public var total: Int {
|
||||||
|
didSet {
|
||||||
|
previousButton.isHidden = true
|
||||||
|
nextButton.isHidden = total <= 1
|
||||||
|
_selectedPageIndex = 0
|
||||||
|
setNeedsUpdate()
|
||||||
|
updateSelection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///Selected active page number and clips to total pages if selected index is greater than the total pages.
|
||||||
|
public var selectedPage: Int {
|
||||||
|
set {
|
||||||
|
if newValue >= total {
|
||||||
|
_selectedPageIndex = total - 1
|
||||||
|
} else if newValue < 0 {
|
||||||
|
_selectedPageIndex = 0
|
||||||
|
} else {
|
||||||
|
_selectedPageIndex = max(newValue - 1, 0)
|
||||||
|
}
|
||||||
|
setNeedsUpdate()
|
||||||
|
updateSelection()
|
||||||
|
}
|
||||||
|
get {
|
||||||
|
_selectedPageIndex + 1 //Returns selected page value not index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Overrides
|
||||||
|
//--------------------------------------------------
|
||||||
|
/// Executed on initialization for this View.
|
||||||
|
open override func initialSetup() {
|
||||||
|
super.initialSetup()
|
||||||
|
|
||||||
|
collectionContainerView.addSubview(collectionView)
|
||||||
|
containerView.addSubview(previousButton)
|
||||||
|
containerView.addSubview(collectionContainerView)
|
||||||
|
containerView.addSubview(nextButton)
|
||||||
|
addSubview(containerView)
|
||||||
|
|
||||||
|
containerView
|
||||||
|
.pinTop()
|
||||||
|
.pinBottom()
|
||||||
|
.pinLeadingGreaterThanOrEqualTo()
|
||||||
|
.pinTrailingLessThanOrEqualTo()
|
||||||
|
.pinCenterX()
|
||||||
|
.width(maxWidth)
|
||||||
|
.height(44)
|
||||||
|
|
||||||
|
previousButton
|
||||||
|
.pinTop()
|
||||||
|
.pinBottom()
|
||||||
|
.pinLeading()
|
||||||
|
.pinTrailingGreaterThanOrEqualTo(collectionContainerView.leadingAnchor)
|
||||||
|
|
||||||
|
collectionContainerView
|
||||||
|
.pinTrailingGreaterThanOrEqualTo(nextButton.leadingAnchor)
|
||||||
|
.pinTop()
|
||||||
|
.pinBottom()
|
||||||
|
|
||||||
|
collectionView
|
||||||
|
.height(VDSLayout.Spacing.space4X.value)
|
||||||
|
.pinCenterY()
|
||||||
|
.pinCenterX()
|
||||||
|
|
||||||
|
collectionViewWidthAnchor = collectionView.width(constant: 92)
|
||||||
|
|
||||||
|
nextButton
|
||||||
|
.pinTop()
|
||||||
|
.pinBottom()
|
||||||
|
.pinTrailing()
|
||||||
|
|
||||||
|
nextButton.onClick = onbuttonTapped
|
||||||
|
previousButton.onClick = onbuttonTapped
|
||||||
|
previousButton.isHidden = true
|
||||||
|
|
||||||
|
flowLayout.$collectionViewWidth
|
||||||
|
.receive(on: RunLoop.main)
|
||||||
|
.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)
|
||||||
|
collectionContainerView.onAccessibilityIncrement = { [weak self] in
|
||||||
|
guard let self else { return }
|
||||||
|
self.selectedPage = max(0, self.selectedPage + 1)
|
||||||
|
}
|
||||||
|
collectionContainerView.onAccessibilityDecrement = { [weak self] in
|
||||||
|
guard let self else { return }
|
||||||
|
self.selectedPage = max(0, self.selectedPage - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///Updating the accessiblity values i.e elements, label, value other items for the component.
|
||||||
|
open override func updateAccessibility() {
|
||||||
|
super.updateAccessibility()
|
||||||
|
accessibilityElements = [previousButton, collectionContainerView, nextButton]
|
||||||
|
collectionContainerView.accessibilityLabel = "Pagination containing \(total) pages"
|
||||||
|
collectionContainerView.accessibilityValue = "Page \(selectedPage) of \(total) selected"
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used to make changes to the View based off a change events or from local properties.
|
||||||
|
open override func updateView() {
|
||||||
|
super.updateView()
|
||||||
|
nextButton.surface = surface
|
||||||
|
previousButton.surface = surface
|
||||||
|
collectionView.reloadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Private Methods
|
||||||
|
//--------------------------------------------------
|
||||||
|
///When previous/next button is tapped
|
||||||
|
private func onbuttonTapped(_ sender: UIButton) {
|
||||||
|
let isNextAction = sender == nextButton
|
||||||
|
_selectedPageIndex = if isNextAction { _selectedPageIndex + 1 } else { _selectedPageIndex - 1 }
|
||||||
|
updateSelection()
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { [weak self] in
|
||||||
|
guard let self else { return }
|
||||||
|
UIAccessibility.post(notification: .announcement, argument: "Page \(self.selectedPage) of \(self.total) selected")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///Refreshing the UI based on the selected page
|
||||||
|
private func updateSelection() {
|
||||||
|
guard _selectedPageIndex < total else { return }
|
||||||
|
//Need to make selected page as second element so scrolling previous index of the selected page to left
|
||||||
|
collectionView.scrollToItem(at: IndexPath(row: max(_selectedPageIndex - 1, 0), section: 0), at: .left, animated: false)
|
||||||
|
previousButton.isHidden = _selectedPageIndex == 0
|
||||||
|
nextButton.isHidden = _selectedPageIndex == total - 1
|
||||||
|
collectionView.reloadData()
|
||||||
|
verifyIfMaxDigitChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
///Identifying if there is any change in the digits of upcoming page
|
||||||
|
private func verifyIfMaxDigitChanged() {
|
||||||
|
let upperLimitPage = _selectedPageIndex + flowLayout.maxNumberOfColumns
|
||||||
|
let upperLimitDigits = upperLimitPage.digitCount //future value digits
|
||||||
|
switch (flowLayout.numberOfColumns, upperLimitDigits) {
|
||||||
|
case (_, 1), (_, 2):
|
||||||
|
flowLayout.numberOfColumns = 4
|
||||||
|
default:
|
||||||
|
flowLayout.numberOfColumns = 3
|
||||||
|
}
|
||||||
|
if upperLimitDigits != flowLayout.upperLimitDigits {
|
||||||
|
flowLayout.upperLimitDigits = upperLimitDigits
|
||||||
|
flowLayout.invalidateLayout()
|
||||||
|
collectionView.reloadData()
|
||||||
|
//Need to make selected page as second element so scrolling previous index of the selected page to left
|
||||||
|
collectionView.scrollToItem(at: IndexPath(row: max(_selectedPageIndex - 1, 0), section: 0), at: .left, animated: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Pagination: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - UICollectionView Delegate & Datasource
|
||||||
|
//--------------------------------------------------
|
||||||
|
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { total }
|
||||||
|
|
||||||
|
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||||
|
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PaginationCellItem.identifier, for: indexPath) as? PaginationCellItem else { return UICollectionViewCell() }
|
||||||
|
cell.update(_selectedPageIndex, currentIndex: indexPath.row, surface: surface)
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||||
|
guard _selectedPageIndex != indexPath.row else { return }
|
||||||
|
_selectedPageIndex = indexPath.row
|
||||||
|
updateSelection()
|
||||||
|
onPageDidSelect?(selectedPage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate extension Int {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Extension on Int to identify number of digits in given number.
|
||||||
|
//--------------------------------------------------
|
||||||
|
var digitCount: Int {
|
||||||
|
numberOfDigits(in: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func numberOfDigits(in number: Int) -> Int {
|
||||||
|
number < 10 && number >= 0 ? 1 : 1 + numberOfDigits(in: number/10)
|
||||||
|
}
|
||||||
|
}
|
||||||
111
VDS/Components/Pagination/PaginationButton.swift
Normal file
111
VDS/Components/Pagination/PaginationButton.swift
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
//
|
||||||
|
// PaginationButton.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Bandaru, Krishna Kishore on 05/03/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import VDSColorTokens
|
||||||
|
|
||||||
|
///This is customised button for Pagination view
|
||||||
|
@objc(PaginationButton)
|
||||||
|
open class PaginationButton: ButtonBase {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Private Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
/// Type of the PaginationButton
|
||||||
|
private var type: Type = .next
|
||||||
|
/// Button tint color configuration
|
||||||
|
private let buttonTintColorConfiguration = SurfaceColorConfiguration(VDSColor.paletteBlack, VDSColor.paletteWhite)
|
||||||
|
/// Button title color configuration
|
||||||
|
private let buttonTextColorConfiguration = SurfaceColorConfiguration(VDSColor.paletteBlack, VDSColor.paletteWhite)
|
||||||
|
/// Button configuration for iOS 15+
|
||||||
|
@available(iOS 15.0, *)
|
||||||
|
private var buttonConfiguration: Button.Configuration {
|
||||||
|
var configuration = ButtonBase.Configuration.plain()
|
||||||
|
configuration.imagePadding = VDSLayout.Spacing.space2X.value
|
||||||
|
configuration.imagePlacement = type == .next ? .trailing : .leading
|
||||||
|
configuration.titleAlignment = type == .next ? .trailing : .leading
|
||||||
|
configuration.contentInsets = .zero
|
||||||
|
return configuration
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Public Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
/// TextStyle used on the titleLabel.
|
||||||
|
open override var textStyle: TextStyle { TextStyle.boldBodySmall }
|
||||||
|
/// UIColor used on the titleLabel text.
|
||||||
|
open override var textColor: UIColor { buttonTextColorConfiguration.getColor(surface) }
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initializers
|
||||||
|
//--------------------------------------------------
|
||||||
|
init(type: Type) {
|
||||||
|
self.type = type
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
required public init() {
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
public required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Overrides
|
||||||
|
//--------------------------------------------------
|
||||||
|
/// Executed on initialization for this View.
|
||||||
|
open override func initialSetup() {
|
||||||
|
super.initialSetup()
|
||||||
|
if #available(iOS 15.0, *) {
|
||||||
|
configuration = buttonConfiguration
|
||||||
|
} else {
|
||||||
|
semanticContentAttribute = type == .next ? .forceRightToLeft : .forceLeftToRight
|
||||||
|
imageEdgeInsets = .init(top: 0, left: 0, bottom: 0, right: VDSLayout.Spacing.space2X.value)
|
||||||
|
}
|
||||||
|
contentHorizontalAlignment = type == .next ? .trailing : .leading
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used to make changes to the View based off a change events or from local properties.
|
||||||
|
open override func updateView() {
|
||||||
|
text = type.title
|
||||||
|
let color = buttonTintColorConfiguration.getColor(surface)
|
||||||
|
setImage(type.image(color), for: .normal)
|
||||||
|
tintColor = color
|
||||||
|
super.updateView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension PaginationButton {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Enum to configure PaginationButton
|
||||||
|
//--------------------------------------------------
|
||||||
|
enum `Type` {
|
||||||
|
case previous, next
|
||||||
|
|
||||||
|
var title: String {
|
||||||
|
switch self {
|
||||||
|
case .next:
|
||||||
|
"Next"
|
||||||
|
case .previous:
|
||||||
|
"Previous"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var imageSize: CGSize { Icon.Size.xsmall.dimensions }
|
||||||
|
|
||||||
|
///Image for the configuration type
|
||||||
|
func image(_ color: UIColor) -> UIImage? {
|
||||||
|
switch self {
|
||||||
|
case .previous:
|
||||||
|
UIImage.image(for: .paginationLeftArrow, color: color, renderingMode: .alwaysTemplate)?.resized(to: imageSize)
|
||||||
|
case .next:
|
||||||
|
UIImage.image(for: .paginationRightArrow, color: color, renderingMode: .alwaysTemplate)?.resized(to: imageSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
63
VDS/Components/Pagination/PaginationCellItem.swift
Normal file
63
VDS/Components/Pagination/PaginationCellItem.swift
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
//
|
||||||
|
// PaginationCellItem.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Bandaru, Krishna Kishore on 05/03/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import VDSColorTokens
|
||||||
|
|
||||||
|
///This is customised view for Pagination cell item
|
||||||
|
final class PaginationCellItem: UICollectionViewCell {
|
||||||
|
|
||||||
|
///Identifier for the PaginationCellItem
|
||||||
|
static let identifier: String = String(describing: PaginationCellItem.self)
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Private Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
///Text color configuration for the element
|
||||||
|
private let textColorConfiguration = SurfaceColorConfiguration(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark)
|
||||||
|
///Pagination index label
|
||||||
|
private var indexLabel: Label = Label().with {
|
||||||
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
$0.textAlignment = .center
|
||||||
|
$0.isAccessibilityElement = false
|
||||||
|
$0.numberOfLines = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initializers
|
||||||
|
//--------------------------------------------------
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
setUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
setUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
///Configuring the cell with default setup
|
||||||
|
private func setUp() {
|
||||||
|
let containerView = View()
|
||||||
|
containerView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
containerView.addSubview(indexLabel)
|
||||||
|
contentView.addSubview(containerView)
|
||||||
|
containerView.pinToSuperView()
|
||||||
|
indexLabel.pinToSuperView()
|
||||||
|
indexLabel.widthGreaterThanEqualTo(VDSLayout.Spacing.space5X.value)
|
||||||
|
contentView.backgroundColor = .clear
|
||||||
|
containerView.backgroundColor = .clear
|
||||||
|
indexLabel.backgroundColor = .clear
|
||||||
|
}
|
||||||
|
|
||||||
|
///Updating UI based on selected index, current index along with surface
|
||||||
|
func update(_ selectedIndex: Int, currentIndex: Int, surface: Surface) {
|
||||||
|
indexLabel.textStyle = selectedIndex == currentIndex ? .boldBodySmall : .bodySmall
|
||||||
|
indexLabel.text = "\(currentIndex + 1)"
|
||||||
|
indexLabel.textColor = textColorConfiguration.getColor(surface)
|
||||||
|
}
|
||||||
|
}
|
||||||
34
VDS/Components/Pagination/PaginationChangeLog.txt
Normal file
34
VDS/Components/Pagination/PaginationChangeLog.txt
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
MM/DD/YYYY
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Initial Brand 3.0 handoff
|
||||||
|
|
||||||
|
12/17/2021
|
||||||
|
----------------
|
||||||
|
- Replaced focusring colors (previously interactive/onlight/ondark) with accessibility/onlight/ondark colors
|
||||||
|
- Updated focus border name (previously interactive.focusring.onlight) with focusring.onlight/ondark
|
||||||
|
|
||||||
|
02/28/2022
|
||||||
|
----------------
|
||||||
|
- Change Page Item Active to Page Item Selected. All Active references changed to Selected.
|
||||||
|
|
||||||
|
03/01/2022
|
||||||
|
----------------
|
||||||
|
- Replaced Left and Right Arrow Non-Scaling icons with VDS Icon.
|
||||||
|
- Removed “weight” and “vector effect” from Anatomy frame.
|
||||||
|
|
||||||
|
08/10/2022
|
||||||
|
----------------
|
||||||
|
- Updated default and inverted prop to light and dark surface.
|
||||||
|
|
||||||
|
11/30/2022
|
||||||
|
----------------
|
||||||
|
- Added "(web only)" to any instance of "keyboard focus"
|
||||||
|
|
||||||
|
12/13/2022
|
||||||
|
----------------
|
||||||
|
- Replaced focus border pixel and style & spacing values with tokens.
|
||||||
|
|
||||||
|
01/12/2023
|
||||||
|
----------------
|
||||||
|
- Removed “Page Item Selected” from Anatomy.
|
||||||
45
VDS/Components/Pagination/PaginationContainer.swift
Normal file
45
VDS/Components/Pagination/PaginationContainer.swift
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// PaginationContainerView.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Bandaru, Krishna Kishore on 12/03/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
///PaginationCollectionView is a container view that holds collectionview for displaying page indexes
|
||||||
|
final class PaginationContainer: View {
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Internal Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
///Notifies when accessibility increment is happend when user swipes up
|
||||||
|
var onAccessibilityIncrement: (() -> Void)?
|
||||||
|
///Notifies when accessibility decrement is happend when user swipes down
|
||||||
|
var onAccessibilityDecrement: (() -> Void)?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Overrides
|
||||||
|
//--------------------------------------------------
|
||||||
|
///Accessibilty traits for the Pagination view
|
||||||
|
override var accessibilityTraits: UIAccessibilityTraits {
|
||||||
|
get { [.adjustable] }
|
||||||
|
set { }
|
||||||
|
}
|
||||||
|
|
||||||
|
///Accessibilty increment
|
||||||
|
override func accessibilityIncrement() {
|
||||||
|
onAccessibilityIncrement?()
|
||||||
|
}
|
||||||
|
|
||||||
|
///Accessibilty decrement
|
||||||
|
override func accessibilityDecrement() {
|
||||||
|
onAccessibilityDecrement?()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Executed on initialization for this View.
|
||||||
|
override func setup() {
|
||||||
|
super.setup()
|
||||||
|
isAccessibilityElement = true
|
||||||
|
}
|
||||||
|
}
|
||||||
91
VDS/Components/Pagination/PaginationFlowLayout.swift
Normal file
91
VDS/Components/Pagination/PaginationFlowLayout.swift
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// PaginationFlowLayout.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Bandaru, Krishna Kishore on 06/03/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
///Customised flow layout for Pagination view
|
||||||
|
final class PaginationFlowLayout : UICollectionViewLayout {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Private Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
///Spacing between the pagination cells
|
||||||
|
private let spacingBetweenCell: CGFloat = VDSLayout.Spacing.space1X.value
|
||||||
|
///Pre-defined sizes of the pagination cell based on number of digits.
|
||||||
|
private var upperLimitSize: CGSize {
|
||||||
|
switch upperLimitDigits {
|
||||||
|
case 1, 2: .init(width: 20, height: 16)
|
||||||
|
case 3: .init(width: 28, height: 16)
|
||||||
|
default: .init(width: 34, height: 16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///Property to store the defined layout attributes.
|
||||||
|
private var itemCache : [UICollectionViewLayoutAttributes] = []
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Internal Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
///Maximum number of page indexes shown on UI
|
||||||
|
let maxNumberOfColumns: Int = 4
|
||||||
|
///Number of digits of the maximum page index.
|
||||||
|
var upperLimitDigits: Int = 0
|
||||||
|
///Number of page indexes shown on UI.
|
||||||
|
var numberOfColumns: Int = 4
|
||||||
|
///A property that publishes when there is change in collection view width.
|
||||||
|
@Published var collectionViewWidth: CGFloat = 0
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Overrides
|
||||||
|
//--------------------------------------------------
|
||||||
|
///Preparing the layout collection attributes for pagination and updating the collectionview width.
|
||||||
|
override func prepare() {
|
||||||
|
|
||||||
|
guard let collectionView else { return }
|
||||||
|
|
||||||
|
itemCache.removeAll()
|
||||||
|
var xPos : CGFloat = 0
|
||||||
|
for item in 0..<collectionView.numberOfItems(inSection: 0) {
|
||||||
|
let indexPath = IndexPath(item: item, section: 0)
|
||||||
|
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
|
||||||
|
attributes.frame = .init(origin: .init(x: xPos, y: 0), size: upperLimitSize)
|
||||||
|
xPos += (spacingBetweenCell + upperLimitSize.width)
|
||||||
|
itemCache.append(attributes)
|
||||||
|
}
|
||||||
|
guard !itemCache.isEmpty else { return }
|
||||||
|
var rightMostVisibleItem: UICollectionViewLayoutAttributes?
|
||||||
|
if numberOfColumns < itemCache.count {
|
||||||
|
rightMostVisibleItem = itemCache[max(numberOfColumns - 1, 0)]
|
||||||
|
} else {
|
||||||
|
rightMostVisibleItem = itemCache.last
|
||||||
|
}
|
||||||
|
if let rightMostVisibleItem {
|
||||||
|
collectionViewWidth = rightMostVisibleItem.frame.minX + rightMostVisibleItem.frame.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///This will return the layout attributes for the elements in the defined rect
|
||||||
|
override func layoutAttributesForElements(in rect: CGRect)-> [UICollectionViewLayoutAttributes]? {
|
||||||
|
var visibleLayoutAttributes: [UICollectionViewLayoutAttributes] = []
|
||||||
|
for attributes in itemCache {
|
||||||
|
if attributes.frame.intersects(rect) {
|
||||||
|
visibleLayoutAttributes.append(attributes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return visibleLayoutAttributes
|
||||||
|
}
|
||||||
|
|
||||||
|
///This will return the layout attributes at particular indexPath
|
||||||
|
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
|
||||||
|
return itemCache[indexPath.row]
|
||||||
|
}
|
||||||
|
|
||||||
|
///Returns the collectionview content size
|
||||||
|
override var collectionViewContentSize: CGSize {
|
||||||
|
guard let lastAttribute = itemCache.last else { return super.collectionViewContentSize }
|
||||||
|
return .init(width: lastAttribute.frame.width + lastAttribute.frame.origin.x, height: 16)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -264,7 +264,6 @@ open class Tabs: View {
|
|||||||
model.onClick?(tab.index)
|
model.onClick?(tab.index)
|
||||||
self.selectedIndex = tab.index
|
self.selectedIndex = tab.index
|
||||||
self.onTabDidSelect?(tab.index)
|
self.onTabDidSelect?(tab.index)
|
||||||
let t = tabViews[tab.index]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,4 +23,17 @@ extension UIImage {
|
|||||||
|
|
||||||
return image.withTintColor(color, renderingMode: renderingMode)
|
return image.withTintColor(color, renderingMode: renderingMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resizes image to a specific Size
|
||||||
|
/// - Parameter size: Size to resize
|
||||||
|
/// - Returns: Image that is resized
|
||||||
|
public func resized(to size: CGSize) -> UIImage? {
|
||||||
|
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
|
||||||
|
|
||||||
|
defer { UIGraphicsEndImageContext() }
|
||||||
|
draw(in: .init(origin: .zero, size: size))
|
||||||
|
|
||||||
|
return UIGraphicsGetImageFromCurrentImageContext()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -478,7 +478,159 @@ extension LayoutConstraintable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Center X Constraints
|
||||||
|
//--------------------------------------------------
|
||||||
|
extension LayoutConstraintable {
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a centerXAnchor.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinCenterX(_ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinCenterX(nil, constant)
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a centerXAnchor to a specific XAxisAnchor.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the centerXAnchor.
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinCenterX(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinCenterX(anchor: anchor, constant: constant)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a centerXAnchor to a specific XAxisAnchor passed in using a lessThanOrEqualTo Constraint
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the centerXAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinCenterXLessThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinCenterXLessThanOrEqualTo(anchor: anchor, constant: constant)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a centerXAnchor to a specific XAxisAnchor passed in using a greaterThanOrEqualTo Constraint
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the centerXAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinCenterXGreaterThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
||||||
|
pinCenterXGreaterThanOrEqualTo(anchor: anchor, constant: constant)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a centerXAnchor for the constant passed into the method.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the centerXAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinCenterX(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.centerXAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return centerXAnchor.constraint(equalTo: found, constant: -constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a centerXAnchor with the constant passed in using a lessThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the centerXAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinCenterXLessThanOrEqualTo(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.centerXAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return centerXAnchor.constraint(lessThanOrEqualTo: found, constant: -constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a centerXAnchor with the constant passed in using a greaterThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the centerXAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinCenterXGreaterThanOrEqualTo(anchor: NSLayoutXAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutXAxisAnchor? = anchor ?? superview?.centerXAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return centerXAnchor.constraint(greaterThanOrEqualTo: found, constant: -constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Center Y Constraints
|
||||||
|
//--------------------------------------------------
|
||||||
|
extension LayoutConstraintable {
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a centerYAnchor.
|
||||||
|
/// - Parameter constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinCenterY(_ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinCenterY(nil, constant)
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a centerYAnchor to a specific YAxisAnchor.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the centerYAnchor.
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinCenterY(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinCenterY(anchor: anchor, constant: constant)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a centerYAnchor to a specific YAxisAnchor passed in using a lessThanOrEqualTo Constraint
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the centerYAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinCenterYLessThanOrEqualTo(_ anchor: NSLayoutYAxisAnchor? = nil, _ constant: CGFloat = 0.0, _ priority: UILayoutPriority = .required) -> Self {
|
||||||
|
pinCenterYLessThanOrEqualTo(anchor: anchor, constant: constant)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a centerYAnchor to a specific YAxisAnchor passed in using a greaterThanOrEqualTo Constraint
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the centerYAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: Yourself.
|
||||||
|
public func pinCenterYGreaterThanOrEqualTo(_ anchor: NSLayoutXAxisAnchor? = nil, _ constant: CGFloat = 0.0) -> Self {
|
||||||
|
pinCenterXGreaterThanOrEqualTo(anchor: anchor, constant: constant)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a centerYAnchor for the constant passed into the method.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the centerYAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinCenterY(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.centerYAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return centerYAnchor.constraint(equalTo: found, constant: -constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a centerYAnchor with the constant passed in using a lessThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the centerYAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinCenterYLessThanOrEqualTo(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.centerYAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return centerYAnchor.constraint(lessThanOrEqualTo: found, constant: -constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
/// Adds a centerYAnchor with the constant passed in using a greaterThanOrEqualTo Constraint.
|
||||||
|
/// - Parameter anchor:The anchor in which to attach the centerYAnchor
|
||||||
|
/// - constant: Constant size.
|
||||||
|
/// - Returns: The Constraint that was created.
|
||||||
|
public func pinCenterYGreaterThanOrEqualTo(anchor: NSLayoutYAxisAnchor?, constant: CGFloat = 0.0, priority: UILayoutPriority = .required) -> NSLayoutConstraint? {
|
||||||
|
let found: NSLayoutYAxisAnchor? = anchor ?? superview?.centerYAnchor
|
||||||
|
guard let found else { return nil }
|
||||||
|
return centerYAnchor.constraint(greaterThanOrEqualTo: found, constant: -constant).with { $0.priority = priority; $0.isActive = true }
|
||||||
|
}
|
||||||
|
}
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Implementations
|
// MARK: - Implementations
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
24
VDS/Utilities/Clamping.swift
Normal file
24
VDS/Utilities/Clamping.swift
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Clamping.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Bandaru, Krishna Kishore on 05/03/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@propertyWrapper public struct Clamping<Value: Comparable> {
|
||||||
|
|
||||||
|
private var value: Value
|
||||||
|
private let range: ClosedRange<Value>
|
||||||
|
|
||||||
|
public init(range: ClosedRange<Value>) {
|
||||||
|
self.value = range.lowerBound
|
||||||
|
self.range = range
|
||||||
|
}
|
||||||
|
|
||||||
|
public var wrappedValue: Value {
|
||||||
|
get { value }
|
||||||
|
set { value = min(max(range.lowerBound, newValue), range.upperBound) }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -21,6 +21,7 @@ Using the system allows designers and developers to collaborate more easily and
|
|||||||
### Components
|
### Components
|
||||||
- ``Badge``
|
- ``Badge``
|
||||||
- ``BadgeIndicator``
|
- ``BadgeIndicator``
|
||||||
|
- ``Breadcrumbs``
|
||||||
- ``Button``
|
- ``Button``
|
||||||
- ``ButtonIcon``
|
- ``ButtonIcon``
|
||||||
- ``ButtonGroup``
|
- ``ButtonGroup``
|
||||||
@ -33,6 +34,7 @@ Using the system allows designers and developers to collaborate more easily and
|
|||||||
- ``Line``
|
- ``Line``
|
||||||
- ``Loader``
|
- ``Loader``
|
||||||
- ``Notification``
|
- ``Notification``
|
||||||
|
- ``Pagination``
|
||||||
- ``RadioBoxItem``
|
- ``RadioBoxItem``
|
||||||
- ``RadioBoxGroup``
|
- ``RadioBoxGroup``
|
||||||
- ``RadioButton``
|
- ``RadioButton``
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user