Initial commit for Table component
This commit is contained in:
parent
52dea2a72e
commit
17c5ab948e
@ -20,6 +20,8 @@
|
|||||||
18A65A042B96F050006602CC /* BreadcrumbItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A65A032B96F050006602CC /* BreadcrumbItem.swift */; };
|
18A65A042B96F050006602CC /* BreadcrumbItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A65A032B96F050006602CC /* BreadcrumbItem.swift */; };
|
||||||
18B463A42BBD3C46005C4528 /* DropdownOptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B463A32BBD3C46005C4528 /* DropdownOptionModel.swift */; };
|
18B463A42BBD3C46005C4528 /* DropdownOptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B463A32BBD3C46005C4528 /* DropdownOptionModel.swift */; };
|
||||||
18BDEE822B75316E00452358 /* ButtonIconChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */; };
|
18BDEE822B75316E00452358 /* ButtonIconChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */; };
|
||||||
|
440B84CA2BD8E0E9004A732A /* Table.swift in Sources */ = {isa = PBXBuildFile; fileRef = 440B84C92BD8E0E9004A732A /* Table.swift */; };
|
||||||
|
443DBAFA2BDA303F0021497E /* TableCellItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 443DBAF92BDA303F0021497E /* TableCellItem.swift */; };
|
||||||
445BA07829C07B3D0036A7C5 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 445BA07729C07B3D0036A7C5 /* Notification.swift */; };
|
445BA07829C07B3D0036A7C5 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 445BA07729C07B3D0036A7C5 /* Notification.swift */; };
|
||||||
44604AD429CE186A00E62B51 /* NotificationButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */; };
|
44604AD429CE186A00E62B51 /* NotificationButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */; };
|
||||||
44604AD729CE196600E62B51 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD629CE196600E62B51 /* Line.swift */; };
|
44604AD729CE196600E62B51 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD629CE196600E62B51 /* Line.swift */; };
|
||||||
@ -209,6 +211,8 @@
|
|||||||
18A65A032B96F050006602CC /* BreadcrumbItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbItem.swift; sourceTree = "<group>"; };
|
18A65A032B96F050006602CC /* BreadcrumbItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbItem.swift; sourceTree = "<group>"; };
|
||||||
18B463A32BBD3C46005C4528 /* DropdownOptionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropdownOptionModel.swift; sourceTree = "<group>"; };
|
18B463A32BBD3C46005C4528 /* DropdownOptionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropdownOptionModel.swift; sourceTree = "<group>"; };
|
||||||
18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = ButtonIconChangeLog.txt; sourceTree = "<group>"; };
|
18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = ButtonIconChangeLog.txt; sourceTree = "<group>"; };
|
||||||
|
440B84C92BD8E0E9004A732A /* Table.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Table.swift; sourceTree = "<group>"; };
|
||||||
|
443DBAF92BDA303F0021497E /* TableCellItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableCellItem.swift; sourceTree = "<group>"; };
|
||||||
445BA07729C07B3D0036A7C5 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
|
445BA07729C07B3D0036A7C5 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
|
||||||
44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationButtonModel.swift; sourceTree = "<group>"; };
|
44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationButtonModel.swift; sourceTree = "<group>"; };
|
||||||
44604AD629CE196600E62B51 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
|
44604AD629CE196600E62B51 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
|
||||||
@ -427,6 +431,15 @@
|
|||||||
path = Breadcrumbs;
|
path = Breadcrumbs;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
440B84C82BD8E0CE004A732A /* Table */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
440B84C92BD8E0E9004A732A /* Table.swift */,
|
||||||
|
443DBAF92BDA303F0021497E /* TableCellItem.swift */,
|
||||||
|
);
|
||||||
|
path = Table;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
445BA07629C07ABA0036A7C5 /* Notification */ = {
|
445BA07629C07ABA0036A7C5 /* Notification */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -584,6 +597,7 @@
|
|||||||
71B23C2B2B91FA510027F7D9 /* Pagination */,
|
71B23C2B2B91FA510027F7D9 /* Pagination */,
|
||||||
EA89200B28B530F0006B9984 /* RadioBox */,
|
EA89200B28B530F0006B9984 /* RadioBox */,
|
||||||
EAF7F11428A1470D00B287F5 /* RadioButton */,
|
EAF7F11428A1470D00B287F5 /* RadioButton */,
|
||||||
|
440B84C82BD8E0CE004A732A /* Table */,
|
||||||
EA596ABB2A16B4D500300C4B /* Tabs */,
|
EA596ABB2A16B4D500300C4B /* Tabs */,
|
||||||
EAC925852911C9DE00091998 /* TextFields */,
|
EAC925852911C9DE00091998 /* TextFields */,
|
||||||
EA5E304A294CBDBB0082B959 /* TileContainer */,
|
EA5E304A294CBDBB0082B959 /* TileContainer */,
|
||||||
@ -1156,6 +1170,7 @@
|
|||||||
EAC9258F2911C9DE00091998 /* EntryFieldBase.swift in Sources */,
|
EAC9258F2911C9DE00091998 /* EntryFieldBase.swift in Sources */,
|
||||||
EAB1D2EA28AE84AA00DAE764 /* UIControlPublisher.swift in Sources */,
|
EAB1D2EA28AE84AA00DAE764 /* UIControlPublisher.swift in Sources */,
|
||||||
EAD068922A560B65002E3A2D /* LoaderViewController.swift in Sources */,
|
EAD068922A560B65002E3A2D /* LoaderViewController.swift in Sources */,
|
||||||
|
443DBAFA2BDA303F0021497E /* TableCellItem.swift in Sources */,
|
||||||
71FC86DA2B96F44C00700965 /* PaginationButton.swift in Sources */,
|
71FC86DA2B96F44C00700965 /* PaginationButton.swift in Sources */,
|
||||||
EABFEB642A26473700C4C106 /* NSAttributedString.swift in Sources */,
|
EABFEB642A26473700C4C106 /* NSAttributedString.swift in Sources */,
|
||||||
EAF7F13328A2A16500B287F5 /* AttachmentLabelAttributeModel.swift in Sources */,
|
EAF7F13328A2A16500B287F5 /* AttachmentLabelAttributeModel.swift in Sources */,
|
||||||
@ -1174,6 +1189,7 @@
|
|||||||
EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */,
|
EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */,
|
||||||
EA0D1C3D2A6AD57600E5C127 /* Typography+Enums.swift in Sources */,
|
EA0D1C3D2A6AD57600E5C127 /* Typography+Enums.swift in Sources */,
|
||||||
EAF1FE9B29DB1A6000101452 /* Changeable.swift in Sources */,
|
EAF1FE9B29DB1A6000101452 /* Changeable.swift in Sources */,
|
||||||
|
440B84CA2BD8E0E9004A732A /* Table.swift in Sources */,
|
||||||
EAF7F0A2289AFB3900B287F5 /* Errorable.swift in Sources */,
|
EAF7F0A2289AFB3900B287F5 /* Errorable.swift in Sources */,
|
||||||
EA8E40912A7D3F6300934ED3 /* UIView+Accessibility.swift in Sources */,
|
EA8E40912A7D3F6300934ED3 /* UIView+Accessibility.swift in Sources */,
|
||||||
EA6F330E2B911E9000BACAB9 /* TextView.swift in Sources */,
|
EA6F330E2B911E9000BACAB9 /* TextView.swift in Sources */,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1530"
|
LastUpgradeVersion = "1530"
|
||||||
version = "1.7">
|
version = "1.8">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
buildImplicitDependencies = "YES"
|
buildImplicitDependencies = "YES"
|
||||||
|
|||||||
157
VDS/Components/Table/Table.swift
Normal file
157
VDS/Components/Table/Table.swift
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
//
|
||||||
|
// Table.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Nadigadda, Sumanth on 24/04/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import VDSTokens
|
||||||
|
|
||||||
|
@objc(VDSTable)
|
||||||
|
open class Table: View {
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Private Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
private lazy var matrixView = SelfSizingCollectionView(frame: .zero, collectionViewLayout: flowLayout).with {
|
||||||
|
$0.register(TableCellItem.self, forCellWithReuseIdentifier: TableCellItem.Identifier)
|
||||||
|
$0.dataSource = self
|
||||||
|
$0.delegate = self
|
||||||
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
$0.allowsSelection = false
|
||||||
|
$0.isScrollEnabled = false
|
||||||
|
$0.showsVerticalScrollIndicator = false
|
||||||
|
$0.showsHorizontalScrollIndicator = false
|
||||||
|
$0.isAccessibilityElement = true
|
||||||
|
$0.backgroundColor = .clear
|
||||||
|
}
|
||||||
|
|
||||||
|
private let flowLayout = MatrixFlowLayout().with {
|
||||||
|
$0.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Enums
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
public enum Padding: String, CaseIterable {
|
||||||
|
case standard, compact
|
||||||
|
|
||||||
|
func horizontalValue() -> CGFloat {
|
||||||
|
switch self {
|
||||||
|
case .standard:
|
||||||
|
return UIDevice.isIPad ? VDSLayout.space8X : VDSLayout.space6X
|
||||||
|
case .compact:
|
||||||
|
return UIDevice.isIPad ? VDSLayout.space8X : VDSLayout.space6X
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func verticalValue() -> CGFloat {
|
||||||
|
switch self {
|
||||||
|
case .standard:
|
||||||
|
return UIDevice.isIPad ? VDSLayout.space8X : VDSLayout.space6X
|
||||||
|
case .compact:
|
||||||
|
return UIDevice.isIPad ? VDSLayout.space4X : VDSLayout.space3X
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Public Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
open var striped: Bool = false { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
|
open var padding: Padding = .standard { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
|
open var headerBottomLine: Bool = false { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
|
open var rowBottomLine: Bool = false { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
|
open var headerBottomLineType: Line.Style = .primary { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
|
open var rowBottomLineType: Line.Style = .secondary { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
|
open var tableData: [[Any]]? { didSet { setNeedsUpdate() } }
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Overrides
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
open override func initialSetup() {
|
||||||
|
super.initialSetup()
|
||||||
|
addSubview(matrixView)
|
||||||
|
matrixView.pinToSuperView()
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func updateView() {
|
||||||
|
super.updateView()
|
||||||
|
matrixView.reloadData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Table : UICollectionViewDelegate, UICollectionViewDataSource {
|
||||||
|
|
||||||
|
public func numberOfSections(in collectionView: UICollectionView) -> Int {
|
||||||
|
return tableData?.count ?? 0
|
||||||
|
}
|
||||||
|
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||||
|
return tableData?[section].count ?? 0
|
||||||
|
}
|
||||||
|
|
||||||
|
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||||
|
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TableCellItem.Identifier, for: indexPath) as? TableCellItem,
|
||||||
|
let currentItem = tableData?[indexPath.section][indexPath.row]
|
||||||
|
else { return UICollectionViewCell() }
|
||||||
|
let shouldStrip = striped ? (indexPath.section % 2 != 0) : false
|
||||||
|
let style = indexPath.section == 0 ? headerBottomLineType : rowBottomLineType
|
||||||
|
let hideSeparator = indexPath.section == 0 ? headerBottomLine : rowBottomLine
|
||||||
|
cell.updateCell(content: currentItem, surface: surface, separatorStyle: style, isHeader: indexPath.section == 0, hideSeparator: hideSeparator, striped: shouldStrip)
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Table: UICollectionViewDelegateFlowLayout {
|
||||||
|
|
||||||
|
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
|
||||||
|
guard let sectionCount = tableData?[indexPath.section].count else { return CGSize.zero }
|
||||||
|
let width = Int(collectionView.frame.width) / sectionCount
|
||||||
|
return CGSize(width: width, height: 50)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
|
||||||
|
//return padding.verticalValue()
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
|
||||||
|
//return padding.horizontalValue()
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
final class MatrixFlowLayout : UICollectionViewFlowLayout {
|
||||||
|
|
||||||
|
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
|
||||||
|
guard let layoutAttributesObjects = super.layoutAttributesForElements(in: rect) else { return nil }
|
||||||
|
layoutAttributesObjects.forEach({ layoutAttributes in
|
||||||
|
if layoutAttributes.representedElementCategory == .cell,
|
||||||
|
let newFrame = layoutAttributesForItem(at: layoutAttributes.indexPath)?.frame {
|
||||||
|
layoutAttributes.frame = newFrame
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return layoutAttributesObjects
|
||||||
|
}
|
||||||
|
|
||||||
|
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
|
||||||
|
guard let collectionView = collectionView,
|
||||||
|
let layoutAttributes = super.layoutAttributesForItem(at: indexPath) else { return nil }
|
||||||
|
let itemsCount = CGFloat(collectionView.numberOfItems(inSection: indexPath.section))
|
||||||
|
layoutAttributes.frame.size.width = ceil(collectionView.safeAreaLayoutGuide.layoutFrame.width / itemsCount)
|
||||||
|
return layoutAttributes
|
||||||
|
}
|
||||||
|
}
|
||||||
80
VDS/Components/Table/TableCellItem.swift
Normal file
80
VDS/Components/Table/TableCellItem.swift
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
//
|
||||||
|
// TableCellItem.swift
|
||||||
|
// VDS
|
||||||
|
//
|
||||||
|
// Created by Nadigadda, Sumanth on 25/04/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import VDSTokens
|
||||||
|
|
||||||
|
final class TableCellItem: UICollectionViewCell {
|
||||||
|
|
||||||
|
static let Identifier: String = String(describing: TableCellItem.self)
|
||||||
|
|
||||||
|
private let containerView = View().with {
|
||||||
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private var cellLabel = Label().with {
|
||||||
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
$0.setContentHuggingPriority(.defaultHigh, for: .horizontal)
|
||||||
|
$0.setContentHuggingPriority(.defaultHigh, for:.vertical)
|
||||||
|
$0.textAlignment = .left
|
||||||
|
$0.lineBreakMode = .byWordWrapping
|
||||||
|
}
|
||||||
|
|
||||||
|
private let separator: Line = Line()
|
||||||
|
|
||||||
|
private let backgroundColorConfiguration = SurfaceColorConfiguration(VDSColor.backgroundPrimaryLight, VDSColor.backgroundPrimaryDark)
|
||||||
|
private let stripedColorConfiguration = SurfaceColorConfiguration(VDSColor.backgroundSecondaryLight, VDSColor.backgroundSecondaryDark)
|
||||||
|
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
setupCell()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
setupCell()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupCell() {
|
||||||
|
contentView.backgroundColor = .clear
|
||||||
|
|
||||||
|
addSubview(containerView)
|
||||||
|
containerView.pinToSuperView()
|
||||||
|
|
||||||
|
containerView.addSubview(cellLabel)
|
||||||
|
cellLabel.pinToSuperView()
|
||||||
|
|
||||||
|
containerView.addSubview(separator)
|
||||||
|
separator.pinLeading().pinTrailing().pinBottom()
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateCell(content: Any, surface: Surface, separatorStyle: Line.Style, isHeader: Bool = false, hideSeparator: Bool = false, striped: Bool = false) {
|
||||||
|
guard let info = content as? String else { return }
|
||||||
|
cellLabel.textStyle = textStyle(for: isHeader)
|
||||||
|
cellLabel.text = info
|
||||||
|
cellLabel.surface = surface
|
||||||
|
|
||||||
|
containerView.surface = surface
|
||||||
|
containerView.backgroundColor = striped ? stripedColorConfiguration.getColor(surface) : backgroundColorConfiguration.getColor(surface)
|
||||||
|
|
||||||
|
separator.isHidden = hideSeparator
|
||||||
|
separator.style = separatorStyle
|
||||||
|
separator.surface = surface
|
||||||
|
}
|
||||||
|
|
||||||
|
private func textStyle(for header:Bool) -> TextStyle {
|
||||||
|
return header ? .boldTitleSmall : UIDevice.isIPad ? .bodyLarge : .bodySmall
|
||||||
|
}
|
||||||
|
|
||||||
|
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
|
||||||
|
let targetSize = CGSize(width: layoutAttributes.frame.width, height: 0)
|
||||||
|
layoutAttributes.frame.size = contentView.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel)
|
||||||
|
return layoutAttributes
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user