@box-kite/react 0.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. package/.claude/rules/box-kite-rules.md +65 -0
  2. package/.claude/skills/box-kite/SKILL.md +138 -0
  3. package/.claude/skills/box-kite/references/components.md +235 -0
  4. package/.claude/skills/box-kite/references/extending.md +42 -0
  5. package/.claude/skills/box-kite/references/patterns.md +27 -0
  6. package/.claude/skills/box-kite/references/styling.md +222 -0
  7. package/.cursor/rules/box-kite.mdc +73 -0
  8. package/AGENTS.md +102 -0
  9. package/BOX_AI_CONTEXT.md +2804 -0
  10. package/BOX_KITE_AI_CONTEXT.md +2804 -0
  11. package/LICENSE +21 -0
  12. package/README.md +744 -7
  13. package/a11y.cjs +1 -0
  14. package/a11y.d.ts +15 -0
  15. package/a11y.mjs +4 -0
  16. package/anchor.cjs +1 -0
  17. package/anchor.d.ts +14 -0
  18. package/anchor.mjs +3 -0
  19. package/behavior.cjs +1 -0
  20. package/behavior.mjs +277 -0
  21. package/box.cjs +1 -0
  22. package/box.d.ts +46 -0
  23. package/box.mjs +23 -0
  24. package/client.cjs +1 -0
  25. package/client.mjs +164 -0
  26. package/components/accordion.cjs +1 -0
  27. package/components/accordion.d.ts +114 -0
  28. package/components/accordion.mjs +251 -0
  29. package/components/baseSvg.cjs +1 -0
  30. package/components/baseSvg.d.ts +5 -0
  31. package/components/baseSvg.mjs +21 -0
  32. package/components/button.cjs +1 -0
  33. package/components/button.d.ts +19 -0
  34. package/components/button.mjs +19 -0
  35. package/components/chart.cjs +1 -0
  36. package/components/chart.d.ts +83 -0
  37. package/components/chart.mjs +236 -0
  38. package/components/checkbox.cjs +1 -0
  39. package/components/checkbox.d.ts +36 -0
  40. package/components/checkbox.mjs +38 -0
  41. package/components/combobox/comboboxChips.d.ts +21 -0
  42. package/components/combobox/comboboxListbox.d.ts +47 -0
  43. package/components/combobox.cjs +1 -0
  44. package/components/combobox.d.ts +121 -0
  45. package/components/combobox.mjs +563 -0
  46. package/components/dataGrid/components/dataGridAggregateValue.d.ts +10 -0
  47. package/components/dataGrid/components/dataGridBody.d.ts +7 -0
  48. package/components/dataGrid/components/dataGridBottomBar.d.ts +6 -0
  49. package/components/dataGrid/components/dataGridCell.d.ts +16 -0
  50. package/components/dataGrid/components/dataGridCellEditor.d.ts +15 -0
  51. package/components/dataGrid/components/dataGridCellPlaceholder.d.ts +14 -0
  52. package/components/dataGrid/components/dataGridCellRowDetail.d.ts +6 -0
  53. package/components/dataGrid/components/dataGridCellRowSelection.d.ts +6 -0
  54. package/components/dataGrid/components/dataGridCellText.d.ts +6 -0
  55. package/components/dataGrid/components/dataGridCellTree.d.ts +16 -0
  56. package/components/dataGrid/components/dataGridColumnFilter.d.ts +9 -0
  57. package/components/dataGrid/components/dataGridColumnGroups.d.ts +7 -0
  58. package/components/dataGrid/components/dataGridContent.d.ts +6 -0
  59. package/components/dataGrid/components/dataGridDataSourceError.d.ts +12 -0
  60. package/components/dataGrid/components/dataGridDetailRow.d.ts +8 -0
  61. package/components/dataGrid/components/dataGridEmptyColumns.d.ts +6 -0
  62. package/components/dataGrid/components/dataGridExport.d.ts +10 -0
  63. package/components/dataGrid/components/dataGridFilterCell.d.ts +11 -0
  64. package/components/dataGrid/components/dataGridFilterRow.d.ts +6 -0
  65. package/components/dataGrid/components/dataGridFooter.d.ts +11 -0
  66. package/components/dataGrid/components/dataGridGlobalFilter.d.ts +6 -0
  67. package/components/dataGrid/components/dataGridGroupRow.d.ts +8 -0
  68. package/components/dataGrid/components/dataGridHeader.d.ts +6 -0
  69. package/components/dataGrid/components/dataGridHeaderCell.d.ts +9 -0
  70. package/components/dataGrid/components/dataGridHeaderCellContextMenu.d.ts +11 -0
  71. package/components/dataGrid/components/dataGridHeaderCellResizer.d.ts +14 -0
  72. package/components/dataGrid/components/dataGridLoader.d.ts +11 -0
  73. package/components/dataGrid/components/dataGridPagination.d.ts +6 -0
  74. package/components/dataGrid/components/dataGridRow.d.ts +8 -0
  75. package/components/dataGrid/components/dataGridTopBar.d.ts +6 -0
  76. package/components/dataGrid/components/dataGridTopBarContextMenu.d.ts +6 -0
  77. package/components/dataGrid/contracts/dataGridContract.d.ts +671 -0
  78. package/components/dataGrid/export/gridExport.d.ts +10 -0
  79. package/components/dataGrid/gridNavigationContext.d.ts +32 -0
  80. package/components/dataGrid/models/aggregateCellModel.d.ts +34 -0
  81. package/components/dataGrid/models/aggregationModel.d.ts +32 -0
  82. package/components/dataGrid/models/cellKeys.d.ts +11 -0
  83. package/components/dataGrid/models/cellModel.d.ts +44 -0
  84. package/components/dataGrid/models/columnModel.d.ts +160 -0
  85. package/components/dataGrid/models/columnVisibilityModel.d.ts +24 -0
  86. package/components/dataGrid/models/dataSourceModel.d.ts +177 -0
  87. package/components/dataGrid/models/detailRowModel.d.ts +22 -0
  88. package/components/dataGrid/models/editModel.d.ts +77 -0
  89. package/components/dataGrid/models/exportModel.d.ts +51 -0
  90. package/components/dataGrid/models/filterModel.d.ts +22 -0
  91. package/components/dataGrid/models/gridModel.d.ts +293 -0
  92. package/components/dataGrid/models/groupRowCellModel.d.ts +34 -0
  93. package/components/dataGrid/models/groupRowModel.d.ts +68 -0
  94. package/components/dataGrid/models/headerCellModel.d.ts +83 -0
  95. package/components/dataGrid/models/paginationModel.d.ts +32 -0
  96. package/components/dataGrid/models/rowModel.d.ts +46 -0
  97. package/components/dataGrid/models/sourceGroupRowModel.d.ts +45 -0
  98. package/components/dataGrid/models/sourceLevel.d.ts +71 -0
  99. package/components/dataGrid/models/sourceRowModel.d.ts +29 -0
  100. package/components/dataGrid/models/sourceTreeRowModel.d.ts +23 -0
  101. package/components/dataGrid/models/treeModel.d.ts +94 -0
  102. package/components/dataGrid/models/treeRow.d.ts +22 -0
  103. package/components/dataGrid/models/treeRowModel.d.ts +50 -0
  104. package/components/dataGrid/models/viewportModel.d.ts +44 -0
  105. package/components/dataGrid/useGrid.d.ts +8 -0
  106. package/components/dataGrid/useGridNavigation.d.ts +21 -0
  107. package/components/dataGrid.cjs +1 -0
  108. package/components/dataGrid.d.ts +4 -0
  109. package/components/dataGrid.mjs +4907 -0
  110. package/components/dialog.cjs +1 -0
  111. package/components/dialog.d.ts +151 -0
  112. package/components/dialog.mjs +223 -0
  113. package/components/dropdown/dropdownContext.d.ts +44 -0
  114. package/components/dropdown/dropdownItems.d.ts +22 -0
  115. package/components/dropdown/dropdownRowRenderer.d.ts +8 -0
  116. package/components/dropdown/dropdownSearch.d.ts +21 -0
  117. package/components/dropdown/utils.d.ts +1 -0
  118. package/components/dropdown.cjs +1 -0
  119. package/components/dropdown.d.ts +77 -0
  120. package/components/dropdown.mjs +491 -0
  121. package/components/flex.cjs +1 -0
  122. package/components/flex.d.ts +6 -0
  123. package/components/flex.mjs +16 -0
  124. package/components/form.cjs +1 -0
  125. package/components/form.d.ts +10 -0
  126. package/components/form.mjs +58 -0
  127. package/components/grid.cjs +1 -0
  128. package/components/grid.d.ts +6 -0
  129. package/components/grid.mjs +16 -0
  130. package/components/icon.cjs +1 -0
  131. package/components/icon.d.ts +37 -0
  132. package/components/icon.mjs +41 -0
  133. package/components/menu.cjs +1 -0
  134. package/components/menu.d.ts +234 -0
  135. package/components/menu.mjs +422 -0
  136. package/components/overlay.cjs +1 -0
  137. package/components/overlay.d.ts +47 -0
  138. package/components/overlay.mjs +52 -0
  139. package/components/popover.cjs +1 -0
  140. package/components/popover.d.ts +100 -0
  141. package/components/popover.mjs +69 -0
  142. package/components/presence.cjs +1 -0
  143. package/components/presence.d.ts +36 -0
  144. package/components/presence.mjs +11 -0
  145. package/components/progress.cjs +1 -0
  146. package/components/progress.d.ts +47 -0
  147. package/components/progress.mjs +28 -0
  148. package/components/radioButton.cjs +1 -0
  149. package/components/radioButton.d.ts +32 -0
  150. package/components/radioButton.mjs +32 -0
  151. package/components/radioGroup.cjs +1 -0
  152. package/components/radioGroup.d.ts +51 -0
  153. package/components/radioGroup.mjs +83 -0
  154. package/components/select.cjs +1 -0
  155. package/components/select.d.ts +51 -0
  156. package/components/select.mjs +36 -0
  157. package/components/semantics.cjs +1 -0
  158. package/components/semantics.d.ts +39 -0
  159. package/components/semantics.mjs +17 -0
  160. package/components/slider.cjs +1 -0
  161. package/components/slider.d.ts +98 -0
  162. package/components/slider.mjs +250 -0
  163. package/components/svg.cjs +1 -0
  164. package/components/svg.d.ts +65 -0
  165. package/components/svg.mjs +141 -0
  166. package/components/switch.cjs +1 -0
  167. package/components/switch.d.ts +29 -0
  168. package/components/switch.mjs +25 -0
  169. package/components/tabs.cjs +1 -0
  170. package/components/tabs.d.ts +87 -0
  171. package/components/tabs.mjs +324 -0
  172. package/components/textarea.cjs +1 -0
  173. package/components/textarea.d.ts +41 -0
  174. package/components/textarea.mjs +33 -0
  175. package/components/textbox.cjs +1 -0
  176. package/components/textbox.d.ts +38 -0
  177. package/components/textbox.mjs +33 -0
  178. package/components/toaster.cjs +1 -0
  179. package/components/toaster.d.ts +106 -0
  180. package/components/toaster.mjs +295 -0
  181. package/components/tooltip.cjs +1 -0
  182. package/components/tooltip.d.ts +98 -0
  183. package/components/tooltip.mjs +110 -0
  184. package/components/visuallyHidden.cjs +1 -0
  185. package/components/visuallyHidden.d.ts +6 -0
  186. package/components/visuallyHidden.mjs +23 -0
  187. package/docs/a11y.md +199 -0
  188. package/docs/anchor.md +139 -0
  189. package/docs/components.md +48 -0
  190. package/docs/index.md +11 -0
  191. package/docs/props.md +1777 -0
  192. package/effects.cjs +1 -0
  193. package/effects.mjs +6 -0
  194. package/forms.cjs +1 -0
  195. package/forms.mjs +21 -0
  196. package/gridExport.cjs +2 -0
  197. package/gridExport.mjs +244 -0
  198. package/icons/dotsIcon.d.ts +2 -0
  199. package/icons/expandIcon.d.ts +2 -0
  200. package/icons/groupingIcon.d.ts +2 -0
  201. package/icons/pinIcon.d.ts +2 -0
  202. package/icons/searchIcon.d.ts +2 -0
  203. package/icons/sortIcon.d.ts +2 -0
  204. package/identity.cjs +1 -0
  205. package/identity.mjs +12 -0
  206. package/keyboard.cjs +1 -0
  207. package/keyboard.mjs +30 -0
  208. package/layer.cjs +1 -0
  209. package/layer.mjs +127 -0
  210. package/motion.cjs +1 -0
  211. package/motion.mjs +66 -0
  212. package/package.json +327 -7
  213. package/placement.cjs +1 -0
  214. package/placement.mjs +180 -0
  215. package/platform.cjs +1 -0
  216. package/platform.mjs +45 -0
  217. package/react/a11y/callbacks.d.ts +12 -0
  218. package/react/a11y/useControllableState.d.ts +25 -0
  219. package/react/a11y/useDismiss.d.ts +25 -0
  220. package/react/a11y/useFocusReturn.d.ts +18 -0
  221. package/react/a11y/useRovingFocus.d.ts +84 -0
  222. package/react/anchor/useAnchorPosition.d.ts +79 -0
  223. package/react/animation/usePresence.d.ts +32 -0
  224. package/react/boxClassNames.d.ts +25 -0
  225. package/react/boxProps.d.ts +49 -0
  226. package/react/boxTagProps.d.ts +7 -0
  227. package/react/clientRuntime.d.ts +11 -0
  228. package/react/dialog/useScrollLock.d.ts +12 -0
  229. package/react/effects.d.ts +10 -0
  230. package/react/forms/labelledControl.d.ts +17 -0
  231. package/react/forms/placeholderProp.d.ts +13 -0
  232. package/react/hooks/usePortalContainer.d.ts +6 -0
  233. package/react/hooks/useVirtualization.d.ts +32 -0
  234. package/react/hooks/useVisibility.d.ts +9 -0
  235. package/react/identity/useIdentifier.d.ts +17 -0
  236. package/react/popover/usePopoverLayer.d.ts +87 -0
  237. package/react/reactTypes.d.ts +10 -0
  238. package/react/resolveStyles.d.ts +18 -0
  239. package/react/styleElements.d.ts +3 -0
  240. package/react/svg/attributesInProps.d.ts +4 -0
  241. package/react/svg/svgNaming.d.ts +15 -0
  242. package/react/theme/theme.d.ts +26 -0
  243. package/react/theme/themeContext.d.ts +7 -0
  244. package/react/useStyles.d.ts +22 -0
  245. package/react-shared.cjs +1 -0
  246. package/react-shared.mjs +122 -0
  247. package/rolldown-runtime.cjs +1 -0
  248. package/rsc.cjs +1 -0
  249. package/rsc.d.ts +27 -0
  250. package/rsc.mjs +18 -0
  251. package/ssg.cjs +1 -0
  252. package/ssg.d.ts +24 -0
  253. package/ssg.mjs +25 -0
  254. package/utils/accordion/accordionUtils.d.ts +48 -0
  255. package/utils/anchor/anchorUtils.d.ts +79 -0
  256. package/utils/animation/animationUtils.d.ts +29 -0
  257. package/utils/array/arrayUtils.d.ts +15 -0
  258. package/utils/array/lazyList.d.ts +10 -0
  259. package/utils/box/boxUtils.d.ts +5 -0
  260. package/utils/chart/chartPalette.d.ts +15 -0
  261. package/utils/chart/chartUtils.d.ts +92 -0
  262. package/utils/combobox/comboboxUtils.d.ts +89 -0
  263. package/utils/dom/domUtils.d.ts +32 -0
  264. package/utils/environment/environmentUtils.d.ts +28 -0
  265. package/utils/export/csvUtils.d.ts +23 -0
  266. package/utils/export/downloadUtils.d.ts +12 -0
  267. package/utils/export/xlsxUtils.d.ts +56 -0
  268. package/utils/export/zipUtils.d.ts +26 -0
  269. package/utils/fn/fnUtils.d.ts +4 -0
  270. package/utils/form/formUtils.d.ts +8 -0
  271. package/utils/keyboard/typeaheadUtils.d.ts +31 -0
  272. package/utils/memo.d.ts +10 -0
  273. package/utils/menu/menuUtils.d.ts +25 -0
  274. package/utils/object/objectUtils.d.ts +13 -0
  275. package/utils/slider/sliderUtils.d.ts +67 -0
  276. package/utils/string/fuzzySearch.d.ts +27 -0
  277. package/utils/string/stringUtils.d.ts +4 -0
  278. package/utils/tabs/tabsUtils.d.ts +75 -0
  279. package/utils/toast/toastStore.d.ts +73 -0
  280. package/utils/virtual/virtualUtils.d.ts +47 -0
@@ -0,0 +1,671 @@
1
+ import { BoxProps } from '../../../box';
2
+ import { ChangeHandler } from '../../../react/a11y/useControllableState';
3
+ import { ComponentsAndVariants } from '../../../types';
4
+ import { SortDirection } from '../../../utils/array/arrayUtils';
5
+ import { default as AggregateCellModel } from '../models/aggregateCellModel';
6
+ import { default as CellModel } from '../models/cellModel';
7
+ export type { SortDirection };
8
+ export type Key = string | number;
9
+ /**
10
+ * Which edge a column is pinned to, named by the reading order rather than by the screen: `START` is the
11
+ * left edge of a left-to-right grid and the right edge of a right-to-left one, so a pinned column stays
12
+ * where the reading starts under either `dir`. `LEFT`/`RIGHT` are the older spelling of the same two.
13
+ */
14
+ export type PinPosition = 'START' | 'END';
15
+ /** What `pin` accepts — the logical pair, plus the physical names it used to be spelled with. */
16
+ export type PinPositionInput = PinPosition | 'LEFT' | 'RIGHT';
17
+ /** The logical side behind whichever spelling the caller used. */
18
+ export declare function pinPositionOf(pin?: PinPositionInput): PinPosition | undefined;
19
+ export declare const NO_PIN = "NO_PIN";
20
+ export type SortColumnType<TRow> = {
21
+ key: keyof TRow;
22
+ dir: SortDirection;
23
+ };
24
+ export type KeysMatching<T, V> = {
25
+ [K in keyof T]-?: T[K] extends V ? K : never;
26
+ }[keyof T];
27
+ export interface PaginationState {
28
+ pageSize: number;
29
+ page: number;
30
+ totalItems: number;
31
+ totalPages: number;
32
+ }
33
+ /** Server-side pagination configuration on GridDefinition */
34
+ export interface PaginationConfig {
35
+ /**
36
+ * Total number of items across all pages, from the server response. Required unless `def.dataSource`
37
+ * is answering the count, in which case the grid already has it.
38
+ */
39
+ totalCount?: number;
40
+ /** Page size override. If omitted, defaults to visibleRowsCount (or 10). */
41
+ pageSize?: number;
42
+ /** Options shown in the page size selector dropdown. If omitted, no selector is shown. */
43
+ pageSizeOptions?: number[];
44
+ }
45
+ /** Snapshot of all server-relevant grid state, passed to onServerStateChange */
46
+ export interface ServerState<TRow> {
47
+ page: number;
48
+ pageSize: number;
49
+ sortColumn: Key | undefined;
50
+ sortDirection: SortDirection | undefined;
51
+ columnFilters: ColumnFilters<TRow>;
52
+ globalFilterValue: string;
53
+ }
54
+ /**
55
+ * What the grid asks its `def.dataSource` for: one block of rows, and the query they have to satisfy.
56
+ * The range is given twice because the two halves of the world spell it differently — `startRow`/`endRow`
57
+ * is an SQL `OFFSET`/`LIMIT`, `page`/`pageSize` is a REST pager, and they always describe the same block.
58
+ */
59
+ export interface DataSourceRequest<TRow> {
60
+ /** First row wanted, 0-based across the whole result set. */
61
+ startRow: number;
62
+ /** One past the last row wanted. `endRow - startRow` is never more than the block size. */
63
+ endRow: number;
64
+ /** The same block, 1-based, for an API that pages. */
65
+ page: number;
66
+ /** Rows per block — the page size when the grid is paginated, `blockSize` otherwise. */
67
+ pageSize: number;
68
+ /** Which column the grid is sorted by, or `undefined` when it is not sorted. */
69
+ sort: DataGridSort | undefined;
70
+ /** What the global filter box holds. Empty when it is not in use. */
71
+ globalFilter: string;
72
+ /** Every column filter still set, keyed by column. */
73
+ columnFilters: ColumnFilters<TRow>;
74
+ /**
75
+ * Which columns the grid is grouping by, outermost first. Empty unless `dataSource.grouping` is on and
76
+ * the user has grouped something; the column this block groups by is `groupBy[groupKeys.length]`.
77
+ */
78
+ groupBy: Key[];
79
+ /**
80
+ * The group this block sits inside, outermost value first — `[]` at the top. `['Japan']` asks for what
81
+ * is inside the Japan group, `['Japan', 2021]` for the level under that. Shorter than `groupBy` and the
82
+ * rows wanted are **group** rows, one per distinct value of `groupBy[groupKeys.length]`; the same length
83
+ * and they are that group's leaf rows.
84
+ */
85
+ groupKeys: Key[];
86
+ /**
87
+ * The row whose children this block holds, named by the keys of it and of every ancestor, outermost
88
+ * first — `[]` is the top of the tree. Empty unless `def.treeData` is set beside the datasource, and
89
+ * the keys are the grid's own (`def.rowKey`), so a server names a node by the id it sent for it.
90
+ */
91
+ treeKeys: Key[];
92
+ /**
93
+ * Aborted when the query changes under a request still in flight — a new sort, a new filter, a page
94
+ * the user left. Hand it to `fetch` and a superseded request costs nothing.
95
+ */
96
+ signal: AbortSignal;
97
+ }
98
+ /** What a `getRows` answers with. */
99
+ export interface DataSourceResult<TRow> {
100
+ /** The block's rows, in order. Fewer than asked for means the end of the data. */
101
+ rows: TRow[];
102
+ /**
103
+ * How many rows the query holds altogether — the scrollbar's length and the pager's last page. Answer
104
+ * it once and the grid keeps it; omit it and the grid follows the rows instead, treating a short block
105
+ * as the end, which is what an API that cannot count cheaply needs.
106
+ */
107
+ totalCount?: number;
108
+ /**
109
+ * For a group level: how many leaf rows each returned group holds, in the order `rows` came in. It is
110
+ * what the group label puts in its brackets, and it is optional — a server that cannot count a group
111
+ * cheaply omits it and the label is the value on its own.
112
+ */
113
+ groupCounts?: number[];
114
+ }
115
+ /**
116
+ * Where the rows come from when the grid fetches them itself: sorting, filtering and paging become a
117
+ * request rather than work done in the browser, so a table of a million rows costs the page one block.
118
+ * `data` is not read at all while this is set.
119
+ */
120
+ export interface DataSource<TRow> {
121
+ /** Answers one block. Called again whenever the sort, the filters or the visible range change. */
122
+ getRows: (request: DataSourceRequest<TRow>) => Promise<DataSourceResult<TRow>>;
123
+ /**
124
+ * Rows per request. Default: the page size when `def.pagination` is set, 100 otherwise. A block is the
125
+ * unit of everything here — of a request, of the loading state, and of what a failure costs.
126
+ */
127
+ blockSize?: number;
128
+ /**
129
+ * How many blocks to keep. Past this the ones furthest from the viewport are dropped and fetched again
130
+ * if the user scrolls back. Default: 40.
131
+ */
132
+ maxBlocks?: number;
133
+ /**
134
+ * Whether `getRows` honours `groupKeys` — which is what puts *Group by* back in the column menu. Off by
135
+ * default, because a `getRows` that ignored the field would answer a group level with leaf rows and the
136
+ * grid has no way to tell. With it on, opening a group is one more request rather than work in the
137
+ * browser: the children of a group nobody has expanded are never in the page at all.
138
+ */
139
+ grouping?: boolean;
140
+ }
141
+ /**
142
+ * Why a server-relevant thing changed. `'page'` and `'page-size'` are the pager; the other three are a
143
+ * query that changed underneath it, which is also what sent the grid back to the first page.
144
+ */
145
+ export type DataGridChangeReason = 'page' | 'page-size' | 'sort' | 'filter' | 'clear';
146
+ /** A filter was typed, or emptied — by the clear button or by deleting the last character. */
147
+ export type DataGridFilterReason = 'filter' | 'clear';
148
+ /** A column was sorted, or the sort was cleared (the third press on a header, and the menu's Clear Sort). */
149
+ export type DataGridSortReason = 'sort' | 'clear';
150
+ /** A detail row was opened or shut. */
151
+ export type DataGridExpandReason = 'expand' | 'collapse';
152
+ /** The same four `Dropdown` reports a selection under: the header checkbox is the `-all`/`clear` pair. */
153
+ export type DataGridSelectionReason = 'select' | 'deselect' | 'select-all' | 'clear';
154
+ /** Which column the grid is sorted by, and which way. `undefined` in a change means it is not sorted. */
155
+ export interface DataGridSort {
156
+ columnKey: Key;
157
+ direction: SortDirection;
158
+ }
159
+ /** Where the pager is. The two move together — a new page size always returns to page 1. */
160
+ export interface DataGridPagination {
161
+ page: number;
162
+ pageSize: number;
163
+ }
164
+ /** Filter type for column-level filtering */
165
+ export type ColumnFilterType = 'text' | 'number' | 'multiselect';
166
+ /** Text filter configuration (fuzzy search) */
167
+ export interface TextFilterValue {
168
+ type: 'text';
169
+ value: string;
170
+ }
171
+ /** Number filter configuration with comparison operators */
172
+ export interface NumberFilterValue {
173
+ type: 'number';
174
+ operator: 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'between';
175
+ value: number;
176
+ valueTo?: number;
177
+ }
178
+ /** Multi-select filter configuration */
179
+ export interface MultiselectFilterValue {
180
+ type: 'multiselect';
181
+ values: (string | number | boolean | null)[];
182
+ }
183
+ /** Union type for all filter values */
184
+ export type FilterValue = TextFilterValue | NumberFilterValue | MultiselectFilterValue;
185
+ /** Column filters record - maps column key to filter value */
186
+ export type ColumnFilters<TRow> = Partial<Record<keyof TRow | Key, FilterValue>>;
187
+ /** Filter configuration for a column */
188
+ export interface ColumnFilterConfig {
189
+ type: ColumnFilterType;
190
+ /** Placeholder text for input */
191
+ placeholder?: string;
192
+ /** For multiselect: custom options. If not provided, unique values are computed from data */
193
+ options?: {
194
+ label: string;
195
+ value: string | number | boolean | null;
196
+ }[];
197
+ /** For number: step value for input */
198
+ step?: number;
199
+ /** For number: min value */
200
+ min?: number;
201
+ /** For number: max value */
202
+ max?: number;
203
+ }
204
+ /** Configuration for expandable row detail panel */
205
+ export interface RowDetailConfig<TRow> {
206
+ /** Render function for the detail content */
207
+ content: (row: TRow) => React.ReactNode;
208
+ /** Height of the detail row. 'auto' sizes to content. Default: 'auto' */
209
+ height?: 'auto' | number | ((row: TRow) => number);
210
+ /** Whether clicking the row also toggles expansion. Default: false */
211
+ expandOnRowClick?: boolean;
212
+ /** Pin the expand column to LEFT. Default: false */
213
+ pinned?: boolean;
214
+ /** Width of the expand column. Default: 50 */
215
+ expandColumnWidth?: number;
216
+ /** Header text for the expand column. Default: '' (empty) */
217
+ expandColumnHeader?: string;
218
+ /** Scroll a panel opened below the fold into view. Default: true */
219
+ scrollIntoView?: boolean;
220
+ }
221
+ /**
222
+ * What a row's own state is before anybody has clicked anything: `true` opens every row, a number opens
223
+ * down to that depth (`1` is the top level's children shown), and a list of keys opens exactly those.
224
+ */
225
+ export type DefaultExpanded = boolean | number | Key[];
226
+ /**
227
+ * Rows that hold rows. The tree is read off the data in one of two shapes — **nested**, where a row
228
+ * carries its children (`childrenKey`/`getChildren`), or **flat**, where every row carries the path to
229
+ * itself (`pathKey`/`getPath`) — and the grid does the rest: one column grows a chevron and an indent,
230
+ * the rows underneath a shut one leave the list, and the grid becomes a `treegrid`.
231
+ *
232
+ * Beside `def.dataSource` it is the third shape: **lazy**, where the tree is not in the browser at all.
233
+ * The server answers one level at a time — the request carries `treeKeys`, the path of the row that was
234
+ * opened — and `hasChildren` is how a row says there is something under it to ask for.
235
+ */
236
+ export interface TreeDataConfig<TRow> {
237
+ /** Nested rows: the field a row's children live in. */
238
+ childrenKey?: keyof TRow | Key;
239
+ /** Nested rows, worked out rather than stored. Answer nothing for a leaf. */
240
+ getChildren?: (row: TRow) => TRow[] | undefined | null;
241
+ /** Flat rows: the field holding the path from the root to this row, its own segment last. */
242
+ pathKey?: keyof TRow | Key;
243
+ /** Flat rows, worked out: `['src', 'core', 'box.ts']` for a row three deep. */
244
+ getPath?: (row: TRow) => Key[];
245
+ /**
246
+ * Lazy rows: whether this row holds any, which is the one thing a server has to say that the row's own
247
+ * values do not. A field of the row or a predicate over it; without one no row grows a chevron, since
248
+ * the browser has nothing under it to read. Ignored by a nested or a flat tree, whose shape says it.
249
+ */
250
+ hasChildren?: keyof TRow | ((row: TRow) => boolean);
251
+ /**
252
+ * Which column carries the chevrons and the indent. Default: the first column of your own, which is
253
+ * the one a tree is almost always read down.
254
+ */
255
+ column?: Key;
256
+ /** How far one level indents, on the ÷4 spacing scale. Default: 4, which is 1rem a level. */
257
+ indent?: number;
258
+ /**
259
+ * Which rows are open before anything has been clicked. Default: nothing but the top level. A lazy
260
+ * tree fetches one level per row it opens, so `true` there is a request per row of the whole tree —
261
+ * name the keys instead.
262
+ */
263
+ defaultExpanded?: DefaultExpanded;
264
+ /**
265
+ * Whether ticking a row ticks everything under it, and a row whose children are partly ticked reads as
266
+ * indeterminate. Default: `'self'` — a checkbox selects the row it is on, which is what every other row
267
+ * in the grid does. Not offered by a lazy tree: a cascade cannot reach rows nobody has fetched.
268
+ */
269
+ selection?: 'self' | 'cascade';
270
+ }
271
+ /**
272
+ * The four editors the grid draws for itself. A column wanting anything else — a date picker, a colour,
273
+ * a lookup against a table — declares `EditCell` instead and renders it, driven by the same model.
274
+ */
275
+ export type CellEditorType = 'text' | 'number' | 'checkbox' | 'select';
276
+ /** One option of a `select` editor. `value` is what the cell holds; `label` is what the list shows. */
277
+ export interface CellEditorOption {
278
+ value: string | number | boolean | null;
279
+ label?: React.ReactNode;
280
+ }
281
+ /** An editor and whatever it needs. A bare name is this with nothing else set. */
282
+ export interface CellEditorConfig<TRow> {
283
+ type: CellEditorType;
284
+ /** `select` only: the options, or a function over the row being edited when they depend on it. */
285
+ options?: CellEditorOption[] | ((row: TRow) => CellEditorOption[]);
286
+ /** `text`/`number`/`select`: what an empty editor shows. */
287
+ placeholder?: string;
288
+ /** `number` only, handed to the input as it stands. */
289
+ step?: number;
290
+ min?: number;
291
+ max?: number;
292
+ }
293
+ /** Whether a column can be edited: every row of it, or the rows a predicate says. */
294
+ export type ColumnEditable<TRow> = boolean | ((row: TRow) => boolean);
295
+ /**
296
+ * One cell, changed. It is what `def.onCellEdit` judges and what the edit stream is made of. `row` is the
297
+ * row as the grid holds it — before this edit, so a validator comparing against a sibling field sees the
298
+ * values the user saw.
299
+ */
300
+ export interface CellEdit<TRow> {
301
+ rowKey: Key;
302
+ columnKey: Key;
303
+ row: TRow;
304
+ value: unknown;
305
+ oldValue: unknown;
306
+ }
307
+ /**
308
+ * What `def.onCellEdit` answers with. Nothing or `true` accepts the value; a string rejects it and is the
309
+ * message the cell shows and a screen reader is told; `false` rejects it with the grid's own wording.
310
+ */
311
+ export type CellEditResult = void | boolean | string;
312
+ /** Why the edit stream changed: a cell was accepted, or the host took the edits off the grid's hands. */
313
+ export type DataGridEditReason = 'edit' | 'clear';
314
+ /** Controls which sections appear in the column header context menu */
315
+ export interface ContextMenuConfig {
316
+ /** Show sort actions (Sort Ascending, Sort Descending, Clear Sort). Default: true */
317
+ sort?: boolean;
318
+ /** Show pin actions (pin to start, pin to end, unpin). Default: true */
319
+ pin?: boolean;
320
+ /** Show group actions (Group By, Un-Group All). Default: true */
321
+ group?: boolean;
322
+ }
323
+ /** What an aggregate comes out as. Formatting it is `AggregateCell`'s job, not the aggregation's. */
324
+ export type AggregateValue = number | string | null;
325
+ /**
326
+ * The five built-in aggregations. `sum`, `avg`, `min` and `max` read the numbers in the column and skip
327
+ * everything else, so a blank cell is not a zero; `count` counts rows rather than values, which is why it
328
+ * is the one that never skips anything.
329
+ */
330
+ export type AggregateName = 'sum' | 'avg' | 'min' | 'max' | 'count';
331
+ /**
332
+ * An aggregation of your own. `values` is this column's value from every row in scope and `rows` are those
333
+ * rows, so a weighted average can reach the column it weights by.
334
+ */
335
+ export type AggregateFn<TRow> = (values: unknown[], rows: TRow[]) => AggregateValue;
336
+ /** What a column's `aggregate` takes: one of the five names, or a function. */
337
+ export type ColumnAggregate<TRow> = AggregateName | AggregateFn<TRow>;
338
+ /** Which rows an aggregate covered: one group row's, or every row the filters left. */
339
+ export type AggregateScope = 'group' | 'footer';
340
+ /** What both export formats take. */
341
+ export interface DataGridExportOptions {
342
+ /** The file's name, without the extension. Default: the grid's `title`, or `export`. */
343
+ fileName?: string;
344
+ /** The columns to write, by key, in the order given. Default: every visible column, plus the grouped ones. */
345
+ columns?: Key[];
346
+ /** Write a row per group, with its totals. Default: true, which writes them wherever the grid is grouped. */
347
+ groups?: boolean;
348
+ /** Write the grand-total row. Default: whatever `def.footer` is. */
349
+ footer?: boolean;
350
+ }
351
+ /** A CSV export. */
352
+ export interface DataGridCsvOptions extends DataGridExportOptions {
353
+ /** The field separator. Default: `,`. */
354
+ delimiter?: string;
355
+ /**
356
+ * Prefix a value beginning `=`, `+`, `-` or `@` with a quote, so a spreadsheet reads it as text rather
357
+ * than running it. Default: true — a cell somebody typed is data, and a file that executes it is CSV
358
+ * injection.
359
+ */
360
+ escapeFormulas?: boolean;
361
+ }
362
+ /** An Excel export. A workbook carries no theme, so its colours are written out rather than themed. */
363
+ export interface DataGridXlsxOptions extends DataGridExportOptions {
364
+ /** The worksheet's name. Default: the grid's `title`, or `Sheet1`. */
365
+ sheetName?: string;
366
+ /** The header row's fill, as `RRGGBB`. Default: the grid header's own grey. */
367
+ headerFill?: string;
368
+ /** The header row's text colour, as `RRGGBB`. */
369
+ headerColor?: string;
370
+ }
371
+ /** The export buttons in the top bar. `true` is both formats, named by the grid's title. */
372
+ export interface ExportConfig extends DataGridExportOptions {
373
+ /** Show the CSV button. Default: true. */
374
+ csv?: boolean;
375
+ /** Show the Excel button. Default: true. */
376
+ xlsx?: boolean;
377
+ }
378
+ /** One column of an exported file. */
379
+ export interface ExportColumn {
380
+ key: Key;
381
+ header: string;
382
+ /** In characters — the unit a spreadsheet sizes a column in. */
383
+ width: number;
384
+ /** The number format its values are written with, from the column's `exportFormat`. */
385
+ format?: string;
386
+ }
387
+ /** One row of an exported file, and where it sits in the grouping. */
388
+ export interface ExportRow {
389
+ kind: 'group' | 'data' | 'footer';
390
+ /** 0 at the top; a row under one group is 1, under two is 2 — Excel's outline level. */
391
+ level: number;
392
+ /** Whether the grid has the group above it collapsed. */
393
+ hidden: boolean;
394
+ /** Whether this row is the summary of a collapsed group. */
395
+ collapsed: boolean;
396
+ values: unknown[];
397
+ }
398
+ /** What an export writes, before either format has written it. */
399
+ export interface ExportTable {
400
+ columns: ExportColumn[];
401
+ rows: ExportRow[];
402
+ }
403
+ /**
404
+ * What a `ref` on a `DataGrid` holds. The export methods load the writers on the first call, so a grid
405
+ * nobody exports from carries none of that code.
406
+ */
407
+ export interface DataGridHandle {
408
+ /** The element the grid renders. */
409
+ readonly element: HTMLDivElement | null;
410
+ /** Download the grid as `.csv`. */
411
+ exportCsv(options?: DataGridCsvOptions): Promise<void>;
412
+ /** Download the grid as `.xlsx`. */
413
+ exportXlsx(options?: DataGridXlsxOptions): Promise<void>;
414
+ /**
415
+ * Throw away the blocks `def.dataSource` has fetched and ask for them again. The grid already does
416
+ * this whenever it changes the query itself; this is for the half it cannot see — a filter of the
417
+ * page's own, a row somebody saved, a tenant that changed under the closure `getRows` lives in. Inert
418
+ * without a datasource.
419
+ */
420
+ refresh(): void;
421
+ /**
422
+ * Drop the edits the grid is holding over its rows, which is how a host says its own data now carries
423
+ * them. Until it does the grid keeps showing what it accepted, so a value survives a block being
424
+ * refetched or a `data` prop that never changes; afterwards the rows answer for themselves again.
425
+ */
426
+ clearEdits(): void;
427
+ }
428
+ export interface ColumnType<TRow> {
429
+ key: Key;
430
+ header?: string;
431
+ pin?: PinPositionInput;
432
+ width?: number;
433
+ columns?: ColumnType<TRow>[];
434
+ /** `start`/`end` follow the reading order; `left`/`right` stay on the screen side they name. */
435
+ align?: 'start' | 'end' | 'center' | 'left' | 'right';
436
+ Cell?: React.ComponentType<{
437
+ cell: CellModel<TRow>;
438
+ }>;
439
+ /**
440
+ * Aggregate this column over the rows under each group row, and over the whole grid when `def.footer`
441
+ * is on. One of the five built-in names, or a function.
442
+ */
443
+ aggregate?: ColumnAggregate<TRow>;
444
+ /**
445
+ * The value this column writes to an exported file. Default: the row's own field at `key` — which is
446
+ * what a column drawn by a `Cell` renderer needs, since an export runs no React.
447
+ */
448
+ exportValue?: (row: TRow) => string | number | boolean | Date | null;
449
+ /** The number format its values are written with in a spreadsheet, `'#,##0.00'` or `'yyyy-mm-dd'`. */
450
+ exportFormat?: string;
451
+ /** Renders this column's aggregate wherever one appears. Without it the value is rendered as it is. */
452
+ AggregateCell?: React.ComponentType<{
453
+ cell: AggregateCellModel<TRow>;
454
+ }>;
455
+ /**
456
+ * Whether this column's cells can be edited — every row of it, or the rows a predicate says. Without
457
+ * one it inherits `def.editable`, which is off by default.
458
+ */
459
+ editable?: ColumnEditable<TRow>;
460
+ /**
461
+ * Which editor a cell opens. Default: `number` for a column whose values are numbers, `checkbox` for
462
+ * booleans, `text` for everything else — read off the first row that has a value, so a column of
463
+ * numbers gets a numeric keypad without being told.
464
+ */
465
+ editor?: CellEditorType | CellEditorConfig<TRow>;
466
+ /**
467
+ * An editor of your own, for what the four built-in ones do not cover. It is handed the cell, and the
468
+ * cell carries the draft value and the two ways out (`commitEdit`, `cancelEdit`) — so a custom editor
469
+ * is a control bound to `cell.draft`, not a second copy of the commit rules.
470
+ */
471
+ EditCell?: React.ComponentType<{
472
+ cell: CellModel<TRow>;
473
+ }>;
474
+ /** Enable filtering for this column. Set to true for default text filter, or provide config */
475
+ filterable?: boolean | ColumnFilterConfig;
476
+ /** Enable sorting for this column. If undefined, inherits from GridDefinition.sortable */
477
+ sortable?: boolean;
478
+ /** Enable resizing for this column. If undefined, inherits from GridDefinition.resizable */
479
+ resizable?: boolean;
480
+ /** If false, column stays fixed at its width and doesn't participate in flex distribution. Default: true */
481
+ flexible?: boolean;
482
+ /** Control the header context menu. false hides it entirely. Object controls individual sections. Inherits from GridDefinition.contextMenu if undefined. */
483
+ contextMenu?: boolean | ContextMenuConfig;
484
+ }
485
+ export interface GridDefinition<TRow> {
486
+ rowKey?: KeysMatching<TRow, Key> | ((rowData: TRow) => Key);
487
+ columns: ColumnType<TRow>[];
488
+ showRowNumber?: boolean | {
489
+ pinned?: boolean;
490
+ width?: number;
491
+ };
492
+ rowSelection?: boolean | {
493
+ pinned?: boolean;
494
+ };
495
+ /**
496
+ * What Tab does from a cell. `'none'` is APG's grid and the default: the grid is a single tab stop, so
497
+ * Tab leaves it for the next control on the page and the widgets a cell holds are reached with Enter or
498
+ * F2. `'cells'` is the spreadsheet reading AG Grid ships — Tab walks to the next cell and on into the
499
+ * rows after it, and Shift+Tab walks back — which a data-entry screen wants and a page of content does
500
+ * not, since it costs the keyboard its way out of the grid.
501
+ */
502
+ tabNavigation?: 'none' | 'cells';
503
+ rowHeight?: number;
504
+ /** Number of visible rows. Set to 'all' to render all rows without virtualization or vertical scrollbar. */
505
+ visibleRowsCount?: number | 'all';
506
+ topBar?: boolean;
507
+ bottomBar?: boolean;
508
+ /** Title displayed in the top bar */
509
+ title?: React.ReactNode;
510
+ /** Custom filters or actions rendered in the top bar */
511
+ topBarContent?: React.ReactNode;
512
+ /** Enable global filter with fuzzy search */
513
+ globalFilter?: boolean;
514
+ /** Keys of columns to search in global filter. If not provided, all columns are searched */
515
+ globalFilterKeys?: (keyof TRow | Key)[];
516
+ /**
517
+ * Whether every column can be edited. Default: false — a column says so for itself, and this is the
518
+ * grid-wide default it falls back to. Individual column settings take priority.
519
+ */
520
+ editable?: boolean;
521
+ /**
522
+ * Judges an edit and is told about it, in one call: answer nothing to accept the value, or a string to
523
+ * reject it — the editor stays open, the message is shown on the cell and announced, and nothing is
524
+ * written. A promise is awaited, so a uniqueness check against a server is the same function; an answer
525
+ * to an edit the user has since abandoned is dropped.
526
+ *
527
+ * The grid does not own `data`, so an accepted value is kept as an **edit over** the rows it was given
528
+ * and is what every cell, every custom `Cell` and every export reads from then on. It does not re-sort
529
+ * or re-filter the grid — a row jumping out from under the pointer as it is typed into is not an edit
530
+ * anybody asked for — and `clearEdits()` on the grid's ref is how a host says its own data has caught up.
531
+ */
532
+ onCellEdit?: (edit: CellEdit<TRow>) => CellEditResult | Promise<CellEditResult>;
533
+ /** Enable sorting for all columns. Default is true. Individual column settings take priority. */
534
+ sortable?: boolean;
535
+ /** Enable resizing for all columns. Default is true. Individual column settings take priority. */
536
+ resizable?: boolean;
537
+ /** Controls the visual style of column resizer handles. 'visible' (default): always shown. 'hover': visible on header cell hover. 'hidden': invisible but resize still works. */
538
+ resizerStyle?: 'visible' | 'hover' | 'hidden';
539
+ /** How the column follows the pointer during a resize drag. 'smooth' (default): updates batched once per animation frame (~60fps, ~1 frame behind the cursor). 'instant': updates synchronously on every pointer move so the column tracks the cursor with no added latency. */
540
+ resizeMode?: 'smooth' | 'instant';
541
+ /** Control the header context menu for all columns. false hides it entirely. Object controls individual sections. Default: true. Individual column settings take priority. */
542
+ contextMenu?: boolean | ContextMenuConfig;
543
+ /** Custom component to render when data is empty */
544
+ noDataComponent?: React.ReactNode;
545
+ /**
546
+ * A row of grand totals pinned under the rows, over every column carrying an `aggregate`. It covers the
547
+ * rows the grid holds after filtering — which is the page, not the table, when the server is paginating.
548
+ */
549
+ footer?: boolean | {
550
+ label?: React.ReactNode;
551
+ };
552
+ /**
553
+ * Export buttons in the top bar. `true` is both formats; the writers are loaded on the first press,
554
+ * so a grid nobody exports from pays nothing for them.
555
+ */
556
+ export?: boolean | ExportConfig;
557
+ /** Enable expandable row detail panel */
558
+ rowDetail?: RowDetailConfig<TRow>;
559
+ /**
560
+ * Rows that hold rows: one column grows a chevron and an indent, and the grid reports itself as a
561
+ * `treegrid`. The tree comes out of the data, either nested in it or named by a path on each row —
562
+ * or, beside `def.dataSource`, out of the server a level at a time.
563
+ */
564
+ treeData?: TreeDataConfig<TRow>;
565
+ /**
566
+ * The columns the grid starts grouped by, outermost first — the declared half of what the column menu's
567
+ * *Group By* does, so a grid can be grouped before anybody has clicked anything (and on a server, where
568
+ * nobody can).
569
+ */
570
+ groupBy?: Key[];
571
+ /** Which group rows start open: `true` is all of them, a number is how many levels down. Default: none. */
572
+ groupDefaultExpanded?: boolean | number;
573
+ /** Server-side pagination. Provide totalCount from the API response. */
574
+ pagination?: PaginationConfig;
575
+ /**
576
+ * Where the rows come from, when the grid is to fetch them itself. Sorting, filtering and paging then
577
+ * round-trip to `getRows` instead of running over `data`, which is what lets a grid stand in front of a
578
+ * table nobody could send to a browser. With `def.pagination` beside it the block is the page; without
579
+ * it the grid scrolls the whole result set and fetches the blocks it reaches.
580
+ */
581
+ dataSource?: DataSource<TRow>;
582
+ }
583
+ /**
584
+ * The grid takes Box style props like anything else — on the element that wraps the bars, the rows and
585
+ * the pager. `component` is declared here rather than inherited so it stays the whole key union: the
586
+ * model hands it to every part, and narrowing it would mean a type parameter on all of them.
587
+ */
588
+ export interface DataGridProps<TRow> extends Omit<BoxProps<'div', 'datagrid'>, 'ref' | 'tag' | 'children' | 'component' | 'variant'> {
589
+ /** Component name for style resolution. Default: 'datagrid'. Set to a custom name to use a different component style tree. */
590
+ component?: keyof ComponentsAndVariants;
591
+ /**
592
+ * The rows. Virtualization means the length is not what is rendered — ten thousand is fine. Optional
593
+ * only because `def.dataSource` replaces it: with one set, this is not read at all.
594
+ */
595
+ data?: TRow[];
596
+ /** Everything about the grid that is not the rows: the columns, the bars, the title, the row height. */
597
+ def: GridDefinition<TRow>;
598
+ /** Show the loading sweep over the rows. The grid keeps whatever it is already showing underneath. */
599
+ loading?: boolean;
600
+ /** Fires with every selected row key and why the selection changed. */
601
+ onSelectedRowKeysChange?: ChangeHandler<Key[], DataGridSelectionReason>;
602
+ /**
603
+ * The older callback, whose event carries the keys *acted on* beside the selection. Both fire.
604
+ * @deprecated `onSelectedRowKeysChange` is the selection itself, with the `action` as a named reason —
605
+ * the spelling every component reports a change under. This one still works.
606
+ */
607
+ onSelectionChange?: (event: SelectionChangeEvent<TRow>) => void;
608
+ /** Controlled global filter value */
609
+ globalFilterValue?: string;
610
+ /** Fires with the global filter's new text, and whether it was typed or emptied. */
611
+ onGlobalFilterChange?: ChangeHandler<string, DataGridFilterReason>;
612
+ /** Controlled column filters */
613
+ columnFilters?: ColumnFilters<TRow>;
614
+ /** Fires with every column filter still set, and whether one was set or cleared. */
615
+ onColumnFiltersChange?: ChangeHandler<ColumnFilters<TRow>, DataGridFilterReason>;
616
+ /** External predicate filters applied before global/column filters. Memoize with useMemo for performance. */
617
+ filters?: ((row: TRow) => boolean)[];
618
+ /** Controlled expanded detail row keys */
619
+ expandedRowKeys?: Key[];
620
+ /** Fires with every expanded detail row key, and whether one was opened or shut. */
621
+ onExpandedRowKeysChange?: ChangeHandler<Key[], DataGridExpandReason>;
622
+ /**
623
+ * Controlled open rows of a `def.treeData` tree. A separate list from `expandedRowKeys`, which is the
624
+ * detail panels: a row can have both, and they open different things.
625
+ */
626
+ expandedTreeKeys?: Key[];
627
+ /** Fires with every open tree row's key, and whether one was opened or shut. */
628
+ onExpandedTreeKeysChange?: ChangeHandler<Key[], DataGridExpandReason>;
629
+ /** Controlled current page (1-indexed). Used with pagination. */
630
+ page?: number;
631
+ /** Controlled page size. Used with pagination and pageSizeOptions. */
632
+ pageSize?: number;
633
+ /**
634
+ * Fires with both pager values and why they changed — the page and the size move together, and a filter
635
+ * or a sort is what sends the grid back to the first page.
636
+ */
637
+ onPaginationChange?: ChangeHandler<DataGridPagination, DataGridChangeReason>;
638
+ /**
639
+ * The older page callback, whose second argument is the page size rather than the reason. Both fire.
640
+ * @deprecated `onPaginationChange` reports both pager values with a reason, which is what says whether
641
+ * the page changed because the user navigated or because a filter reset it. This one still works.
642
+ */
643
+ onPageChange?: (page: number, pageSize: number) => void;
644
+ /**
645
+ * The older page-size callback. Both fire.
646
+ * @deprecated `onPaginationChange` covers it: a new page size always returns to page 1, so the two were
647
+ * never separate changes. This one still works.
648
+ */
649
+ onPageSizeChange?: (pageSize: number) => void;
650
+ /**
651
+ * Fires with every edit the grid has accepted, oldest first — the stream an undo is built out of. It is
652
+ * the whole list rather than the one that changed, so a host keeps no history of its own, and it empties
653
+ * when `clearEdits()` says the host has saved them.
654
+ */
655
+ onCellEditsChange?: ChangeHandler<CellEdit<TRow>[], DataGridEditReason>;
656
+ /** Fires with the column and direction the grid is sorted by, or `undefined` once the sort is cleared. */
657
+ onSortingChange?: ChangeHandler<DataGridSort | undefined, DataGridSortReason>;
658
+ /**
659
+ * The older sort callback, whose two arguments are the column and the direction. Both fire.
660
+ * @deprecated `onSortingChange` reports the sort as one value with a reason beside it. This one still works.
661
+ */
662
+ onSortChange?: (columnKey: Key | undefined, direction: SortDirection | undefined) => void;
663
+ /** Fires on any server-relevant state change with the full snapshot for an API call, and what moved. */
664
+ onServerStateChange?: ChangeHandler<ServerState<TRow>, DataGridChangeReason>;
665
+ }
666
+ interface SelectionChangeEvent<TRow, TKey = TRow[keyof TRow] | number | string> {
667
+ action: 'select' | 'deselect';
668
+ selectedRowKeys: TKey[];
669
+ affectedRowKeys: TKey[];
670
+ isAllSelected: boolean;
671
+ }