Skip to content

Commit

Permalink
Six new multi-select variants; simple select/unselect for Stack/Grid
Browse files Browse the repository at this point in the history
  • Loading branch information
Reed Es committed Mar 7, 2022
1 parent 0c8bdb1 commit 899222f
Show file tree
Hide file tree
Showing 26 changed files with 1,441 additions and 28 deletions.
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ macOS | iOS
* Presently targeting macOS v11+ and iOS v14+\*
* Supporting both value and reference semantics (including Core Data, which uses the latter)
* Option to support a bound data source, where inline controls can directly mutate your data model
* Support for single-select, multi-select, or no selection
* Option to sort by column, with indicators and concise syntax
* Option to specify a row background
* Option to specify a row overlay
* Option to specify a row background and/or overlay
* On macOS, option for a hovering highlight, to indicate which row the mouse is over
* MINIMAL use of View erasure (i.e., use of `AnyView`), which can impact scalability and performance\*\*
* No external dependencies!
Expand All @@ -28,11 +28,9 @@ Three table types are supported, as determined by the mechanism by which their h
### List
* Based on SwiftUI's `List`
* Option to support moving of rows through drag and drop
* Support for single-select, multi-select, or no selection at all

### Stack
* Based on `ScrollView`/`LazyVStack`
* Support for single-select and no selection at all

### Grid
* Based on `ScrollView`/`LazyVGrid`
Expand Down Expand Up @@ -107,14 +105,14 @@ While `LazyVGrid` is used here to wrap the header and row items, you could alter

## Tabler Views

_Tabler_ offers twenty-one (21) variants of table views from which you can choose. They break down along the following lines:
_Tabler_ offers twenty-seven (27) variants of table views from which you can choose. They break down along the following lines:

* Table View - the View name
* Type - each of the three table types differ in how they render:
- **List** - based on `List`
- **Stack** - based on `ScrollView`/`LazyVStack`
- **Grid** - based on `ScrollView`/`LazyVGrid`
* Select - single-select, multi-select, or selection not supported
* Select - single-select, multi-select, or no selection
* Value - if checked, can be used with value types (e.g., struct values)
* Reference - if checked, can be used with reference types (e.g., class objects, Core Data, etc.)
* Filter - if checked, `config.filter` is supported (see caveat below)
Expand All @@ -136,12 +134,18 @@ Table View | Type | Select | Value | Reference | Filter
`TablerStack1` | **Stack** | Single | ✓ | ✓ | ✓
`TablerStack1B` | **Stack** | Single | ✓ | | ✓\*
`TablerStack1C` | **Stack** | Single | | ✓ |
`TablerStackM` | **Stack** | Multi | ✓ | ✓ | ✓
`TablerStackMB` | **Stack** | Multi | ✓ | | ✓\*
`TablerStackMC` | **Stack** | Multi | | ✓ |
`TablerGrid` | **Grid** | | ✓ | ✓ | ✓
`TablerGridB` | **Grid** | | ✓ | |
`TablerGridC` | **Grid** | | | ✓ |
`TablerGrid1` | **Grid** | Single | ✓ | ✓ | ✓
`TablerGrid1B` | **Grid** | Single | ✓ | |
`TablerGrid1C` | **Grid** | Single | | ✓ |
`TablerGridM` | **Grid** | Multi | ✓ | ✓ | ✓
`TablerGridMB` | **Grid** | Multi | ✓ | |
`TablerGridMC` | **Grid** | Multi | | ✓ |

\* filtering with bound values likely not scalable as implemented. If you can find a better way to implement, please submit a pull request!

Expand Down
14 changes: 11 additions & 3 deletions Sources/Grid/Internal/GridItemMod1.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// GridItemMod.swift
// GridItemMod1.swift
//
// Copyright 2022 FlowAllocator LLC
//
Expand All @@ -18,6 +18,7 @@

import SwiftUI

/// Support for single-select Grid-based rows
struct GridItemMod1<Element>: ViewModifier
where Element: Identifiable
{
Expand All @@ -34,10 +35,17 @@ struct GridItemMod1<Element>: ViewModifier
content
.padding(config.itemPadding)

#if os(macOS) || targetEnvironment(macCatalyst)
// simple tap to select (or unselect)
.contentShape(Rectangle())
.onTapGesture { selected = element.id }
.onTapGesture {
if selected == element.id {
selected = nil
} else {
selected = element.id
}
}

#if os(macOS) || targetEnvironment(macCatalyst)
.onHover { if $0 { hovered = element.id } }
//.frame(maxWidth: .infinity) // NOTE this centers the grid item
.background(hovered == element.id ? config.hoverColor : Color.clear)
Expand Down
54 changes: 54 additions & 0 deletions Sources/Grid/Internal/GridItemModM.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// GridItemModM.swift
//
// Copyright 2022 FlowAllocator LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import SwiftUI

/// Support for multi-select Grid-based rows
struct GridItemModM<Element>: ViewModifier
where Element: Identifiable
{
typealias Config = TablerGridConfig<Element>
typealias Hovered = Element.ID?
typealias Selected = Set<Element.ID>

let config: Config
let element: Element
@Binding var hovered: Hovered
@Binding var selected: Selected

func body(content: Content) -> some View {
content
.padding(config.itemPadding)

// simple tap to select (or unselect)
.contentShape(Rectangle())
.onTapGesture {
if selected.contains(element.id) {
selected.remove(element.id)
} else {
selected.insert(element.id)
}
}

#if os(macOS) || targetEnvironment(macCatalyst)
.onHover { if $0 { hovered = element.id } }
//.frame(maxWidth: .infinity) // NOTE this centers the grid item
.background(hovered == element.id ? config.hoverColor : Color.clear)
#endif
}
}
2 changes: 1 addition & 1 deletion Sources/Grid/TablerGrid1.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import SwiftUI

/// Grid-based table, with support for single-selection
/// Grid-based table, with support for single-select
public struct TablerGrid1<Element, Header, Row, RowBack, RowOver, Results>: View
where Element: Identifiable,
Header: View,
Expand Down
2 changes: 1 addition & 1 deletion Sources/Grid/TablerGrid1B.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import SwiftUI

/// Grid-based table, with support for single-selection and bound values from RandomAccessCollection
/// Grid-based table, with support for single-select and bound value types
public struct TablerGrid1B<Element, Header, Row, RowBack, RowOver, Results>: View
where Element: Identifiable,
Header: View,
Expand Down
1 change: 0 additions & 1 deletion Sources/Grid/TablerGrid1C.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
// limitations under the License.
//

import CoreData
import SwiftUI

/// Grid-based table, with support for reference types
Expand Down
2 changes: 1 addition & 1 deletion Sources/Grid/TablerGridB.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import SwiftUI

/// Grid-based table, with support for bound values from RandomAccessCollection
/// Grid-based table, with support for bound value types
public struct TablerGridB<Element, Header, Row, RowBack, RowOver, Results>: View
where Element: Identifiable,
Header: View,
Expand Down
1 change: 0 additions & 1 deletion Sources/Grid/TablerGridC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
// limitations under the License.
//

import CoreData
import SwiftUI

/// Grid-based table, with support for reference types
Expand Down
Loading

0 comments on commit 899222f

Please sign in to comment.