@uxf/data-grid 11.122.3 → 11.122.4
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 +181 -89
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -1,48 +1,104 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @uxf/data-grid
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A schema-driven, server-side data grid: one compound `DataGrid` component with a built-in toolbar, tabs, filters, sorting, column visibility, row selection, pagination and CSV export.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## When to use
|
|
6
6
|
|
|
7
|
+
Reach for `@uxf/data-grid` when you have a paginated, filterable, server-fetched table driven by a generated schema (columns, filters, tabs). The grid owns fetching, filtering, sorting and pagination state; you provide a `schema` and a `loader`.
|
|
8
|
+
|
|
9
|
+
It is **not** a headless table primitive and not a spreadsheet — layout, toolbar and footer are opinionated. For a plain, fully custom table render the internal parts yourself (see [Custom composition](#custom-composition)) rather than reaching for a different library.
|
|
10
|
+
|
|
11
|
+
> **Note:** This package ships translations. Wrap your app in the `TranslationsProvider` from `@uxf/core-react/translations` for correct labels.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
yarn add @uxf/data-grid
|
|
7
17
|
```
|
|
8
|
-
yarn add @uxf/core @uxf/ui @uxf/data-grid
|
|
9
18
|
|
|
10
|
-
|
|
19
|
+
Peer dependencies (install if not already present):
|
|
11
20
|
|
|
12
|
-
yarn upgrade @uxf/core@latest @uxf/ui@latest @uxf/data-grid@latest
|
|
13
21
|
```
|
|
22
|
+
yarn add @uxf/core @uxf/core-react @uxf/localize @uxf/styles @uxf/ui \
|
|
23
|
+
@dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities dayjs react react-dom
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### CSS
|
|
14
27
|
|
|
15
|
-
|
|
28
|
+
Import the dependency stylesheets first, then the grid's own stylesheet last. The `@uxf/ui` component styles are published under the flattened `@uxf/ui/css/` directory (the `@uxf/ui/<component>/<file>.css` source paths do not exist in the published package).
|
|
16
29
|
|
|
17
30
|
```css
|
|
18
31
|
@import url("tailwindcss/components.css");
|
|
19
|
-
@import url("@uxf/ui/
|
|
20
|
-
@import url("@uxf/ui/
|
|
21
|
-
@import url("@uxf/ui/
|
|
22
|
-
@import url("@uxf/ui/
|
|
23
|
-
@import url("@uxf/ui/
|
|
24
|
-
@import url("@uxf/ui/
|
|
25
|
-
@import url("@uxf/ui/
|
|
26
|
-
@import url("@uxf/ui/
|
|
27
|
-
@import url("@uxf/ui/
|
|
28
|
-
@import url("@uxf/ui/
|
|
29
|
-
@import url("@uxf/ui/
|
|
30
|
-
@import url("@uxf/ui/
|
|
31
|
-
@import url("@uxf/ui/
|
|
32
|
-
@import url("@uxf/ui/
|
|
33
|
-
@import url("@uxf/ui/
|
|
34
|
-
@import url("@uxf/ui/
|
|
35
|
-
@import url("@uxf/ui/
|
|
36
|
-
@import url("@uxf/ui/
|
|
37
|
-
@import url("@uxf/ui/
|
|
38
|
-
@import url("@uxf/ui/
|
|
39
|
-
@import url("@uxf/ui/
|
|
40
|
-
|
|
41
|
-
/* must be after component css files */
|
|
32
|
+
@import url("@uxf/ui/css/button.css");
|
|
33
|
+
@import url("@uxf/ui/css/button-list.css");
|
|
34
|
+
@import url("@uxf/ui/css/calendar.css");
|
|
35
|
+
@import url("@uxf/ui/css/checkbox.css");
|
|
36
|
+
@import url("@uxf/ui/css/chip.css");
|
|
37
|
+
@import url("@uxf/ui/css/dialog.css");
|
|
38
|
+
@import url("@uxf/ui/css/dropdown.css");
|
|
39
|
+
@import url("@uxf/ui/css/icon.css");
|
|
40
|
+
@import url("@uxf/ui/css/label.css");
|
|
41
|
+
@import url("@uxf/ui/css/form-component.css");
|
|
42
|
+
@import url("@uxf/ui/css/input-basic.css");
|
|
43
|
+
@import url("@uxf/ui/css/input.css");
|
|
44
|
+
@import url("@uxf/ui/css/input-with-popover.css");
|
|
45
|
+
@import url("@uxf/ui/css/combobox.css");
|
|
46
|
+
@import url("@uxf/ui/css/modal-header.css");
|
|
47
|
+
@import url("@uxf/ui/css/multi-select.css");
|
|
48
|
+
@import url("@uxf/ui/css/multi-combobox.css");
|
|
49
|
+
@import url("@uxf/ui/css/pagination.css");
|
|
50
|
+
@import url("@uxf/ui/css/select.css");
|
|
51
|
+
@import url("@uxf/ui/css/toggle.css");
|
|
52
|
+
@import url("@uxf/ui/css/tabs.css");
|
|
53
|
+
|
|
54
|
+
/* must be after the component css files */
|
|
42
55
|
@import url("@uxf/data-grid/styles.css");
|
|
43
56
|
```
|
|
44
57
|
|
|
45
|
-
##
|
|
58
|
+
## Quick start
|
|
59
|
+
|
|
60
|
+
`useDataGridControl` owns grid state and actions; `useDataGridFetching` runs the loader whenever the request changes. Feed both into `DataGrid`.
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
"use client";
|
|
64
|
+
|
|
65
|
+
import { DataGrid } from "@uxf/data-grid";
|
|
66
|
+
import { useDataGridControl } from "@uxf/data-grid/use-data-grid-control";
|
|
67
|
+
import { useDataGridFetching } from "@uxf/data-grid/use-data-grid-fetching";
|
|
68
|
+
import { schema } from "@generated/data-grid/schema/example";
|
|
69
|
+
|
|
70
|
+
export function ExampleGrid() {
|
|
71
|
+
const { state, actions } = useDataGridControl({ schema });
|
|
72
|
+
|
|
73
|
+
const { isLoading, error, data, reload } = useDataGridFetching({ schema, state });
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<DataGrid
|
|
77
|
+
actions={actions}
|
|
78
|
+
data={data}
|
|
79
|
+
error={error}
|
|
80
|
+
isLoading={isLoading}
|
|
81
|
+
reload={reload}
|
|
82
|
+
schema={schema}
|
|
83
|
+
state={state}
|
|
84
|
+
/>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`useDataGridFetching` uses a default loader that calls the conventional grid endpoint. To fetch yourself, pass a `loader`:
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
const { ... } = useDataGridFetching({
|
|
93
|
+
schema,
|
|
94
|
+
state,
|
|
95
|
+
loader: (gridName, request, encodedRequest) => myFetch(gridName, request),
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Persisting user config
|
|
100
|
+
|
|
101
|
+
`useUserConfigLocalStorageAdapter` returns a `middleware` (persists column visibility, widths, order, etc. to `localStorage`) and a `useUserConfig` hook that restores it. Wire the middleware into `useDataGridControl` and call `useUserConfig(actions)`.
|
|
46
102
|
|
|
47
103
|
```tsx
|
|
48
104
|
import { useDataGridControl } from "@uxf/data-grid/use-data-grid-control";
|
|
@@ -52,25 +108,55 @@ const { middleware, useUserConfig } = useUserConfigLocalStorageAdapter(schema);
|
|
|
52
108
|
|
|
53
109
|
const { state, actions } = useDataGridControl({
|
|
54
110
|
schema,
|
|
55
|
-
|
|
56
|
-
|
|
111
|
+
middleware,
|
|
112
|
+
// optional base64-encoded request or a Request object to hydrate initial state
|
|
113
|
+
initialState: encodedRequest,
|
|
114
|
+
// optional default column config
|
|
115
|
+
initialUserConfig: {
|
|
57
116
|
columns: {
|
|
58
117
|
id: { isHidden: true },
|
|
59
|
-
}
|
|
118
|
+
},
|
|
60
119
|
},
|
|
61
|
-
middleware,
|
|
62
|
-
isDebug: true,
|
|
63
120
|
});
|
|
64
121
|
|
|
65
122
|
useUserConfig(actions);
|
|
66
123
|
```
|
|
67
124
|
|
|
68
|
-
##
|
|
125
|
+
## API
|
|
69
126
|
|
|
70
|
-
|
|
71
|
-
(be aware - it must be interface)
|
|
127
|
+
Only exports listed below are part of the public surface. Import paths resolve by filesystem (there is no `exports` map).
|
|
72
128
|
|
|
73
|
-
|
|
129
|
+
### Root export — `@uxf/data-grid`
|
|
130
|
+
|
|
131
|
+
| Name | Kind | Description |
|
|
132
|
+
| --- | --- | --- |
|
|
133
|
+
| `DataGrid` | component | The compound grid. Props: `DataGridProps<GridType>`. |
|
|
134
|
+
| `DataGridProps<GridType>` | type | Grid props = base props + control (`state`, `actions`) + data (`isLoading`, `error`, `data`, `reload`). |
|
|
135
|
+
| `InferDataGridRow<Schema>` | type | Derives the row shape from a schema via `ColumnTypes`. |
|
|
136
|
+
| `BaseGridType`, `Schema`, `ChangeTabFilterBehavior`, `DataGridActionCell`, … | types | Re-exported from `./types`. |
|
|
137
|
+
| `mergeSchemaWithConfig(schema, config)` | fn | Returns a new schema with a frontend config applied (see below). |
|
|
138
|
+
| `encodeFilter(request)` / `decodeFilter(string)` | fn | Base64 (de)serialize a grid request. |
|
|
139
|
+
|
|
140
|
+
### Deep imports
|
|
141
|
+
|
|
142
|
+
| Import path | Export | Description |
|
|
143
|
+
| --- | --- | --- |
|
|
144
|
+
| `@uxf/data-grid/use-data-grid-control` | `useDataGridControl(config)` | Owns grid `state` + `actions`. Config: `{ schema, initialState?, initialUserConfig?, middleware? }`. |
|
|
145
|
+
| `@uxf/data-grid/use-data-grid-fetching` | `useDataGridFetching(config)` | Runs the loader on request changes. Config: `{ schema, state, loader?, isWithTabCounts? }`. Returns `{ isLoading, error, data, reload }`. |
|
|
146
|
+
| `@uxf/data-grid/user-config-storage-adapters/local-storage` | `useUserConfigLocalStorageAdapter(schema)`, `useClearLocalStorageUserConfig(schema)` | `localStorage` persistence of user column config. |
|
|
147
|
+
| `@uxf/data-grid/column-types` | `ColumnTypes` (interface) | Augment to register custom column value types. |
|
|
148
|
+
|
|
149
|
+
Notable optional `DataGrid` props: `actionCell`, `bodyCells`, `changeTabFilterBehavior`, `customActions`, `filterHandlers`, `fulltextInputPlaceholder`, `getCsvDownloadUrl`, `hasStickyHeader`, `isRowsSelectable`, `isRowSelectDisabled`, `isWithTabCounts`, `keyExtractor`, `rowAccent`, `rowClassName`, `rowHeight`, `tabsVariant`, `HiddenColumnsComponent`, `NoRowsFallback`, `SelectedRowsToolbarActions`, `isDebug`.
|
|
150
|
+
|
|
151
|
+
## Column types
|
|
152
|
+
|
|
153
|
+
A column's `type` (from the schema) maps to a value type via the `ColumnTypes` interface, which drives `InferDataGridRow`. Built-in types:
|
|
154
|
+
|
|
155
|
+
`boolean`, `chip`, `chips`, `date`, `datetime`, `email`, `id`, `int`, `money`, `phone`, `string`, `url`, `uuid`.
|
|
156
|
+
|
|
157
|
+
Register a custom column type with module augmentation. Create a `column-types.d.ts` at the project root (next to `tsconfig.json`) — it **must** be an `interface`:
|
|
158
|
+
|
|
159
|
+
```ts
|
|
74
160
|
declare module "@uxf/data-grid/column-types" {
|
|
75
161
|
export interface ColumnTypes {
|
|
76
162
|
"my-custom-type": MyCustomType;
|
|
@@ -78,85 +164,91 @@ declare module "@uxf/data-grid/column-types" {
|
|
|
78
164
|
}
|
|
79
165
|
```
|
|
80
166
|
|
|
81
|
-
Then
|
|
167
|
+
Then infer the row type from a schema:
|
|
82
168
|
|
|
83
|
-
```
|
|
169
|
+
```ts
|
|
84
170
|
import { InferDataGridRow } from "@uxf/data-grid";
|
|
85
171
|
import { schema } from "@generated/data-grid/schema/example";
|
|
86
172
|
|
|
87
173
|
type Row = InferDataGridRow<typeof schema>;
|
|
88
174
|
```
|
|
89
175
|
|
|
90
|
-
##
|
|
176
|
+
## Filter handlers
|
|
177
|
+
|
|
178
|
+
Each filter is rendered by looking up `filterHandlers[filter.type]`. The grid uses `defaultFilterHandlers` unless you pass a `filterHandlers` prop. Built-in handler keys:
|
|
179
|
+
|
|
180
|
+
| `filter.type` | Renders |
|
|
181
|
+
| --- | --- |
|
|
182
|
+
| `checkbox` | Checkbox (value is sent only when checked) |
|
|
183
|
+
| `date` | Date range (from / to date pickers) |
|
|
184
|
+
| `datetime` | Datetime range |
|
|
185
|
+
| `entitySelect` | Single-select combobox (async entity) |
|
|
186
|
+
| `entityMultiSelect` | Multi-select combobox (async entity) |
|
|
187
|
+
| `interval` | Numeric range (min / max inputs) |
|
|
188
|
+
| `multiSelect` | Multi-select |
|
|
189
|
+
| `select` | Select |
|
|
190
|
+
| `string` | Text input |
|
|
191
|
+
|
|
192
|
+
Extend or override by merging into `defaultFilterHandlers` and passing the result as the `filterHandlers` prop:
|
|
91
193
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
- `entitySelect`
|
|
98
|
-
- `interval`
|
|
99
|
-
- `multiSelect`
|
|
100
|
-
- `select`
|
|
101
|
-
- `string`, `text`
|
|
194
|
+
```tsx
|
|
195
|
+
import { defaultFilterHandlers } from "@uxf/data-grid/filter-handler";
|
|
196
|
+
|
|
197
|
+
<DataGrid filterHandlers={{ ...defaultFilterHandlers, myType: myHandler }} {...rest} />;
|
|
198
|
+
```
|
|
102
199
|
|
|
103
|
-
##
|
|
200
|
+
## Frontend config
|
|
104
201
|
|
|
105
|
-
|
|
202
|
+
`mergeSchemaWithConfig` returns a new schema with per-column and per-filter overrides and `perPage` applied — useful for tweaking a generated schema without regenerating it.
|
|
106
203
|
|
|
107
204
|
```tsx
|
|
205
|
+
import { DataGrid } from "@uxf/data-grid";
|
|
206
|
+
import { mergeSchemaWithConfig } from "@uxf/data-grid";
|
|
108
207
|
import { useDataGridControl } from "@uxf/data-grid/use-data-grid-control";
|
|
109
208
|
import { useDataGridFetching } from "@uxf/data-grid/use-data-grid-fetching";
|
|
110
|
-
import {
|
|
209
|
+
import { schema as baseSchema } from "@generated/data-grid/schema/example";
|
|
111
210
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
211
|
+
const schema = mergeSchemaWithConfig(baseSchema, {
|
|
212
|
+
perPage: 100,
|
|
213
|
+
columns: {
|
|
214
|
+
id: { width: 100, isHidden: true },
|
|
215
|
+
},
|
|
216
|
+
filters: {
|
|
217
|
+
id: { placeholder: "Search by ID..." },
|
|
218
|
+
},
|
|
219
|
+
});
|
|
117
220
|
|
|
118
|
-
|
|
221
|
+
export function ConfiguredGrid() {
|
|
222
|
+
const { state, actions } = useDataGridControl({ schema });
|
|
223
|
+
const { isLoading, error, data, reload } = useDataGridFetching({ schema, state });
|
|
119
224
|
|
|
120
225
|
return (
|
|
121
226
|
<DataGrid
|
|
122
|
-
reload={reload}
|
|
123
|
-
state={state}
|
|
124
227
|
actions={actions}
|
|
125
228
|
data={data}
|
|
126
|
-
isLoading={isLoading}
|
|
127
229
|
error={error}
|
|
230
|
+
isLoading={isLoading}
|
|
231
|
+
reload={reload}
|
|
128
232
|
schema={schema}
|
|
233
|
+
state={state}
|
|
129
234
|
/>
|
|
130
235
|
);
|
|
131
236
|
}
|
|
132
237
|
```
|
|
133
238
|
|
|
134
|
-
|
|
239
|
+
## Custom composition
|
|
135
240
|
|
|
136
|
-
|
|
137
|
-
import { useDataGridControl } from "@uxf/data-grid/use-data-grid-control";
|
|
138
|
-
import { mergeSchemaWithConfig } from "@uxf/data-grid";
|
|
241
|
+
The `DataGrid` component is a fixed composition of internal parts. For a fully custom layout, import the parts individually and assemble them yourself, still driving them from `useDataGridControl` / `useDataGridFetching`:
|
|
139
242
|
|
|
140
|
-
|
|
141
|
-
dataGridSchema_ExampleGrid,
|
|
142
|
-
{
|
|
143
|
-
columns: {
|
|
144
|
-
id: { width: 100, isHidden: true },
|
|
145
|
-
},
|
|
146
|
-
filters: {
|
|
147
|
-
id: { placeholder: "Hledejte podle ID..." }
|
|
148
|
-
},
|
|
149
|
-
perPage: 100,
|
|
150
|
-
}
|
|
151
|
-
);
|
|
243
|
+
`@uxf/data-grid/root`, `@uxf/data-grid/toolbar`, `@uxf/data-grid/toolbar-tabs`, `@uxf/data-grid/toolbar-control`, `@uxf/data-grid/toolbar-customs`, `@uxf/data-grid/filter-list`, `@uxf/data-grid/table-v2`, `@uxf/data-grid/footer`, `@uxf/data-grid/pagination`, `@uxf/data-grid/row-counts`, `@uxf/data-grid/rows-per-page-select`, `@uxf/data-grid/selected-rows-toolbar`, `@uxf/data-grid/linear-progress`, `@uxf/data-grid/body-cell`, `@uxf/data-grid/filter-handler`.
|
|
152
244
|
|
|
153
|
-
|
|
154
|
-
const { state, actions } = useDataGridControl({
|
|
155
|
-
schema,
|
|
156
|
-
initialUserConfig: props.userConfig,
|
|
157
|
-
})
|
|
245
|
+
See `data-grid.tsx` (the default composition) and `data-grid-custom-example.stories.tsx` in the package for a worked example.
|
|
158
246
|
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
```
|
|
247
|
+
## Gotchas
|
|
162
248
|
|
|
249
|
+
- **Client component only.** The hooks use React state, effects and `localStorage`. Render the grid in a client component (`"use client"`).
|
|
250
|
+
- **`TranslationsProvider` required.** Labels come from bundled translations via `@uxf/core-react/translations`.
|
|
251
|
+
- **CSS order matters.** Import `@uxf/data-grid/styles.css` after the `@uxf/ui/css/*` component styles.
|
|
252
|
+
- **`ColumnTypes` augmentation must be an `interface`**, not a `type`, or the declaration merge will not apply.
|
|
253
|
+
- **`initialState` is a base64-encoded request string** (or a `Request` object) — use `encodeFilter` / `decodeFilter` to (de)serialize, e.g. to persist the current view in the URL.
|
|
254
|
+
- **`isDebug` is a `DataGrid` prop**, not a `useDataGridControl` config option.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uxf/data-grid",
|
|
3
|
-
"version": "11.122.
|
|
3
|
+
"version": "11.122.4",
|
|
4
4
|
"description": "UXF DataGrid",
|
|
5
5
|
"homepage": "https://gitlab.com/uxf-npm/data-grid#readme",
|
|
6
6
|
"main": "index.js",
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
"@dnd-kit/utilities": "^3.2.2",
|
|
44
44
|
"@uxf/core": "11.114.0",
|
|
45
45
|
"@uxf/core-react": "11.122.2",
|
|
46
|
-
"@uxf/localize": "11.122.
|
|
47
|
-
"@uxf/styles": "11.
|
|
48
|
-
"@uxf/ui": "11.122.
|
|
46
|
+
"@uxf/localize": "11.122.4",
|
|
47
|
+
"@uxf/styles": "11.122.4",
|
|
48
|
+
"@uxf/ui": "11.122.4",
|
|
49
49
|
"dayjs": "^1.11.19",
|
|
50
50
|
"react": ">=18.2.0",
|
|
51
51
|
"react-dom": ">=18.2.0"
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
"@types/react-dom": "18.3.7",
|
|
59
59
|
"@uxf/core": "11.114.0",
|
|
60
60
|
"@uxf/core-react": "11.122.2",
|
|
61
|
-
"@uxf/localize": "11.122.
|
|
62
|
-
"@uxf/styles": "11.
|
|
63
|
-
"@uxf/ui": "11.122.
|
|
61
|
+
"@uxf/localize": "11.122.4",
|
|
62
|
+
"@uxf/styles": "11.122.4",
|
|
63
|
+
"@uxf/ui": "11.122.4",
|
|
64
64
|
"dayjs": "^1.11.19",
|
|
65
65
|
"react": "18.3.1",
|
|
66
66
|
"react-dom": "18.3.1"
|