// // Tooltip.swift // VDS // // Created by Matt Bruce on 4/13/23. // import Foundation import UIKit import VDSColorTokens import VDSFormControlsTokens import Combine @objc(VDSTooltip) open class Tooltip: Control, TooltipLaunchable { //-------------------------------------------------- // MARK: - Enums //-------------------------------------------------- public enum FillColor: String, CaseIterable { case primary, secondary, brandHighlight } public enum Size: String, CaseIterable { case small case medium public var dimensions: CGSize { switch self { case .small: return .init(width: 13.33, height: 13.33) case .medium: return .init(width: 16.67, height: 16.67) } } } //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- private var widthConstraint: NSLayoutConstraint? private var heightConstraint: NSLayoutConstraint? private var infoImage = UIImage() //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- open var imageView = UIImageView().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.contentMode = .scaleAspectFill $0.clipsToBounds = true } open var closeButtonText: String = "Close" { didSet { didChange() }} open var fillColor: FillColor = .primary { didSet { didChange() }} open var size: Size = .medium { didSet { didChange() }} open var title: String = "" { didSet { didChange() }} open var content: String = "" { didSet { didChange() }} //-------------------------------------------------- // MARK: - Configuration //-------------------------------------------------- private var iconColorConfig: AnyColorable = { let config = KeyedColorConfiguration(keyPath: \.fillColor) config.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forKey: .primary) config.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark, forKey: .secondary) config.setSurfaceColors(VDSColor.elementsBrandhighlight, VDSColor.elementsBrandhighlight, forKey: .brandHighlight) return config.eraseToAnyColorable() }() //-------------------------------------------------- // 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: - Lifecycle //-------------------------------------------------- open override func setup() { super.setup() if let image = BundleManager.shared.image(for: "info") { infoImage = image } addSubview(imageView) imageView.pinToSuperView() heightConstraint = imageView.heightAnchor.constraint(equalToConstant: size.dimensions.height) heightConstraint?.isActive = true widthConstraint = imageView.widthAnchor.constraint(equalToConstant: size.dimensions.width) widthConstraint?.isActive = true backgroundColor = .clear isAccessibilityElement = true accessibilityTraits = .link onClickSubscriber = publisher(for: .touchUpInside) .sink(receiveValue: { [weak self] tooltip in guard let self else { return} self.presentTooltip(surface: tooltip.surface, title: tooltip.title, content: tooltip.content, closeButtonText: tooltip.closeButtonText) }) } open override func reset() { super.reset() size = .medium title = "" content = "" fillColor = .primary closeButtonText = "Close" imageView.image = nil } open override func updateView() { super.updateView() //set the dimensions let dimensions = size.dimensions heightConstraint?.constant = dimensions.height widthConstraint?.constant = dimensions.width //get the color for the image let imageColor = iconColorConfig.getColor(self) imageView.image = infoImage.withTintColor(imageColor) accessibilityLabel = "Tooltip: \(title)" } }