diff --git a/VDS/Components/Modal/Modal.swift b/VDS/Components/Modal/Modal.swift new file mode 100644 index 00000000..6f28175c --- /dev/null +++ b/VDS/Components/Modal/Modal.swift @@ -0,0 +1,120 @@ +// +// Modal.swift +// VDS +// +// Created by Kanamarlapudi, Vasavi on 5/09/24. +// + +import Foundation +import UIKit +import VDSCoreTokens +import Combine + +/// A Modal is an overlay that interrupts the user flow +/// to force the customer to provide information or a response. +/// After the customer interacts with the modal, they can return to the parent content. +@objcMembers +@objc(VDSModal) +open class Modal: Control, ModalLaunchable { + + //-------------------------------------------------- + // 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: - Private Properties + //-------------------------------------------------- + internal var showModalButton = Button().with { + $0.use = .primary + $0.text = "Show Modal" + } + + //-------------------------------------------------- + // MARK: - Public Properties + //-------------------------------------------------- + /// Text rendered for the title of the modal + open var title: String? { didSet { setNeedsUpdate() } } + + /// Text rendered for the content of the modal + open var content: String? { didSet { setNeedsUpdate() } } + + /// UIView rendered for the content area of the modal + open var contentView: UIView? { didSet { setNeedsUpdate() } } + + //-------------------------------------------------- + // 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() + + addSubview(showModalButton) + showModalButton.pinToSuperView() + backgroundColor = .clear + + isAccessibilityElement = true + accessibilityTraits = .button + } + + open override func setDefaults() { + super.setDefaults() + title = nil + content = nil + contentView = nil + + showModalButton.onClick = { _ in self.showModalButtonClick() } + } + + internal func showModalButtonClick() { + print("Clicked showModalButton") + self.presentModal(surface: self.surface, + modalModel: .init(closeButtonText: showModalButton.text ?? "", + title: title, + content: content, + contentView: contentView), + presenter: self) + } + + + /// Used to make changes to the View based off a change events or from local properties. + open override func updateView() { + super.updateView() + showModalButton.surface = surface + } + + public static func accessibleText(for title: String?, content: String?, closeButtonText: String) -> String { + var label = "" + if let title { + label = title + } + if let content { + if !label.isEmpty { + label += "," + } + label += content + } + return label + } +} + + +// MARK: AppleGuidelinesTouchable +extension Modal: AppleGuidelinesTouchable { + /// Overrides to ensure that the touch point meets a minimum of the minimumTappableArea. + override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + Self.acceptablyOutsideBounds(point: point, bounds: bounds) + } + +}