@gridkitjs/core 0.0.0-dev-20261106222533

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.
@@ -0,0 +1,4229 @@
1
+ /**
2
+ * A row or column selection change by id — see
3
+ * `GridControllerOptions.onSelectionDiff`.
4
+ */
5
+ interface SelectionDiffEvent extends SelectionDiff {
6
+ /** Which selection changed. */
7
+ readonly target: "rows" | "columns";
8
+ /** The whole selection after the change. */
9
+ readonly selection: SelectionState;
10
+ }
11
+ /**
12
+ * What `createGridController` is given: the grid's options and selection
13
+ * callbacks, plus what a renderer supplies that is not a setting — the column
14
+ * definitions, whose templates name the renderer's own node type, the width
15
+ * the viewport measured, and a hook for its own selection feedback.
16
+ */
17
+ interface GridControllerOptions<Row, Node = string> extends GridOptions<Row>, SelectionCallbacks<Row, Node> {
18
+ /**
19
+ * The columns to show. Omitted or empty, one column is inferred per field
20
+ * of `dataSource` — see `defineColumnsFromRows`.
21
+ */
22
+ columns?: readonly ColumnDefinition<Row, Node>[] | undefined;
23
+ /**
24
+ * The width, in px, `resizeMode: "fit"` fills. `null` or absent before it
25
+ * has been measured, or where there is no viewport at all (an export in
26
+ * Node), and then columns keep their resolved widths.
27
+ */
28
+ viewportWidth?: number | null | undefined;
29
+ /**
30
+ * Called once per row or column selection change, after the selection
31
+ * callbacks, with the change by id — every id it added or removed,
32
+ * including those with no row on screen (on another page, in a collapsed
33
+ * group, filtered out), which the callbacks' resolved rows leave out. For a
34
+ * renderer's own feedback, such as a live region announcing how many rows
35
+ * are selected; an application reads the selection callbacks instead.
36
+ */
37
+ onSelectionDiff?: ((event: SelectionDiffEvent) => void) | undefined;
38
+ }
39
+ /**
40
+ * A grid without a renderer: its state, the view derived from it, and every
41
+ * action that changes it. A renderer creates one per grid, hands it the
42
+ * current options on each update, draws `getView()` and calls the actions
43
+ * from its event handlers, so no renderer decides anything the user can see.
44
+ *
45
+ * Each slice of `GridState` is controlled or not on its own, the way a form
46
+ * input is: given as an option (`columnSort`), the grid shows that value and
47
+ * an action only asks for a change through the slice's callback
48
+ * (`onColumnSortChange`); left out, the controller keeps the slice itself,
49
+ * starting from its default (`defaultColumnSort`).
50
+ *
51
+ * Every action follows the same steps: work out the next value; stop if it
52
+ * is the very object the slice already holds; keep it, unless the slice is
53
+ * controlled; report it through the slice's callback; then call every
54
+ * subscriber, synchronously. The setters (`setColumnSort` and the like) also
55
+ * stop for a value equal to the current one, so restoring what is already
56
+ * there reports nothing.
57
+ *
58
+ * Every member is a plain function bound to its grid, safe to hand around on
59
+ * its own — `onClick={controller.nextPage}`.
60
+ */
61
+ interface GridController<Row, Node = string> {
62
+ readonly getOptions: () => GridControllerOptions<Row, Node>;
63
+ /**
64
+ * Replaces the options, as a renderer does with its current props on every
65
+ * update; calling it again with equal options changes nothing. A controlled
66
+ * slice takes its new value from here.
67
+ *
68
+ * Does not call subscribers: a renderer calls this while it updates, and
69
+ * draws the result itself — a subscriber called mid-update would update
70
+ * mid-update too. A renderer that also tells other listeners about it does
71
+ * so once its update is done.
72
+ */
73
+ readonly setOptions: (options: GridControllerOptions<Row, Node>) => void;
74
+ /** Every slice as the grid now applies it. The same object until a slice changes. */
75
+ readonly getState: () => GridState<Row>;
76
+ /** What the user is looking at — see `resolveGridView`. The same object until something in it changes. */
77
+ readonly getView: () => GridView<Row, Node>;
78
+ /**
79
+ * Calls `listener` after each action that got as far as reporting a
80
+ * change. Returns the function that unsubscribes it.
81
+ */
82
+ readonly subscribe: (listener: () => void) => () => void;
83
+ /**
84
+ * Puts back state saved earlier — from `getState()`, or from
85
+ * `serializeGridState` and back through JSON. Every slice given is set as
86
+ * its own `set*` action would set it, so each that changes fires its
87
+ * callback and a controlled one only asks; slices left out keep their value.
88
+ * Subscribers are called once, after every slice is in place, and a
89
+ * restored pagination is kept even when the same call changed the sort,
90
+ * filter or grouping that would otherwise send it back to the first page.
91
+ */
92
+ readonly restoreState: (saved: Partial<GridState<Row>> | Partial<SerializedGridState<Row>>) => void;
93
+ /**
94
+ * Replaces the column widths. Reported through `onColumnResize` as the
95
+ * `"end"` of a resize of the first column whose width changed, at its new
96
+ * width — or, when its entry was removed, the width its definition gives
97
+ * it. Equal widths report nothing.
98
+ */
99
+ readonly setColumnSizing: (sizing: ColumnSizingState) => void;
100
+ /**
101
+ * Sets one column's width, as a resize gesture does: `"move"` while the
102
+ * gesture lasts, `"end"` once it is over. Never skipped for an unchanged
103
+ * width, so a drag held against a column's minimum still reports every
104
+ * move.
105
+ */
106
+ readonly resizeColumn: (columnId: string, width: number, phase: "move" | "end") => void;
107
+ /**
108
+ * Ends a resize gesture by putting its column back as it was when the
109
+ * gesture began — `startSizing` is the sizing state then, `startWidth` the
110
+ * width the column was drawn at — keeping any other column's change made in
111
+ * the meantime. Reported as the gesture's `"end"`, at `startWidth`.
112
+ */
113
+ readonly cancelColumnResize: (columnId: string, startSizing: ColumnSizingState, startWidth: number) => void;
114
+ /**
115
+ * Replaces the column order. Reported through `onColumnOrderChange` naming
116
+ * the first column whose position changed; an equal order reports nothing.
117
+ */
118
+ readonly setColumnOrder: (order: ColumnOrderState) => void;
119
+ /**
120
+ * Moves a column in front of `beforeId`, or to the end when that is
121
+ * `null`, among every column — hidden ones keep their place. A move that
122
+ * changes nothing reports nothing.
123
+ */
124
+ readonly moveColumn: (columnId: string, beforeId: string | null) => void;
125
+ /**
126
+ * Replaces the column visibility state. Reported through
127
+ * `onColumnVisibilityChange` with every column whose entry changed; an
128
+ * equal state reports nothing.
129
+ */
130
+ readonly setColumnVisibility: (visibility: ColumnVisibilityState) => void;
131
+ /** Shows the given columns, each in the place it held when hidden. One report for the whole call. */
132
+ readonly showColumns: (columnIds: readonly string[]) => void;
133
+ /** Hides the given columns. A hidden column still sorts, filters and groups. */
134
+ readonly hideColumns: (columnIds: readonly string[]) => void;
135
+ /**
136
+ * Replaces the filter. Reported through `onFilterChange`; a filter equal to
137
+ * the current one — the same entries in the same order, a `Date` value
138
+ * compared by time and a predicate by identity — reports nothing.
139
+ */
140
+ readonly setFilter: (filter: FilterState<Row>) => void;
141
+ /**
142
+ * Replaces the selected row ids as given, whatever `selectable` allows —
143
+ * the way a controlled or default value is applied. The same ids in the
144
+ * same order report nothing.
145
+ */
146
+ readonly setRowSelection: (selection: SelectionState) => void;
147
+ /**
148
+ * Selects rows as a user could, within what `selectable.rows` allows:
149
+ * `"replace"` (the default) selects exactly these — only the last of them
150
+ * under `"single"` — and `"toggle"` flips each one. An id need not name a
151
+ * row on screen. A call that leaves the selection as it was reports
152
+ * nothing.
153
+ */
154
+ readonly selectRows: (rowIds: readonly string[], intent?: "replace" | "toggle") => void;
155
+ /**
156
+ * Applies one click or key press to a row: `"replace"`, `"toggle"` or
157
+ * `"range"` from the last row selected by anything but a range, across
158
+ * the data rows on the current page.
159
+ */
160
+ readonly selectRow: (rowId: string, intent: SelectIntent) => void;
161
+ /** Selects every data row on the current page, when `selectable.rows` is `"multiple"`. */
162
+ readonly selectAllRows: () => void;
163
+ /** Lets go of every row, column and cell selection at once, as Escape does. */
164
+ readonly clearSelection: () => void;
165
+ /** Replaces the selected column ids as given — see `setRowSelection`. */
166
+ readonly setColumnSelection: (selection: SelectionState) => void;
167
+ /** `selectRow`, for a column among the columns as rendered. */
168
+ readonly selectColumn: (columnId: string, intent: SelectIntent) => void;
169
+ /** Replaces the selected cell as given, `null` for none. */
170
+ readonly setCellSelection: (selection: CellSelectionState) => void;
171
+ /**
172
+ * Applies one click or key press to a cell: `"toggle"` lets go of it when
173
+ * it is the one selected; anything else selects it. A cell holds one value,
174
+ * so a range over cells reads as a plain click.
175
+ */
176
+ readonly selectCell: (cell: SelectedCellRef, intent: SelectIntent) => void;
177
+ /**
178
+ * Replaces the sort. Reported through `onColumnSortChange` naming the
179
+ * first column whose place or direction changed; a sort equal to the
180
+ * current one changes nothing and reports nothing.
181
+ */
182
+ readonly setColumnSort: (sort: ColumnSortState) => void;
183
+ /**
184
+ * Cycles a column's sort, as its header toggle does: ascending, descending,
185
+ * off. `stack` adds it to the sort rather than replacing the sort with it.
186
+ */
187
+ readonly toggleColumnSort: (columnId: string, options?: {
188
+ readonly stack?: boolean | undefined;
189
+ }) => void;
190
+ /**
191
+ * Takes one column out of the sort, keeping the rest in their order, and
192
+ * reports naming that column — which `setColumnSort` without it would not
193
+ * when it was the first key, naming instead the key that moved up. A
194
+ * column the sort leaves out already reports nothing.
195
+ */
196
+ readonly clearColumnSort: (columnId: string) => void;
197
+ /**
198
+ * Replaces the group-by stack. Reported through `onGroupByChange` naming
199
+ * the first level that changed; an equal stack reports nothing.
200
+ */
201
+ readonly setGroupBy: (groupBy: GroupByState) => void;
202
+ /** Adds a column to the end of the group-by stack, or removes it if it is already there. */
203
+ readonly toggleGroupBy: (columnId: string) => void;
204
+ /**
205
+ * Puts a column into the group-by stack in front of `beforeColumnId`, or at
206
+ * the end when that is `null` — adding it, or moving it if it is already
207
+ * there.
208
+ */
209
+ readonly moveGroupBy: (columnId: string, beforeColumnId: string | null) => void;
210
+ /**
211
+ * Replaces the collapsed groups. Reported with `groupId: null`, as a change
212
+ * to every group at once; the same ids in the same order report nothing.
213
+ */
214
+ readonly setGroupExpansion: (expansion: GroupExpansionState) => void;
215
+ readonly toggleGroupExpansion: (groupId: string) => void;
216
+ readonly expandAllGroups: () => void;
217
+ /** Collapses every group currently shown — see `collapseAllGroups`. */
218
+ readonly collapseAllGroups: () => void;
219
+ /**
220
+ * Replaces the page and page size as given; the view clamps a page past
221
+ * the last one. An equal pagination reports nothing.
222
+ */
223
+ readonly setPagination: (pagination: PaginationState) => void;
224
+ /**
225
+ * Moves to the given page, clamped into range. A page that clamps to the
226
+ * current one reports nothing.
227
+ */
228
+ readonly goToPage: (pageIndex: number) => void;
229
+ /** Moves one page on; on the last page it does nothing and reports nothing. */
230
+ readonly nextPage: () => void;
231
+ /** Moves one page back; on the first page it does nothing and reports nothing. */
232
+ readonly previousPage: () => void;
233
+ /**
234
+ * Changes the page size and goes back to the first page. The current size,
235
+ * already on the first page, reports nothing.
236
+ */
237
+ readonly setPageSize: (pageSize: number) => void;
238
+ }
239
+
240
+ /** How a column's values compare, which decides what an operand must be. */
241
+ type ValueKind = "number" | "boolean" | "date" | "text";
242
+
243
+ /**
244
+ * The kind of value a column filters as — what decides which conditions a
245
+ * filter menu offers on it, how their operators read, and what a typed
246
+ * operand must be.
247
+ */
248
+ type FilterOperatorFamily = ValueKind;
249
+ /**
250
+ * The family a column of `type` falls in: `"number"` for the numeric
251
+ * types, `"date"` for date, date-time and time, `"boolean"`, and `"text"`
252
+ * for everything else. It is the filter engine's own reading of `type`, so
253
+ * a menu never offers a condition the column would compare differently.
254
+ */
255
+ declare function filterOperatorFamily(type: ColumnType | undefined): FilterOperatorFamily;
256
+ /**
257
+ * The conditions a filter menu offers on a column of `type`, in the order it
258
+ * lists them, unless the column names its own. Never `in`: a list of values
259
+ * is the checklist's to pick, not a condition's to type.
260
+ */
261
+ declare function defaultFilterOperators(type: ColumnType | undefined): readonly FilterOperator[];
262
+ /**
263
+ * How many operands `operator` takes — how many inputs a condition row
264
+ * shows: none for the blanks, `between`'s two ends, one for the rest. `in`
265
+ * takes one list, which only a checklist writes.
266
+ */
267
+ declare function filterOperandArity(operator: FilterOperator): 0 | 1 | 2;
268
+ /**
269
+ * The operand a condition input's `text` stands for on a column of `type`,
270
+ * read as the column filters — or `undefined` when the text is empty or
271
+ * doesn't read as one, which an editor shows as a value still to fix.
272
+ *
273
+ * - Text is kept as typed, spaces and all.
274
+ * - A number reads with a point for decimals, as a number input gives it:
275
+ * `"12abc"` and `"1,5"` read as nothing rather than as a guess.
276
+ * - A date reads as a date input gives it, `yyyy-mm-dd`, at that day's
277
+ * local midnight; or as a date-time input does, `yyyy-mm-ddThh:mm`, at
278
+ * that local time.
279
+ * - A boolean reads `"true"` or `"false"`.
280
+ */
281
+ declare function parseFilterOperand(text: string, type: ColumnType | undefined): Exclude<FilterScalar, null> | undefined;
282
+ /**
283
+ * The text a condition input shows for `value` — `parseFilterOperand`'s
284
+ * inverse, for opening a condition already applied. A date reads back in
285
+ * the form its column's input takes: the day alone on a `"date"` column,
286
+ * the day and time on a `"dateTime"` or `"time"` one. A blank operand is
287
+ * empty, and one that isn't a date on a date column — a string set in code
288
+ * that names none — shows as it is, for the user to fix.
289
+ */
290
+ declare function formatFilterOperand(value: FilterScalar | undefined, type: ColumnType | undefined): string;
291
+
292
+ /** The locale(s) values are formatted for — `undefined` is the runtime's own. */
293
+ type FormatLocale = string | readonly string[] | undefined;
294
+ /**
295
+ * The text a value reads as in `column` — what a cell shows when the column
296
+ * has no `cellTemplate`, and what an export or a print writes, so the two
297
+ * cannot disagree.
298
+ *
299
+ * A `valueFormatter` decides outright. `null`/`undefined` read `""`, a
300
+ * boolean `"true"`/`"false"` — or `messages.booleanTrue`/`booleanFalse`
301
+ * when given, for a grid speaking another language — a string as it is, a
302
+ * plain object or array as JSON.
303
+ *
304
+ * Dates and numbers are formatted through `Intl` only once asked to — the
305
+ * column has a `format`, or a `locale` is given. Until then they print as a
306
+ * grid always printed them, so adopting this changes nothing on screen: a
307
+ * `Date` through `toLocaleString()`, a number as-is (`1234.5`, never
308
+ * `1,234.5`). Once asked:
309
+ *
310
+ * - A `Date` → `Intl.DateTimeFormat`: the date alone under `"date"`, the time
311
+ * alone under `"time"`, both otherwise.
312
+ * - A number under a numeric `type` → `Intl.NumberFormat`: `"currency"` with
313
+ * a currency symbol once `format.currency` names one (two fraction digits
314
+ * until then), `"percent"` reading `0.25` as 25 %. Under any other type it
315
+ * is still printed as-is, the way a number id should be.
316
+ *
317
+ * `format` and `locale` go to the `Intl` constructor unchanged, so any
318
+ * option it accepts is honoured.
319
+ */
320
+ declare function formatCellValue<Row>(value: unknown, column: ColumnDefinition<Row, unknown>, locale?: FormatLocale, row?: Row, messages?: Pick<GridMessages, "booleanTrue" | "booleanFalse">): string;
321
+ /**
322
+ * The text an aggregate result reads as — a footer cell, a group's subtotal
323
+ * — through `formatCellValue`, so once a `format` or `locale` asks for it a
324
+ * `sum` of a currency column reads as currency and a `max` of a date column
325
+ * as a date. `column` is `undefined` for a spec naming a column the grid
326
+ * does not have, which then formats by its value alone.
327
+ *
328
+ * Until then a numeric result reads through `toLocaleString()`, with digit
329
+ * grouping, where a cell prints its number as-is: that is how a grid has
330
+ * always shown its totals, and a sum easily runs into the thousands.
331
+ */
332
+ declare function formatAggregateValue<Row>(value: unknown, spec: AggregateSpec<Row>, column: ColumnDefinition<Row, unknown> | undefined, locale?: FormatLocale): string;
333
+ /**
334
+ * The text a group's own value reads as — a group header's name, and the
335
+ * label an export writes for it: as the grouped column's cells read it,
336
+ * except that a missing value reads `messages.blankGroupValue` ("(blank)"),
337
+ * since an empty label would leave the group looking unnamed rather than
338
+ * named "nothing".
339
+ */
340
+ declare function formatGroupValue<Row>(value: unknown, column: ColumnDefinition<Row, unknown>, locale: FormatLocale, messages: Pick<GridMessages, "booleanTrue" | "booleanFalse" | "blankGroupValue">): string;
341
+
342
+ /**
343
+ * Every string a grid shows or announces of its own — the pager, the group-by
344
+ * bar, the loading row, the text of a boolean or missing value, the labels of
345
+ * its built-in commands, the names of its menus, toolbar and column chooser,
346
+ * and the live-region
347
+ * announcements — so a grid can
348
+ * speak a language other than English. A message that names something takes
349
+ * a function, so a translation can put the name where its own grammar wants
350
+ * it.
351
+ *
352
+ * Text the data supplies (cells, headers, labels) is not here: it is already
353
+ * the app's to choose. Nor is formatting — dates and numbers follow
354
+ * `locale`, and so do the counts the defaults print: "1,204 of 10,000 rows"
355
+ * under `"en"`, "1.204 of 10.000 rows" under `"de-DE"`.
356
+ */
357
+ interface GridMessages {
358
+ /** The pager's accessible name. */
359
+ pagerLabel: string;
360
+ /** The pager button to the first page; drawn as an icon, so this is its accessible name. */
361
+ firstPage: string;
362
+ /** The pager button to the previous page; its accessible name. */
363
+ previousPage: string;
364
+ /** The pager button to the next page; its accessible name. */
365
+ nextPage: string;
366
+ /** The pager button to the last page; its accessible name. */
367
+ lastPage: string;
368
+ /** The page-size control's label. */
369
+ pageSizeLabel: string;
370
+ /** A numbered pager button's accessible name. */
371
+ pageButtonLabel: (page: number) => string;
372
+ /**
373
+ * The compact pager's status, and what a page change announces. `page`
374
+ * counts from one, and is `0` while there are no pages.
375
+ */
376
+ pageStatus: (page: number, pageCount: number) => string;
377
+ /** The row shown while `infiniteScroll` loads more. */
378
+ loadingMore: string;
379
+ /** A boolean cell's text. */
380
+ booleanTrue: string;
381
+ booleanFalse: string;
382
+ /** What a group header names a group of missing values. */
383
+ blankGroupValue: string;
384
+ /** The group-by bar's accessible name. */
385
+ groupByBarLabel: string;
386
+ /** Shown in an empty group-by bar a header can be dragged into. */
387
+ groupByBarPlaceholder: string;
388
+ /** A group-by chip's accessible name. `level` counts from one. */
389
+ groupByChipLabel: (columnName: string, level: number, levelCount: number) => string;
390
+ /** A group-by chip's remove button's accessible name. */
391
+ removeGroupBy: (columnName: string) => string;
392
+ /** Announced when a resize ends, `width` in whole pixels. */
393
+ columnResized: (columnName: string, width: number) => string;
394
+ /** Announced when a column is moved. `position` counts from one. */
395
+ columnMoved: (columnName: string, position: number, columnCount: number) => string;
396
+ /** Announced when a column is sorted. `key` is its place in the sort, from one. */
397
+ columnSorted: (columnName: string, direction: SortDirection, key: number, keyCount: number) => string;
398
+ /** Announced when a column leaves the sort. */
399
+ sortCleared: (columnName: string) => string;
400
+ /** Announced when a column is grouped by. `level` counts from one. */
401
+ groupedBy: (columnName: string, level: number, levelCount: number) => string;
402
+ /** Announced when a column leaves the grouping. */
403
+ groupingRemoved: (columnName: string) => string;
404
+ groupExpanded: string;
405
+ groupCollapsed: string;
406
+ allGroupsExpanded: string;
407
+ allGroupsCollapsed: string;
408
+ /** Announced when one change selects or deselects more than one row or column. */
409
+ selectedCount: (count: number, target: "rows" | "columns") => string;
410
+ /** Announced when a cell is selected. `rowNumber` counts from one. */
411
+ cellSelected: (columnName: string, rowNumber: number) => string;
412
+ /** Announced when one column is hidden. */
413
+ columnHidden: (columnName: string) => string;
414
+ /** Announced when one column is shown. */
415
+ columnShown: (columnName: string) => string;
416
+ /** Announced when one change hides more than one column. */
417
+ columnsHidden: (count: number) => string;
418
+ /** Announced when one change shows more than one column. */
419
+ columnsShown: (count: number) => string;
420
+ /**
421
+ * Announced when one action autofits more than one column, as
422
+ * `column.autoFitAll` does, in place of each column's `columnResized`.
423
+ */
424
+ columnsAutoFitted: (count: number) => string;
425
+ /** A column header's context menu's accessible name. */
426
+ headerMenuLabel: (columnName: string) => string;
427
+ /** A data cell's context menu's accessible name — a menu for its row. */
428
+ cellMenuLabel: string;
429
+ /** A group header row's context menu's accessible name. */
430
+ groupMenuLabel: string;
431
+ /** The accessible name of the menu in the body's empty space. */
432
+ bodyMenuLabel: string;
433
+ /** The built-in `sort.ascending` command's label. */
434
+ sortAscending: string;
435
+ sortDescending: string;
436
+ /** `sort.clear`: takes one column out of the sort. */
437
+ clearSort: string;
438
+ /** `sort.clearAll` */
439
+ clearAllSorting: string;
440
+ /** `group.add`, naming the column it groups by. */
441
+ groupByColumn: (columnName: string) => string;
442
+ /** `group.clearAll`. `group.remove` reads `removeGroupBy`, as the group-by chip's button does. */
443
+ ungroupAll: string;
444
+ expandAllGroups: string;
445
+ collapseAllGroups: string;
446
+ /** `column.hide` */
447
+ hideColumn: string;
448
+ /** `column.autoFit`: sizes the column to its content. */
449
+ autoFitColumn: string;
450
+ autoFitAllColumns: string;
451
+ /** `selection.selectAllRows` */
452
+ selectAllRows: string;
453
+ /** `selection.clear` */
454
+ clearSelection: string;
455
+ /** `filter.clearAll`, which clears the search too. */
456
+ clearFilters: string;
457
+ /** `column.choose`, which opens the column chooser. */
458
+ chooseColumns: string;
459
+ /** The toolbar's accessible name, unless its `label` gives one. */
460
+ toolbarLabel: string;
461
+ /** The toolbar's search box's accessible name. */
462
+ searchLabel: string;
463
+ /** Shown in the toolbar's empty search box. */
464
+ searchPlaceholder: string;
465
+ /** The toolbar's "More" button, holding the items that do not fit. */
466
+ moreToolbarItems: string;
467
+ /** Announced when a search settles: how many rows it found. */
468
+ searchResults: (count: number) => string;
469
+ /** The column chooser's accessible name. */
470
+ columnChooserLabel: string;
471
+ /** The column chooser's search box's accessible name. */
472
+ columnChooserSearchLabel: string;
473
+ /** The column chooser's checkbox showing or hiding every column its search lists. */
474
+ showAllColumns: string;
475
+ /** Shown in the column chooser when its search matches no column. */
476
+ noMatchingColumns: string;
477
+ /**
478
+ * A condition's operator, as a filter menu lists it. `family` is the
479
+ * column's (`filterOperatorFamily`), so a date can read `lt` as "Before"
480
+ * where a number reads "Less than".
481
+ */
482
+ filterOperatorLabel: (operator: FilterOperator, family: FilterOperatorFamily) => string;
483
+ /** A filter checklist's item for the column's blank cells. */
484
+ filterBlanks: string;
485
+ /**
486
+ * Shown in place of a filter checklist whose column holds more values
487
+ * than `filterMenu.valueLimit`, until something is searched.
488
+ */
489
+ filterSearchFirst: (total: number) => string;
490
+ /** Shown under a searched filter checklist `filterMenu.valueLimit` cut short: how many matches it left out. */
491
+ filterMoreValues: (count: number) => string;
492
+ /** `filter.open`, which opens a column's filter menu. */
493
+ openFilter: string;
494
+ /** `filter.clear`, and the filter menu's button doing the same: clears one column's filter. */
495
+ clearColumnFilter: string;
496
+ /** A column's filter menu's accessible name. */
497
+ filterMenuLabel: (columnName: string) => string;
498
+ /** What a column header is described as while its column is filtered. */
499
+ columnFiltered: string;
500
+ /** The filter menu's button applying what it holds. */
501
+ applyFilter: string;
502
+ /** The filter menu's button closing it without applying. */
503
+ cancelFilter: string;
504
+ /**
505
+ * Shown in a filter menu for a filter its editor cannot show — a
506
+ * predicate, a text query, a group across columns — which applying
507
+ * replaces.
508
+ */
509
+ customFilter: string;
510
+ /** Announced when a filter menu applies: how many rows the filter keeps, of how many. */
511
+ filterResults: (shown: number, total: number) => string;
512
+ /** The accessible name of one of a filter menu's conditions. `position` counts from one. */
513
+ filterConditionLabel: (position: number) => string;
514
+ /** The accessible name of a condition's operator picker. */
515
+ filterOperatorFieldLabel: string;
516
+ /** The accessible name of a condition's value box. */
517
+ filterValueLabel: string;
518
+ /** The accessible name of a `between` condition's first value box, its lower end. */
519
+ filterFromLabel: string;
520
+ /** The accessible name of a `between` condition's second value box, its upper end. */
521
+ filterToLabel: string;
522
+ /** The accessible name of the choice joining a filter menu's two conditions. */
523
+ filterCombinatorLabel: string;
524
+ /** Joins two conditions: a row has to meet both. */
525
+ filterAnd: string;
526
+ /** Joins two conditions: a row has to meet either. */
527
+ filterOr: string;
528
+ /**
529
+ * Shown under a filter menu's conditions when one's value is missing or
530
+ * doesn't read as its column's `family` (`filterOperatorFamily`) — "Enter
531
+ * a number" on a number column.
532
+ */
533
+ filterValueInvalid: (family: FilterOperatorFamily) => string;
534
+ /** The accessible name of a filter checklist's search box. */
535
+ filterSearchLabel: string;
536
+ /** The checkbox above a filter checklist checking every value its search shows. */
537
+ filterSelectAll: string;
538
+ /** The accessible name of a filter checklist's list of values. */
539
+ filterValuesLabel: string;
540
+ /**
541
+ * Shown above a filter checklist whose column is filtered by conditions,
542
+ * which checking values replaces.
543
+ */
544
+ filterByCondition: string;
545
+ /**
546
+ * The excel editor's button opening the conditions its column offers, and
547
+ * that menu's accessible name — "Number filters" on a number column, by
548
+ * its `family` (`filterOperatorFamily`).
549
+ */
550
+ filterOperatorMenu: (family: FilterOperatorFamily) => string;
551
+ /** The button taking the excel editor from a condition back to its checklist. */
552
+ filterBackToValues: string;
553
+ /** The toolbar's `"export"` dropdown, listing the export commands. */
554
+ exportMenu: string;
555
+ /** `export.csv` */
556
+ exportCsv: string;
557
+ /** `export.json` */
558
+ exportJson: string;
559
+ /** `export.xlsx`, shown once an xlsx writer is registered. */
560
+ exportXlsx: string;
561
+ /** `export.pdf`, shown once a PDF writer is registered. */
562
+ exportPdf: string;
563
+ /** `exportSelection.csv`: the selected rows only. */
564
+ exportSelectionCsv: string;
565
+ /** `exportSelection.json` */
566
+ exportSelectionJson: string;
567
+ /** `exportSelection.xlsx` */
568
+ exportSelectionXlsx: string;
569
+ /** Announced when an export's writer fails, so no file is saved. */
570
+ exportFailed: string;
571
+ /** `copy.cell` */
572
+ copyCell: string;
573
+ /** `copy.row` */
574
+ copyRow: string;
575
+ /** `copy.selection` */
576
+ copySelection: string;
577
+ /** Announced once a copy is on the clipboard. */
578
+ copied: (count: number, unit: "cells" | "rows" | "columns") => string;
579
+ /** Announced when the browser refuses the clipboard, so nothing was copied. */
580
+ copyFailed: string;
581
+ /** `print` */
582
+ print: string;
583
+ }
584
+ /**
585
+ * The grid's own English, its counts printed in `locale`'s digits —
586
+ * "1,204 of 10,000 rows" under `"en"`, "1.204 of 10.000 rows" under
587
+ * `"de-DE"`. Without a locale, the runtime's own; that one is
588
+ * `defaultMessages`.
589
+ */
590
+ declare function createDefaultMessages(locale?: FormatLocale): GridMessages;
591
+ /** The grid's own English, which `messages` replaces key by key. */
592
+ declare const defaultMessages: GridMessages;
593
+ /**
594
+ * `messages` over the defaults for `locale` — every key the grid needs,
595
+ * whichever the caller gave, the defaults counting in `locale`'s digits. The
596
+ * defaults themselves, same object for the same locale, when it gave none, so
597
+ * a renderer memoising on the result does not see a change that is not one.
598
+ */
599
+ declare function resolveMessages(messages: Partial<GridMessages> | undefined, locale?: FormatLocale): GridMessages;
600
+
601
+ /**
602
+ * A value an export stores as it is rather than as text — what a cell's
603
+ * `ExportCell.value` holds and a column's `exportValue` returns. Narrow on
604
+ * purpose: these are the kinds every format has a reading for (a spreadsheet
605
+ * number, date or boolean cell; a JSON scalar), so nothing a writer cannot
606
+ * represent reaches it.
607
+ */
608
+ type ExportScalar = string | number | boolean | Date | null;
609
+ /**
610
+ * One cell of an export, in both of its readings. `text` is what the grid
611
+ * shows — CSV, the clipboard and print write it, so a file reads as the
612
+ * screen does. `value` is the typed value a spreadsheet stores, so a number
613
+ * stays a number a formula can sum rather than text that looks like one.
614
+ */
615
+ interface ExportCell {
616
+ readonly value: ExportScalar;
617
+ readonly text: string;
618
+ }
619
+ /**
620
+ * A column of an export, settled once so that no writer reads a column
621
+ * definition for itself. `type` and `format` pass through for a writer that
622
+ * keeps typed values, which derives its own number or date format from them.
623
+ */
624
+ interface ExportColumn {
625
+ readonly id: string;
626
+ /** The column's name as text — `resolveColumnHeaderText`, never markup. */
627
+ readonly header: string;
628
+ /** The column's `type`, `"string"` when it has none. */
629
+ readonly type: ColumnType;
630
+ readonly format?: Intl.NumberFormatOptions | Intl.DateTimeFormatOptions | undefined;
631
+ /** How the column's cells align, after falling back to its type. */
632
+ readonly alignment: ColumnAlignment;
633
+ /** Width in px: as rendered for a visible column, as it would start for a hidden one. */
634
+ readonly width: number;
635
+ }
636
+ /** One row of data: a cell per `ExportTable.columns` entry, in that order. */
637
+ interface ExportDataRow {
638
+ readonly kind: "data";
639
+ readonly rowId: string;
640
+ readonly cells: readonly ExportCell[];
641
+ }
642
+ /**
643
+ * A group header. `label` is the header's text, `"Region: West"`; `cells`
644
+ * holds the group's aggregates under their own columns when the grid shows
645
+ * them inline in the header, and is empty text elsewhere — a cell per
646
+ * column either way, so a writer can lay it out like any other row.
647
+ */
648
+ interface ExportGroupRow {
649
+ readonly kind: "group";
650
+ /** Nesting depth, 0 for a top-level group. */
651
+ readonly level: number;
652
+ readonly groupId: string;
653
+ readonly label: string;
654
+ /** Data rows under this group, at every depth. */
655
+ readonly count: number;
656
+ readonly cells: readonly ExportCell[];
657
+ }
658
+ /**
659
+ * A group's aggregates as a row of their own, after everything in the group
660
+ * — present where the grid shows them that way (`groupAggregateDisplay:
661
+ * "row"`), and at the same `level` as its group.
662
+ */
663
+ interface ExportGroupSummaryRow {
664
+ readonly kind: "groupSummary";
665
+ readonly level: number;
666
+ readonly cells: readonly ExportCell[];
667
+ }
668
+ /**
669
+ * A body row of an export, in the order the grid shows them. Discriminate on
670
+ * `kind`.
671
+ */
672
+ type ExportRow = ExportDataRow | ExportGroupRow | ExportGroupSummaryRow;
673
+ /**
674
+ * The grand total — every aggregate over the exported rows. Its own kind
675
+ * rather than an `ExportRow`, since it only ever stands in
676
+ * `ExportTable.footer`, never among the body rows.
677
+ */
678
+ interface ExportTotalRow {
679
+ readonly kind: "total";
680
+ readonly cells: readonly ExportCell[];
681
+ }
682
+ /**
683
+ * What an export writes, whatever the format: the grid's view as data,
684
+ * built by `buildExportTable` from the controller's view and state and
685
+ * never from the page. Every serialiser and writer reads this one shape, so
686
+ * a file, the clipboard and a print cannot disagree.
687
+ */
688
+ interface ExportTable {
689
+ readonly columns: readonly ExportColumn[];
690
+ /** Whether a header row of column names leads the output. */
691
+ readonly header: boolean;
692
+ readonly rows: readonly ExportRow[];
693
+ /** The grand total, or `null` when there are no aggregates to total. */
694
+ readonly footer: ExportTotalRow | null;
695
+ }
696
+ /**
697
+ * Narrows what an export holds. Every field defaults to what the user sees,
698
+ * with nothing hidden by paging or a collapsed group.
699
+ */
700
+ interface ExportOptions {
701
+ /**
702
+ * Which rows: `"all"` (the default) every row the filter, search and sort
703
+ * leave, across every page; `"page"` the data rows on the current page;
704
+ * `"selection"` the selected rows among those `"all"` holds.
705
+ */
706
+ readonly scope?: "all" | "page" | "selection" | undefined;
707
+ /**
708
+ * Which columns: `"visible"` (the default) those shown, in their current
709
+ * order; `"all"` hidden ones too; or a list of column ids, in that order.
710
+ * A column with `exportable: false` is left out of every one.
711
+ */
712
+ readonly columns?: "visible" | "all" | readonly string[] | undefined;
713
+ /**
714
+ * Whether a grouped grid exports its group header rows, every group
715
+ * expanded whatever its state on screen. Defaults to `true`; `false`
716
+ * keeps the rows in grouped order without the headers.
717
+ */
718
+ readonly includeGroups?: boolean | undefined;
719
+ /** Whether group aggregates and the grand total are exported. Defaults to `true`. */
720
+ readonly includeAggregates?: boolean | undefined;
721
+ /** Whether a header row of column names leads the output. Defaults to `true`. */
722
+ readonly includeHeader?: boolean | undefined;
723
+ }
724
+
725
+ /**
726
+ * What an export is built from: the grid's view and state as a controller
727
+ * holds them, never the page — so rows virtualised, paged or scrolled out of
728
+ * sight still export. Typed as the few fields it reads, so a
729
+ * `GridCommandContext` is one as it stands.
730
+ */
731
+ interface ExportSource<Row> {
732
+ readonly view: GridView<Row, unknown>;
733
+ readonly state: Pick<GridState<Row>, "groupBy" | "rowSelection" | "columnSizing">;
734
+ readonly options: {
735
+ readonly locale?: FormatLocale;
736
+ readonly aggregates?: AggregateState<Row> | undefined;
737
+ readonly groupAggregateDisplay?: GroupAggregateDisplay | undefined;
738
+ readonly columnSizeDefaults?: Partial<ColumnSizeDefaults> | undefined;
739
+ };
740
+ readonly messages: Pick<GridMessages, "booleanTrue" | "booleanFalse" | "blankGroupValue">;
741
+ }
742
+ /**
743
+ * The grid's view as an `ExportTable` — the one model every export format,
744
+ * the clipboard and print are written from, so none of them reads the page
745
+ * and none can disagree with another.
746
+ *
747
+ * By default it holds what the user sees, minus what only hides it: every
748
+ * row the filter, search and sort leave, across every page; the visible
749
+ * columns in their current order, less any with `exportable: false`; and,
750
+ * in a grouped grid, every group expanded whatever its state on screen,
751
+ * with its aggregates where the grid shows them. `options` narrows it.
752
+ *
753
+ * Each cell carries the text `formatCellValue` makes of it, so the export
754
+ * reads as the screen does, and a typed value — the column's `exportValue`,
755
+ * else the raw value when it is a string, number, boolean or `Date`.
756
+ *
757
+ * The groups are rebuilt from the exported rows rather than read off
758
+ * `displayRows`, which omits a collapsed group's rows; so group counts,
759
+ * subtotals and the grand total describe exactly the rows exported — the
760
+ * selection, under `scope: "selection"`, not the whole grid.
761
+ */
762
+ declare function buildExportTable<Row>(source: ExportSource<Row>, options?: ExportOptions): ExportTable;
763
+
764
+ /**
765
+ * What a copy is built from: an export's source, with the column and cell
766
+ * selection a selection copy reads as well. A `GridCommandContext` is one
767
+ * as it stands.
768
+ */
769
+ interface CopySource<Row> extends ExportSource<Row> {
770
+ readonly state: Pick<GridState<Row>, "groupBy" | "rowSelection" | "columnSizing" | "columnSelection" | "cellSelection">;
771
+ }
772
+ /**
773
+ * What to copy: one cell, one row, or whatever the grid has selected — the
774
+ * selected rows, else the selected columns, else the selected cell.
775
+ */
776
+ type CopyRequest = {
777
+ readonly kind: "cell";
778
+ readonly rowId: string;
779
+ readonly columnId: string;
780
+ } | {
781
+ readonly kind: "row";
782
+ readonly rowId: string;
783
+ } | {
784
+ readonly kind: "selection";
785
+ };
786
+ /**
787
+ * A copy in the two forms the clipboard carries, with what it holds for the
788
+ * announcement: `count` cells, rows or columns.
789
+ */
790
+ interface CopyContent {
791
+ /** Tab-separated text, as `toTsv` writes it — what a spreadsheet splits into cells. */
792
+ readonly text: string;
793
+ /** The same as an HTML table, as `toHtmlTable` writes it — what a word processor keeps the columns of. */
794
+ readonly html: string;
795
+ readonly count: number;
796
+ readonly unit: "cells" | "rows" | "columns";
797
+ }
798
+ /**
799
+ * What `request` copies, as tab-separated text and an HTML table, or `null`
800
+ * when there is nothing to copy — a row the filter hides, a column hidden
801
+ * or marked `exportable: false`, or an empty selection.
802
+ *
803
+ * Built from the export model, never the page, so a copy holds exactly what
804
+ * an export would and reads as the grid shows it: each cell's formatted
805
+ * text, the shown columns in their order less any with `exportable: false`.
806
+ * The text has no byte order mark and no formula neutralising — what is
807
+ * copied is what is seen, and pasting it is the user's own act.
808
+ *
809
+ * A cell copies its text alone, and a row its cells without a header. A
810
+ * selection copies the selected rows, in the order the grid shows them and
811
+ * under a header row once there are two or more; else the selected columns
812
+ * over every row the filter leaves, under their header; else the selected
813
+ * cell.
814
+ */
815
+ declare function copyContent<Row>(source: CopySource<Row>, request: CopyRequest): CopyContent | null;
816
+
817
+ /** Which way the paper is turned. */
818
+ type PrintOrientation = "portrait" | "landscape";
819
+ /**
820
+ * How a grid prints: which rows and columns (every `ExportOptions` field),
821
+ * the text around the table, and the page it is laid out on. The grid's
822
+ * `print` option.
823
+ */
824
+ interface PrintOptions extends ExportOptions {
825
+ /** A heading above the table, and the printed document's title. */
826
+ readonly title?: string | undefined;
827
+ /** A line under the title. */
828
+ readonly subtitle?: string | undefined;
829
+ /** A line after the table. */
830
+ readonly footer?: string | undefined;
831
+ /**
832
+ * When the print was made, under the title: `true` for now, or a `Date`
833
+ * to print instead. Off by default.
834
+ */
835
+ readonly timestamp?: boolean | Date | undefined;
836
+ /** The language the timestamp is written in. Defaults to the grid's. */
837
+ readonly locale?: FormatLocale;
838
+ /**
839
+ * Which way the paper is turned. Defaults to `"landscape"` for a table of
840
+ * more than six columns, which rarely fits a portrait page, else
841
+ * `"portrait"`.
842
+ */
843
+ readonly orientation?: PrintOrientation | undefined;
844
+ /**
845
+ * A page size CSS names — `"A4"` (the default), `"Letter"`, `"A3"`,
846
+ * `"Legal"`.
847
+ */
848
+ readonly paperSize?: "A4" | "Letter" | (string & {}) | undefined;
849
+ /** Whether each page is numbered, "3 / 12", where the browser can. Defaults to `true`. */
850
+ readonly pageNumbers?: boolean | undefined;
851
+ /**
852
+ * Whether a wide table is squeezed onto the page — a smaller font and
853
+ * fixed column widths that wrap their text — rather than run off its
854
+ * edge. Defaults to `false`.
855
+ */
856
+ readonly fitToWidth?: boolean | undefined;
857
+ /** CSS added after the print stylesheet, to restyle the printed table. */
858
+ readonly styles?: string | undefined;
859
+ }
860
+ /**
861
+ * The page a print is laid out on, every choice settled — what
862
+ * `@gridkitjs/dom`'s `printStyles` turns into the page's CSS.
863
+ */
864
+ interface PrintPage {
865
+ readonly paperSize: string;
866
+ readonly orientation: PrintOrientation;
867
+ readonly pageNumbers: boolean;
868
+ readonly fitToWidth: boolean;
869
+ }
870
+ /** A print ready for a renderer to put on paper: what `buildPrintDocument` returns. */
871
+ interface PrintDocument {
872
+ /**
873
+ * The document's title as text, `""` when untitled — what the browser
874
+ * puts in a page's header and names a PDF saved from the print dialog.
875
+ */
876
+ readonly title: string;
877
+ /** The `<body>`'s markup: the heading, the table and the footer, every piece of text escaped. */
878
+ readonly bodyHtml: string;
879
+ readonly page: PrintPage;
880
+ }
881
+ /**
882
+ * The table as a printable document: its heading — the title, subtitle and
883
+ * timestamp `options` set — then the table as `toHtmlTable` writes it, then
884
+ * the footer line, with the page it is laid out on. Every piece of text is
885
+ * escaped. It holds no styles: putting it on paper, with a stylesheet for
886
+ * the page, is the renderer's — `@gridkitjs/dom`'s `printStyles` and
887
+ * `printDocument` in a browser.
888
+ *
889
+ * The heading and footer carry semantic class names for a stylesheet:
890
+ * `gridkit-print-header` around `print-title`, `print-subtitle` and
891
+ * `print-timestamp`, and `gridkit-print-footer`.
892
+ */
893
+ declare function buildPrintDocument(table: ExportTable, options?: PrintOptions): PrintDocument;
894
+ /**
895
+ * What `exportPrintDocument` prints from: an `ExportSource` that may carry
896
+ * the grid's `label`. A `GridCommandContext` is one as it stands.
897
+ */
898
+ interface PrintSource<Row> extends ExportSource<Row> {
899
+ readonly options: ExportSource<Row>["options"] & {
900
+ readonly label?: string | undefined;
901
+ };
902
+ }
903
+ /**
904
+ * The grid's view as a print document: the table `options` narrow, laid out
905
+ * as `buildPrintDocument` lays it out, with the timestamp in the grid's
906
+ * locale unless `options` name another. Given no `title`, it takes the
907
+ * grid's `label` — the name a screen reader already reads for it; `""`
908
+ * leaves it untitled.
909
+ */
910
+ declare function exportPrintDocument<Row>(source: PrintSource<Row>, options?: PrintOptions): PrintDocument;
911
+
912
+ /** How `toCsv` writes a file. Every field is optional. */
913
+ interface CsvOptions {
914
+ /**
915
+ * The field separator: `","` by default, any string, or `"auto"` for the
916
+ * separator a spreadsheet expects in `locale` — `";"` where a decimal is
917
+ * written with a comma, as in most of Europe, since a comma there is part
918
+ * of a number; `","` elsewhere.
919
+ */
920
+ readonly delimiter?: string | undefined;
921
+ /** The locale `delimiter: "auto"` reads; the runtime's own when absent. */
922
+ readonly locale?: FormatLocale;
923
+ /** What ends each record. Defaults to `"\r\n"`, as RFC 4180 writes it. */
924
+ readonly eol?: string | undefined;
925
+ /**
926
+ * Whether the file starts with a UTF-8 byte order mark. Defaults to
927
+ * `true`: without one, Excel reads the file in the system's legacy code
928
+ * page and garbles every character outside ASCII.
929
+ */
930
+ readonly bom?: boolean | undefined;
931
+ /**
932
+ * Whether a field a spreadsheet would run as a formula is written as text
933
+ * instead. Defaults to `true`; see `toCsv`.
934
+ */
935
+ readonly neutralizeFormulas?: boolean | undefined;
936
+ /**
937
+ * Which reading of each cell is written: `"text"` (the default), as the
938
+ * grid shows it; or `"raw"`, the typed value — numbers plain, dates in ISO
939
+ * 8601, booleans as `true` and `false` — for a file a program reads.
940
+ */
941
+ readonly values?: "text" | "raw" | undefined;
942
+ }
943
+ /**
944
+ * The table as CSV, quoted per RFC 4180: a field is quoted when it holds the
945
+ * delimiter, a quote or a line break, and a quote inside one is doubled, so
946
+ * a line break inside a cell survives. A group row writes its label in the
947
+ * first column; summary rows and the footer write their aggregates under
948
+ * their columns.
949
+ *
950
+ * A CSV file opened in a spreadsheet runs any field that starts with `=`,
951
+ * `+`, `-` or `@` as a formula — and a tab or a carriage return can hide
952
+ * such a start — so a value a user typed into the data could make another
953
+ * user's spreadsheet fetch a URL or run a command. By default such a field
954
+ * gets a leading `'`, which the spreadsheet shows as text. A cell whose
955
+ * value is a number keeps its leading sign, since it is one.
956
+ *
957
+ * Returns a string, not a file: making a `Blob` of it, with the type
958
+ * `text/csv;charset=utf-8`, is the renderer's job.
959
+ */
960
+ declare function toCsv(table: ExportTable, options?: CsvOptions): string;
961
+
962
+ /** How `toJson` writes its text. Every field is optional. */
963
+ interface JsonOptions {
964
+ /**
965
+ * What each record is keyed by: `"id"` (the default), the column's id,
966
+ * stable whatever the header says; or `"header"`, its header text, for a
967
+ * reader who sees the keys. A header repeated across columns is suffixed
968
+ * ` (2)`, ` (3)` and so on, so no column overwrites another.
969
+ */
970
+ readonly keys?: "id" | "header" | undefined;
971
+ /** Indentation, as `JSON.stringify` takes it; none by default. */
972
+ readonly space?: number | string | undefined;
973
+ }
974
+ /**
975
+ * The table's data rows as a JSON array of objects, one property per
976
+ * column holding the cell's typed value — a number stays a number, a `Date`
977
+ * becomes its ISO 8601 string. Group headers, summary rows and the footer
978
+ * are left out: JSON is read by programs, which group and total for
979
+ * themselves, and a row that is not data would only have to be filtered
980
+ * out again.
981
+ *
982
+ * Returns a string; making a `Blob` of it, with the type
983
+ * `application/json`, is the renderer's job.
984
+ */
985
+ declare function toJson(table: ExportTable, options?: JsonOptions): string;
986
+
987
+ /**
988
+ * How a grid exports unless a call says otherwise: which rows and columns
989
+ * (every `ExportOptions` field), what the file is called, and each built-in
990
+ * format's settings. The grid's `export` option.
991
+ */
992
+ interface GridExportOptions extends ExportOptions {
993
+ /**
994
+ * The file's name, without its extension — the writer's is added unless
995
+ * the name already ends with it. A function is asked per export with the
996
+ * format, `"csv"` or `"xlsx"`. Defaults to `"export"`.
997
+ */
998
+ readonly fileName?: string | ((format: string) => string) | undefined;
999
+ /**
1000
+ * How the CSV writer writes. Its `locale`, which `delimiter: "auto"`
1001
+ * reads, defaults to the grid's.
1002
+ */
1003
+ readonly csv?: CsvOptions | undefined;
1004
+ /** How the JSON writer writes. */
1005
+ readonly json?: JsonOptions | undefined;
1006
+ }
1007
+ /** What a writer is given beside the table: the grid's language and the export's settings. */
1008
+ interface ExportWriteContext {
1009
+ /** The grid's `locale`. */
1010
+ readonly locale: FormatLocale;
1011
+ /** The grid's messages, over the defaults. */
1012
+ readonly messages: GridMessages;
1013
+ /**
1014
+ * The export's options, where a writer finds its own settings: the CSV
1015
+ * writer reads `csv`, the JSON writer `json`. A writer of the app's own
1016
+ * takes its settings when it is made instead, as a closure.
1017
+ */
1018
+ readonly options: GridExportOptions;
1019
+ }
1020
+ /**
1021
+ * One export format: how to write an `ExportTable` as a file of it, and what
1022
+ * the file is. CSV and JSON ship with the grid; any other — xlsx from
1023
+ * `@gridkitjs/export-xlsx`, or one of the app's own — is registered through
1024
+ * the grid's `exportWriters`.
1025
+ *
1026
+ * `write` returns the file's contents, not a file: text, bytes, or a promise
1027
+ * of either for a writer that loads a library first. Making a `Blob` of it
1028
+ * is the renderer's job.
1029
+ */
1030
+ interface ExportWriter {
1031
+ /** The id the grid knows it by — `"csv"`, `"xlsx"`; one per grid. */
1032
+ readonly format: string;
1033
+ /** Without the dot: `"csv"`. */
1034
+ readonly fileExtension: string;
1035
+ /** The file's media type, the `Blob`'s `type`. */
1036
+ readonly mimeType: string;
1037
+ readonly write: (table: ExportTable, context: ExportWriteContext) => string | Uint8Array | Promise<string | Uint8Array>;
1038
+ }
1039
+ /** An export ready to save: what `exportFile` hands a renderer to download. */
1040
+ interface ExportFile {
1041
+ /** With its extension: `"export.csv"`. */
1042
+ readonly fileName: string;
1043
+ readonly mimeType: string;
1044
+ readonly content: string | Uint8Array;
1045
+ }
1046
+ /** CSV through `toCsv`, its delimiter read for the grid's locale unless `csv.locale` says otherwise. */
1047
+ declare const csvWriter: ExportWriter;
1048
+ /** The data rows as JSON, through `toJson`. */
1049
+ declare const jsonWriter: ExportWriter;
1050
+ /**
1051
+ * Every writer a grid can export with, by format: CSV and JSON, then
1052
+ * `writers` — one with a built-in's format replacing it, as an app command
1053
+ * replaces a built-in of the same id.
1054
+ */
1055
+ declare function resolveExportWriters(writers: readonly ExportWriter[] | undefined): ReadonlyMap<string, ExportWriter>;
1056
+
1057
+ /**
1058
+ * Where a command was asked for: the part of the grid a menu was opened on,
1059
+ * the toolbar item pressed, or nowhere in particular for a call through a
1060
+ * renderer's API. A built-in reads the column, row or group it acts on from
1061
+ * here, and is hidden on a target that has none.
1062
+ */
1063
+ type GridCommandTarget = {
1064
+ readonly area: "header";
1065
+ readonly columnId: string;
1066
+ } | {
1067
+ readonly area: "cell";
1068
+ readonly rowId: string;
1069
+ readonly columnId: string;
1070
+ } | {
1071
+ readonly area: "group";
1072
+ readonly groupId: string;
1073
+ readonly columnId: string;
1074
+ }
1075
+ /** Empty body space, or a grid with no rows. */
1076
+ | {
1077
+ readonly area: "body";
1078
+ } | {
1079
+ readonly area: "toolbar";
1080
+ readonly itemId: string;
1081
+ }
1082
+ /** A renderer's API, with no particular place. */
1083
+ | {
1084
+ readonly area: "grid";
1085
+ };
1086
+ /**
1087
+ * Where a command was run from: a context menu, the toolbar, a renderer's
1088
+ * API, or a column's filter menu — its sort entries and its "Clear filter".
1089
+ */
1090
+ type GridCommandSource = "contextMenu" | "toolbar" | "api" | "filterMenu";
1091
+ /** What `onCommand` is told of a command, or an inline menu item, that ran. */
1092
+ interface GridCommandEvent {
1093
+ /** The command's id, or the inline item's. */
1094
+ readonly commandId: string;
1095
+ /** Where it was asked for. */
1096
+ readonly target: GridCommandTarget;
1097
+ readonly source: GridCommandSource;
1098
+ }
1099
+ /**
1100
+ * The panels a command can ask a renderer to open: the column chooser, and
1101
+ * a column's filter menu, which opens on a header target only.
1102
+ */
1103
+ type GridPanelKind = "columnChooser" | "filter";
1104
+ /**
1105
+ * What a command needs that only a renderer has: a DOM to measure, panels to
1106
+ * open, a live region to speak through. A caller with none of these — a test,
1107
+ * a script in Node — passes members that do nothing.
1108
+ */
1109
+ interface GridCommandHost {
1110
+ /** Sizes each column to fit its content, as double-clicking its resize handle does. */
1111
+ readonly autoFitColumns: (columnIds: readonly string[]) => void;
1112
+ /** Opens one of the grid's panels, anchored to where the command was asked for. */
1113
+ readonly openPanel: (kind: GridPanelKind, target: GridCommandTarget) => void;
1114
+ /** Reads `text` out through the grid's live region. */
1115
+ readonly announce: (text: string) => void;
1116
+ /**
1117
+ * Saves an export as a file — in a browser, a download. A promise is the
1118
+ * file of a writer still writing; the host waits for it, and reports a
1119
+ * rejected one rather than saving.
1120
+ */
1121
+ readonly saveFile: (file: ExportFile | Promise<ExportFile>) => void;
1122
+ /**
1123
+ * Puts a copy on the clipboard, as text and as HTML, and announces it —
1124
+ * `count` and `unit` say what to announce — or that the browser refused.
1125
+ */
1126
+ readonly writeClipboard: (content: CopyContent) => void;
1127
+ /**
1128
+ * Puts a print document on paper — in a browser, through the print
1129
+ * dialog. `options` are those it was built under, for what the host adds
1130
+ * itself, such as `styles` over its print stylesheet.
1131
+ */
1132
+ readonly print: (document: PrintDocument, options: PrintOptions) => void;
1133
+ }
1134
+ /**
1135
+ * Every action of the controller — the only way a command changes state, so
1136
+ * each change reports through its slice's callback exactly as the user's own
1137
+ * gesture would. Leaves out `setOptions`, which is the renderer's alone,
1138
+ * `subscribe`, and the getters whose results the context already carries.
1139
+ *
1140
+ * Nothing left names the renderer's node type, so a controller of any `Node`
1141
+ * is one.
1142
+ */
1143
+ type GridCommandActions<Row> = Omit<GridController<Row, unknown>, "getOptions" | "setOptions" | "subscribe" | "getState" | "getView">;
1144
+ /**
1145
+ * Everything a command reads to decide whether it shows, whether it is
1146
+ * enabled and what it does — one snapshot of the grid, taken when a menu or
1147
+ * toolbar is resolved. Build one with `createCommandContext`.
1148
+ */
1149
+ interface GridCommandContext<Row> {
1150
+ readonly target: GridCommandTarget;
1151
+ readonly state: GridState<Row>;
1152
+ readonly view: GridView<Row, unknown>;
1153
+ readonly options: GridOptions<Row>;
1154
+ readonly messages: GridMessages;
1155
+ readonly actions: GridCommandActions<Row>;
1156
+ readonly host: GridCommandHost;
1157
+ /** The row a cell target is on; `null` for any other target, or a row the filter hides. */
1158
+ readonly row: ResolvedRow<Row> | null;
1159
+ /** The column a header, cell or group target names, hidden or not; `null` otherwise. */
1160
+ readonly column: DataColumn<Row, unknown> | null;
1161
+ /**
1162
+ * The selected rows that pass the filter, in the order they are shown,
1163
+ * across every page and collapsed group. A function, computed on first
1164
+ * call and remembered: resolving it walks every filtered row, and a toolbar
1165
+ * builds a context on every change without most commands ever asking.
1166
+ */
1167
+ readonly selectedRows: () => readonly ResolvedRow<Row>[];
1168
+ }
1169
+ /**
1170
+ * The one implementation behind a menu item, a toolbar button and a
1171
+ * renderer's `runCommand`. Whether it shows and whether it is enabled are
1172
+ * predicates over the context, asked each time a menu or toolbar is resolved,
1173
+ * so a command follows the grid's state without being told about it.
1174
+ */
1175
+ interface GridCommand<Row> {
1176
+ /** `"sort.ascending"` for a built-in, or any id of the app's own. Never `"separator"`, which a menu reads as one. */
1177
+ readonly id: string;
1178
+ readonly label: string | ((context: GridCommandContext<Row>) => string);
1179
+ /** A key the renderer maps to an icon of its own; a key it does not know draws nothing. */
1180
+ readonly icon?: string | undefined;
1181
+ /** A key-combination hint in `aria-keyshortcuts` syntax, such as `"Alt+ArrowUp"`. Shown, not bound. */
1182
+ readonly shortcut?: string | undefined;
1183
+ /** Whether the command shows here at all. Defaults to always. */
1184
+ readonly isVisible?: ((context: GridCommandContext<Row>) => boolean) | undefined;
1185
+ /** Whether it can run. A disabled command still shows, so a user can see what is not possible. Defaults to always. */
1186
+ readonly isEnabled?: ((context: GridCommandContext<Row>) => boolean) | undefined;
1187
+ /** Present for a checkable command — drawn as a checkbox item or a toggle button — and says whether it is checked. */
1188
+ readonly isChecked?: ((context: GridCommandContext<Row>) => boolean) | undefined;
1189
+ readonly execute: (context: GridCommandContext<Row>) => void;
1190
+ }
1191
+
1192
+ /** The id of every command `builtInCommands` returns. */
1193
+ type BuiltInCommandId = "sort.ascending" | "sort.descending" | "sort.clear" | "sort.clearAll" | "group.add" | "group.remove" | "group.clearAll" | "group.expandAll" | "group.collapseAll" | "column.hide" | "column.autoFit" | "column.autoFitAll" | "column.choose" | "filter.open" | "filter.clear" | "selection.selectAllRows" | "selection.clear" | "filter.clearAll" | "export.csv" | "export.json" | "export.xlsx" | "export.pdf" | "exportSelection.csv" | "exportSelection.json" | "exportSelection.xlsx" | "copy.cell" | "copy.row" | "copy.selection" | "print";
1194
+ /**
1195
+ * The icon keys the built-ins carry, which a renderer draws as icons of its
1196
+ * own. An app command may use them too, to look like the built-ins.
1197
+ */
1198
+ type BuiltInCommandIcon = "sortAscending" | "sortDescending" | "group" | "hide" | "autoFit" | "copy" | "print";
1199
+ /**
1200
+ * The grid's own commands, one per action its menus and toolbar offer —
1201
+ * sorting, grouping, hiding, fitting and choosing columns, selecting,
1202
+ * clearing, exporting, copying and printing.
1203
+ * Labels come from `messages`, so they follow the grid's language.
1204
+ *
1205
+ * A function rather than a constant so each comes typed for the caller's
1206
+ * `Row`; the commands hold no state, and two calls build equal ones.
1207
+ */
1208
+ declare function builtInCommands<Row>(): readonly GridCommand<Row>[];
1209
+
1210
+ /** A value given outright, or worked out from the context each time the menu is resolved. */
1211
+ type FromContext<Row, Value> = Value | ((context: GridCommandContext<Row>) => Value);
1212
+ /**
1213
+ * An item written into the menu itself rather than registered as a command —
1214
+ * for an action only one menu offers.
1215
+ */
1216
+ interface MenuItemEntry<Row> {
1217
+ readonly type: "item";
1218
+ readonly id: string;
1219
+ readonly label: FromContext<Row, string>;
1220
+ readonly icon?: string | undefined;
1221
+ readonly shortcut?: string | undefined;
1222
+ readonly hidden?: FromContext<Row, boolean> | undefined;
1223
+ readonly disabled?: FromContext<Row, boolean> | undefined;
1224
+ /** Present for a checkable item, and says whether it is checked. */
1225
+ readonly checked?: FromContext<Row, boolean> | undefined;
1226
+ readonly onSelect: (context: GridCommandContext<Row>) => void;
1227
+ }
1228
+ /** An item that opens a menu of its own. Left out when nothing in it shows. */
1229
+ interface MenuSubmenuEntry<Row> {
1230
+ readonly type: "submenu";
1231
+ readonly id: string;
1232
+ readonly label: FromContext<Row, string>;
1233
+ readonly icon?: string | undefined;
1234
+ readonly items: readonly MenuEntry<Row>[];
1235
+ }
1236
+ /**
1237
+ * One entry of a menu as an app writes it: a command id — a built-in's or
1238
+ * one of its own — `"separator"`, an inline item or a submenu. The same
1239
+ * vocabulary every menu and toolbar is listed in.
1240
+ */
1241
+ type MenuEntry<Row> = BuiltInCommandId | "separator" | (string & {}) | MenuItemEntry<Row> | MenuSubmenuEntry<Row>;
1242
+ /**
1243
+ * A menu item ready to draw: every label a string, every flag a boolean, and
1244
+ * `run` bound to the context the menu was resolved in.
1245
+ */
1246
+ interface ResolvedMenuItem {
1247
+ readonly type: "item";
1248
+ /** The command's id, or the inline item's. */
1249
+ readonly id: string;
1250
+ readonly label: string;
1251
+ readonly icon?: string | undefined;
1252
+ readonly shortcut?: string | undefined;
1253
+ /** Drawn, and focusable, but `run` does nothing. */
1254
+ readonly disabled: boolean;
1255
+ /** `undefined` for an item that is not checkable. */
1256
+ readonly checked: boolean | undefined;
1257
+ /**
1258
+ * Runs the item — a command only when it is still visible and enabled —
1259
+ * and says whether it ran, so a renderer reports only what did something.
1260
+ */
1261
+ readonly run: () => boolean;
1262
+ }
1263
+ interface ResolvedMenuSubmenu {
1264
+ readonly type: "submenu";
1265
+ readonly id: string;
1266
+ readonly label: string;
1267
+ readonly icon?: string | undefined;
1268
+ /** Never empty: a submenu with nothing to show is left out. */
1269
+ readonly items: readonly ResolvedMenuEntry[];
1270
+ }
1271
+ interface ResolvedMenuSeparator {
1272
+ readonly type: "separator";
1273
+ /**
1274
+ * The separator's place among the entries it was resolved from, which
1275
+ * stays put however the items around it come and go — a key for a
1276
+ * renderer that needs one, unique among its menu's separators.
1277
+ */
1278
+ readonly key: string;
1279
+ }
1280
+ /** One entry of a menu as `resolveMenu` hands it to a renderer to draw. */
1281
+ type ResolvedMenuEntry = ResolvedMenuItem | ResolvedMenuSubmenu | ResolvedMenuSeparator;
1282
+
1283
+ /** The parts of a grid that open a context menu of their own. */
1284
+ type GridContextMenuArea = "header" | "cell" | "group" | "body";
1285
+ /**
1286
+ * Where a context menu opens: a command target in one of the context menu
1287
+ * areas — a column header, a data cell, a group header row, or empty space
1288
+ * in the body — or in `Area` alone.
1289
+ */
1290
+ type GridContextMenuTarget<Area extends GridContextMenuArea = GridContextMenuArea> = Extract<GridCommandTarget, {
1291
+ readonly area: Area;
1292
+ }>;
1293
+ /** What `onContextMenuOpenChange` is told as a context menu opens or closes. */
1294
+ interface ContextMenuOpenChangeEvent {
1295
+ readonly open: boolean;
1296
+ /** Where the menu opened, or where the one closing had. */
1297
+ readonly target: GridContextMenuTarget;
1298
+ }
1299
+ /** What a function given for an area is asked, each time its menu opens. */
1300
+ interface GridContextMenuRequest<Row, Area extends GridContextMenuArea = GridContextMenuArea> {
1301
+ /** Where the menu opens. */
1302
+ readonly target: GridContextMenuTarget<Area>;
1303
+ /** The area's default entries, to keep, trim, reorder or add to. */
1304
+ readonly defaults: readonly MenuEntry<Row>[];
1305
+ /** The grid as the menu sees it — the context its items run in. */
1306
+ readonly context: GridCommandContext<Row>;
1307
+ }
1308
+ /**
1309
+ * An area's menu: its entries, or a function that works them out each time
1310
+ * the menu opens — from where it opens, the area's defaults and the grid's
1311
+ * state. A function giving `null` or `[]` shows no grid menu there, so the
1312
+ * browser's own menu shows.
1313
+ */
1314
+ type GridContextMenuEntries<Row, Area extends GridContextMenuArea = GridContextMenuArea> = readonly MenuEntry<Row>[] | ((request: GridContextMenuRequest<Row, Area>) => readonly MenuEntry<Row>[] | null);
1315
+ /**
1316
+ * A grid's context menus, by area, in the vocabulary every grid menu is
1317
+ * written in. An area left out shows its defaults; one given `[]` shows no
1318
+ * grid menu, so the browser's own menu shows there.
1319
+ */
1320
+ interface GridContextMenuOptions<Row> {
1321
+ /** A column header's menu. */
1322
+ readonly header?: GridContextMenuEntries<Row, "header"> | undefined;
1323
+ /** A data cell's menu, acting on its row and cell. */
1324
+ readonly cell?: GridContextMenuEntries<Row, "cell"> | undefined;
1325
+ /** A group header row's menu. */
1326
+ readonly group?: GridContextMenuEntries<Row, "group"> | undefined;
1327
+ /** The menu of the body's empty space, below the last row or in a grid with none. */
1328
+ readonly body?: GridContextMenuEntries<Row, "body"> | undefined;
1329
+ }
1330
+ /**
1331
+ * The menu each area shows unless the grid says otherwise — built-in
1332
+ * commands only, each hidden where it has nothing to act on, so the menu a
1333
+ * column header shows holds only what that column can do. The body has
1334
+ * none: empty space keeps the browser's menu until a grid gives it one.
1335
+ */
1336
+ declare const defaultContextMenu: {
1337
+ readonly [Area in GridContextMenuArea]: readonly (BuiltInCommandId | "separator")[];
1338
+ };
1339
+ /**
1340
+ * Whether the `contextMenu` option opens a grid menu on `area` at all: it is
1341
+ * on, and gives the area entries or a function rather than `[]`. A function
1342
+ * may still give no menu for one place or another; this answers for the
1343
+ * area, as a cell's `aria-keyshortcuts` needs to before anything is asked.
1344
+ */
1345
+ declare function hasContextMenu<Row>(contextMenu: boolean | GridContextMenuOptions<Row> | undefined, area: GridContextMenuArea): boolean;
1346
+ /**
1347
+ * The entries a grid's `contextMenu` option gives the place `context.target`
1348
+ * names, to resolve with `resolveMenu` in that same context: none while the
1349
+ * option is off — left out or `false` — or for a target no context menu
1350
+ * opens on; the area's defaults under `true` or when the option leaves the
1351
+ * area out; the entries it lists; or what its function gives this request.
1352
+ * No entries means no grid menu there.
1353
+ */
1354
+ declare function contextMenuEntries<Row>(contextMenu: boolean | GridContextMenuOptions<Row> | undefined, context: GridCommandContext<Row>): readonly MenuEntry<Row>[];
1355
+
1356
+ /** Where a toolbar item's command runs: the toolbar item it was asked from. */
1357
+ type GridToolbarTarget = Extract<GridCommandTarget, {
1358
+ readonly area: "toolbar";
1359
+ }>;
1360
+ /**
1361
+ * A place in the toolbar the renderer fills with content of the app's own —
1362
+ * React's `renderToolbarItem(id)` — for anything the entries cannot say.
1363
+ */
1364
+ interface ToolbarCustomEntry {
1365
+ readonly type: "custom";
1366
+ readonly id: string;
1367
+ }
1368
+ /**
1369
+ * One entry of a toolbar as an app writes it: anything a menu lists — a
1370
+ * command id, `"separator"`, an inline item, or a submenu, which the toolbar
1371
+ * draws as a dropdown button — plus the entries only a toolbar has:
1372
+ * `"search"`, the box searching every column; `"spacer"`, which takes up the
1373
+ * free space and so pushes what follows it to the far end; `"export"`, a
1374
+ * dropdown of the export commands that show; and a custom entry.
1375
+ */
1376
+ type ToolbarEntry<Row> = MenuEntry<Row> | "search" | "spacer" | "export" | ToolbarCustomEntry;
1377
+ /**
1378
+ * A toolbar button ready to draw — a command, or an inline item — with
1379
+ * every label a string, every flag a boolean, and `run` bound to the
1380
+ * context of its place in the toolbar.
1381
+ */
1382
+ interface ResolvedToolbarButton {
1383
+ readonly type: "button";
1384
+ /** The command's id, or the inline item's. */
1385
+ readonly id: string;
1386
+ /** The same as `id`. */
1387
+ readonly key: string;
1388
+ readonly label: string;
1389
+ readonly icon?: string | undefined;
1390
+ readonly shortcut?: string | undefined;
1391
+ /** Drawn, and focusable, but `run` does nothing. */
1392
+ readonly disabled: boolean;
1393
+ /**
1394
+ * Whether a toggle button is pressed — `undefined` for a button that is
1395
+ * not one: a checkable command or item draws as a toggle.
1396
+ */
1397
+ readonly pressed: boolean | undefined;
1398
+ /** Runs the button, and says whether it ran — see `ResolvedMenuItem.run`. */
1399
+ readonly run: () => boolean;
1400
+ }
1401
+ /** A dropdown button, opening the menu its submenu entry lists. */
1402
+ interface ResolvedToolbarMenu {
1403
+ readonly type: "menu";
1404
+ readonly id: string;
1405
+ /** The same as `id`. */
1406
+ readonly key: string;
1407
+ readonly label: string;
1408
+ readonly icon?: string | undefined;
1409
+ /** Never empty: a dropdown with nothing to show is left out. */
1410
+ readonly items: readonly ResolvedMenuEntry[];
1411
+ }
1412
+ /** The search box, over the grid's global text filter. */
1413
+ interface ResolvedToolbarSearch {
1414
+ readonly type: "search";
1415
+ /** Always `"search"`. */
1416
+ readonly key: string;
1417
+ }
1418
+ /** The free space between the entries either side of it. */
1419
+ interface ResolvedToolbarSpacer {
1420
+ readonly type: "spacer";
1421
+ /** `spacer-<index>`, from its place among the entries it was resolved from. */
1422
+ readonly key: string;
1423
+ }
1424
+ /** A custom entry's place, for the renderer to fill. */
1425
+ interface ResolvedToolbarCustom {
1426
+ readonly type: "custom";
1427
+ readonly id: string;
1428
+ /** The same as `id`. */
1429
+ readonly key: string;
1430
+ }
1431
+ /**
1432
+ * One entry of a toolbar as `resolveToolbar` hands it to a renderer to draw.
1433
+ * Each has a `key` — an item's id, `"search"`, or a separator's or spacer's
1434
+ * place among the entries — unique among the toolbar's entries, which the
1435
+ * renderer writes into the entry's `data-gridkit-toolbar-item`.
1436
+ */
1437
+ type ResolvedToolbarItem = ResolvedToolbarButton | ResolvedToolbarMenu | ResolvedToolbarSearch | ResolvedToolbarSpacer | ResolvedMenuSeparator | ResolvedToolbarCustom;
1438
+
1439
+ /** A grid's toolbar: what it lists, and what a screen reader calls it. */
1440
+ interface GridToolbarOptions<Row> {
1441
+ /** The toolbar's entries, in order. Left out, the defaults. */
1442
+ readonly items?: readonly ToolbarEntry<Row>[] | undefined;
1443
+ /** The toolbar's accessible name. Left out, `messages.toolbarLabel`. */
1444
+ readonly label?: string | undefined;
1445
+ }
1446
+ /**
1447
+ * What a toolbar lists unless the grid says otherwise: the search box, then
1448
+ * the free space, then "Clear filters" and "Choose columns" at the far end.
1449
+ */
1450
+ declare const defaultToolbar: readonly (BuiltInCommandId | "search" | "spacer")[];
1451
+ /**
1452
+ * The entries a grid's `toolbar` option lists, to resolve with
1453
+ * `resolveToolbar`: none while it is off — left out or `false` — the
1454
+ * defaults under `true` or an object without `items`, else its `items`.
1455
+ * No entries means no toolbar.
1456
+ */
1457
+ declare function toolbarEntries<Row>(toolbar: boolean | GridToolbarOptions<Row> | undefined): readonly ToolbarEntry<Row>[];
1458
+
1459
+ /** Which cell borders a grid draws. */
1460
+ type Borders = "horizontal" | "vertical" | "all" | "none";
1461
+ /** Which hover highlighting a grid shows. Every member defaults to on. */
1462
+ interface HoverableConfig {
1463
+ rows?: boolean;
1464
+ columns?: boolean;
1465
+ cells?: boolean;
1466
+ }
1467
+ /**
1468
+ * How the group-by bar's visibility follows the active grouping. `"always"`
1469
+ * renders it even with an empty `groupBy` — a fixed drop target and a
1470
+ * constant reminder grouping exists. `"never"` never renders it, for a grid
1471
+ * driving `groupBy` entirely by its own UI (a header toggle, `Alt+ArrowDown`)
1472
+ * or programmatically. `"auto"` renders it once `groupBy` is non-empty, or
1473
+ * while a header drag eligible to drop into it is in progress — so there is
1474
+ * always somewhere to drop the very first column, even from a fully empty
1475
+ * grouping.
1476
+ */
1477
+ type GroupByBarVisibility = "always" | "auto" | "never";
1478
+ /**
1479
+ * What `getRowProps` adds to a data row: a class for the theme or the
1480
+ * app's own stylesheet to target, and `data-*` attributes for a test or a
1481
+ * script to find the row by. No inline style — styling belongs to the
1482
+ * stylesheet, which a class already reaches.
1483
+ */
1484
+ interface RowProps {
1485
+ className?: string | undefined;
1486
+ /**
1487
+ * Set on the row alongside the grid's own `data-gridkit-*` attributes,
1488
+ * which win over one of the same name — the grid finds its rows by them.
1489
+ */
1490
+ attributes?: Readonly<Record<`data-${string}`, string>> | undefined;
1491
+ }
1492
+ /**
1493
+ * Every setting of a grid that names no renderer's types: the data, what the
1494
+ * user may do with it, the state it starts in and the callbacks that report
1495
+ * changes. A renderer's own props are this plus what only it can express —
1496
+ * React's `columns` (whose templates return `ReactNode`), its pager and
1497
+ * infinite-scroll templates, its `ref` — so two renderers cannot drift apart
1498
+ * on what a setting is called or what it means.
1499
+ */
1500
+ interface GridOptions<Row> {
1501
+ dataSource?: readonly Row[] | undefined;
1502
+ /**
1503
+ * A row's stable identity, for state keyed by it. Defaults to the row's
1504
+ * position, which is enough for a static grid but ties that state to where a
1505
+ * row sits rather than to the row — so anything sorting, filtering or paging
1506
+ * its data should give one.
1507
+ *
1508
+ * Called for every row on every change to `dataSource`, so it should be
1509
+ * cheap and stable; an inline arrow is fine, one that re-reads the data is
1510
+ * not.
1511
+ */
1512
+ getRowId?: ((row: Row, index: number) => string) | undefined;
1513
+ /**
1514
+ * A class and `data-*` attributes for each data row, worked out from the
1515
+ * row — an `is-overdue` class, a `data-status` to style or find it by.
1516
+ * Group headers and summary rows are not passed to it.
1517
+ *
1518
+ * Called for each data row as it renders, so it should be cheap. A row
1519
+ * whose result reads the same as last time is not redrawn for it, so an
1520
+ * inline arrow returning a fresh object each time is fine.
1521
+ */
1522
+ getRowProps?: ((row: ResolvedRow<Row>) => RowProps) | undefined;
1523
+ /**
1524
+ * Called when a data row is clicked, after the click has changed the
1525
+ * selection — so a handler reading the selection sees the new one. Not
1526
+ * called for a group header, whose click expands or collapses it.
1527
+ */
1528
+ onRowClick?: ((event: RowPointerEvent<Row>) => void) | undefined;
1529
+ /**
1530
+ * Called once when a data row is double-clicked — the usual "open this
1531
+ * record" gesture. The two clicks before it still report through
1532
+ * `onRowClick` and select as clicks do.
1533
+ */
1534
+ onRowDoubleClick?: ((event: RowPointerEvent<Row>) => void) | undefined;
1535
+ borders?: Borders | undefined;
1536
+ hoverable?: HoverableConfig | undefined;
1537
+ /**
1538
+ * Which parts of the grid the user may select, and how many of each —
1539
+ * `{ rows: "multiple", cells: "single" }`. A cell addresses one value, so it
1540
+ * has no `"multiple"`.
1541
+ *
1542
+ * Off by default, unlike `hoverable`: selection claims the click, which a
1543
+ * grid that only displays data should not do. Give `getRowId` alongside it
1544
+ * for data that sorts, filters or pages, or a selection follows the position
1545
+ * rather than the row.
1546
+ */
1547
+ selectable?: SelectableConfig | undefined;
1548
+ /** Row ids selected to start with, keyed as `getRowId` resolves them. Uncontrolled. */
1549
+ defaultRowSelection?: SelectionState | undefined;
1550
+ /**
1551
+ * The selected row ids, controlled — applied as given, changed only through
1552
+ * the row selection callbacks (`onRowSelectionChange` carries the whole
1553
+ * next state). Leave it `undefined` for the grid to keep it itself,
1554
+ * starting from `defaultRowSelection`.
1555
+ */
1556
+ rowSelection?: SelectionState | undefined;
1557
+ /** Column ids selected to start with. Uncontrolled. */
1558
+ defaultColumnSelection?: SelectionState | undefined;
1559
+ /**
1560
+ * The selected column ids, controlled — changed only through the column
1561
+ * selection callbacks. Leave it `undefined` for the grid to keep it.
1562
+ */
1563
+ columnSelection?: SelectionState | undefined;
1564
+ /** The cell selected to start with. Uncontrolled. */
1565
+ defaultCellSelection?: CellSelectionState | undefined;
1566
+ /**
1567
+ * The selected cell, controlled — `null` for none, changed only through
1568
+ * the cell selection callbacks. Leave it `undefined` for the grid to keep
1569
+ * it.
1570
+ */
1571
+ cellSelection?: CellSelectionState | undefined;
1572
+ /** Whether columns can be dragged wider, unless a column says otherwise. */
1573
+ resizableColumns?: boolean | undefined;
1574
+ /**
1575
+ * Whether columns can be dragged into a new position, unless a column says
1576
+ * otherwise. Turning it off leaves an order the user already made in place.
1577
+ */
1578
+ reorderableColumns?: boolean | undefined;
1579
+ /**
1580
+ * Whether columns fill the grid's width or sit at their own. Defaults to
1581
+ * `"fit"`, under which columns the user has sized keep their width and the
1582
+ * rest share what is left.
1583
+ */
1584
+ resizeMode?: ResizeMode | undefined;
1585
+ /** Column widths to start from, keyed by column id. Uncontrolled. */
1586
+ defaultColumnSizing?: ColumnSizingState | undefined;
1587
+ /**
1588
+ * Column widths, controlled — applied as given, changed only through
1589
+ * `onColumnResize`, whose `sizing` is the next state. Leave it
1590
+ * `undefined` for the grid to keep the widths itself, starting from
1591
+ * `defaultColumnSizing`.
1592
+ */
1593
+ columnSizing?: ColumnSizingState | undefined;
1594
+ /**
1595
+ * Column ids in the order to start in. Uncontrolled, and partial: ids it
1596
+ * omits keep their position among `columns` and follow those it lists.
1597
+ */
1598
+ defaultColumnOrder?: ColumnOrderState | undefined;
1599
+ /**
1600
+ * The column order, controlled — applied as given, changed only through
1601
+ * `onColumnOrderChange`. Leave it `undefined` for the grid to keep the
1602
+ * order itself, starting from `defaultColumnOrder`.
1603
+ */
1604
+ columnOrder?: ColumnOrderState | undefined;
1605
+ /**
1606
+ * Columns shown (`true`) or hidden (`false`) to start with, keyed by
1607
+ * column id, over each definition's own `hidden`. Uncontrolled.
1608
+ */
1609
+ defaultColumnVisibility?: ColumnVisibilityState | undefined;
1610
+ /**
1611
+ * Which columns are shown, controlled — applied as given, changed only
1612
+ * through `onColumnVisibilityChange`. Leave it `undefined` for the grid to
1613
+ * keep it itself, starting from `defaultColumnVisibility`.
1614
+ */
1615
+ columnVisibility?: ColumnVisibilityState | undefined;
1616
+ /**
1617
+ * Called once when columns are shown or hidden, with every column that one
1618
+ * change touched. A call that changes nothing does not call it.
1619
+ */
1620
+ onColumnVisibilityChange?: ((event: ColumnVisibilityEvent) => void) | undefined;
1621
+ /**
1622
+ * Sizes applied to columns that do not set their own — the width they start
1623
+ * at and the bounds they may be resized between. Distinct from
1624
+ * `defaultColumnSizing`, which sets specific columns' starting widths.
1625
+ */
1626
+ columnSizeDefaults?: Partial<ColumnSizeDefaults> | undefined;
1627
+ /**
1628
+ * Called as the user resizes a column. Fires continuously with
1629
+ * `phase: "move"` and once on release with `phase: "end"` — the latter being
1630
+ * the one to persist. Auto-fitting a column calls it once, with "end".
1631
+ */
1632
+ onColumnResize?: ((event: ColumnResizeEvent) => void) | undefined;
1633
+ /**
1634
+ * Called once when the user drops a column somewhere new. A drop that leaves
1635
+ * the order as it was does not call it.
1636
+ */
1637
+ onColumnOrderChange?: ((event: ColumnOrderEvent) => void) | undefined;
1638
+ /**
1639
+ * Whether columns can be sorted by clicking their header toggle, unless a
1640
+ * column says otherwise. Shift-click stacks a column into the sort instead
1641
+ * of replacing it.
1642
+ */
1643
+ sortableColumns?: boolean | undefined;
1644
+ /** The sort to start with, in priority order. Uncontrolled. */
1645
+ defaultColumnSort?: ColumnSortState | undefined;
1646
+ /**
1647
+ * The sort, controlled: the grid shows exactly this, and a header click
1648
+ * only asks for a change through `onColumnSortChange`, which takes effect
1649
+ * once this prop follows it. Leave it `undefined` for the grid to keep the
1650
+ * sort itself, starting from `defaultColumnSort`.
1651
+ */
1652
+ columnSort?: ColumnSortState | undefined;
1653
+ /**
1654
+ * Called once when the user changes the sort — a toggle, a stack, or a
1655
+ * clear back to "none".
1656
+ */
1657
+ onColumnSortChange?: ((event: ColumnSortEvent) => void) | undefined;
1658
+ /**
1659
+ * Whether columns can be grouped by — a header's click/`Alt+ArrowDown`
1660
+ * toggle — unless a column says otherwise. The grouping itself still
1661
+ * applies when this is off, via `defaultGroupBy` or the imperative API;
1662
+ * this only gates that one interaction, the same way `sortableColumns`
1663
+ * gates the sort toggle without disabling `defaultColumnSort`. Independent
1664
+ * of `groupByBarVisibility` and `groupByDraggableColumns`, which gate the
1665
+ * bar and the drag-in gesture respectively.
1666
+ */
1667
+ groupableColumns?: boolean | undefined;
1668
+ /**
1669
+ * Whether a groupable header shows its group-toggle icon, unless a column
1670
+ * says otherwise. Purely a rendering choice: `Alt+ArrowDown` keeps working
1671
+ * on a groupable header with the icon hidden.
1672
+ */
1673
+ groupToggleIconColumns?: boolean | undefined;
1674
+ /**
1675
+ * Whether a column's header may be dragged into the group-by bar to add
1676
+ * it to the grouping, unless a column says otherwise. Independent of
1677
+ * `groupableColumns`: a column can be groupable via its header's
1678
+ * click/keyboard toggle, via this drag, both, or neither.
1679
+ */
1680
+ groupByDraggableColumns?: boolean | undefined;
1681
+ /** How the group-by bar's visibility follows the active grouping. */
1682
+ groupByBarVisibility?: GroupByBarVisibility | undefined;
1683
+ /** The group-by stack to start with, outer to inner. Uncontrolled. */
1684
+ defaultGroupBy?: GroupByState | undefined;
1685
+ /**
1686
+ * The group-by stack, controlled — applied as given, changed only through
1687
+ * `onGroupByChange`. Leave it `undefined` for the grid to keep it itself,
1688
+ * starting from `defaultGroupBy`.
1689
+ */
1690
+ groupBy?: GroupByState | undefined;
1691
+ /**
1692
+ * Called once when the user changes the group-by stack — adding, removing,
1693
+ * or reordering a level.
1694
+ */
1695
+ onGroupByChange?: ((event: GroupByEvent) => void) | undefined;
1696
+ /** Group keys collapsed to start with — every other group starts expanded. Uncontrolled. */
1697
+ defaultGroupExpansion?: GroupExpansionState | undefined;
1698
+ /**
1699
+ * The collapsed groups, controlled — applied as given, changed only
1700
+ * through `onGroupExpansionChange`. Leave it `undefined` for the grid to
1701
+ * keep it itself, starting from `defaultGroupExpansion`.
1702
+ */
1703
+ groupExpansion?: GroupExpansionState | undefined;
1704
+ /** Called once when the user expands or collapses a group, or every group at once. */
1705
+ onGroupExpansionChange?: ((event: GroupExpansionEvent) => void) | undefined;
1706
+ /** The filter to start with — every applied entry, ANDed together. Uncontrolled. */
1707
+ defaultFilter?: FilterState<Row> | undefined;
1708
+ /**
1709
+ * The filter, controlled — applied as given, changed only through
1710
+ * `onFilterChange`. Leave it `undefined` for the grid to keep it itself,
1711
+ * starting from `defaultFilter`.
1712
+ */
1713
+ filter?: FilterState<Row> | undefined;
1714
+ /**
1715
+ * Called once when the filter changes — from the toolbar's search box, the
1716
+ * `filter.clearAll` command, `setFilter` or a restored state.
1717
+ */
1718
+ onFilterChange?: ((event: FilterChangeEvent<Row>) => void) | undefined;
1719
+ /**
1720
+ * Whether columns get a filter menu, opened from their header, unless a
1721
+ * column says otherwise. Off by default, like `sortableColumns`; the
1722
+ * filter itself applies either way, from `defaultFilter`, `setFilter` or a
1723
+ * search box. A renderer draws the menu from what
1724
+ * `resolveColumnFilterMenu` settles.
1725
+ */
1726
+ filterableColumns?: boolean | undefined;
1727
+ /**
1728
+ * How the filter menus look: which editor they open — `"simple"`
1729
+ * conditions or an `"excel"` checklist — and the checklist's counts and
1730
+ * value limit. A column's own `filterMenu` wins over it. Switching `ui`
1731
+ * keeps every filter, since both editors edit the one `filter`.
1732
+ */
1733
+ filterMenu?: GridFilterMenuOptions | undefined;
1734
+ /**
1735
+ * Whether the grid's rows are split into pages. A page's unit is a
1736
+ * top-level group or a bare data row, never a leaf row — a group is never
1737
+ * split across a page boundary. Off by default, matching `sortableColumns`.
1738
+ */
1739
+ paginated?: boolean | undefined;
1740
+ /**
1741
+ * The page and page size to start on. Uncontrolled. Defaults to
1742
+ * `{ pageIndex: 0, pageSize: 25 }` when `paginated` is on and this is
1743
+ * omitted.
1744
+ */
1745
+ defaultPagination?: PaginationState | undefined;
1746
+ /**
1747
+ * The page and page size, controlled — applied as given, changed only
1748
+ * through `onPaginationChange`. Leave it `undefined` for the grid to keep
1749
+ * them itself, starting from `defaultPagination`.
1750
+ *
1751
+ * The grid sends an uncontrolled pagination back to the first page when
1752
+ * the filter, sort or grouping changes; a controlled one is the parent's
1753
+ * to reset alongside that change. Until it does, the grid shows the last
1754
+ * page that exists rather than an empty one.
1755
+ */
1756
+ pagination?: PaginationState | undefined;
1757
+ /** Called once when the user changes the page or the page size. */
1758
+ onPaginationChange?: ((event: PaginationChangeEvent) => void) | undefined;
1759
+ /**
1760
+ * Aggregates to compute — a subtotal per group (rendered in that group's
1761
+ * header) plus a grand total over the whole filtered/grouped dataset
1762
+ * (rendered in a footer). Always computed over every row, never scoped to
1763
+ * the current page. A plain controlled prop, unlike `sort`/`filter`/
1764
+ * `groupBy`/`pagination`: there is no built-in UI for a user to add or
1765
+ * remove an aggregate interactively, so there is no `defaultAggregates`/
1766
+ * `onAggregatesChange` pair to go with it.
1767
+ */
1768
+ aggregates?: AggregateState<Row> | undefined;
1769
+ /**
1770
+ * Where a group's own aggregate results render. `"inline"` (the default)
1771
+ * keeps them as text in the group header, next to its leaf-row count.
1772
+ * `"row"` instead renders a dedicated row after that group's last visible
1773
+ * entry, with each aggregate's value in the `<td>` for its own column —
1774
+ * the same alignment the grand-total footer's own cells have. Has no
1775
+ * effect when `aggregates` is empty or omitted.
1776
+ */
1777
+ groupAggregateDisplay?: GroupAggregateDisplay | undefined;
1778
+ /**
1779
+ * Bounds the row area's height, independently scrollable — the grid's own
1780
+ * chrome (group-by bar, header, footer, pager) stays outside it and
1781
+ * always visible. A number is pixels; a string is passed through as a CSS
1782
+ * length (e.g. "60vh"). Omitted, the body's height stays content-driven,
1783
+ * same as today.
1784
+ */
1785
+ height?: number | string | undefined;
1786
+ /**
1787
+ * Renders only the rows near the current scroll position rather than every
1788
+ * row at once — for a dataset too large to mount in full. Requires
1789
+ * `height` to be set; a grid without a bounded body has no viewport to
1790
+ * window rows against (a dev-time console warning fires when it's
1791
+ * missing). Off by default, matching every other opt-in behavior here.
1792
+ */
1793
+ virtualized?: boolean | undefined;
1794
+ /**
1795
+ * Rows rendered outside the visible range on each side, to reduce
1796
+ * blank-frame flashes on fast scrolling. Only meaningful with `virtualized`
1797
+ * on.
1798
+ */
1799
+ overscan?: number | undefined;
1800
+ /**
1801
+ * Assumed height for a row never yet measured — only matters for the very
1802
+ * first paint and for `scrollToRow`'s initial jump before it corrects
1803
+ * itself against that row's real, measured height. Only meaningful with
1804
+ * `virtualized` on.
1805
+ */
1806
+ estimatedRowHeight?: number | undefined;
1807
+ /**
1808
+ * The grid's accessible name, announced when it takes focus. A grid without
1809
+ * one is read only as "grid", which says nothing about which grid.
1810
+ */
1811
+ label?: string | undefined;
1812
+ /**
1813
+ * The id of an element naming the grid, for a heading already on the page.
1814
+ * Takes precedence over `label`, as `aria-labelledby` does.
1815
+ */
1816
+ labelledBy?: string | undefined;
1817
+ /**
1818
+ * The locale values are formatted for — a BCP 47 tag such as `"de-DE"`, or
1819
+ * a list to fall back through. Setting it turns on `Intl` formatting of
1820
+ * dates and numbers in every cell and aggregate shown without a template;
1821
+ * without it, only a column with its own `format` is formatted, in the
1822
+ * runtime's locale, and the rest print as they always have.
1823
+ */
1824
+ locale?: FormatLocale;
1825
+ /**
1826
+ * The grid's own strings, replacing its English key by key — the pager's
1827
+ * buttons, the group-by bar, the loading row, boolean and blank values,
1828
+ * the built-in commands' labels, the menus' names, and every live-region
1829
+ * announcement. Keys
1830
+ * left out keep their default.
1831
+ * Formatting is `locale`'s, not this.
1832
+ */
1833
+ messages?: Partial<GridMessages> | undefined;
1834
+ /**
1835
+ * The grid's own context menu, opened on a column header, a data cell, a
1836
+ * group row or the body's empty space by a right-click, Shift+F10 or the
1837
+ * ContextMenu key. Off by default, like every other feature, leaving the
1838
+ * browser's menu. `true` shows each area's defaults — see
1839
+ * `defaultContextMenu`; an object lists an area's entries, an area left
1840
+ * out keeping its defaults and one given `[]` showing the browser's menu
1841
+ * there.
1842
+ */
1843
+ contextMenu?: boolean | GridContextMenuOptions<Row> | undefined;
1844
+ /**
1845
+ * Called when the grid's context menu opens or closes, with where. A menu
1846
+ * opened in place of another reports that one closing first. The open
1847
+ * state is the renderer's to keep, so no option holds it.
1848
+ */
1849
+ onContextMenuOpenChange?: ((event: ContextMenuOpenChangeEvent) => void) | undefined;
1850
+ /**
1851
+ * The app's own commands, for its menus to list by id. One with a
1852
+ * built-in's id replaces it wherever that id is listed — a translated,
1853
+ * privilege-gated or differently behaving "Hide column" — see
1854
+ * `resolveCommands`.
1855
+ */
1856
+ commands?: readonly GridCommand<Row>[] | undefined;
1857
+ /**
1858
+ * Called after a command or an inline menu item runs — chosen from a menu,
1859
+ * or run through a renderer's API — saying which, where it was asked for
1860
+ * and from where. One that did not run, being hidden or disabled, is not
1861
+ * reported.
1862
+ */
1863
+ onCommand?: ((event: GridCommandEvent) => void) | undefined;
1864
+ /**
1865
+ * A toolbar above the grid: its own commands, a search box over the
1866
+ * filter's global text entry, dropdowns and the app's own content, in the
1867
+ * menu vocabulary. Off by default. `true` lists `defaultToolbar`; an object
1868
+ * lists its `items` and may name it with `label` — see `ToolbarEntry`.
1869
+ */
1870
+ toolbar?: boolean | GridToolbarOptions<Row> | undefined;
1871
+ /**
1872
+ * How the grid exports unless a call says otherwise: which rows and
1873
+ * columns, the file's name, and the CSV and JSON settings. Left out, an
1874
+ * export holds what the user sees, across every page, in a file named
1875
+ * `export` with the format's extension.
1876
+ */
1877
+ export?: GridExportOptions | undefined;
1878
+ /**
1879
+ * Export formats beyond CSV and JSON — an xlsx writer, or one of the
1880
+ * app's own — each registered by its `format`, replacing a built-in
1881
+ * writer of the same format. `export.xlsx` and `export.pdf` show only
1882
+ * once a writer for their format is here — see `resolveExportWriters`.
1883
+ */
1884
+ exportWriters?: readonly ExportWriter[] | undefined;
1885
+ /**
1886
+ * How the grid prints unless a call says otherwise: the rows and columns,
1887
+ * the title and text around the table, and the page. Left out, a print
1888
+ * holds what an export does, titled with `label`, on an A4 page.
1889
+ */
1890
+ print?: PrintOptions | undefined;
1891
+ }
1892
+ /**
1893
+ * Reported as the user selects. Every one of these is fanned out from a single
1894
+ * diff of the transition it describes, so no two can disagree about what one
1895
+ * interaction did.
1896
+ *
1897
+ * Kept apart from `GridOptions` because the column payloads carry resolved
1898
+ * columns, whose labels are whatever a renderer's `headerTemplate` returns —
1899
+ * `Node` is that renderer's node type.
1900
+ */
1901
+ interface SelectionCallbacks<Row, Node = string> {
1902
+ /** Called once per row newly selected. The last call names the last row. */
1903
+ onRowSelect?: ((event: RowSelectEvent<Row>) => void) | undefined;
1904
+ /** Called once with every row one interaction selected. */
1905
+ onRowsSelect?: ((event: RowsSelectEvent<Row>) => void) | undefined;
1906
+ onRowDeselect?: ((event: RowSelectEvent<Row>) => void) | undefined;
1907
+ onRowsDeselect?: ((event: RowsSelectEvent<Row>) => void) | undefined;
1908
+ /**
1909
+ * Called once per change with what it added, what it removed and everything
1910
+ * selected after it — the one to persist from.
1911
+ */
1912
+ onRowSelectionChange?: ((event: RowSelectionChangeEvent<Row>) => void) | undefined;
1913
+ onColumnSelect?: ((event: ColumnSelectEvent<Row, Node>) => void) | undefined;
1914
+ onColumnsSelect?: ((event: ColumnsSelectEvent<Row, Node>) => void) | undefined;
1915
+ onColumnDeselect?: ((event: ColumnSelectEvent<Row, Node>) => void) | undefined;
1916
+ onColumnsDeselect?: ((event: ColumnsSelectEvent<Row, Node>) => void) | undefined;
1917
+ onColumnSelectionChange?: ((event: ColumnSelectionChangeEvent<Row, Node>) => void) | undefined;
1918
+ onCellSelect?: ((event: CellSelectEvent<Row, Node>) => void) | undefined;
1919
+ onCellDeselect?: ((event: CellSelectEvent<Row, Node>) => void) | undefined;
1920
+ onCellSelectionChange?: ((event: CellSelectionChangeEvent<Row, Node>) => void) | undefined;
1921
+ }
1922
+
1923
+ /**
1924
+ * Which editor a filter menu opens. Both edit the same `FilterState`, so
1925
+ * switching between them keeps every filter applied.
1926
+ *
1927
+ * - `"simple"`: one or two conditions — an operator and a value each —
1928
+ * joined by and/or.
1929
+ * - `"excel"`: a search box over a checklist of the column's values, with
1930
+ * the conditions a submenu away.
1931
+ */
1932
+ type FilterMenuUi = "simple" | "excel";
1933
+ /** How a grid's filter menus look, unless a column says otherwise. */
1934
+ interface GridFilterMenuOptions {
1935
+ /** Which editor a filter menu opens. Defaults to `"simple"`. */
1936
+ readonly ui?: FilterMenuUi | undefined;
1937
+ /** Whether the excel editor's checklist shows how many rows hold each value. Off by default. */
1938
+ readonly showCounts?: boolean | undefined;
1939
+ /**
1940
+ * How many distinct values the excel editor's checklist lists before it
1941
+ * asks for a search first. Defaults to `DEFAULT_FILTER_VALUE_LIMIT`.
1942
+ */
1943
+ readonly valueLimit?: number | undefined;
1944
+ }
1945
+ /** A column's own filter menu settings, over the grid's `filterMenu`. */
1946
+ interface ColumnFilterMenuOptions {
1947
+ /** Which editor this column's filter menu opens, over the grid's `filterMenu.ui`. */
1948
+ readonly ui?: FilterMenuUi | undefined;
1949
+ /**
1950
+ * The operators this column's conditions offer, in order, in place of its
1951
+ * type's `defaultFilterOperators`. `in` is dropped — the checklist is its
1952
+ * editor — and `[]` offers no condition, leaving the excel editor its
1953
+ * checklist alone.
1954
+ */
1955
+ readonly operators?: readonly FilterOperator[] | undefined;
1956
+ }
1957
+ /** One column's filter menu with every setting settled — what a renderer draws. */
1958
+ interface ResolvedColumnFilterMenu {
1959
+ readonly ui: FilterMenuUi;
1960
+ /** The operators its conditions offer, in order. Never `in`. */
1961
+ readonly operators: readonly FilterOperator[];
1962
+ /** The family the column's `type` falls in, which its operators are labelled by. */
1963
+ readonly family: FilterOperatorFamily;
1964
+ readonly showCounts: boolean;
1965
+ readonly valueLimit: number;
1966
+ }
1967
+ /**
1968
+ * How many distinct values a checklist lists before asking for a search —
1969
+ * Excel's own cap. The list is virtualized, so what this bounds is counting
1970
+ * the values, not drawing them.
1971
+ */
1972
+ declare const DEFAULT_FILTER_VALUE_LIMIT = 10000;
1973
+ /**
1974
+ * The filter menu `column` opens, or `null` when it has none: a column is
1975
+ * filterable when its own `filterable` says so, else when the grid's
1976
+ * `filterableColumns` does — off unless one of them turns it on, as
1977
+ * `sortable` is. The column's `filterMenu` settings win over the grid's
1978
+ * one by one; what neither sets takes its default.
1979
+ */
1980
+ declare function resolveColumnFilterMenu(options: Pick<GridOptions<unknown>, "filterableColumns" | "filterMenu">, column: Pick<ColumnDefinition<unknown, unknown>, "type" | "filterable" | "filterMenu">): ResolvedColumnFilterMenu | null;
1981
+
1982
+ /**
1983
+ * Values a cell shows as-is instead of being drilled into. Arrays and `Date`s
1984
+ * are cell values rather than groups of columns, and `null` cannot be
1985
+ * introspected, so all three end a path.
1986
+ */
1987
+ type LeafValue = bigint | boolean | number | string | symbol | null | undefined | Date | readonly unknown[] | ((...args: never[]) => unknown);
1988
+ /** Keys of `T` holding a leaf value — the only ones a path may end on. */
1989
+ type LeafKey<T> = {
1990
+ [K in keyof T & string]: NonNullable<T[K]> extends LeafValue ? K : never;
1991
+ }[keyof T & string];
1992
+ /**
1993
+ * Every addressable field of `Row`, one level deep: `"Id"` for a flat field,
1994
+ * `"Application.Id"` for a leaf inside a nested object. A nested object
1995
+ * contributes only its leaf children, never itself and never anything deeper.
1996
+ */
1997
+ type FieldPath<Row> = {
1998
+ [K in keyof Row & string]: NonNullable<Row[K]> extends LeafValue ? K : `${K}.${LeafKey<NonNullable<Row[K]>>}`;
1999
+ }[keyof Row & string];
2000
+ /**
2001
+ * The value type of a column's cells. This package is framework-agnostic so it
2002
+ * defaults to `string`;
2003
+ */
2004
+ type ColumnType = "dateTime" | "date" | "time" | "number" | "string" | "boolean" | "decimal" | "currency" | "percent";
2005
+ type ColumnAlignment = "left" | "center" | "right";
2006
+ /**
2007
+ * What `cellTemplate` receives. An object rather than positional arguments so
2008
+ * that a later addition — a sort state, whether the row is selected — is not a
2009
+ * breaking change to every template already written.
2010
+ */
2011
+ interface CellTemplateContext<Row> {
2012
+ /**
2013
+ * This cell's value, read off the column's field path. `unknown` because a
2014
+ * dotted path's type cannot be recovered here; a template narrows it.
2015
+ */
2016
+ value: unknown;
2017
+ /** The whole row, for a template that needs a sibling field. */
2018
+ row: Row;
2019
+ /** Position among the rows as rendered — the index within the current page once paging is on. */
2020
+ rowIndex: number;
2021
+ /** This row's absolute position in the whole filtered/sorted/grouped dataset, unaffected by which page is showing. */
2022
+ datasetIndex: number;
2023
+ /** This row's id, as `resolveRowId` settled it. */
2024
+ rowId: string;
2025
+ /** Whether this row is selected, so a template can style itself to match. */
2026
+ selected: boolean;
2027
+ }
2028
+ /**
2029
+ * What a column's `footerTemplate` receives. Mirrors `CellTemplateContext`'s
2030
+ * shape where it applies — `value`, `rows` — minus everything scoped to one
2031
+ * rendered row (`rowIndex`, `rowId`, `selected`), since a footer addresses
2032
+ * every row an aggregate was computed over at once, not a single one.
2033
+ */
2034
+ interface FooterTemplateContext<Row> {
2035
+ /** This column's aggregate result, as `computeAggregates` produced it. */
2036
+ value: unknown;
2037
+ /** Every row the aggregate was computed over — the grand total's full dataset, or one group's full leaf descendants. */
2038
+ rows: readonly Row[];
2039
+ }
2040
+ /**
2041
+ * @typeParam Node - What a header or cell renders to. This package is
2042
+ * framework-agnostic so it defaults to `string`; `@gridkitjs/react` binds it to
2043
+ * `ReactNode` so a template can return JSX.
2044
+ */
2045
+ interface ColumnDefinition<Row, Node = string> {
2046
+ /**
2047
+ * Path to this cell's value: a key of `Row`, or `"Parent.Child"` for a leaf
2048
+ * one level inside a nested object. Any string still compiles — the union
2049
+ * exists to drive autocomplete, not to lock the grid down.
2050
+ */
2051
+ field: FieldPath<Row> | (string & {});
2052
+ /**
2053
+ * Stable identity for state keyed by this column. Defaults to `field`, which
2054
+ * is unique in the common case but need not be — two columns may render the
2055
+ * same field differently.
2056
+ */
2057
+ id?: string;
2058
+ /**
2059
+ * The column's name as plain text. The header shows it when there is no
2060
+ * `headerTemplate`, and anything that needs the name as text rather than
2061
+ * markup — a screen-reader announcement, an export — reads it even when
2062
+ * there is one, since a template's output need not be text at all.
2063
+ */
2064
+ header?: string | undefined;
2065
+ /** Header content, or a function returning it at render time. */
2066
+ headerTemplate?: Node | (() => Node) | undefined;
2067
+ /**
2068
+ * Renders this column's cells in place of the text `formatCellValue` makes
2069
+ * of the value at `field`. The raw value is still resolved and handed over,
2070
+ * so a template never repeats the field path.
2071
+ */
2072
+ cellTemplate?: ((context: CellTemplateContext<Row>) => Node) | undefined;
2073
+ /**
2074
+ * Renders this column's own aggregate result in a group footer or the
2075
+ * grand-total footer, in place of the raw computed value. Absent for a
2076
+ * column with no aggregate: nothing is shown, the same way a column
2077
+ * missing from `AggregateState` contributes no cell to either footer.
2078
+ */
2079
+ footerTemplate?: ((context: FooterTemplateContext<Row>) => Node) | undefined;
2080
+ /**
2081
+ * The value type of this column's cells. This package is framework-agnostic so it
2082
+ * defaults to `string`;
2083
+ */
2084
+ type?: ColumnType;
2085
+ /**
2086
+ * `Intl` options for how this column's values read as text: number options
2087
+ * for a numeric `type`, date options for a date or time one. Passed to
2088
+ * `Intl.NumberFormat`/`Intl.DateTimeFormat` with the grid's `locale` — see
2089
+ * `formatCellValue` for the defaults each `type` starts from. Setting it,
2090
+ * or the grid's `locale`, is what turns that formatting on: without either,
2091
+ * numbers print as-is and dates through `toLocaleString()`.
2092
+ */
2093
+ format?: Intl.NumberFormatOptions | Intl.DateTimeFormatOptions | undefined;
2094
+ /**
2095
+ * Turns a value into the text shown for it, in place of `format` and
2096
+ * `type`. Applies wherever this column's values are shown as text — its
2097
+ * cells and its aggregates. `row` is the cell's row, and `undefined` for a
2098
+ * value no single row owns: an aggregate result, or a group header's value.
2099
+ */
2100
+ valueFormatter?: ((value: unknown, row: Row | undefined) => string) | undefined;
2101
+ /**
2102
+ * Alignment of this column's cells. This package is framework-agnostic so it
2103
+ * defaults to `left` (`right` for numbers);
2104
+ */
2105
+ alignment?: ColumnAlignment;
2106
+ /**
2107
+ * Width in px this column starts at. A user resize overrides it for as long
2108
+ * as that resize lives in the sizing state.
2109
+ */
2110
+ width?: number;
2111
+ /** Lower bound a resize may not drag below. */
2112
+ minWidth?: number;
2113
+ /** Upper bound a resize may not drag above. */
2114
+ maxWidth?: number;
2115
+ /** Whether this column can be resized, overriding the grid-level default. */
2116
+ resizable?: boolean;
2117
+ /**
2118
+ * Whether this column can be dragged to a new position, overriding the
2119
+ * grid-level default. A column that cannot move can still be moved past.
2120
+ */
2121
+ reorderable?: boolean;
2122
+ /** Whether this column can be sorted, overriding the grid-level default. */
2123
+ sortable?: boolean;
2124
+ /**
2125
+ * Whether this column has a filter menu, overriding the grid-level
2126
+ * `filterableColumns`. Like `sortable`, it gates the user's way in and
2127
+ * nothing else: a filter on the column set in code still applies.
2128
+ */
2129
+ filterable?: boolean | undefined;
2130
+ /**
2131
+ * This column's own filter menu settings — its editor and the operators
2132
+ * its conditions offer — over the grid's `filterMenu`.
2133
+ */
2134
+ filterMenu?: ColumnFilterMenuOptions | undefined;
2135
+ /** Whether this column can be grouped by, overriding the grid-level default. */
2136
+ groupable?: boolean;
2137
+ /**
2138
+ * Whether this column's header shows its group-toggle icon, overriding
2139
+ * the grid-level default. Purely a rendering choice — it does not affect
2140
+ * whether the column can be grouped by (`groupable`) or the
2141
+ * `Alt+ArrowDown` shortcut, which keeps working with the icon hidden, the
2142
+ * same way the resize handle stays `aria-hidden` while `Alt+ArrowLeft`/
2143
+ * `ArrowRight` still resize.
2144
+ */
2145
+ groupToggleIcon?: boolean;
2146
+ /**
2147
+ * Whether this column's header may be dragged into the group-by bar to
2148
+ * add it to the active grouping, overriding the grid-level default.
2149
+ * Distinct from `groupable`: a column can be groupable via its header's
2150
+ * click/`Alt+ArrowDown` toggle, via this drag, both, or neither.
2151
+ */
2152
+ groupByDraggable?: boolean;
2153
+ /**
2154
+ * Lets this column's header and/or cell text wrap onto multiple lines
2155
+ * instead of the grid's default single line with an ellipsis. Off by
2156
+ * default: wrapping changes row height, so it stays a column's own choice
2157
+ * rather than something a minor release could turn on under an existing
2158
+ * grid.
2159
+ */
2160
+ wrap?: ColumnWrapConfig;
2161
+ /**
2162
+ * Extra class names appended to this column's `th`. An escape hatch for a
2163
+ * consumer's own CSS — nothing in this package reads them — for anything
2164
+ * `wrap` and the rest of this type don't cover.
2165
+ */
2166
+ headerClassName?: string;
2167
+ /**
2168
+ * Extra class names appended to this column's `td`, on every row. Static
2169
+ * per column: a per-row condition is already `cellTemplate`'s job (a
2170
+ * template returning its own markup with a conditional class), so this
2171
+ * stays a plain string rather than taking the row.
2172
+ */
2173
+ cellClassName?: string;
2174
+ /**
2175
+ * Whether this column starts out hidden. A hidden column is not rendered
2176
+ * but is still a column of the grid: a sort, filter or grouping on it
2177
+ * still applies, and it keeps its place in the column order. The user
2178
+ * showing or hiding it lives in `ColumnVisibilityState`, which wins over
2179
+ * this for as long as it holds an entry for the column.
2180
+ */
2181
+ hidden?: boolean | undefined;
2182
+ /**
2183
+ * Whether the user may hide this column — from its header's menu, or the
2184
+ * column chooser. Defaults to `true`. Like `sortable`, it gates the user's
2185
+ * ways to do it and nothing else: `hideColumns` still hides the column.
2186
+ */
2187
+ hideable?: boolean | undefined;
2188
+ /**
2189
+ * Whether this column is written to an export, a clipboard copy or a
2190
+ * print. Defaults to `true`. `false` keeps it out of every one of them —
2191
+ * even when an export names it by id — for a column whose cells mean
2192
+ * nothing off screen, such as one of action buttons.
2193
+ */
2194
+ exportable?: boolean | undefined;
2195
+ /**
2196
+ * The typed value an export stores for this column's cells, where the raw
2197
+ * value at `field` is not the one to keep — an id to resolve into a name,
2198
+ * a string date to turn into a `Date`. Only a format that keeps typed
2199
+ * values (a spreadsheet, JSON) reads it; the text every format writes
2200
+ * still comes from `formatCellValue`, so what is exported reads as what
2201
+ * is shown.
2202
+ */
2203
+ exportValue?: ((value: unknown, row: Row) => ExportScalar) | undefined;
2204
+ }
2205
+ /** Which parts of a column opt out of the grid's default single-line text. */
2206
+ interface ColumnWrapConfig {
2207
+ header?: boolean;
2208
+ cells?: boolean;
2209
+ }
2210
+ /**
2211
+ * Widths the user has changed, keyed by column id. Holding only what changed —
2212
+ * rather than every width — means a `width` edited in the column definition
2213
+ * still takes effect, and resetting is discarding the state.
2214
+ */
2215
+ type ColumnSizingState = Readonly<Record<string, number>>;
2216
+ /** The active page, and how many rows/units make one up. */
2217
+ interface PaginationState {
2218
+ readonly pageIndex: number;
2219
+ readonly pageSize: number;
2220
+ }
2221
+ /** Reports a user page/page-size change whole — the one to persist from, mirroring ColumnSortEvent. */
2222
+ interface PaginationChangeEvent {
2223
+ readonly pagination: PaginationState;
2224
+ readonly pageCount: number;
2225
+ }
2226
+ /** Sizes used for a column that does not specify its own. */
2227
+ interface ColumnSizeDefaults {
2228
+ width: number;
2229
+ minWidth: number;
2230
+ maxWidth: number;
2231
+ }
2232
+ /** The bounds a column's width is held between, resolved once from both. */
2233
+ interface ColumnConstraints {
2234
+ minWidth: number;
2235
+ maxWidth: number;
2236
+ }
2237
+ /**
2238
+ * Grid-level defaults a column falls back to when it does not set its own.
2239
+ * Sizes are grouped so the rest of the grid's defaults have somewhere to go.
2240
+ */
2241
+ interface ColumnResolveOptions {
2242
+ sizes?: Partial<ColumnSizeDefaults> | undefined;
2243
+ /** Whether columns are resizable, unless a column says otherwise. */
2244
+ resizable?: boolean | undefined;
2245
+ /** Whether columns are reorderable, unless a column says otherwise. */
2246
+ reorderable?: boolean | undefined;
2247
+ /** Whether columns may be dragged into the group-by bar, unless a column says otherwise. */
2248
+ groupByDraggable?: boolean | undefined;
2249
+ }
2250
+ /**
2251
+ * How a column's width relates to the grid's.
2252
+ *
2253
+ * `"fit"` keeps the columns filling the grid: the space a column gives up is
2254
+ * handed to the others, and the space it takes comes out of them. `"fixed"`
2255
+ * lets every column keep its own width, so a resize moves one column and
2256
+ * nothing else, and the grid scrolls or leaves a gap accordingly.
2257
+ */
2258
+ type ResizeMode = "fit" | "fixed";
2259
+ /**
2260
+ * A column as the data stages read it — filtering, sorting, grouping and
2261
+ * aggregating need its id and its definition's `field` and `type`, never its
2262
+ * width. Kept apart from `ResolvedColumn` so that a resize or a viewport
2263
+ * change, which re-resolves every width, leaves these stages' input — and so
2264
+ * their output — untouched. `ResolvedColumn` satisfies it structurally.
2265
+ */
2266
+ interface DataColumn<Row, Node = string> {
2267
+ readonly id: string;
2268
+ readonly column: ColumnDefinition<Row, Node>;
2269
+ }
2270
+ /**
2271
+ * A column paired with everything it takes to render it. Each field is a
2272
+ * decision made once here rather than in each adapter, so a second framework
2273
+ * binding renders identically without repeating the logic.
2274
+ */
2275
+ interface ResolvedColumn<Row, Node = string> {
2276
+ column: ColumnDefinition<Row, Node>;
2277
+ id: string;
2278
+ width: number;
2279
+ /**
2280
+ * Whether `width` came from the sizing state rather than the column
2281
+ * definition — that is, whether the user set it. Auto-fit leaves these
2282
+ * columns alone so that resizing one does not undo itself.
2283
+ */
2284
+ sized: boolean;
2285
+ /**
2286
+ * What the header shows: the column's own `headerTemplate`, else its
2287
+ * `header`, else a label read off the field path. `string` is in the
2288
+ * union because both fallbacks are text whatever `Node` is bound to.
2289
+ */
2290
+ label: Node | string;
2291
+ /** Whether this column can be resized, after the grid-level default. */
2292
+ resizable: boolean;
2293
+ /** Whether this column can be dragged, after the grid-level default. */
2294
+ reorderable: boolean;
2295
+ /** Whether this column's header may be dragged into the group-by bar, after the grid-level default. */
2296
+ groupByDraggable: boolean;
2297
+ /** How this column's cells align, after falling back to its type. */
2298
+ alignment: ColumnAlignment;
2299
+ }
2300
+ /**
2301
+ * A resize in progress. It captures its constraints up front so that applying
2302
+ * a pointer position is arithmetic on numbers alone — no column, no DOM.
2303
+ */
2304
+ interface ColumnResizeSession {
2305
+ readonly columnId: string;
2306
+ readonly startWidth: number;
2307
+ readonly startPosition: number;
2308
+ readonly constraints: ColumnConstraints;
2309
+ }
2310
+ /**
2311
+ * Reports a user resize. `phase` separates the two audiences: `"move"` fires
2312
+ * continuously for live feedback, `"end"` once on release — the one to persist.
2313
+ */
2314
+ interface ColumnResizeEvent {
2315
+ readonly columnId: string;
2316
+ readonly width: number;
2317
+ readonly sizing: ColumnSizingState;
2318
+ readonly phase: "move" | "end";
2319
+ }
2320
+ /**
2321
+ * Columns shown (`true`) or hidden (`false`) since the grid started, keyed by
2322
+ * column id. Holding only what changed, the way `ColumnSizingState` does: a
2323
+ * column absent from it follows its definition's `hidden`, so a definition
2324
+ * edited later still takes effect for every column the user never touched.
2325
+ */
2326
+ type ColumnVisibilityState = Readonly<Record<string, boolean>>;
2327
+ /**
2328
+ * Reports columns shown or hidden. `columnIds` lists every column the one
2329
+ * change touched — showing three columns at once is one event, not three —
2330
+ * and `visibility` is the whole state to persist from.
2331
+ */
2332
+ interface ColumnVisibilityEvent {
2333
+ readonly columnIds: readonly string[];
2334
+ readonly visibility: ColumnVisibilityState;
2335
+ }
2336
+ /**
2337
+ * Column ids in the order they render. It need not list every column: one
2338
+ * absent from it keeps its position among the definitions and follows those
2339
+ * that are listed.
2340
+ */
2341
+ type ColumnOrderState = readonly string[];
2342
+ /**
2343
+ * Which side of a column a drop lands on, normalised away by
2344
+ * `resolveDropBefore` so it reaches no state.
2345
+ */
2346
+ type DropSide = "before" | "after";
2347
+ /**
2348
+ * Reports a user reorder. Unlike a resize there is no `"move"` phase — the
2349
+ * order does not change until the drop.
2350
+ */
2351
+ interface ColumnOrderEvent {
2352
+ readonly columnId: string;
2353
+ readonly order: ColumnOrderState;
2354
+ }
2355
+ /** Which way a column sorts. */
2356
+ type SortDirection = "asc" | "desc";
2357
+ /** One column's place in a stacked sort, and which way it sorts. */
2358
+ interface ColumnSortEntry {
2359
+ readonly columnId: string;
2360
+ readonly direction: SortDirection;
2361
+ }
2362
+ /**
2363
+ * The active sort, in priority order: index 0 sorts first, ties broken by
2364
+ * index 1, and so on down the stack. Empty for an unsorted grid, mirroring
2365
+ * `SelectionState`'s empty array for "nothing selected".
2366
+ */
2367
+ type ColumnSortState = readonly ColumnSortEntry[];
2368
+ /**
2369
+ * Reports a user sort change whole — the stack to persist from. No `phase`:
2370
+ * unlike a resize, a sort has no in-progress state, only before and after.
2371
+ */
2372
+ interface ColumnSortEvent {
2373
+ readonly columnId: string;
2374
+ readonly sort: ColumnSortState;
2375
+ }
2376
+ /** One level of a stacked group-by, outer to inner. Mirrors ColumnSortEntry. */
2377
+ interface GroupByEntry {
2378
+ readonly columnId: string;
2379
+ /** Order of this level's own group values (not row order within a group). Defaults to "asc". */
2380
+ readonly direction?: SortDirection;
2381
+ }
2382
+ /**
2383
+ * The active grouping, outer to inner: index 0 groups first, each
2384
+ * subsequent index nests inside it. Empty for an ungrouped grid, mirroring
2385
+ * ColumnSortState's empty array for "no sort".
2386
+ */
2387
+ type GroupByState = readonly GroupByEntry[];
2388
+ /**
2389
+ * Reports a user group-by change whole — the stack to persist from. Mirrors
2390
+ * ColumnSortEvent's `{columnId, sort}` shape.
2391
+ */
2392
+ interface GroupByEvent {
2393
+ readonly columnId: string;
2394
+ readonly groupBy: GroupByState;
2395
+ }
2396
+ /**
2397
+ * Group keys collapsed by the user — holding only the exceptions, the same
2398
+ * way ColumnSizingState holds only resized widths. A key absent from this
2399
+ * set is expanded; there is no separate "collapsed by default" concept.
2400
+ */
2401
+ type GroupExpansionState = readonly string[];
2402
+ /**
2403
+ * Reports a user expansion change. `groupId` is the group toggled, or `null`
2404
+ * for expandAllGroups/collapseAllGroups, which touch every group in one call
2405
+ * rather than one at a time.
2406
+ */
2407
+ interface GroupExpansionEvent {
2408
+ readonly groupId: string | null;
2409
+ readonly expansion: GroupExpansionState;
2410
+ }
2411
+ /**
2412
+ * One group header in a grouped result. `path` is every ancestor value
2413
+ * down to and including this group's own, outermost first — what a header
2414
+ * template needs to render "West / Enterprise", not just "Enterprise".
2415
+ *
2416
+ * Not parameterized by `Row`: nothing here holds a `Row`-typed value today —
2417
+ * `aggregates` holds computed `unknown` results, not rows themselves.
2418
+ */
2419
+ interface ResolvedGroupRow {
2420
+ readonly kind: "group";
2421
+ /** Stable id for this node: this plan's join of `path`, used as the React key and the GroupExpansionState entry. Opaque — build it with `groupRowId`, never construct one by hand. */
2422
+ readonly groupId: string;
2423
+ /** Nesting depth, 0 for a top-level group. */
2424
+ readonly level: number;
2425
+ readonly columnId: string;
2426
+ /** This level's own value — the last entry of `path`. */
2427
+ readonly value: unknown;
2428
+ readonly path: readonly unknown[];
2429
+ readonly expanded: boolean;
2430
+ /** Leaf row count under this group, regardless of collapse state. */
2431
+ readonly count: number;
2432
+ /** Position among the display rows as rendered — same invariant ResolvedRow.rowIndex keeps. */
2433
+ readonly rowIndex: number;
2434
+ /** This header's absolute position in the whole filtered/sorted/grouped dataset, matching ResolvedRow.datasetIndex. */
2435
+ readonly datasetIndex: number;
2436
+ /**
2437
+ * This group's own aggregate results, computed over its full leaf-row
2438
+ * descendants regardless of collapse state — see `withGroupAggregates`.
2439
+ * Empty when no `AggregateState` is active.
2440
+ */
2441
+ readonly aggregates: AggregateResults;
2442
+ }
2443
+ /**
2444
+ * A group's own aggregate results, rendered as a row of its own rather than
2445
+ * inline in its header — see `groupAggregateDisplay: "row"`. Emitted by
2446
+ * `withGroupAggregates` immediately after a group's last visible
2447
+ * descendant (its last nested group or data row, or immediately after its
2448
+ * own header when collapsed), at that same group's `level`, one per group
2449
+ * with `AggregateState` active — mirroring `ResolvedGroupRow` closely
2450
+ * enough that the two are meant to be read side by side.
2451
+ */
2452
+ interface ResolvedGroupSummaryRow {
2453
+ readonly kind: "group-summary";
2454
+ /** The group this summary belongs to — shared with that group's own `ResolvedGroupRow.groupId`, not a new id of its own. */
2455
+ readonly groupId: string;
2456
+ /** Nesting depth, matching the group's own `level`. */
2457
+ readonly level: number;
2458
+ /** Position among the display rows as rendered — same invariant every other DisplayRow's `rowIndex` keeps. */
2459
+ readonly rowIndex: number;
2460
+ /** This row's absolute position in the whole filtered/sorted/grouped dataset, matching ResolvedRow.datasetIndex. */
2461
+ readonly datasetIndex: number;
2462
+ /** This group's own aggregate results — identical to its `ResolvedGroupRow.aggregates`, computed once and shared rather than recomputed. */
2463
+ readonly aggregates: AggregateResults;
2464
+ }
2465
+ /**
2466
+ * One entry of a grouped result: an ordinary data row (no `kind` field at
2467
+ * all — ResolvedRow is unchanged, so every existing consumer of plain
2468
+ * ResolvedRow[] keeps compiling), a group header, or — only when
2469
+ * `groupAggregateDisplay: "row"` is active — that group's own summary row.
2470
+ * Discriminate with `"kind" in entry`, then `entry.kind`.
2471
+ */
2472
+ type DisplayRow<Row> = ResolvedRow<Row> | ResolvedGroupRow | ResolvedGroupSummaryRow;
2473
+ /** A reducer this package computes without a custom `AggregateFn`. */
2474
+ type BuiltInAggregate = "sum" | "avg" | "min" | "max" | "count" | "countDistinct";
2475
+ /**
2476
+ * Called with every raw row in scope — always the full leaf set, never a
2477
+ * partial reduction combined from child groups, so a non-associative
2478
+ * aggregate (median, distinct count) is never computed from
2479
+ * already-aggregated values. Mirrors `FilterPredicate`'s shape, minus the
2480
+ * per-row `value` since an aggregate reduces across rows rather than
2481
+ * testing one.
2482
+ */
2483
+ type AggregateFn<Row> = (rows: readonly Row[]) => unknown;
2484
+ /** One aggregate to compute against a column — a built-in reducer, or custom logic via `fn`. */
2485
+ interface AggregateSpec<Row> {
2486
+ readonly columnId: string;
2487
+ readonly fn: BuiltInAggregate | AggregateFn<Row>;
2488
+ /** Distinguishes two aggregates on the same column (e.g. both sum and avg of Amount). Defaults to columnId, mirroring ColumnDefinition.id defaulting to field. */
2489
+ readonly id?: string;
2490
+ /**
2491
+ * Overrides this aggregate's own cell alignment, in the grand-total
2492
+ * footer and a group's own summary row (`groupAggregateDisplay: "row"`)
2493
+ * — inline rendering (`"inline"`) is text, not a cell, so this has no
2494
+ * effect there. Falls back to the column's own `alignment` when omitted.
2495
+ * When two specs share a column and disagree, the first one in
2496
+ * `AggregateState` wins for that shared cell, since one `<td>` can only
2497
+ * take one `text-align`.
2498
+ */
2499
+ readonly alignment?: ColumnAlignment;
2500
+ }
2501
+ /**
2502
+ * The active aggregates to compute. Empty for a grid with none, mirroring
2503
+ * `FilterState`'s empty array for "no filter". A fully controlled prop —
2504
+ * unlike `sort`/`filter`/`groupBy`/`pagination`, there is no built-in UI
2505
+ * affordance for a user to add or remove an aggregate interactively.
2506
+ */
2507
+ type AggregateState<Row> = readonly AggregateSpec<Row>[];
2508
+ /** One computed aggregate result, keyed by `spec.id ?? spec.columnId`. */
2509
+ type AggregateResults = ReadonlyMap<string, unknown>;
2510
+ /**
2511
+ * Where a group's own aggregate results render. `"inline"` (the default)
2512
+ * keeps them as text in the group header itself, next to its leaf-row
2513
+ * count. `"row"` instead emits a `ResolvedGroupSummaryRow` immediately
2514
+ * after that group's last visible descendant, with each aggregate's value
2515
+ * in the `<td>` for its own column — the same alignment a grand-total
2516
+ * footer cell has to its column, just scoped to one group instead of the
2517
+ * whole dataset.
2518
+ */
2519
+ type GroupAggregateDisplay = "inline" | "row";
2520
+ interface FilterEntryBase<Row> {
2521
+ readonly columnId?: FieldPath<Row> | (string & {});
2522
+ }
2523
+ /** Matches a column's stringified value against an SQL LIKE-style query. */
2524
+ interface TextFilterEntry<Row> extends FilterEntryBase<Row> {
2525
+ /**
2526
+ * A bare query is an exact match; `%text%` is contains; `text%` is
2527
+ * starts-with; `%text` is ends-with. Always case-insensitive. Only the
2528
+ * first and last characters are read as anchors — a `%` anywhere else is
2529
+ * a literal character, not a wildcard.
2530
+ */
2531
+ readonly query: string;
2532
+ }
2533
+ /**
2534
+ * Matches a column's actual (non-stringified) value by strict equality —
2535
+ * only when the column's resolved `type` agrees: `number`/`decimal`/
2536
+ * `currency`/`percent` for a `number` value, `boolean` for a `boolean`
2537
+ * value, `date`/`dateTime`/`time` for a `Date` value (compared via
2538
+ * `getTime()`). A `value` against a column of the wrong type never matches,
2539
+ * rather than silently stringifying and falling through to a text
2540
+ * comparison — the whole point of this variant existing separately from
2541
+ * `TextFilterEntry` is that it doesn't do that.
2542
+ */
2543
+ interface ValueFilterEntry<Row> extends FilterEntryBase<Row> {
2544
+ readonly value: number | boolean | Date;
2545
+ }
2546
+ type FilterPredicate<Row> = (value: unknown, row: Row) => boolean;
2547
+ /**
2548
+ * Matches via caller-supplied logic — a numeric range, a cross-field
2549
+ * combination, anything `query`/`value` can't express. Called once per row,
2550
+ * not per column: when `columnId` is given, `value` is that column's value,
2551
+ * resolved for convenience; when it's omitted, `value` is `undefined` and
2552
+ * the predicate is expected to read whatever it needs off `row` itself.
2553
+ */
2554
+ interface PredicateFilterEntry<Row> extends FilterEntryBase<Row> {
2555
+ readonly predicate: FilterPredicate<Row>;
2556
+ }
2557
+ /**
2558
+ * A nested group of entries, combined with `combinator` instead of the
2559
+ * implicit AND every top-level `FilterState` uses. `entries` is itself a
2560
+ * `FilterState<Row>`, so groups nest to any depth — the only entry variant
2561
+ * with no `columnId` of its own, since it isn't scoped to one column, only
2562
+ * to the entries it composes.
2563
+ */
2564
+ interface GroupFilterEntry<Row> {
2565
+ readonly combinator: "and" | "or";
2566
+ readonly entries: FilterState<Row>;
2567
+ }
2568
+ /**
2569
+ * What an `OperatorFilterEntry` asks of a cell. `contains`, `notContains`,
2570
+ * `startsWith` and `endsWith` read the value as text; the rest compare it as
2571
+ * the column's `type` says.
2572
+ */
2573
+ type FilterOperator = "eq" | "ne" | "contains" | "notContains" | "startsWith" | "endsWith" | "gt" | "gte" | "lt" | "lte" | "between" | "in" | "isEmpty" | "isNotEmpty";
2574
+ /** A value an `OperatorFilterEntry` compares a cell against. */
2575
+ type FilterScalar = string | number | boolean | Date | null;
2576
+ /**
2577
+ * Matches one column's value by a named operator — plain data, unlike a
2578
+ * predicate, so a filter built from these can be saved and restored.
2579
+ *
2580
+ * `value` is one `FilterScalar` for most operators, a list of them for
2581
+ * `in`, a `[low, high]` pair for `between` (both ends inclusive), and
2582
+ * absent for `isEmpty`/`isNotEmpty`.
2583
+ *
2584
+ * - An empty cell is `null`, `undefined` or `""`. `isEmpty` matches it,
2585
+ * `isNotEmpty` does not, and so does no other operator — except `ne` and
2586
+ * `notContains`, which match it: a "not" filter must not quietly drop the
2587
+ * blanks. Each of those two is the exact opposite of `eq`/`contains`.
2588
+ * - The text operators compare the stringified value, case-insensitively.
2589
+ * - `eq`, `ne`, `gt`, `gte`, `lt`, `lte` and `between` compare as
2590
+ * `compareValues` does under the column's `type`: numerically,
2591
+ * chronologically, or as text (case-insensitively, like a query). A cell
2592
+ * of another kind — a string in a number column — is never equal, greater
2593
+ * or less.
2594
+ * - `in` matches the values grouping would put in the same group.
2595
+ * - A date column reads a string `value` as `new Date(value)`.
2596
+ * - A `value` of the wrong kind for the column — a string against a number
2597
+ * column, a missing pair for `between` — matches no row at all, as a
2598
+ * `ValueFilterEntry` of the wrong type doesn't.
2599
+ */
2600
+ interface OperatorFilterEntry<Row> {
2601
+ readonly columnId: FieldPath<Row> | (string & {});
2602
+ readonly operator: FilterOperator;
2603
+ readonly value?: FilterScalar | readonly FilterScalar[];
2604
+ }
2605
+ type FilterEntry<Row> = TextFilterEntry<Row> | ValueFilterEntry<Row> | PredicateFilterEntry<Row> | OperatorFilterEntry<Row> | GroupFilterEntry<Row>;
2606
+ /**
2607
+ * The active filter, every entry ANDed together at the top level — nest a
2608
+ * `GroupFilterEntry` for anything that needs OR. Empty for an unfiltered
2609
+ * grid, mirroring `ColumnSortState`'s empty array for "no sort".
2610
+ */
2611
+ type FilterState<Row> = readonly FilterEntry<Row>[];
2612
+ /**
2613
+ * A `ValueFilterEntry` as JSON holds it: a `Date` value becomes its ISO
2614
+ * string, which restoring turns back into a `Date`.
2615
+ */
2616
+ interface SerializedValueFilterEntry<Row> extends FilterEntryBase<Row> {
2617
+ readonly value: number | boolean | string;
2618
+ }
2619
+ /** A `FilterScalar` as JSON holds it: a `Date` becomes its ISO string. */
2620
+ type SerializedFilterScalar = string | number | boolean | null;
2621
+ /**
2622
+ * An `OperatorFilterEntry` as JSON holds it: each `Date` becomes its ISO
2623
+ * string, which restoring turns back into a `Date` when the column is a
2624
+ * date, date-time or time column.
2625
+ */
2626
+ interface SerializedOperatorFilterEntry<Row> {
2627
+ readonly columnId: FieldPath<Row> | (string & {});
2628
+ readonly operator: FilterOperator;
2629
+ readonly value?: SerializedFilterScalar | readonly SerializedFilterScalar[];
2630
+ }
2631
+ /** A `GroupFilterEntry` whose entries are serialised too. */
2632
+ interface SerializedGroupFilterEntry<Row> {
2633
+ readonly combinator: "and" | "or";
2634
+ readonly entries: SerializedFilterState<Row>;
2635
+ }
2636
+ /**
2637
+ * A filter entry that survives `JSON.stringify`: every kind but a predicate,
2638
+ * which is a function and cannot be written down.
2639
+ */
2640
+ type SerializedFilterEntry<Row> = TextFilterEntry<Row> | SerializedValueFilterEntry<Row> | SerializedOperatorFilterEntry<Row> | SerializedGroupFilterEntry<Row>;
2641
+ type SerializedFilterState<Row> = readonly SerializedFilterEntry<Row>[];
2642
+ /** Reports a filter change whole — the filter to persist from. */
2643
+ interface FilterChangeEvent<Row> {
2644
+ readonly filter: FilterState<Row>;
2645
+ }
2646
+ /**
2647
+ * Ids selected, in the order they were selected — so the most recent is last,
2648
+ * and a consumer wanting only that reads `at(-1)` rather than tracking it
2649
+ * alongside.
2650
+ *
2651
+ * Ordered rather than a keyed record for that reason alone; a render layer
2652
+ * that needs lookups builds a `Set` from it. Rows and columns share the type:
2653
+ * they are both a list of ids, and the state they live in already names which.
2654
+ */
2655
+ type SelectionState = readonly string[];
2656
+ /**
2657
+ * How much of a member may be selected at once. `false` rather than an absent
2658
+ * key so that turning selection off for one member reads the same as never
2659
+ * having enabled it.
2660
+ */
2661
+ type SelectionMode = false | "single" | "multiple";
2662
+ /**
2663
+ * The modes a cell may take. A cell addresses one value, so it has no
2664
+ * `"multiple"` — a range of cells is a different feature, with a rectangle
2665
+ * rather than a list behind it.
2666
+ */
2667
+ type CellSelectionMode = false | "single";
2668
+ /**
2669
+ * Which parts of the grid the user may select, and how many of each.
2670
+ *
2671
+ * Off by default, unlike `HoverableConfig`: selection claims the click, which
2672
+ * a grid that only displays data should not do.
2673
+ */
2674
+ interface SelectableConfig {
2675
+ rows?: SelectionMode | undefined;
2676
+ columns?: SelectionMode | undefined;
2677
+ cells?: CellSelectionMode | undefined;
2678
+ /**
2679
+ * Whether a plain click on a row toggles it rather than selecting it
2680
+ * alone — a checklist, where picking rows one after another should not
2681
+ * need Ctrl held down. Shift still selects a range and Ctrl/Cmd still
2682
+ * toggles. Rows only: a column or cell click is unchanged.
2683
+ */
2684
+ toggleOnClick?: boolean | undefined;
2685
+ }
2686
+ /**
2687
+ * What an interaction means for the selection, read off its modifiers once at
2688
+ * the boundary so that nothing downstream handles a raw event.
2689
+ */
2690
+ type SelectIntent = "replace" | "toggle" | "range";
2691
+ /** The address of one cell: which row, and which column within it. */
2692
+ interface SelectedCellRef {
2693
+ readonly rowId: string;
2694
+ readonly columnId: string;
2695
+ }
2696
+ /** The one selected cell, or `null` for none. */
2697
+ type CellSelectionState = SelectedCellRef | null;
2698
+ /**
2699
+ * What changed between two selections. Ids rather than resolved members, so
2700
+ * that the transform producing it stays free of the data it selects from.
2701
+ */
2702
+ interface SelectionDiff {
2703
+ readonly added: readonly string[];
2704
+ readonly removed: readonly string[];
2705
+ }
2706
+ /**
2707
+ * A row paired with the identity and position it renders under — the row
2708
+ * counterpart to `ResolvedColumn`, and resolved once for the same reason: so
2709
+ * no part of the grid works out a row's id for itself.
2710
+ *
2711
+ * It is also what the selection callbacks report, so a handler reads the row
2712
+ * itself rather than an id it has to look up.
2713
+ */
2714
+ interface ResolvedRow<Row> {
2715
+ readonly rowId: string;
2716
+ readonly row: Row;
2717
+ /** Position among the rows as rendered, matching `CellTemplateContext`. */
2718
+ readonly rowIndex: number;
2719
+ /** This row's absolute position in the whole filtered/sorted/grouped dataset, matching `CellTemplateContext`. */
2720
+ readonly datasetIndex: number;
2721
+ }
2722
+ /**
2723
+ * A selected column. Carries the resolved column rather than the bare
2724
+ * definition, so a handler reads the width and label the user actually
2725
+ * clicked rather than what the definition asked for.
2726
+ */
2727
+ interface SelectedColumn<Row, Node = string> {
2728
+ readonly columnId: string;
2729
+ readonly column: ResolvedColumn<Row, Node>;
2730
+ /** Position among the columns as displayed, so after any reorder. */
2731
+ readonly columnIndex: number;
2732
+ }
2733
+ /** A selected cell, resolved down to the value it shows. */
2734
+ interface SelectedCell<Row, Node = string> {
2735
+ readonly rowId: string;
2736
+ readonly columnId: string;
2737
+ readonly row: Row;
2738
+ readonly column: ResolvedColumn<Row, Node>;
2739
+ readonly rowIndex: number;
2740
+ readonly columnIndex: number;
2741
+ /** Read off the column's field path — the value a `cellTemplate` receives. */
2742
+ readonly value: unknown;
2743
+ }
2744
+ /**
2745
+ * Reports a click or double-click on a data row. Carries the modifiers and
2746
+ * button rather than the browser's own event, so a handler reads the same
2747
+ * payload whichever renderer drew the row.
2748
+ */
2749
+ interface RowPointerEvent<Row> {
2750
+ readonly row: ResolvedRow<Row>;
2751
+ /** The column of the cell the pointer was on, or `null` when it was on no cell. */
2752
+ readonly columnId: string | null;
2753
+ readonly native: {
2754
+ readonly ctrlKey: boolean;
2755
+ readonly metaKey: boolean;
2756
+ readonly shiftKey: boolean;
2757
+ readonly altKey: boolean;
2758
+ /** Which button was pressed, numbered as `MouseEvent.button` numbers them — `0` for the main one. */
2759
+ readonly button: number;
2760
+ };
2761
+ }
2762
+ /** Reports one row selected or deselected. */
2763
+ interface RowSelectEvent<Row> {
2764
+ readonly row: ResolvedRow<Row>;
2765
+ readonly selection: SelectionState;
2766
+ }
2767
+ /**
2768
+ * Reports every row one interaction selected or deselected. Fires once for a
2769
+ * range that `RowSelectEvent` reports one row at a time.
2770
+ */
2771
+ interface RowsSelectEvent<Row> {
2772
+ readonly rows: readonly ResolvedRow<Row>[];
2773
+ readonly selection: SelectionState;
2774
+ }
2775
+ /**
2776
+ * Reports a row selection change whole: what it gained, what it lost, and
2777
+ * everything it now holds. The one to persist from.
2778
+ */
2779
+ interface RowSelectionChangeEvent<Row> {
2780
+ readonly added: readonly ResolvedRow<Row>[];
2781
+ readonly removed: readonly ResolvedRow<Row>[];
2782
+ /** Every selected row, not only what this interaction changed. */
2783
+ readonly selected: readonly ResolvedRow<Row>[];
2784
+ readonly selection: SelectionState;
2785
+ }
2786
+ /** Reports one column selected or deselected. */
2787
+ interface ColumnSelectEvent<Row, Node = string> {
2788
+ readonly column: SelectedColumn<Row, Node>;
2789
+ readonly selection: SelectionState;
2790
+ }
2791
+ /** Reports every column one interaction selected or deselected. */
2792
+ interface ColumnsSelectEvent<Row, Node = string> {
2793
+ readonly columns: readonly SelectedColumn<Row, Node>[];
2794
+ readonly selection: SelectionState;
2795
+ }
2796
+ /** Reports a column selection change whole. The one to persist from. */
2797
+ interface ColumnSelectionChangeEvent<Row, Node = string> {
2798
+ readonly added: readonly SelectedColumn<Row, Node>[];
2799
+ readonly removed: readonly SelectedColumn<Row, Node>[];
2800
+ /** Every selected column, not only what this interaction changed. */
2801
+ readonly selected: readonly SelectedColumn<Row, Node>[];
2802
+ readonly selection: SelectionState;
2803
+ }
2804
+ /** Reports the cell selected or deselected. */
2805
+ interface CellSelectEvent<Row, Node = string> {
2806
+ readonly cell: SelectedCell<Row, Node>;
2807
+ readonly selection: CellSelectionState;
2808
+ }
2809
+ /**
2810
+ * Reports a cell selection change whole. Both fields are nullable and one
2811
+ * interaction can fill both — moving between cells deselects and selects at
2812
+ * once.
2813
+ */
2814
+ interface CellSelectionChangeEvent<Row, Node = string> {
2815
+ readonly selected: SelectedCell<Row, Node> | null;
2816
+ readonly deselected: SelectedCell<Row, Node> | null;
2817
+ readonly selection: CellSelectionState;
2818
+ }
2819
+ /**
2820
+ * Everything about a grid the user can change, one slice per feature. Each
2821
+ * slice is the same `*State` type its own `default*` prop and change event
2822
+ * already use, so state read from here can be fed straight back as a default.
2823
+ */
2824
+ interface GridState<Row> {
2825
+ readonly columnSizing: ColumnSizingState;
2826
+ readonly columnOrder: ColumnOrderState;
2827
+ readonly columnVisibility: ColumnVisibilityState;
2828
+ readonly columnSort: ColumnSortState;
2829
+ readonly filter: FilterState<Row>;
2830
+ readonly groupBy: GroupByState;
2831
+ readonly groupExpansion: GroupExpansionState;
2832
+ readonly pagination: PaginationState;
2833
+ readonly rowSelection: SelectionState;
2834
+ readonly columnSelection: SelectionState;
2835
+ readonly cellSelection: CellSelectionState;
2836
+ }
2837
+ /**
2838
+ * `GridState` as `serializeGridState` writes it: safe to pass through
2839
+ * `JSON.stringify` and back, and to hand straight to `restoreState`.
2840
+ */
2841
+ interface SerializedGridState<Row> extends Omit<GridState<Row>, "filter"> {
2842
+ readonly filter: SerializedFilterState<Row>;
2843
+ }
2844
+ /**
2845
+ * The slices the view is derived from: every one but the selections, which
2846
+ * change what is highlighted and never what is shown. A whole `GridState`
2847
+ * is one.
2848
+ */
2849
+ type GridViewState<Row> = Omit<GridState<Row>, "rowSelection" | "columnSelection" | "cellSelection">;
2850
+ /**
2851
+ * The settings that shape the view but are not user state: what the grid is
2852
+ * configured to do, plus the one measurement — `viewportWidth` — that fitting
2853
+ * columns needs from the page. Every field falls back to the same default
2854
+ * the React grid's matching prop does.
2855
+ */
2856
+ interface GridViewOptions<Row> {
2857
+ /** Whether `pageRows` is one page of `displayRows` rather than all of it. Defaults to `false`. */
2858
+ readonly paginated?: boolean | undefined;
2859
+ readonly aggregates?: AggregateState<Row> | undefined;
2860
+ /** Defaults to `"inline"`. */
2861
+ readonly groupAggregateDisplay?: GroupAggregateDisplay | undefined;
2862
+ readonly columnSizeDefaults?: Partial<ColumnSizeDefaults> | undefined;
2863
+ readonly resizableColumns?: boolean | undefined;
2864
+ readonly reorderableColumns?: boolean | undefined;
2865
+ readonly groupByDraggableColumns?: boolean | undefined;
2866
+ /** Defaults to `"fit"`, which only takes effect once `viewportWidth` is known. */
2867
+ readonly resizeMode?: ResizeMode | undefined;
2868
+ /**
2869
+ * The width, in px, `"fit"` fills. `null` or absent before it has been
2870
+ * measured, or where there is no viewport at all (an export in Node), and
2871
+ * then columns keep their resolved widths.
2872
+ */
2873
+ readonly viewportWidth?: number | null | undefined;
2874
+ }
2875
+ /** What `resolveGridView` derives the view from. */
2876
+ interface GridViewInput<Row, Node = string> {
2877
+ readonly rows: readonly Row[];
2878
+ readonly getRowId?: ((row: Row, index: number) => string) | undefined;
2879
+ readonly columns: readonly ColumnDefinition<Row, Node>[];
2880
+ readonly state: GridViewState<Row>;
2881
+ readonly options: GridViewOptions<Row>;
2882
+ }
2883
+ /**
2884
+ * What the user is looking at, derived once from `GridViewInput` — every
2885
+ * list a renderer draws, and the ones an export, a toolbar or a status line
2886
+ * reads, so none of them composes the pipeline for itself.
2887
+ */
2888
+ interface GridView<Row, Node = string> {
2889
+ /** Every column, hidden ones included, ordered but not sized — what the data stages read. */
2890
+ readonly dataColumns: readonly DataColumn<Row, Node>[];
2891
+ /** The columns as rendered: visible, ordered and sized. */
2892
+ readonly columns: readonly ResolvedColumn<Row, Node>[];
2893
+ /** The rows, filtered then sorted. */
2894
+ readonly rows: readonly ResolvedRow<Row>[];
2895
+ /** `rows` grouped, with each group's aggregates attached — every page of it. */
2896
+ readonly displayRows: readonly DisplayRow<Row>[];
2897
+ /** The current page of `displayRows`; all of it when not paginated. */
2898
+ readonly pageRows: readonly DisplayRow<Row>[];
2899
+ /** `pageRows` narrowed to its data rows, in display order — what a range selection spans. */
2900
+ readonly displayDataRows: readonly ResolvedRow<Row>[];
2901
+ /** `1` when not paginated. */
2902
+ readonly pageCount: number;
2903
+ /** `state.pagination.pageIndex` clamped into range; `0` when not paginated. */
2904
+ readonly pageIndex: number;
2905
+ /** Every aggregate over all of `rows`, ungrouped and unpaginated. */
2906
+ readonly grandTotal: AggregateResults;
2907
+ }
2908
+
2909
+ /**
2910
+ * Creates the state container for one grid — see `GridController`. Hold one
2911
+ * per grid for its whole life: it keeps the uncontrolled slices, and its view
2912
+ * is memoised across calls the way `createGridViewResolver`'s is.
2913
+ */
2914
+ declare function createGridController<Row, Node = string>(initial: GridControllerOptions<Row, Node>): GridController<Row, Node>;
2915
+
2916
+ /** What `createCommandContext` builds a context from. */
2917
+ interface GridCommandContextInput<Row, Node> {
2918
+ readonly controller: GridController<Row, Node>;
2919
+ readonly target: GridCommandTarget;
2920
+ /** The grid's messages, already laid over the defaults — see `resolveMessages`. */
2921
+ readonly messages: GridMessages;
2922
+ readonly host: GridCommandHost;
2923
+ }
2924
+ /**
2925
+ * A command context for `target`, over the controller's state, view and
2926
+ * options as they are now. The controller itself serves as `actions`, typed
2927
+ * down to them, so a command cannot reach `setOptions`.
2928
+ *
2929
+ * `row` and `column` are looked up once here, against every filtered row and
2930
+ * every column, hidden ones included, so a target the API names off screen
2931
+ * still resolves.
2932
+ */
2933
+ declare function createCommandContext<Row, Node>({ controller, target, messages, host, }: GridCommandContextInput<Row, Node>): GridCommandContext<Row>;
2934
+
2935
+ /**
2936
+ * Every command a grid knows, by id: the built-ins, then `commands` — an app
2937
+ * command with a built-in's id replacing it, so every menu and toolbar
2938
+ * listing that id gets the app's version (translated, gated by a privilege,
2939
+ * or doing something else) without being changed itself.
2940
+ *
2941
+ * A fresh map per call; a renderer resolves it once per change to
2942
+ * `commands`, not per menu.
2943
+ */
2944
+ declare function resolveCommands<Row>(commands: readonly GridCommand<Row>[] | undefined): ReadonlyMap<string, GridCommand<Row>>;
2945
+ /**
2946
+ * Runs `command` when it is visible and enabled on `context`'s target, and
2947
+ * says whether it did — so a renderer reports only a command that ran, and a
2948
+ * stale button or a call through the API cannot run one the grid's state no
2949
+ * longer allows.
2950
+ */
2951
+ declare function runCommand<Row>(command: GridCommand<Row>, context: GridCommandContext<Row>): boolean;
2952
+
2953
+ /** What `resolveMenu` resolves a menu's entries against. */
2954
+ interface MenuResolveOptions<Row> {
2955
+ /** Every command the grid knows, by id — see `resolveCommands`. */
2956
+ readonly commands: ReadonlyMap<string, GridCommand<Row>>;
2957
+ readonly context: GridCommandContext<Row>;
2958
+ }
2959
+ /**
2960
+ * A menu's entries resolved against the grid as `context` sees it, ready to
2961
+ * draw:
2962
+ *
2963
+ * - A command id becomes its command's item, and a hidden command or item
2964
+ * is left out. An id naming no command is left out too, and reported once
2965
+ * per command map through `console.error`.
2966
+ * - Labels become strings and flags booleans; `checked` stays `undefined`
2967
+ * for an item that is not checkable.
2968
+ * - A submenu is resolved the same way, and left out when nothing in it
2969
+ * shows.
2970
+ * - Separators never lead, trail or double up, however the items around
2971
+ * them came and went.
2972
+ *
2973
+ * An empty result means there is nothing to show — no grid menu at all
2974
+ * here.
2975
+ */
2976
+ declare function resolveMenu<Row>(entries: readonly MenuEntry<Row>[], options: MenuResolveOptions<Row>): readonly ResolvedMenuEntry[];
2977
+
2978
+ /** Where an arrow, Home or End key moves a menu's focus. */
2979
+ type MenuMove = "next" | "previous" | "first" | "last";
2980
+ /**
2981
+ * The index of the item focus moves to from `from` — `-1` when nothing is
2982
+ * focused yet, so `"next"` lands on the first item and `"previous"` on the
2983
+ * last. Separators are skipped and `"next"`/`"previous"` wrap round the
2984
+ * ends; disabled items count, since they stay focusable for a screen reader
2985
+ * to find. `-1` when there is no item at all.
2986
+ *
2987
+ * Takes anything with a `type`, so a behaviour that reads its items off the
2988
+ * page can pass `{ type: "item" }` for each.
2989
+ */
2990
+ declare function nextMenuIndex(entries: readonly Pick<ResolvedMenuEntry, "type">[], from: number, move: MenuMove): number;
2991
+ /**
2992
+ * The index of the item `query` — what was typed, buffered for a moment —
2993
+ * picks, matched case-insensitively against the start of each label and
2994
+ * wrapping round the end; `-1` when none matches.
2995
+ *
2996
+ * `from` is the item focused now. A single letter, or the same letter
2997
+ * typed again and again, searches from the item after it, so repeating a
2998
+ * letter steps through every item it starts. A longer query searches from
2999
+ * `from` itself, so the item already found stays put while what is typed
3000
+ * still matches it.
3001
+ */
3002
+ declare function typeaheadIndex(labels: readonly string[], from: number, query: string): number;
3003
+
3004
+ /** What `resolveToolbar` resolves a toolbar's entries against. */
3005
+ interface ToolbarResolveOptions<Row> {
3006
+ /** Every command the grid knows, by id — see `resolveCommands`. */
3007
+ readonly commands: ReadonlyMap<string, GridCommand<Row>>;
3008
+ /**
3009
+ * The context an item resolves and runs in, for its target — the item
3010
+ * itself, or the dropdown an item in one is listed under. A command that
3011
+ * opens a panel anchors it there.
3012
+ */
3013
+ readonly contextFor: (target: GridToolbarTarget) => GridCommandContext<Row>;
3014
+ }
3015
+ /**
3016
+ * A toolbar's entries resolved against the grid, ready to draw, by the
3017
+ * rules `resolveMenu` follows:
3018
+ *
3019
+ * - A command id becomes its command's button, and an inline item a button
3020
+ * of its own; either is a toggle, with `pressed`, when it is checkable. A
3021
+ * hidden one is left out, and so is an id naming no command, reported
3022
+ * once per command map through `console.error`.
3023
+ * - A submenu becomes a dropdown, its items resolved as a menu's, and is
3024
+ * left out when nothing in it shows. `"export"` is one too, of the export
3025
+ * commands, keyed `"export"`.
3026
+ * - `"search"`, `"spacer"` and custom entries stay as they are.
3027
+ * - Separators never lead, trail, double up or sit next to a spacer, which
3028
+ * already parts what is on either side of it.
3029
+ *
3030
+ * Resolve again whenever the grid changes, so each button's label, flags
3031
+ * and `run` follow its state.
3032
+ */
3033
+ declare function resolveToolbar<Row>(entries: readonly ToolbarEntry<Row>[], options: ToolbarResolveOptions<Row>): readonly ResolvedToolbarItem[];
3034
+
3035
+ /** What `fitToolbarItems` fits: a toolbar's entries, by width, into its space. */
3036
+ interface ToolbarFitInput {
3037
+ /** Each entry's width, in order — `0` for a spacer, whose width is only the space left over. */
3038
+ readonly widths: readonly number[];
3039
+ /** The width the entries share. */
3040
+ readonly available: number;
3041
+ /** The width of the "More" button the entries that do not fit go into. */
3042
+ readonly moreWidth: number;
3043
+ /** Whether each entry, in order, stays however little room there is. */
3044
+ readonly pinned: readonly boolean[];
3045
+ }
3046
+ /**
3047
+ * How many of a toolbar's entries fit, from the start: the first `count`
3048
+ * stay in the toolbar, with every pinned entry after them, and the rest go
3049
+ * into a "More" menu.
3050
+ *
3051
+ * Pinned entries take their room first, wherever they are. Room for "More"
3052
+ * is kept only when something does not fit — when everything does, the
3053
+ * result is every entry and no "More" is drawn. Entries are taken in order
3054
+ * and the first that does not fit ends the count, so the toolbar keeps its
3055
+ * order rather than filling gaps with later, narrower entries; one with no
3056
+ * width, a spacer, fits wherever the entries before it did.
3057
+ */
3058
+ declare function fitToolbarItems({ widths, available, moreWidth, pinned, }: ToolbarFitInput): number;
3059
+ /**
3060
+ * Whether a toolbar entry stays in the toolbar however narrow it gets: the
3061
+ * search box and custom entries, which have no menu item to become.
3062
+ */
3063
+ declare function isPinnedToolbarItem(item: Pick<ResolvedToolbarItem, "type">): boolean;
3064
+ /** A toolbar split at the count `fitToolbarItems` gave — see `splitToolbarItems`. */
3065
+ interface ToolbarSplit {
3066
+ /** What stays in the toolbar. */
3067
+ readonly shown: readonly ResolvedToolbarItem[];
3068
+ /** The "More" menu's entries, empty when everything fits. */
3069
+ readonly overflow: readonly ResolvedMenuEntry[];
3070
+ }
3071
+ /**
3072
+ * `items` split at the first `fit`: those before it, and every pinned item,
3073
+ * stay in the toolbar; the rest become the "More" menu's entries — a button
3074
+ * an item, checked where it was pressed, and a dropdown a submenu. Neither
3075
+ * side keeps a separator at its ends, doubled, or beside a spacer.
3076
+ */
3077
+ declare function splitToolbarItems(items: readonly ResolvedToolbarItem[], fit: number): ToolbarSplit;
3078
+
3079
+ /**
3080
+ * What a search box shows for `filter`: the global text entry's query — the
3081
+ * one naming no column — without the `%` anchors that make it a "contains"
3082
+ * match, or `""` when there is none. A `%` the user typed inside the text
3083
+ * stays: only the first and last characters are anchors.
3084
+ */
3085
+ declare function searchTextOf<Row>(filter: FilterState<Row>): string;
3086
+ /**
3087
+ * `filter` with its global text entry set to search for `text` anywhere in
3088
+ * any column — the query `%text%` — or removed for an empty `text`. Every
3089
+ * entry naming a column stays as it was. `filter` itself, unchanged, when
3090
+ * it already searches for `text`.
3091
+ *
3092
+ * `text` is written as typed, spaces and all: a search box reads its text
3093
+ * back from the filter, and trimming here would take a space away from
3094
+ * under the caret as the user types it.
3095
+ */
3096
+ declare function setSearchText<Row>(filter: FilterState<Row>, text: string): FilterState<Row>;
3097
+
3098
+ /**
3099
+ * How a column of `type` aligns by default. Numeric types align right so that
3100
+ * their digits line up by place value; everything else reads from the left.
3101
+ */
3102
+ declare function alignmentForType(type: ColumnType): ColumnAlignment;
3103
+ /**
3104
+ * Derives one column per field across `rows`, in the order each field is first
3105
+ * seen — so a key that only appears in a later row still gets a column,
3106
+ * appended at the end. Nested objects contribute their non-object properties
3107
+ * as `"Parent.Child"`; anything deeper is skipped, as is the nested object
3108
+ * itself.
3109
+ *
3110
+ * Order follows `Object.entries`, which lists integer-like keys first
3111
+ * regardless of the order they were written in.
3112
+ *
3113
+ * `Node` is whatever the caller's renderer draws: an inferred column sets no
3114
+ * template, so it suits any.
3115
+ */
3116
+ declare function defineColumnsFromRows<Row, Node = string>(rows: readonly Row[]): readonly ColumnDefinition<Row, Node>[];
3117
+ /**
3118
+ * The key state about a column is stored under, and the key it renders with.
3119
+ * Every such lookup goes through here so the two can never disagree.
3120
+ */
3121
+ declare function getColumnId<Row>(column: ColumnDefinition<Row, unknown>): string;
3122
+ /**
3123
+ * The key state about a row is stored under, and the key it renders with — the
3124
+ * row's counterpart to `getColumnId`, and for the same reason: every such
3125
+ * lookup goes through here so no two can disagree.
3126
+ *
3127
+ * Falls back to the position so a grid given no `getRowId` still works. That
3128
+ * fallback ties a selection to where a row sits rather than to the row, so
3129
+ * anything that sorts, filters or pages its data has to supply one — otherwise
3130
+ * a re-sort leaves the same positions selected under different rows.
3131
+ */
3132
+ declare function resolveRowId<Row>(row: Row, index: number, getRowId?: (row: Row, index: number) => string): string;
3133
+ /**
3134
+ * What a column's header shows: its own `headerTemplate`, called first if it is
3135
+ * a function, or else its plain-text `header`, or else a label read off the
3136
+ * field path.
3137
+ */
3138
+ declare function resolveColumnLabel<Row, Node>(column: ColumnDefinition<Row, Node>): Node | string;
3139
+ /**
3140
+ * A column's name as text, for wherever markup will not do — an
3141
+ * announcement, an export. Its `header` first, even beside a
3142
+ * `headerTemplate`, since a template's output need not be text; then the
3143
+ * label `resolveColumnLabel` gives, when that is a string; then the label
3144
+ * read off the field path.
3145
+ */
3146
+ declare function resolveColumnHeaderText<Row>(column: ColumnDefinition<Row, unknown>): string;
3147
+ /** Which of a column header's keyboard interactions to announce. */
3148
+ interface KeyShortcutCapabilities {
3149
+ reorderable: boolean;
3150
+ resizable: boolean;
3151
+ sortable: boolean;
3152
+ groupable: boolean;
3153
+ /** Whether the column has a filter menu the header opens. Defaults to `false`. */
3154
+ filterable?: boolean | undefined;
3155
+ /** Whether the header opens the grid's context menu. Defaults to `false`. */
3156
+ contextMenu?: boolean | undefined;
3157
+ }
3158
+ /**
3159
+ * The `aria-keyshortcuts` string for a column header, naming only the keys
3160
+ * that column actually responds to — so the keys are discoverable, since
3161
+ * none of them is a convention a user would try unprompted.
3162
+ */
3163
+ declare function buildKeyShortcuts(capabilities: KeyShortcutCapabilities): string;
3164
+ /**
3165
+ * Accesses a value at a dotted path, e.g. `foo.bar.baz`.
3166
+ *
3167
+ * @param obj The object to access
3168
+ * @param path Path to the value, e.g. `"foo.bar"`
3169
+ * @returns The value at `path`, or `undefined` if it doesn't exist
3170
+ */
3171
+ declare function accessDotted(obj: unknown, path: string): unknown;
3172
+
3173
+ /**
3174
+ * The header's row index. One coordinate space covers the header and the body
3175
+ * so that arrowing up out of the first row reaches the header without a case
3176
+ * of its own, and every other move is plain arithmetic.
3177
+ */
3178
+ declare const HEADER_ROW = -1;
3179
+ /** The cell the grid's single tab stop sits on. */
3180
+ interface GridFocus {
3181
+ readonly rowIndex: number;
3182
+ readonly columnIndex: number;
3183
+ }
3184
+ /** The modifier keys held with a navigation key press. */
3185
+ interface NavigationModifiers {
3186
+ readonly ctrlKey: boolean;
3187
+ readonly metaKey: boolean;
3188
+ readonly altKey: boolean;
3189
+ readonly shiftKey: boolean;
3190
+ }
3191
+ /**
3192
+ * Holds a coordinate inside the grid, so that a focus surviving a column
3193
+ * removal or a shorter page never leaves the grid with no tab stop at all —
3194
+ * which is a grid a keyboard cannot reach.
3195
+ */
3196
+ declare function clampFocus(focus: GridFocus, rowCount: number, columnCount: number): GridFocus;
3197
+ /**
3198
+ * The focus a navigation key press moves to, or `null` when the key isn't
3199
+ * this grid's to handle — left for the browser or another handler.
3200
+ *
3201
+ * `pageSize` is a pre-measured row count rather than a callback: this
3202
+ * function takes plain data only, so a caller measures the viewport once and
3203
+ * hands over the number.
3204
+ *
3205
+ * `isSkippableRow` names rows the vertical moves (`ArrowUp`/`ArrowDown`/
3206
+ * `PageUp`/`PageDown`/`Ctrl+End`) never land a tab stop on — a group's own
3207
+ * summary row (`groupAggregateDisplay: "row"`), which still occupies a real
3208
+ * row slot for `rowCount`/`aria-rowindex` purposes but is presentational,
3209
+ * not a stop of its own. Left/right and plain `Home`/`End` stay row-scoped
3210
+ * and so never consult it. Defaults to skipping nothing, so every existing
3211
+ * caller (and every horizontal move) is unaffected.
3212
+ */
3213
+ declare function nextFocusForKey(key: string, modifiers: NavigationModifiers, focus: GridFocus, rowCount: number, columnCount: number, pageSize: number, isSkippableRow?: (rowIndex: number) => boolean): GridFocus | null;
3214
+
3215
+ /**
3216
+ * Puts `columns` in the order `order` gives. Ids it lists come first, in that
3217
+ * order; columns it omits keep their position among the definitions and
3218
+ * follow. Ids naming no column are ignored.
3219
+ *
3220
+ * Tolerating both gaps is what lets a stored order outlive the column list it
3221
+ * was made against.
3222
+ */
3223
+ declare function applyColumnOrder<Row, Node>(columns: readonly ColumnDefinition<Row, Node>[], order: ColumnOrderState): readonly ColumnDefinition<Row, Node>[];
3224
+ /**
3225
+ * `columns` in the order `order` gives, each paired with its id — the
3226
+ * width-free column list the data stages (filter, sort, group, aggregate)
3227
+ * read. Ordered here, ahead of sizing, so every later stage sees the one
3228
+ * already-ordered list and no part of the grid has to know a reorder
3229
+ * happened.
3230
+ */
3231
+ declare function resolveDataColumns<Row, Node>(columns: readonly ColumnDefinition<Row, Node>[], order: ColumnOrderState): readonly DataColumn<Row, Node>[];
3232
+ /**
3233
+ * The order with `movedId` lifted out and put back in front of `beforeId`, or
3234
+ * at the end when that is `null`.
3235
+ *
3236
+ * Returns `orderedIds` itself when the move changes nothing, so callers can
3237
+ * treat an unchanged reference as "no move happened".
3238
+ */
3239
+ declare function moveColumnBefore(orderedIds: ColumnOrderState, movedId: string, beforeId: string | null): ColumnOrderState;
3240
+ /**
3241
+ * Whether moving `movedId` in front of `beforeId` would rearrange anything, so
3242
+ * that a drop indicator promises exactly the moves that happen.
3243
+ *
3244
+ * Defined against `moveColumnBefore` rather than restating its conditions, so
3245
+ * the two cannot disagree about what a no-op is.
3246
+ */
3247
+ declare function movesColumn(orderedIds: ColumnOrderState, movedId: string, beforeId: string | null): boolean;
3248
+ /**
3249
+ * The id a drop on `side` of `targetId` lands in front of, which is `null`
3250
+ * past the last column.
3251
+ *
3252
+ * "After C" and "before D" name the same gap, so collapsing both to one id
3253
+ * keeps a drop target a single nullable string.
3254
+ */
3255
+ declare function resolveDropBefore(orderedIds: ColumnOrderState, targetId: string, side: DropSide): string | null;
3256
+ /**
3257
+ * The `beforeId` a keyboard nudge on `columnId` produces, for `onDrop` to
3258
+ * apply the same way a pointer drop does — or `undefined` when the nudge is a
3259
+ * no-op: `columnId` is not in `orderedIds`, or the nudge would move it left
3260
+ * of the start.
3261
+ *
3262
+ * `null` is a real answer here, not "no-op": it means append to the end, the
3263
+ * same convention `moveColumnBefore` uses.
3264
+ */
3265
+ declare function resolveKeyboardDropTarget(orderedIds: ColumnOrderState, columnId: string, direction: -1 | 1): string | null | undefined;
3266
+
3267
+ /**
3268
+ * The selection with `id` added if absent and removed if present — a
3269
+ * Ctrl-click, or Space on the focused member.
3270
+ *
3271
+ * The mode is enforced here rather than by each caller, so `"single"` cannot
3272
+ * accumulate no matter which interaction reaches it. Returns `selection`
3273
+ * itself when `mode` is `false`, keeping the unchanged-reference contract
3274
+ * `moveColumnBefore` set: a caller treats an unchanged reference as "nothing
3275
+ * happened" and neither renders nor reports.
3276
+ */
3277
+ declare function toggleSelection(selection: SelectionState, id: string, mode: SelectionMode): SelectionState;
3278
+ /**
3279
+ * The selection reduced to `id` alone — a plain click, which discards what
3280
+ * came before rather than adding to it.
3281
+ *
3282
+ * Never deselects, so clicking the one selected row leaves it selected.
3283
+ * Letting go of it is Ctrl-click's job, and `toggleSelection`'s.
3284
+ */
3285
+ declare function selectOnly(selection: SelectionState, id: string, mode: SelectionMode): SelectionState;
3286
+ /**
3287
+ * The selection replaced by every id from `anchorId` to `focusId` inclusive — a
3288
+ * Shift-click. The two may be given in either order.
3289
+ *
3290
+ * Spans `orderedIds`, the order as displayed, rather than the selection's own:
3291
+ * the range a user drew across the screen is the range they mean, whatever
3292
+ * order they clicked its ends in. Degrades to `selectOnly` under `"single"`,
3293
+ * where a range has nowhere to go.
3294
+ */
3295
+ declare function selectRange(selection: SelectionState, orderedIds: readonly string[], anchorId: string, focusId: string, mode: SelectionMode): SelectionState;
3296
+ /**
3297
+ * Every id in `orderedIds`, or `selection` untouched under any mode but
3298
+ * `"multiple"` — there is no selecting all of one thing.
3299
+ */
3300
+ declare function selectAll(selection: SelectionState, orderedIds: readonly string[], mode: SelectionMode): SelectionState;
3301
+ declare function clearSelection(selection: SelectionState): SelectionState;
3302
+ /**
3303
+ * What one transition added and what it removed.
3304
+ *
3305
+ * Defined here rather than in an adapter so that every callback reporting a
3306
+ * selection change reads one answer, and a select and a deselect fired for the
3307
+ * same interaction cannot disagree about which it was.
3308
+ */
3309
+ declare function diffSelection(previous: SelectionState, next: SelectionState): SelectionDiff;
3310
+ declare function isSameCell(a: CellSelectionState, b: CellSelectionState): boolean;
3311
+ /**
3312
+ * The cell selection moved to `cell` — a plain click. Idempotent: clicking the
3313
+ * selected cell again leaves it selected, matching `selectOnly`.
3314
+ */
3315
+ declare function selectCell(selection: CellSelectionState, cell: SelectedCellRef, mode: CellSelectionMode): CellSelectionState;
3316
+ /**
3317
+ * The cell selection moved to `cell`, or cleared when it is already there — a
3318
+ * Ctrl-click, matching `toggleSelection`.
3319
+ */
3320
+ declare function toggleCellSelection(selection: CellSelectionState, cell: SelectedCellRef, mode: CellSelectionMode): CellSelectionState;
3321
+ /**
3322
+ * The intent a click or key press carries, by the modifiers held with it.
3323
+ *
3324
+ * `toggleOnClick` makes the unmodified press a toggle — the
3325
+ * `selectable.toggleOnClick` checklist behaviour — leaving Shift and Ctrl
3326
+ * to mean what they always do.
3327
+ */
3328
+ declare function intentOf(event: {
3329
+ ctrlKey: boolean;
3330
+ metaKey: boolean;
3331
+ shiftKey: boolean;
3332
+ }, options?: {
3333
+ toggleOnClick?: boolean | undefined;
3334
+ }): SelectIntent;
3335
+ /**
3336
+ * The transform an intent asks for. A function rather than a branch inside
3337
+ * each caller, so a row and a column cannot come to mean different things by
3338
+ * the same click.
3339
+ */
3340
+ declare function applySelectionIntent(selection: SelectionState, orderedIds: readonly string[], anchorId: string | null, id: string, intent: SelectIntent, mode: SelectionMode): SelectionState;
3341
+
3342
+ /**
3343
+ * Applied to any column that does not size itself. The minimum is a width a
3344
+ * header stays legible at rather than a measured value — a column dragged
3345
+ * narrower than this reads as a rendering fault.
3346
+ */
3347
+ declare const DEFAULT_COLUMN_SIZES: ColumnSizeDefaults;
3348
+ /** How far one arrow key press moves a column edge. */
3349
+ declare const KEYBOARD_STEP = 10;
3350
+ /**
3351
+ * The bounds `column` may be sized between. Resolved in one place so that a
3352
+ * drag, a clamp and an auto-fit cannot disagree about a column's limits.
3353
+ */
3354
+ declare function resolveColumnConstraints<Row>(column: ColumnDefinition<Row, unknown>, defaults?: Partial<ColumnSizeDefaults>): ColumnConstraints;
3355
+ /** Holds `width` within `constraints`. */
3356
+ declare function clampColumnWidth(width: number, constraints: ColumnConstraints): number;
3357
+ /**
3358
+ * Pairs each column with everything needed to render it — the width it sits
3359
+ * at, the label its header shows, whether it may be resized and how its cells
3360
+ * align. Widths take the first of the sizing state, the column's own `width`,
3361
+ * and the default, then clamp.
3362
+ *
3363
+ * The sizing state winning means a user's drag outlives a re-render; a column
3364
+ * absent from it still tracks a `width` edited in the definition.
3365
+ */
3366
+ declare function resolveColumnWidths<Row, Node>(columns: readonly ColumnDefinition<Row, Node>[], sizing: ColumnSizingState, options?: ColumnResolveOptions): readonly ResolvedColumn<Row, Node>[];
3367
+ declare function totalColumnWidth<Row, Node>(resolved: readonly ResolvedColumn<Row, Node>[]): number;
3368
+ /**
3369
+ * Opens a resize. The session captures its constraints and starting point up
3370
+ * front, so applying a pointer position later is arithmetic on numbers alone —
3371
+ * which is what keeps the drag testable without a DOM.
3372
+ *
3373
+ * @param startPosition Where the pointer went down, on the axis being dragged.
3374
+ */
3375
+ declare function beginColumnResize<Row>(column: ColumnDefinition<Row, unknown>, startWidth: number, startPosition: number, defaults?: Partial<ColumnSizeDefaults>): ColumnResizeSession;
3376
+ /**
3377
+ * The width the dragged column takes with the pointer at `position`. The delta
3378
+ * is signed, so a right-to-left adapter negates it and nothing else changes.
3379
+ */
3380
+ declare function applyColumnResize(session: ColumnResizeSession, position: number): number;
3381
+ /**
3382
+ * Fits columns to `availableWidth`: grows them to fill leftover space, or
3383
+ * shrinks them to relieve an overflow, in both cases proportionally to each
3384
+ * column's current width. Columns the user has sized are left alone in
3385
+ * either direction, so dragging one column neither rubber-bands it back nor
3386
+ * has it absorb a squeeze meant for the rest.
3387
+ *
3388
+ * Growing stops at each column's `maxWidth`; shrinking stops at its
3389
+ * `minWidth`. If shrinking every adjustable column to its floor still does
3390
+ * not reach `availableWidth`, the columns are returned untouched and the
3391
+ * container scrolls rather than crushing them further.
3392
+ */
3393
+ declare function fitColumnsToWidth<Row, Node>(resolved: readonly ResolvedColumn<Row, Node>[], availableWidth: number, defaults?: Partial<ColumnSizeDefaults>): readonly ResolvedColumn<Row, Node>[];
3394
+ /**
3395
+ * The width a column needs to show `measuredWidth` of content.
3396
+ *
3397
+ * `padding` is an allowance on top of the measurement, since a column sized to
3398
+ * exactly its content can still round down into an ellipsis.
3399
+ */
3400
+ declare function sizeColumnToContent(measuredWidth: number, constraints: ColumnConstraints, padding?: number): number;
3401
+ /**
3402
+ * `current` with `columnId` reverted to its width in `base` — or omitted
3403
+ * entirely if `base` had none — for Escape to restore a resize in progress.
3404
+ *
3405
+ * A column with no stored width in `base` is correctly omitted by deleting
3406
+ * the key rather than merging its `base` width back in, which would
3407
+ * otherwise leave it pinned and hidden from auto-fit.
3408
+ */
3409
+ declare function revertColumnSize(current: ColumnSizingState, base: ColumnSizingState, columnId: string): ColumnSizingState;
3410
+
3411
+ /**
3412
+ * Compares two cell values the way `type` implies — numerically for the
3413
+ * numeric types, chronologically for the date/time types, lexically
3414
+ * otherwise. Defaults to string comparison when `type` is absent, mirroring
3415
+ * `ColumnDefinition.type`'s own default.
3416
+ *
3417
+ * `null`/`undefined` sort after every value on both sides. Used directly,
3418
+ * that ordering is fixed; `sortRows` applies it directionally without
3419
+ * disturbing it — see its own doc comment.
3420
+ */
3421
+ declare function compareValues(a: unknown, b: unknown, type?: ColumnType): number;
3422
+ /** This column's direction in `sort`, or `null` outside it. */
3423
+ declare function sortDirectionFor(sort: ColumnSortState, columnId: string): SortDirection | null;
3424
+ /** This column's 1-based place in `sort`, or `null` outside it. */
3425
+ declare function sortPriorityFor(sort: ColumnSortState, columnId: string): number | null;
3426
+ /**
3427
+ * The sort with `columnId` cycled to its next direction — none → asc → desc →
3428
+ * none.
3429
+ *
3430
+ * `stack: false` (a plain click) means "sort by only this column": unless
3431
+ * `columnId` is already the sole entry, in which case its own cycle just
3432
+ * continues, it collapses `sort` down to `columnId` alone at `"asc"`,
3433
+ * regardless of any direction it held as part of a larger stack.
3434
+ *
3435
+ * `stack: true` (a Shift-click) cycles or appends `columnId` in place without
3436
+ * disturbing the rest of the stack; cycling it back to `"none"` removes it
3437
+ * and closes the gap, leaving the others in their existing order.
3438
+ */
3439
+ declare function toggleColumnSort(sort: ColumnSortState, columnId: string, options: {
3440
+ readonly stack: boolean;
3441
+ }): ColumnSortState;
3442
+ /**
3443
+ * `rows` ordered by `sort` — each entry read against `columns` for its
3444
+ * `field` and `type` — with `rowIndex` and `datasetIndex` renumbered to
3445
+ * match the new positions, the invariant the rest of the grid relies on for
3446
+ * keyboard navigation and `aria-rowindex`.
3447
+ *
3448
+ * Stable (`Array.prototype.sort` has been stable since ES2019), so rows
3449
+ * equal under every active key keep their relative order. A `null`/
3450
+ * `undefined` value sorts last under either direction — resolved before
3451
+ * `compareValues` is asked, and left out of the direction flip below, so
3452
+ * that toggling a column reorders the values it holds rather than moving its
3453
+ * gaps to the front.
3454
+ *
3455
+ * Returns `rows` itself, untouched, when `sort` is empty or names only
3456
+ * columns absent from `columns` — a stored sort tolerates a column removed
3457
+ * from the definition the same way a stored `ColumnOrderState` does.
3458
+ */
3459
+ declare function sortRows<Row>(rows: readonly ResolvedRow<Row>[], sort: ColumnSortState, columns: readonly DataColumn<Row, unknown>[]): readonly ResolvedRow<Row>[];
3460
+
3461
+ /**
3462
+ * Whether `value`, stringified, matches `query`'s SQL LIKE-style pattern —
3463
+ * case-insensitive always. A bare query is an exact match; `%text%` is
3464
+ * contains; `text%` is starts-with; `%text` is ends-with. `null`/`undefined`
3465
+ * stringify to `""`.
3466
+ *
3467
+ * A one-shot convenience: parses `query` fresh on every call. `filterRows`
3468
+ * does not call this per cell — it compiles each `TextFilterEntry` once,
3469
+ * outside its row loop.
3470
+ */
3471
+ declare function matchesQuery(value: unknown, query: string): boolean;
3472
+ /**
3473
+ * This column's current text query, or the global entry's when `columnId`
3474
+ * is omitted; `null` if no `TextFilterEntry` names it — including when the
3475
+ * entry that exists for that key is a `ValueFilterEntry`/
3476
+ * `PredicateFilterEntry`/`OperatorFilterEntry`/`GroupFilterEntry` instead,
3477
+ * since none of those hold a query string to report.
3478
+ */
3479
+ declare function filterQueryFor<Row>(filter: FilterState<Row>, columnId?: FieldPath<Row> | (string & {})): string | null;
3480
+ /**
3481
+ * The filter with the `TextFilterEntry` for `columnId` (or the global
3482
+ * entry, when `columnId` is omitted) set to `query` — replacing whatever
3483
+ * entry already holds that key, of any variant, if present; appending a new
3484
+ * `TextFilterEntry` if not. An empty `query` removes the entry instead of
3485
+ * storing a filter that can never usefully match.
3486
+ *
3487
+ * Returns `filter` itself, unchanged, when the result would be a no-op: an
3488
+ * empty `query` naming a key with no existing entry, or a `query` equal to
3489
+ * an existing `TextFilterEntry`'s.
3490
+ */
3491
+ declare function setColumnFilter<Row>(filter: FilterState<Row>, columnId: (FieldPath<Row> | (string & {})) | undefined, query: string): FilterState<Row>;
3492
+ /** `filter` reduced to empty. Returns `filter` itself when already empty. */
3493
+ declare function clearAllFilters<Row>(filter: FilterState<Row>): FilterState<Row>;
3494
+ /**
3495
+ * `rows` reduced to those matching every entry in `filter` (AND at the top
3496
+ * level — nest a `GroupFilterEntry` for OR). `rowIndex` and `datasetIndex`
3497
+ * are renumbered to match the retained positions — the same invariant
3498
+ * `sortRows` keeps,
3499
+ * needed here independently since `filterRows` runs before `sortRows` in
3500
+ * the composed pipeline (see `resolveShownRows`).
3501
+ *
3502
+ * Order-preserving: surviving rows keep their relative order, which is what
3503
+ * makes running this before a sort produce the identical final order a
3504
+ * sort-then-filter would — only the cost differs.
3505
+ *
3506
+ * Every entry is compiled once, before the row loop.
3507
+ *
3508
+ * Returns `rows` itself, untouched, when `filter` is empty or names only
3509
+ * columns absent from `columns` — a stored filter tolerates a column
3510
+ * removed from the definition the same way a stored `ColumnSortState` does.
3511
+ */
3512
+ declare function filterRows<Row>(rows: readonly ResolvedRow<Row>[], filter: FilterState<Row>, columns: readonly DataColumn<Row, unknown>[]): readonly ResolvedRow<Row>[];
3513
+
3514
+ /**
3515
+ * This group's id, from its path. Every group-id producer/consumer in this
3516
+ * package goes through this — never join `path` by hand elsewhere.
3517
+ *
3518
+ * `JSON.stringify` rather than a delimiter join: a delimiter would have to be
3519
+ * escaped in every segment to stay collision-free against a value that
3520
+ * legitimately contains it, and `JSON.stringify` already draws that
3521
+ * boundary between array entries for free.
3522
+ */
3523
+ declare function groupRowId(path: readonly unknown[]): string;
3524
+ /**
3525
+ * `rows`, regrouped into `groupBy`'s stacked levels — a group header per
3526
+ * distinct value at each level, ordered by `compareValues` per that level's
3527
+ * own `direction`, followed depth-first by its nested groups and/or data
3528
+ * rows. A collapsed group (its `groupId` present in `expansion`) contributes
3529
+ * only its own header, nothing beneath it — but its `count` still reports
3530
+ * the group's full leaf-row count either way.
3531
+ *
3532
+ * Filter and sort are expected to have already run (see `resolveShownRows`):
3533
+ * this only reshapes their output, and never changes which rows appear or
3534
+ * their relative order within a group.
3535
+ *
3536
+ * `rowIndex` and `datasetIndex` are renumbered across the whole flattened
3537
+ * output, header rows included — the same invariant `sortRows`/`filterRows`
3538
+ * keep for a `ResolvedRow`, extended to `ResolvedGroupRow` since `GridBody`
3539
+ * addresses both kinds by the same flat position, and `aria-rowindex`
3540
+ * counts both.
3541
+ *
3542
+ * Returns `rows` itself, untouched, when `groupBy` is empty or names only
3543
+ * columns absent from `columns` — a stored grouping tolerates a column
3544
+ * removed from the definition the same way a stored `ColumnSortState` does.
3545
+ */
3546
+ declare function groupRows<Row>(rows: readonly ResolvedRow<Row>[], groupBy: GroupByState, expansion: GroupExpansionState, columns: readonly DataColumn<Row, unknown>[]): readonly DisplayRow<Row>[];
3547
+ /**
3548
+ * The expansion with `groupId` collapsed if it was expanded, or expanded if
3549
+ * it was collapsed.
3550
+ */
3551
+ declare function toggleGroupExpansion(expansion: GroupExpansionState, groupId: string): GroupExpansionState;
3552
+ /** `expansion` reduced to empty — every group expanded. Mirrors `clearAllFilters`. */
3553
+ declare function expandAllGroups(expansion: GroupExpansionState): GroupExpansionState;
3554
+ /**
3555
+ * Every group id present in `rows` — for collapsing every group currently
3556
+ * shown in one call. Operates on the already-grouped display, not the raw
3557
+ * grouping, so a group hidden beneath an already-collapsed ancestor (and so
3558
+ * absent from `rows`) keeps whatever expansion it already had rather than
3559
+ * being forced closed too; expanding that ancestor again reveals it exactly
3560
+ * as it was left.
3561
+ *
3562
+ * Group headers only: a summary row (`groupAggregateDisplay: "row"`) carries
3563
+ * its group's id too, and counting it would list that group twice.
3564
+ */
3565
+ declare function collapseAllGroups<Row>(rows: readonly DisplayRow<Row>[]): GroupExpansionState;
3566
+ /**
3567
+ * `groupBy` with `columnId` positioned in front of `beforeColumnId` — or at
3568
+ * the end when that is `null` — inserting a fresh entry if `columnId` isn't
3569
+ * already part of the stack, or lifting its existing entry out and back in
3570
+ * if it is. The one function both a header dropped on the group-by bar and
3571
+ * a chip dragged within it need: the former's `columnId` is usually new to
3572
+ * the stack, the latter's never is, and this doesn't need to be told which.
3573
+ *
3574
+ * An existing entry keeps its own object (and so its own `direction`)
3575
+ * rather than being rebuilt, so a level merely repositioned stays
3576
+ * reference-equal at its new index — the same reason `moveColumnBefore`
3577
+ * moves ids rather than rebuilding them.
3578
+ *
3579
+ * Returns `groupBy` itself, untouched, when the move changes nothing: a
3580
+ * drop on the entry's own id, or back into the gap it already occupies, or
3581
+ * naming a `beforeColumnId` absent from the stack. Inserting a column not
3582
+ * yet in the stack is never a no-op.
3583
+ */
3584
+ declare function moveGroupByBefore(groupBy: GroupByState, columnId: string, beforeColumnId: string | null): GroupByState;
3585
+ /**
3586
+ * Whether moving `columnId` in front of `beforeColumnId` would change
3587
+ * `groupBy` at all, so that a drop indicator promises exactly the move that
3588
+ * happens. Defined against `moveGroupByBefore` rather than restating its
3589
+ * conditions, the same relationship `movesColumn` keeps with
3590
+ * `moveColumnBefore`.
3591
+ */
3592
+ declare function movesGroupBy(groupBy: GroupByState, columnId: string, beforeColumnId: string | null): boolean;
3593
+
3594
+ /**
3595
+ * `rows`, filtered then sorted — the one function `DataGrid.tsx` (and any
3596
+ * future framework binding) calls instead of composing `filterRows`/
3597
+ * `sortRows` itself.
3598
+ *
3599
+ * Filter always runs first: an O(n) pass that shrinks what the O(n log n)
3600
+ * sort has to touch whenever a filter is active, free when it isn't. This
3601
+ * is a performance choice, not a correctness one — filtering is an
3602
+ * order-preserving predicate and sort is a stable total order over whatever
3603
+ * it's handed, so the final order is identical either way.
3604
+ */
3605
+ declare function resolveShownRows<Row>(rows: readonly ResolvedRow<Row>[], filter: FilterState<Row>, sort: ColumnSortState, columns: readonly DataColumn<Row, unknown>[]): readonly ResolvedRow<Row>[];
3606
+ /**
3607
+ * `ids` resolved back to the rows behind them, keyed by `rowsById`.
3608
+ *
3609
+ * An id with no row behind it is dropped rather than left `undefined`: a
3610
+ * selection outlives a change to the data, so that filtering a row out and
3611
+ * back leaves it selected, and only what still exists can be handed to a
3612
+ * callback.
3613
+ */
3614
+ declare function resolveRows<Row>(rowsById: ReadonlyMap<string, ResolvedRow<Row>>, ids: readonly string[]): readonly ResolvedRow<Row>[];
3615
+ /**
3616
+ * `ids` resolved back to the columns behind them, paired with the position
3617
+ * each holds in `columns` — a stale id is dropped, matching `resolveRows`.
3618
+ */
3619
+ declare function resolveColumns<Row, Node>(columns: readonly ResolvedColumn<Row, Node>[], ids: readonly string[]): readonly SelectedColumn<Row, Node>[];
3620
+ /**
3621
+ * `cell` resolved down to the row, column and value it addresses — `null`
3622
+ * when there is no cell, or when either half of it names a row or column
3623
+ * that no longer exists.
3624
+ */
3625
+ declare function resolveCell<Row, Node>(rowsById: ReadonlyMap<string, ResolvedRow<Row>>, columns: readonly ResolvedColumn<Row, Node>[], cell: SelectedCellRef | null): SelectedCell<Row, Node> | null;
3626
+
3627
+ interface PaginatedRows<Row> {
3628
+ readonly rows: readonly DisplayRow<Row>[];
3629
+ readonly pageCount: number;
3630
+ /**
3631
+ * `pagination.pageIndex` clamped into `[0, pageCount - 1]` (or `0` when
3632
+ * `pageCount` is `0`) — read this back rather than trusting the input
3633
+ * verbatim, the same way `sortRows`/`filterRows` tolerate a stale stored
3634
+ * state.
3635
+ */
3636
+ readonly pageIndex: number;
3637
+ }
3638
+ /**
3639
+ * `rows` sliced into pages of `pagination.pageSize` units — see `unitsOf`
3640
+ * for what a unit is. `pageIndex` is clamped into range, `pageSize <= 0` is
3641
+ * clamped to `1` (this codebase's general tolerance for stale/odd stored
3642
+ * state, matching `sortRows`/`filterRows`), and the returned page's
3643
+ * `rowIndex` is renumbered to be page-relative — 0-based from the top of the
3644
+ * page, header rows included, mirroring `groupRows`'s own renumbering
3645
+ * invariant. `datasetIndex` is left untouched: the stages ahead of this one
3646
+ * set it to each row's position in the whole displayed result, which stays
3647
+ * the same whichever page is showing.
3648
+ */
3649
+ declare function paginateRows<Row>(rows: readonly DisplayRow<Row>[], pagination: PaginationState): PaginatedRows<Row>;
3650
+
3651
+ type PaginationWindowEntry = number | "ellipsis";
3652
+ /**
3653
+ * Which page numbers a numbered pager should show for `currentPage` of
3654
+ * `pageCount` — the boundary + sibling windowing MUI's `usePagination` uses.
3655
+ * Always includes the first/last `boundaryCount` pages and a run of
3656
+ * `2 * siblingCount + 1` pages around `currentPage`, slid inwards rather than
3657
+ * cut short near either end, with one slot between each boundary and that
3658
+ * run holding either the single page it skips or an `"ellipsis"`.
3659
+ *
3660
+ * So once `pageCount` exceeds `2 * boundaryCount + 2 * siblingCount + 3`,
3661
+ * every window is exactly that many entries long, wherever `currentPage`
3662
+ * sits: a pager drawing one fixed-width slot per entry keeps its trailing
3663
+ * controls in place as the user pages through. Below that, every page shows.
3664
+ */
3665
+ declare function paginationWindow(currentPage: number, pageCount: number, options?: {
3666
+ boundaryCount?: number | undefined;
3667
+ siblingCount?: number | undefined;
3668
+ }): readonly PaginationWindowEntry[];
3669
+
3670
+ /**
3671
+ * `rows` reduced through every spec in `specs`, keyed by `spec.id ??
3672
+ * spec.columnId`. A custom `fn` (a plain function, not a `BuiltInAggregate`
3673
+ * name) is called once with the raw `rows` — no wrapping, no
3674
+ * pre-processing, so it sees exactly the same leaf set a built-in reducer
3675
+ * does.
3676
+ *
3677
+ * Two specs resolving to the same key: the later one wins, matching
3678
+ * `setColumnFilter`'s own silent-replace precedent for a key collision
3679
+ * rather than throwing.
3680
+ *
3681
+ * Returns a fresh empty `Map` for empty `rows` or empty `specs` — never a
3682
+ * shared singleton — matching this codebase's general avoidance of shared
3683
+ * mutable module state.
3684
+ */
3685
+ declare function computeAggregates<Row>(rows: readonly Row[], specs: AggregateState<Row>, columns: readonly DataColumn<Row, unknown>[]): AggregateResults;
3686
+ declare function withGroupAggregates<Row>(displayRows: readonly DisplayRow<Row>[], flatRows: readonly ResolvedRow<Row>[], groupBy: GroupByState, specs: AggregateState<Row>, columns: readonly DataColumn<Row, unknown>[], display?: GroupAggregateDisplay): readonly DisplayRow<Row>[];
3687
+
3688
+ /**
3689
+ * Whether `column` is shown: what the user last chose for it, if anything,
3690
+ * else what its definition says. The one place that precedence is decided,
3691
+ * so the view and an imperative "is it showing?" cannot disagree.
3692
+ */
3693
+ declare function isColumnVisible<Row>(column: ColumnDefinition<Row, unknown>, visibility: ColumnVisibilityState): boolean;
3694
+ /**
3695
+ * `columns` without the hidden ones, in the same order. `columns` itself when
3696
+ * every column is shown — the common case — so a stage memoised on this
3697
+ * output sees nothing change.
3698
+ */
3699
+ declare function applyColumnVisibility<Row, Node>(columns: readonly DataColumn<Row, Node>[], visibility: ColumnVisibilityState): readonly DataColumn<Row, Node>[];
3700
+ /**
3701
+ * `visibility` with each of `columnIds` shown (`visible: true`) or hidden.
3702
+ * Only a column whose visibility actually changes gets an entry, and ids
3703
+ * naming no column are ignored, so asking to show what is already showing
3704
+ * hands back `visibility` itself — the same reference, for a caller deciding
3705
+ * whether anything happened.
3706
+ */
3707
+ declare function setColumnVisibility<Row>(columns: readonly DataColumn<Row, unknown>[], visibility: ColumnVisibilityState, columnIds: readonly string[], visible: boolean): ColumnVisibilityState;
3708
+
3709
+ /**
3710
+ * What one column's filter looks like to an editor — which of its forms can
3711
+ * show it, or that none can.
3712
+ *
3713
+ * - `"none"`: no entry touches the column.
3714
+ * - `"values"`: a checklist — one `in` entry, optionally OR-grouped with an
3715
+ * `isEmpty` on the same column (`includeBlanks`).
3716
+ * - `"conditions"`: one or two operator entries on the column (any but
3717
+ * `in`), at the top level (ANDed) or alone in one group with its
3718
+ * combinator.
3719
+ * - `"custom"`: anything else that touches the column — a text query, a
3720
+ * predicate, a group spanning several columns. An editor shows it as
3721
+ * such, and applying an editor's draft replaces it.
3722
+ */
3723
+ type ColumnFilterShape<Row> = {
3724
+ readonly kind: "none";
3725
+ } | {
3726
+ readonly kind: "values";
3727
+ readonly values: readonly FilterScalar[];
3728
+ readonly includeBlanks: boolean;
3729
+ } | {
3730
+ readonly kind: "conditions";
3731
+ readonly conditions: readonly OperatorFilterEntry<Row>[];
3732
+ readonly combinator: "and" | "or";
3733
+ } | {
3734
+ readonly kind: "custom";
3735
+ };
3736
+ /** One distinct value a column holds, as a checklist offers it. */
3737
+ interface ColumnValueOption {
3738
+ readonly value: Exclude<FilterScalar, null>;
3739
+ /** The value as the column prints it — what a search matches against. */
3740
+ readonly label: string;
3741
+ /** How many rows hold it, among the rows the other columns' filters keep. */
3742
+ readonly count: number;
3743
+ }
3744
+ /** What `columnValueOptions` narrows its list by. */
3745
+ interface ColumnValueQuery {
3746
+ /** Keeps the values whose label contains this, ignoring case. */
3747
+ readonly search?: string;
3748
+ /** Keeps at most this many values, first in sorted order. */
3749
+ readonly limit?: number;
3750
+ /** The locale labels are formatted for — the grid's own `locale`. */
3751
+ readonly locale?: FormatLocale;
3752
+ /**
3753
+ * The grid's own `messages`, over the defaults: a boolean is labelled
3754
+ * `booleanTrue`/`booleanFalse`, as its cells print it.
3755
+ */
3756
+ readonly messages?: Partial<GridMessages>;
3757
+ }
3758
+ interface ColumnValueOptions {
3759
+ /** The distinct values, sorted as the column sorts, searched and cut to `limit`. */
3760
+ readonly options: readonly ColumnValueOption[];
3761
+ /** How many values matched the search, before `limit` cut them. */
3762
+ readonly total: number;
3763
+ /** Whether `limit` left values out. */
3764
+ readonly truncated: boolean;
3765
+ /** How many of the same rows hold a blank — `null`, `undefined` or `""`. */
3766
+ readonly blanks: number;
3767
+ /**
3768
+ * The column's `type`, which tells values apart the way an `in` filter
3769
+ * does — on a date column, a date string and the `Date` it names are one
3770
+ * value. `initialFilterEditorDraft` carries it into the draft.
3771
+ */
3772
+ readonly columnType?: ColumnType | undefined;
3773
+ }
3774
+ /**
3775
+ * A checklist or condition editor's working copy of one column's filter,
3776
+ * changed by `filterEditorReducer` and turned into a filter by
3777
+ * `draftToFilter` only when the user applies it — so cancelling is just
3778
+ * dropping the draft.
3779
+ */
3780
+ interface FilterEditorDraft<Row> {
3781
+ /** Which half of the draft `draftToFilter` applies: the last one changed. */
3782
+ readonly mode: "values" | "conditions";
3783
+ /** Every value the editor offers, from `columnValueOptions`. */
3784
+ readonly options: readonly ColumnValueOption[];
3785
+ /** How many rows hold a blank; the blanks entry only matters when some do. */
3786
+ readonly blanks: number;
3787
+ readonly search: string;
3788
+ /** The checked values, keyed as an `in` filter on the column keys them. */
3789
+ readonly checked: ReadonlyMap<string, FilterScalar>;
3790
+ readonly includeBlanks: boolean;
3791
+ readonly conditions: readonly OperatorFilterEntry<Row>[];
3792
+ readonly combinator: "and" | "or";
3793
+ /** The column's `type`, from `ColumnValueOptions` — what values are keyed by. */
3794
+ readonly columnType?: ColumnType | undefined;
3795
+ }
3796
+ type FilterEditorAction<Row> = {
3797
+ readonly type: "search";
3798
+ readonly search: string;
3799
+ } | {
3800
+ readonly type: "toggleValue";
3801
+ readonly value: FilterScalar;
3802
+ }
3803
+ /** Checks every value the search shows, or unchecks them once all are. */
3804
+ | {
3805
+ readonly type: "toggleAll";
3806
+ } | {
3807
+ readonly type: "setIncludeBlanks";
3808
+ readonly includeBlanks: boolean;
3809
+ } | {
3810
+ readonly type: "setConditions";
3811
+ readonly conditions: readonly OperatorFilterEntry<Row>[];
3812
+ /** Keeps the draft's own when omitted. */
3813
+ readonly combinator?: "and" | "or";
3814
+ }
3815
+ /** Back to "no filter": every value checked, no conditions, no search. */
3816
+ | {
3817
+ readonly type: "clear";
3818
+ };
3819
+ /** A select-all checkbox's state over the values the search shows. */
3820
+ type SelectAllState = "checked" | "unchecked" | "mixed";
3821
+ /**
3822
+ * How `filter` filters `columnId`, as one of the forms an editor can show —
3823
+ * see `ColumnFilterShape`. Entries about other columns don't count, nor do
3824
+ * entries across every column (a global search).
3825
+ */
3826
+ declare function describeColumnFilter<Row>(filter: FilterState<Row>, columnId: string): ColumnFilterShape<Row>;
3827
+ /**
3828
+ * Whether `filter` filters `columnId` — whether `describeColumnFilter` reads
3829
+ * it as anything but `"none"` — for a header to show its column as
3830
+ * filtered. A global search filters every column alike, so it marks none.
3831
+ */
3832
+ declare function isColumnFiltered<Row>(filter: FilterState<Row>, columnId: string): boolean;
3833
+ /**
3834
+ * The distinct values `columnId` holds, for a checklist editor: each with
3835
+ * its label and how many rows hold it.
3836
+ *
3837
+ * Counted over the rows every *other* column's filter keeps — every entry
3838
+ * except those `describeColumnFilter` would count for this column — so a
3839
+ * column's list cascades from the other filters without its own pick
3840
+ * hiding the values the user unchecked. Values are told apart as an `in`
3841
+ * filter tells them apart — as grouping does, except that a date column's
3842
+ * date strings are the dates they name — ordered as the column sorts, and
3843
+ * labelled as its cells print, a boolean in `query.messages`' words; blanks
3844
+ * are counted apart, in `blanks`.
3845
+ *
3846
+ * Costs one pass over `rows` (tens of milliseconds at 100k rows), so compute
3847
+ * it when an editor opens rather than on every render, and hand the whole
3848
+ * list to `initialFilterEditorDraft`, whose search needs no recount.
3849
+ */
3850
+ declare function columnValueOptions<Row>(rows: readonly Row[], dataColumns: readonly DataColumn<Row, unknown>[], filter: FilterState<Row>, columnId: string, query?: ColumnValueQuery): ColumnValueOptions;
3851
+ /**
3852
+ * A draft showing `shape` over `values` — what an editor opens with. A
3853
+ * column with no filter, or one only a custom editor could show, opens with
3854
+ * every value checked; a checklist with its own values checked, kept even
3855
+ * when the other filters now hide them; conditions as they are.
3856
+ */
3857
+ declare function initialFilterEditorDraft<Row>(shape: ColumnFilterShape<Row>, values: ColumnValueOptions): FilterEditorDraft<Row>;
3858
+ /** The options the draft's search shows — those a select-all acts on. */
3859
+ declare function visibleFilterOptions<Row>(draft: FilterEditorDraft<Row>): readonly ColumnValueOption[];
3860
+ /**
3861
+ * The select-all checkbox's state: whether every value the search shows is
3862
+ * checked, none is, or some are — blanks included while nothing is
3863
+ * searched.
3864
+ */
3865
+ declare function selectAllState<Row>(draft: FilterEditorDraft<Row>): SelectAllState;
3866
+ /**
3867
+ * The next draft after `action` — a plain reducer, so a renderer can hold
3868
+ * the draft in whatever state it has (`useReducer`, a signal, a store).
3869
+ * Changing a value or the blanks switches the draft to its checklist;
3870
+ * setting conditions switches it to them.
3871
+ */
3872
+ declare function filterEditorReducer<Row>(draft: FilterEditorDraft<Row>, action: FilterEditorAction<Row>): FilterEditorDraft<Row>;
3873
+ /**
3874
+ * `current` with `columnId`'s filter replaced by what `draft` holds — what
3875
+ * applying an editor sets. Every entry about the column goes (custom ones
3876
+ * included); the draft's entries take the place of the first, so the rest
3877
+ * keep their order.
3878
+ *
3879
+ * A checklist with everything checked is no filter at all, and a partial
3880
+ * pick is one `in` entry, OR-grouped with an `isEmpty` when blanks are
3881
+ * kept. One condition is stored as itself, two as a group with the
3882
+ * draft's combinator. Returns `current` itself when nothing changes.
3883
+ */
3884
+ declare function draftToFilter<Row>(draft: FilterEditorDraft<Row>, columnId: string, current: FilterState<Row>): FilterState<Row>;
3885
+
3886
+ /** What a column chooser is drawn from: every column, the visibility, and the search typed. */
3887
+ interface ColumnChooserInput<Row> {
3888
+ /** Every column in its current order, hidden ones included — a view's `dataColumns`. */
3889
+ readonly columns: readonly DataColumn<Row, unknown>[];
3890
+ readonly visibility: ColumnVisibilityState;
3891
+ /** Narrows the list to the columns whose header text contains it, ignoring case. */
3892
+ readonly search?: string | undefined;
3893
+ }
3894
+ /** One column's checkbox in a column chooser. */
3895
+ interface ColumnChooserEntry {
3896
+ readonly columnId: string;
3897
+ /** The column's header text — what the search matches, and the checkbox's label. */
3898
+ readonly label: string;
3899
+ /** Whether the column is shown — whether its checkbox is checked. */
3900
+ readonly visible: boolean;
3901
+ /**
3902
+ * Whether the checkbox cannot be unchecked: the column is shown and is
3903
+ * either not `hideable` or the last column shown. A hidden column can
3904
+ * always be shown, `hideable` or not.
3905
+ */
3906
+ readonly disabled: boolean;
3907
+ }
3908
+ /** What toggling a chooser's "Show all" checkbox does: shows these columns, or hides them. */
3909
+ interface ColumnChooserToggle {
3910
+ readonly visible: boolean;
3911
+ readonly columnIds: readonly string[];
3912
+ }
3913
+ interface ColumnChooserModel {
3914
+ /** The columns the search matches, in column order. */
3915
+ readonly entries: readonly ColumnChooserEntry[];
3916
+ /**
3917
+ * The "Show all" checkbox's state over the entries whose columns are
3918
+ * `hideable` — the ones it acts on. A column the user cannot hide is
3919
+ * always on, so counting it would leave "Show all" stuck at mixed.
3920
+ */
3921
+ readonly selectAll: SelectAllState;
3922
+ /** What toggling "Show all" does, or `null` when it can do nothing — a disabled checkbox. */
3923
+ readonly toggleAll: ColumnChooserToggle | null;
3924
+ }
3925
+ /**
3926
+ * A column chooser's list for a search, and what its "Show all" checkbox
3927
+ * says and does — the same tri-state over what the search shows that a
3928
+ * filter editor's select-all is (`selectAllState`).
3929
+ *
3930
+ * "Show all" shows every hidden column the search shows once any is hidden,
3931
+ * and hides those it shows once none is. It never touches a column that is
3932
+ * not `hideable`, and never hides the last column shown: when that is all
3933
+ * that would be left, the first of them in column order stays, since a grid
3934
+ * with no column shown has no header to bring one back from.
3935
+ */
3936
+ declare function resolveColumnChooser<Row>({ columns, visibility, search, }: ColumnChooserInput<Row>): ColumnChooserModel;
3937
+
3938
+ /**
3939
+ * `resolveGridView`, memoised per stage: each stage remembers its last
3940
+ * inputs and returns its last output when none of them changed identity, so
3941
+ * a call that changes one slice of state recomputes only what depends on
3942
+ * it. The data stages (filter → sort → group → aggregate → paginate) read
3943
+ * `dataColumns`, which carry no width, so a resize or a viewport change
3944
+ * leaves `rows`, `displayRows`, `pageRows`, `displayDataRows` and
3945
+ * `grandTotal` reference-equal to the previous call's — only `columns` is
3946
+ * new. The view object itself is reused when every field is unchanged, so a
3947
+ * snapshot-based renderer sees nothing to re-render.
3948
+ *
3949
+ * Hold one resolver per grid and call it with the current input every time
3950
+ * the view is needed; the memo only pays off across calls to the same one.
3951
+ */
3952
+ declare function createGridViewResolver<Row, Node = string>(): (input: GridViewInput<Row, Node>) => GridView<Row, Node>;
3953
+ /**
3954
+ * What the user is looking at, derived from the rows, the columns, the
3955
+ * grid's state and its options in one call: rows filtered → sorted →
3956
+ * grouped → aggregated → paginated, and columns ordered → hidden → sized.
3957
+ * The one function a renderer, an export or a toolbar calls instead of
3958
+ * composing the stages itself, so none of them can disagree about what is
3959
+ * shown.
3960
+ *
3961
+ * Unmemoised — a one-off resolver. A renderer that derives the view on every
3962
+ * change holds a `createGridViewResolver()` instead.
3963
+ */
3964
+ declare function resolveGridView<Row, Node = string>(input: GridViewInput<Row, Node>): GridView<Row, Node>;
3965
+
3966
+ /**
3967
+ * `state` in a form that survives `JSON.stringify` and back unchanged, for
3968
+ * saving a layout — to local storage, a URL, a user's profile — and handing
3969
+ * it to `restoreState` later. Every slice is plain data already except the
3970
+ * filter: a `Date` value or operand is written as its ISO string, and a
3971
+ * predicate entry, being a function, cannot be written at all and is left
3972
+ * out with a `console.error` naming its column.
3973
+ */
3974
+ declare function serializeGridState<Row>(state: GridState<Row>): SerializedGridState<Row>;
3975
+
3976
+ /**
3977
+ * One condition row of a simple filter editor as the user types it: text,
3978
+ * not yet a value, so a half-typed number or date stays in its input until
3979
+ * the editor is applied and `conditionsFromRows` reads it.
3980
+ */
3981
+ interface ConditionRowDraft {
3982
+ readonly operator: FilterOperator;
3983
+ /** The operand as typed — `between`'s lower end. */
3984
+ readonly text: string;
3985
+ /**
3986
+ * `between`'s upper end, as typed. Kept under any other operator, unread,
3987
+ * so switching back to `between` finds it still there.
3988
+ */
3989
+ readonly textTo: string;
3990
+ }
3991
+ /** What `conditionsFromRows` reads off an editor's rows. */
3992
+ interface ParsedConditionRows<Row> {
3993
+ /** A condition for each row that reads as one, in row order. */
3994
+ readonly conditions: readonly OperatorFilterEntry<Row>[];
3995
+ /**
3996
+ * The indexes of the rows that don't, for the editor to mark. Apply the
3997
+ * conditions only once this is empty.
3998
+ */
3999
+ readonly invalid: readonly number[];
4000
+ }
4001
+ /**
4002
+ * The rows a simple editor opens with over a column's filter `shape`, its
4003
+ * operands written as the column's `type` reads them: two, holding the
4004
+ * column's conditions when its filter is conditions, and each row they
4005
+ * don't fill starting at the first of `operators`, empty. With no operator
4006
+ * to start one at, only the rows the filter fills.
4007
+ */
4008
+ declare function conditionRowsFrom<Row>(shape: ColumnFilterShape<Row>, operators: readonly FilterOperator[], type: ColumnType | undefined): readonly ConditionRowDraft[];
4009
+ /**
4010
+ * The conditions a simple editor's rows stand for on `columnId`, each
4011
+ * operand read as the column's `type` filters (`parseFilterOperand`) — for
4012
+ * `filterEditorReducer`'s `setConditions`, with the combinator the editor
4013
+ * shows.
4014
+ *
4015
+ * A row needs every operand its operator takes, or it is `invalid`; the
4016
+ * blanks operators take none. A row after the first left empty is dropped
4017
+ * rather than invalid, since the second condition is optional; an empty
4018
+ * first row is invalid — clearing the filter is the editor's clear action,
4019
+ * not an apply with nothing typed.
4020
+ */
4021
+ declare function conditionsFromRows<Row>(rows: readonly ConditionRowDraft[], columnId: string, type: ColumnType | undefined): ParsedConditionRows<Row>;
4022
+
4023
+ /**
4024
+ * What a cached list is labelled by: `columnValueOptions`' query without
4025
+ * `search` and `limit`, which a draft applies over the whole list.
4026
+ */
4027
+ type ColumnValueCacheQuery = Pick<ColumnValueQuery, "locale" | "messages">;
4028
+ /** `columnValueOptions`, remembered per column. */
4029
+ interface ColumnValueOptionsCache<Row> {
4030
+ /**
4031
+ * `columnId`'s whole value list — `columnValueOptions` with no `search`
4032
+ * or `limit` — or the very list it returned last time, when nothing the
4033
+ * list is counted from or labelled by has changed since.
4034
+ */
4035
+ readonly get: (rows: readonly Row[], dataColumns: readonly DataColumn<Row, unknown>[], filter: FilterState<Row>, columnId: string, query?: ColumnValueCacheQuery) => ColumnValueOptions;
4036
+ }
4037
+ /**
4038
+ * A memo of each column's checklist values, for a renderer to hold one of
4039
+ * per grid: reopening a column's checklist hands back the list it was given
4040
+ * last time — the same object — rather than counting `rows` again, until
4041
+ * something the list depends on changes.
4042
+ *
4043
+ * That is the `rows` and `dataColumns`, the `locale` and `messages` it is
4044
+ * labelled in, and the filter's entries not about the column — all compared
4045
+ * by identity, the entries one by one. Identity holds across an apply:
4046
+ * `draftToFilter` keeps every entry it doesn't replace as it was, so
4047
+ * filtering one column leaves the lists of the others to recount and its
4048
+ * own cached, since a column's list never depends on its own entries.
4049
+ *
4050
+ * Each column keeps its latest list. New rows, columns, locale or messages
4051
+ * drop every list, so the cache never holds on to rows the grid has let go
4052
+ * of — pass the grid's own, which keep their identity between renders.
4053
+ */
4054
+ declare function createColumnValueOptionsCache<Row>(): ColumnValueOptionsCache<Row>;
4055
+
4056
+ /** One row of a checklist: a value the column holds, or its blank cells. */
4057
+ type FilterChecklistItem = {
4058
+ /**
4059
+ * Tells the item apart from every other in the list: a value's key is the
4060
+ * one `draft.checked` holds it under, and the blanks have their own.
4061
+ */
4062
+ readonly key: string;
4063
+ /** The value as its cells print it, or the blanks' label. */
4064
+ readonly label: string;
4065
+ /** How many rows hold it, among those the other columns' filters keep. */
4066
+ readonly count: number;
4067
+ readonly checked: boolean;
4068
+ } & ({
4069
+ /** Toggled with `filterEditorReducer`'s `toggleValue`. */
4070
+ readonly kind: "value";
4071
+ readonly value: Exclude<FilterScalar, null>;
4072
+ } | {
4073
+ /** Toggled with `filterEditorReducer`'s `setIncludeBlanks`. */
4074
+ readonly kind: "blanks";
4075
+ });
4076
+ interface FilterChecklistOptions {
4077
+ /** How many values the list shows at most: the column's resolved `valueLimit`. */
4078
+ readonly valueLimit: number;
4079
+ /** The blanks item's label: the grid's `filterBlanks` message. */
4080
+ readonly blanksLabel: string;
4081
+ }
4082
+ /** What a checklist editor draws below its search box and select-all. */
4083
+ interface FilterChecklist {
4084
+ /**
4085
+ * The rows to draw, in order: the values the search shows, cut to
4086
+ * `valueLimit`, then the blanks while nothing is searched and some cells
4087
+ * are blank. Empty while `needsSearch`.
4088
+ */
4089
+ readonly items: readonly FilterChecklistItem[];
4090
+ /**
4091
+ * Whether the list waits for a search: the column holds more values than
4092
+ * `valueLimit` and nothing is searched yet — `filterSearchFirst(total)`.
4093
+ */
4094
+ readonly needsSearch: boolean;
4095
+ /**
4096
+ * How many of the values the search matches `valueLimit` left out of
4097
+ * `items` — `filterMoreValues(hiddenCount)`. `0` while `needsSearch`, so
4098
+ * the two notes never show together.
4099
+ */
4100
+ readonly hiddenCount: number;
4101
+ /** How many values the search matches — every value while nothing is searched. Blanks aside. */
4102
+ readonly total: number;
4103
+ }
4104
+ /**
4105
+ * The list a checklist editor draws for `draft`: the window of values its
4106
+ * search shows, as items carrying what each row says and whether it is
4107
+ * checked.
4108
+ *
4109
+ * A column can hold far more values than a list is worth scrolling, so the
4110
+ * list shows at most `valueLimit` of them. Past that, it shows nothing until
4111
+ * something is searched (`needsSearch`) — every value is still in the draft,
4112
+ * and select-all still covers them all — and a search matching more shows
4113
+ * the first `valueLimit` of its matches in sort order, with the rest counted
4114
+ * in `hiddenCount`.
4115
+ *
4116
+ * The blanks item comes last, as in Excel's, and only while nothing is
4117
+ * searched: exactly when select-all counts the blanks, so the checkbox acts
4118
+ * on what the list shows.
4119
+ */
4120
+ declare function filterChecklist<Row>(draft: FilterEditorDraft<Row>, { valueLimit, blanksLabel }: FilterChecklistOptions): FilterChecklist;
4121
+
4122
+ /**
4123
+ * One entry per row: its measured height once known, `undefined` until then.
4124
+ * A row never yet rendered (or rendered but not yet observed) falls back to
4125
+ * `visibleRange`'s own `estimatedHeight` argument.
4126
+ */
4127
+ type RowHeights = readonly (number | undefined)[];
4128
+ interface VisibleRange {
4129
+ readonly startIndex: number;
4130
+ readonly endIndex: number;
4131
+ /** Total height of every row before `startIndex` — the leading spacer's height. */
4132
+ readonly offsetBefore: number;
4133
+ /** Total height of every row after `endIndex` — the trailing spacer's height. */
4134
+ readonly offsetAfter: number;
4135
+ }
4136
+ /**
4137
+ * Which rows of a dynamic-height, virtualized list fall within
4138
+ * `[scrollTop, scrollTop + viewportHeight)`, padded by `overscan` rows on
4139
+ * each side and clamped to the array's own bounds.
4140
+ *
4141
+ * Walks a cumulative-offset prefix sum built from `heights` (measured height
4142
+ * where known, `estimatedHeight` otherwise) rather than assuming a uniform
4143
+ * row height — this codebase's rows are not uniform (`.is-wrapped` cells,
4144
+ * group header/summary rows), so a fixed-height virtualizer would either
4145
+ * break wrapping or force it out of scope.
4146
+ *
4147
+ * `O(n)` in `heights.length`. Deliberately not a Fenwick tree or a
4148
+ * binary-searchable prefix-sum structure — that optimization belongs in the
4149
+ * mutable height cache that already owns mutability (`createRowVirtualizer`
4150
+ * in `@gridkitjs/dom`), not in this pure function's contract, and is not
4151
+ * worth taking on until a profiled scenario actually shows it matters at
4152
+ * realistic row counts.
4153
+ */
4154
+ declare function visibleRange(heights: RowHeights, estimatedHeight: number, scrollTop: number, viewportHeight: number, overscan: number): VisibleRange;
4155
+
4156
+ /** How `toTsv` writes its text. */
4157
+ interface TsvOptions {
4158
+ /**
4159
+ * Which reading of each cell is written: `"text"` (the default), as the
4160
+ * grid shows it; or `"raw"`, the typed value written plainly.
4161
+ */
4162
+ readonly values?: "text" | "raw" | undefined;
4163
+ }
4164
+ /**
4165
+ * The table as tab-separated text, records ending `"\n"` — the plain-text
4166
+ * form a spreadsheet splits into cells when it is pasted, which is what the
4167
+ * clipboard carries. TSV has no quoting a paste target agrees on, so a tab
4168
+ * or line break inside a cell becomes a space instead. Unlike `toCsv` it
4169
+ * writes no byte order mark and leaves formulas alone: what is copied is
4170
+ * exactly what the grid shows, and pasting it is the user's own act.
4171
+ */
4172
+ declare function toTsv(table: ExportTable, options?: TsvOptions): string;
4173
+
4174
+ /** How `toHtmlTable` writes its markup. */
4175
+ interface HtmlTableOptions {
4176
+ /** Text for a `<caption>` above the table; none by default. */
4177
+ readonly caption?: string | undefined;
4178
+ }
4179
+ /**
4180
+ * The table as an HTML `<table>` string: a `<thead>` of column names when
4181
+ * the table has a header, every row in `<tbody>`, and the grand total in
4182
+ * `<tfoot>`. Every piece of text is escaped. It carries the semantic class
4183
+ * names a stylesheet targets — `gridkit-export-table` on the table,
4184
+ * `export-group` with a `data-level` on group headers,
4185
+ * `export-group-summary` on summary rows — and nothing else of style but
4186
+ * each column's alignment, so it reads the same pasted into a document as
4187
+ * it does printed.
4188
+ */
4189
+ declare function toHtmlTable(table: ExportTable, options?: HtmlTableOptions): string;
4190
+
4191
+ /**
4192
+ * What `exportFile` exports from: an `ExportSource` whose messages are the
4193
+ * grid's whole set, since a writer may print any of them. A
4194
+ * `GridCommandContext` is one as it stands.
4195
+ */
4196
+ interface ExportFileSource<Row> extends ExportSource<Row> {
4197
+ readonly messages: GridMessages;
4198
+ }
4199
+ /**
4200
+ * The grid's view exported as a file of `format`: the table `options`
4201
+ * narrow, written by that format's writer among `writers` (see
4202
+ * `resolveExportWriters`) — or by `format` itself, when it is a writer —
4203
+ * and named. A writer that returns a promise gives a promise of the file.
4204
+ *
4205
+ * A format no writer is registered for is reported and gives `null`, so a
4206
+ * renderer saves nothing rather than failing.
4207
+ */
4208
+ declare function exportFile<Row>(source: ExportFileSource<Row>, format: string | ExportWriter, options: GridExportOptions, writers: ReadonlyMap<string, ExportWriter>): ExportFile | Promise<ExportFile> | null;
4209
+
4210
+ /**
4211
+ * Turns on the per-column filter popup in its Excel-style form — a search
4212
+ * box, a checklist of the column's values with their counts, and an operator
4213
+ * submenu — in one spread: `<DataGrid {...excelFilter} />`.
4214
+ *
4215
+ * A preset is a plain value of `GridOptions`, not a component or a hook, so
4216
+ * any renderer can take it the way it takes its other options (a Vue spread,
4217
+ * an Angular binding) and a later option overrides it: spreading it before
4218
+ * `filterMenu={{ ui: "simple" }}` brings the simple editor back. `filterMenu`
4219
+ * is replaced whole, not merged, so repeat `showCounts` if it should stay.
4220
+ */
4221
+ declare const excelFilter: {
4222
+ readonly filterableColumns: true;
4223
+ readonly filterMenu: {
4224
+ readonly ui: "excel";
4225
+ readonly showCounts: true;
4226
+ };
4227
+ };
4228
+
4229
+ export { type AggregateFn, type AggregateResults, type AggregateSpec, type AggregateState, type Borders, type BuiltInAggregate, type BuiltInCommandIcon, type BuiltInCommandId, type CellSelectEvent, type CellSelectionChangeEvent, type CellSelectionMode, type CellSelectionState, type CellTemplateContext, type ColumnAlignment, type ColumnChooserEntry, type ColumnChooserInput, type ColumnChooserModel, type ColumnChooserToggle, type ColumnConstraints, type ColumnDefinition, type ColumnFilterMenuOptions, type ColumnFilterShape, type ColumnOrderEvent, type ColumnOrderState, type ColumnResizeEvent, type ColumnResizeSession, type ColumnResolveOptions, type ColumnSelectEvent, type ColumnSelectionChangeEvent, type ColumnSizeDefaults, type ColumnSizingState, type ColumnSortEntry, type ColumnSortEvent, type ColumnSortState, type ColumnType, type ColumnValueCacheQuery, type ColumnValueOption, type ColumnValueOptions, type ColumnValueOptionsCache, type ColumnValueQuery, type ColumnVisibilityEvent, type ColumnVisibilityState, type ColumnWrapConfig, type ColumnsSelectEvent, type ConditionRowDraft, type ContextMenuOpenChangeEvent, type CopyContent, type CopyRequest, type CopySource, type CsvOptions, DEFAULT_COLUMN_SIZES, DEFAULT_FILTER_VALUE_LIMIT, type DataColumn, type DisplayRow, type DropSide, type ExportCell, type ExportColumn, type ExportDataRow, type ExportFile, type ExportFileSource, type ExportGroupRow, type ExportGroupSummaryRow, type ExportOptions, type ExportRow, type ExportScalar, type ExportSource, type ExportTable, type ExportTotalRow, type ExportWriteContext, type ExportWriter, type FieldPath, type FilterChangeEvent, type FilterChecklist, type FilterChecklistItem, type FilterChecklistOptions, type FilterEditorAction, type FilterEditorDraft, type FilterEntry, type FilterMenuUi, type FilterOperator, type FilterOperatorFamily, type FilterPredicate, type FilterScalar, type FilterState, type FooterTemplateContext, type FormatLocale, type GridCommand, type GridCommandActions, type GridCommandContext, type GridCommandContextInput, type GridCommandEvent, type GridCommandHost, type GridCommandSource, type GridCommandTarget, type GridContextMenuArea, type GridContextMenuEntries, type GridContextMenuOptions, type GridContextMenuRequest, type GridContextMenuTarget, type GridController, type GridControllerOptions, type GridExportOptions, type GridFilterMenuOptions, type GridFocus, type GridMessages, type GridOptions, type GridPanelKind, type GridState, type GridToolbarOptions, type GridToolbarTarget, type GridView, type GridViewInput, type GridViewOptions, type GridViewState, type GroupAggregateDisplay, type GroupByBarVisibility, type GroupByEntry, type GroupByEvent, type GroupByState, type GroupExpansionEvent, type GroupExpansionState, type GroupFilterEntry, HEADER_ROW, type HoverableConfig, type HtmlTableOptions, type JsonOptions, KEYBOARD_STEP, type KeyShortcutCapabilities, type MenuEntry, type MenuItemEntry, type MenuMove, type MenuResolveOptions, type MenuSubmenuEntry, type NavigationModifiers, type OperatorFilterEntry, type PaginatedRows, type PaginationChangeEvent, type PaginationState, type PaginationWindowEntry, type ParsedConditionRows, type PredicateFilterEntry, type PrintDocument, type PrintOptions, type PrintOrientation, type PrintPage, type PrintSource, type ResizeMode, type ResolvedColumn, type ResolvedColumnFilterMenu, type ResolvedGroupRow, type ResolvedGroupSummaryRow, type ResolvedMenuEntry, type ResolvedMenuItem, type ResolvedMenuSeparator, type ResolvedMenuSubmenu, type ResolvedRow, type ResolvedToolbarButton, type ResolvedToolbarCustom, type ResolvedToolbarItem, type ResolvedToolbarMenu, type ResolvedToolbarSearch, type ResolvedToolbarSpacer, type RowHeights, type RowPointerEvent, type RowProps, type RowSelectEvent, type RowSelectionChangeEvent, type RowsSelectEvent, type SelectAllState, type SelectIntent, type SelectableConfig, type SelectedCell, type SelectedCellRef, type SelectedColumn, type SelectionCallbacks, type SelectionDiff, type SelectionDiffEvent, type SelectionMode, type SelectionState, type SerializedFilterEntry, type SerializedFilterScalar, type SerializedFilterState, type SerializedGridState, type SerializedGroupFilterEntry, type SerializedOperatorFilterEntry, type SerializedValueFilterEntry, type SortDirection, type TextFilterEntry, type ToolbarCustomEntry, type ToolbarEntry, type ToolbarFitInput, type ToolbarResolveOptions, type ToolbarSplit, type TsvOptions, type ValueFilterEntry, type VisibleRange, accessDotted, alignmentForType, applyColumnOrder, applyColumnResize, applyColumnVisibility, applySelectionIntent, beginColumnResize, buildExportTable, buildKeyShortcuts, buildPrintDocument, builtInCommands, clampColumnWidth, clampFocus, clearAllFilters, clearSelection, collapseAllGroups, columnValueOptions, compareValues, computeAggregates, conditionRowsFrom, conditionsFromRows, contextMenuEntries, copyContent, createColumnValueOptionsCache, createCommandContext, createDefaultMessages, createGridController, createGridViewResolver, csvWriter, defaultContextMenu, defaultFilterOperators, defaultMessages, defaultToolbar, defineColumnsFromRows, describeColumnFilter, diffSelection, draftToFilter, excelFilter, expandAllGroups, exportFile, exportPrintDocument, filterChecklist, filterEditorReducer, filterOperandArity, filterOperatorFamily, filterQueryFor, filterRows, fitColumnsToWidth, fitToolbarItems, formatAggregateValue, formatCellValue, formatFilterOperand, formatGroupValue, getColumnId, groupRowId, groupRows, hasContextMenu, initialFilterEditorDraft, intentOf, isColumnFiltered, isColumnVisible, isPinnedToolbarItem, isSameCell, jsonWriter, matchesQuery, moveColumnBefore, moveGroupByBefore, movesColumn, movesGroupBy, nextFocusForKey, nextMenuIndex, paginateRows, paginationWindow, parseFilterOperand, resolveCell, resolveColumnChooser, resolveColumnConstraints, resolveColumnFilterMenu, resolveColumnHeaderText, resolveColumnLabel, resolveColumnWidths, resolveColumns, resolveCommands, resolveDataColumns, resolveDropBefore, resolveExportWriters, resolveGridView, resolveKeyboardDropTarget, resolveMenu, resolveMessages, resolveRowId, resolveRows, resolveShownRows, resolveToolbar, revertColumnSize, runCommand, searchTextOf, selectAll, selectAllState, selectCell, selectOnly, selectRange, serializeGridState, setColumnFilter, setColumnVisibility, setSearchText, sizeColumnToContent, sortDirectionFor, sortPriorityFor, sortRows, splitToolbarItems, toCsv, toHtmlTable, toJson, toTsv, toggleCellSelection, toggleColumnSort, toggleGroupExpansion, toggleSelection, toolbarEntries, totalColumnWidth, typeaheadIndex, visibleFilterOptions, visibleRange, withGroupAggregates };