diff --git a/Development/Development/BookCollectionView.swift b/Development/Development/BookCollectionView.swift index 1086502..5e3dde1 100644 --- a/Development/Development/BookCollectionView.swift +++ b/Development/Development/BookCollectionView.swift @@ -1,6 +1,7 @@ -import CollectionView import SwiftUI +@testable import CollectionView + struct BookCollectionViewSingleSection: View, PreviewProvider { var body: some View { @@ -18,17 +19,19 @@ struct BookCollectionViewSingleSection: View, PreviewProvider { var body: some View { CollectionView( - dataSource: .collection( - data: Item.mock(), - selection: .single( - selected: selected?.id, - onChange: { e in - selected = e - }), - cell: { index, item in - Cell(index: index, item: item) - } - ), + content: { + SelectableForEach( + data: Item.mock(), + selection: .single( + selected: selected?.id, + onChange: { e in + selected = e + }), + cell: { index, item in + Cell(index: index, item: item) + } + ) + }, layout: .list { RoundedRectangle(cornerRadius: 8) .fill(.secondary) @@ -59,7 +62,7 @@ struct BookCollectionViewCombined: View, PreviewProvider { var body: some View { CollectionView( - dataSource: CollectionViewDataSources.Unified { + content: { Text("Static content") .overlay(content: { @@ -68,7 +71,7 @@ struct BookCollectionViewCombined: View, PreviewProvider { Text("📱❄️") - CollectionViewDataSources.UsingCollection( + SelectableForEach( data: Item.mock(10), selection: .single( selected: selected?.id, @@ -82,7 +85,7 @@ struct BookCollectionViewCombined: View, PreviewProvider { Text("📱❄️") - CollectionViewDataSources.UsingCollection( + SelectableForEach( data: Item.mock(10), selection: .single( selected: selected2?.id, @@ -110,19 +113,6 @@ struct BookCollectionViewCombined: View, PreviewProvider { } -#Preview { - CollectionViewDataSources.UsingCollection( - data: Item.mock(10), - selection: .disabled(), - cell: { index, item in - Cell(index: index, item: item) - } - ) -} -//#Preview { -// BookPreview() -//} - #Preview("Custom List / Single selection") { struct Book: View { @@ -131,17 +121,19 @@ struct BookCollectionViewCombined: View, PreviewProvider { var body: some View { CollectionView( - dataSource: CollectionViewDataSources.UsingCollection( - data: Item.mock(), - selection: .single( - selected: selected?.id, - onChange: { e in - selected = e - }), - cell: { index, item in - Cell(index: index, item: item) - } - ), + content: { + SelectableForEach( + data: Item.mock(), + selection: .single( + selected: selected?.id, + onChange: { e in + selected = e + }), + cell: { index, item in + Cell(index: index, item: item) + } + ) + }, layout: .list { RoundedRectangle(cornerRadius: 8) .fill(.secondary) @@ -164,23 +156,25 @@ struct BookCollectionViewCombined: View, PreviewProvider { var body: some View { CollectionView( - dataSource: CollectionViewDataSources.UsingCollection( - data: Item.mock(), - selection: .multiple( - selected: selected, - canMoreSelect: selected.count < 3, - onChange: { e, action in - switch action { - case .selected: - selected.insert(e.id) - case .deselected: - selected.remove(e.id) - } - }), - cell: { index, item in - Cell(index: index, item: item) - } - ), + content: { + SelectableForEach( + data: Item.mock(), + selection: .multiple( + selected: selected, + canMoreSelect: selected.count < 3, + onChange: { e, action in + switch action { + case .selected: + selected.insert(e.id) + case .deselected: + selected.remove(e.id) + } + }), + cell: { index, item in + Cell(index: index, item: item) + } + ) + }, layout: .list { RoundedRectangle(cornerRadius: 8) .fill(.secondary) @@ -197,16 +191,18 @@ struct BookCollectionViewCombined: View, PreviewProvider { #Preview("SwiftUI List") { CollectionView( - dataSource: CollectionViewDataSources.UsingCollection( - data: Item.mock(), - selection: .disabled(), - cell: { index, item in - HStack { - Text(index.description) - Text(item.title) + content: { + SelectableForEach( + data: Item.mock(), + selection: .disabled(), + cell: { index, item in + HStack { + Text(index.description) + Text(item.title) + } } - } - ), + ) + }, layout: CollectionViewLayouts.PlatformList() ) } @@ -246,84 +242,27 @@ struct BookCollectionViewCombined: View, PreviewProvider { return BookList() } -struct Item: Identifiable { - var id: Int - var title: String - - static func mock(_ count: Int = 1000) -> [Item] { - return (0..: CollectionViewSelection { - - private let selected: Item.ID? - private let onChange: (_ selected: Item?) -> Void - private let canSelect: (_ item: Item) -> Bool - - public init( - selected: Item.ID?, - canSelect: @escaping (_ item: Item) -> Bool, - onChange: @escaping (_ selected: Item?) -> Void - ) { - self.selected = selected - self.onChange = onChange - self.canSelect = canSelect } - public func isSelected(for id: Item.ID) -> Bool { - self.selected == id - } - - public func isEnabled(for id: Item.ID) -> Bool { - return true - } - - public func update(isSelected: Bool, for item: Item) { - if isSelected { - if canSelect(item) { - onChange(item) - } - } else { - onChange(nil) - } - } + return Book() } diff --git a/Sources/CollectionView/CollectionView.swift b/Sources/CollectionView/CollectionView.swift index a9af0ab..7035935 100644 --- a/Sources/CollectionView/CollectionView.swift +++ b/Sources/CollectionView/CollectionView.swift @@ -1,39 +1,28 @@ import IndexedCollection import SwiftUI - -/// Still searching better name -/// - built on top of SwiftUI only -@available(iOS 16, *) public struct CollectionView< - DataSource: CollectionViewDataSource, + Content: View, Layout: CollectionViewLayoutType >: View { - private let dataSource: DataSource + private let content: Content + private let layout: Layout public init( - dataSource: DataSource, + @ViewBuilder content: () -> Content, layout: Layout ) { - self.dataSource = dataSource + self.content = content() self.layout = layout + self.items = items + self.selection = .init() } public var body: some View { - - self.dataSource + content .modifier(layout) - } } - -extension EnvironmentValues { - @Entry public var collectionView_isSelected: Bool = false -} - -extension EnvironmentValues { - @Entry public var collectionView_updateSelection: (Bool) -> Void = { _ in } -} diff --git a/Sources/CollectionView/PreviewSupport.swift b/Sources/CollectionView/PreviewSupport.swift new file mode 100644 index 0000000..5b3cae3 --- /dev/null +++ b/Sources/CollectionView/PreviewSupport.swift @@ -0,0 +1,51 @@ + +#if DEBUG + +import SwiftUI + +struct Item: Identifiable { + var id: Int + var title: String + + static func mock(_ count: Int = 1000) -> [Item] { + return (0.. +>: View where Data.Element: Identifiable { + + public let data: Data + public let selection: Selection + private let cell: (Data.Index, Data.Element) -> Cell + + public init( + data: Data, + selection: Selection, + cell: @escaping (Data.Index, Data.Element) -> Cell + ) { + self.data = data + self.cell = cell + self.selection = selection + } + + public var body: some View { + ForEach(IndexedCollection(data)) { element in + + let isSelected: Bool = selection.isSelected(for: element.id) + let isDisabled: Bool = !selection.isEnabled(for: element.id) + + cell(element.index, element.value) + .disabled(isDisabled) + .environment(\.collectionView_isSelected, isSelected) + .environment( + \.collectionView_updateSelection, + { [selection] isSelected in + selection.update(isSelected: isSelected, for: element.value) + }) + } + } + +} + +extension EnvironmentValues { + @Entry public var collectionView_isSelected: Bool = false +} + +extension EnvironmentValues { + @Entry public var collectionView_updateSelection: (Bool) -> Void = { _ in } +} +