@sio-group/ui-datatable 0.1.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/CHANGELOG.md +16 -0
- package/README.md +429 -0
- package/dist/index.cjs +647 -0
- package/dist/index.d.cts +83 -0
- package/dist/index.d.ts +83 -0
- package/dist/index.js +620 -0
- package/dist/styles/index.css +154 -0
- package/dist/styles/index.css.map +1 -0
- package/package.json +44 -0
- package/src/assets/scss/index.scss +170 -0
- package/src/assets/scss/tokens/_color.scss +19 -0
- package/src/assets/scss/tokens/_datatable.scss +10 -0
- package/src/components/ActionCell.tsx +88 -0
- package/src/components/DataTable.tsx +85 -0
- package/src/components/DataTableBody.tsx +34 -0
- package/src/components/DataTableControls.tsx +35 -0
- package/src/components/DataTableHeader.tsx +59 -0
- package/src/components/DefaultSortIcon.tsx +13 -0
- package/src/components/TableCell.tsx +17 -0
- package/src/components/cell-types/BooleanCell.tsx +29 -0
- package/src/components/cell-types/DateCell.tsx +28 -0
- package/src/components/cell-types/EmptyCell.tsx +3 -0
- package/src/components/cell-types/InlineInputCell.tsx +129 -0
- package/src/hooks/useDataTable.ts +113 -0
- package/src/index.ts +14 -0
- package/src/types/action-cell-props.d.ts +9 -0
- package/src/types/action-menu.d.ts +15 -0
- package/src/types/column.d.ts +10 -0
- package/src/types/data-table-body-props.d.ts +16 -0
- package/src/types/data-table-header-props.d.ts +11 -0
- package/src/types/data-table-props.d.ts +32 -0
- package/src/types/entity.d.ts +4 -0
- package/src/types/form-field.d.ts +8 -0
- package/src/types/index.ts +11 -0
- package/src/types/pagination-meta.d.ts +7 -0
- package/src/types/sort-state.d.ts +6 -0
- package/src/types/table-cell-props.d.ts +9 -0
- package/src/types/use-data-table-props.d.ts +14 -0
- package/src/types/use-data-table-return.d.ts +14 -0
- package/src/utils/is-pill-value.ts +7 -0
- package/src/utils/render-object.tsx +18 -0
- package/src/utils/render-value.tsx +89 -0
- package/tsconfig.json +17 -0
- package/tsup.config.ts +8 -0
- package/vitest.config.ts +9 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# @sio-group/ui-datatable
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e606fc1: Feat: added datatable
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [430252c]
|
|
12
|
+
- Updated dependencies [a7139b5]
|
|
13
|
+
- Updated dependencies [e606fc1]
|
|
14
|
+
- @sio-group/ui-core@0.4.0
|
|
15
|
+
- @sio-group/ui-modal@0.4.0
|
|
16
|
+
- @sio-group/ui-pagination@0.1.1
|
package/README.md
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
# @sio-group/ui-datatable
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/ISC)
|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
A flexible and accessible datatable component for React applications.
|
|
8
|
+
Supports both client-side and server-side data handling through a single unified API.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
* 🔄 **Client-side & server-side** – one component for both local and API-driven data
|
|
15
|
+
* 🔍 **Search** – built-in search bar, client-side filtering or server-side delegation
|
|
16
|
+
* ↕️ **Sorting** – per-column sort with custom sort icons
|
|
17
|
+
* 📄 **Pagination** – via `@sio-group/ui-pagination`
|
|
18
|
+
* ✏️ **Inline editing** – editable cells with text input and select support
|
|
19
|
+
* 🎯 **Action menu** – inline or dropdown row actions, fully controlled by the consumer
|
|
20
|
+
* 🎨 **Custom styling** – supports custom classes and inline styles
|
|
21
|
+
* ♿ **Accessible** – ARIA attributes on sort controls and search input
|
|
22
|
+
* 📦 **TypeScript** – full generic type support
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install @sio-group/ui-datatable
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Peer dependencies
|
|
33
|
+
|
|
34
|
+
This package requires:
|
|
35
|
+
|
|
36
|
+
* `react` ^19.0.0
|
|
37
|
+
* `react-dom` ^19.0.0
|
|
38
|
+
|
|
39
|
+
### Dependencies
|
|
40
|
+
|
|
41
|
+
This package includes:
|
|
42
|
+
|
|
43
|
+
* `@sio-group/ui-pagination`
|
|
44
|
+
* `@sio-group/ui-core`
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Styling
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
import "@sio-group/ui-datatable/sio-datatable-style.css";
|
|
52
|
+
import "@sio-group/ui-core/sio-core-style.css";
|
|
53
|
+
import "@sio-group/ui-pagination/sio-pagination-style.css";
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Quick Example
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
import { DataTable } from "@sio-group/ui-datatable";
|
|
62
|
+
|
|
63
|
+
interface User {
|
|
64
|
+
id: number;
|
|
65
|
+
name: string;
|
|
66
|
+
email: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const columns = [
|
|
70
|
+
{ name: 'name', label: 'Naam', sort: true },
|
|
71
|
+
{ name: 'email', label: 'E-mail', format: 'email' as const },
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
function Example() {
|
|
75
|
+
return (
|
|
76
|
+
<DataTable<User>
|
|
77
|
+
columns={columns}
|
|
78
|
+
data={users}
|
|
79
|
+
clientPageSize={20}
|
|
80
|
+
clientSearchKeys={['name', 'email']}
|
|
81
|
+
/>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Client-side vs Server-side
|
|
89
|
+
|
|
90
|
+
The datatable has two modes. The mode is determined automatically based on the props you provide — there is no explicit `mode` prop.
|
|
91
|
+
|
|
92
|
+
| | Client-side | Server-side |
|
|
93
|
+
|-----------------|-------------------------|---------------------------|
|
|
94
|
+
| Data | Full dataset via `data` | Current page via `data` |
|
|
95
|
+
| Pagination info | Calculated internally | Provided via `pagination` |
|
|
96
|
+
| Search | Filtered internally | Delegated via `onSearch` |
|
|
97
|
+
| Sort | Sorted internally | Delegated via `onSort` |
|
|
98
|
+
|
|
99
|
+
### Client-side
|
|
100
|
+
|
|
101
|
+
Pass the full dataset via `data`. The datatable handles filtering, sorting and pagination internally.
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
<DataTable<User>
|
|
105
|
+
columns={columns}
|
|
106
|
+
data={allUsers}
|
|
107
|
+
clientPageSize={20}
|
|
108
|
+
clientSearchKeys={['name', 'email']}
|
|
109
|
+
/>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
- **Search** is shown when `clientSearchKeys` is provided.
|
|
113
|
+
- **Pagination** is shown when `clientPageSize` is provided.
|
|
114
|
+
- **Sorting** is active per column when `column.sort` is `true`.
|
|
115
|
+
|
|
116
|
+
### Server-side
|
|
117
|
+
|
|
118
|
+
Pass the current page of data via `data` and provide a `pagination` object with the metadata from your API response. The datatable delegates search, sort and pagination back to you via callbacks.
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
<DataTable<User>
|
|
122
|
+
columns={columns}
|
|
123
|
+
data={pagedUsers}
|
|
124
|
+
pagination={{
|
|
125
|
+
currentPage: 1,
|
|
126
|
+
pageCount: 12,
|
|
127
|
+
total: 240,
|
|
128
|
+
from: 1,
|
|
129
|
+
to: 20,
|
|
130
|
+
}}
|
|
131
|
+
onPaginate={(page) => fetchPage(page)}
|
|
132
|
+
onSearch={(query) => setSearch(query)}
|
|
133
|
+
onSort={(sort) => setSort(sort)}
|
|
134
|
+
searchValue={search}
|
|
135
|
+
sortValue={sort}
|
|
136
|
+
/>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
- **Search** is shown when `onSearch` is provided.
|
|
140
|
+
- **Pagination** is shown when `onPaginate` is provided.
|
|
141
|
+
- **Sorting** is active per column when `column.sort` is `true`.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Action Menu
|
|
146
|
+
|
|
147
|
+
Row actions are fully controlled by the consumer via `onClick`. The datatable has no knowledge of navigation, deletion or confirmation dialogs.
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
const actionMenu = {
|
|
151
|
+
type: 'dropdown' as const,
|
|
152
|
+
actions: [
|
|
153
|
+
{
|
|
154
|
+
name: 'detail',
|
|
155
|
+
label: 'Bekijken',
|
|
156
|
+
icon: <EyeIcon />,
|
|
157
|
+
onClick: (item) => navigate(`/users/${item.id}`),
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: 'edit',
|
|
161
|
+
label: 'Wijzigen',
|
|
162
|
+
icon: <PencilIcon />,
|
|
163
|
+
onClick: (item) => navigate(`/users/${item.id}/wijzigen`),
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: 'delete',
|
|
167
|
+
label: 'Verwijderen',
|
|
168
|
+
icon: <TrashIcon />,
|
|
169
|
+
onClick: (item) => setConfirmItem(item),
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
<DataTable<User>
|
|
175
|
+
columns={columns}
|
|
176
|
+
data={users}
|
|
177
|
+
actionMenu={actionMenu}
|
|
178
|
+
renderMenuIcon={() => <EllipsisIcon />}
|
|
179
|
+
/>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The `type` prop controls how the actions are rendered:
|
|
183
|
+
|
|
184
|
+
| `type` | Description |
|
|
185
|
+
|--------------|----------------------------------------------|
|
|
186
|
+
| `'inline'` | All action buttons shown directly in the row |
|
|
187
|
+
| `'dropdown'` | Actions hidden behind a trigger button |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Inline Editing
|
|
192
|
+
|
|
193
|
+
Mark columns as editable by providing a `formFields` array. Each entry maps a column by `name` to an input type.
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
const formFields = [
|
|
197
|
+
{ name: 'name', type: 'text', required: true },
|
|
198
|
+
{
|
|
199
|
+
name: 'status',
|
|
200
|
+
type: 'select',
|
|
201
|
+
options: [
|
|
202
|
+
{ label: 'Actief', value: 'active' },
|
|
203
|
+
{ label: 'Inactief', value: 'inactive' },
|
|
204
|
+
],
|
|
205
|
+
},
|
|
206
|
+
];
|
|
207
|
+
|
|
208
|
+
<DataTable<User>
|
|
209
|
+
columns={columns}
|
|
210
|
+
data={users}
|
|
211
|
+
formFields={formFields}
|
|
212
|
+
onUpdate={(id, values) => updateUser(id, values)}
|
|
213
|
+
/>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
An edit icon appears next to the cell value. Clicking it opens an input. Changes are confirmed with ✓ or cancelled with ✗. Pressing `Escape` also cancels the edit.
|
|
217
|
+
|
|
218
|
+
`onUpdate` is called with the row `id` and a partial object containing the changed field:
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
onUpdate={(id, values) => {
|
|
222
|
+
// id: 1
|
|
223
|
+
// values: { name: 'Sophia' }
|
|
224
|
+
}}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Column Formats
|
|
230
|
+
|
|
231
|
+
The `format` prop on a column controls how the cell value is rendered.
|
|
232
|
+
|
|
233
|
+
| `format` | Input type | Renders |
|
|
234
|
+
|-------------------|------------------------------------|----------------------------------------------------|
|
|
235
|
+
| `'date'` | `string \| Date` | Localized date (`nl-BE`) |
|
|
236
|
+
| `'datetime'` | `string \| Date` | Localized date + time (`nl-BE`) |
|
|
237
|
+
| `'boolean'` | `boolean` | Clickable ✓/✗, calls `onUpdate` |
|
|
238
|
+
| `'button'` | `boolean` | Same as boolean, rendered as a primary button |
|
|
239
|
+
| `'pill'` | `{ status: Color, label: string }` | `<Pill>` from `@sio-group/ui-core` |
|
|
240
|
+
| `'email'` | `string` | `mailto:` link |
|
|
241
|
+
| `{ key: string }` | `object \| object[]` | Renders the value of the given key from the object |
|
|
242
|
+
| _(none)_ | `string \| number` | Raw value |
|
|
243
|
+
|
|
244
|
+
For objects and arrays without a `format`, all key-value pairs are rendered stacked.
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
// Render only the `name` key from an object or array of objects
|
|
248
|
+
{ name: 'role', label: 'Rol', format: { key: 'name' } }
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Sort Icons
|
|
254
|
+
|
|
255
|
+
Provide a custom sort icon via `renderSortIcon`:
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
<DataTable
|
|
259
|
+
...
|
|
260
|
+
renderSortIcon={(direction, active) => (
|
|
261
|
+
<MyIcon
|
|
262
|
+
name={direction === 'asc' ? 'sort-up' : 'sort-down'}
|
|
263
|
+
style={{ opacity: active ? 1 : 0.3 }}
|
|
264
|
+
/>
|
|
265
|
+
)}
|
|
266
|
+
/>
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## API Reference
|
|
272
|
+
|
|
273
|
+
### DataTable Props
|
|
274
|
+
|
|
275
|
+
| Prop | Type | Default | Description |
|
|
276
|
+
|--------------------|------------------------------------------------------------|-------------------|----------------------------------------------------------------------------|
|
|
277
|
+
| `columns` | `Column<T>[]` | — | Column definitions |
|
|
278
|
+
| `data` | `T[]` | — | Data to display — full dataset (client-side) or current page (server-side) |
|
|
279
|
+
| `pagination` | `PaginationMeta` | — | Server pagination metadata. Presence determines server-side mode |
|
|
280
|
+
| `onPaginate` | `(page: number) => void` | — | Called on page change. Shows pagination when provided (server-side) |
|
|
281
|
+
| `onSearch` | `(query: string) => void` | — | Called on search input. Shows search bar when provided (server-side) |
|
|
282
|
+
| `onSort` | `(sort: SortState \| null) => void` | — | Called on column sort (server-side) |
|
|
283
|
+
| `searchValue` | `string` | — | Controlled search value (server-side) |
|
|
284
|
+
| `sortValue` | `SortState \| null` | — | Controlled sort state (server-side) |
|
|
285
|
+
| `clientPageSize` | `number` | — | Page size for client-side pagination. Shows pagination when provided |
|
|
286
|
+
| `clientSearchKeys` | `(keyof T)[]` | — | Fields to search on client-side. Shows search bar when provided |
|
|
287
|
+
| `entity` | `Entity` | — | Used for search bar placeholder text |
|
|
288
|
+
| `actionMenu` | `ActionMenu<T>` | — | Row action configuration |
|
|
289
|
+
| `renderMenuIcon` | `() => ReactNode` | — | Custom dropdown trigger icon |
|
|
290
|
+
| `onUpdate` | `(id: string \| number, values: Partial<T>) => void` | — | Called on inline edit save or boolean toggle |
|
|
291
|
+
| `formFields` | `FormField[]` | — | Makes columns inline-editable |
|
|
292
|
+
| `renderSortIcon` | `(direction: SortDirection, active: boolean) => ReactNode` | — | Custom sort indicator |
|
|
293
|
+
| `emptyMessage` | `string` | `'Nog geen data'` | Message shown when data is empty |
|
|
294
|
+
| `striped` | `boolean` | `false` | Alternating row background color |
|
|
295
|
+
| `hover` | `boolean` | `false` | Highlight row on mouse hover |
|
|
296
|
+
| `style` | `CSSProperties` | — | Inline styles for the table wrapper |
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
### Column
|
|
301
|
+
|
|
302
|
+
| Prop | Type | Default | Description |
|
|
303
|
+
|-------------|-----------------------------------------------------------------------------------------|---------|-------------------------------------------|
|
|
304
|
+
| `name` | `keyof T` | — | Maps to a key on the data object |
|
|
305
|
+
| `label` | `string` | — | Column header label |
|
|
306
|
+
| `sort` | `boolean` | — | Enables sorting for this column |
|
|
307
|
+
| `format` | `'boolean' \| 'button' \| 'date' \| 'datetime' \| 'pill' \| 'email' \| { key: string }` | — | Cell render format |
|
|
308
|
+
| `className` | `string` | — | Additional CSS class on `<th>` and `<td>` |
|
|
309
|
+
| `style` | `CSSProperties` | — | Inline styles on `<th>` and `<td>` |
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Utility Classes
|
|
314
|
+
|
|
315
|
+
The following CSS classes can be applied to a column via the `className` prop.
|
|
316
|
+
|
|
317
|
+
| Class | Description |
|
|
318
|
+
|-------------|----------------------------------------------------------------|
|
|
319
|
+
| `center` | Centers the cell content |
|
|
320
|
+
| `right` | Aligns the cell content to the right |
|
|
321
|
+
| `linebreak` | Renders newlines in the cell value (`\n` becomes a line break) |
|
|
322
|
+
| `no-style` | Removes link styling — underline on hover only |
|
|
323
|
+
|
|
324
|
+
```tsx
|
|
325
|
+
const columns = [
|
|
326
|
+
{ name: 'amount', label: 'Bedrag', className: 'right' },
|
|
327
|
+
{ name: 'notes', label: 'Notities', className: 'linebreak' },
|
|
328
|
+
];
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
`no-style` is useful on columns with `format: 'email' or other link-based formats where you want to suppress the default link appearance.
|
|
332
|
+
|
|
333
|
+
### ActionMenu
|
|
334
|
+
|
|
335
|
+
| Prop | Type | Description |
|
|
336
|
+
|-----------|--------------------------|--------------------------|
|
|
337
|
+
| `type` | `'inline' \| 'dropdown'` | How actions are rendered |
|
|
338
|
+
| `actions` | `Action<T>[]` | List of row actions |
|
|
339
|
+
|
|
340
|
+
### Action
|
|
341
|
+
|
|
342
|
+
| Prop | Type | Description |
|
|
343
|
+
|-----------|---------------------|-------------------------------|
|
|
344
|
+
| `name` | `string` | Identifier for the action |
|
|
345
|
+
| `label` | `string` | Display label |
|
|
346
|
+
| `icon` | `ReactNode` | Optional icon |
|
|
347
|
+
| `onClick` | `(item: T) => void` | Called with the full row item |
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
### FormField
|
|
352
|
+
|
|
353
|
+
| Prop | Type | Default | Description |
|
|
354
|
+
|------------|--------------------------------------------------|---------|--------------------------------|
|
|
355
|
+
| `name` | `string` | — | Maps to a column by name |
|
|
356
|
+
| `type` | `'text' \| 'select' \| 'radio'` | — | Input type |
|
|
357
|
+
| `options` | `string[] \| { label: string; value: string }[]` | — | Options for select and radio |
|
|
358
|
+
| `required` | `boolean` | — | Prevents saving an empty value |
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
### PaginationMeta
|
|
363
|
+
|
|
364
|
+
| Prop | Type | Description |
|
|
365
|
+
|---------------|----------|-----------------------------|
|
|
366
|
+
| `currentPage` | `number` | Active page (1-based) |
|
|
367
|
+
| `pageCount` | `number` | Total number of pages |
|
|
368
|
+
| `total` | `number` | Total number of items |
|
|
369
|
+
| `from` | `number` | First item on current page |
|
|
370
|
+
| `to` | `number` | Last item on current page |
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
### SortState
|
|
375
|
+
|
|
376
|
+
| Prop | Type | Description |
|
|
377
|
+
|-------------|-------------------|---------------------|
|
|
378
|
+
| `name` | `keyof T` | Column being sorted |
|
|
379
|
+
| `direction` | `'asc' \| 'desc'` | Sort direction |
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
### Entity
|
|
384
|
+
|
|
385
|
+
| Prop | Type | Description |
|
|
386
|
+
|---------|----------|----------------------------------------------------------------|
|
|
387
|
+
| `name` | `string` | Machine name, e.g. `'users'` |
|
|
388
|
+
| `label` | `string` | Display name, e.g. `'Gebruikers'` — used in search placeholder |
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## TypeScript
|
|
393
|
+
|
|
394
|
+
This package includes full TypeScript definitions. All main types are exported.
|
|
395
|
+
|
|
396
|
+
```ts
|
|
397
|
+
import { DataTable } from "@sio-group/ui-datatable";
|
|
398
|
+
import type {
|
|
399
|
+
DataTableProps,
|
|
400
|
+
Column,
|
|
401
|
+
Entity,
|
|
402
|
+
Action,
|
|
403
|
+
ActionMenu,
|
|
404
|
+
ActionMenuType,
|
|
405
|
+
FormField,
|
|
406
|
+
FormFieldType,
|
|
407
|
+
SortState,
|
|
408
|
+
SortDirection,
|
|
409
|
+
} from "@sio-group/ui-datatable";
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
## Browser Support
|
|
415
|
+
|
|
416
|
+
Supports all modern browsers that support:
|
|
417
|
+
|
|
418
|
+
* ES6 modules
|
|
419
|
+
* React 19+
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## Contributing
|
|
424
|
+
|
|
425
|
+
Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
|
|
426
|
+
|
|
427
|
+
## License
|
|
428
|
+
|
|
429
|
+
This project is licensed under the ISC License - see the [LICENSE](../../LICENSE) file for details.
|