175 lines
5.9 KiB
Swift
175 lines
5.9 KiB
Swift
//
|
|
// 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 {
|
|
switch fillColor {
|
|
|
|
case .primary:
|
|
return primaryColorConfig.eraseToAnyColorable()
|
|
case .secondary:
|
|
return secondaryColorConfig.eraseToAnyColorable()
|
|
case .brandHighlight:
|
|
return brandHighlightColorConfig.eraseToAnyColorable()
|
|
}
|
|
}
|
|
|
|
private var primaryColorConfig = ControlColorConfiguration().with {
|
|
$0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal)
|
|
$0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .highlighted)
|
|
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled)
|
|
}
|
|
|
|
private var secondaryColorConfig = ControlColorConfiguration().with {
|
|
$0.setSurfaceColors(VDSColor.elementsSecondaryOnlight, VDSColor.elementsSecondaryOndark, forState: .normal)
|
|
$0.setSurfaceColors(VDSColor.paletteGray65, VDSColor.paletteGray65, forState: .highlighted)
|
|
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled)
|
|
}
|
|
|
|
private var brandHighlightColorConfig = ControlColorConfiguration().with {
|
|
$0.setSurfaceColors(VDSColor.elementsBrandhighlight, VDSColor.elementsBrandhighlight, forState: .normal)
|
|
$0.setSurfaceColors(VDSColor.elementsBrandhighlight, VDSColor.elementsBrandhighlight, forState: .highlighted)
|
|
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled)
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
// 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)"
|
|
}
|
|
|
|
}
|