@geovi/the-datagrid 0.1.1 → 0.1.2
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 +47 -1253
- package/dist/BoolEditor.cjs +1 -1
- package/dist/BoolEditor.js +235 -222
- package/dist/DateEditor.cjs +1 -1
- package/dist/DateEditor.js +297 -273
- package/dist/DateFilter.cjs +1 -1
- package/dist/DateFilter.js +65 -63
- package/dist/NumberFilter.cjs +1 -1
- package/dist/NumberFilter.js +104 -102
- package/dist/NumericEditor.cjs +1 -1
- package/dist/NumericEditor.js +296 -277
- package/dist/SelectEditor.cjs +42 -0
- package/dist/SelectEditor.js +6703 -0
- package/dist/StringFilter.cjs +1 -1
- package/dist/StringFilter.js +121 -119
- package/dist/TextEditor.cjs +2 -0
- package/dist/TextEditor.js +2972 -0
- package/dist/base.css +1 -1
- package/dist/community-package-manifest.json +3 -1
- package/dist/components/ui/input.d.ts +2 -0
- package/dist/components/ui/input.d.ts.map +1 -1
- package/dist/editors/BoolEditor.d.ts +1 -1
- package/dist/editors/BoolEditor.d.ts.map +1 -1
- package/dist/editors/DateEditor.d.ts +1 -1
- package/dist/editors/DateEditor.d.ts.map +1 -1
- package/dist/editors/NumericEditor.d.ts +1 -1
- package/dist/editors/NumericEditor.d.ts.map +1 -1
- package/dist/editors/SelectEditor.d.ts +27 -0
- package/dist/editors/SelectEditor.d.ts.map +1 -0
- package/dist/editors/TextEditor.d.ts +27 -0
- package/dist/editors/TextEditor.d.ts.map +1 -0
- package/dist/editors/editorTypes.d.ts +24 -0
- package/dist/editors/editorTypes.d.ts.map +1 -1
- package/dist/editors/index.d.ts +5 -0
- package/dist/editors/index.d.ts.map +1 -1
- package/dist/grid/ReactDataGrid.d.ts.map +1 -1
- package/dist/grid/components/GridBody.d.ts.map +1 -1
- package/dist/grid/components/GridContextMenuLayer.d.ts.map +1 -1
- package/dist/grid/hooks/useGridEditing.d.ts.map +1 -1
- package/dist/grid/menuRuntime.d.ts +27 -0
- package/dist/grid/menuRuntime.d.ts.map +1 -0
- package/dist/index.cjs +13 -13
- package/dist/index.css +1 -1
- package/dist/index.js +9435 -9164
- package/dist/main.d.ts +2 -2
- package/dist/main.d.ts.map +1 -1
- package/dist/style/theme/amber-dark/index.css +1 -1
- package/dist/style/theme/amber-light/index.css +1 -1
- package/dist/style/theme/blue-dark/index.css +1 -1
- package/dist/style/theme/blue-light/index.css +1 -1
- package/dist/style/theme/default-dark/index.css +1 -1
- package/dist/style/theme/default-light/index.css +1 -1
- package/dist/style/theme/green-dark/index.css +1 -1
- package/dist/style/theme/green-light/index.css +1 -1
- package/dist/style/theme/pink-dark/index.css +1 -1
- package/dist/style/theme/pink-light/index.css +1 -1
- package/dist/toolbar/RDGToolbar.d.ts.map +1 -1
- package/dist/toolbar/icons.d.ts +0 -2
- package/dist/toolbar/icons.d.ts.map +1 -1
- package/dist/toolbar/runtime.d.ts +7 -0
- package/dist/toolbar/runtime.d.ts.map +1 -1
- package/dist/toolbar.css +1 -1
- package/dist/toolbar.js +548 -651
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +20 -2
package/README.md
CHANGED
|
@@ -1,1297 +1,91 @@
|
|
|
1
1
|
# the-datagrid
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A fast, fully typed React data grid with an Inovua-compatible API and a
|
|
4
|
+
shadcn-aligned interface.
|
|
4
5
|
|
|
5
|
-
Documentation and live examples
|
|
6
|
+
[Documentation and live examples](https://geo-vi.github.io/the-datagrid/) ·
|
|
7
|
+
[npm](https://www.npmjs.com/package/@geovi/the-datagrid) ·
|
|
8
|
+
[GitHub](https://github.com/geo-vi/the-datagrid)
|
|
6
9
|
|
|
7
|
-
##
|
|
10
|
+
## Why the-datagrid?
|
|
8
11
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
- Pagination (local + remote)
|
|
17
|
-
- Row selection (checkbox column)
|
|
18
|
-
- Modern shadcn-aligned look-and-feel with packaged styles
|
|
19
|
-
- Fully typed TypeScript API
|
|
20
|
-
- Public product target of 100% backwards compatibility with Inovua Community
|
|
12
|
+
- Familiar Inovua Community 5.10.2 naming and behavior for easier migrations.
|
|
13
|
+
- Virtualized rows and columns for large datasets.
|
|
14
|
+
- Local and remote sorting, filtering, pagination, selection, and editing.
|
|
15
|
+
- Resizable, reorderable, hideable, nested, and responsive columns.
|
|
16
|
+
- Optional search, column controls, CSV/JSON/XLSX export, and mobile layout.
|
|
17
|
+
- Packaged styles with shadcn-compatible tokens—Tailwind and shadcn are not
|
|
18
|
+
required in consumer apps.
|
|
21
19
|
|
|
22
|
-
##
|
|
23
|
-
|
|
24
|
-
the-datagrid targets **100% backwards compatibility** with the documented
|
|
25
|
-
public API and observable behavior of
|
|
26
|
-
[`@inovua/reactdatagrid-community@5.10.2`](https://www.npmjs.com/package/@inovua/reactdatagrid-community/v/5.10.2).
|
|
27
|
-
After changing the package dependency and import specifier, public
|
|
28
|
-
Inovua-shaped application business logic should not require a rewrite.
|
|
29
|
-
|
|
30
|
-
The audited Community 5.10.2 release gate is implemented and backed by
|
|
31
|
-
type, runtime, browser, packed-package, and performance tests. Compatibility
|
|
32
|
-
covers more than similarly named TypeScript fields: it includes defaults,
|
|
33
|
-
runtime behavior, callback payloads and timing, controlled/uncontrolled state,
|
|
34
|
-
local and remote data flow, layout, keyboard and focus interaction, and
|
|
35
|
-
accessibility behavior.
|
|
36
|
-
|
|
37
|
-
The Issue 17 and Issue 31–45 compatibility batches implement and
|
|
38
|
-
regression-test:
|
|
39
|
-
|
|
40
|
-
- Inovua's `idProperty`, theme, row/filter height, text-selection, filter-menu,
|
|
41
|
-
and column-menu defaults;
|
|
42
|
-
- tri-state filter-row inference and the upstream controlled/uncontrolled local
|
|
43
|
-
transformation split;
|
|
44
|
-
- root class/style and focus, blur, and keyboard lifecycle handlers; and
|
|
45
|
-
- packed-package compatibility across React 16.8, 17, 18, and 19;
|
|
46
|
-
- natural and per-row height (`rowHeight={null}`, a `rowHeight` function,
|
|
47
|
-
`minRowHeight`/`maxRowHeight`, and width-change remeasurement);
|
|
48
|
-
- `onColumnResize`, controlled `width`, and uncontrolled `defaultWidth`;
|
|
49
|
-
- weighted `flex`/`defaultFlex` remaining-space allocation;
|
|
50
|
-
- visible zebra rows by default and the per-grid `showZebraRows` toggle;
|
|
51
|
-
- inline editing (`editable`, `editStartEvent`, column editors, lifecycle
|
|
52
|
-
callbacks, cancellation, focus, and keyboard navigation);
|
|
53
|
-
- object- or function-valued whole-row `rowStyle`.
|
|
54
|
-
- stacked and nested column groups, custom group headers, split/rejoin
|
|
55
|
-
reordering, controlled group moves, proportional group resizing, and
|
|
56
|
-
horizontal-virtualization geometry;
|
|
57
|
-
- the standalone
|
|
58
|
-
`@geovi/the-datagrid/packages/TextInput` compatibility entry, including its
|
|
59
|
-
value-first callbacks, clear tool, legacy class hooks, and imperative ref;
|
|
60
|
-
- the `onDidMount` computed-props lifecycle callback; and
|
|
61
|
-
- `getVirtualList().adjustHeights()` for instantiated variable-height rows in
|
|
62
|
-
virtual and non-virtual layouts.
|
|
63
|
-
|
|
64
|
-
This closes the audited Community gate. The
|
|
65
|
-
[source release ledger](docs/inovua-community-5.10.2-compatibility.md) maps
|
|
66
|
-
every child issue to executable evidence, and
|
|
67
|
-
[`community-api-manifest.json`](community-api-manifest.json) records the
|
|
68
|
-
behavior-backed computed API, plugins, types, and Enterprise exclusions.
|
|
69
|
-
Unknown computed method names are absent instead of being fabricated as no-op
|
|
70
|
-
functions. Any future mismatch is a compatibility regression and must be
|
|
71
|
-
tracked with executable coverage.
|
|
72
|
-
|
|
73
|
-
Issue 48 explicitly adopts Inovua's standalone `TextInput` toolkit path. Migrate
|
|
74
|
-
its default import to `@geovi/the-datagrid/packages/TextInput`; the package also
|
|
75
|
-
provides a named root export. The deep entry and its class-instance TypeScript
|
|
76
|
-
shape are now part of the compatibility contract.
|
|
77
|
-
|
|
78
|
-
Read the public
|
|
79
|
-
[compatibility contract](https://geo-vi.github.io/the-datagrid/docs/migration/inovua-compat)
|
|
80
|
-
and the
|
|
81
|
-
[living implementation-status ledger](https://geo-vi.github.io/the-datagrid/docs/migration/inovua-status)
|
|
82
|
-
before treating the current package as a drop-in runtime replacement.
|
|
83
|
-
|
|
84
|
-
## Implemented today
|
|
85
|
-
|
|
86
|
-
The following inventory describes behavior that ships in the current package.
|
|
87
|
-
The public docs contain the full
|
|
88
|
-
[source-backed implemented-surface reference](https://geo-vi.github.io/the-datagrid/docs/reference/implemented-surface),
|
|
89
|
-
including exact defaults, timing, transform order, exports, and imperative
|
|
90
|
-
method allowlists.
|
|
91
|
-
|
|
92
|
-
- **Data loading:** local arrays, static Promises, and function-backed sources
|
|
93
|
-
returning either an array or `{ data, count }`. Function sources
|
|
94
|
-
receive `sortInfo`, `filterValue`, `columnOrder`, `columns`, `idProperty`, and
|
|
95
|
-
`theme`, plus `skip`/`limit` when remote pagination is active and the optional
|
|
96
|
-
`searchValue` when connected to the search entry. Function args also include
|
|
97
|
-
an optional, non-enumerable `AbortSignal`; replacement requests abort the
|
|
98
|
-
prior signal without changing the established enumerable request keys, and
|
|
99
|
-
stale async responses are ignored even when a source does not honor it.
|
|
100
|
-
Rejections preserve the last committed rows and clear their automatic loading
|
|
101
|
-
state. `loading`, `loadingText`, `renderLoadMask`, and `onLoadingChange`
|
|
102
|
-
expose the effective lifecycle without unmounting replacement rows.
|
|
103
|
-
- **Local and remote data flow:** local arrays own local pagination. With
|
|
104
|
-
`pagination={true}`, every Promise/function result is an authoritative remote
|
|
105
|
-
page and is never sliced a second time. `pagination="local"` opts a
|
|
106
|
-
Promise/function source into local slicing; bare Promise arrays can also be
|
|
107
|
-
searched, filtered, and sorted when pagination is disabled or explicitly
|
|
108
|
-
local.
|
|
109
|
-
`filteredRowsCount` reports the post-search, post-filter count before local
|
|
110
|
-
page slicing.
|
|
111
|
-
- **Columns and cells:** stable `id`/`name` identity, controlled rendered order,
|
|
112
|
-
callback-driven drag reordering, explicit visibility, custom headers and cell
|
|
113
|
-
renderers, per-column sorting/filtering/search configuration, alignment, cell
|
|
114
|
-
classes/styles, and header props. Root `groups`, `column.group`, and nested
|
|
115
|
-
`groups[].group` render accessible stacked headers with automatic split/rejoin
|
|
116
|
-
segments, block dragging, and proportional min/max-clamped resizing.
|
|
117
|
-
- **Column and row sizing:** controlled `width`/`flex`, uncontrolled
|
|
118
|
-
`defaultWidth`/`defaultFlex`, `minWidth`/`maxWidth` clamps, proportional flex
|
|
119
|
-
allocation, the upstream 40px implicit column minimum (while preserving an
|
|
120
|
-
explicit `minWidth={0}`), deterministic autosizing from a bounded row sample,
|
|
121
|
-
mouse/pen/touch drag resizing with `onColumnResize`, opt-in
|
|
122
|
-
animation-frame-coalesced `liveColumnResize`, and double-click autosizing.
|
|
123
|
-
Rows support numeric, functional, and natural measured heights with
|
|
124
|
-
minimum/maximum bounds and width-change remeasurement.
|
|
125
|
-
- **Filtering and sorting:** inferred or explicitly controlled filter-row
|
|
126
|
-
visibility, uncontrolled local filters, externally owned controlled filter
|
|
127
|
-
state, custom filter registries and editors, filter operator menus, single
|
|
128
|
-
sorting, persistent array-valued multi-sorting, custom comparator registries
|
|
129
|
-
and sort tools, configurable initial direction, optional unsorting, and
|
|
130
|
-
configurable scroll reset behavior. Filter and sort changes reset pagination
|
|
131
|
-
to the first page.
|
|
132
|
-
- **Pagination:** controlled or uncontrolled `skip` and `limit`, local and remote
|
|
133
|
-
modes, configurable page sizes, a built-in accessible pager, an
|
|
134
|
-
Inovua-shaped `renderPaginationToolbar` contract, and reload/refresh/page
|
|
135
|
-
navigation helpers.
|
|
136
|
-
- **Selection:** single or multi-row selection, a configurable checkbox column,
|
|
137
|
-
controlled or uncontrolled selection maps, checkbox-only row selection,
|
|
138
|
-
Shift-range checkbox selection, and custom checkbox rendering.
|
|
139
|
-
- **Rendering modes:** fixed, per-row, or natural measured desktop row
|
|
140
|
-
virtualization, a non-virtual table path, sticky header and filter rows, and
|
|
141
|
-
an opt-in responsive virtual card layout at viewport widths up to 1024px. The
|
|
142
|
-
mobile layout retains cell renderers and selection while providing search,
|
|
143
|
-
sorting, and a hideable-column picker.
|
|
144
|
-
- **Row appearance and editing:** visible default zebra striping with a per-grid
|
|
145
|
-
toggle, data-dependent row styling, default/custom inline editors, click or
|
|
146
|
-
double-click activation, sync/async column editability, session-safe async
|
|
147
|
-
completion, cancellation, and keyboard traversal. Custom editors receive the
|
|
148
|
-
Inovua-shaped editor/cell contract, and the imperative API can start, inspect,
|
|
149
|
-
complete, or cancel an edit. Completing an edit reports the value;
|
|
150
|
-
applications remain responsible for persisting it to their data source. The
|
|
151
|
-
mobile card transform stays disabled whenever root or column-level editing is
|
|
152
|
-
enabled so the editing surface is never silently replaced.
|
|
153
|
-
- **Optional global search:** a separate tree-shakeable provider/bar/target
|
|
154
|
-
entry, normalized AND matching, column-scoped queries and aliases, nested or
|
|
155
|
-
derived search values, hidden-column search, a lazy cached local index, static
|
|
156
|
-
Promise search, and `searchValue` forwarding for remote functions.
|
|
157
|
-
- **Optional toolbar:** a separate provider/toolbar/target entry that
|
|
158
|
-
follows live grid order and visibility, honors non-hideable columns, protects
|
|
159
|
-
the final visible column, and accepts application actions on the right.
|
|
160
|
-
- **Themes and UI:** packaged CSS, shadcn-aligned controls, fixed
|
|
161
|
-
`default-light`/`light`, adaptive `default`, and fixed `dark` token bases,
|
|
162
|
-
custom `data-theme` hooks, grid-scoped menu portals, cell-border modes, i18n
|
|
163
|
-
overrides, and compatibility class hooks for existing Inovua-oriented theme
|
|
164
|
-
styles.
|
|
165
|
-
- **Imperative compatibility API:** `onDidMount`, `handle`, and `onReady`
|
|
166
|
-
expose the same stable `TypeComputedProps` ref with implemented data,
|
|
167
|
-
pagination, filtering, sorting, column lookup/order/visibility, selection, DOM
|
|
168
|
-
lookup, scrolling, loading, header/filter visibility, localization, editing,
|
|
169
|
-
and virtual-list helpers. `onDidMount` runs first from the passive mount
|
|
170
|
-
lifecycle; `getVirtualList().adjustHeights()` reads the instantiated
|
|
171
|
-
variable-height rows' DOM `scrollHeight` without registering extra resize
|
|
172
|
-
observers.
|
|
173
|
-
The editing subset includes `startEdit`, `tryStartEdit`, `completeEdit`,
|
|
174
|
-
`cancelEdit`, `getCurrentEditInfo`, `isInEdit`, and
|
|
175
|
-
`currentEditCompletePromise`. The API is explicit and behavior-backed;
|
|
176
|
-
unknown method-like properties resolve to `undefined`.
|
|
177
|
-
|
|
178
|
-
### Migration: data-transform ownership
|
|
179
|
-
|
|
180
|
-
This release makes one component responsible for each sort/page transform:
|
|
181
|
-
|
|
182
|
-
- A controlled `sortInfo` supplies indicators and callback/request state but
|
|
183
|
-
does not reorder a local array. Use `defaultSortInfo` for grid-owned local
|
|
184
|
-
sorting, or sort the rows in the parent before passing them to `dataSource`.
|
|
185
|
-
- With `pagination={true}` or `"remote"`, static Promise arrays and
|
|
186
|
-
`Promise<{ data, count }>` values are authoritative remote pages and are not
|
|
187
|
-
sliced a second time.
|
|
188
|
-
- Set `pagination="local"` to opt a Promise result into local slicing. Bare
|
|
189
|
-
Promise arrays also retain local search/filter/sort composition when
|
|
190
|
-
pagination is disabled.
|
|
191
|
-
|
|
192
|
-
These are intentional compatibility changes for consumers that relied on the
|
|
193
|
-
previous implicit transforms. They align the grid with React controlled-state
|
|
194
|
-
ownership, TanStack manual sorting/pagination, and Inovua 5.10.2. See the
|
|
195
|
-
[source-backed architecture evaluation](docs/inovua-parity-issues-32-37.md#architecture-evaluation-one-owner-per-transform)
|
|
196
|
-
for rationale and migration examples.
|
|
197
|
-
|
|
198
|
-
### Public package entries and exports
|
|
199
|
-
|
|
200
|
-
The main entry, `@geovi/the-datagrid`, exports:
|
|
201
|
-
|
|
202
|
-
- default and named `ReactDataGrid`, plus executable descriptors for the
|
|
203
|
-
built-in sorting, filtering, menu, and cell-selection plugins;
|
|
204
|
-
- `BoolEditor`, `DateEditor`, `NumericEditor`, `StringFilter`, `BoolFilter`,
|
|
205
|
-
`DateFilter`, `NumberFilter`, `SelectFilter`, `CheckBox`, and the named
|
|
206
|
-
`TextInput`;
|
|
207
|
-
- `DEFAULT_FILTER_TYPES` and its `filterTypes` alias;
|
|
208
|
-
- the public types `CellProps`, `IColumn`, `SortDirection`, `TypeColumn`,
|
|
209
|
-
`TypeColumns`, `TypeColumnEditorProps`, `TypeColumnResizeContext`,
|
|
210
|
-
`TypeColumnResizeInfo`, `TypeColumnEditorCell`, `TypeComputedColumn`,
|
|
211
|
-
`TypeComputedColumnsMap`, `TypeComputedProps`, `TypeDataGridProps`,
|
|
212
|
-
`TypeColumnGroup`, `TypeColumnGroupDOMProps`,
|
|
213
|
-
`TypeColumnGroupHeaderProps`, `TypeDataSourceArgs`, `TypeDataSource`,
|
|
214
|
-
`TypeDataSourceResult`,
|
|
215
|
-
`TypePaginationProps`, `TypeLoadMaskProps`, `TypeEditInfo`, `TypeStartEditArgs`,
|
|
216
|
-
`TypeTryStartEditArgs`, `TypeCompleteEditArgs`, `TypeCancelEditArgs`,
|
|
217
|
-
`TypeFilterOperator`, `TypeFilterType`, `TypeFilterTypes`, `TypeFilterValue`,
|
|
218
|
-
`TypeGetColumnByParam`, `TypeI18n`, `TypeOnSelectionChangeArg`,
|
|
219
|
-
`TypePaginationMode`, `TypeRowSelection`, `TypeRowStyle`, `TypeRowStyleArgs`,
|
|
220
|
-
`TypeRowStyleProps`, `TypeShowCellBorders`, `TypeSize`, `TypeSingleFilterValue`,
|
|
221
|
-
`TypeSingleSortInfo`, `TypeSortInfo`, `TypeSortFunction`,
|
|
222
|
-
`TypeSortFunctions`, `TypeColumnSort`, `TypeSortToolProps`,
|
|
223
|
-
`TypeRenderSortTool`, `TypeCheckboxColumn`, `TypeCheckboxProps`,
|
|
224
|
-
`TextInputProps`, `TypeTextInputProps`, and the TextInput
|
|
225
|
-
callback/input/wrapper/clear-button helper types.
|
|
226
|
-
|
|
227
|
-
The same editors and filters are available through their documented deep
|
|
228
|
-
imports. `@geovi/the-datagrid/types` and the documented
|
|
229
|
-
`@geovi/the-datagrid/types/Type*` paths expose the migration type vocabulary.
|
|
230
|
-
The main and Community compatibility entries publish both ESM and CommonJS.
|
|
231
|
-
|
|
232
|
-
The optional `@geovi/the-datagrid/search` entry exports `RDGSearchProvider`,
|
|
233
|
-
`RDGSearchBar`, `RDGSearchTarget`, and their prop types. The explicit stylesheet
|
|
234
|
-
fallbacks include `@geovi/the-datagrid/index.css`,
|
|
235
|
-
`@geovi/the-datagrid/base.css`, every documented default/amber/blue/green/pink
|
|
236
|
-
light/dark theme path, and `@geovi/the-datagrid/search/style.css`.
|
|
237
|
-
|
|
238
|
-
The optional `@geovi/the-datagrid/components` entry is the one-import choice for
|
|
239
|
-
mixed contextual controls. It exports `RDGProvider`, `RDGTarget`,
|
|
240
|
-
`RDGSearchBar`, `RDGToolbar`, all four stable feature-specific
|
|
241
|
-
provider/target APIs, and their prop types. It reuses the existing search and
|
|
242
|
-
toolbar singleton contexts and automatically loads both isolated
|
|
243
|
-
stylesheets; there is intentionally no duplicate `components/style.css`.
|
|
244
|
-
|
|
245
|
-
The optional `@geovi/the-datagrid/toolbar` entry exports
|
|
246
|
-
`RDGToolbarProvider`, `RDGToolbar`, `RDGToolbarTarget`, and their prop types.
|
|
247
|
-
Its explicit stylesheet fallback is
|
|
248
|
-
`@geovi/the-datagrid/toolbar/style.css`.
|
|
249
|
-
|
|
250
|
-
The Inovua-compatible standalone input remains a default class export at
|
|
251
|
-
`@geovi/the-datagrid/packages/TextInput`. That deep entry loads the packaged
|
|
252
|
-
standalone styles, does not load the grid runtime, and preserves `focus()` /
|
|
253
|
-
`setValue()` instance refs.
|
|
254
|
-
|
|
255
|
-
### Runtime defaults and filter registry
|
|
256
|
-
|
|
257
|
-
Both the default and named grid exports expose `ReactDataGrid.defaultProps` for
|
|
258
|
-
Inovua-shaped integrations that inspect or extend runtime defaults. It contains
|
|
259
|
-
the shipped theme, filtering, autosize, resize, virtualization, mobile,
|
|
260
|
-
selection-text, border, menu, and row/header/filter-height defaults, including
|
|
261
|
-
the default filter registry.
|
|
262
|
-
|
|
263
|
-
That registry ships string operators (`contains`, `notContains`, `containsOr`,
|
|
264
|
-
`eq`, `neq`, `empty`, `notEmpty`, `startsWith`, and `endsWith`), select
|
|
265
|
-
operators (`inlist`, `notinlist`, `eq`, and `neq`), boolean equality operators,
|
|
266
|
-
number comparison/range operators, and date/time comparison/range operators.
|
|
267
|
-
Operator definitions can opt into empty-value filtering, initialize a value
|
|
268
|
-
when selected, or disable the editor for value-free operations.
|
|
269
|
-
|
|
270
|
-
Unseeded `bool` and `boolean` filters default to `eq`, matching their shipped
|
|
271
|
-
operator registry. Other defaults are `contains` for strings, `gte` for
|
|
272
|
-
numbers, `eq` for selects, and `afterOrOn` for date/time values.
|
|
273
|
-
|
|
274
|
-
Custom filter types are shallow-merged by registry key with the built-ins:
|
|
275
|
-
|
|
276
|
-
```tsx
|
|
277
|
-
import ReactDataGrid, { type TypeFilterTypes } from "@geovi/the-datagrid";
|
|
278
|
-
|
|
279
|
-
const filterTypes: TypeFilterTypes = {
|
|
280
|
-
...ReactDataGrid.defaultProps.filterTypes,
|
|
281
|
-
status: {
|
|
282
|
-
type: "status",
|
|
283
|
-
emptyValue: null,
|
|
284
|
-
operators: [
|
|
285
|
-
{
|
|
286
|
-
name: "eq",
|
|
287
|
-
fn: ({ value, filterValue }) =>
|
|
288
|
-
filterValue == null || value === filterValue,
|
|
289
|
-
},
|
|
290
|
-
],
|
|
291
|
-
},
|
|
292
|
-
};
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
## Installation
|
|
20
|
+
## Install
|
|
296
21
|
|
|
297
22
|
```bash
|
|
298
23
|
npm install @geovi/the-datagrid react react-dom
|
|
299
|
-
# or
|
|
300
|
-
yarn add @geovi/the-datagrid react react-dom
|
|
301
|
-
# or
|
|
302
|
-
pnpm add @geovi/the-datagrid react react-dom
|
|
303
24
|
```
|
|
304
25
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
The peer contract supports React and React DOM 16.8, 17, 18, and 19. The
|
|
308
|
-
published-package compatibility matrix installs the packed tarball against an
|
|
309
|
-
exact version from every supported major, compiles its declarations, and mounts
|
|
310
|
-
the core grid, optional providers, mobile layout, and menu interactions. React
|
|
311
|
-
16/17 use the package's official external-store shim and compatibility fallbacks
|
|
312
|
-
for newer React hooks.
|
|
313
|
-
|
|
314
|
-
The shipped JavaScript already bundles the tested Radix, TanStack, icon, and
|
|
315
|
-
utility implementations, so consumers do not install a second, independently
|
|
316
|
-
resolved UI dependency graph. Those packages remain development dependencies
|
|
317
|
-
for building the library; the official external-store shim is the only runtime
|
|
318
|
-
dependency in the published manifest.
|
|
319
|
-
|
|
320
|
-
You do **not** need to install:
|
|
321
|
-
|
|
322
|
-
- Tailwind CSS
|
|
323
|
-
- shadcn/ui
|
|
324
|
-
- a separate package stylesheet import in normal app setups
|
|
325
|
-
|
|
326
|
-
This also applies when you use custom grid themes. The grid theme variables are plain CSS variables in the shipped stylesheet, so consumers do not need Tailwind just to use `theme="dark"`, `theme="hf-dark"`, or their own imported grid theme CSS.
|
|
327
|
-
|
|
328
|
-
## Styling
|
|
329
|
-
|
|
330
|
-
`@geovi/the-datagrid` ships compiled CSS and loads it automatically from the package entry.
|
|
331
|
-
|
|
332
|
-
In a typical React app with a modern bundler, this is enough:
|
|
333
|
-
|
|
334
|
-
- Vite
|
|
335
|
-
- Next.js
|
|
336
|
-
- Webpack-based apps
|
|
337
|
-
- other setups that support CSS imports from npm packages
|
|
338
|
-
|
|
339
|
-
The grid keeps a shadcn-aligned look and uses the same token vocabulary
|
|
340
|
-
(`--background`, `--foreground`, `--border`, `--ring`, etc.). The adaptive
|
|
341
|
-
`theme="default"` inherits those app-level variables, while fixed theme bases
|
|
342
|
-
and explicit `--tdg-*` custom-theme tokens stay scoped to the grid. Packaged
|
|
343
|
-
fallbacks keep the grid usable when an app does not define shadcn variables.
|
|
344
|
-
|
|
345
|
-
Theme variables are resolved at runtime from normal CSS, not from the consumer's Tailwind build. Tailwind is only used to build this library, not required to consume it.
|
|
346
|
-
|
|
347
|
-
Built-in theme behavior:
|
|
348
|
-
|
|
349
|
-
- `theme="default-light"` is the default and keeps a fixed shadcn light token
|
|
350
|
-
base—even below a `.dark` application ancestor—while preserving the
|
|
351
|
-
Inovua-compatible theme name on the grid root
|
|
352
|
-
- `theme="default"` follows the nearest `.dark` ancestor
|
|
353
|
-
- `theme="light"` forces the light token set
|
|
354
|
-
- `theme="dark"` forces the dark token set
|
|
355
|
-
- `theme="<custom-name>"` activates a named custom theme on the grid root via `data-theme="<custom-name>"`
|
|
356
|
-
|
|
357
|
-
The fixed light base remains customizable through the documented
|
|
358
|
-
`--tdg-color-*` and component-level `--tdg-*` variables. A custom named theme
|
|
359
|
-
can therefore opt into a `-light` suffix without losing its own explicit grid
|
|
360
|
-
tokens.
|
|
361
|
-
|
|
362
|
-
For non-built-in theme names, the grid also keeps Inovua-compatible root and
|
|
363
|
-
element class hooks. When a readable legacy Inovua stylesheet for that theme is
|
|
364
|
-
already loaded, the runtime maps its grid, text-input, combo-box, and menu
|
|
365
|
-
colors into the corresponding `--tdg-*` tokens. This bridge helps existing
|
|
366
|
-
themes migrate incrementally; it is browser-only, ignores unreadable or
|
|
367
|
-
late-loaded stylesheets, and does not reproduce legacy layout CSS. Defining the
|
|
368
|
-
grid tokens directly remains the deterministic long-term path.
|
|
369
|
-
|
|
370
|
-
If your environment does **not** process CSS imported from package entries, use the exported fallback once in your app:
|
|
371
|
-
|
|
372
|
-
```ts
|
|
373
|
-
import "@geovi/the-datagrid/style.css";
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
### Custom named themes
|
|
377
|
-
|
|
378
|
-
Named themes are configured with CSS variables on the grid root selector. For example, this custom `hf-dark` theme can be used with `theme="hf-dark"`:
|
|
379
|
-
|
|
380
|
-
```css
|
|
381
|
-
.tdg-root[data-theme="hf-dark"] {
|
|
382
|
-
--tdg-color-background: #191919;
|
|
383
|
-
--tdg-color-foreground: #e5e5e5;
|
|
384
|
-
--tdg-color-accent: #26324a;
|
|
385
|
-
--tdg-grid-bg: #191919;
|
|
386
|
-
--tdg-header-bg: #1e1e1e;
|
|
387
|
-
--tdg-grid-border-color: #2c2c2c;
|
|
388
|
-
--tdg-cell-border-color: #2c2c2c;
|
|
389
|
-
--tdg-header-border-color: #2c2c2c;
|
|
390
|
-
--tdg-row-odd-bg: #191919;
|
|
391
|
-
--tdg-row-even-bg: #191919;
|
|
392
|
-
--tdg-row-odd-hover-bg: #26324a;
|
|
393
|
-
--tdg-row-even-hover-bg: #26324a;
|
|
394
|
-
--tdg-row-selected-bg: #1a2740;
|
|
395
|
-
--tdg-row-selected-hover-bg: #1a2740;
|
|
396
|
-
--tdg-input-bg: #191919;
|
|
397
|
-
--tdg-input-border-color: #383838;
|
|
398
|
-
--tdg-input-border-color-hover: #383838;
|
|
399
|
-
--tdg-input-border-color-focus: #383838;
|
|
400
|
-
--tdg-select-bg: #191919;
|
|
401
|
-
--tdg-select-list-bg: #191919;
|
|
402
|
-
--tdg-select-border-color: #383838;
|
|
403
|
-
--tdg-select-border-color-hover: #383838;
|
|
404
|
-
--tdg-select-border-color-focus: #383838;
|
|
405
|
-
--tdg-select-item-hover-bg: #26324a;
|
|
406
|
-
--tdg-select-item-selected-bg: #26324a;
|
|
407
|
-
--tdg-checkbox-checked-bg: #688ad7;
|
|
408
|
-
--tdg-checkbox-checked-color: #e5e5e5;
|
|
409
|
-
--tdg-checkbox-indeterminate-bg: #688ad7;
|
|
410
|
-
color-scheme: dark;
|
|
411
|
-
}
|
|
412
|
-
```
|
|
413
|
-
|
|
414
|
-
This lets you keep using a migration-friendly theme name such as `hf-dark` while mapping it to the grid’s internal theme tokens.
|
|
415
|
-
|
|
416
|
-
The example assigns identical odd/even row colors, which intentionally
|
|
417
|
-
suppresses visible striping for that custom theme. Built-in themes show zebra
|
|
418
|
-
rows by default; `showZebraRows={false}` disables them for one grid, while
|
|
419
|
-
`--tdg-row-odd-bg` and `--tdg-row-even-bg` customize their theme colors.
|
|
420
|
-
|
|
421
|
-
---
|
|
26
|
+
React 16.8 through 19 is supported. Package styles load automatically in modern
|
|
27
|
+
bundlers.
|
|
422
28
|
|
|
423
|
-
##
|
|
29
|
+
## Quick start
|
|
424
30
|
|
|
425
31
|
```tsx
|
|
426
|
-
import {
|
|
427
|
-
import type { TypeColumns } from "@geovi/the-datagrid";
|
|
32
|
+
import ReactDataGrid, { type TypeColumns } from "@geovi/the-datagrid";
|
|
428
33
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
];
|
|
435
|
-
|
|
436
|
-
const rows = [
|
|
437
|
-
{ id: 1, name: "John Doe", email: "john@example.com" },
|
|
438
|
-
{ id: 2, name: "Jane Smith", email: "jane@example.com" },
|
|
439
|
-
];
|
|
440
|
-
|
|
441
|
-
return (
|
|
442
|
-
<ReactDataGrid
|
|
443
|
-
idProperty="id"
|
|
444
|
-
columns={columns}
|
|
445
|
-
dataSource={rows}
|
|
446
|
-
virtualized
|
|
447
|
-
enableFiltering
|
|
448
|
-
defaultFilterValue={[
|
|
449
|
-
{ name: "id", type: "number", operator: "eq", value: null },
|
|
450
|
-
{ name: "name", type: "string", operator: "contains", value: "" },
|
|
451
|
-
{ name: "email", type: "string", operator: "contains", value: "" },
|
|
452
|
-
]}
|
|
453
|
-
/>
|
|
454
|
-
);
|
|
455
|
-
}
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
## Combined contextual controls
|
|
459
|
-
|
|
460
|
-
Use one `RDGProvider` when search and the toolbar control the same grid.
|
|
461
|
-
A direct grid child connects automatically:
|
|
462
|
-
|
|
463
|
-
```tsx
|
|
464
|
-
import ReactDataGrid from "@geovi/the-datagrid";
|
|
465
|
-
import {
|
|
466
|
-
RDGToolbar,
|
|
467
|
-
RDGProvider,
|
|
468
|
-
RDGSearchBar,
|
|
469
|
-
} from "@geovi/the-datagrid/components";
|
|
470
|
-
|
|
471
|
-
<RDGProvider>
|
|
472
|
-
<RDGSearchBar />
|
|
473
|
-
<RDGToolbar showExport showFilterToggle />
|
|
474
|
-
<ReactDataGrid idProperty="id" columns={columns} dataSource={rows} />
|
|
475
|
-
</RDGProvider>;
|
|
476
|
-
```
|
|
477
|
-
|
|
478
|
-
If a `div`, card, Fragment, Suspense boundary, or application component sits
|
|
479
|
-
between the provider and grid, put one `RDGTarget` immediately around the grid.
|
|
480
|
-
`RDGProvider` and `RDGTarget` add no DOM elements and support one grid per
|
|
481
|
-
provider scope. Use `defaultSearchValue` when the shared search query needs a
|
|
482
|
-
non-empty initial value. Do not nest `RDGSearchTarget` and
|
|
483
|
-
`RDGToolbarTarget`; use the combined target instead.
|
|
484
|
-
|
|
485
|
-
Controls imported from `@geovi/the-datagrid/search` and
|
|
486
|
-
`@geovi/the-datagrid/toolbar` also work inside `RDGProvider`. The
|
|
487
|
-
existing `RDGSearchProvider`, `RDGSearchTarget`,
|
|
488
|
-
`RDGToolbarProvider`, and `RDGToolbarTarget` exports remain
|
|
489
|
-
supported and are not deprecated.
|
|
490
|
-
|
|
491
|
-
## Optional table search
|
|
492
|
-
|
|
493
|
-
Global search is intentionally separate from the main component entry. A plain
|
|
494
|
-
`ReactDataGrid` does not render a search control, subscribe to search context,
|
|
495
|
-
or load the optional provider, store, or search stylesheet. The optional entry
|
|
496
|
-
reuses the same core search field and search engine already used by the mobile
|
|
497
|
-
layout, so search-enabled screens do not ship a second implementation. Import
|
|
498
|
-
the provider and bar only on screens that need them:
|
|
34
|
+
const columns: TypeColumns = [
|
|
35
|
+
{ name: "id", header: "ID", sortable: true },
|
|
36
|
+
{ name: "name", header: "Name", sortable: true, filterable: true },
|
|
37
|
+
{ name: "email", header: "Email", filterable: true },
|
|
38
|
+
];
|
|
499
39
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
40
|
+
const rows = [
|
|
41
|
+
{ id: 1, name: "Ada Lovelace", email: "ada@example.com" },
|
|
42
|
+
{ id: 2, name: "Grace Hopper", email: "grace@example.com" },
|
|
43
|
+
];
|
|
503
44
|
|
|
504
|
-
export function
|
|
45
|
+
export function UsersGrid() {
|
|
505
46
|
return (
|
|
506
|
-
<
|
|
507
|
-
<RDGSearchBar />
|
|
47
|
+
<div style={{ height: 480 }}>
|
|
508
48
|
<ReactDataGrid
|
|
509
49
|
idProperty="id"
|
|
510
50
|
columns={columns}
|
|
511
51
|
dataSource={rows}
|
|
52
|
+
enableFiltering
|
|
512
53
|
virtualized
|
|
513
54
|
/>
|
|
514
|
-
</
|
|
55
|
+
</div>
|
|
515
56
|
);
|
|
516
57
|
}
|
|
517
58
|
```
|
|
518
59
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
60
|
+
## Search and toolbar
|
|
61
|
+
|
|
62
|
+
The optional components entry adds search, column visibility, filters, and
|
|
63
|
+
export without increasing the core grid API:
|
|
522
64
|
|
|
523
65
|
```tsx
|
|
524
66
|
import {
|
|
67
|
+
RDGProvider,
|
|
525
68
|
RDGSearchBar,
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
} from "@geovi/the-datagrid/search";
|
|
69
|
+
RDGToolbar,
|
|
70
|
+
} from "@geovi/the-datagrid/components";
|
|
529
71
|
|
|
530
|
-
<
|
|
72
|
+
<RDGProvider>
|
|
531
73
|
<RDGSearchBar />
|
|
532
|
-
<
|
|
533
|
-
<RDGSearchTarget>
|
|
534
|
-
<ReactDataGrid idProperty="id" columns={columns} dataSource={rows} />
|
|
535
|
-
</RDGSearchTarget>
|
|
536
|
-
</section>
|
|
537
|
-
</RDGSearchProvider>;
|
|
538
|
-
```
|
|
539
|
-
|
|
540
|
-
See [Providers and targets](https://geo-vi.github.io/the-datagrid/docs/reference/providers-and-targets)
|
|
541
|
-
for the exact direct-child rule, Fragment and Suspense boundaries, and
|
|
542
|
-
multiple-grid scoping.
|
|
543
|
-
|
|
544
|
-
The normal-table bar and transformed-mobile search are two placements of the
|
|
545
|
-
same internal component. They use the same shadcn-style Input and Button,
|
|
546
|
-
column-prefix highlighting, IME handling, Escape behavior, and clear/refocus
|
|
547
|
-
interaction. Local arrays and bare Promise snapshots under disabled/explicitly
|
|
548
|
-
local pagination also use the same normalization and matching engine. Function
|
|
549
|
-
data sources receive the committed `searchValue` and remain responsible for
|
|
550
|
-
remote matching. When
|
|
551
|
-
`allowMobileTransform` is active under `RDGSearchProvider`, the external
|
|
552
|
-
placement remains the single search control; the mobile list suppresses only
|
|
553
|
-
its duplicate placement while keeping its sort and column tools.
|
|
554
|
-
|
|
555
|
-
`RDGSearchBar` uses the accessible label `Search all fields`, the placeholder
|
|
556
|
-
`Search all fields`, and a 150 ms provider commit debounce by default. Set
|
|
557
|
-
`debounceMs={0}` for an immediate remote/local commit or pass another delay.
|
|
558
|
-
The input interaction itself is shared with mobile. Terms are matched with AND
|
|
559
|
-
semantics after case, whitespace, and diacritic normalization. Prefix a query
|
|
560
|
-
with a column id, name, string header, or configured alias to scope it, for
|
|
561
|
-
example `city:paris`.
|
|
562
|
-
|
|
563
|
-
Column-level search configuration stays on `TypeColumn` rather than adding new
|
|
564
|
-
`ReactDataGrid` props. Configured columns remain searchable when hidden; use
|
|
565
|
-
`searchable: false` for an explicit exclusion:
|
|
566
|
-
|
|
567
|
-
```tsx
|
|
568
|
-
const columns: TypeColumns = [
|
|
569
|
-
{
|
|
570
|
-
name: "city",
|
|
571
|
-
header: "Office city",
|
|
572
|
-
searchAliases: ["location", "office"],
|
|
573
|
-
},
|
|
574
|
-
{
|
|
575
|
-
name: "customer",
|
|
576
|
-
searchValue: (row) => [row.customer.name, row.customer.reference],
|
|
577
|
-
},
|
|
578
|
-
{ name: "internalNote", searchable: false },
|
|
579
|
-
];
|
|
580
|
-
```
|
|
581
|
-
|
|
582
|
-
For local data, the normalized search index is built lazily on the first
|
|
583
|
-
committed query and reused while the row and column arrays keep the same
|
|
584
|
-
identity. Update rows and column configuration immutably so changed searchable
|
|
585
|
-
content naturally invalidates that cache.
|
|
586
|
-
|
|
587
|
-
The optional entry loads its own scoped stylesheet. If your environment does
|
|
588
|
-
not process package CSS imports, add
|
|
589
|
-
`import "@geovi/the-datagrid/search/style.css"` beside the manual grid
|
|
590
|
-
stylesheet import.
|
|
591
|
-
|
|
592
|
-
For local arrays, search is combined with column filters before local
|
|
593
|
-
pagination and `filteredRowsCount` reports the combined result count. A bare
|
|
594
|
-
static Promise array is locally searchable when pagination is disabled or
|
|
595
|
-
explicitly `"local"`. With `pagination={true}`/`"remote"`, either Promise
|
|
596
|
-
result shape is authoritative and is not post-filtered or sliced. A function
|
|
597
|
-
data source remains remote and receives `searchValue` alongside its existing
|
|
598
|
-
args; when remote pagination is active, a new search resets `skip` to `0`.
|
|
599
|
-
|
|
600
|
-
```tsx
|
|
601
|
-
import type { TypeDataSourceArgs } from "@geovi/the-datagrid";
|
|
602
|
-
|
|
603
|
-
const dataSource = async ({
|
|
604
|
-
searchValue,
|
|
605
|
-
signal,
|
|
606
|
-
...gridArgs
|
|
607
|
-
}: TypeDataSourceArgs) => {
|
|
608
|
-
const response = await fetch("/api/accounts/search", {
|
|
609
|
-
method: "POST",
|
|
610
|
-
headers: { "content-type": "application/json" },
|
|
611
|
-
body: JSON.stringify({ ...gridArgs, searchValue }),
|
|
612
|
-
signal,
|
|
613
|
-
});
|
|
614
|
-
|
|
615
|
-
return response.json();
|
|
616
|
-
};
|
|
617
|
-
```
|
|
618
|
-
|
|
619
|
-
Remote functions own the search operation. The grid does not post-filter one
|
|
620
|
-
remote page and present it as a server-wide result. If the backend does not yet
|
|
621
|
-
support global search, keep that search state application-owned until its
|
|
622
|
-
request contract is defined.
|
|
623
|
-
|
|
624
|
-
## Optional grid toolbar
|
|
625
|
-
|
|
626
|
-
Grid toolbar controls are also an opt-in contextual entry. A direct grid child
|
|
627
|
-
connects automatically. Column toggles always render; export, filter-row and
|
|
628
|
-
clear-filter buttons are opt-in props, and toolbar children stay a separate
|
|
629
|
-
right-side action area for consumer-owned controls:
|
|
630
|
-
|
|
631
|
-
```tsx
|
|
632
|
-
import ReactDataGrid from "@geovi/the-datagrid";
|
|
633
|
-
import { RDGToolbarProvider, RDGToolbar } from "@geovi/the-datagrid/toolbar";
|
|
634
|
-
|
|
635
|
-
<RDGToolbarProvider>
|
|
636
|
-
<RDGToolbar showExport showFilterToggle showClearFilters>
|
|
637
|
-
<button type="button" onClick={reload}>
|
|
638
|
-
Reload
|
|
639
|
-
</button>
|
|
640
|
-
</RDGToolbar>
|
|
74
|
+
<RDGToolbar showExport showFilterToggle showClearFilters />
|
|
641
75
|
<ReactDataGrid idProperty="id" columns={columns} dataSource={rows} />
|
|
642
|
-
</
|
|
76
|
+
</RDGProvider>;
|
|
643
77
|
```
|
|
644
78
|
|
|
645
|
-
`
|
|
646
|
-
XLSX. Spreadsheet output needs the optional `xlsx` peer dependency:
|
|
79
|
+
Install `xlsx` only when workbook export is needed:
|
|
647
80
|
|
|
648
81
|
```bash
|
|
649
82
|
npm install xlsx
|
|
650
83
|
```
|
|
651
84
|
|
|
652
|
-
|
|
653
|
-
size of the toolbar entry, and it is imported on demand the first time somebody
|
|
654
|
-
exports a workbook. Values keep their JavaScript type on the way into a
|
|
655
|
-
workbook, so numbers stay summable, `Date` values become date cells carrying
|
|
656
|
-
`exportDateFormat`, and booleans become `TRUE`/`FALSE`; text formats stringify
|
|
657
|
-
the same values and write dates as ISO-8601. `exportDateFormat` is an Excel
|
|
658
|
-
number format code rather than a date-library pattern, `exportSheetName` names
|
|
659
|
-
the worksheet, and the two callbacks report the outcome: `onExportSuccess`
|
|
660
|
-
receives the format, scope, row and column counts, file name and byte size,
|
|
661
|
-
which is enough for a confirmation toast, while `onExportError` reports a
|
|
662
|
-
failure such as a missing peer dependency.
|
|
663
|
-
|
|
664
|
-
`exportScope` selects the rows: `"view"` (default) exports the filtered,
|
|
665
|
-
searched and sorted rows, `"all"` the entire data source. Under local pagination
|
|
666
|
-
the grid holds a single page, so `"view"` exports that page. `exportFormats`,
|
|
667
|
-
`exportFileName` and `labels` cover the rest; with exactly one format the button
|
|
668
|
-
exports on click instead of opening a menu.
|
|
669
|
-
|
|
670
|
-
Every string the toolbar renders itself comes from `labels`, as a string or an
|
|
671
|
-
element, so a translation helper can supply all of them:
|
|
672
|
-
|
|
673
|
-
```tsx
|
|
674
|
-
<RDGToolbar
|
|
675
|
-
showExport
|
|
676
|
-
showFilterToggle
|
|
677
|
-
showClearFilters
|
|
678
|
-
labels={{
|
|
679
|
-
export: t("export"),
|
|
680
|
-
showFilters: t("show_filters"),
|
|
681
|
-
hideFilters: t("hide_filters"),
|
|
682
|
-
clearFilters: t("clear_filters"),
|
|
683
|
-
columns: t("columns"),
|
|
684
|
-
|
|
685
|
-
// Menu entry per format; an unnamed format keeps its own name.
|
|
686
|
-
exportFormats: { csv: t("csv"), xlsx: t("excel") },
|
|
687
|
-
|
|
688
|
-
// Whole button text when one format is offered. The default joins
|
|
689
|
-
// `export` and the format name in that order ("Export CSV"), which a
|
|
690
|
-
// translation file cannot reorder - set this for "CSV exportieren".
|
|
691
|
-
exportSingle: { csv: t("export_csv") },
|
|
692
|
-
}}
|
|
693
|
-
/>
|
|
694
|
-
```
|
|
695
|
-
|
|
696
|
-
`title`, `description` and `ariaLabel` are separate props and take the same
|
|
697
|
-
treatment; column toggles read each column's `header`. The export menu is named
|
|
698
|
-
after its own trigger, so a translated label needs no second string.
|
|
699
|
-
|
|
700
|
-
At widths up to `1024px`, the toolbar automatically replaces the wrapping row
|
|
701
|
-
of column buttons with one `Columns` dropdown. The menu contains the same
|
|
702
|
-
hideable columns in grid order, stays open while several columns are toggled,
|
|
703
|
-
and keeps the rule that the final visible column cannot be hidden. Set
|
|
704
|
-
`toolbarCollapsedColumnToggles` to force the dropdown at every width, or set
|
|
705
|
-
`disableMobileAutoToolbarCollapsedColumns` to keep the buttons inline on
|
|
706
|
-
mobile. Override `labels.columns` to localize the trigger:
|
|
707
|
-
|
|
708
|
-
```tsx
|
|
709
|
-
<RDGToolbar toolbarCollapsedColumnToggles labels={{ columns: t("columns") }} />
|
|
710
|
-
|
|
711
|
-
<RDGToolbar disableMobileAutoToolbarCollapsedColumns />
|
|
712
|
-
```
|
|
713
|
-
|
|
714
|
-
Set `collapsible` when a dense screen should show only one right-aligned control
|
|
715
|
-
until the toolbar is needed. The card surface, border, shadow and spacing collapse
|
|
716
|
-
fully into that disclosure button, then expand left and down from it; column,
|
|
717
|
-
filter and export state remain mounted while it is closed. Override
|
|
718
|
-
`labels.showToolbar` and
|
|
719
|
-
`labels.hideToolbar` to localize the disclosure:
|
|
720
|
-
|
|
721
|
-
```tsx
|
|
722
|
-
<RDGToolbar
|
|
723
|
-
collapsible
|
|
724
|
-
showExport
|
|
725
|
-
showFilterToggle
|
|
726
|
-
showClearFilters
|
|
727
|
-
labels={{
|
|
728
|
-
showToolbar: t("show_table_controls"),
|
|
729
|
-
hideToolbar: t("hide_table_controls"),
|
|
730
|
-
}}
|
|
731
|
-
/>
|
|
732
|
-
```
|
|
733
|
-
|
|
734
|
-
Export reads row values, never `render`, which returns React nodes. Columns
|
|
735
|
-
describe their own exported shape:
|
|
736
|
-
|
|
737
|
-
```tsx
|
|
738
|
-
const columns: TypeColumns = [
|
|
739
|
-
{ name: "id", header: "ID" },
|
|
740
|
-
|
|
741
|
-
// render returns a React node, so export needs its own value.
|
|
742
|
-
{
|
|
743
|
-
name: "active",
|
|
744
|
-
header: "Active",
|
|
745
|
-
render: ({ value }) => <StatusPill active={value} />,
|
|
746
|
-
exportValue: ({ value }) => (value ? "Yes" : "No"),
|
|
747
|
-
},
|
|
748
|
-
|
|
749
|
-
// Hidden in the grid, still written to the file.
|
|
750
|
-
{
|
|
751
|
-
name: "auditId",
|
|
752
|
-
header: "Audit ID",
|
|
753
|
-
defaultVisible: false,
|
|
754
|
-
exportWhenHidden: true,
|
|
755
|
-
},
|
|
756
|
-
|
|
757
|
-
// Row buttons have no exportable representation.
|
|
758
|
-
{ name: "actions", header: "Actions", exportable: false },
|
|
759
|
-
];
|
|
760
|
-
```
|
|
761
|
-
|
|
762
|
-
Only visible columns are exported unless a column sets `exportWhenHidden`, and
|
|
763
|
-
`exportable: false` always wins. `showFilterToggle` drives the grid's own
|
|
764
|
-
filter-row state, so it renders disabled while `enableFiltering` is passed as a
|
|
765
|
-
controlled prop; `showClearFilters` calls `clearAllFilters` and stays disabled
|
|
766
|
-
while nothing is filtered.
|
|
85
|
+
## Learn more
|
|
767
86
|
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
visible column to be hidden. Button state is exposed through `aria-pressed`; no
|
|
772
|
-
eye icon or parallel application visibility state is required.
|
|
87
|
+
- [Examples and API documentation](https://geo-vi.github.io/the-datagrid/)
|
|
88
|
+
- [Inovua migration contract](https://geo-vi.github.io/the-datagrid/docs/migration/inovua-compat)
|
|
89
|
+
- [Implemented compatibility status](https://geo-vi.github.io/the-datagrid/docs/migration/inovua-status)
|
|
773
90
|
|
|
774
|
-
|
|
775
|
-
legacy `defaultHidden: true` alias on a column that should start hidden.
|
|
776
|
-
`hideable: false` disables menu/toolbar toggles but does not block the
|
|
777
|
-
imperative API. `onColumnVisibleChange({ column, visible })` receives every
|
|
778
|
-
effective proposal. A declarative `visible` value remains authoritative until
|
|
779
|
-
the parent applies that proposal; otherwise the grid persists the change in
|
|
780
|
-
its own runtime state.
|
|
781
|
-
|
|
782
|
-
The default title is a level-two heading that labels the toolbar region. The
|
|
783
|
-
toggle group keeps its `ariaLabel`, and the description is associated with both
|
|
784
|
-
through `aria-describedby`. Passing `title={null}` suppresses the heading while
|
|
785
|
-
preserving the group's accessible name.
|
|
786
|
-
|
|
787
|
-
### Styling the toolbar
|
|
788
|
-
|
|
789
|
-
The toolbar carries no utility classes: every visual decision is a
|
|
790
|
-
`--tdg-toolbar-*` custom property, so restyling means redeclaring tokens on
|
|
791
|
-
`.tdg-toolbar-root` or any ancestor.
|
|
792
|
-
|
|
793
|
-
```css
|
|
794
|
-
.tdg-toolbar-root {
|
|
795
|
-
--tdg-toolbar-padding: 0;
|
|
796
|
-
--tdg-toolbar-radius: 0;
|
|
797
|
-
--tdg-toolbar-border-width: 0;
|
|
798
|
-
--tdg-toolbar-shadow: none;
|
|
799
|
-
|
|
800
|
-
--tdg-toolbar-toggle-gap: 3px;
|
|
801
|
-
--tdg-toolbar-control-padding: 6px 8px;
|
|
802
|
-
--tdg-toolbar-control-radius: 4px;
|
|
803
|
-
--tdg-toolbar-control-height: auto;
|
|
804
|
-
--tdg-toolbar-control-cursor: pointer;
|
|
805
|
-
|
|
806
|
-
/* Export and clear-filters. */
|
|
807
|
-
--tdg-toolbar-action-fill: #eef1f5;
|
|
808
|
-
--tdg-toolbar-action-color: #12263f;
|
|
809
|
-
|
|
810
|
-
/* A released toggle, filled here rather than recessed. */
|
|
811
|
-
--tdg-toolbar-toggle-off-fill: #eef1f5;
|
|
812
|
-
--tdg-toolbar-toggle-off-color: #5b6b7f;
|
|
813
|
-
|
|
814
|
-
/* A pressed toggle, and export while its menu is open. */
|
|
815
|
-
--tdg-toolbar-toggle-on-fill: #1a73e8;
|
|
816
|
-
--tdg-toolbar-toggle-on-color: #ffffff;
|
|
817
|
-
}
|
|
818
|
-
```
|
|
819
|
-
|
|
820
|
-
The three appearances differ by one signal each: an action keeps its border, a
|
|
821
|
-
released toggle drops it and dims the label, a pressed toggle keeps it over an
|
|
822
|
-
opaque `card` fill. Hover only changes the fill, so it never reads as a state.
|
|
823
|
-
|
|
824
|
-
Colour tokens fall back through `--tdg-color-*` and then the shadcn variable of
|
|
825
|
-
the same name, so a themed application inherits sensible values without setting
|
|
826
|
-
anything. Bridging another design system - BaseUI, MUI, a styled-components
|
|
827
|
-
theme - means assigning its values to these tokens once, on a wrapper element.
|
|
828
|
-
|
|
829
|
-
A grid theme named `*-dark` or `*-light` is the exception: it states a mode, so
|
|
830
|
-
the toolbar skips the shadcn step, which tracks the page's mode rather than the
|
|
831
|
-
grid's. Reading it would paint a dark toolbar with the page's white `--card`. A
|
|
832
|
-
theme named `default` states no mode and keeps following the page.
|
|
833
|
-
|
|
834
|
-
Two caveats when you theme a toolbar that sits outside the grid. Theme
|
|
835
|
-
stylesheets scope their variables to the grid root, so a sibling toolbar never
|
|
836
|
-
sees them - declare `--tdg-color-*` on a common ancestor to share one palette.
|
|
837
|
-
And the mode rules above are selected by attribute, so they only ever move
|
|
838
|
-
private plumbing (`--tdg-toolbar-host-*`, `--tdg-toolbar-*-fallback`,
|
|
839
|
-
`--tdg-toolbar-surface-backdrop`); every token in the reference is declared once
|
|
840
|
-
at plain `.tdg-toolbar-root` specificity, so your override always wins.
|
|
841
|
-
|
|
842
|
-
Plain CSS overrides work too, and never need `!important`: every default rule is
|
|
843
|
-
written with exactly one unit of specificity, so any selector of yours that adds
|
|
844
|
-
a second part outranks it.
|
|
845
|
-
|
|
846
|
-
```css
|
|
847
|
-
.tdg-toolbar-root button[data-state="off"] {
|
|
848
|
-
background-color: var(--button-secondary-fill);
|
|
849
|
-
}
|
|
850
|
-
```
|
|
851
|
-
|
|
852
|
-
Elements expose stable `data-slot` names (`rdg-toolbar`, `rdg-column-toggle`,
|
|
853
|
-
`rdg-toolbar-column-toggle-trigger`, `rdg-toolbar-actions`,
|
|
854
|
-
`rdg-toolbar-export`, `rdg-toolbar-filter-toggle`, ...), and toggles expose
|
|
855
|
-
`data-state` as `on` or `off`. Inline toggles expose `aria-pressed`; compact-menu
|
|
856
|
-
toggles use `menuitemcheckbox` with `aria-checked`. `RDGToolbar` also accepts
|
|
857
|
-
`className` for scoping overrides to a class of your own. The complete token
|
|
858
|
-
table lives in
|
|
859
|
-
[the toolbar styling reference](https://geo-vi.github.io/the-datagrid/docs/reference/toolbar#toolbar-styling).
|
|
860
|
-
|
|
861
|
-
Stacked, the toolbar places its actions above the column toggles, since a
|
|
862
|
-
wrapping toggle list would otherwise push export and the filter controls far
|
|
863
|
-
down the card; from `80rem` it becomes a row with toggles leading.
|
|
864
|
-
|
|
865
|
-
Use `RDGToolbarTarget` around the grid when layout markup separates it
|
|
866
|
-
from the provider. Keep one grid per provider so the column model is
|
|
867
|
-
unambiguous. The JavaScript entry loads its scoped stylesheet automatically; if
|
|
868
|
-
your environment requires manual CSS imports, add
|
|
869
|
-
`import "@geovi/the-datagrid/toolbar/style.css"`.
|
|
870
|
-
|
|
871
|
-
For the complete direct-child rules, nested layout examples, multiple-grid
|
|
872
|
-
scoping, and the stability contract for all feature-specific providers and
|
|
873
|
-
targets, see [Providers and targets](https://geo-vi.github.io/the-datagrid/docs/reference/providers-and-targets).
|
|
874
|
-
|
|
875
|
-
When search and the toolbar share a grid, prefer `RDGProvider`/`RDGTarget` from
|
|
876
|
-
`@geovi/the-datagrid/components`. The feature-specific provider and target
|
|
877
|
-
remain supported for toolbar-only screens and existing integrations.
|
|
878
|
-
|
|
879
|
-
## Advanced usage
|
|
880
|
-
|
|
881
|
-
```tsx
|
|
882
|
-
import { useMemo, useState } from "react";
|
|
883
|
-
import { ReactDataGrid } from "@geovi/the-datagrid";
|
|
884
|
-
import type {
|
|
885
|
-
TypeColumns,
|
|
886
|
-
TypeFilterValue,
|
|
887
|
-
TypeI18n,
|
|
888
|
-
TypeOnSelectionChangeArg,
|
|
889
|
-
TypeRowSelection,
|
|
890
|
-
} from "@geovi/the-datagrid";
|
|
891
|
-
|
|
892
|
-
export default function App() {
|
|
893
|
-
const [selected, setSelected] = useState<TypeRowSelection>({});
|
|
894
|
-
const [columnOrder, setColumnOrder] = useState<string[]>([]);
|
|
895
|
-
|
|
896
|
-
const columns: TypeColumns = useMemo(
|
|
897
|
-
() => [
|
|
898
|
-
{ name: "id", header: "ID", sortable: true, filterable: true },
|
|
899
|
-
{ name: "name", header: "Name", sortable: true, filterable: true },
|
|
900
|
-
{ name: "email", header: "Email", sortable: true, filterable: true },
|
|
901
|
-
],
|
|
902
|
-
[]
|
|
903
|
-
);
|
|
904
|
-
|
|
905
|
-
const defaultFilterValue = useMemo<TypeFilterValue>(
|
|
906
|
-
() => [
|
|
907
|
-
{ name: "id", type: "number", operator: "eq", value: null },
|
|
908
|
-
{ name: "name", type: "string", operator: "contains", value: "" },
|
|
909
|
-
{ name: "email", type: "string", operator: "contains", value: "" },
|
|
910
|
-
],
|
|
911
|
-
[]
|
|
912
|
-
);
|
|
913
|
-
|
|
914
|
-
const rows = useMemo(
|
|
915
|
-
() => [
|
|
916
|
-
{ id: 1, name: "John Doe", email: "john@example.com" },
|
|
917
|
-
{ id: 2, name: "Jane Smith", email: "jane@example.com" },
|
|
918
|
-
],
|
|
919
|
-
[]
|
|
920
|
-
);
|
|
921
|
-
|
|
922
|
-
const i18n: TypeI18n = useMemo(
|
|
923
|
-
() => ({
|
|
924
|
-
noRecords: "No records",
|
|
925
|
-
clear: "Clear",
|
|
926
|
-
clearAll: "Clear all",
|
|
927
|
-
enable: "Enable",
|
|
928
|
-
disable: "Disable",
|
|
929
|
-
filter: "Filter",
|
|
930
|
-
operator: "Operator",
|
|
931
|
-
contains: "Contains",
|
|
932
|
-
sortAsc: "Sort A→Z",
|
|
933
|
-
sortDesc: "Sort Z→A",
|
|
934
|
-
}),
|
|
935
|
-
[]
|
|
936
|
-
);
|
|
937
|
-
|
|
938
|
-
const onSelectionChange = (config: TypeOnSelectionChangeArg) => {
|
|
939
|
-
setSelected(config.selected);
|
|
940
|
-
};
|
|
941
|
-
|
|
942
|
-
return (
|
|
943
|
-
<ReactDataGrid
|
|
944
|
-
theme="default"
|
|
945
|
-
idProperty="id"
|
|
946
|
-
columns={columns}
|
|
947
|
-
columnOrder={columnOrder}
|
|
948
|
-
dataSource={rows}
|
|
949
|
-
enableFiltering
|
|
950
|
-
defaultFilterValue={defaultFilterValue}
|
|
951
|
-
onFilterValueChange={(v) => console.log("Filters:", v)}
|
|
952
|
-
filteredRowsCount={(count) => console.log("Filtered rows:", count)}
|
|
953
|
-
enableColumnFilterContextMenu
|
|
954
|
-
enableColumnAutosize
|
|
955
|
-
skipHeaderOnAutoSize={false}
|
|
956
|
-
onColumnOrderChange={setColumnOrder}
|
|
957
|
-
virtualized
|
|
958
|
-
columnUserSelect
|
|
959
|
-
i18n={i18n}
|
|
960
|
-
showColumnMenuTool={false}
|
|
961
|
-
checkboxColumn
|
|
962
|
-
onSelectionChange={onSelectionChange}
|
|
963
|
-
selected={selected}
|
|
964
|
-
/>
|
|
965
|
-
);
|
|
966
|
-
}
|
|
967
|
-
```
|
|
968
|
-
|
|
969
|
-
`onSelectionChange` still emits the Inovua-style config object. For migration ergonomics, the grid also accepts the emitted object back through `selected`, so `onSelectionChange={setSelectedRows}` works with the same state variable used for `selected`.
|
|
970
|
-
|
|
971
|
-
## Props (high-level)
|
|
972
|
-
|
|
973
|
-
Note: this is a curated overview. For the complete contract, refer to the exported TypeScript types.
|
|
974
|
-
|
|
975
|
-
### Core
|
|
976
|
-
|
|
977
|
-
| Prop | Type | Default | Description |
|
|
978
|
-
| ------------ | ------------------- | -------- | ------------------------------------------------------------ |
|
|
979
|
-
| `idProperty` | `string` | `"id"` | Property name used as unique row identifier; JSX may omit it |
|
|
980
|
-
| `columns` | `TypeColumns` | required | Column definitions |
|
|
981
|
-
| `groups` | `TypeColumnGroup[]` | `[]` | Stacked and nested column-header descriptors |
|
|
982
|
-
| `dataSource` | `TypeDataSource` | required | Data source (array, function, or promise) |
|
|
983
|
-
|
|
984
|
-
### Display
|
|
985
|
-
|
|
986
|
-
| Prop | Type | Default | Description |
|
|
987
|
-
| ---------------------- | ------------------------------------------------ | ----------------- | ----------------------------------------------------------------- |
|
|
988
|
-
| `theme` | `string` | `"default-light"` | Theme name |
|
|
989
|
-
| `rowHeight` | `number \| ((rowIndex) => number) \| null` | `40` | Fixed, per-row, or naturally measured row height |
|
|
990
|
-
| `minRowHeight` | `number` | `20` | Minimum natural row height and virtualizer estimate |
|
|
991
|
-
| `maxRowHeight` | `number` | - | Optional upper bound for measured or functional row heights |
|
|
992
|
-
| `rowStyle` | `CSSProperties \| ({ data, props, style }) => …` | - | Static or data-dependent style merged onto each row |
|
|
993
|
-
| `disabledRows` | `{ [displayedIndex: string]: boolean } \| null` | - | Dim and block pointer interaction for displayed row indexes |
|
|
994
|
-
| `showZebraRows` | `boolean` | `true` | Show visible alternating row backgrounds |
|
|
995
|
-
| `headerHeight` | `number` | `40` | Header height in pixels |
|
|
996
|
-
| `filterRowHeight` | `number` | `40` | Filter row height in pixels |
|
|
997
|
-
| `virtualized` | `boolean` | `true` | Enable virtual scrolling, including measured natural rows |
|
|
998
|
-
| `allowMobileTransform` | `boolean` | `false` | Use searchable, sortable virtual cards at widths up to 1024px |
|
|
999
|
-
| `columnUserSelect` | `boolean \| "text" \| "none"` | `false` | Column text selection behavior |
|
|
1000
|
-
| `showCellBorders` | `boolean \| "vertical" \| "horizontal"` | `true` | Cell separator mode; use `"horizontal"` to disable vertical lines |
|
|
1001
|
-
|
|
1002
|
-
A `rowStyle` callback receives the live Inovua-shaped base style, including
|
|
1003
|
-
`height`, `width`, `minWidth`, and LTR `direction`. It may mutate that object
|
|
1004
|
-
and return `undefined`, or return a style object to merge. `props.id` preserves
|
|
1005
|
-
numeric IDs, `rowIndex` is page-local, and `remoteRowIndex` includes the current
|
|
1006
|
-
pagination offset. Locked-column indexes, presence flags, and section widths
|
|
1007
|
-
reflect the live rendered geometry.
|
|
1008
|
-
|
|
1009
|
-
`disabledRows` follows the Inovua 5.10.2 index contract. A truthy entry such as
|
|
1010
|
-
`{ 1: true }` disables the second row in the current sorted, filtered, and
|
|
1011
|
-
page-local view; keys are not row IDs. Disabled rows receive the legacy
|
|
1012
|
-
`InovuaReactDataGrid__row--disabled` hook, 50% opacity, and no pointer
|
|
1013
|
-
interaction. They are deliberately still included by controlled selection,
|
|
1014
|
-
header select-all, and imperative selection/editing APIs, matching upstream.
|
|
1015
|
-
The current state is also exposed as `props.disabledRow` to `rowStyle` and
|
|
1016
|
-
custom cell metadata. That callback value preserves upstream’s raw shape:
|
|
1017
|
-
`null` when the map is absent, `undefined` for a missing key, and the explicit
|
|
1018
|
-
`false` or `true` entry otherwise.
|
|
1019
|
-
|
|
1020
|
-
### Columns
|
|
1021
|
-
|
|
1022
|
-
| Prop | Type | Default | Description |
|
|
1023
|
-
| -------------------------- | ------------------------------- | ------- | ------------------------------------------------------------------------------- |
|
|
1024
|
-
| `columnOrder` | `string[]` | - | Controlled ordered array of column ids/names |
|
|
1025
|
-
| `defaultColumnOrder` | `string[]` | columns | Initial order for grid-owned ordering |
|
|
1026
|
-
| `onColumnOrderChange` | `(order: string[]) => void` | - | Receives reorder proposals; optional for grid-owned ordering |
|
|
1027
|
-
| `onColumnVisibleChange` | `({ column, visible }) => void` | - | Receives controlled or uncontrolled visibility proposals |
|
|
1028
|
-
| `reorderColumns` | `boolean` | `true` | Disable user drag reordering |
|
|
1029
|
-
| `allowGroupSplitOnReorder` | `boolean` | `true` | Allow reordering to split one logical group into visual segments |
|
|
1030
|
-
| `resizable` | `boolean` | `true` | Enable header resize handles |
|
|
1031
|
-
| `columnDefaultWidth` | `number` | `150` | Root fallback when a column has no width/defaultWidth |
|
|
1032
|
-
| `columnMinWidth` | `number` | `40` | Root fallback when a column has no minWidth |
|
|
1033
|
-
| `columnMaxWidth` | `number \| null` | `null` | Root fallback when a column has no maxWidth |
|
|
1034
|
-
| `shareSpaceOnResize` | `boolean` | `false` | Resize the adjacent visible column in the opposite direction |
|
|
1035
|
-
| `columnResizeHandleWidth` | `number` | `24` | Header resize pointer-target width |
|
|
1036
|
-
| `columnResizeProxyWidth` | `number` | `5` | Deferred resize-proxy width |
|
|
1037
|
-
| `liveColumnResize` | `boolean` | `false` | Resize rendered geometry during drag; callbacks remain completion-only |
|
|
1038
|
-
| `onColumnResize` | `(info, context) => void` | - | Reports each proposed width/flex and reserved viewport width |
|
|
1039
|
-
| `onBatchColumnResize` | `(entries, context) => void` | - | Reports one coherent callback for every resize transaction |
|
|
1040
|
-
| `enableColumnAutosize` | `boolean` | `true` | Estimate widths from a bounded row sample when no numeric width is supplied |
|
|
1041
|
-
| `skipHeaderOnAutoSize` | `boolean` | `false` | Skip header text when estimating an automatic width |
|
|
1042
|
-
| `showColumnMenuTool` | `boolean` | `true` | Show sort, visibility, auto-size, and fit actions in the accessible column menu |
|
|
1043
|
-
|
|
1044
|
-
When `columnOrder` is omitted, `defaultColumnOrder` seeds grid-owned ordering
|
|
1045
|
-
and drag changes persist even without a callback. When `columnOrder` is
|
|
1046
|
-
supplied, it is authoritative: `onColumnOrderChange` receives the proposal and
|
|
1047
|
-
the display changes only after the parent returns it. The same ownership rule
|
|
1048
|
-
applies to `column.visible` versus `defaultVisible`/`defaultHidden`.
|
|
1049
|
-
|
|
1050
|
-
Column sizing precedence is controlled `width`, column `defaultWidth` and
|
|
1051
|
-
`minWidth`/`maxWidth`, then the root fallbacks. An uncontrolled flex column
|
|
1052
|
-
retains flex ownership by default; set `column.keepFlex: false` to convert it to
|
|
1053
|
-
fixed sizing after a no-share resize. Shared-space resize preserves the adjacent
|
|
1054
|
-
pair's total width and handles fixed/fixed, flex/flex, and mixed pairs.
|
|
1055
|
-
Controlled `width` and `flex` values remain prop-owned while both resize
|
|
1056
|
-
callbacks receive the proposal.
|
|
1057
|
-
|
|
1058
|
-
Set `column.locked` to `"start"` or `"end"` to keep it visible at that
|
|
1059
|
-
horizontal edge; `true` is the Inovua-compatible alias for `"start"`. Locked
|
|
1060
|
-
columns keep their relative `columnOrder` within the start/unlocked/end
|
|
1061
|
-
sections, remain mounted during column virtualization, and use the same
|
|
1062
|
-
header, filter-row, body, resize, and controlled-reorder geometry.
|
|
1063
|
-
|
|
1064
|
-
This is an opt-in, Enterprise-derived compatibility extension rather than part
|
|
1065
|
-
of the Inovua Community 5.10.2 release gate. The implemented contract is the
|
|
1066
|
-
declarative `column.locked` field above. Inovua's `column.defaultLocked`,
|
|
1067
|
-
`column.lockable`, `column.autoLock`, root `onColumnLockedChange` and
|
|
1068
|
-
`showColumnMenuLockOptions`, imperative `setColumnLocked`, lock/unlock menu
|
|
1069
|
-
actions, and RTL edge mirroring are not implemented. Dragging may reorder
|
|
1070
|
-
columns inside the same locked/unlocked section, but a cross-section drop is
|
|
1071
|
-
rejected instead of changing the column's locked state. Declare the target
|
|
1072
|
-
section in the column definition up front; changing a column's locked section
|
|
1073
|
-
at runtime is not a supported contract yet.
|
|
1074
|
-
The grid groups columns only for rendering: the controlled `columnOrder` and
|
|
1075
|
-
remote data-source argument keep the application-owned sequence, with lock
|
|
1076
|
-
state carried separately by each column. Computed locked-section widths report
|
|
1077
|
-
the grid's logical column allocation; when an underfilled fixed-layout table is
|
|
1078
|
-
stretched to the viewport, browser-distributed surplus space is not added to
|
|
1079
|
-
those compatibility metrics.
|
|
1080
|
-
|
|
1081
|
-
### Filtering
|
|
1082
|
-
|
|
1083
|
-
| Prop | Type | Default | Description |
|
|
1084
|
-
| --------------------------------------- | ---------------------------------------------- | ------------------ | --------------------------------------------------------- |
|
|
1085
|
-
| `enableFiltering` | `boolean` | inferred | Explicitly show or hide the filter row |
|
|
1086
|
-
| `filterValue` | `TypeFilterValue` | - | Controlled display state; data ownership remains external |
|
|
1087
|
-
| `defaultFilterValue` | `TypeFilterValue` | - | Uncontrolled initial state and local filtering input |
|
|
1088
|
-
| `onFilterValueChange` | `(value: TypeFilterValue) => void` | - | Fired on filter change |
|
|
1089
|
-
| `filterTypes` | `TypeFilterTypes` | built-in registry | Extend or override filter types and operators |
|
|
1090
|
-
| `enableColumnFilterContextMenu` | `boolean` | `true` | Operator, activation, Clear, and Clear All menu |
|
|
1091
|
-
| `scrollTopOnFilter` | `boolean` | `true` | Reset vertical scroll after a filter commits |
|
|
1092
|
-
| `renderColumnFilterContextMenu` | `TypeRenderColumnFilterContextMenu` | - | Render a custom operator menu with grid/cell context |
|
|
1093
|
-
| `columnFilterContextMenuAlignPositions` | `string[]` | built-in fallbacks | Configure custom/operator menu alignment candidates |
|
|
1094
|
-
| `columnFilterContextMenuConstrainTo` | `boolean \| HTMLElement \| string \| function` | `true` | Supply the custom menu constraint target |
|
|
1095
|
-
| `columnFilterContextMenuPosition` | `string` | `"absolute"` | Supply the custom menu positioning mode |
|
|
1096
|
-
| `updateMenuPositionOnScroll` | `boolean` | `true` | Request custom menu repositioning while scrolling |
|
|
1097
|
-
| `filteredRowsCount` | `(count: number) => void` | - | Reports filtered row count |
|
|
1098
|
-
|
|
1099
|
-
For Inovua 5.10.2 compatibility, filter-row visibility and local array
|
|
1100
|
-
transformation are separate decisions. With no explicit `enableFiltering`, a
|
|
1101
|
-
non-empty `defaultFilterValue` or `filterValue` shows the row; an empty or
|
|
1102
|
-
missing descriptor array hides it. `enableFiltering` explicitly overrides only
|
|
1103
|
-
that row's visibility. A descriptor is still required for a column to render a
|
|
1104
|
-
filter editor; `enableFiltering={true}` by itself renders the structural row
|
|
1105
|
-
without inventing filter state. Active uncontrolled `defaultFilterValue`
|
|
1106
|
-
entries filter a local array even when the row is hidden, while controlled
|
|
1107
|
-
`filterValue` is treated as externally owned display state and is not reapplied
|
|
1108
|
-
locally. An entry with `active: false` still makes its editor visible but does
|
|
1109
|
-
not filter data. Clear resets values without changing activation; Enable and
|
|
1110
|
-
Disable are explicit menu actions, and Clear All emits one aggregate update.
|
|
1111
|
-
|
|
1112
|
-
### Sorting
|
|
1113
|
-
|
|
1114
|
-
| Prop | Type | Default | Description |
|
|
1115
|
-
| ------------------------- | ------------------------------ | ------------- | -------------------------------------------------------------- |
|
|
1116
|
-
| `sortInfo` | `TypeSortInfo` | - | Controlled sort state |
|
|
1117
|
-
| `defaultSortInfo` | `TypeSortInfo` | - | Uncontrolled initial sort |
|
|
1118
|
-
| `onSortInfoChange` | `(info: TypeSortInfo) => void` | - | Fired on sort change |
|
|
1119
|
-
| `sortable` | `boolean` | `true` | Root sorting switch; `column.sortable` can override it |
|
|
1120
|
-
| `allowUnsort` | `boolean` | `true` | Allow a single sort to return to “unsorted” |
|
|
1121
|
-
| `defaultSortingDirection` | `"asc" \| "desc"` | `"asc"` | Default sort direction |
|
|
1122
|
-
| `sortFunctions` | `TypeSortFunctions` | date registry | Comparator registry addressed by `column.type` |
|
|
1123
|
-
| `renderSortTool` | `TypeRenderSortTool` | built-in icon | Root sort-indicator renderer; `column.renderSortTool` wins |
|
|
1124
|
-
| `scrollTopOnSort` | `boolean \| "always"` | `true` | Reset vertical scroll on sort, never, or on every data refresh |
|
|
1125
|
-
|
|
1126
|
-
An object-valued `sortInfo` is single-sort mode. An array-valued sort state is
|
|
1127
|
-
persistent multi-sort mode, including when the array contains zero or one
|
|
1128
|
-
descriptor; ordinary click, Enter, Space, header-menu, mobile, and imperative
|
|
1129
|
-
sort actions retain that array shape without requiring Shift. Descriptor order
|
|
1130
|
-
is sort priority, and retoggling a descriptor preserves its position until it
|
|
1131
|
-
is removed.
|
|
1132
|
-
|
|
1133
|
-
Local sorting uses `column.sort` first, then a descriptor `fn`, a
|
|
1134
|
-
`sortFunctions[column.type]` registry entry, and finally the built-in
|
|
1135
|
-
`number`/`date`/`string` comparator. A named column comparator receives
|
|
1136
|
-
`(value1, value2, column, data1, data2, sortInfo)`. An id-only column receives
|
|
1137
|
-
the complete rows as `value1` and `value2`. Controlled `sortInfo` remains
|
|
1138
|
-
externally owned and is not applied again to local array order.
|
|
1139
|
-
|
|
1140
|
-
Migration notes for the completed Inovua sorting contract:
|
|
1141
|
-
|
|
1142
|
-
- Previous releases inferred numeric ordering when both values were
|
|
1143
|
-
number-like. Untyped columns now use Inovua's string comparator; declare
|
|
1144
|
-
`type: "number"` (or provide a comparator) for numeric ordering.
|
|
1145
|
-
- Shift no longer changes a single descriptor into multi-sort mode. Initialize
|
|
1146
|
-
`sortInfo` or `defaultSortInfo` as an array to opt into persistent multi-sort.
|
|
1147
|
-
- `TypeSingleSortInfo.fn`, `column.sort`, and registered sort functions now
|
|
1148
|
-
expose their exact comparator argument lists while retaining Inovua's
|
|
1149
|
-
`number | boolean` result compatibility.
|
|
1150
|
-
|
|
1151
|
-
### Selection
|
|
1152
|
-
|
|
1153
|
-
| Prop | Type | Default | Description |
|
|
1154
|
-
| ------------------------------ | ----------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------- |
|
|
1155
|
-
| `checkboxColumn` | `boolean \| IColumn` | `false` | Enable or customize the checkbox column |
|
|
1156
|
-
| `selected` | `TypeRowSelection` | - | Controlled selection |
|
|
1157
|
-
| `defaultSelected` | `TypeRowSelection` | `{}` for multi-select, else null | Uncontrolled initial selection |
|
|
1158
|
-
| `unselected` | `{ [rowId: string]: boolean }` | - | Controlled exclusions while `selected === true` |
|
|
1159
|
-
| `defaultUnselected` | `{ [rowId: string]: boolean }` | - | Initial uncontrolled select-all exclusions |
|
|
1160
|
-
| `onSelectionChange` | `(config: TypeOnSelectionChangeArg) => void` | - | Fired with the next selection and row metadata |
|
|
1161
|
-
| `multiSelect` | `boolean` | `true` with `checkboxColumn` | Enable multi-row selection semantics |
|
|
1162
|
-
| `checkboxOnlyRowSelect` | `boolean` | `false` | Require the checkbox instead of a plain row click |
|
|
1163
|
-
| `checkboxSelectEnableShiftKey` | `boolean` | `false` | Enable Shift-range selection through the checkbox column |
|
|
1164
|
-
| `toggleRowSelectOnClick` | `boolean` | `false` | Toggle off the sole selected row on an unmodified click |
|
|
1165
|
-
| `activeIndex` | `number` | - | Controlled active-row index |
|
|
1166
|
-
| `defaultActiveIndex` | `number` | `-1` | Initial uncontrolled active-row index |
|
|
1167
|
-
| `onActiveIndexChange` | `(index: number) => void` | - | Fired when pointer, keyboard, or focus changes the active row |
|
|
1168
|
-
| `enableKeyboardNavigation` | `boolean` | `true` | Enable Arrow, Home, End, Page, Enter, and optional Tab row navigation |
|
|
1169
|
-
| `activateRowOnFocus` | `boolean` | `true` | Restore the last active row when grid focus returns |
|
|
1170
|
-
| `keyPageStep` | `number` | `10` | Row distance for Page Up and Page Down |
|
|
1171
|
-
| `allowRowTabNavigation` | `boolean` | `false` | Move the active row with Tab while another row remains available |
|
|
1172
|
-
| `disabledRows` | `{ [displayedIndex: string]: boolean } \| null` | - | Block pointer interaction by current view index without excluding API selection |
|
|
1173
|
-
|
|
1174
|
-
Shift-click selects an inclusive range from the previous row anchor. Ctrl/Cmd
|
|
1175
|
-
click toggles one row, while an unmodified multi-select click selects only that
|
|
1176
|
-
row. Enter applies the same selection rules to the active row. Focus leaving
|
|
1177
|
-
the grid clears the live active index and restores the last index when focus
|
|
1178
|
-
returns; virtualized navigation scrolls the active row into view.
|
|
1179
|
-
|
|
1180
|
-
### Editing
|
|
1181
|
-
|
|
1182
|
-
| Prop | Type | Default | Description |
|
|
1183
|
-
| ------------------- | ------------------------------ | ------------ | -------------------------------------------------------------------------------------------- |
|
|
1184
|
-
| `editable` | `boolean` | `false` | Enable default editing for columns that do not opt out |
|
|
1185
|
-
| `editStartEvent` | `string` | `"dblclick"` | Use double-click or compatible click activation |
|
|
1186
|
-
| `onEditStart` | `(info: TypeEditInfo) => void` | - | Reports the original value and stable row/column identity |
|
|
1187
|
-
| `onEditValueChange` | `(info: TypeEditInfo) => void` | - | Reports each draft value change |
|
|
1188
|
-
| `onEditStop` | `(info: TypeEditInfo) => void` | - | Runs before completion or cancellation |
|
|
1189
|
-
| `onEditComplete` | `(info) => void \| Promise` | - | Runs after the editor stops; navigation waits for fulfillment and is suppressed on rejection |
|
|
1190
|
-
| `onEditCancel` | `(info: TypeEditInfo) => void` | - | Reports Escape cancellation without persisting the draft |
|
|
1191
|
-
|
|
1192
|
-
Column-level `editable` may be a boolean or a synchronous/asynchronous
|
|
1193
|
-
predicate. Pointer and imperative starts pass it the same Inovua-shaped
|
|
1194
|
-
`CellProps`, including raw string/number row identity, row/render/remote
|
|
1195
|
-
indices, column aliases and computed indices/width, selection and row-height
|
|
1196
|
-
metadata, theme, and native-scroll state. A falsy result or rejection refuses
|
|
1197
|
-
the edit. `editor` accepts a component type or React element, while
|
|
1198
|
-
`renderEditor(editorProps, cellProps, cell)` receives the compatibility
|
|
1199
|
-
contract. Values from `editorProps` are
|
|
1200
|
-
available both as top-level editor props and through the nested `editorProps`
|
|
1201
|
-
object. Navigation callbacks use `(complete, direction)`: passing
|
|
1202
|
-
`complete=false` stops the editor and navigates without firing
|
|
1203
|
-
`onEditComplete` or `onEditCancel`. The built-in editor exposes a stable
|
|
1204
|
-
accessible name from the column header/name/ID.
|
|
1205
|
-
|
|
1206
|
-
The stable `TypeComputedProps` ref exposes these editing methods and fields:
|
|
1207
|
-
|
|
1208
|
-
| Member | Behavior |
|
|
1209
|
-
| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1210
|
-
| `startEdit({ columnId, rowIndex?, rowId?, value? })` | Starts the requested editable cell after scroll/deferred dispatch and resolves to its start value. It replaces an active editor without ending the former edit. Invalid columns reject with an error; invalid rows reject with `null`. |
|
|
1211
|
-
| `tryStartEdit({ columnId, rowIndex?, rowId?, dir? })` | Searches in `dir` order after deferred dispatch and resolves to the first editable value, replacing an active editor without end callbacks. It rejects with `null` if none can start. Numeric columns are visible-column indices. |
|
|
1212
|
-
| `completeEdit(args?)` | Scrolls, waits for the rendered/editable target, and reads live cell metadata/draft at dispatch. An invalid/missing column falls back both coordinates to current. No object uses `""`; an omitted cross-target value is `undefined`. |
|
|
1213
|
-
| `cancelEdit(args?)` | Immediately targets only a rendered/editable cell and never scrolls. An invalid/missing column falls back to current; a valid column without a row, a non-editable target, or an offscreen target is a no-op. |
|
|
1214
|
-
| `getCurrentEditInfo()` | Returns the live edit identity/value or `null`. |
|
|
1215
|
-
| `isInEdit.current` | Exposes the upstream lifecycle edit flag. |
|
|
1216
|
-
| `currentEditCompletePromise.current` | Tracks the current completion callback promise. |
|
|
1217
|
-
|
|
1218
|
-
It also exposes behavior-backed column-state methods:
|
|
1219
|
-
|
|
1220
|
-
| Member | Behavior |
|
|
1221
|
-
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
1222
|
-
| `setColumnVisible(column, visible)` | Uses the same controlled/uncontrolled ownership and callback path as the built-in menu and optional toolbar. |
|
|
1223
|
-
| `setColumnOrder(order)` | Applies an uncontrolled order or emits a controlled proposal without mutating consumer state. |
|
|
1224
|
-
| `setColumnSizes(action)` / `setColumnFlexes(action)` | Replace grid-owned width/flex maps; declarative `width`/`flex` values remain authoritative. |
|
|
1225
|
-
| `onBatchColumnResize(entries, context?)` | Applies a width/flex transaction and emits per-column plus batch completion callbacks. |
|
|
1226
|
-
| `setColumnSizeAuto(id, skipHeader?)` | Deterministically auto-sizes one resizable visible column. |
|
|
1227
|
-
| `setColumnsSizesAuto(config?)` | Auto-sizes selected or all resizable visible columns as one batch. |
|
|
1228
|
-
| `setColumnSizesToFit()` | Fits resizable visible columns to the viewport while honoring min/max bounds. |
|
|
1229
|
-
|
|
1230
|
-
Completion is session-safe: an older async completion settling cannot clear or
|
|
1231
|
-
navigate a newer edit. The editor is already stopped when `onEditComplete`
|
|
1232
|
-
runs; rejecting its Promise leaves it stopped and suppresses keyboard
|
|
1233
|
-
navigation. Exact 5.10.2 cross-target behavior is preserved: dispatching
|
|
1234
|
-
complete/cancel to a different valid cell reports that target without emitting
|
|
1235
|
-
`onEditStop` for it and leaves the current editor/edit info in place; the
|
|
1236
|
-
upstream lifecycle flag becomes false. Numeric row IDs remain numeric in all
|
|
1237
|
-
lifecycle payloads, and numeric row lookup accepts equivalent numeric strings.
|
|
1238
|
-
The published upstream `TypeEditInfo` declaration nevertheless labels
|
|
1239
|
-
`rowId` as `string`; the compatibility type intentionally uses `any` so both
|
|
1240
|
-
existing string-typed handlers and the observed numeric runtime contract remain
|
|
1241
|
-
source-compatible.
|
|
1242
|
-
|
|
1243
|
-
### Pagination
|
|
1244
|
-
|
|
1245
|
-
| Prop | Type | Default | Description |
|
|
1246
|
-
| ------------------------- | ------------------------------------------- | ----------------------- | ---------------------------------------------------------------------- |
|
|
1247
|
-
| `pagination` | `true \| false \| "remote" \| "local"` | `false` | Pagination mode |
|
|
1248
|
-
| `skip` | `number` | - | Controlled offset |
|
|
1249
|
-
| `defaultSkip` | `number` | `0` | Initial offset |
|
|
1250
|
-
| `limit` | `number` | - | Controlled page size |
|
|
1251
|
-
| `defaultLimit` | `number` | first page size or `10` | Initial page size |
|
|
1252
|
-
| `onSkipChange` | `(skip: number) => void` | - | Fired when offset changes |
|
|
1253
|
-
| `onLimitChange` | `(limit: number) => void` | - | Fired when page size changes |
|
|
1254
|
-
| `pageSizes` | `number[]` | `[10, 50, 100, 1000]` | Allowed page sizes |
|
|
1255
|
-
| `renderPaginationToolbar` | `(props: TypePaginationProps) => ReactNode` | - | Custom toolbar; `undefined` uses the built-in and `null` suppresses it |
|
|
1256
|
-
|
|
1257
|
-
### Misc
|
|
1258
|
-
|
|
1259
|
-
| Prop | Type | Default | Description |
|
|
1260
|
-
| ----------------- | ---------------------------------------------------- | ----------- | ------------------------------------------------------------------- |
|
|
1261
|
-
| `i18n` | `TypeI18n` | - | Text overrides (labels, operators, etc.) |
|
|
1262
|
-
| `loading` | `boolean` | - | Controlled effective loading state |
|
|
1263
|
-
| `loadingText` | `ReactNode \| (() => ReactNode)` | `"Loading"` | Built-in/custom mask content |
|
|
1264
|
-
| `renderLoadMask` | `(props: TypeLoadMaskProps) => ReactNode \| null` | - | Custom mask; `undefined` uses the built-in and `null` suppresses it |
|
|
1265
|
-
| `onLoadingChange` | `(loading: boolean) => void` | - | Fires once per effective loading transition |
|
|
1266
|
-
| `onDidMount` | `(ref: MutableRefObject<TypeComputedProps \| null>)` | - | Passive mount callback after API hydration, before handle/onReady |
|
|
1267
|
-
| `handle` | `(ref: MutableRefObject<TypeComputedProps \| null>)` | - | Receives the same stable ref after onDidMount |
|
|
1268
|
-
| `onReady` | `(ref: MutableRefObject<TypeComputedProps \| null>)` | - | Receives the same stable ref after handle |
|
|
1269
|
-
| `className` | `string` | - | Extra CSS classes on the outer grid root |
|
|
1270
|
-
| `style` | `CSSProperties` | - | Inline styles on the outer grid root |
|
|
1271
|
-
| `onFocus` | `FocusEventHandler<HTMLDivElement>` | - | Bubbling root focus lifecycle handler |
|
|
1272
|
-
| `onBlur` | `FocusEventHandler<HTMLDivElement>` | - | Bubbling root blur lifecycle handler |
|
|
1273
|
-
| `onKeyDown` | `KeyboardEventHandler<HTMLDivElement>` | - | Bubbling root keyboard handler |
|
|
1274
|
-
|
|
1275
|
-
Issue 48 certifies the `onDidMount` mount contract. The existing `handle` and
|
|
1276
|
-
`onReady` adapters are usable, but Inovua's callback-identity cleanup and
|
|
1277
|
-
nonzero-width readiness details remain explicitly listed as a known gap in the
|
|
1278
|
-
public compatibility ledger.
|
|
1279
|
-
|
|
1280
|
-
## TypeScript
|
|
1281
|
-
|
|
1282
|
-
The package ships full type definitions.
|
|
1283
|
-
|
|
1284
|
-
```tsx
|
|
1285
|
-
import { ReactDataGrid } from "@geovi/the-datagrid";
|
|
1286
|
-
import type {
|
|
1287
|
-
TypeColumns,
|
|
1288
|
-
TypeColumn,
|
|
1289
|
-
TypeDataGridProps,
|
|
1290
|
-
TypeDataSourceArgs,
|
|
1291
|
-
TypeRowSelection,
|
|
1292
|
-
TypeOnSelectionChangeArg,
|
|
1293
|
-
TypeFilterValue,
|
|
1294
|
-
TypeSortInfo,
|
|
1295
|
-
TypeI18n,
|
|
1296
|
-
} from "@geovi/the-datagrid";
|
|
1297
|
-
```
|
|
91
|
+
MIT licensed.
|