Skip to content

Commit

Permalink
Improved MUIList with dynamic data.
Browse files Browse the repository at this point in the history
  • Loading branch information
aumChauhan committed Jan 30, 2024
1 parent a262e95 commit 2187d5f
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 86 deletions.
23 changes: 12 additions & 11 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -570,26 +570,27 @@ struct ContentView: View {
## `MUIList`
`MUIList` is a SwiftUI view that provides a MaterialUI-styled list with various visual styles. The `MUIList` view is designed to display a collection of elements with different visual styles such as plain, inset, or insetGrouped.

## Usage

To use `MUIList`, create an instance of the view by specifying the data, a key path to uniquely identify each element, and a closure that returns the content view for a given element. Additionally, you can customize the list style.

## Parameters

- `data: Data`: A collection of elements to display in the list.
- `id: KeyPath<Data.Element, ID>`: A key path to an `ID` property on each element to uniquely identify them.
- `listStyle: MUIListStyle`: The style of the list, such as `.plain`, `.inset`, or `.insetGrouped`.
- `content: (Data.Element) -> Content`: A closure that returns the content view for a given element.
- `listStyle:`: The style of the list, such as `.plain`, `.inset`, or `.insetGrouped`.
- `content:`: A closure that returns the content view for a given element.

## Example

```swift
struct ContentView: View {
let items = ["Item 1", "Item 2", "Item 3"]

var body: some View {
MUIList(items, id: \.self, listStyle: .insetGrouped) { item in
Text(item)
MUIList(listStyle: .insetGrouped) { in
Text("item_1")
Text("item_2")
}

// OR

MUIList() {
Text("item_1")
Text("item_2")
}
}
}
Expand Down
55 changes: 37 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,58 +17,76 @@ MaterialUIKit is a SwiftUI package offering a set of user interface components i
<details>
<summary> Get a glimpse of MaterialUI components: </summary>

### Alert
---
## Alert
![Alert](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/f3098833-2f6e-4758-a5a3-9da37c72aa97)

### Button
---
## Button
![Button](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/8a1fa8ab-84ab-4058-bfa1-a8aa8d7da1b6)

### Card View
---
## Card View
![CardView](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/366b24f4-78a1-4c67-bde6-76ce3e83c2b8)

### Checkbox
---
## Checkbox
![Checkbox](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/2fdcfad1-7456-4e0f-94c5-00a683627539)

### Date Picker
---
## Date Picker
![DatePicker](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/ce23247f-4fa4-4c75-9841-8c062902adbc)

### Dialog Sheet
---
## Dialog Sheet
![Dialog Sheet](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/4018cb9b-64c5-4b99-a6ca-b452277cc056)

### Floating Button
---
## Floating Button
![FAB](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/fca45946-4c95-4d65-b834-054763e456ba)

### Icon Button
---
## Icon Button
![IconButton](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/001f5052-38e6-46c0-aa06-f187b690730c)

### List
---
## List
![List](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/00589eb0-14bf-445a-a525-20a02dbf4065)

### Navigation View
---
## Navigation View
![NavigationView](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/f94f73cb-0a8d-4f49-b122-3c8ce46b9614)

### Progress View
---
## Progress View
![ProgressView](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/6ab95c67-6b4a-4618-a2d7-c421df4e4e79)

### SearchBar
---
## SearchBar
![SearchBar](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/40b05fa6-24a5-41fe-9e2b-d89b4fb14611)

### Segmented Control
---
## Segmented Control
![SegmentedControl](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/4e048a08-c759-4b59-8d18-bbd6568e1bcd)

### Snackbar
---
## Snackbar
![SnackBar](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/aa5bd193-4463-48f4-8d30-7415fa13630f)

### Switch
---
## Switch
![Switch](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/fe3c6276-1c2b-4acd-a5df-1145dc999d45)

### TabView
---
## TabView
![TabVIew](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/f38be0ad-8195-466b-a889-470813b2db5c)

### TimePicker
---
## TimePicker
![TimePicker](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/bca2c916-e30f-40b6-969e-6703b865b37d)

### Text & Secure Field
---
## Text & Secure Field
![TextField](https://github.com/aumChauhan/MaterialUIKit/assets/83302656/093b5ed5-1d39-4ba4-966d-ef68fc5f0939)

</details>
Expand Down Expand Up @@ -132,3 +150,4 @@ Detailed documentation for each component can be found [here](https://github.com

MaterialUIKit is released under the [MIT License](LICENSE)


163 changes: 106 additions & 57 deletions Sources/MaterialUIKit/Components/Navigation And Structure/MUIList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import SwiftUI
// MARK: - MUIListStyle

/// Enum representing different styles for `MUIList`.
@available(iOS 15.0, *)
public enum MUIListStyle {
/// A plain-style list with default spacing and divider lines.
case plain
Expand All @@ -23,96 +22,75 @@ public enum MUIListStyle {
case insetGrouped
}

// MARK: - MUIList
// MARK: - MUIListViewLayout

/// A MaterialUI style list with different visual styles.
/// A `_Variadic­View.Tree` with a MUIListViewLayout and list styles.
@available(iOS 15.0, *)
public struct MUIList<Data, ID, Content>: View where Data: RandomAccessCollection, ID: Hashable, Content: View, Data.Element: Hashable, Data: Hashable {
private struct MUIListViewLayout: _VariadicView_UnaryViewRoot {

// MARK: - Properties

public var data: Data
public var id: KeyPath<Data.Element, ID>
public var content: (Data.Element) -> Content
public var listStyle: MUIListStyle

// MARK: - Initializers

/// Creates a stylized list with a default insetGrouped style.
/// - Parameters:
/// - data: A collection of elements to display in the list.
/// - id: A key path to an `ID` property on each element to uniquely identify them.
/// - content: A closure that returns the content view for a given element.
public init(_ data: Data, id: KeyPath<Data.Element, ID>, @ViewBuilder _ content: @escaping (Data.Element) -> Content) {
self.data = data
self.id = id
self.content = content
self.listStyle = .insetGrouped
}

/// Creates a stylized list with a custom list style.
/// - Parameters:
/// - data: A collection of elements to display in the list.
/// - id: A key path to an `ID` property on each element to uniquely identify them.
/// - listStyle: The style of the list, such as `.plain`, `.inset`, or `.insetGrouped`.
/// - content: A closure that returns the content view for a given element.
public init(_ data: Data, id: KeyPath<Data.Element, ID>, listStyle: MUIListStyle, @ViewBuilder _ content: @escaping (Data.Element) -> Content) {
self.data = data
self.id = id
self.content = content
public init(listStyle: MUIListStyle) {
self.listStyle = listStyle
}

// MARK: - View Body
// MARK: - Body

public var body: some View {
ScrollView(.vertical) {
@ViewBuilder
public func body(children: _VariadicView.Children) -> some View {

ScrollView {
switch listStyle {
case .plain:
plainStyle()
plainStyle(children: children)

case .inset:
insetStyle()
insetStyle(children: children)

case .insetGrouped:
insetGroupedStyle()
insetGroupedStyle(children: children)
}
}
}
}

// MARK: - Extension MIUList

@available(iOS 15.0, *)
extension MUIList {
extension MUIListViewLayout {

/// Returns a plain-style list with a vertical stack of content items.
private func plainStyle() -> some View {
VStack(spacing: 12) {
ForEach(data, id: id) { item in
content(item)
.tag(item)
private func plainStyle(children: _VariadicView.Children) -> some View {

let last = children.last?.id

return VStack(spacing: 12) {
ForEach(children) { child in
child
.frame(maxWidth: .infinity, alignment: .leading)
.font(.headline)
.fontWeightWithFallback(.regular)
.foregroundColor(MaterialUI.tint.primaryTitle())
.padding(.horizontal, 15)
.padding(.vertical, 2)

if !isLastElement(data: data, item: item) {
if child.id != last {
MUIDivider()
}

}
}
.padding(10)
}

/// Returns an inset-style list with rounded rectangles as background on individual list item.
private func insetStyle() -> some View {
VStack(spacing: 12) {
ForEach(data, id: id) { item in
content(item)
.tag(item)
private func insetStyle(children: _VariadicView.Children) -> some View {
return VStack(spacing: 12) {
ForEach(children) { child in
child
.frame(maxWidth: .infinity, alignment: .leading)
.font(.headline)
.fontWeightWithFallback(.regular)
Expand All @@ -126,18 +104,19 @@ extension MUIList {
}

/// Returns an inset-grouped-style list with rounded rectangles as background.
private func insetGroupedStyle() -> some View {
VStack(spacing: 12) {
ForEach(data, id: id) { item in
content(item)
.tag(item)
private func insetGroupedStyle(children: _VariadicView.Children) -> some View {
let last = children.last?.id

return VStack(spacing: 12) {
ForEach(children) { child in
child
.frame(maxWidth: .infinity, alignment: .leading)
.font(.headline)
.fontWeightWithFallback(.regular)
.foregroundColor(MaterialUI.tint.primaryTitle())
.padding(0)

if !isLastElement(data: data, item: item) {
if child.id != last {
MUIDivider()
}
}
Expand All @@ -147,10 +126,80 @@ extension MUIList {
.cornerRadius(25)
.padding(15)
}
}


// MARK: - MUIList

/// A MaterialUI style list with different visual styles.
@available(iOS 15.0, *)
public struct MUIList<Content>: View where Content: View {

// MARK: - Properties

public var content: Content
public var listStyle: MUIListStyle

// MARK: - Initializers

/// Creates a stylized list with a default insetGrouped style.
/// - Parameters:
/// - content: A closure that returns the content view for a given element.
public init(@ViewBuilder content: () -> Content) {
self.content = content()
self.listStyle = .insetGrouped
}

/// Checks if the current element is the last one in the collection.
private func isLastElement(data: Data, item: Data.Element) -> Bool {
return data.last == item
/// Creates a stylized list with a custom list style.
/// - Parameters:
/// - listStyle: The style of the list, such as `.plain`, `.inset`, or `.insetGrouped`.
/// - content: A closure that returns the content view for a given element.
public init(listStyle: MUIListStyle, @ViewBuilder content: () -> Content) {
self.content = content()
self.listStyle = listStyle
}

// MARK: - View Body

public var body: some View {
ScrollView(.vertical) {
switch listStyle {
case .plain:
plainStyle()

case .inset:
insetStyle()

case .insetGrouped:
insetGroupedStyle()
}
}
}
}


// MARK: - Extension MIUList
@available(iOS 15.0, *)
extension MUIList {

/// Returns a plain-style list with a vertical stack of content items.
private func plainStyle() -> some View {
_VariadicView.Tree(MUIListViewLayout(listStyle: listStyle)) {
content
}
}

/// Returns an inset-style list with rounded rectangles as background on individual list item.
private func insetStyle() -> some View {
_VariadicView.Tree(MUIListViewLayout(listStyle: listStyle)) {
content
}
}

/// Returns an inset-grouped-style list with rounded rectangles as background.
private func insetGroupedStyle() -> some View {
_VariadicView.Tree(MUIListViewLayout(listStyle: listStyle)) {
content
}
}
}

0 comments on commit 2187d5f

Please sign in to comment.