@gridkitjs/core 0.11.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -187,6 +187,12 @@ interface ColumnDefinition<Row, Node = string> {
187
187
  * this for as long as it holds an entry for the column.
188
188
  */
189
189
  hidden?: boolean | undefined;
190
+ /**
191
+ * Whether the user may hide this column — from its header's menu, or the
192
+ * column chooser. Defaults to `true`. Like `sortable`, it gates the user's
193
+ * ways to do it and nothing else: `hideColumns` still hides the column.
194
+ */
195
+ hideable?: boolean | undefined;
190
196
  }
191
197
  /** Which parts of a column opt out of the grid's default single-line text. */
192
198
  interface ColumnWrapConfig {
@@ -892,12 +898,254 @@ interface GridView<Row, Node = string> {
892
898
  readonly grandTotal: AggregateResults;
893
899
  }
894
900
 
901
+ /**
902
+ * A row or column selection change by id — see
903
+ * `GridControllerOptions.onSelectionDiff`.
904
+ */
905
+ interface SelectionDiffEvent extends SelectionDiff {
906
+ /** Which selection changed. */
907
+ readonly target: "rows" | "columns";
908
+ /** The whole selection after the change. */
909
+ readonly selection: SelectionState;
910
+ }
911
+ /**
912
+ * What `createGridController` is given: the grid's options and selection
913
+ * callbacks, plus what a renderer supplies that is not a setting — the column
914
+ * definitions, whose templates name the renderer's own node type, the width
915
+ * the viewport measured, and a hook for its own selection feedback.
916
+ */
917
+ interface GridControllerOptions<Row, Node = string> extends GridOptions<Row>, SelectionCallbacks<Row, Node> {
918
+ /**
919
+ * The columns to show. Omitted or empty, one column is inferred per field
920
+ * of `dataSource` — see `defineColumnsFromRows`.
921
+ */
922
+ columns?: readonly ColumnDefinition<Row, Node>[] | undefined;
923
+ /**
924
+ * The width, in px, `resizeMode: "fit"` fills. `null` or absent before it
925
+ * has been measured, or where there is no viewport at all (an export in
926
+ * Node), and then columns keep their resolved widths.
927
+ */
928
+ viewportWidth?: number | null | undefined;
929
+ /**
930
+ * Called once per row or column selection change, after the selection
931
+ * callbacks, with the change by id — every id it added or removed,
932
+ * including those with no row on screen (on another page, in a collapsed
933
+ * group, filtered out), which the callbacks' resolved rows leave out. For a
934
+ * renderer's own feedback, such as a live region announcing how many rows
935
+ * are selected; an application reads the selection callbacks instead.
936
+ */
937
+ onSelectionDiff?: ((event: SelectionDiffEvent) => void) | undefined;
938
+ }
939
+ /**
940
+ * A grid without a renderer: its state, the view derived from it, and every
941
+ * action that changes it. A renderer creates one per grid, hands it the
942
+ * current options on each update, draws `getView()` and calls the actions
943
+ * from its event handlers, so no renderer decides anything the user can see.
944
+ *
945
+ * Each slice of `GridState` is controlled or not on its own, the way a form
946
+ * input is: given as an option (`columnSort`), the grid shows that value and
947
+ * an action only asks for a change through the slice's callback
948
+ * (`onColumnSortChange`); left out, the controller keeps the slice itself,
949
+ * starting from its default (`defaultColumnSort`).
950
+ *
951
+ * Every action follows the same steps: work out the next value; stop if it
952
+ * is the very object the slice already holds; keep it, unless the slice is
953
+ * controlled; report it through the slice's callback; then call every
954
+ * subscriber, synchronously. The setters (`setColumnSort` and the like) also
955
+ * stop for a value equal to the current one, so restoring what is already
956
+ * there reports nothing.
957
+ *
958
+ * Every member is a plain function bound to its grid, safe to hand around on
959
+ * its own — `onClick={controller.nextPage}`.
960
+ */
961
+ interface GridController<Row, Node = string> {
962
+ readonly getOptions: () => GridControllerOptions<Row, Node>;
963
+ /**
964
+ * Replaces the options, as a renderer does with its current props on every
965
+ * update; calling it again with equal options changes nothing. A controlled
966
+ * slice takes its new value from here.
967
+ *
968
+ * Does not call subscribers: a renderer calls this while it updates, and
969
+ * draws the result itself — a subscriber called mid-update would update
970
+ * mid-update too. A renderer that also tells other listeners about it does
971
+ * so once its update is done.
972
+ */
973
+ readonly setOptions: (options: GridControllerOptions<Row, Node>) => void;
974
+ /** Every slice as the grid now applies it. The same object until a slice changes. */
975
+ readonly getState: () => GridState<Row>;
976
+ /** What the user is looking at — see `resolveGridView`. The same object until something in it changes. */
977
+ readonly getView: () => GridView<Row, Node>;
978
+ /**
979
+ * Calls `listener` after each action that got as far as reporting a
980
+ * change. Returns the function that unsubscribes it.
981
+ */
982
+ readonly subscribe: (listener: () => void) => () => void;
983
+ /**
984
+ * Puts back state saved earlier — from `getState()`, or from
985
+ * `serializeGridState` and back through JSON. Every slice given is set as
986
+ * its own `set*` action would set it, so each that changes fires its
987
+ * callback and a controlled one only asks; slices left out keep their value.
988
+ * Subscribers are called once, after every slice is in place, and a
989
+ * restored pagination is kept even when the same call changed the sort,
990
+ * filter or grouping that would otherwise send it back to the first page.
991
+ */
992
+ readonly restoreState: (saved: Partial<GridState<Row>> | Partial<SerializedGridState<Row>>) => void;
993
+ /**
994
+ * Replaces the column widths. Reported through `onColumnResize` as the
995
+ * `"end"` of a resize of the first column whose width changed, at its new
996
+ * width — or, when its entry was removed, the width its definition gives
997
+ * it. Equal widths report nothing.
998
+ */
999
+ readonly setColumnSizing: (sizing: ColumnSizingState) => void;
1000
+ /**
1001
+ * Sets one column's width, as a resize gesture does: `"move"` while the
1002
+ * gesture lasts, `"end"` once it is over. Never skipped for an unchanged
1003
+ * width, so a drag held against a column's minimum still reports every
1004
+ * move.
1005
+ */
1006
+ readonly resizeColumn: (columnId: string, width: number, phase: "move" | "end") => void;
1007
+ /**
1008
+ * Ends a resize gesture by putting its column back as it was when the
1009
+ * gesture began — `startSizing` is the sizing state then, `startWidth` the
1010
+ * width the column was drawn at — keeping any other column's change made in
1011
+ * the meantime. Reported as the gesture's `"end"`, at `startWidth`.
1012
+ */
1013
+ readonly cancelColumnResize: (columnId: string, startSizing: ColumnSizingState, startWidth: number) => void;
1014
+ /**
1015
+ * Replaces the column order. Reported through `onColumnOrderChange` naming
1016
+ * the first column whose position changed; an equal order reports nothing.
1017
+ */
1018
+ readonly setColumnOrder: (order: ColumnOrderState) => void;
1019
+ /**
1020
+ * Moves a column in front of `beforeId`, or to the end when that is
1021
+ * `null`, among every column — hidden ones keep their place. A move that
1022
+ * changes nothing reports nothing.
1023
+ */
1024
+ readonly moveColumn: (columnId: string, beforeId: string | null) => void;
1025
+ /**
1026
+ * Replaces the column visibility state. Reported through
1027
+ * `onColumnVisibilityChange` with every column whose entry changed; an
1028
+ * equal state reports nothing.
1029
+ */
1030
+ readonly setColumnVisibility: (visibility: ColumnVisibilityState) => void;
1031
+ /** Shows the given columns, each in the place it held when hidden. One report for the whole call. */
1032
+ readonly showColumns: (columnIds: readonly string[]) => void;
1033
+ /** Hides the given columns. A hidden column still sorts, filters and groups. */
1034
+ readonly hideColumns: (columnIds: readonly string[]) => void;
1035
+ /**
1036
+ * Replaces the filter. Reported through `onFilterChange`; a filter equal to
1037
+ * the current one — the same entries in the same order, a `Date` value
1038
+ * compared by time and a predicate by identity — reports nothing.
1039
+ */
1040
+ readonly setFilter: (filter: FilterState<Row>) => void;
1041
+ /**
1042
+ * Replaces the selected row ids as given, whatever `selectable` allows —
1043
+ * the way a controlled or default value is applied. The same ids in the
1044
+ * same order report nothing.
1045
+ */
1046
+ readonly setRowSelection: (selection: SelectionState) => void;
1047
+ /**
1048
+ * Selects rows as a user could, within what `selectable.rows` allows:
1049
+ * `"replace"` (the default) selects exactly these — only the last of them
1050
+ * under `"single"` — and `"toggle"` flips each one. An id need not name a
1051
+ * row on screen. A call that leaves the selection as it was reports
1052
+ * nothing.
1053
+ */
1054
+ readonly selectRows: (rowIds: readonly string[], intent?: "replace" | "toggle") => void;
1055
+ /**
1056
+ * Applies one click or key press to a row: `"replace"`, `"toggle"` or
1057
+ * `"range"` from the last row selected by anything but a range, across
1058
+ * the data rows on the current page.
1059
+ */
1060
+ readonly selectRow: (rowId: string, intent: SelectIntent) => void;
1061
+ /** Selects every data row on the current page, when `selectable.rows` is `"multiple"`. */
1062
+ readonly selectAllRows: () => void;
1063
+ /** Lets go of every row, column and cell selection at once, as Escape does. */
1064
+ readonly clearSelection: () => void;
1065
+ /** Replaces the selected column ids as given — see `setRowSelection`. */
1066
+ readonly setColumnSelection: (selection: SelectionState) => void;
1067
+ /** `selectRow`, for a column among the columns as rendered. */
1068
+ readonly selectColumn: (columnId: string, intent: SelectIntent) => void;
1069
+ /** Replaces the selected cell as given, `null` for none. */
1070
+ readonly setCellSelection: (selection: CellSelectionState) => void;
1071
+ /**
1072
+ * Applies one click or key press to a cell: `"toggle"` lets go of it when
1073
+ * it is the one selected; anything else selects it. A cell holds one value,
1074
+ * so a range over cells reads as a plain click.
1075
+ */
1076
+ readonly selectCell: (cell: SelectedCellRef, intent: SelectIntent) => void;
1077
+ /**
1078
+ * Replaces the sort. Reported through `onColumnSortChange` naming the
1079
+ * first column whose place or direction changed; a sort equal to the
1080
+ * current one changes nothing and reports nothing.
1081
+ */
1082
+ readonly setColumnSort: (sort: ColumnSortState) => void;
1083
+ /**
1084
+ * Cycles a column's sort, as its header toggle does: ascending, descending,
1085
+ * off. `stack` adds it to the sort rather than replacing the sort with it.
1086
+ */
1087
+ readonly toggleColumnSort: (columnId: string, options?: {
1088
+ readonly stack?: boolean | undefined;
1089
+ }) => void;
1090
+ /**
1091
+ * Takes one column out of the sort, keeping the rest in their order, and
1092
+ * reports naming that column — which `setColumnSort` without it would not
1093
+ * when it was the first key, naming instead the key that moved up. A
1094
+ * column the sort leaves out already reports nothing.
1095
+ */
1096
+ readonly clearColumnSort: (columnId: string) => void;
1097
+ /**
1098
+ * Replaces the group-by stack. Reported through `onGroupByChange` naming
1099
+ * the first level that changed; an equal stack reports nothing.
1100
+ */
1101
+ readonly setGroupBy: (groupBy: GroupByState) => void;
1102
+ /** Adds a column to the end of the group-by stack, or removes it if it is already there. */
1103
+ readonly toggleGroupBy: (columnId: string) => void;
1104
+ /**
1105
+ * Puts a column into the group-by stack in front of `beforeColumnId`, or at
1106
+ * the end when that is `null` — adding it, or moving it if it is already
1107
+ * there.
1108
+ */
1109
+ readonly moveGroupBy: (columnId: string, beforeColumnId: string | null) => void;
1110
+ /**
1111
+ * Replaces the collapsed groups. Reported with `groupId: null`, as a change
1112
+ * to every group at once; the same ids in the same order report nothing.
1113
+ */
1114
+ readonly setGroupExpansion: (expansion: GroupExpansionState) => void;
1115
+ readonly toggleGroupExpansion: (groupId: string) => void;
1116
+ readonly expandAllGroups: () => void;
1117
+ /** Collapses every group currently shown — see `collapseAllGroups`. */
1118
+ readonly collapseAllGroups: () => void;
1119
+ /**
1120
+ * Replaces the page and page size as given; the view clamps a page past
1121
+ * the last one. An equal pagination reports nothing.
1122
+ */
1123
+ readonly setPagination: (pagination: PaginationState) => void;
1124
+ /**
1125
+ * Moves to the given page, clamped into range. A page that clamps to the
1126
+ * current one reports nothing.
1127
+ */
1128
+ readonly goToPage: (pageIndex: number) => void;
1129
+ /** Moves one page on; on the last page it does nothing and reports nothing. */
1130
+ readonly nextPage: () => void;
1131
+ /** Moves one page back; on the first page it does nothing and reports nothing. */
1132
+ readonly previousPage: () => void;
1133
+ /**
1134
+ * Changes the page size and goes back to the first page. The current size,
1135
+ * already on the first page, reports nothing.
1136
+ */
1137
+ readonly setPageSize: (pageSize: number) => void;
1138
+ }
1139
+
895
1140
  /**
896
1141
  * Every string a grid shows or announces of its own — the pager, the group-by
897
- * bar, the loading row, the text of a boolean or missing value, and the
898
- * live-region announcements — so a grid can speak a language other than
899
- * English. A message that names something takes a function, so a translation
900
- * can put the name where its own grammar wants it.
1142
+ * bar, the loading row, the text of a boolean or missing value, the labels of
1143
+ * its built-in commands, the names of its menus, toolbar and column chooser,
1144
+ * and the live-region
1145
+ * announcements — so a grid can
1146
+ * speak a language other than English. A message that names something takes
1147
+ * a function, so a translation can put the name where its own grammar wants
1148
+ * it.
901
1149
  *
902
1150
  * Text the data supplies (cells, headers, labels) is not here: it is already
903
1151
  * the app's to choose. Nor is formatting — dates and numbers follow
@@ -952,6 +1200,71 @@ interface GridMessages {
952
1200
  selectedCount: (count: number, target: "rows" | "columns") => string;
953
1201
  /** Announced when a cell is selected. `rowNumber` counts from one. */
954
1202
  cellSelected: (columnName: string, rowNumber: number) => string;
1203
+ /** Announced when one column is hidden. */
1204
+ columnHidden: (columnName: string) => string;
1205
+ /** Announced when one column is shown. */
1206
+ columnShown: (columnName: string) => string;
1207
+ /** Announced when one change hides more than one column. */
1208
+ columnsHidden: (count: number) => string;
1209
+ /** Announced when one change shows more than one column. */
1210
+ columnsShown: (count: number) => string;
1211
+ /**
1212
+ * Announced when one action autofits more than one column, as
1213
+ * `column.autoFitAll` does, in place of each column's `columnResized`.
1214
+ */
1215
+ columnsAutoFitted: (count: number) => string;
1216
+ /** A column header's context menu's accessible name. */
1217
+ headerMenuLabel: (columnName: string) => string;
1218
+ /** A data cell's context menu's accessible name — a menu for its row. */
1219
+ cellMenuLabel: string;
1220
+ /** A group header row's context menu's accessible name. */
1221
+ groupMenuLabel: string;
1222
+ /** The accessible name of the menu in the body's empty space. */
1223
+ bodyMenuLabel: string;
1224
+ /** The built-in `sort.ascending` command's label. */
1225
+ sortAscending: string;
1226
+ sortDescending: string;
1227
+ /** `sort.clear`: takes one column out of the sort. */
1228
+ clearSort: string;
1229
+ /** `sort.clearAll` */
1230
+ clearAllSorting: string;
1231
+ /** `group.add`, naming the column it groups by. */
1232
+ groupByColumn: (columnName: string) => string;
1233
+ /** `group.clearAll`. `group.remove` reads `removeGroupBy`, as the group-by chip's button does. */
1234
+ ungroupAll: string;
1235
+ expandAllGroups: string;
1236
+ collapseAllGroups: string;
1237
+ /** `column.hide` */
1238
+ hideColumn: string;
1239
+ /** `column.autoFit`: sizes the column to its content. */
1240
+ autoFitColumn: string;
1241
+ autoFitAllColumns: string;
1242
+ /** `selection.selectAllRows` */
1243
+ selectAllRows: string;
1244
+ /** `selection.clear` */
1245
+ clearSelection: string;
1246
+ /** `filter.clearAll`, which clears the search too. */
1247
+ clearFilters: string;
1248
+ /** `column.choose`, which opens the column chooser. */
1249
+ chooseColumns: string;
1250
+ /** The toolbar's accessible name, unless its `label` gives one. */
1251
+ toolbarLabel: string;
1252
+ /** The toolbar's search box's accessible name. */
1253
+ searchLabel: string;
1254
+ /** Shown in the toolbar's empty search box. */
1255
+ searchPlaceholder: string;
1256
+ /** The toolbar's "More" button, holding the items that do not fit. */
1257
+ moreToolbarItems: string;
1258
+ /** Announced when a search settles: how many rows it found. */
1259
+ searchResults: (count: number) => string;
1260
+ /** The column chooser's accessible name. */
1261
+ columnChooserLabel: string;
1262
+ /** The column chooser's search box's accessible name. */
1263
+ columnChooserSearchLabel: string;
1264
+ /** The column chooser's checkbox showing or hiding every column its search lists. */
1265
+ showAllColumns: string;
1266
+ /** Shown in the column chooser when its search matches no column. */
1267
+ noMatchingColumns: string;
955
1268
  }
956
1269
  /** The grid's own English, which `messages` replaces key by key. */
957
1270
  declare const defaultMessages: GridMessages;
@@ -962,33 +1275,415 @@ declare const defaultMessages: GridMessages;
962
1275
  */
963
1276
  declare function resolveMessages(messages: Partial<GridMessages> | undefined): GridMessages;
964
1277
 
965
- /** The locale(s) values are formatted for — `undefined` is the runtime's own. */
966
- type FormatLocale = string | readonly string[] | undefined;
967
1278
  /**
968
- * The text a value reads as in `column` — what a cell shows when the column
969
- * has no `cellTemplate`, and what an export or a print writes, so the two
970
- * cannot disagree.
971
- *
972
- * A `valueFormatter` decides outright. `null`/`undefined` read `""`, a
973
- * boolean `"true"`/`"false"` — or `messages.booleanTrue`/`booleanFalse`
974
- * when given, for a grid speaking another language — a string as it is, a
975
- * plain object or array as JSON.
976
- *
977
- * Dates and numbers are formatted through `Intl` only once asked to — the
978
- * column has a `format`, or a `locale` is given. Until then they print as a
979
- * grid always printed them, so adopting this changes nothing on screen: a
980
- * `Date` through `toLocaleString()`, a number as-is (`1234.5`, never
981
- * `1,234.5`). Once asked:
982
- *
983
- * - A `Date` → `Intl.DateTimeFormat`: the date alone under `"date"`, the time
984
- * alone under `"time"`, both otherwise.
985
- * - A number under a numeric `type` → `Intl.NumberFormat`: `"currency"` with
986
- * a currency symbol once `format.currency` names one (two fraction digits
987
- * until then), `"percent"` reading `0.25` as 25 %. Under any other type it
988
- * is still printed as-is, the way a number id should be.
989
- *
990
- * `format` and `locale` go to the `Intl` constructor unchanged, so any
991
- * option it accepts is honoured.
1279
+ * Where a command was asked for: the part of the grid a menu was opened on,
1280
+ * the toolbar item pressed, or nowhere in particular for a call through a
1281
+ * renderer's API. A built-in reads the column, row or group it acts on from
1282
+ * here, and is hidden on a target that has none.
1283
+ */
1284
+ type GridCommandTarget = {
1285
+ readonly area: "header";
1286
+ readonly columnId: string;
1287
+ } | {
1288
+ readonly area: "cell";
1289
+ readonly rowId: string;
1290
+ readonly columnId: string;
1291
+ } | {
1292
+ readonly area: "group";
1293
+ readonly groupId: string;
1294
+ readonly columnId: string;
1295
+ }
1296
+ /** Empty body space, or a grid with no rows. */
1297
+ | {
1298
+ readonly area: "body";
1299
+ } | {
1300
+ readonly area: "toolbar";
1301
+ readonly itemId: string;
1302
+ }
1303
+ /** A renderer's API, with no particular place. */
1304
+ | {
1305
+ readonly area: "grid";
1306
+ };
1307
+ /** Where a command was run from: a context menu, the toolbar, or a renderer's API. */
1308
+ type GridCommandSource = "contextMenu" | "toolbar" | "api";
1309
+ /** What `onCommand` is told of a command, or an inline menu item, that ran. */
1310
+ interface GridCommandEvent {
1311
+ /** The command's id, or the inline item's. */
1312
+ readonly commandId: string;
1313
+ /** Where it was asked for. */
1314
+ readonly target: GridCommandTarget;
1315
+ readonly source: GridCommandSource;
1316
+ }
1317
+ /**
1318
+ * The panels a command can ask a renderer to open. A union so the filter UI
1319
+ * can add its own kind through the same door.
1320
+ */
1321
+ type GridPanelKind = "columnChooser";
1322
+ /**
1323
+ * What a command needs that only a renderer has: a DOM to measure, panels to
1324
+ * open, a live region to speak through. A caller with none of these — a test,
1325
+ * a script in Node — passes members that do nothing.
1326
+ */
1327
+ interface GridCommandHost {
1328
+ /** Sizes each column to fit its content, as double-clicking its resize handle does. */
1329
+ readonly autoFitColumns: (columnIds: readonly string[]) => void;
1330
+ /** Opens one of the grid's panels, anchored to where the command was asked for. */
1331
+ readonly openPanel: (kind: GridPanelKind, target: GridCommandTarget) => void;
1332
+ /** Reads `text` out through the grid's live region. */
1333
+ readonly announce: (text: string) => void;
1334
+ }
1335
+ /**
1336
+ * Every action of the controller — the only way a command changes state, so
1337
+ * each change reports through its slice's callback exactly as the user's own
1338
+ * gesture would. Leaves out `setOptions`, which is the renderer's alone,
1339
+ * `subscribe`, and the getters whose results the context already carries.
1340
+ *
1341
+ * Nothing left names the renderer's node type, so a controller of any `Node`
1342
+ * is one.
1343
+ */
1344
+ type GridCommandActions<Row> = Omit<GridController<Row, unknown>, "getOptions" | "setOptions" | "subscribe" | "getState" | "getView">;
1345
+ /**
1346
+ * Everything a command reads to decide whether it shows, whether it is
1347
+ * enabled and what it does — one snapshot of the grid, taken when a menu or
1348
+ * toolbar is resolved. Build one with `createCommandContext`.
1349
+ */
1350
+ interface GridCommandContext<Row> {
1351
+ readonly target: GridCommandTarget;
1352
+ readonly state: GridState<Row>;
1353
+ readonly view: GridView<Row, unknown>;
1354
+ readonly options: GridOptions<Row>;
1355
+ readonly messages: GridMessages;
1356
+ readonly actions: GridCommandActions<Row>;
1357
+ readonly host: GridCommandHost;
1358
+ /** The row a cell target is on; `null` for any other target, or a row the filter hides. */
1359
+ readonly row: ResolvedRow<Row> | null;
1360
+ /** The column a header, cell or group target names, hidden or not; `null` otherwise. */
1361
+ readonly column: DataColumn<Row, unknown> | null;
1362
+ /**
1363
+ * The selected rows that pass the filter, in the order they are shown,
1364
+ * across every page and collapsed group. A function, computed on first
1365
+ * call and remembered: resolving it walks every filtered row, and a toolbar
1366
+ * builds a context on every change without most commands ever asking.
1367
+ */
1368
+ readonly selectedRows: () => readonly ResolvedRow<Row>[];
1369
+ }
1370
+ /**
1371
+ * The one implementation behind a menu item, a toolbar button and a
1372
+ * renderer's `runCommand`. Whether it shows and whether it is enabled are
1373
+ * predicates over the context, asked each time a menu or toolbar is resolved,
1374
+ * so a command follows the grid's state without being told about it.
1375
+ */
1376
+ interface GridCommand<Row> {
1377
+ /** `"sort.ascending"` for a built-in, or any id of the app's own. Never `"separator"`, which a menu reads as one. */
1378
+ readonly id: string;
1379
+ readonly label: string | ((context: GridCommandContext<Row>) => string);
1380
+ /** A key the renderer maps to an icon of its own; a key it does not know draws nothing. */
1381
+ readonly icon?: string | undefined;
1382
+ /** A key-combination hint in `aria-keyshortcuts` syntax, such as `"Alt+ArrowUp"`. Shown, not bound. */
1383
+ readonly shortcut?: string | undefined;
1384
+ /** Whether the command shows here at all. Defaults to always. */
1385
+ readonly isVisible?: ((context: GridCommandContext<Row>) => boolean) | undefined;
1386
+ /** Whether it can run. A disabled command still shows, so a user can see what is not possible. Defaults to always. */
1387
+ readonly isEnabled?: ((context: GridCommandContext<Row>) => boolean) | undefined;
1388
+ /** Present for a checkable command — drawn as a checkbox item or a toggle button — and says whether it is checked. */
1389
+ readonly isChecked?: ((context: GridCommandContext<Row>) => boolean) | undefined;
1390
+ readonly execute: (context: GridCommandContext<Row>) => void;
1391
+ }
1392
+
1393
+ /** The id of every command `builtInCommands` returns. */
1394
+ 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" | "selection.selectAllRows" | "selection.clear" | "filter.clearAll";
1395
+ /**
1396
+ * The icon keys the built-ins carry, which a renderer draws as icons of its
1397
+ * own. An app command may use them too, to look like the built-ins.
1398
+ */
1399
+ type BuiltInCommandIcon = "sortAscending" | "sortDescending" | "group" | "hide" | "autoFit";
1400
+ /**
1401
+ * The grid's own commands, one per action its menus and toolbar offer —
1402
+ * sorting, grouping, hiding, fitting and choosing columns, selecting and
1403
+ * clearing.
1404
+ * Labels come from `messages`, so they follow the grid's language.
1405
+ *
1406
+ * A function rather than a constant so each comes typed for the caller's
1407
+ * `Row`; the commands hold no state, and two calls build equal ones.
1408
+ */
1409
+ declare function builtInCommands<Row>(): readonly GridCommand<Row>[];
1410
+
1411
+ /** A value given outright, or worked out from the context each time the menu is resolved. */
1412
+ type FromContext<Row, Value> = Value | ((context: GridCommandContext<Row>) => Value);
1413
+ /**
1414
+ * An item written into the menu itself rather than registered as a command —
1415
+ * for an action only one menu offers.
1416
+ */
1417
+ interface MenuItemEntry<Row> {
1418
+ readonly type: "item";
1419
+ readonly id: string;
1420
+ readonly label: FromContext<Row, string>;
1421
+ readonly icon?: string | undefined;
1422
+ readonly shortcut?: string | undefined;
1423
+ readonly hidden?: FromContext<Row, boolean> | undefined;
1424
+ readonly disabled?: FromContext<Row, boolean> | undefined;
1425
+ /** Present for a checkable item, and says whether it is checked. */
1426
+ readonly checked?: FromContext<Row, boolean> | undefined;
1427
+ readonly onSelect: (context: GridCommandContext<Row>) => void;
1428
+ }
1429
+ /** An item that opens a menu of its own. Left out when nothing in it shows. */
1430
+ interface MenuSubmenuEntry<Row> {
1431
+ readonly type: "submenu";
1432
+ readonly id: string;
1433
+ readonly label: FromContext<Row, string>;
1434
+ readonly icon?: string | undefined;
1435
+ readonly items: readonly MenuEntry<Row>[];
1436
+ }
1437
+ /**
1438
+ * One entry of a menu as an app writes it: a command id — a built-in's or
1439
+ * one of its own — `"separator"`, an inline item or a submenu. The same
1440
+ * vocabulary every menu and toolbar is listed in.
1441
+ */
1442
+ type MenuEntry<Row> = BuiltInCommandId | "separator" | (string & {}) | MenuItemEntry<Row> | MenuSubmenuEntry<Row>;
1443
+ /**
1444
+ * A menu item ready to draw: every label a string, every flag a boolean, and
1445
+ * `run` bound to the context the menu was resolved in.
1446
+ */
1447
+ interface ResolvedMenuItem {
1448
+ readonly type: "item";
1449
+ /** The command's id, or the inline item's. */
1450
+ readonly id: string;
1451
+ readonly label: string;
1452
+ readonly icon?: string | undefined;
1453
+ readonly shortcut?: string | undefined;
1454
+ /** Drawn, and focusable, but `run` does nothing. */
1455
+ readonly disabled: boolean;
1456
+ /** `undefined` for an item that is not checkable. */
1457
+ readonly checked: boolean | undefined;
1458
+ /**
1459
+ * Runs the item — a command only when it is still visible and enabled —
1460
+ * and says whether it ran, so a renderer reports only what did something.
1461
+ */
1462
+ readonly run: () => boolean;
1463
+ }
1464
+ interface ResolvedMenuSubmenu {
1465
+ readonly type: "submenu";
1466
+ readonly id: string;
1467
+ readonly label: string;
1468
+ readonly icon?: string | undefined;
1469
+ /** Never empty: a submenu with nothing to show is left out. */
1470
+ readonly items: readonly ResolvedMenuEntry[];
1471
+ }
1472
+ interface ResolvedMenuSeparator {
1473
+ readonly type: "separator";
1474
+ /**
1475
+ * The separator's place among the entries it was resolved from, which
1476
+ * stays put however the items around it come and go — a key for a
1477
+ * renderer that needs one, unique among its menu's separators.
1478
+ */
1479
+ readonly key: string;
1480
+ }
1481
+ /** One entry of a menu as `resolveMenu` hands it to a renderer to draw. */
1482
+ type ResolvedMenuEntry = ResolvedMenuItem | ResolvedMenuSubmenu | ResolvedMenuSeparator;
1483
+
1484
+ /** The parts of a grid that open a context menu of their own. */
1485
+ type GridContextMenuArea = "header" | "cell" | "group" | "body";
1486
+ /**
1487
+ * Where a context menu opens: a command target in one of the context menu
1488
+ * areas — a column header, a data cell, a group header row, or empty space
1489
+ * in the body — or in `Area` alone.
1490
+ */
1491
+ type GridContextMenuTarget<Area extends GridContextMenuArea = GridContextMenuArea> = Extract<GridCommandTarget, {
1492
+ readonly area: Area;
1493
+ }>;
1494
+ /** What `onContextMenuOpenChange` is told as a context menu opens or closes. */
1495
+ interface ContextMenuOpenChangeEvent {
1496
+ readonly open: boolean;
1497
+ /** Where the menu opened, or where the one closing had. */
1498
+ readonly target: GridContextMenuTarget;
1499
+ }
1500
+ /** What a function given for an area is asked, each time its menu opens. */
1501
+ interface GridContextMenuRequest<Row, Area extends GridContextMenuArea = GridContextMenuArea> {
1502
+ /** Where the menu opens. */
1503
+ readonly target: GridContextMenuTarget<Area>;
1504
+ /** The area's default entries, to keep, trim, reorder or add to. */
1505
+ readonly defaults: readonly MenuEntry<Row>[];
1506
+ /** The grid as the menu sees it — the context its items run in. */
1507
+ readonly context: GridCommandContext<Row>;
1508
+ }
1509
+ /**
1510
+ * An area's menu: its entries, or a function that works them out each time
1511
+ * the menu opens — from where it opens, the area's defaults and the grid's
1512
+ * state. A function giving `null` or `[]` shows no grid menu there, so the
1513
+ * browser's own menu shows.
1514
+ */
1515
+ type GridContextMenuEntries<Row, Area extends GridContextMenuArea = GridContextMenuArea> = readonly MenuEntry<Row>[] | ((request: GridContextMenuRequest<Row, Area>) => readonly MenuEntry<Row>[] | null);
1516
+ /**
1517
+ * A grid's context menus, by area, in the vocabulary every grid menu is
1518
+ * written in. An area left out shows its defaults; one given `[]` shows no
1519
+ * grid menu, so the browser's own menu shows there.
1520
+ */
1521
+ interface GridContextMenuOptions<Row> {
1522
+ /** A column header's menu. */
1523
+ readonly header?: GridContextMenuEntries<Row, "header"> | undefined;
1524
+ /** A data cell's menu, acting on its row and cell. */
1525
+ readonly cell?: GridContextMenuEntries<Row, "cell"> | undefined;
1526
+ /** A group header row's menu. */
1527
+ readonly group?: GridContextMenuEntries<Row, "group"> | undefined;
1528
+ /** The menu of the body's empty space, below the last row or in a grid with none. */
1529
+ readonly body?: GridContextMenuEntries<Row, "body"> | undefined;
1530
+ }
1531
+ /**
1532
+ * The menu each area shows unless the grid says otherwise — built-in
1533
+ * commands only, each hidden where it has nothing to act on, so the menu a
1534
+ * column header shows holds only what that column can do. The body has
1535
+ * none: empty space keeps the browser's menu until a grid gives it one.
1536
+ */
1537
+ declare const defaultContextMenu: {
1538
+ readonly [Area in GridContextMenuArea]: readonly (BuiltInCommandId | "separator")[];
1539
+ };
1540
+ /**
1541
+ * Whether the `contextMenu` option opens a grid menu on `area` at all: it is
1542
+ * on, and gives the area entries or a function rather than `[]`. A function
1543
+ * may still give no menu for one place or another; this answers for the
1544
+ * area, as a cell's `aria-keyshortcuts` needs to before anything is asked.
1545
+ */
1546
+ declare function hasContextMenu<Row>(contextMenu: boolean | GridContextMenuOptions<Row> | undefined, area: GridContextMenuArea): boolean;
1547
+ /**
1548
+ * The entries a grid's `contextMenu` option gives the place `context.target`
1549
+ * names, to resolve with `resolveMenu` in that same context: none while the
1550
+ * option is off — left out or `false` — or for a target no context menu
1551
+ * opens on; the area's defaults under `true` or when the option leaves the
1552
+ * area out; the entries it lists; or what its function gives this request.
1553
+ * No entries means no grid menu there.
1554
+ */
1555
+ declare function contextMenuEntries<Row>(contextMenu: boolean | GridContextMenuOptions<Row> | undefined, context: GridCommandContext<Row>): readonly MenuEntry<Row>[];
1556
+
1557
+ /** Where a toolbar item's command runs: the toolbar item it was asked from. */
1558
+ type GridToolbarTarget = Extract<GridCommandTarget, {
1559
+ readonly area: "toolbar";
1560
+ }>;
1561
+ /**
1562
+ * A place in the toolbar the renderer fills with content of the app's own —
1563
+ * React's `renderToolbarItem(id)` — for anything the entries cannot say.
1564
+ */
1565
+ interface ToolbarCustomEntry {
1566
+ readonly type: "custom";
1567
+ readonly id: string;
1568
+ }
1569
+ /**
1570
+ * One entry of a toolbar as an app writes it: anything a menu lists — a
1571
+ * command id, `"separator"`, an inline item, or a submenu, which the toolbar
1572
+ * draws as a dropdown button — plus the entries only a toolbar has:
1573
+ * `"search"`, the box searching every column; `"spacer"`, which takes up the
1574
+ * free space and so pushes what follows it to the far end; and a custom
1575
+ * entry.
1576
+ */
1577
+ type ToolbarEntry<Row> = MenuEntry<Row> | "search" | "spacer" | ToolbarCustomEntry;
1578
+ /**
1579
+ * A toolbar button ready to draw — a command, or an inline item — with
1580
+ * every label a string, every flag a boolean, and `run` bound to the
1581
+ * context of its place in the toolbar.
1582
+ */
1583
+ interface ResolvedToolbarButton {
1584
+ readonly type: "button";
1585
+ /** The command's id, or the inline item's. */
1586
+ readonly id: string;
1587
+ /** The same as `id`. */
1588
+ readonly key: string;
1589
+ readonly label: string;
1590
+ readonly icon?: string | undefined;
1591
+ readonly shortcut?: string | undefined;
1592
+ /** Drawn, and focusable, but `run` does nothing. */
1593
+ readonly disabled: boolean;
1594
+ /**
1595
+ * Whether a toggle button is pressed — `undefined` for a button that is
1596
+ * not one: a checkable command or item draws as a toggle.
1597
+ */
1598
+ readonly pressed: boolean | undefined;
1599
+ /** Runs the button, and says whether it ran — see `ResolvedMenuItem.run`. */
1600
+ readonly run: () => boolean;
1601
+ }
1602
+ /** A dropdown button, opening the menu its submenu entry lists. */
1603
+ interface ResolvedToolbarMenu {
1604
+ readonly type: "menu";
1605
+ readonly id: string;
1606
+ /** The same as `id`. */
1607
+ readonly key: string;
1608
+ readonly label: string;
1609
+ readonly icon?: string | undefined;
1610
+ /** Never empty: a dropdown with nothing to show is left out. */
1611
+ readonly items: readonly ResolvedMenuEntry[];
1612
+ }
1613
+ /** The search box, over the grid's global text filter. */
1614
+ interface ResolvedToolbarSearch {
1615
+ readonly type: "search";
1616
+ /** Always `"search"`. */
1617
+ readonly key: string;
1618
+ }
1619
+ /** The free space between the entries either side of it. */
1620
+ interface ResolvedToolbarSpacer {
1621
+ readonly type: "spacer";
1622
+ /** `spacer-<index>`, from its place among the entries it was resolved from. */
1623
+ readonly key: string;
1624
+ }
1625
+ /** A custom entry's place, for the renderer to fill. */
1626
+ interface ResolvedToolbarCustom {
1627
+ readonly type: "custom";
1628
+ readonly id: string;
1629
+ /** The same as `id`. */
1630
+ readonly key: string;
1631
+ }
1632
+ /**
1633
+ * One entry of a toolbar as `resolveToolbar` hands it to a renderer to draw.
1634
+ * Each has a `key` — an item's id, `"search"`, or a separator's or spacer's
1635
+ * place among the entries — unique among the toolbar's entries, which the
1636
+ * renderer writes into the entry's `data-gridkit-toolbar-item`.
1637
+ */
1638
+ type ResolvedToolbarItem = ResolvedToolbarButton | ResolvedToolbarMenu | ResolvedToolbarSearch | ResolvedToolbarSpacer | ResolvedMenuSeparator | ResolvedToolbarCustom;
1639
+
1640
+ /** A grid's toolbar: what it lists, and what a screen reader calls it. */
1641
+ interface GridToolbarOptions<Row> {
1642
+ /** The toolbar's entries, in order. Left out, the defaults. */
1643
+ readonly items?: readonly ToolbarEntry<Row>[] | undefined;
1644
+ /** The toolbar's accessible name. Left out, `messages.toolbarLabel`. */
1645
+ readonly label?: string | undefined;
1646
+ }
1647
+ /**
1648
+ * What a toolbar lists unless the grid says otherwise: the search box, then
1649
+ * the free space, then "Clear filters" and "Choose columns" at the far end.
1650
+ */
1651
+ declare const defaultToolbar: readonly (BuiltInCommandId | "search" | "spacer")[];
1652
+ /**
1653
+ * The entries a grid's `toolbar` option lists, to resolve with
1654
+ * `resolveToolbar`: none while it is off — left out or `false` — the
1655
+ * defaults under `true` or an object without `items`, else its `items`.
1656
+ * No entries means no toolbar.
1657
+ */
1658
+ declare function toolbarEntries<Row>(toolbar: boolean | GridToolbarOptions<Row> | undefined): readonly ToolbarEntry<Row>[];
1659
+
1660
+ /** The locale(s) values are formatted for — `undefined` is the runtime's own. */
1661
+ type FormatLocale = string | readonly string[] | undefined;
1662
+ /**
1663
+ * The text a value reads as in `column` — what a cell shows when the column
1664
+ * has no `cellTemplate`, and what an export or a print writes, so the two
1665
+ * cannot disagree.
1666
+ *
1667
+ * A `valueFormatter` decides outright. `null`/`undefined` read `""`, a
1668
+ * boolean `"true"`/`"false"` — or `messages.booleanTrue`/`booleanFalse`
1669
+ * when given, for a grid speaking another language — a string as it is, a
1670
+ * plain object or array as JSON.
1671
+ *
1672
+ * Dates and numbers are formatted through `Intl` only once asked to — the
1673
+ * column has a `format`, or a `locale` is given. Until then they print as a
1674
+ * grid always printed them, so adopting this changes nothing on screen: a
1675
+ * `Date` through `toLocaleString()`, a number as-is (`1234.5`, never
1676
+ * `1,234.5`). Once asked:
1677
+ *
1678
+ * - A `Date` → `Intl.DateTimeFormat`: the date alone under `"date"`, the time
1679
+ * alone under `"time"`, both otherwise.
1680
+ * - A number under a numeric `type` → `Intl.NumberFormat`: `"currency"` with
1681
+ * a currency symbol once `format.currency` names one (two fraction digits
1682
+ * until then), `"percent"` reading `0.25` as 25 %. Under any other type it
1683
+ * is still printed as-is, the way a number id should be.
1684
+ *
1685
+ * `format` and `locale` go to the `Intl` constructor unchanged, so any
1686
+ * option it accepts is honoured.
992
1687
  */
993
1688
  declare function formatCellValue<Row>(value: unknown, column: ColumnDefinition<Row, unknown>, locale?: FormatLocale, row?: Row, messages?: Pick<GridMessages, "booleanTrue" | "booleanFalse">): string;
994
1689
  /**
@@ -1175,7 +1870,7 @@ interface GridOptions<Row> {
1175
1870
  /**
1176
1871
  * Called as the user resizes a column. Fires continuously with
1177
1872
  * `phase: "move"` and once on release with `phase: "end"` — the latter being
1178
- * the one to persist. Auto-fit does not call it; it reports user intent only.
1873
+ * the one to persist. Auto-fitting a column calls it once, with "end".
1179
1874
  */
1180
1875
  onColumnResize?: ((event: ColumnResizeEvent) => void) | undefined;
1181
1876
  /**
@@ -1260,8 +1955,8 @@ interface GridOptions<Row> {
1260
1955
  */
1261
1956
  filter?: FilterState<Row> | undefined;
1262
1957
  /**
1263
- * Called once when the filter changes — through `setFilter` for now, as
1264
- * the grid has no filter UI of its own yet.
1958
+ * Called once when the filter changes — from the toolbar's search box, the
1959
+ * `filter.clearAll` command, `setFilter` or a restored state.
1265
1960
  */
1266
1961
  onFilterChange?: ((event: FilterChangeEvent<Row>) => void) | undefined;
1267
1962
  /**
@@ -1325,297 +2020,112 @@ interface GridOptions<Row> {
1325
2020
  */
1326
2021
  virtualized?: boolean | undefined;
1327
2022
  /**
1328
- * Rows rendered outside the visible range on each side, to reduce
1329
- * blank-frame flashes on fast scrolling. Only meaningful with `virtualized`
1330
- * on.
1331
- */
1332
- overscan?: number | undefined;
1333
- /**
1334
- * Assumed height for a row never yet measured — only matters for the very
1335
- * first paint and for `scrollToRow`'s initial jump before it corrects
1336
- * itself against that row's real, measured height. Only meaningful with
1337
- * `virtualized` on.
1338
- */
1339
- estimatedRowHeight?: number | undefined;
1340
- /**
1341
- * The grid's accessible name, announced when it takes focus. A grid without
1342
- * one is read only as "grid", which says nothing about which grid.
1343
- */
1344
- label?: string | undefined;
1345
- /**
1346
- * The id of an element naming the grid, for a heading already on the page.
1347
- * Takes precedence over `label`, as `aria-labelledby` does.
1348
- */
1349
- labelledBy?: string | undefined;
1350
- /**
1351
- * The locale values are formatted for — a BCP 47 tag such as `"de-DE"`, or
1352
- * a list to fall back through. Setting it turns on `Intl` formatting of
1353
- * dates and numbers in every cell and aggregate shown without a template;
1354
- * without it, only a column with its own `format` is formatted, in the
1355
- * runtime's locale, and the rest print as they always have.
1356
- */
1357
- locale?: FormatLocale;
1358
- /**
1359
- * The grid's own strings, replacing its English key by key — the pager's
1360
- * buttons, the group-by bar, the loading row, boolean and blank values,
1361
- * and every live-region announcement. Keys left out keep their default.
1362
- * Formatting is `locale`'s, not this.
1363
- */
1364
- messages?: Partial<GridMessages> | undefined;
1365
- }
1366
- /**
1367
- * Reported as the user selects. Every one of these is fanned out from a single
1368
- * diff of the transition it describes, so no two can disagree about what one
1369
- * interaction did.
1370
- *
1371
- * Kept apart from `GridOptions` because the column payloads carry resolved
1372
- * columns, whose labels are whatever a renderer's `headerTemplate` returns —
1373
- * `Node` is that renderer's node type.
1374
- */
1375
- interface SelectionCallbacks<Row, Node = string> {
1376
- /** Called once per row newly selected. The last call names the last row. */
1377
- onRowSelect?: ((event: RowSelectEvent<Row>) => void) | undefined;
1378
- /** Called once with every row one interaction selected. */
1379
- onRowsSelect?: ((event: RowsSelectEvent<Row>) => void) | undefined;
1380
- onRowDeselect?: ((event: RowSelectEvent<Row>) => void) | undefined;
1381
- onRowsDeselect?: ((event: RowsSelectEvent<Row>) => void) | undefined;
1382
- /**
1383
- * Called once per change with what it added, what it removed and everything
1384
- * selected after it — the one to persist from.
1385
- */
1386
- onRowSelectionChange?: ((event: RowSelectionChangeEvent<Row>) => void) | undefined;
1387
- onColumnSelect?: ((event: ColumnSelectEvent<Row, Node>) => void) | undefined;
1388
- onColumnsSelect?: ((event: ColumnsSelectEvent<Row, Node>) => void) | undefined;
1389
- onColumnDeselect?: ((event: ColumnSelectEvent<Row, Node>) => void) | undefined;
1390
- onColumnsDeselect?: ((event: ColumnsSelectEvent<Row, Node>) => void) | undefined;
1391
- onColumnSelectionChange?: ((event: ColumnSelectionChangeEvent<Row, Node>) => void) | undefined;
1392
- onCellSelect?: ((event: CellSelectEvent<Row, Node>) => void) | undefined;
1393
- onCellDeselect?: ((event: CellSelectEvent<Row, Node>) => void) | undefined;
1394
- onCellSelectionChange?: ((event: CellSelectionChangeEvent<Row, Node>) => void) | undefined;
1395
- }
1396
-
1397
- /**
1398
- * A row or column selection change by id — see
1399
- * `GridControllerOptions.onSelectionDiff`.
1400
- */
1401
- interface SelectionDiffEvent extends SelectionDiff {
1402
- /** Which selection changed. */
1403
- readonly target: "rows" | "columns";
1404
- /** The whole selection after the change. */
1405
- readonly selection: SelectionState;
1406
- }
1407
- /**
1408
- * What `createGridController` is given: the grid's options and selection
1409
- * callbacks, plus what a renderer supplies that is not a setting — the column
1410
- * definitions, whose templates name the renderer's own node type, the width
1411
- * the viewport measured, and a hook for its own selection feedback.
1412
- */
1413
- interface GridControllerOptions<Row, Node = string> extends GridOptions<Row>, SelectionCallbacks<Row, Node> {
1414
- /**
1415
- * The columns to show. Omitted or empty, one column is inferred per field
1416
- * of `dataSource` — see `defineColumnsFromRows`.
1417
- */
1418
- columns?: readonly ColumnDefinition<Row, Node>[] | undefined;
1419
- /**
1420
- * The width, in px, `resizeMode: "fit"` fills. `null` or absent before it
1421
- * has been measured, or where there is no viewport at all (an export in
1422
- * Node), and then columns keep their resolved widths.
1423
- */
1424
- viewportWidth?: number | null | undefined;
1425
- /**
1426
- * Called once per row or column selection change, after the selection
1427
- * callbacks, with the change by id — every id it added or removed,
1428
- * including those with no row on screen (on another page, in a collapsed
1429
- * group, filtered out), which the callbacks' resolved rows leave out. For a
1430
- * renderer's own feedback, such as a live region announcing how many rows
1431
- * are selected; an application reads the selection callbacks instead.
1432
- */
1433
- onSelectionDiff?: ((event: SelectionDiffEvent) => void) | undefined;
1434
- }
1435
- /**
1436
- * A grid without a renderer: its state, the view derived from it, and every
1437
- * action that changes it. A renderer creates one per grid, hands it the
1438
- * current options on each update, draws `getView()` and calls the actions
1439
- * from its event handlers, so no renderer decides anything the user can see.
1440
- *
1441
- * Each slice of `GridState` is controlled or not on its own, the way a form
1442
- * input is: given as an option (`columnSort`), the grid shows that value and
1443
- * an action only asks for a change through the slice's callback
1444
- * (`onColumnSortChange`); left out, the controller keeps the slice itself,
1445
- * starting from its default (`defaultColumnSort`).
1446
- *
1447
- * Every action follows the same steps: work out the next value; stop if it
1448
- * is the very object the slice already holds; keep it, unless the slice is
1449
- * controlled; report it through the slice's callback; then call every
1450
- * subscriber, synchronously. The setters (`setColumnSort` and the like) also
1451
- * stop for a value equal to the current one, so restoring what is already
1452
- * there reports nothing.
1453
- *
1454
- * Every member is a plain function bound to its grid, safe to hand around on
1455
- * its own — `onClick={controller.nextPage}`.
1456
- */
1457
- interface GridController<Row, Node = string> {
1458
- readonly getOptions: () => GridControllerOptions<Row, Node>;
1459
- /**
1460
- * Replaces the options, as a renderer does with its current props on every
1461
- * update; calling it again with equal options changes nothing. A controlled
1462
- * slice takes its new value from here.
1463
- *
1464
- * Does not call subscribers: a renderer calls this while it updates, and
1465
- * draws the result itself — a subscriber called mid-update would update
1466
- * mid-update too. A renderer that also tells other listeners about it does
1467
- * so once its update is done.
1468
- */
1469
- readonly setOptions: (options: GridControllerOptions<Row, Node>) => void;
1470
- /** Every slice as the grid now applies it. The same object until a slice changes. */
1471
- readonly getState: () => GridState<Row>;
1472
- /** What the user is looking at — see `resolveGridView`. The same object until something in it changes. */
1473
- readonly getView: () => GridView<Row, Node>;
1474
- /**
1475
- * Calls `listener` after each action that got as far as reporting a
1476
- * change. Returns the function that unsubscribes it.
1477
- */
1478
- readonly subscribe: (listener: () => void) => () => void;
1479
- /**
1480
- * Puts back state saved earlier — from `getState()`, or from
1481
- * `serializeGridState` and back through JSON. Every slice given is set as
1482
- * its own `set*` action would set it, so each that changes fires its
1483
- * callback and a controlled one only asks; slices left out keep their value.
1484
- * Subscribers are called once, after every slice is in place, and a
1485
- * restored pagination is kept even when the same call changed the sort,
1486
- * filter or grouping that would otherwise send it back to the first page.
1487
- */
1488
- readonly restoreState: (saved: Partial<GridState<Row>> | Partial<SerializedGridState<Row>>) => void;
1489
- /**
1490
- * Replaces the column widths. Reported through `onColumnResize` as the
1491
- * `"end"` of a resize of the first column whose width changed, at its new
1492
- * width — or, when its entry was removed, the width its definition gives
1493
- * it. Equal widths report nothing.
1494
- */
1495
- readonly setColumnSizing: (sizing: ColumnSizingState) => void;
1496
- /**
1497
- * Sets one column's width, as a resize gesture does: `"move"` while the
1498
- * gesture lasts, `"end"` once it is over. Never skipped for an unchanged
1499
- * width, so a drag held against a column's minimum still reports every
1500
- * move.
1501
- */
1502
- readonly resizeColumn: (columnId: string, width: number, phase: "move" | "end") => void;
1503
- /**
1504
- * Ends a resize gesture by putting its column back as it was when the
1505
- * gesture began — `startSizing` is the sizing state then, `startWidth` the
1506
- * width the column was drawn at — keeping any other column's change made in
1507
- * the meantime. Reported as the gesture's `"end"`, at `startWidth`.
1508
- */
1509
- readonly cancelColumnResize: (columnId: string, startSizing: ColumnSizingState, startWidth: number) => void;
1510
- /**
1511
- * Replaces the column order. Reported through `onColumnOrderChange` naming
1512
- * the first column whose position changed; an equal order reports nothing.
1513
- */
1514
- readonly setColumnOrder: (order: ColumnOrderState) => void;
1515
- /**
1516
- * Moves a column in front of `beforeId`, or to the end when that is
1517
- * `null`, among every column — hidden ones keep their place. A move that
1518
- * changes nothing reports nothing.
1519
- */
1520
- readonly moveColumn: (columnId: string, beforeId: string | null) => void;
1521
- /**
1522
- * Replaces the column visibility state. Reported through
1523
- * `onColumnVisibilityChange` with every column whose entry changed; an
1524
- * equal state reports nothing.
2023
+ * Rows rendered outside the visible range on each side, to reduce
2024
+ * blank-frame flashes on fast scrolling. Only meaningful with `virtualized`
2025
+ * on.
1525
2026
  */
1526
- readonly setColumnVisibility: (visibility: ColumnVisibilityState) => void;
1527
- /** Shows the given columns, each in the place it held when hidden. One report for the whole call. */
1528
- readonly showColumns: (columnIds: readonly string[]) => void;
1529
- /** Hides the given columns. A hidden column still sorts, filters and groups. */
1530
- readonly hideColumns: (columnIds: readonly string[]) => void;
2027
+ overscan?: number | undefined;
1531
2028
  /**
1532
- * Replaces the filter. Reported through `onFilterChange`; a filter equal to
1533
- * the current one — the same entries in the same order, a `Date` value
1534
- * compared by time and a predicate by identity — reports nothing.
2029
+ * Assumed height for a row never yet measured — only matters for the very
2030
+ * first paint and for `scrollToRow`'s initial jump before it corrects
2031
+ * itself against that row's real, measured height. Only meaningful with
2032
+ * `virtualized` on.
1535
2033
  */
1536
- readonly setFilter: (filter: FilterState<Row>) => void;
2034
+ estimatedRowHeight?: number | undefined;
1537
2035
  /**
1538
- * Replaces the selected row ids as given, whatever `selectable` allows —
1539
- * the way a controlled or default value is applied. The same ids in the
1540
- * same order report nothing.
2036
+ * The grid's accessible name, announced when it takes focus. A grid without
2037
+ * one is read only as "grid", which says nothing about which grid.
1541
2038
  */
1542
- readonly setRowSelection: (selection: SelectionState) => void;
2039
+ label?: string | undefined;
1543
2040
  /**
1544
- * Selects rows as a user could, within what `selectable.rows` allows:
1545
- * `"replace"` (the default) selects exactly these — only the last of them
1546
- * under `"single"` — and `"toggle"` flips each one. An id need not name a
1547
- * row on screen. A call that leaves the selection as it was reports
1548
- * nothing.
2041
+ * The id of an element naming the grid, for a heading already on the page.
2042
+ * Takes precedence over `label`, as `aria-labelledby` does.
1549
2043
  */
1550
- readonly selectRows: (rowIds: readonly string[], intent?: "replace" | "toggle") => void;
2044
+ labelledBy?: string | undefined;
1551
2045
  /**
1552
- * Applies one click or key press to a row: `"replace"`, `"toggle"` or
1553
- * `"range"` from the last row selected by anything but a range, across
1554
- * the data rows on the current page.
2046
+ * The locale values are formatted for — a BCP 47 tag such as `"de-DE"`, or
2047
+ * a list to fall back through. Setting it turns on `Intl` formatting of
2048
+ * dates and numbers in every cell and aggregate shown without a template;
2049
+ * without it, only a column with its own `format` is formatted, in the
2050
+ * runtime's locale, and the rest print as they always have.
1555
2051
  */
1556
- readonly selectRow: (rowId: string, intent: SelectIntent) => void;
1557
- /** Selects every data row on the current page, when `selectable.rows` is `"multiple"`. */
1558
- readonly selectAllRows: () => void;
1559
- /** Lets go of every row, column and cell selection at once, as Escape does. */
1560
- readonly clearSelection: () => void;
1561
- /** Replaces the selected column ids as given — see `setRowSelection`. */
1562
- readonly setColumnSelection: (selection: SelectionState) => void;
1563
- /** `selectRow`, for a column among the columns as rendered. */
1564
- readonly selectColumn: (columnId: string, intent: SelectIntent) => void;
1565
- /** Replaces the selected cell as given, `null` for none. */
1566
- readonly setCellSelection: (selection: CellSelectionState) => void;
2052
+ locale?: FormatLocale;
1567
2053
  /**
1568
- * Applies one click or key press to a cell: `"toggle"` lets go of it when
1569
- * it is the one selected; anything else selects it. A cell holds one value,
1570
- * so a range over cells reads as a plain click.
2054
+ * The grid's own strings, replacing its English key by key — the pager's
2055
+ * buttons, the group-by bar, the loading row, boolean and blank values,
2056
+ * the built-in commands' labels, the menus' names, and every live-region
2057
+ * announcement. Keys
2058
+ * left out keep their default.
2059
+ * Formatting is `locale`'s, not this.
1571
2060
  */
1572
- readonly selectCell: (cell: SelectedCellRef, intent: SelectIntent) => void;
2061
+ messages?: Partial<GridMessages> | undefined;
1573
2062
  /**
1574
- * Replaces the sort. Reported through `onColumnSortChange` naming the
1575
- * first column whose place or direction changed; a sort equal to the
1576
- * current one changes nothing and reports nothing.
2063
+ * The grid's own context menu, opened on a column header, a data cell, a
2064
+ * group row or the body's empty space by a right-click, Shift+F10 or the
2065
+ * ContextMenu key. Off by default, like every other feature, leaving the
2066
+ * browser's menu. `true` shows each area's defaults — see
2067
+ * `defaultContextMenu`; an object lists an area's entries, an area left
2068
+ * out keeping its defaults and one given `[]` showing the browser's menu
2069
+ * there.
1577
2070
  */
1578
- readonly setColumnSort: (sort: ColumnSortState) => void;
2071
+ contextMenu?: boolean | GridContextMenuOptions<Row> | undefined;
1579
2072
  /**
1580
- * Cycles a column's sort, as its header toggle does: ascending, descending,
1581
- * off. `stack` adds it to the sort rather than replacing the sort with it.
2073
+ * Called when the grid's context menu opens or closes, with where. A menu
2074
+ * opened in place of another reports that one closing first. The open
2075
+ * state is the renderer's to keep, so no option holds it.
1582
2076
  */
1583
- readonly toggleColumnSort: (columnId: string, options?: {
1584
- readonly stack?: boolean | undefined;
1585
- }) => void;
2077
+ onContextMenuOpenChange?: ((event: ContextMenuOpenChangeEvent) => void) | undefined;
1586
2078
  /**
1587
- * Replaces the group-by stack. Reported through `onGroupByChange` naming
1588
- * the first level that changed; an equal stack reports nothing.
2079
+ * The app's own commands, for its menus to list by id. One with a
2080
+ * built-in's id replaces it wherever that id is listed — a translated,
2081
+ * privilege-gated or differently behaving "Hide column" — see
2082
+ * `resolveCommands`.
1589
2083
  */
1590
- readonly setGroupBy: (groupBy: GroupByState) => void;
1591
- /** Adds a column to the end of the group-by stack, or removes it if it is already there. */
1592
- readonly toggleGroupBy: (columnId: string) => void;
2084
+ commands?: readonly GridCommand<Row>[] | undefined;
1593
2085
  /**
1594
- * Puts a column into the group-by stack in front of `beforeColumnId`, or at
1595
- * the end when that is `null` — adding it, or moving it if it is already
1596
- * there.
2086
+ * Called after a command or an inline menu item runs — chosen from a menu,
2087
+ * or run through a renderer's API — saying which, where it was asked for
2088
+ * and from where. One that did not run, being hidden or disabled, is not
2089
+ * reported.
1597
2090
  */
1598
- readonly moveGroupBy: (columnId: string, beforeColumnId: string | null) => void;
2091
+ onCommand?: ((event: GridCommandEvent) => void) | undefined;
1599
2092
  /**
1600
- * Replaces the collapsed groups. Reported with `groupId: null`, as a change
1601
- * to every group at once; the same ids in the same order report nothing.
2093
+ * A toolbar above the grid: its own commands, a search box over the
2094
+ * filter's global text entry, dropdowns and the app's own content, in the
2095
+ * menu vocabulary. Off by default. `true` lists `defaultToolbar`; an object
2096
+ * lists its `items` and may name it with `label` — see `ToolbarEntry`.
1602
2097
  */
1603
- readonly setGroupExpansion: (expansion: GroupExpansionState) => void;
1604
- readonly toggleGroupExpansion: (groupId: string) => void;
1605
- readonly expandAllGroups: () => void;
1606
- /** Collapses every group currently shown — see `collapseAllGroups`. */
1607
- readonly collapseAllGroups: () => void;
2098
+ toolbar?: boolean | GridToolbarOptions<Row> | undefined;
2099
+ }
2100
+ /**
2101
+ * Reported as the user selects. Every one of these is fanned out from a single
2102
+ * diff of the transition it describes, so no two can disagree about what one
2103
+ * interaction did.
2104
+ *
2105
+ * Kept apart from `GridOptions` because the column payloads carry resolved
2106
+ * columns, whose labels are whatever a renderer's `headerTemplate` returns —
2107
+ * `Node` is that renderer's node type.
2108
+ */
2109
+ interface SelectionCallbacks<Row, Node = string> {
2110
+ /** Called once per row newly selected. The last call names the last row. */
2111
+ onRowSelect?: ((event: RowSelectEvent<Row>) => void) | undefined;
2112
+ /** Called once with every row one interaction selected. */
2113
+ onRowsSelect?: ((event: RowsSelectEvent<Row>) => void) | undefined;
2114
+ onRowDeselect?: ((event: RowSelectEvent<Row>) => void) | undefined;
2115
+ onRowsDeselect?: ((event: RowsSelectEvent<Row>) => void) | undefined;
1608
2116
  /**
1609
- * Replaces the page and page size as given; the view clamps a page past
1610
- * the last one. An equal pagination reports nothing.
2117
+ * Called once per change with what it added, what it removed and everything
2118
+ * selected after it — the one to persist from.
1611
2119
  */
1612
- readonly setPagination: (pagination: PaginationState) => void;
1613
- /** Moves to the given page, clamped into range. */
1614
- readonly goToPage: (pageIndex: number) => void;
1615
- readonly nextPage: () => void;
1616
- readonly previousPage: () => void;
1617
- /** Changes the page size and goes back to the first page. */
1618
- readonly setPageSize: (pageSize: number) => void;
2120
+ onRowSelectionChange?: ((event: RowSelectionChangeEvent<Row>) => void) | undefined;
2121
+ onColumnSelect?: ((event: ColumnSelectEvent<Row, Node>) => void) | undefined;
2122
+ onColumnsSelect?: ((event: ColumnsSelectEvent<Row, Node>) => void) | undefined;
2123
+ onColumnDeselect?: ((event: ColumnSelectEvent<Row, Node>) => void) | undefined;
2124
+ onColumnsDeselect?: ((event: ColumnsSelectEvent<Row, Node>) => void) | undefined;
2125
+ onColumnSelectionChange?: ((event: ColumnSelectionChangeEvent<Row, Node>) => void) | undefined;
2126
+ onCellSelect?: ((event: CellSelectEvent<Row, Node>) => void) | undefined;
2127
+ onCellDeselect?: ((event: CellSelectEvent<Row, Node>) => void) | undefined;
2128
+ onCellSelectionChange?: ((event: CellSelectionChangeEvent<Row, Node>) => void) | undefined;
1619
2129
  }
1620
2130
 
1621
2131
  /**
@@ -1625,6 +2135,187 @@ interface GridController<Row, Node = string> {
1625
2135
  */
1626
2136
  declare function createGridController<Row, Node = string>(initial: GridControllerOptions<Row, Node>): GridController<Row, Node>;
1627
2137
 
2138
+ /** What `createCommandContext` builds a context from. */
2139
+ interface GridCommandContextInput<Row, Node> {
2140
+ readonly controller: GridController<Row, Node>;
2141
+ readonly target: GridCommandTarget;
2142
+ /** The grid's messages, already laid over the defaults — see `resolveMessages`. */
2143
+ readonly messages: GridMessages;
2144
+ readonly host: GridCommandHost;
2145
+ }
2146
+ /**
2147
+ * A command context for `target`, over the controller's state, view and
2148
+ * options as they are now. The controller itself serves as `actions`, typed
2149
+ * down to them, so a command cannot reach `setOptions`.
2150
+ *
2151
+ * `row` and `column` are looked up once here, against every filtered row and
2152
+ * every column, hidden ones included, so a target the API names off screen
2153
+ * still resolves.
2154
+ */
2155
+ declare function createCommandContext<Row, Node>({ controller, target, messages, host, }: GridCommandContextInput<Row, Node>): GridCommandContext<Row>;
2156
+
2157
+ /**
2158
+ * Every command a grid knows, by id: the built-ins, then `commands` — an app
2159
+ * command with a built-in's id replacing it, so every menu and toolbar
2160
+ * listing that id gets the app's version (translated, gated by a privilege,
2161
+ * or doing something else) without being changed itself.
2162
+ *
2163
+ * A fresh map per call; a renderer resolves it once per change to
2164
+ * `commands`, not per menu.
2165
+ */
2166
+ declare function resolveCommands<Row>(commands: readonly GridCommand<Row>[] | undefined): ReadonlyMap<string, GridCommand<Row>>;
2167
+ /**
2168
+ * Runs `command` when it is visible and enabled on `context`'s target, and
2169
+ * says whether it did — so a renderer reports only a command that ran, and a
2170
+ * stale button or a call through the API cannot run one the grid's state no
2171
+ * longer allows.
2172
+ */
2173
+ declare function runCommand<Row>(command: GridCommand<Row>, context: GridCommandContext<Row>): boolean;
2174
+
2175
+ /** What `resolveMenu` resolves a menu's entries against. */
2176
+ interface MenuResolveOptions<Row> {
2177
+ /** Every command the grid knows, by id — see `resolveCommands`. */
2178
+ readonly commands: ReadonlyMap<string, GridCommand<Row>>;
2179
+ readonly context: GridCommandContext<Row>;
2180
+ }
2181
+ /**
2182
+ * A menu's entries resolved against the grid as `context` sees it, ready to
2183
+ * draw:
2184
+ *
2185
+ * - A command id becomes its command's item, and a hidden command or item
2186
+ * is left out. An id naming no command is left out too, and reported once
2187
+ * per command map through `console.error`.
2188
+ * - Labels become strings and flags booleans; `checked` stays `undefined`
2189
+ * for an item that is not checkable.
2190
+ * - A submenu is resolved the same way, and left out when nothing in it
2191
+ * shows.
2192
+ * - Separators never lead, trail or double up, however the items around
2193
+ * them came and went.
2194
+ *
2195
+ * An empty result means there is nothing to show — no grid menu at all
2196
+ * here.
2197
+ */
2198
+ declare function resolveMenu<Row>(entries: readonly MenuEntry<Row>[], options: MenuResolveOptions<Row>): readonly ResolvedMenuEntry[];
2199
+
2200
+ /** Where an arrow, Home or End key moves a menu's focus. */
2201
+ type MenuMove = "next" | "previous" | "first" | "last";
2202
+ /**
2203
+ * The index of the item focus moves to from `from` — `-1` when nothing is
2204
+ * focused yet, so `"next"` lands on the first item and `"previous"` on the
2205
+ * last. Separators are skipped and `"next"`/`"previous"` wrap round the
2206
+ * ends; disabled items count, since they stay focusable for a screen reader
2207
+ * to find. `-1` when there is no item at all.
2208
+ *
2209
+ * Takes anything with a `type`, so a behaviour that reads its items off the
2210
+ * page can pass `{ type: "item" }` for each.
2211
+ */
2212
+ declare function nextMenuIndex(entries: readonly Pick<ResolvedMenuEntry, "type">[], from: number, move: MenuMove): number;
2213
+ /**
2214
+ * The index of the item `query` — what was typed, buffered for a moment —
2215
+ * picks, matched case-insensitively against the start of each label and
2216
+ * wrapping round the end; `-1` when none matches.
2217
+ *
2218
+ * `from` is the item focused now. A single letter, or the same letter
2219
+ * typed again and again, searches from the item after it, so repeating a
2220
+ * letter steps through every item it starts. A longer query searches from
2221
+ * `from` itself, so the item already found stays put while what is typed
2222
+ * still matches it.
2223
+ */
2224
+ declare function typeaheadIndex(labels: readonly string[], from: number, query: string): number;
2225
+
2226
+ /** What `resolveToolbar` resolves a toolbar's entries against. */
2227
+ interface ToolbarResolveOptions<Row> {
2228
+ /** Every command the grid knows, by id — see `resolveCommands`. */
2229
+ readonly commands: ReadonlyMap<string, GridCommand<Row>>;
2230
+ /**
2231
+ * The context an item resolves and runs in, for its target — the item
2232
+ * itself, or the dropdown an item in one is listed under. A command that
2233
+ * opens a panel anchors it there.
2234
+ */
2235
+ readonly contextFor: (target: GridToolbarTarget) => GridCommandContext<Row>;
2236
+ }
2237
+ /**
2238
+ * A toolbar's entries resolved against the grid, ready to draw, by the
2239
+ * rules `resolveMenu` follows:
2240
+ *
2241
+ * - A command id becomes its command's button, and an inline item a button
2242
+ * of its own; either is a toggle, with `pressed`, when it is checkable. A
2243
+ * hidden one is left out, and so is an id naming no command, reported
2244
+ * once per command map through `console.error`.
2245
+ * - A submenu becomes a dropdown, its items resolved as a menu's, and is
2246
+ * left out when nothing in it shows.
2247
+ * - `"search"`, `"spacer"` and custom entries stay as they are.
2248
+ * - Separators never lead, trail, double up or sit next to a spacer, which
2249
+ * already parts what is on either side of it.
2250
+ *
2251
+ * Resolve again whenever the grid changes, so each button's label, flags
2252
+ * and `run` follow its state.
2253
+ */
2254
+ declare function resolveToolbar<Row>(entries: readonly ToolbarEntry<Row>[], options: ToolbarResolveOptions<Row>): readonly ResolvedToolbarItem[];
2255
+
2256
+ /** What `fitToolbarItems` fits: a toolbar's entries, by width, into its space. */
2257
+ interface ToolbarFitInput {
2258
+ /** Each entry's width, in order — `0` for a spacer, whose width is only the space left over. */
2259
+ readonly widths: readonly number[];
2260
+ /** The width the entries share. */
2261
+ readonly available: number;
2262
+ /** The width of the "More" button the entries that do not fit go into. */
2263
+ readonly moreWidth: number;
2264
+ /** Whether each entry, in order, stays however little room there is. */
2265
+ readonly pinned: readonly boolean[];
2266
+ }
2267
+ /**
2268
+ * How many of a toolbar's entries fit, from the start: the first `count`
2269
+ * stay in the toolbar, with every pinned entry after them, and the rest go
2270
+ * into a "More" menu.
2271
+ *
2272
+ * Pinned entries take their room first, wherever they are. Room for "More"
2273
+ * is kept only when something does not fit — when everything does, the
2274
+ * result is every entry and no "More" is drawn. Entries are taken in order
2275
+ * and the first that does not fit ends the count, so the toolbar keeps its
2276
+ * order rather than filling gaps with later, narrower entries; one with no
2277
+ * width, a spacer, fits wherever the entries before it did.
2278
+ */
2279
+ declare function fitToolbarItems({ widths, available, moreWidth, pinned, }: ToolbarFitInput): number;
2280
+ /**
2281
+ * Whether a toolbar entry stays in the toolbar however narrow it gets: the
2282
+ * search box and custom entries, which have no menu item to become.
2283
+ */
2284
+ declare function isPinnedToolbarItem(item: Pick<ResolvedToolbarItem, "type">): boolean;
2285
+ /** A toolbar split at the count `fitToolbarItems` gave — see `splitToolbarItems`. */
2286
+ interface ToolbarSplit {
2287
+ /** What stays in the toolbar. */
2288
+ readonly shown: readonly ResolvedToolbarItem[];
2289
+ /** The "More" menu's entries, empty when everything fits. */
2290
+ readonly overflow: readonly ResolvedMenuEntry[];
2291
+ }
2292
+ /**
2293
+ * `items` split at the first `fit`: those before it, and every pinned item,
2294
+ * stay in the toolbar; the rest become the "More" menu's entries — a button
2295
+ * an item, checked where it was pressed, and a dropdown a submenu. Neither
2296
+ * side keeps a separator at its ends, doubled, or beside a spacer.
2297
+ */
2298
+ declare function splitToolbarItems(items: readonly ResolvedToolbarItem[], fit: number): ToolbarSplit;
2299
+
2300
+ /**
2301
+ * What a search box shows for `filter`: the global text entry's query — the
2302
+ * one naming no column — without the `%` anchors that make it a "contains"
2303
+ * match, or `""` when there is none. A `%` the user typed inside the text
2304
+ * stays: only the first and last characters are anchors.
2305
+ */
2306
+ declare function searchTextOf<Row>(filter: FilterState<Row>): string;
2307
+ /**
2308
+ * `filter` with its global text entry set to search for `text` anywhere in
2309
+ * any column — the query `%text%` — or removed for an empty `text`. Every
2310
+ * entry naming a column stays as it was. `filter` itself, unchanged, when
2311
+ * it already searches for `text`.
2312
+ *
2313
+ * `text` is written as typed, spaces and all: a search box reads its text
2314
+ * back from the filter, and trimming here would take a space away from
2315
+ * under the caret as the user types it.
2316
+ */
2317
+ declare function setSearchText<Row>(filter: FilterState<Row>, text: string): FilterState<Row>;
2318
+
1628
2319
  /**
1629
2320
  * How a column of `type` aligns by default. Numeric types align right so that
1630
2321
  * their digits line up by place value; everything else reads from the left.
@@ -1680,6 +2371,8 @@ interface KeyShortcutCapabilities {
1680
2371
  resizable: boolean;
1681
2372
  sortable: boolean;
1682
2373
  groupable: boolean;
2374
+ /** Whether the header opens the grid's context menu. Defaults to `false`. */
2375
+ contextMenu?: boolean | undefined;
1683
2376
  }
1684
2377
  /**
1685
2378
  * The `aria-keyshortcuts` string for a column header, naming only the keys
@@ -2226,44 +2919,6 @@ declare function applyColumnVisibility<Row, Node>(columns: readonly DataColumn<R
2226
2919
  */
2227
2920
  declare function setColumnVisibility<Row>(columns: readonly DataColumn<Row, unknown>[], visibility: ColumnVisibilityState, columnIds: readonly string[], visible: boolean): ColumnVisibilityState;
2228
2921
 
2229
- /**
2230
- * `resolveGridView`, memoised per stage: each stage remembers its last
2231
- * inputs and returns its last output when none of them changed identity, so
2232
- * a call that changes one slice of state recomputes only what depends on
2233
- * it. The data stages (filter → sort → group → aggregate → paginate) read
2234
- * `dataColumns`, which carry no width, so a resize or a viewport change
2235
- * leaves `rows`, `displayRows`, `pageRows`, `displayDataRows` and
2236
- * `grandTotal` reference-equal to the previous call's — only `columns` is
2237
- * new. The view object itself is reused when every field is unchanged, so a
2238
- * snapshot-based renderer sees nothing to re-render.
2239
- *
2240
- * Hold one resolver per grid and call it with the current input every time
2241
- * the view is needed; the memo only pays off across calls to the same one.
2242
- */
2243
- declare function createGridViewResolver<Row, Node = string>(): (input: GridViewInput<Row, Node>) => GridView<Row, Node>;
2244
- /**
2245
- * What the user is looking at, derived from the rows, the columns, the
2246
- * grid's state and its options in one call: rows filtered → sorted →
2247
- * grouped → aggregated → paginated, and columns ordered → hidden → sized.
2248
- * The one function a renderer, an export or a toolbar calls instead of
2249
- * composing the stages itself, so none of them can disagree about what is
2250
- * shown.
2251
- *
2252
- * Unmemoised — a one-off resolver. A renderer that derives the view on every
2253
- * change holds a `createGridViewResolver()` instead.
2254
- */
2255
- declare function resolveGridView<Row, Node = string>(input: GridViewInput<Row, Node>): GridView<Row, Node>;
2256
-
2257
- /**
2258
- * `state` in a form that survives `JSON.stringify` and back unchanged, for
2259
- * saving a layout — to local storage, a URL, a user's profile — and handing
2260
- * it to `restoreState` later. Every slice is plain data already except the
2261
- * filter: a `Date` value or operand is written as its ISO string, and a
2262
- * predicate entry, being a function, cannot be written at all and is left
2263
- * out with a `console.error` naming its column.
2264
- */
2265
- declare function serializeGridState<Row>(state: GridState<Row>): SerializedGridState<Row>;
2266
-
2267
2922
  /**
2268
2923
  * What one column's filter looks like to an editor — which of its forms can
2269
2924
  * show it, or that none can.
@@ -2307,6 +2962,11 @@ interface ColumnValueQuery {
2307
2962
  readonly limit?: number;
2308
2963
  /** The locale labels are formatted for — the grid's own `locale`. */
2309
2964
  readonly locale?: FormatLocale;
2965
+ /**
2966
+ * The grid's own `messages`, over the defaults: a boolean is labelled
2967
+ * `booleanTrue`/`booleanFalse`, as its cells print it.
2968
+ */
2969
+ readonly messages?: Partial<GridMessages>;
2310
2970
  }
2311
2971
  interface ColumnValueOptions {
2312
2972
  /** The distinct values, sorted as the column sorts, searched and cut to `limit`. */
@@ -2317,6 +2977,12 @@ interface ColumnValueOptions {
2317
2977
  readonly truncated: boolean;
2318
2978
  /** How many of the same rows hold a blank — `null`, `undefined` or `""`. */
2319
2979
  readonly blanks: number;
2980
+ /**
2981
+ * The column's `type`, which tells values apart the way an `in` filter
2982
+ * does — on a date column, a date string and the `Date` it names are one
2983
+ * value. `initialFilterEditorDraft` carries it into the draft.
2984
+ */
2985
+ readonly columnType?: ColumnType | undefined;
2320
2986
  }
2321
2987
  /**
2322
2988
  * A checklist or condition editor's working copy of one column's filter,
@@ -2332,11 +2998,13 @@ interface FilterEditorDraft<Row> {
2332
2998
  /** How many rows hold a blank; the blanks entry only matters when some do. */
2333
2999
  readonly blanks: number;
2334
3000
  readonly search: string;
2335
- /** The checked values, keyed as grouping keys them. */
3001
+ /** The checked values, keyed as an `in` filter on the column keys them. */
2336
3002
  readonly checked: ReadonlyMap<string, FilterScalar>;
2337
3003
  readonly includeBlanks: boolean;
2338
3004
  readonly conditions: readonly OperatorFilterEntry<Row>[];
2339
3005
  readonly combinator: "and" | "or";
3006
+ /** The column's `type`, from `ColumnValueOptions` — what values are keyed by. */
3007
+ readonly columnType?: ColumnType | undefined;
2340
3008
  }
2341
3009
  type FilterEditorAction<Row> = {
2342
3010
  readonly type: "search";
@@ -2376,9 +3044,11 @@ declare function describeColumnFilter<Row>(filter: FilterState<Row>, columnId: s
2376
3044
  * Counted over the rows every *other* column's filter keeps — every entry
2377
3045
  * except those `describeColumnFilter` would count for this column — so a
2378
3046
  * column's list cascades from the other filters without its own pick
2379
- * hiding the values the user unchecked. Values are told apart as grouping
2380
- * tells them apart, ordered as the column sorts, labelled as its cells
2381
- * print; blanks are counted apart, in `blanks`.
3047
+ * hiding the values the user unchecked. Values are told apart as an `in`
3048
+ * filter tells them apart — as grouping does, except that a date column's
3049
+ * date strings are the dates they name — ordered as the column sorts, and
3050
+ * labelled as its cells print, a boolean in `query.messages`' words; blanks
3051
+ * are counted apart, in `blanks`.
2382
3052
  *
2383
3053
  * Costs one pass over `rows` (tens of milliseconds at 100k rows), so compute
2384
3054
  * it when an editor opens rather than on every render, and hand the whole
@@ -2420,6 +3090,96 @@ declare function filterEditorReducer<Row>(draft: FilterEditorDraft<Row>, action:
2420
3090
  */
2421
3091
  declare function draftToFilter<Row>(draft: FilterEditorDraft<Row>, columnId: string, current: FilterState<Row>): FilterState<Row>;
2422
3092
 
3093
+ /** What a column chooser is drawn from: every column, the visibility, and the search typed. */
3094
+ interface ColumnChooserInput<Row> {
3095
+ /** Every column in its current order, hidden ones included — a view's `dataColumns`. */
3096
+ readonly columns: readonly DataColumn<Row, unknown>[];
3097
+ readonly visibility: ColumnVisibilityState;
3098
+ /** Narrows the list to the columns whose header text contains it, ignoring case. */
3099
+ readonly search?: string | undefined;
3100
+ }
3101
+ /** One column's checkbox in a column chooser. */
3102
+ interface ColumnChooserEntry {
3103
+ readonly columnId: string;
3104
+ /** The column's header text — what the search matches, and the checkbox's label. */
3105
+ readonly label: string;
3106
+ /** Whether the column is shown — whether its checkbox is checked. */
3107
+ readonly visible: boolean;
3108
+ /**
3109
+ * Whether the checkbox cannot be unchecked: the column is shown and is
3110
+ * either not `hideable` or the last column shown. A hidden column can
3111
+ * always be shown, `hideable` or not.
3112
+ */
3113
+ readonly disabled: boolean;
3114
+ }
3115
+ /** What toggling a chooser's "Show all" checkbox does: shows these columns, or hides them. */
3116
+ interface ColumnChooserToggle {
3117
+ readonly visible: boolean;
3118
+ readonly columnIds: readonly string[];
3119
+ }
3120
+ interface ColumnChooserModel {
3121
+ /** The columns the search matches, in column order. */
3122
+ readonly entries: readonly ColumnChooserEntry[];
3123
+ /**
3124
+ * The "Show all" checkbox's state over the entries whose columns are
3125
+ * `hideable` — the ones it acts on. A column the user cannot hide is
3126
+ * always on, so counting it would leave "Show all" stuck at mixed.
3127
+ */
3128
+ readonly selectAll: SelectAllState;
3129
+ /** What toggling "Show all" does, or `null` when it can do nothing — a disabled checkbox. */
3130
+ readonly toggleAll: ColumnChooserToggle | null;
3131
+ }
3132
+ /**
3133
+ * A column chooser's list for a search, and what its "Show all" checkbox
3134
+ * says and does — the same tri-state over what the search shows that a
3135
+ * filter editor's select-all is (`selectAllState`).
3136
+ *
3137
+ * "Show all" shows every hidden column the search shows once any is hidden,
3138
+ * and hides those it shows once none is. It never touches a column that is
3139
+ * not `hideable`, and never hides the last column shown: when that is all
3140
+ * that would be left, the first of them in column order stays, since a grid
3141
+ * with no column shown has no header to bring one back from.
3142
+ */
3143
+ declare function resolveColumnChooser<Row>({ columns, visibility, search, }: ColumnChooserInput<Row>): ColumnChooserModel;
3144
+
3145
+ /**
3146
+ * `resolveGridView`, memoised per stage: each stage remembers its last
3147
+ * inputs and returns its last output when none of them changed identity, so
3148
+ * a call that changes one slice of state recomputes only what depends on
3149
+ * it. The data stages (filter → sort → group → aggregate → paginate) read
3150
+ * `dataColumns`, which carry no width, so a resize or a viewport change
3151
+ * leaves `rows`, `displayRows`, `pageRows`, `displayDataRows` and
3152
+ * `grandTotal` reference-equal to the previous call's — only `columns` is
3153
+ * new. The view object itself is reused when every field is unchanged, so a
3154
+ * snapshot-based renderer sees nothing to re-render.
3155
+ *
3156
+ * Hold one resolver per grid and call it with the current input every time
3157
+ * the view is needed; the memo only pays off across calls to the same one.
3158
+ */
3159
+ declare function createGridViewResolver<Row, Node = string>(): (input: GridViewInput<Row, Node>) => GridView<Row, Node>;
3160
+ /**
3161
+ * What the user is looking at, derived from the rows, the columns, the
3162
+ * grid's state and its options in one call: rows filtered → sorted →
3163
+ * grouped → aggregated → paginated, and columns ordered → hidden → sized.
3164
+ * The one function a renderer, an export or a toolbar calls instead of
3165
+ * composing the stages itself, so none of them can disagree about what is
3166
+ * shown.
3167
+ *
3168
+ * Unmemoised — a one-off resolver. A renderer that derives the view on every
3169
+ * change holds a `createGridViewResolver()` instead.
3170
+ */
3171
+ declare function resolveGridView<Row, Node = string>(input: GridViewInput<Row, Node>): GridView<Row, Node>;
3172
+
3173
+ /**
3174
+ * `state` in a form that survives `JSON.stringify` and back unchanged, for
3175
+ * saving a layout — to local storage, a URL, a user's profile — and handing
3176
+ * it to `restoreState` later. Every slice is plain data already except the
3177
+ * filter: a `Date` value or operand is written as its ISO string, and a
3178
+ * predicate entry, being a function, cannot be written at all and is left
3179
+ * out with a `console.error` naming its column.
3180
+ */
3181
+ declare function serializeGridState<Row>(state: GridState<Row>): SerializedGridState<Row>;
3182
+
2423
3183
  /**
2424
3184
  * One entry per row: its measured height once known, `undefined` until then.
2425
3185
  * A row never yet rendered (or rendered but not yet observed) falls back to
@@ -2454,4 +3214,4 @@ interface VisibleRange {
2454
3214
  */
2455
3215
  declare function visibleRange(heights: RowHeights, estimatedHeight: number, scrollTop: number, viewportHeight: number, overscan: number): VisibleRange;
2456
3216
 
2457
- export { type AggregateFn, type AggregateResults, type AggregateSpec, type AggregateState, type Borders, type BuiltInAggregate, type CellSelectEvent, type CellSelectionChangeEvent, type CellSelectionMode, type CellSelectionState, type CellTemplateContext, type ColumnAlignment, type ColumnConstraints, type ColumnDefinition, 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 ColumnValueOption, type ColumnValueOptions, type ColumnValueQuery, type ColumnVisibilityEvent, type ColumnVisibilityState, type ColumnWrapConfig, type ColumnsSelectEvent, DEFAULT_COLUMN_SIZES, type DataColumn, type DisplayRow, type DropSide, type FieldPath, type FilterChangeEvent, type FilterEditorAction, type FilterEditorDraft, type FilterEntry, type FilterOperator, type FilterPredicate, type FilterScalar, type FilterState, type FooterTemplateContext, type FormatLocale, type GridController, type GridControllerOptions, type GridFocus, type GridMessages, type GridOptions, type GridState, 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, KEYBOARD_STEP, type KeyShortcutCapabilities, type NavigationModifiers, type OperatorFilterEntry, type PaginatedRows, type PaginationChangeEvent, type PaginationState, type PaginationWindowEntry, type PredicateFilterEntry, type ResizeMode, type ResolvedColumn, type ResolvedGroupRow, type ResolvedGroupSummaryRow, type ResolvedRow, 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 ValueFilterEntry, type VisibleRange, accessDotted, alignmentForType, applyColumnOrder, applyColumnResize, applyColumnVisibility, applySelectionIntent, beginColumnResize, buildKeyShortcuts, clampColumnWidth, clampFocus, clearAllFilters, clearSelection, collapseAllGroups, columnValueOptions, compareValues, computeAggregates, createGridController, createGridViewResolver, defaultMessages, defineColumnsFromRows, describeColumnFilter, diffSelection, draftToFilter, expandAllGroups, filterEditorReducer, filterQueryFor, filterRows, fitColumnsToWidth, formatAggregateValue, formatCellValue, getColumnId, groupRowId, groupRows, initialFilterEditorDraft, intentOf, isColumnVisible, isSameCell, matchesQuery, moveColumnBefore, moveGroupByBefore, movesColumn, movesGroupBy, nextFocusForKey, paginateRows, paginationWindow, resolveCell, resolveColumnConstraints, resolveColumnHeaderText, resolveColumnLabel, resolveColumnWidths, resolveColumns, resolveDataColumns, resolveDropBefore, resolveGridView, resolveKeyboardDropTarget, resolveMessages, resolveRowId, resolveRows, resolveShownRows, revertColumnSize, selectAll, selectAllState, selectCell, selectOnly, selectRange, serializeGridState, setColumnFilter, setColumnVisibility, sizeColumnToContent, sortDirectionFor, sortPriorityFor, sortRows, toggleCellSelection, toggleColumnSort, toggleGroupExpansion, toggleSelection, totalColumnWidth, visibleFilterOptions, visibleRange, withGroupAggregates };
3217
+ 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 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 ColumnValueOption, type ColumnValueOptions, type ColumnValueQuery, type ColumnVisibilityEvent, type ColumnVisibilityState, type ColumnWrapConfig, type ColumnsSelectEvent, type ContextMenuOpenChangeEvent, DEFAULT_COLUMN_SIZES, type DataColumn, type DisplayRow, type DropSide, type FieldPath, type FilterChangeEvent, type FilterEditorAction, type FilterEditorDraft, type FilterEntry, type FilterOperator, 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 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, 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 PredicateFilterEntry, type ResizeMode, type ResolvedColumn, 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 ValueFilterEntry, type VisibleRange, accessDotted, alignmentForType, applyColumnOrder, applyColumnResize, applyColumnVisibility, applySelectionIntent, beginColumnResize, buildKeyShortcuts, builtInCommands, clampColumnWidth, clampFocus, clearAllFilters, clearSelection, collapseAllGroups, columnValueOptions, compareValues, computeAggregates, contextMenuEntries, createCommandContext, createGridController, createGridViewResolver, defaultContextMenu, defaultMessages, defaultToolbar, defineColumnsFromRows, describeColumnFilter, diffSelection, draftToFilter, expandAllGroups, filterEditorReducer, filterQueryFor, filterRows, fitColumnsToWidth, fitToolbarItems, formatAggregateValue, formatCellValue, getColumnId, groupRowId, groupRows, hasContextMenu, initialFilterEditorDraft, intentOf, isColumnVisible, isPinnedToolbarItem, isSameCell, matchesQuery, moveColumnBefore, moveGroupByBefore, movesColumn, movesGroupBy, nextFocusForKey, nextMenuIndex, paginateRows, paginationWindow, resolveCell, resolveColumnChooser, resolveColumnConstraints, resolveColumnHeaderText, resolveColumnLabel, resolveColumnWidths, resolveColumns, resolveCommands, resolveDataColumns, resolveDropBefore, 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, toggleCellSelection, toggleColumnSort, toggleGroupExpansion, toggleSelection, toolbarEntries, totalColumnWidth, typeaheadIndex, visibleFilterOptions, visibleRange, withGroupAggregates };