// // TableViewTestController.swift // VDSSample // // Created by Matt Bruce on 5/3/23. // import Foundation import UIKit import VDS import VDSColorTokens public typealias ComponentSampleView = UIView & Surfaceable public struct ComponentSample { public var component: ComponentSampleView public var canPinLeading: Bool public var canPinTrailing: Bool public var canPinTop: Bool public var canPinBottom: Bool public init(component: ComponentSampleView, canPinLeading: Bool = true, canPinTrailing: Bool = true, canPinTop: Bool = true, canPinBottom: Bool = true) { self.component = component self.canPinLeading = canPinLeading self.canPinTrailing = canPinTrailing self.canPinTop = canPinTop self.canPinBottom = canPinBottom } } protocol ComponentSampleable { static func makeSample() -> ComponentSample } public class TableViewTestController: UITableViewController, Initable, Surfaceable { var components:[ComponentSample] = [] public var surface: Surface = .light { didSet { tableView.reloadData() } } //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- required public init() { super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } public override func viewDidLoad() { super.viewDidLoad() MenuViewController.items.forEach { menuItem in if let componentable = menuItem.viewController as? ComponentSampleable.Type { components.append(componentable.makeSample()) } } tableView.register(VDSCell.self, forCellReuseIdentifier: "cell") tableView.allowsSelection = false tableView.estimatedRowHeight = 45 tableView.separatorStyle = .none tableView.rowHeight = UITableView.automaticDimension tableView.reloadData() let view = View(frame: .init(origin: .zero, size: .init(width: tableView.bounds.width, height: 100))) let toggle = Toggle().with { $0.showText = true $0.textPosition = .right $0.offText = "Light" $0.onText = "Dark" $0.onChange = { [weak self] toggle in self?.surface = toggle.isOn ? .dark : .light } } view.addSubview(toggle) toggle.pinToSuperView(.init(top: 5, left: 16, bottom: 5, right: 16)) tableView.tableHeaderView = view tableView.tableHeaderView?.frame.size.height = 40 } public override func numberOfSections(in tableView: UITableView) -> Int { components.count } public override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { "\(type(of: components[section].component))" } public override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 40 } public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 1 } public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? VDSCell else { return UITableViewCell() } cell.prepareForReuse() cell.surface = surface cell.sample = components[indexPath.section] return cell } } public class VDSCell: UITableViewCell, AppleGuidlinesTouchable, Surfaceable { public var surface: Surface = .light public var sample: ComponentSample? { didSet { contentView.subviews.forEach { $0.removeFromSuperview() } let edges: UIEdgeInsets = .init(top: 16, left: 16, bottom: 16, right: 16) guard let sample else { return } var component = sample.component component.surface = surface let wrapper = View() wrapper.addSubview(component) if sample.canPinTop { component.pinTop(anchor: wrapper.topAnchor, constant: edges.top) } else { component.pinTopGreaterThanOrEqualTo(anchor: wrapper.topAnchor, constant: edges.top) } if sample.canPinLeading { component.pinLeading(anchor: wrapper.leadingAnchor, constant: edges.left) } else { component.pinLeadingGreaterThanOrEqualTo(anchor: wrapper.leadingAnchor, constant: edges.left) } if sample.canPinTrailing { component.pinTrailing(anchor: wrapper.trailingAnchor, constant: edges.right) } else { component.pinTrailingLessThanOrEqualTo(anchor: wrapper.trailingAnchor, constant: edges.right) } if sample.canPinBottom { component.pinBottom(anchor: wrapper.bottomAnchor, constant: edges.bottom) } else { component.pinBottomLessThanOrEqualTo(anchor: wrapper.bottomAnchor, constant: edges.bottom) } contentView.addSubview(wrapper) wrapper.pinToSuperView(edges) backgroundColor = .systemYellow //surface.color } } override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { Self.acceptablyOutsideBounds(point: point, bounds: bounds) } }