@snowpact/react-tanstack-query-table 1.3.0 → 1.4.1
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 +195 -225
- package/dist/index.cjs +14 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -14
- package/dist/index.js +1999 -1981
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,55 +2,99 @@
|
|
|
2
2
|
|
|
3
3
|
Ultra-light, registry-based data table for React + TanStack Table + TanStack Query.
|
|
4
4
|
|
|
5
|
+
**[Live Demo](https://snowpact.github.io/react-tanstack-query-table/)**
|
|
6
|
+
|
|
5
7
|
## Features
|
|
6
8
|
|
|
7
|
-
- **Zero heavy dependencies**:
|
|
9
|
+
- **Zero heavy dependencies**: Only `@tanstack/react-query` and `@tanstack/react-table` as peer dependencies
|
|
8
10
|
- **Registry-based**: Inject your own i18n, Link component, confirmation dialogs
|
|
9
11
|
- **TypeScript**: Full type support with generics
|
|
10
12
|
- **Two modes**: Client-side and Server-side pagination/filtering/sorting
|
|
11
|
-
- **Customizable**: Override styles via registry
|
|
13
|
+
- **Customizable**: Override styles via CSS variables or registry
|
|
14
|
+
|
|
15
|
+
## Quick Setup
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
### 1. Install
|
|
14
18
|
|
|
15
19
|
```bash
|
|
20
|
+
npm install @tanstack/react-query @tanstack/react-table
|
|
16
21
|
npm install @snowpact/react-tanstack-query-table
|
|
17
|
-
# or
|
|
18
|
-
pnpm add @snowpact/react-tanstack-query-table
|
|
19
22
|
```
|
|
20
23
|
|
|
21
|
-
###
|
|
24
|
+
### 2. Import styles
|
|
22
25
|
|
|
23
|
-
```
|
|
24
|
-
|
|
26
|
+
```tsx
|
|
27
|
+
// In your app entry point (main.tsx or App.tsx)
|
|
28
|
+
import '@snowpact/react-tanstack-query-table/styles.css';
|
|
25
29
|
```
|
|
26
30
|
|
|
27
|
-
###
|
|
31
|
+
### 3. Setup once
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
```tsx
|
|
34
|
+
// In your app entry point (main.tsx or App.tsx)
|
|
35
|
+
import { setupSnowTable } from '@snowpact/react-tanstack-query-table';
|
|
36
|
+
import { Link } from 'react-router-dom';
|
|
37
|
+
|
|
38
|
+
// Your translation function (or just return the key)
|
|
39
|
+
const t = (key: string) => translations[key] || key;
|
|
40
|
+
|
|
41
|
+
setupSnowTable({
|
|
42
|
+
t,
|
|
43
|
+
LinkComponent: Link,
|
|
44
|
+
confirm: ({ title }) => window.confirm(title),
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 4. Use the table
|
|
30
49
|
|
|
31
50
|
```tsx
|
|
32
|
-
import '@snowpact/react-tanstack-query-table
|
|
51
|
+
import { SnowClientDataTable, SnowColumnConfig } from '@snowpact/react-tanstack-query-table';
|
|
52
|
+
|
|
53
|
+
type User = { id: string; name: string; email: string; status: string };
|
|
54
|
+
|
|
55
|
+
const columns: SnowColumnConfig<User>[] = [
|
|
56
|
+
{ key: 'name', label: 'Name' },
|
|
57
|
+
{ key: 'email', label: 'Email' },
|
|
58
|
+
{ key: 'status', label: 'Status', render: (item) => <Badge>{item.status}</Badge> },
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
<SnowClientDataTable
|
|
62
|
+
queryKey={['users']}
|
|
63
|
+
fetchAllItemsEndpoint={() => fetchUsers()}
|
|
64
|
+
columnConfig={columns}
|
|
65
|
+
enableGlobalSearch
|
|
66
|
+
enablePagination
|
|
67
|
+
enableSorting
|
|
68
|
+
enableColumnConfiguration
|
|
69
|
+
defaultPageSize={20}
|
|
70
|
+
defaultSortBy="name"
|
|
71
|
+
defaultSortOrder="asc"
|
|
72
|
+
persistState
|
|
73
|
+
/>
|
|
33
74
|
```
|
|
34
75
|
|
|
35
|
-
|
|
76
|
+
That's it! You have a working data table.
|
|
77
|
+
|
|
78
|
+
---
|
|
36
79
|
|
|
37
|
-
|
|
80
|
+
## Advanced Configuration
|
|
81
|
+
|
|
82
|
+
### Theme Customization
|
|
83
|
+
|
|
84
|
+
Override CSS variables to match your design:
|
|
38
85
|
|
|
39
86
|
```css
|
|
40
87
|
:root {
|
|
41
|
-
--snow-background: #ffffff;
|
|
42
|
-
--snow-foreground: #0a0a0a;
|
|
43
|
-
--snow-secondary: #f5f5f5;
|
|
44
|
-
--snow-secondary-foreground: #737373;
|
|
45
|
-
--snow-border: #d4d4d4;
|
|
46
|
-
--snow-ring: #a3a3a3;
|
|
47
|
-
--snow-radius: 0.375rem;
|
|
88
|
+
--snow-background: #ffffff;
|
|
89
|
+
--snow-foreground: #0a0a0a;
|
|
90
|
+
--snow-secondary: #f5f5f5;
|
|
91
|
+
--snow-secondary-foreground: #737373;
|
|
92
|
+
--snow-border: #d4d4d4;
|
|
93
|
+
--snow-ring: #a3a3a3;
|
|
94
|
+
--snow-radius: 0.375rem;
|
|
48
95
|
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
**Dark mode example:**
|
|
52
96
|
|
|
53
|
-
|
|
97
|
+
/* Dark mode */
|
|
54
98
|
.dark {
|
|
55
99
|
--snow-background: #1a1a2e;
|
|
56
100
|
--snow-foreground: #eaeaea;
|
|
@@ -61,73 +105,102 @@ You can customize the library appearance by overriding CSS variables:
|
|
|
61
105
|
}
|
|
62
106
|
```
|
|
63
107
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
### 1. Setup (once in your app)
|
|
108
|
+
### Setup with i18n (react-i18next)
|
|
67
109
|
|
|
68
110
|
```tsx
|
|
69
|
-
// Import styles first
|
|
70
|
-
import '@snowpact/react-tanstack-query-table/styles.css';
|
|
71
|
-
|
|
72
|
-
import { setupSnowTable } from '@snowpact/react-tanstack-query-table';
|
|
73
111
|
import { useTranslation } from 'react-i18next';
|
|
74
|
-
|
|
75
|
-
|
|
112
|
+
|
|
113
|
+
// Get t function at module level or use a hook wrapper
|
|
114
|
+
const { t } = i18n;
|
|
76
115
|
|
|
77
116
|
setupSnowTable({
|
|
78
|
-
|
|
117
|
+
t: (key) => t(key),
|
|
79
118
|
LinkComponent: Link,
|
|
80
|
-
|
|
119
|
+
confirm: ({ title, content }) => {
|
|
120
|
+
const message = typeof content === 'string' ? `${title}\n\n${content}` : title;
|
|
121
|
+
return window.confirm(message);
|
|
122
|
+
},
|
|
81
123
|
});
|
|
82
124
|
```
|
|
83
125
|
|
|
84
|
-
|
|
126
|
+
The `t` function is automatically called with:
|
|
127
|
+
- All column `key` values from your `columnConfig` (e.g., `t('name')`, `t('email')`, `t('status')`)
|
|
128
|
+
- Internal UI keys:
|
|
129
|
+
- `dataTable.search` - Search placeholder
|
|
130
|
+
- `dataTable.elements` - "elements" label
|
|
131
|
+
- `dataTable.searchEmpty` - Empty state text
|
|
132
|
+
- `dataTable.resetFilters` - Reset button tooltip
|
|
133
|
+
- `dataTable.columns` - Columns button label
|
|
85
134
|
|
|
86
|
-
###
|
|
135
|
+
### Setup with custom confirm dialog
|
|
87
136
|
|
|
88
137
|
```tsx
|
|
89
|
-
import {
|
|
90
|
-
import { Edit, Trash } from 'lucide-react';
|
|
138
|
+
import { useConfirmDialog } from './your-confirm-hook';
|
|
91
139
|
|
|
92
|
-
|
|
140
|
+
// If you have a hook-based confirm dialog
|
|
141
|
+
const confirmDialog = useConfirmDialog();
|
|
93
142
|
|
|
94
|
-
|
|
143
|
+
setupSnowTable({
|
|
144
|
+
t,
|
|
145
|
+
LinkComponent: Link,
|
|
146
|
+
confirm: async ({ title, content, confirmText, cancelText }) => {
|
|
147
|
+
return confirmDialog.open({
|
|
148
|
+
title,
|
|
149
|
+
description: content,
|
|
150
|
+
confirmLabel: confirmText,
|
|
151
|
+
cancelLabel: cancelText,
|
|
152
|
+
});
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
```
|
|
95
156
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
157
|
+
### Override component styles (rare)
|
|
158
|
+
|
|
159
|
+
For deep customization, override internal Tailwind classes:
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
setupSnowTable({
|
|
163
|
+
t,
|
|
164
|
+
LinkComponent: Link,
|
|
165
|
+
confirm: ({ title }) => window.confirm(title),
|
|
166
|
+
styles: {
|
|
167
|
+
button: {
|
|
168
|
+
visual: 'rounded-full bg-primary text-primary-foreground',
|
|
169
|
+
hover: 'hover:bg-primary/90',
|
|
170
|
+
},
|
|
171
|
+
table: {
|
|
172
|
+
header: 'bg-slate-100 dark:bg-slate-800',
|
|
173
|
+
rowHover: 'hover:bg-slate-50',
|
|
174
|
+
},
|
|
175
|
+
input: 'rounded-full border-2 border-primary',
|
|
176
|
+
},
|
|
177
|
+
});
|
|
107
178
|
```
|
|
108
179
|
|
|
180
|
+
---
|
|
181
|
+
|
|
109
182
|
## Client vs Server Mode
|
|
110
183
|
|
|
111
|
-
| Mode | Component
|
|
112
|
-
| ---------- |
|
|
113
|
-
| **Client** | `SnowClientDataTable` | < 5,000 items | All data loaded, filtered/sorted locally
|
|
114
|
-
| **Server** | `SnowServerDataTable` | > 5,000 items |
|
|
184
|
+
| Mode | Component | Use case | Data handling |
|
|
185
|
+
| ---------- | --------------------- | ------------- | ---------------------------------------- |
|
|
186
|
+
| **Client** | `SnowClientDataTable` | < 5,000 items | All data loaded, filtered/sorted locally |
|
|
187
|
+
| **Server** | `SnowServerDataTable` | > 5,000 items | Server handles pagination/filtering |
|
|
115
188
|
|
|
116
189
|
### SnowClientDataTable
|
|
117
190
|
|
|
118
|
-
|
|
191
|
+
Fetches all data once, handles everything in the browser:
|
|
119
192
|
|
|
120
193
|
```tsx
|
|
121
194
|
<SnowClientDataTable
|
|
122
195
|
queryKey={['users']}
|
|
123
|
-
fetchAllItemsEndpoint={() => api.getUsers()}
|
|
196
|
+
fetchAllItemsEndpoint={() => api.getUsers()}
|
|
124
197
|
columnConfig={columns}
|
|
125
198
|
/>
|
|
126
199
|
```
|
|
127
200
|
|
|
128
201
|
### SnowServerDataTable
|
|
129
202
|
|
|
130
|
-
|
|
203
|
+
Server handles pagination, search, filtering, and sorting:
|
|
131
204
|
|
|
132
205
|
```tsx
|
|
133
206
|
import { SnowServerDataTable, ServerFetchParams } from '@snowpact/react-tanstack-query-table';
|
|
@@ -141,21 +214,25 @@ const fetchUsers = async (params: ServerFetchParams) => {
|
|
|
141
214
|
};
|
|
142
215
|
};
|
|
143
216
|
|
|
144
|
-
<SnowServerDataTable
|
|
217
|
+
<SnowServerDataTable
|
|
218
|
+
queryKey={['users']}
|
|
219
|
+
fetchServerEndpoint={fetchUsers}
|
|
220
|
+
columnConfig={columns}
|
|
221
|
+
/>
|
|
145
222
|
```
|
|
146
223
|
|
|
224
|
+
---
|
|
225
|
+
|
|
147
226
|
## Actions
|
|
148
227
|
|
|
149
|
-
Actions appear as buttons in each row
|
|
228
|
+
Actions appear as buttons in each row:
|
|
150
229
|
|
|
151
230
|
### Click Action
|
|
152
231
|
|
|
153
|
-
Simple callback when clicked.
|
|
154
|
-
|
|
155
232
|
```tsx
|
|
156
233
|
{
|
|
157
234
|
type: 'click',
|
|
158
|
-
icon:
|
|
235
|
+
icon: EditIcon,
|
|
159
236
|
label: 'Edit',
|
|
160
237
|
onClick: (item) => openEditModal(item),
|
|
161
238
|
}
|
|
@@ -163,12 +240,10 @@ Simple callback when clicked.
|
|
|
163
240
|
|
|
164
241
|
### Link Action
|
|
165
242
|
|
|
166
|
-
Navigates to a URL. Uses your registered `LinkComponent`.
|
|
167
|
-
|
|
168
243
|
```tsx
|
|
169
244
|
{
|
|
170
245
|
type: 'link',
|
|
171
|
-
icon:
|
|
246
|
+
icon: EyeIcon,
|
|
172
247
|
label: 'View',
|
|
173
248
|
href: (item) => `/users/${item.id}`,
|
|
174
249
|
external: false, // true for target="_blank"
|
|
@@ -177,123 +252,57 @@ Navigates to a URL. Uses your registered `LinkComponent`.
|
|
|
177
252
|
|
|
178
253
|
### Endpoint Action
|
|
179
254
|
|
|
180
|
-
Calls an async endpoint (API mutation). Integrates with React Query invalidation.
|
|
181
|
-
|
|
182
|
-
```tsx
|
|
183
|
-
{
|
|
184
|
-
type: 'endpoint',
|
|
185
|
-
icon: Trash,
|
|
186
|
-
label: 'Delete',
|
|
187
|
-
endpoint: (item) => api.deleteUser(item.id),
|
|
188
|
-
onSuccess: () => queryClient.invalidateQueries(['users']),
|
|
189
|
-
onError: (error) => toast.error(error.message),
|
|
190
|
-
}
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
### Confirmation Dialog
|
|
194
|
-
|
|
195
|
-
Any action can require confirmation before executing:
|
|
196
|
-
|
|
197
255
|
```tsx
|
|
198
256
|
{
|
|
199
257
|
type: 'endpoint',
|
|
200
|
-
icon:
|
|
258
|
+
icon: TrashIcon,
|
|
201
259
|
label: 'Delete',
|
|
202
260
|
variant: 'danger',
|
|
203
261
|
endpoint: (item) => api.deleteUser(item.id),
|
|
262
|
+
onSuccess: () => queryClient.invalidateQueries(['users']),
|
|
204
263
|
confirm: {
|
|
205
264
|
title: 'Delete user?',
|
|
206
265
|
content: 'This action cannot be undone.',
|
|
207
|
-
confirmText: 'Delete',
|
|
208
|
-
cancelText: 'Cancel',
|
|
209
266
|
},
|
|
210
267
|
}
|
|
211
268
|
```
|
|
212
269
|
|
|
213
|
-
For forms inside confirm dialogs, use a function to access the `close` helper:
|
|
214
|
-
|
|
215
|
-
```tsx
|
|
216
|
-
{
|
|
217
|
-
type: 'click',
|
|
218
|
-
icon: Edit,
|
|
219
|
-
label: 'Change Status',
|
|
220
|
-
onClick: () => {},
|
|
221
|
-
confirm: {
|
|
222
|
-
title: 'Change Status',
|
|
223
|
-
hideButtons: true, // Form handles its own buttons
|
|
224
|
-
content: ({ close }) => (
|
|
225
|
-
<StatusForm
|
|
226
|
-
onSuccess={() => {
|
|
227
|
-
queryClient.invalidateQueries(['users']);
|
|
228
|
-
close();
|
|
229
|
-
}}
|
|
230
|
-
/>
|
|
231
|
-
),
|
|
232
|
-
},
|
|
233
|
-
}
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
### Action Options
|
|
237
|
-
|
|
238
|
-
| Option | Type | Description |
|
|
239
|
-
| ----------- | ----------------------------------------------------------- | ---------------------------------------- |
|
|
240
|
-
| `icon` | `ComponentType<SVGProps>` | Icon component (lucide-react or any SVG) |
|
|
241
|
-
| `label` | `string` | Button label (used for tooltip) |
|
|
242
|
-
| `variant` | `'default' \| 'danger' \| 'warning' \| 'info' \| 'success'` | Button color variant |
|
|
243
|
-
| `display` | `'button' \| 'dropdown'` | Show as button or in dropdown menu |
|
|
244
|
-
| `hidden` | `boolean` | Conditionally hide the action |
|
|
245
|
-
| `disabled` | `boolean` | Disable the action |
|
|
246
|
-
| `showLabel` | `boolean` | Show label text next to icon |
|
|
247
|
-
|
|
248
270
|
### Dynamic Actions
|
|
249
271
|
|
|
250
|
-
Actions can be functions that return the action config, allowing per-row customization:
|
|
251
|
-
|
|
252
272
|
```tsx
|
|
253
273
|
actions={[
|
|
254
274
|
(item) => ({
|
|
255
275
|
type: 'click',
|
|
256
|
-
icon: item.isActive ?
|
|
276
|
+
icon: item.isActive ? PauseIcon : PlayIcon,
|
|
257
277
|
label: item.isActive ? 'Deactivate' : 'Activate',
|
|
258
278
|
onClick: () => toggleStatus(item),
|
|
259
|
-
hidden: item.role === 'admin',
|
|
279
|
+
hidden: item.role === 'admin',
|
|
260
280
|
}),
|
|
261
281
|
]}
|
|
262
282
|
```
|
|
263
283
|
|
|
264
|
-
|
|
284
|
+
---
|
|
265
285
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
Enable fuzzy search across all columns:
|
|
269
|
-
|
|
270
|
-
```tsx
|
|
271
|
-
<SnowClientDataTable enableGlobalSearch texts={{ searchPlaceholder: 'Search users...' }} />
|
|
272
|
-
```
|
|
286
|
+
## Filters
|
|
273
287
|
|
|
274
|
-
|
|
288
|
+
### Global Search
|
|
275
289
|
|
|
276
290
|
```tsx
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
render: item => `${item.firstName} ${item.lastName}`,
|
|
282
|
-
searchableValue: item => `${item.firstName} ${item.lastName}`,
|
|
283
|
-
},
|
|
284
|
-
];
|
|
291
|
+
<SnowClientDataTable
|
|
292
|
+
enableGlobalSearch
|
|
293
|
+
texts={{ searchPlaceholder: 'Search users...' }}
|
|
294
|
+
/>
|
|
285
295
|
```
|
|
286
296
|
|
|
287
297
|
### Column Filters
|
|
288
298
|
|
|
289
|
-
Multi-select dropdown filters:
|
|
290
|
-
|
|
291
299
|
```tsx
|
|
292
300
|
<SnowClientDataTable
|
|
293
301
|
filters={[
|
|
294
302
|
{
|
|
295
303
|
key: 'status',
|
|
296
304
|
label: 'Status',
|
|
305
|
+
multipleSelection: true, // Allow multiple values
|
|
297
306
|
options: [
|
|
298
307
|
{ value: 'active', label: 'Active' },
|
|
299
308
|
{ value: 'inactive', label: 'Inactive' },
|
|
@@ -313,14 +322,11 @@ Multi-select dropdown filters:
|
|
|
313
322
|
|
|
314
323
|
### Prefilters (Tabs)
|
|
315
324
|
|
|
316
|
-
Quick segmentation via tabs:
|
|
317
|
-
|
|
318
325
|
```tsx
|
|
319
326
|
<SnowClientDataTable
|
|
320
327
|
prefilters={[
|
|
321
328
|
{ id: 'all', label: 'All' },
|
|
322
329
|
{ id: 'active', label: 'Active' },
|
|
323
|
-
{ id: 'archived', label: 'Archived' },
|
|
324
330
|
]}
|
|
325
331
|
prefilterFn={(item, prefilterId) => {
|
|
326
332
|
if (prefilterId === 'all') return true;
|
|
@@ -329,72 +335,37 @@ Quick segmentation via tabs:
|
|
|
329
335
|
/>
|
|
330
336
|
```
|
|
331
337
|
|
|
332
|
-
|
|
338
|
+
---
|
|
333
339
|
|
|
334
|
-
##
|
|
340
|
+
## Other Features
|
|
335
341
|
|
|
336
|
-
###
|
|
337
|
-
|
|
338
|
-
Users can show/hide columns via a settings button. Configuration is saved in cookies.
|
|
342
|
+
### URL State Persistence
|
|
339
343
|
|
|
340
344
|
```tsx
|
|
341
|
-
<SnowClientDataTable
|
|
342
|
-
enableColumnConfiguration
|
|
343
|
-
columnConfig={[
|
|
344
|
-
{ key: 'name' }, // Always visible
|
|
345
|
-
{ key: 'email' },
|
|
346
|
-
{ key: 'details', meta: { defaultHidden: true } }, // Hidden by default
|
|
347
|
-
]}
|
|
348
|
-
/>
|
|
345
|
+
<SnowClientDataTable persistState />
|
|
349
346
|
```
|
|
350
347
|
|
|
351
|
-
|
|
348
|
+
Saves pagination, search, filters, and sorting in URL params.
|
|
352
349
|
|
|
353
|
-
|
|
350
|
+
### Column Configuration
|
|
354
351
|
|
|
355
352
|
```tsx
|
|
356
353
|
<SnowClientDataTable
|
|
357
|
-
|
|
354
|
+
enableColumnConfiguration
|
|
355
|
+
columnConfig={[
|
|
356
|
+
{ key: 'name' },
|
|
357
|
+
{ key: 'details', meta: { defaultHidden: true } },
|
|
358
|
+
]}
|
|
358
359
|
/>
|
|
359
360
|
```
|
|
360
361
|
|
|
361
|
-
URL params used:
|
|
362
|
-
|
|
363
|
-
- `dt_page`, `dt_pageSize` - Pagination
|
|
364
|
-
- `dt_search` - Search query
|
|
365
|
-
- `dt_prefilter` - Active prefilter
|
|
366
|
-
- `dt_filters` - Column filters
|
|
367
|
-
- `dt_sortBy`, `dt_sortDesc` - Sorting
|
|
368
|
-
|
|
369
|
-
### Column Meta Properties
|
|
370
|
-
|
|
371
|
-
```tsx
|
|
372
|
-
{
|
|
373
|
-
key: 'actions',
|
|
374
|
-
meta: {
|
|
375
|
-
width: '100px', // Fixed width
|
|
376
|
-
minWidth: '80px', // Minimum width
|
|
377
|
-
center: true, // Center content
|
|
378
|
-
defaultHidden: true, // Hidden by default
|
|
379
|
-
disableColumnClick: true, // Disable row click for this column
|
|
380
|
-
},
|
|
381
|
-
}
|
|
382
|
-
```
|
|
383
|
-
|
|
384
362
|
### Sorting
|
|
385
363
|
|
|
386
|
-
```tsx
|
|
387
|
-
<SnowClientDataTable enableSorting defaultSortBy="createdAt" defaultSortOrder="desc" />
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
### Pagination
|
|
391
|
-
|
|
392
364
|
```tsx
|
|
393
365
|
<SnowClientDataTable
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
enableElementLabel // Show element label
|
|
366
|
+
enableSorting
|
|
367
|
+
defaultSortBy="createdAt"
|
|
368
|
+
defaultSortOrder="desc"
|
|
398
369
|
/>
|
|
399
370
|
```
|
|
400
371
|
|
|
@@ -402,35 +373,35 @@ URL params used:
|
|
|
402
373
|
|
|
403
374
|
```tsx
|
|
404
375
|
<SnowClientDataTable
|
|
405
|
-
onRowClick={item => navigate(`/users/${item.id}`)}
|
|
406
|
-
activeRowId={selectedUserId}
|
|
376
|
+
onRowClick={(item) => navigate(`/users/${item.id}`)}
|
|
377
|
+
activeRowId={selectedUserId}
|
|
407
378
|
/>
|
|
408
379
|
```
|
|
409
380
|
|
|
410
|
-
### Custom
|
|
411
|
-
|
|
412
|
-
Override default Tailwind classes via the registry:
|
|
381
|
+
### Custom Column Rendering
|
|
413
382
|
|
|
414
383
|
```tsx
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
hover: 'hover:bg-blue-600',
|
|
426
|
-
},
|
|
384
|
+
const columns: SnowColumnConfig<User>[] = [
|
|
385
|
+
{ key: 'name', label: 'Name' },
|
|
386
|
+
{
|
|
387
|
+
key: 'status',
|
|
388
|
+
label: 'Status',
|
|
389
|
+
render: (item) => (
|
|
390
|
+
<span className={item.status === 'active' ? 'text-green-500' : 'text-red-500'}>
|
|
391
|
+
{item.status}
|
|
392
|
+
</span>
|
|
393
|
+
),
|
|
427
394
|
},
|
|
428
|
-
|
|
395
|
+
{
|
|
396
|
+
key: '_extra_fullName', // Use _extra_ prefix for computed columns
|
|
397
|
+
label: 'Full Name',
|
|
398
|
+
render: (item) => `${item.firstName} ${item.lastName}`,
|
|
399
|
+
searchableValue: (item) => `${item.firstName} ${item.lastName}`,
|
|
400
|
+
},
|
|
401
|
+
];
|
|
429
402
|
```
|
|
430
403
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
Action buttons automatically display tooltips on hover. The tooltip uses your theme's CSS variables (`--snow-foreground`, `--snow-background`, `--snow-radius`) for consistent styling.
|
|
404
|
+
---
|
|
434
405
|
|
|
435
406
|
## API Reference
|
|
436
407
|
|
|
@@ -441,23 +412,22 @@ Action buttons automatically display tooltips on hover. The tooltip uses your th
|
|
|
441
412
|
| `queryKey` | `string[]` | Required | React Query cache key |
|
|
442
413
|
| `fetchAllItemsEndpoint` | `() => Promise<T[]>` | Required | Data fetching function |
|
|
443
414
|
| `columnConfig` | `SnowColumnConfig<T>[]` | Required | Column definitions |
|
|
444
|
-
| `actions` | `TableAction<T>[]` |
|
|
445
|
-
| `filters` | `FilterConfig<T>[]` |
|
|
446
|
-
| `prefilters` | `PreFilter[]` |
|
|
415
|
+
| `actions` | `TableAction<T>[]` | - | Row actions |
|
|
416
|
+
| `filters` | `FilterConfig<T>[]` | - | Column filters |
|
|
417
|
+
| `prefilters` | `PreFilter[]` | - | Tab filters |
|
|
447
418
|
| `prefilterFn` | `(item, id) => boolean` | - | Client-side prefilter logic |
|
|
448
419
|
| `persistState` | `boolean` | `false` | Persist state in URL |
|
|
449
420
|
| `enableGlobalSearch` | `boolean` | `false` | Enable search bar |
|
|
450
|
-
| `enablePagination` | `boolean` | `
|
|
451
|
-
| `enableSorting` | `boolean` | `
|
|
421
|
+
| `enablePagination` | `boolean` | `true` | Enable pagination |
|
|
422
|
+
| `enableSorting` | `boolean` | `true` | Enable column sorting |
|
|
452
423
|
| `enableColumnConfiguration` | `boolean` | `false` | Enable column visibility toggle |
|
|
453
|
-
| `enableResetFilters` | `boolean` | `false` | Show reset filters button |
|
|
454
424
|
| `defaultPageSize` | `number` | `10` | Initial page size |
|
|
455
425
|
| `defaultSortBy` | `string` | - | Initial sort column |
|
|
456
426
|
| `defaultSortOrder` | `'asc' \| 'desc'` | `'asc'` | Initial sort direction |
|
|
457
427
|
|
|
458
428
|
### SnowServerDataTable Props
|
|
459
429
|
|
|
460
|
-
Same as `SnowClientDataTable`,
|
|
430
|
+
Same as `SnowClientDataTable`, plus:
|
|
461
431
|
|
|
462
432
|
| Prop | Type | Description |
|
|
463
433
|
| --------------------- | -------------------------------------------------------------------- | ------------------------ |
|