// // Pagination.swift // VDS // // Created by Bandaru, Krishna Kishore on 01/03/24. // import Foundation import VDSColorTokens import Combine @objc(VDSPagination) open class Pagination: View { open var onPageDidSelect: ((Int) -> Void)? public let previousButton: PaginationButton = .init(type: .previous) public let nextButton: PaginationButton = .init(type: .next) public var total: Int = 0 { didSet { previousButton.isHidden = true nextButton.isHidden = total <= 1 _selectedPage = 0 setNeedsUpdate() } } public var selectedPage: Int { set { if newValue >= total { _selectedPage = total - 1 } else if newValue < 0 { _selectedPage = 0 } else { _selectedPage = max(newValue - 1, 0) } setNeedsUpdate() updateSelection() } get { _selectedPage } } private var _selectedPage: Int = 0 private let pageItemCellSize: CGSize = .init(width: 20, height: 16) private let spacingBetweenCell: CGFloat = VDSLayout.Spacing.space1X.value private let containerView: View = View().with { $0.translatesAutoresizingMaskIntoConstraints = false } private lazy var flowLayout: UICollectionViewFlowLayout = { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal layout.minimumInteritemSpacing = spacingBetweenCell layout.minimumLineSpacing = spacingBetweenCell layout.sectionInset = .zero layout.estimatedItemSize = pageItemCellSize return layout }() private lazy var collectionView: UICollectionView = { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout) collectionView.isScrollEnabled = false collectionView.translatesAutoresizingMaskIntoConstraints = false collectionView.delegate = self collectionView.dataSource = self collectionView.showsHorizontalScrollIndicator = false collectionView.showsVerticalScrollIndicator = false collectionView.register(PaginationCellItem.self, forCellWithReuseIdentifier: PaginationCellItem.identifier) collectionView.backgroundColor = .clear return collectionView }() open override func initialSetup() { super.initialSetup() addSubview(containerView) containerView.pinToSuperView() containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: 288).activate() containerView.heightAnchor.constraint(equalToConstant: 44).activate() containerView.addSubview(previousButton) containerView.addSubview(collectionView) containerView.addSubview(nextButton) previousButton .pinTop() .pinBottom() .pinLeading() previousButton.trailingAnchor.constraint(greaterThanOrEqualTo: collectionView.leadingAnchor).activate() collectionView.heightAnchor.constraint(equalToConstant: VDSLayout.Spacing.space4X.value).activate() collectionView.centerYAnchor.constraint(equalTo: centerYAnchor).activate() collectionView.centerXAnchor.constraint(equalTo: centerXAnchor).activate() collectionView.trailingAnchor.constraint(greaterThanOrEqualTo: nextButton.leadingAnchor).activate() collectionView.widthAnchor.constraint(equalToConstant: 92).activate() nextButton .pinTop() .pinBottom() .pinTrailing() nextButton.onClick = onbuttonTapped previousButton.onClick = onbuttonTapped previousButton.isHidden = true } open override func updateView() { super.updateView() nextButton.surface = surface previousButton.surface = surface collectionView.reloadData() } private func onbuttonTapped(_ sender: UIButton) { let isNextAction = sender == nextButton if isNextAction { _selectedPage += 1 } else { _selectedPage -= 1 } updateSelection() } private func updateSelection() { let indexPath = IndexPath(row: selectedPage, section: 0) collectionView.scrollToItem(at: indexPath, at: .left, animated: false) previousButton.isHidden = selectedPage == 0 nextButton.isHidden = selectedPage == total - 1 collectionView.reloadData() } } extension Pagination: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { total } public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PaginationCellItem.identifier, for: indexPath) as? PaginationCellItem else { return UICollectionViewCell() } cell.update(selectedPage, currentIndex: indexPath.row, surface: surface) return cell } public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { _selectedPage = indexPath.row updateSelection() onPageDidSelect?(indexPath.row) } }