@ethanhann/mantine-dataview 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +216 -40
- package/dist/components/DataCards/DataCards.d.ts +3 -1
- package/dist/components/DataTable/DataTable.d.ts +5 -1
- package/dist/components/DataToolbar/DataToolbar.d.ts +8 -1
- package/dist/components/DataToolbar/ViewSwitcher.d.ts +8 -2
- package/dist/components/DataToolbar/index.d.ts +1 -0
- package/dist/components/{DataView/DataView.d.ts → DataViewer/DataViewer.d.ts} +9 -7
- package/dist/components/{DataView → DataViewer}/context.d.ts +1 -0
- package/dist/components/DataViewer/index.d.ts +2 -0
- package/dist/core/useRowTransition.d.ts +8 -0
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +482 -413
- package/dist/index.js.map +1 -1
- package/dist/mantine-dataview.css +2 -0
- package/dist/types/options.d.ts +3 -1
- package/dist/types/request.d.ts +4 -0
- package/package.json +1 -1
- package/dist/components/DataView/index.d.ts +0 -2
package/README.md
CHANGED
|
@@ -18,13 +18,16 @@ Built on [Mantine](https://mantine.dev) v9 and [TanStack Table](https://tanstack
|
|
|
18
18
|
- Column data types (`text`, `number`, `currency`, `date`, `boolean`) with automatic Intl-based formatting.
|
|
19
19
|
- Seven filter variants with smart controls: `SegmentedControl` for booleans, `RangeSlider` for bounded numbers,
|
|
20
20
|
`DatePickerInput` for dates.
|
|
21
|
-
- Custom filter components
|
|
21
|
+
- Custom filter components. Bring your own UI per column.
|
|
22
22
|
- Column pinning (left/right) with sticky positioning.
|
|
23
23
|
- CSV export with optional formatted output.
|
|
24
24
|
- Router-agnostic URL state sync with a default History-API adapter.
|
|
25
25
|
- Cross-page row selection + a shared bulk-action bar.
|
|
26
26
|
- Column-meta card composition (`title`/`subtitle`/`media`/`badge`/`meta`) + a `renderCard` escape hatch.
|
|
27
27
|
- Responsive: force-to-cards below a breakpoint, filters collapse to a bottom drawer on mobile.
|
|
28
|
+
- Faceted search with server-provided counts on filter options and range buckets with dynamic totals.
|
|
29
|
+
- External parameters (`params`) for scope selectors, toggles, and other non-column filters.
|
|
30
|
+
- Controls automatically disabled while data is loading (opt-out with `disableWhileLoading`).
|
|
28
31
|
- Loading / empty / filtered-empty / error states, consistent across both views.
|
|
29
32
|
- Dark mode support via Mantine's color scheme system.
|
|
30
33
|
- Strongly typed end to end; ships its own `.d.ts`. No icon dependency.
|
|
@@ -58,7 +61,7 @@ The easiest path is `useDataViewFetcher`, which owns the fetch lifecycle for you
|
|
|
58
61
|
|
|
59
62
|
```tsx
|
|
60
63
|
import {
|
|
61
|
-
|
|
64
|
+
DataViewer,
|
|
62
65
|
useDataViewFetcher,
|
|
63
66
|
createColumnHelper,
|
|
64
67
|
type DataColumnDef,
|
|
@@ -101,11 +104,11 @@ function Users() {
|
|
|
101
104
|
},
|
|
102
105
|
});
|
|
103
106
|
|
|
104
|
-
return <
|
|
107
|
+
return <DataViewer view={view}/>;
|
|
105
108
|
}
|
|
106
109
|
```
|
|
107
110
|
|
|
108
|
-
`<
|
|
111
|
+
`<DataViewer view={view} />` renders the toolbar, the active presentation, and pagination.
|
|
109
112
|
|
|
110
113
|
## Column builder
|
|
111
114
|
|
|
@@ -153,12 +156,12 @@ or object to merge), `format`, `align`, `cell`, `enableSorting`.
|
|
|
153
156
|
Compose your own layout by passing children:
|
|
154
157
|
|
|
155
158
|
```tsx
|
|
156
|
-
<
|
|
157
|
-
<
|
|
158
|
-
<
|
|
159
|
-
<
|
|
160
|
-
<
|
|
161
|
-
</
|
|
159
|
+
<DataViewer view={view}>
|
|
160
|
+
<DataViewer.Toolbar/>
|
|
161
|
+
<DataViewer.BulkActions/>
|
|
162
|
+
<DataViewer.Body/>
|
|
163
|
+
<DataViewer.Pagination/>
|
|
164
|
+
</DataViewer>
|
|
162
165
|
```
|
|
163
166
|
|
|
164
167
|
Or use the standalone components directly for full control:
|
|
@@ -169,10 +172,54 @@ Or use the standalone components directly for full control:
|
|
|
169
172
|
<DataPagination view={view}/>
|
|
170
173
|
```
|
|
171
174
|
|
|
175
|
+
### Toolbar sections
|
|
176
|
+
|
|
177
|
+
Inject controls into the toolbar without rebuilding it from scratch using `leftSection`
|
|
178
|
+
and `rightSection`:
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
<DataViewer.Toolbar
|
|
182
|
+
leftSection={<Text fw={600}>Users</Text>}
|
|
183
|
+
rightSection={
|
|
184
|
+
<Group gap="xs">
|
|
185
|
+
<Button size="xs" onClick={() => view.exportCsv()}>Export</Button>
|
|
186
|
+
<Button size="xs" onClick={() => view.refetch()}>Refresh</Button>
|
|
187
|
+
</Group>
|
|
188
|
+
}
|
|
189
|
+
/>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
- `leftSection` renders before the search input (start of the left group).
|
|
193
|
+
- `rightSection` renders after the view switcher (end of the right group).
|
|
194
|
+
|
|
195
|
+
Both sections are disabled during loading along with the other toolbar controls.
|
|
196
|
+
|
|
197
|
+
### View switcher
|
|
198
|
+
|
|
199
|
+
The `ViewSwitcher` is exported for standalone use with customizable labels:
|
|
200
|
+
|
|
201
|
+
```tsx
|
|
202
|
+
import { ViewSwitcher } from "@ethanhann/mantine-dataview";
|
|
203
|
+
|
|
204
|
+
// Default
|
|
205
|
+
<ViewSwitcher view={view} />
|
|
206
|
+
|
|
207
|
+
// Custom labels (text or icons)
|
|
208
|
+
<ViewSwitcher view={view} tableLabel="List" cardsLabel="Grid" />
|
|
209
|
+
<ViewSwitcher view={view} tableLabel={<IconList />} cardsLabel={<IconGrid />} />
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Or drive the view programmatically:
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
view.setView("cards"); // switch to cards
|
|
216
|
+
view.view; // current view: "table" | "cards"
|
|
217
|
+
```
|
|
218
|
+
|
|
172
219
|
## Controlled (bring your own data layer)
|
|
173
220
|
|
|
174
|
-
`useDataViewFetcher` is a thin convenience wrapper. The core, `useDataView`, is fully controlled
|
|
175
|
-
|
|
221
|
+
`useDataViewFetcher` is a thin convenience wrapper. The core, `useDataView`, is fully controlled.
|
|
222
|
+
You supply `rows`/`rowCount`/`status` and respond to `onRequestChange`:
|
|
176
223
|
|
|
177
224
|
```tsx
|
|
178
225
|
const [resp, setResp] = useState({rows: [], rowCount: 0});
|
|
@@ -198,21 +245,50 @@ const view = useDataView<User>({
|
|
|
198
245
|
|
|
199
246
|
The request is emitted immediately for pagination/sorting and debounced for search/filters.
|
|
200
247
|
|
|
248
|
+
### External parameters
|
|
249
|
+
|
|
250
|
+
Pass arbitrary parameters that aren't tied to a column. They're included in every
|
|
251
|
+
`DataViewRequest`, trigger a refetch when they change, and reset pagination to page 1:
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
const [tenantId, setTenantId] = useState("acme");
|
|
255
|
+
const [showArchived, setShowArchived] = useState(false);
|
|
256
|
+
|
|
257
|
+
const view = useDataViewFetcher<User>({
|
|
258
|
+
columns,
|
|
259
|
+
getRowId,
|
|
260
|
+
fetcher: async (request) => {
|
|
261
|
+
// request.params = { tenantId: "acme", showArchived: false }
|
|
262
|
+
const res = await api.list(request);
|
|
263
|
+
return {rows: res.items, rowCount: res.total};
|
|
264
|
+
},
|
|
265
|
+
params: {tenantId, showArchived},
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// Render your own controls...
|
|
269
|
+
<Select data={tenants} value={tenantId} onChange={setTenantId}/>
|
|
270
|
+
<Switch checked={showArchived} onChange={(e) => setShowArchived(e.currentTarget.checked)}/>
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Values are typed as `FilterParam` (`string | number | boolean | null | string[] | number[]`).
|
|
274
|
+
|
|
201
275
|
### Refetching on external changes
|
|
202
276
|
|
|
203
|
-
|
|
204
|
-
|
|
277
|
+
For cases where external state affects the fetcher but isn't a named parameter (e.g. it's
|
|
278
|
+
baked into the closure), use `deps` to trigger a refetch:
|
|
205
279
|
|
|
206
280
|
```tsx
|
|
207
281
|
const view = useDataViewFetcher<User>({
|
|
208
282
|
columns,
|
|
209
283
|
getRowId,
|
|
210
284
|
fetcher,
|
|
211
|
-
deps: [selectedTenantId
|
|
285
|
+
deps: [selectedTenantId],
|
|
212
286
|
});
|
|
213
287
|
```
|
|
214
288
|
|
|
215
289
|
When any value in `deps` changes, the current request is re-emitted to the fetcher.
|
|
290
|
+
Prefer `params` when the server needs to see the values; use `deps` when they're already
|
|
291
|
+
in the fetcher closure.
|
|
216
292
|
|
|
217
293
|
### Manual refresh
|
|
218
294
|
|
|
@@ -230,7 +306,7 @@ error retry button uses.
|
|
|
230
306
|
Set `dataType` on a column's meta to enable automatic value formatting. When no explicit
|
|
231
307
|
`cell` renderer is provided, the library formats values using `Intl.NumberFormat` or
|
|
232
308
|
`Intl.DateTimeFormat` based on the data type. Raw values are preserved for server requests,
|
|
233
|
-
sorting, and filtering
|
|
309
|
+
sorting, and filtering. Formatting is display-only.
|
|
234
310
|
|
|
235
311
|
```tsx
|
|
236
312
|
col.accessor("price", {
|
|
@@ -254,9 +330,9 @@ col.accessor("createdAt", {
|
|
|
254
330
|
|
|
255
331
|
### Format overrides (three levels)
|
|
256
332
|
|
|
257
|
-
1. **Library defaults
|
|
258
|
-
2. **Table-scoped
|
|
259
|
-
3. **Column-scoped
|
|
333
|
+
1. **Library defaults**, the built-in formatters per data type (above).
|
|
334
|
+
2. **Table-scoped**, `formatDefaults` on the hook options, keyed by data type.
|
|
335
|
+
3. **Column-scoped**, `format` on `ColumnMeta`, overrides everything for that column.
|
|
260
336
|
|
|
261
337
|
```tsx
|
|
262
338
|
const view = useDataViewFetcher({
|
|
@@ -315,7 +391,7 @@ col.accessor("avatar", {header: "Avatar", enableSorting: false});
|
|
|
315
391
|
|
|
316
392
|
## Custom headers
|
|
317
393
|
|
|
318
|
-
Column headers support the same render function pattern as cells
|
|
394
|
+
Column headers support the same render function pattern as cells. Pass a component or
|
|
319
395
|
function to the `header` property:
|
|
320
396
|
|
|
321
397
|
```tsx
|
|
@@ -399,7 +475,7 @@ Define filters declaratively on column meta. Seven variants are built in:
|
|
|
399
475
|
| `dateRange` | `DatePickerInput` (range) | Two-date calendar picker |
|
|
400
476
|
|
|
401
477
|
```tsx
|
|
402
|
-
// Boolean
|
|
478
|
+
// Boolean, renders as a segmented control
|
|
403
479
|
meta: {
|
|
404
480
|
filter: {
|
|
405
481
|
variant: "boolean"
|
|
@@ -465,19 +541,19 @@ col.accessor("location", {
|
|
|
465
541
|
```tsx
|
|
466
542
|
import {FilterControl} from "@ethanhann/mantine-dataview";
|
|
467
543
|
|
|
468
|
-
<
|
|
544
|
+
<DataViewer view={view}>
|
|
469
545
|
{view.table.getColumn("inStock") && (
|
|
470
546
|
<FilterControl column={view.table.getColumn("inStock")!}/>
|
|
471
547
|
)}
|
|
472
|
-
<
|
|
473
|
-
<
|
|
474
|
-
<
|
|
475
|
-
</
|
|
548
|
+
<DataViewer.Toolbar/>
|
|
549
|
+
<DataViewer.Body/>
|
|
550
|
+
<DataViewer.Pagination/>
|
|
551
|
+
</DataViewer>
|
|
476
552
|
```
|
|
477
553
|
|
|
478
554
|
### Programmatic filter control
|
|
479
555
|
|
|
480
|
-
Reset all filters or clear a specific column from anywhere
|
|
556
|
+
Reset all filters or clear a specific column from anywhere, no need to be inside the toolbar:
|
|
481
557
|
|
|
482
558
|
```tsx
|
|
483
559
|
// Reset all filters
|
|
@@ -494,6 +570,73 @@ Reset all filters or clear a specific column from anywhere — no need to be ins
|
|
|
494
570
|
- **Mobile** (below `sm` breakpoint): always collapsed into a bottom drawer.
|
|
495
571
|
- A "Reset filters" button appears automatically when any filter is active.
|
|
496
572
|
|
|
573
|
+
## Faceted search
|
|
574
|
+
|
|
575
|
+
When the server returns `facets` in the response, filter controls automatically adapt to show
|
|
576
|
+
dynamic counts, disable zero-result options, and render clickable range buckets.
|
|
577
|
+
|
|
578
|
+
### Server response with facets
|
|
579
|
+
|
|
580
|
+
```tsx
|
|
581
|
+
fetcher: async (request) => {
|
|
582
|
+
const res = await api.list(request);
|
|
583
|
+
return {
|
|
584
|
+
rows: res.items,
|
|
585
|
+
rowCount: res.total,
|
|
586
|
+
facets: {
|
|
587
|
+
size: {
|
|
588
|
+
type: "values",
|
|
589
|
+
values: [
|
|
590
|
+
{ value: "S", label: "Small", count: 12 },
|
|
591
|
+
{ value: "M", label: "Medium", count: 34 },
|
|
592
|
+
{ value: "L", label: "Large", count: 0 },
|
|
593
|
+
],
|
|
594
|
+
},
|
|
595
|
+
price: {
|
|
596
|
+
type: "ranges",
|
|
597
|
+
ranges: [
|
|
598
|
+
{ label: "Under $25", from: 0, to: 25, count: 15 },
|
|
599
|
+
{ label: "$25-$50", from: 25, to: 50, count: 28 },
|
|
600
|
+
{ label: "$50+", from: 50, to: 999, count: 7 },
|
|
601
|
+
],
|
|
602
|
+
min: 5,
|
|
603
|
+
max: 249,
|
|
604
|
+
},
|
|
605
|
+
},
|
|
606
|
+
};
|
|
607
|
+
};
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
### How controls adapt
|
|
611
|
+
|
|
612
|
+
| Filter type | Without facets | With value facets | With range facets |
|
|
613
|
+
|------------|---------------|-------------------|-------------------|
|
|
614
|
+
| Select | Static options | Options with counts, zero-count dimmed | - |
|
|
615
|
+
| Boolean | All / Yes / No | All / Yes (12) / No (3) | - |
|
|
616
|
+
| Number range | Slider or inputs | Slider (bounds from facet) | Clickable range buckets + slider |
|
|
617
|
+
| Date range | Date picker | Date picker | Clickable range buckets + picker |
|
|
618
|
+
|
|
619
|
+
Facets are optional and backward compatible. Facet data updates on every fetch, creating the
|
|
620
|
+
classic faceted search loop where filtering one dimension updates counts on all others.
|
|
621
|
+
|
|
622
|
+
### Facet types
|
|
623
|
+
|
|
624
|
+
```ts
|
|
625
|
+
// Discrete values - for select, multiselect, boolean filters
|
|
626
|
+
type ValueFacet = {
|
|
627
|
+
type: "values";
|
|
628
|
+
values: { value: string; label?: string; count: number }[];
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
// Bucketed ranges - for numberRange, dateRange filters
|
|
632
|
+
type RangeFacet = {
|
|
633
|
+
type: "ranges";
|
|
634
|
+
ranges: { label: string; from: number | string; to: number | string; count: number }[];
|
|
635
|
+
min?: number | string;
|
|
636
|
+
max?: number | string;
|
|
637
|
+
};
|
|
638
|
+
```
|
|
639
|
+
|
|
497
640
|
## Card composition
|
|
498
641
|
|
|
499
642
|
In card view, each visible column is placed by its `meta.card.role`:
|
|
@@ -515,7 +658,7 @@ role group, columns are ordered by `meta.card.order`.
|
|
|
515
658
|
For full control over card content, use `renderCard`:
|
|
516
659
|
|
|
517
660
|
```tsx
|
|
518
|
-
<
|
|
661
|
+
<DataViewer
|
|
519
662
|
view={view}
|
|
520
663
|
renderCard={({data, selected, toggleSelected}) => (
|
|
521
664
|
<Card withBorder padding="md" onClick={toggleSelected}>
|
|
@@ -530,7 +673,7 @@ For full control over card content, use `renderCard`:
|
|
|
530
673
|
To keep the default composition but wrap it in a custom card shell, use the `Card` slot:
|
|
531
674
|
|
|
532
675
|
```tsx
|
|
533
|
-
<
|
|
676
|
+
<DataViewer
|
|
534
677
|
view={view}
|
|
535
678
|
slots={{
|
|
536
679
|
Card: ({data, selected, children}) => (
|
|
@@ -551,7 +694,7 @@ To keep the default composition but wrap it in a custom card shell, use the `Car
|
|
|
551
694
|
Provide a `BulkActions` slot to add actions when rows are selected:
|
|
552
695
|
|
|
553
696
|
```tsx
|
|
554
|
-
<
|
|
697
|
+
<DataViewer
|
|
555
698
|
view={view}
|
|
556
699
|
slots={{
|
|
557
700
|
BulkActions: (selection) => (
|
|
@@ -578,7 +721,7 @@ The `selection` object provides `count`, `ids` (all selected row IDs across page
|
|
|
578
721
|
Override loading, empty, and error states:
|
|
579
722
|
|
|
580
723
|
```tsx
|
|
581
|
-
<
|
|
724
|
+
<DataViewer
|
|
582
725
|
view={view}
|
|
583
726
|
slots={{
|
|
584
727
|
Empty: () => <Text>No users found.</Text>,
|
|
@@ -594,7 +737,7 @@ Override loading, empty, and error states:
|
|
|
594
737
|
/>
|
|
595
738
|
```
|
|
596
739
|
|
|
597
|
-
A filtered-empty state is handled automatically
|
|
740
|
+
A filtered-empty state is handled automatically. It shows a "clear filters" action so
|
|
598
741
|
users can reset without manually removing each filter.
|
|
599
742
|
|
|
600
743
|
## URL state sync
|
|
@@ -690,7 +833,7 @@ const view = useDataViewFetcher<User>({
|
|
|
690
833
|
responsive: {forceCardsBelow: "sm", lockSwitcherOnMobile: true},
|
|
691
834
|
});
|
|
692
835
|
|
|
693
|
-
<
|
|
836
|
+
<DataViewer view={view} lockSwitcherOnMobile/>;
|
|
694
837
|
```
|
|
695
838
|
|
|
696
839
|
When `forceCardsBelow` is set and the viewport is below that breakpoint:
|
|
@@ -700,23 +843,56 @@ When `forceCardsBelow` is set and the viewport is below that breakpoint:
|
|
|
700
843
|
- The view switcher is disabled (or hidden entirely with `lockSwitcherOnMobile`).
|
|
701
844
|
- Filters always open in a bottom drawer on mobile.
|
|
702
845
|
|
|
846
|
+
## Loading behavior
|
|
847
|
+
|
|
848
|
+
By default, filter controls, sort controls, and column visibility/pinning menus are disabled
|
|
849
|
+
while data is loading. Sort headers in the table also become non-interactive, with a dimmed
|
|
850
|
+
appearance showing the current sort state. The search input stays enabled so users can keep
|
|
851
|
+
typing during debounced search.
|
|
852
|
+
|
|
853
|
+
Opt out per component:
|
|
854
|
+
|
|
855
|
+
```tsx
|
|
856
|
+
<DataTable view={view} disableWhileLoading={false} />
|
|
857
|
+
<DataToolbar view={view} disableWhileLoading={false} />
|
|
858
|
+
```
|
|
859
|
+
|
|
860
|
+
### Animated row transitions
|
|
861
|
+
|
|
862
|
+
Instead of skeleton loading, rows can animate in and out with CSS transitions. New rows
|
|
863
|
+
fade and slide in, removed rows fade out, and unchanged rows stay in place:
|
|
864
|
+
|
|
865
|
+
```tsx
|
|
866
|
+
<DataViewer view={view} animateRows />
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
When `animateRows` is enabled:
|
|
870
|
+
- Previous rows stay visible while new data loads (no skeleton flash).
|
|
871
|
+
- New rows enter with a slide-down fade-in animation (200ms).
|
|
872
|
+
- Removed rows fade out (150ms) before being removed from the DOM.
|
|
873
|
+
- Works in both table and card views.
|
|
874
|
+
|
|
875
|
+
This is opt-in. The default behavior (skeleton loading) is unchanged.
|
|
876
|
+
|
|
703
877
|
## API overview
|
|
704
878
|
|
|
705
879
|
| Export | Purpose |
|
|
706
880
|
|----------------------------------------------------------------------|-----------------------------------------------|
|
|
707
|
-
| `useDataView` | Headless core
|
|
881
|
+
| `useDataView` | Headless core, owns all feature state |
|
|
708
882
|
| `useDataViewFetcher` | Convenience wrapper that manages the fetch |
|
|
709
|
-
| `
|
|
883
|
+
| `DataViewer` (+ `.Toolbar` / `.BulkActions` / `.Body` / `.Pagination`) | Orchestrator + compound parts |
|
|
710
884
|
| `DataTable`, `DataCards` | The two presentations (usable standalone) |
|
|
711
885
|
| `DataToolbar`, `DataPagination`, `DataBulkActions` | Standalone affordances |
|
|
712
886
|
| `FilterControl` | Individual filter control (place anywhere) |
|
|
887
|
+
| `ViewSwitcher` | Table/Cards toggle (customizable labels) |
|
|
713
888
|
| `exportCsv` | Standalone CSV export utility |
|
|
889
|
+
| `col` | Fluent column builder factory |
|
|
714
890
|
| `createColumnHelper`, `composeCardLayout`, `resolveColumnLabel` | Column helpers |
|
|
715
891
|
| `@ethanhann/mantine-dataview/url` | `windowHistoryAdapter` + serializer utilities |
|
|
716
892
|
|
|
717
893
|
### Customization slots
|
|
718
894
|
|
|
719
|
-
Passed via the `slots` prop on `
|
|
895
|
+
Passed via the `slots` prop on `DataViewer` or the presentation components:
|
|
720
896
|
|
|
721
897
|
| Slot | Receives | Purpose |
|
|
722
898
|
|----------------|-------------------------------------|----------------------------|
|
|
@@ -730,20 +906,20 @@ Passed via the `slots` prop on `DataView` or the presentation components:
|
|
|
730
906
|
|
|
731
907
|
## Known issues
|
|
732
908
|
|
|
733
|
-
### `
|
|
909
|
+
### `DataViewer` name shadows the JS global
|
|
734
910
|
|
|
735
|
-
The `
|
|
911
|
+
The `DataViewer` component shares its name with the JavaScript `DataViewer` global (typed arrays).
|
|
736
912
|
Linters like Biome's `noShadowRestrictedNames` will flag the import. Suppress it with:
|
|
737
913
|
|
|
738
914
|
```tsx
|
|
739
915
|
// biome-ignore lint/suspicious/noShadowRestrictedNames: component name
|
|
740
|
-
import {
|
|
916
|
+
import {DataViewer} from "@ethanhann/mantine-dataview";
|
|
741
917
|
```
|
|
742
918
|
|
|
743
919
|
Or import with an alias:
|
|
744
920
|
|
|
745
921
|
```tsx
|
|
746
|
-
import {
|
|
922
|
+
import {DataViewer as MantineDataView} from "@ethanhann/mantine-dataview";
|
|
747
923
|
```
|
|
748
924
|
|
|
749
925
|
## Development
|
|
@@ -20,5 +20,7 @@ export interface DataCardsProps<TData> extends Omit<SimpleGridProps, "children">
|
|
|
20
20
|
enableSelection?: boolean;
|
|
21
21
|
/** Skeleton cards shown while loading. It defaults to the current page size, capped at 6. */
|
|
22
22
|
loadingCardCount?: number;
|
|
23
|
+
/** Animate card enter/exit instead of showing skeletons. Default: false. */
|
|
24
|
+
animateRows?: boolean;
|
|
23
25
|
}
|
|
24
|
-
export declare function DataCards<TData>({ view, slots, renderCard, fallbackRole, enableSelection, loadingCardCount, cols, ...gridProps }: DataCardsProps<TData>): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import('react').ReactPortal | import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react").JSX.Element | null | undefined;
|
|
26
|
+
export declare function DataCards<TData>({ view, slots, renderCard, fallbackRole, enableSelection, loadingCardCount, animateRows, cols, ...gridProps }: DataCardsProps<TData>): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import('react').ReactPortal | import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react").JSX.Element | null | undefined;
|
|
@@ -9,5 +9,9 @@ export interface DataTableProps<TData> extends Omit<TableProps, "data" | "childr
|
|
|
9
9
|
enableSelection?: boolean;
|
|
10
10
|
/** Skeleton rows shown while loading. It defaults to the current page size, capped at 8. */
|
|
11
11
|
loadingRowCount?: number;
|
|
12
|
+
/** Disable sorting interactions while data is loading. Default: true. */
|
|
13
|
+
disableWhileLoading?: boolean;
|
|
14
|
+
/** Animate row enter/exit instead of showing skeletons. Default: false. */
|
|
15
|
+
animateRows?: boolean;
|
|
12
16
|
}
|
|
13
|
-
export declare function DataTable<TData>({ view, slots, enableSelection, loadingRowCount, ...tableProps }: DataTableProps<TData>): import("react").JSX.Element;
|
|
17
|
+
export declare function DataTable<TData>({ view, slots, enableSelection, loadingRowCount, disableWhileLoading, animateRows, ...tableProps }: DataTableProps<TData>): import("react").JSX.Element;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GroupProps } from '@mantine/core';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
2
3
|
import { UseDataViewReturn } from '../../types/options';
|
|
3
4
|
export interface DataToolbarProps<TData> extends Omit<GroupProps, "children"> {
|
|
4
5
|
/** The `useDataView` instance to drive. */
|
|
@@ -12,5 +13,11 @@ export interface DataToolbarProps<TData> extends Omit<GroupProps, "children"> {
|
|
|
12
13
|
showSort?: boolean;
|
|
13
14
|
showVisibility?: boolean;
|
|
14
15
|
showViewSwitcher?: boolean;
|
|
16
|
+
/** Disable search, filter, and sort controls while data is loading. Default: true. */
|
|
17
|
+
disableWhileLoading?: boolean;
|
|
18
|
+
/** Content injected at the start of the left control group (before search). */
|
|
19
|
+
leftSection?: ReactNode;
|
|
20
|
+
/** Content injected at the end of the right control group (after view switcher). */
|
|
21
|
+
rightSection?: ReactNode;
|
|
15
22
|
}
|
|
16
|
-
export declare function DataToolbar<TData>({ view, searchPlaceholder, filterInlineThreshold, lockSwitcherOnMobile, showSearch, showFilters, showSort, showVisibility, showViewSwitcher, ...groupProps }: DataToolbarProps<TData>): import("react").JSX.Element;
|
|
23
|
+
export declare function DataToolbar<TData>({ view, searchPlaceholder, filterInlineThreshold, lockSwitcherOnMobile, showSearch, showFilters, showSort, showVisibility, showViewSwitcher, disableWhileLoading, leftSection, rightSection, ...groupProps }: DataToolbarProps<TData>): import("react").JSX.Element;
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
1
2
|
import { UseDataViewReturn } from '../../types/options';
|
|
2
|
-
export
|
|
3
|
+
export interface ViewSwitcherProps<TData> {
|
|
3
4
|
view: UseDataViewReturn<TData>;
|
|
4
5
|
lockSwitcherOnMobile?: boolean;
|
|
5
|
-
|
|
6
|
+
/** Custom label for the table option. Default: "Table". */
|
|
7
|
+
tableLabel?: ReactNode;
|
|
8
|
+
/** Custom label for the cards option. Default: "Cards". */
|
|
9
|
+
cardsLabel?: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
export declare function ViewSwitcher<TData>({ view, lockSwitcherOnMobile, tableLabel, cardsLabel, }: ViewSwitcherProps<TData>): import("react").JSX.Element | null;
|
|
@@ -7,30 +7,32 @@ import { DataPaginationProps } from '../DataPagination';
|
|
|
7
7
|
import { DataTableProps } from '../DataTable';
|
|
8
8
|
import { DataToolbarProps } from '../DataToolbar';
|
|
9
9
|
import { DataViewSlots } from '../types';
|
|
10
|
-
export interface
|
|
10
|
+
export interface DataViewerProps<TData> extends Omit<StackProps, "children"> {
|
|
11
11
|
/** The `useDataView` instance to project. */
|
|
12
12
|
view: UseDataViewReturn<TData>;
|
|
13
13
|
slots?: DataViewSlots<TData>;
|
|
14
14
|
renderCard?: DataCardsProps<TData>["renderCard"];
|
|
15
15
|
fallbackRole?: DataCardsProps<TData>["fallbackRole"];
|
|
16
16
|
lockSwitcherOnMobile?: boolean;
|
|
17
|
+
/** Animate row enter/exit instead of showing skeletons. Default: false. */
|
|
18
|
+
animateRows?: boolean;
|
|
17
19
|
/** Custom composition. It defaults to Toolbar, BulkActions, Body, and Pagination. */
|
|
18
20
|
children?: ReactNode;
|
|
19
21
|
}
|
|
20
|
-
export declare function
|
|
21
|
-
export declare namespace
|
|
22
|
+
export declare function DataViewer<TData>({ view, slots, renderCard, fallbackRole, lockSwitcherOnMobile, animateRows, children, ...stackProps }: DataViewerProps<TData>): import("react").JSX.Element;
|
|
23
|
+
export declare namespace DataViewer {
|
|
22
24
|
var Toolbar: typeof DataViewToolbar;
|
|
23
25
|
var BulkActions: typeof DataViewBulkActions;
|
|
24
26
|
var Body: typeof DataViewBody;
|
|
25
27
|
var Pagination: typeof DataViewPagination;
|
|
26
28
|
}
|
|
27
|
-
export type
|
|
28
|
-
declare function DataViewToolbar<TData>(props:
|
|
29
|
-
export interface
|
|
29
|
+
export type DataViewerToolbarProps<TData> = Omit<DataToolbarProps<TData>, "view">;
|
|
30
|
+
declare function DataViewToolbar<TData>(props: DataViewerToolbarProps<TData>): import("react").JSX.Element;
|
|
31
|
+
export interface DataViewerBodyProps<TData> {
|
|
30
32
|
tableProps?: Omit<DataTableProps<TData>, "view" | "slots">;
|
|
31
33
|
cardsProps?: Omit<DataCardsProps<TData>, "view" | "slots" | "renderCard" | "fallbackRole">;
|
|
32
34
|
}
|
|
33
|
-
declare function DataViewBody<TData>({ tableProps, cardsProps, }:
|
|
35
|
+
declare function DataViewBody<TData>({ tableProps, cardsProps, }: DataViewerBodyProps<TData>): import("react").JSX.Element;
|
|
34
36
|
declare function DataViewPagination<TData>(props: Omit<DataPaginationProps<TData>, "view">): import("react").JSX.Element;
|
|
35
37
|
declare function DataViewBulkActions<TData>(props: Omit<DataBulkActionsProps<TData>, "view" | "slots">): import("react").JSX.Element;
|
|
36
38
|
export {};
|
|
@@ -8,6 +8,7 @@ export interface DataViewContextValue<TData> {
|
|
|
8
8
|
renderCard?: DataCardsProps<TData>["renderCard"];
|
|
9
9
|
fallbackRole?: ComposeCardOptions["fallbackRole"];
|
|
10
10
|
lockSwitcherOnMobile?: boolean;
|
|
11
|
+
animateRows?: boolean;
|
|
11
12
|
}
|
|
12
13
|
export declare const DataViewProvider: import('react').Provider<DataViewContextValue<unknown> | null>;
|
|
13
14
|
export declare function useDataViewContext<TData>(): DataViewContextValue<TData>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Row } from '@tanstack/react-table';
|
|
2
|
+
export interface RowTransitionResult<TData> {
|
|
3
|
+
rows: Row<TData>[];
|
|
4
|
+
entering: Set<string>;
|
|
5
|
+
/** Increments each time the row set or order changes. Use as a CSS animation key. */
|
|
6
|
+
generation: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function useRowTransition<TData>(currentRows: Row<TData>[], enabled: boolean): RowTransitionResult<TData>;
|