diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index ee4cc638..695012e9 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -63,6 +63,7 @@ EA985BF9296C710100F2FF2E /* IconColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985BF8296C710100F2FF2E /* IconColor.swift */; }; EA985C1D296CD13600F2FF2E /* BundleManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C1C296CD13600F2FF2E /* BundleManager.swift */; }; EA985C23296E033A00F2FF2E /* TextArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C22296E033A00F2FF2E /* TextArea.swift */; }; + EA985C2D296F03FE00F2FF2E /* TiletIconModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C2C296F03FE00F2FF2E /* TiletIconModels.swift */; }; EAA5EEB528ECBFB4003B3210 /* ImageLabelAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA5EEB428ECBFB4003B3210 /* ImageLabelAttribute.swift */; }; EAA5EEB728ECC03A003B3210 /* ToolTipLabelAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA5EEB628ECC03A003B3210 /* ToolTipLabelAttribute.swift */; }; EAA5EEB928ECD24B003B3210 /* Icons.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EAA5EEB828ECD24B003B3210 /* Icons.xcassets */; }; @@ -175,6 +176,7 @@ EA985BF8296C710100F2FF2E /* IconColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconColor.swift; sourceTree = ""; }; EA985C1C296CD13600F2FF2E /* BundleManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleManager.swift; sourceTree = ""; }; EA985C22296E033A00F2FF2E /* TextArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextArea.swift; sourceTree = ""; }; + EA985C2C296F03FE00F2FF2E /* TiletIconModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TiletIconModels.swift; sourceTree = ""; }; EAA5EEB428ECBFB4003B3210 /* ImageLabelAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLabelAttribute.swift; sourceTree = ""; }; EAA5EEB628ECC03A003B3210 /* ToolTipLabelAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolTipLabelAttribute.swift; sourceTree = ""; }; EAA5EEB828ECD24B003B3210 /* Icons.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Icons.xcassets; sourceTree = ""; }; @@ -498,6 +500,7 @@ EA985BE529688F6A00F2FF2E /* TiletBadgeModel.swift */, EA985BE929689B6D00F2FF2E /* TiletSubTitleModel.swift */, EA985BE72968951C00F2FF2E /* TiletTitleModel.swift */, + EA985C2C296F03FE00F2FF2E /* TiletIconModels.swift */, ); path = Tilet; sourceTree = ""; @@ -744,6 +747,7 @@ EAF7F0B5289C126F00B287F5 /* UILabel.swift in Sources */, EA5E304C294CBDD00082B959 /* TileContainer.swift in Sources */, EAF7F0A6289B0CE000B287F5 /* Resetable.swift in Sources */, + EA985C2D296F03FE00F2FF2E /* TiletIconModels.swift in Sources */, EA89200428AECF4B006B9984 /* UITextField+Publisher.swift in Sources */, EA3361C328902D960071C351 /* Toggle.swift in Sources */, EAF7F0A0289AB7EC00B287F5 /* View.swift in Sources */, diff --git a/VDS/Classes/Control.swift b/VDS/Classes/Control.swift index ba2acd42..cba0078d 100644 --- a/VDS/Classes/Control.swift +++ b/VDS/Classes/Control.swift @@ -29,7 +29,7 @@ open class Control: UIControl, Handlerable, ViewProtocol, Resettable { open override var isSelected: Bool { didSet { didChange() } } - internal var enabledHighlight: Bool = true + internal var enabledHighlight: Bool = false var isHighlightAnimating = false open override var isHighlighted: Bool { diff --git a/VDS/Components/Icon/IconName.swift b/VDS/Components/Icon/IconName.swift index 9db8e362..fe58a1b0 100644 --- a/VDS/Components/Icon/IconName.swift +++ b/VDS/Components/Icon/IconName.swift @@ -21,8 +21,6 @@ public struct IconName: RawRepresentable { self.rawValue = name } - internal static let paginationLeftArrow = IconName(name: "pagination-left-arrow") - internal static let paginationRightArrow = IconName(name: "pagination-right-arrow") public static let checkmark = IconName(name: "checkmark") internal static let checkmarkBold = IconName(name: "checkmark-bold") public static let checkmarkAlt = IconName(name: "checkmark-alt") @@ -33,10 +31,18 @@ public struct IconName: RawRepresentable { internal static let errorBold = IconName(name: "error-bold") public static let info = IconName(name: "info") internal static let infoBold = IconName(name: "info-bold") + public static let multipleDocuments = IconName(name: "multiple-documents") + + public static let leftArrow = IconName(name: "left-arrow") public static let leftCaret = IconName(name: "left-caret") internal static let leftCaretBold = IconName(name: "left-caret-bold") + internal static let paginationLeftArrow = IconName(name: "pagination-left-arrow") + + public static let rightArrow = IconName(name: "right-arrow") public static let rightCaret = IconName(name: "right-caret") internal static let rightCaretBold = IconName(name: "right-caret-bold") + internal static let paginationRightArrow = IconName(name: "pagination-right-arrow") + public static let warning = IconName(name: "warning") internal static let warningBold = IconName(name: "warning-bold") } diff --git a/VDS/Components/TileContainer/TileContainer.swift b/VDS/Components/TileContainer/TileContainer.swift index 40efde6d..154bc95c 100644 --- a/VDS/Components/TileContainer/TileContainer.swift +++ b/VDS/Components/TileContainer/TileContainer.swift @@ -76,14 +76,14 @@ open class TileContainer: Control { public var imageFallbackColor: Surface = .light { didSet{ didChange() } } - private var _width: CGFloat = 100 - public var width: CGFloat { + private var _width: CGFloat? + public var width: CGFloat? { get { return _width } set { - if newValue > 100 { + if let newValue, newValue > 100 { _width = newValue } else { - _width = 100 + _width = nil } didChange() } @@ -152,14 +152,12 @@ open class TileContainer: Control { addSubview(containerView) addSubview(highlightView) - widthConstraint = widthAnchor.constraint(equalToConstant: width) - widthConstraint?.isActive = true + widthConstraint = widthAnchor.constraint(equalToConstant: 0) heightGreaterThanConstraint = heightAnchor.constraint(greaterThanOrEqualToConstant: 44.0) heightGreaterThanConstraint?.isActive = false - heightConstraint = heightAnchor.constraint(equalToConstant: width) - heightConstraint?.isActive = true + heightConstraint = heightAnchor.constraint(equalToConstant: 0) backgroundImageView.pinToSuperView() backgroundImageView.isUserInteractionEnabled = false @@ -219,7 +217,7 @@ open class TileContainer: Control { //-------------------------------------------------- // MARK: - State //-------------------------------------------------- - var ratioSize: CGSize { + private func ratioSize(for width: CGFloat) -> CGSize { var height: CGFloat = width switch aspectRatio { @@ -272,21 +270,27 @@ open class TileContainer: Control { containerBottomConstraint?.constant = -padding containerTrailingConstraint?.constant = -padding - if aspectRatio == .none && height == nil{ + if let width, aspectRatio == .none && height == nil{ widthConstraint?.constant = width + widthConstraint?.isActive = true heightConstraint?.isActive = false heightGreaterThanConstraint?.isActive = true - } else if let height { + } else if let height, let width { widthConstraint?.constant = width heightConstraint?.constant = height heightConstraint?.isActive = true + widthConstraint?.isActive = true heightGreaterThanConstraint?.isActive = false - } else { - let size = ratioSize + } else if let width { + let size = ratioSize(for: width) widthConstraint?.constant = size.width heightConstraint?.constant = size.height + widthConstraint?.isActive = true heightConstraint?.isActive = true heightGreaterThanConstraint?.isActive = false + } else { + widthConstraint?.isActive = false + heightConstraint?.isActive = false } } diff --git a/VDS/Components/Tilet/Tilet.swift b/VDS/Components/Tilet/Tilet.swift index 5c44503a..f395c04d 100644 --- a/VDS/Components/Tilet/Tilet.swift +++ b/VDS/Components/Tilet/Tilet.swift @@ -13,6 +13,11 @@ import UIKit @objc(VDSTilet) open class Tilet: TileContainer { + public enum TextPosition { + case top + case bottom + } + //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- @@ -114,6 +119,16 @@ open class Tilet: TileContainer { $0.fillColor = .red } + private let iconContainerView = UIView().with { + $0.translatesAutoresizingMaskIntoConstraints = false + $0.backgroundColor = .clear + } + + private var descriptiveIcon = Icon() + private var directionalIcon = Icon().with { + $0.name = .rightArrow + } + //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- @@ -122,7 +137,7 @@ open class Tilet: TileContainer { open var textWidth: CGFloat? { get { _textWidth } set { - if let newValue, newValue > 44.0 && newValue <= width { + if let newValue, newValue > 44.0 { _textWidth = newValue if _textPercentage != nil { _textPercentage = nil @@ -151,11 +166,33 @@ open class Tilet: TileContainer { } } + open var textPostion: TextPosition = .top { didSet { didChange() }} + //models public var badgeModel: TiletBadgeModel? { didSet { didChange() }} public var titleModel: TiletTitleModel? { didSet { didChange() }} public var subTitleModel: TiletSubTitleModel? { didSet { didChange() }} + //only 1 Icon can be active + private var _descriptiveIconModel: TiletDescriptiveIcon? + public var descriptiveIconModel: TiletDescriptiveIcon? { + get { _descriptiveIconModel } + set { + _descriptiveIconModel = newValue; + _directionalIconModel = nil + didChange() + } + } + + private var _directionalIconModel: TiletDirectionalIcon? + public var directionalIconModel: TiletDirectionalIcon? { + get { _directionalIconModel } + set { + _directionalIconModel = newValue; + _descriptiveIconModel = nil + didChange() + } + } //icons @@ -174,8 +211,15 @@ open class Tilet: TileContainer { width = 100 aspectRatio = .none containerBackgroundColor = .black - - addContentView(stackView) + let view = UIView().with { + $0.translatesAutoresizingMaskIntoConstraints = false + } + view.addSubview(stackView) + stackView.pinTop() + stackView.pinLeading() + stackView.pinTrailing() + stackView.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor).isActive = true + addContentView(view) //badge badgeContainerView.addSubview(badge) @@ -193,8 +237,18 @@ open class Tilet: TileContainer { titleLockupTrailingConstraint = titleLockup.trailingAnchor.constraint(equalTo: titleLockupContainerView.trailingAnchor) titleLockupTrailingConstraint?.isActive = true - //stackView.addArrangedSubview(badgeContainerView) - //stackView.addArrangedSubview(titleLockupContainerView) + iconContainerView.addSubview(descriptiveIcon) + iconContainerView.addSubview(directionalIcon) + + descriptiveIcon + .pinLeading() + .pinTop() + .pinBottom() + + directionalIcon + .pinTrailing() + .pinTop() + .pinBottom() } @@ -204,43 +258,33 @@ open class Tilet: TileContainer { surface = .light containerBackgroundColor = .black - //badge - badge.reset() + //models badgeModel = nil - - //titleLockup - titleLockup.reset() titleModel = nil subTitleModel = nil + descriptiveIconModel = nil + directionalIconModel = nil } //-------------------------------------------------- // MARK: - State //-------------------------------------------------- - - open override func updateView() { - super.updateView() - - //flip the surface for the titleLockup - let titleLockupSurface: Surface = containerBackgroundColor == .black ? .dark : .light - titleLockup.surface = titleLockupSurface - - //update constraints - - //badge + fileprivate func updateBadge() { if let badgeModel { - if badgeContainerView.superview == nil { - stackView.insertArrangedSubview(badgeContainerView, at: 0) - } badge.text = badgeModel.text badge.fillColor = badgeModel.fillColor badge.numberOfLines = badgeModel.numberOfLines badge.surface = badgeModel.surface badge.maxWidth = badgeModel.maxWidth + if badgeContainerView.superview == nil { + stackView.insertArrangedSubview(badgeContainerView, at: 0) + } } else { - badge.reset() badgeContainerView.removeFromSuperview() } + } + + fileprivate func updateTitleLockup() { var showTitleLockup = false @@ -251,11 +295,10 @@ open class Tilet: TileContainer { if let subTitleModel, !subTitleModel.text.isEmpty { showTitleLockup = true } - + if showTitleLockup { - if titleLockupContainerView.superview == nil { - stackView.insertArrangedSubview(titleLockupContainerView, at: badgeContainerView.superview == nil ? 0 : 1) - } + //flip the surface for the titleLockup + titleLockup.surface = containerBackgroundColor == .black ? .dark : .light //titleLockup if let textWidth { @@ -288,11 +331,78 @@ open class Tilet: TileContainer { if let style = subTitleModel?.typographicalStyle.value { titleLockup.otherTypograpicalStyle = style } - + + if titleLockupContainerView.superview == nil { + stackView.insertArrangedSubview(titleLockupContainerView, at: badgeContainerView.superview == nil ? 0 : 1) + } } else { titleLockupContainerView.removeFromSuperview() } } + + fileprivate func updateIcons() { + //icons + var showIconContainerView = false + if let descriptiveIconModel { + descriptiveIcon.name = descriptiveIconModel.name + descriptiveIcon.size = descriptiveIconModel.size + descriptiveIcon.surface = descriptiveIconModel.surface + showIconContainerView = true + } + + if let directionalIconModel { + directionalIcon.size = directionalIconModel.size + directionalIcon.surface = directionalIconModel.surface + showIconContainerView = true + } + + //iconContainer + descriptiveIcon.isHidden = descriptiveIconModel == nil + directionalIcon.isHidden = directionalIconModel == nil + + if showIconContainerView { + //spacing before iconContainerView + var view: UIView? + if badgeContainerView.superview != nil { + view = badgeContainerView + } + if titleLockupContainerView.superview != nil { + view = titleLockupContainerView + } + if let view { + stackView.setCustomSpacing(containerPadding.tiletSpacing, after: view) + } + if iconContainerView.superview == nil { + stackView.addArrangedSubview(iconContainerView) + } + } else { + iconContainerView.removeFromSuperview() + } + + } + + open override func updateView() { + super.updateView() + + updateBadge() + updateTitleLockup() + updateIcons() + } } - +extension TileContainer.ContainerPadding { + fileprivate var tiletSpacing: CGFloat { + switch self { + case .twelve: + return 16 + case .sixteen: + return 24 + case .twentyFour: + return 32 + case .thirtyTwo: + return 48 + case .fourtyEight: + return 16 + } + } +} diff --git a/VDS/Components/Tilet/TiletIconModels.swift b/VDS/Components/Tilet/TiletIconModels.swift new file mode 100644 index 00000000..744631e1 --- /dev/null +++ b/VDS/Components/Tilet/TiletIconModels.swift @@ -0,0 +1,31 @@ +// +// TiletDescriptiveIconModel.swift +// VDS +// +// Created by Matt Bruce on 1/11/23. +// + +import Foundation +import UIKit + +public struct TiletDescriptiveIcon { + public var name: IconName + public var size: IconSize + public var surface: Surface + + public init(name: IconName = .multipleDocuments, size: IconSize, surface: Surface) { + self.name = name + self.size = size + self.surface = surface + } +} + +public struct TiletDirectionalIcon { + public var size: IconSize + public var surface: Surface + + public init(size: IconSize, surface: Surface) { + self.size = size + self.surface = surface + } +} diff --git a/VDS/Publishers/UIControlPublisher.swift b/VDS/Publishers/UIControlPublisher.swift index bfcf6b5b..404fe7c5 100644 --- a/VDS/Publishers/UIControlPublisher.swift +++ b/VDS/Publishers/UIControlPublisher.swift @@ -17,6 +17,12 @@ public final class UIControlSubscription + + diff --git a/VDS/SupportingFiles/Icons.xcassets/Restricted/multiple-documents.imageset/Contents.json b/VDS/SupportingFiles/Icons.xcassets/Restricted/multiple-documents.imageset/Contents.json new file mode 100644 index 00000000..a8edc344 --- /dev/null +++ b/VDS/SupportingFiles/Icons.xcassets/Restricted/multiple-documents.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "multiple-documents.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/VDS/SupportingFiles/Icons.xcassets/Restricted/multiple-documents.imageset/multiple-documents.svg b/VDS/SupportingFiles/Icons.xcassets/Restricted/multiple-documents.imageset/multiple-documents.svg new file mode 100644 index 00000000..b5a14342 --- /dev/null +++ b/VDS/SupportingFiles/Icons.xcassets/Restricted/multiple-documents.imageset/multiple-documents.svg @@ -0,0 +1,9 @@ + + + + + diff --git a/VDS/SupportingFiles/Icons.xcassets/Restricted/right-arrow.imageset/Contents.json b/VDS/SupportingFiles/Icons.xcassets/Restricted/right-arrow.imageset/Contents.json new file mode 100644 index 00000000..de24a6e9 --- /dev/null +++ b/VDS/SupportingFiles/Icons.xcassets/Restricted/right-arrow.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "right-arrow.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/VDS/SupportingFiles/Icons.xcassets/Restricted/right-arrow.imageset/right-arrow.svg b/VDS/SupportingFiles/Icons.xcassets/Restricted/right-arrow.imageset/right-arrow.svg new file mode 100644 index 00000000..3b085d8d --- /dev/null +++ b/VDS/SupportingFiles/Icons.xcassets/Restricted/right-arrow.imageset/right-arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/VDS/SupportingFiles/Icons.xcassets/Restricted/right-caret.imageset/Contents.json b/VDS/SupportingFiles/Icons.xcassets/Restricted/right-caret.imageset/Contents.json new file mode 100644 index 00000000..616090e3 --- /dev/null +++ b/VDS/SupportingFiles/Icons.xcassets/Restricted/right-caret.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "right-caret.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/VDS/SupportingFiles/Icons.xcassets/Restricted/right-caret.imageset/right-caret.svg b/VDS/SupportingFiles/Icons.xcassets/Restricted/right-caret.imageset/right-caret.svg new file mode 100644 index 00000000..98ecd43c --- /dev/null +++ b/VDS/SupportingFiles/Icons.xcassets/Restricted/right-caret.imageset/right-caret.svg @@ -0,0 +1,3 @@ + + +