@svgrid/grid 1.0.2 → 1.1.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.
Files changed (216) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +137 -39
  3. package/dist/GridFooter.svelte +164 -0
  4. package/dist/GridFooter.svelte.d.ts +29 -0
  5. package/dist/GridMenus.svelte +648 -0
  6. package/dist/GridMenus.svelte.d.ts +31 -0
  7. package/dist/SvGrid.controller.svelte.d.ts +472 -0
  8. package/dist/SvGrid.controller.svelte.js +1917 -0
  9. package/dist/SvGrid.css +2012 -0
  10. package/dist/SvGrid.helpers.d.ts +35 -0
  11. package/dist/SvGrid.helpers.js +160 -0
  12. package/dist/SvGrid.helpers.test.d.ts +1 -0
  13. package/dist/SvGrid.helpers.test.js +298 -0
  14. package/dist/SvGrid.svelte +2346 -8742
  15. package/dist/SvGrid.svelte.d.ts +4 -357
  16. package/dist/SvGrid.types.d.ts +523 -0
  17. package/dist/SvGrid.types.js +1 -0
  18. package/dist/SvGridChart.svelte +1060 -23
  19. package/dist/SvGridChart.svelte.d.ts +17 -0
  20. package/dist/aligned-grids.d.ts +6 -0
  21. package/dist/aligned-grids.js +84 -0
  22. package/dist/aligned-grids.test.d.ts +1 -0
  23. package/dist/aligned-grids.test.js +75 -0
  24. package/dist/build-api.coverage.test.d.ts +20 -0
  25. package/dist/build-api.coverage.test.js +505 -0
  26. package/dist/build-api.d.ts +5 -0
  27. package/dist/build-api.js +557 -0
  28. package/dist/cell-render.d.ts +15 -0
  29. package/dist/cell-render.js +246 -0
  30. package/dist/cell-render.test.d.ts +1 -0
  31. package/dist/cell-render.test.js +338 -0
  32. package/dist/cell-values.d.ts +28 -0
  33. package/dist/cell-values.js +89 -0
  34. package/dist/chart-export.test.d.ts +1 -0
  35. package/dist/chart-export.test.js +302 -0
  36. package/dist/chart.coverage.test.d.ts +1 -0
  37. package/dist/chart.coverage.test.js +748 -0
  38. package/dist/chart.d.ts +370 -3
  39. package/dist/chart.js +1135 -42
  40. package/dist/clipboard.d.ts +15 -0
  41. package/dist/clipboard.js +420 -0
  42. package/dist/clipboard.test.d.ts +1 -0
  43. package/dist/clipboard.test.js +700 -0
  44. package/dist/collaboration.coverage.test.d.ts +1 -0
  45. package/dist/collaboration.coverage.test.js +200 -0
  46. package/dist/column-groups.d.ts +19 -0
  47. package/dist/column-groups.js +62 -0
  48. package/dist/column-groups.test.d.ts +1 -0
  49. package/dist/column-groups.test.js +56 -0
  50. package/dist/column-types.d.ts +10 -0
  51. package/dist/column-types.js +63 -0
  52. package/dist/column-types.test.d.ts +1 -0
  53. package/dist/column-types.test.js +62 -0
  54. package/dist/columns.d.ts +30 -0
  55. package/dist/columns.js +277 -0
  56. package/dist/columns.test.d.ts +1 -0
  57. package/dist/columns.test.js +625 -0
  58. package/dist/core.d.ts +86 -1
  59. package/dist/css.d.ts +3 -0
  60. package/dist/editing.d.ts +31 -0
  61. package/dist/editing.js +529 -0
  62. package/dist/editing.test.d.ts +1 -0
  63. package/dist/editing.test.js +732 -0
  64. package/dist/editors/cell-editors.coverage.test.d.ts +1 -0
  65. package/dist/editors/cell-editors.coverage.test.js +139 -0
  66. package/dist/editors/cell-editors.d.ts +1 -1
  67. package/dist/facet-buckets.d.ts +13 -0
  68. package/dist/facet-buckets.js +54 -0
  69. package/dist/facet-buckets.test.d.ts +1 -0
  70. package/dist/facet-buckets.test.js +296 -0
  71. package/dist/features.d.ts +5 -0
  72. package/dist/features.js +30 -0
  73. package/dist/filter-operators.d.ts +16 -0
  74. package/dist/filter-operators.js +69 -0
  75. package/dist/filter-operators.test.d.ts +1 -0
  76. package/dist/filter-operators.test.js +135 -0
  77. package/dist/hyperformula-adapter.d.ts +82 -0
  78. package/dist/hyperformula-adapter.js +73 -0
  79. package/dist/hyperformula-adapter.test.d.ts +1 -0
  80. package/dist/hyperformula-adapter.test.js +205 -0
  81. package/dist/index.d.ts +9 -3
  82. package/dist/index.js +8 -2
  83. package/dist/keyboard-handlers.coverage.test.d.ts +1 -0
  84. package/dist/keyboard-handlers.coverage.test.js +495 -0
  85. package/dist/keyboard-handlers.d.ts +7 -0
  86. package/dist/keyboard-handlers.js +202 -0
  87. package/dist/menus.d.ts +40 -0
  88. package/dist/menus.js +390 -0
  89. package/dist/menus.test.d.ts +1 -0
  90. package/dist/menus.test.js +560 -0
  91. package/dist/named-views.coverage.test.d.ts +1 -0
  92. package/dist/named-views.coverage.test.js +180 -0
  93. package/dist/named-views.d.ts +27 -0
  94. package/dist/named-views.js +39 -0
  95. package/dist/row-drag.d.ts +49 -0
  96. package/dist/row-drag.js +221 -0
  97. package/dist/row-drag.test.d.ts +1 -0
  98. package/dist/row-drag.test.js +142 -0
  99. package/dist/row-resize.d.ts +43 -0
  100. package/dist/row-resize.js +158 -0
  101. package/dist/row-resize.test.d.ts +1 -0
  102. package/dist/row-resize.test.js +329 -0
  103. package/dist/scroll-sync.d.ts +9 -0
  104. package/dist/scroll-sync.js +89 -0
  105. package/dist/scroll-sync.test.d.ts +1 -0
  106. package/dist/scroll-sync.test.js +290 -0
  107. package/dist/selection.d.ts +32 -0
  108. package/dist/selection.js +427 -0
  109. package/dist/selection.multi-range.test.d.ts +1 -0
  110. package/dist/selection.multi-range.test.js +55 -0
  111. package/dist/selection.test.d.ts +1 -0
  112. package/dist/selection.test.js +647 -0
  113. package/dist/server-data-source.coverage.test.d.ts +1 -0
  114. package/dist/server-data-source.coverage.test.js +154 -0
  115. package/dist/spreadsheet.d.ts +110 -0
  116. package/dist/spreadsheet.js +242 -0
  117. package/dist/spreadsheet.test.d.ts +1 -0
  118. package/dist/spreadsheet.test.js +446 -0
  119. package/dist/summaries.d.ts +12 -0
  120. package/dist/summaries.js +65 -0
  121. package/dist/sv-grid-scrollbar.js +13 -1
  122. package/dist/svgrid-wrapper.types.d.ts +31 -1
  123. package/dist/svgrid.behavior.test.js +20 -0
  124. package/dist/svgrid.comments-autocomplete.test.d.ts +1 -0
  125. package/dist/svgrid.comments-autocomplete.test.js +96 -0
  126. package/dist/svgrid.context-menu.test.d.ts +1 -0
  127. package/dist/svgrid.context-menu.test.js +102 -0
  128. package/dist/svgrid.interaction.test.js +31 -0
  129. package/dist/svgrid.new-features.wrapper.test.js +64 -6
  130. package/dist/svgrid.wrapper.test.js +27 -1
  131. package/dist/test-setup.js +9 -3
  132. package/dist/virtualization/column-virtualizer.d.ts +2 -0
  133. package/dist/virtualization/scroll-scaling.d.ts +45 -0
  134. package/dist/virtualization/scroll-scaling.js +99 -0
  135. package/dist/virtualization/scroll-scaling.test.d.ts +1 -0
  136. package/dist/virtualization/scroll-scaling.test.js +127 -0
  137. package/dist/virtualization/svelte-virtualizer.svelte.d.ts +2 -0
  138. package/dist/virtualization/svelte-virtualizer.svelte.js +2 -0
  139. package/dist/virtualization/virtualizer.d.ts +7 -0
  140. package/dist/virtualization/virtualizer.js +30 -0
  141. package/package.json +2 -1
  142. package/src/GridFooter.svelte +164 -0
  143. package/src/GridMenus.svelte +648 -0
  144. package/src/SvGrid.controller.svelte.ts +2352 -0
  145. package/src/SvGrid.css +2012 -0
  146. package/src/SvGrid.helpers.test.ts +415 -0
  147. package/src/SvGrid.helpers.ts +185 -0
  148. package/src/SvGrid.svelte +2346 -8742
  149. package/src/SvGrid.types.ts +537 -0
  150. package/src/SvGridChart.svelte +1060 -23
  151. package/src/aligned-grids.test.ts +80 -0
  152. package/src/aligned-grids.ts +87 -0
  153. package/src/build-api.coverage.test.ts +532 -0
  154. package/src/build-api.ts +683 -0
  155. package/src/cell-render.test.ts +451 -0
  156. package/src/cell-render.ts +426 -0
  157. package/src/cell-values.ts +114 -0
  158. package/src/chart-export.test.ts +370 -0
  159. package/src/chart.coverage.test.ts +814 -0
  160. package/src/chart.ts +1352 -47
  161. package/src/clipboard.test.ts +780 -0
  162. package/src/clipboard.ts +552 -0
  163. package/src/collaboration.coverage.test.ts +220 -0
  164. package/src/column-groups.test.ts +59 -0
  165. package/src/column-groups.ts +80 -0
  166. package/src/column-types.test.ts +68 -0
  167. package/src/column-types.ts +82 -0
  168. package/src/columns.test.ts +702 -0
  169. package/src/columns.ts +419 -0
  170. package/src/core.ts +86 -0
  171. package/src/css.d.ts +3 -0
  172. package/src/editing.test.ts +837 -0
  173. package/src/editing.ts +669 -0
  174. package/src/editors/cell-editors.coverage.test.ts +156 -0
  175. package/src/editors/cell-editors.ts +1 -0
  176. package/src/facet-buckets.test.ts +353 -0
  177. package/src/facet-buckets.ts +67 -0
  178. package/src/features.ts +128 -0
  179. package/src/filter-operators.test.ts +174 -0
  180. package/src/filter-operators.ts +87 -0
  181. package/src/hyperformula-adapter.test.ts +256 -0
  182. package/src/hyperformula-adapter.ts +124 -0
  183. package/src/index.ts +49 -0
  184. package/src/keyboard-handlers.coverage.test.ts +560 -0
  185. package/src/keyboard-handlers.ts +353 -0
  186. package/src/keyboard.ts +97 -97
  187. package/src/menus.test.ts +620 -0
  188. package/src/menus.ts +555 -0
  189. package/src/named-views.coverage.test.ts +210 -0
  190. package/src/named-views.ts +48 -0
  191. package/src/row-drag.test.ts +168 -0
  192. package/src/row-drag.ts +255 -0
  193. package/src/row-resize.test.ts +369 -0
  194. package/src/row-resize.ts +171 -0
  195. package/src/scroll-sync.test.ts +330 -0
  196. package/src/scroll-sync.ts +218 -0
  197. package/src/selection.multi-range.test.ts +61 -0
  198. package/src/selection.test.ts +722 -0
  199. package/src/selection.ts +579 -0
  200. package/src/server-data-source.coverage.test.ts +180 -0
  201. package/src/spreadsheet.test.ts +489 -0
  202. package/src/spreadsheet.ts +304 -0
  203. package/src/summaries.ts +204 -0
  204. package/src/sv-grid-scrollbar.ts +13 -1
  205. package/src/svgrid-wrapper.types.ts +31 -1
  206. package/src/svgrid.behavior.test.ts +22 -0
  207. package/src/svgrid.comments-autocomplete.test.ts +112 -0
  208. package/src/svgrid.context-menu.test.ts +126 -0
  209. package/src/svgrid.interaction.test.ts +30 -0
  210. package/src/svgrid.new-features.wrapper.test.ts +67 -6
  211. package/src/svgrid.wrapper.test.ts +27 -1
  212. package/src/test-setup.ts +9 -6
  213. package/src/virtualization/scroll-scaling.test.ts +148 -0
  214. package/src/virtualization/scroll-scaling.ts +121 -0
  215. package/src/virtualization/svelte-virtualizer.svelte.ts +2 -0
  216. package/src/virtualization/virtualizer.ts +26 -0
@@ -0,0 +1,537 @@
1
+ // Type definitions extracted from SvGrid.svelte. These are compile-time
2
+ // only - moving them out keeps the component's <script> focused on logic.
3
+ import type { Snippet } from "svelte";
4
+ import type {
5
+ CellEditorType,
6
+ ColumnDef,
7
+ RowData,
8
+ SvGridApi,
9
+ TableFeatures,
10
+ } from "./index";
11
+ import type { ConditionalFormat } from "./conditional-formatting";
12
+
13
+ /** The cell a context menu was opened on. Passed to every item's callbacks. */
14
+ export type ContextMenuTarget<TData extends RowData = RowData> = {
15
+ rowIndex: number;
16
+ colIndex: number;
17
+ columnId: string;
18
+ /** Stable row id (from getRowId / row model), for keying notes etc. */
19
+ rowId: string;
20
+ row: TData | null;
21
+ };
22
+
23
+ /**
24
+ * A context-menu entry. Either a built-in action key, the `"separator"`
25
+ * divider, or a custom item. Built-in keys: `"copy" | "cut" | "paste" |
26
+ * "clear" | "row_above" | "row_below" | "remove_row" | "remove_col"`.
27
+ */
28
+ export type ContextMenuItem<TData extends RowData = RowData> =
29
+ | string
30
+ | {
31
+ key: string;
32
+ label: string;
33
+ /** Hide the item entirely for this target. */
34
+ hidden?: (target: ContextMenuTarget<TData>) => boolean;
35
+ /** Render the item greyed-out and non-clickable for this target. */
36
+ disabled?: (target: ContextMenuTarget<TData>) => boolean;
37
+ /** Invoked on click. The menu closes afterwards. */
38
+ action: (target: ContextMenuTarget<TData>) => void;
39
+ };
40
+
41
+ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends RowData = RowData> = {
42
+ data: ReadonlyArray<TData>;
43
+ columns: Array<ColumnDef<TFeatures, TData>>;
44
+ /**
45
+ * Right-click context menu. `true` shows the default item set (copy, cut,
46
+ * paste, clear, insert row above/below, remove row, remove column). Pass an
47
+ * array to customize: strings are built-in keys, `"separator"` is a divider,
48
+ * and objects are custom items. Omitted/`false` disables the menu (native
49
+ * browser menu shows instead).
50
+ */
51
+ contextMenu?: boolean | ReadonlyArray<ContextMenuItem<TData>>;
52
+ /**
53
+ * The feature set built with `tableFeatures({ ... })`. Optional - the
54
+ * `sortable` / `filterable` / `groupable` shortcuts below inject the
55
+ * matching feature for you, so a grid can be configured entirely from
56
+ * the boolean shortcuts without importing the feature constants.
57
+ */
58
+ features?: TFeatures;
59
+ /**
60
+ * Convenience shortcuts to switch a whole capability on without wiring
61
+ * `features` or the finer-grained props by hand. Every capability is OFF
62
+ * by default - a bare grid is a plain read-only table - so set the
63
+ * shortcut `true` to opt in. (`false` / omitted both leave it off; the
64
+ * shortcut is mainly there to turn things ON.)
65
+ *
66
+ * `sortable` - column sorting (injects `rowSortingFeature`)
67
+ * `filterable` - column filtering (injects `columnFilteringFeature`)
68
+ * `editable` - inline cell editing (alias of `enableInlineEditing`)
69
+ * `groupable` - row grouping controls(alias of `showGroupingControls`,
70
+ * also injects `columnGroupingFeature`)
71
+ * `pageable` - pagination footer (alias of `showPagination`)
72
+ *
73
+ * Fine-grained props (`enableInlineEditing`, `showPagination`, ...) still
74
+ * work; the shortcut wins only when it is explicitly set.
75
+ */
76
+ sortable?: boolean;
77
+ filterable?: boolean;
78
+ editable?: boolean;
79
+ groupable?: boolean;
80
+ pageable?: boolean;
81
+ loading?: boolean;
82
+ /**
83
+ * Render `loading` as a non-blocking overlay instead of replacing the
84
+ * whole grid: the current rows stay visible (dimmed, with a top progress
85
+ * bar) during a refetch, and the first load shows shimmer skeleton rows.
86
+ * Ideal for server-paged grids so paging/sorting doesn't flash. Defaults
87
+ * to `false` (the classic full "Loading..." replacement).
88
+ */
89
+ loadingOverlay?: boolean;
90
+ /** Skeleton placeholder rows to show on first load. Defaults to 8. */
91
+ loadingSkeletonRows?: number;
92
+ error?: string | null;
93
+ emptyMessage?: string;
94
+ showGlobalFilter?: boolean;
95
+ showColumnFilters?: boolean;
96
+ /**
97
+ * Quick way to pick a single filtering UI. When set it controls which of
98
+ * the three filter surfaces appears (and is overridden per-surface by the
99
+ * `showGlobalFilter` / `showColumnFilters` / `showFilterRow` props).
100
+ * Defaults to `'menu'` (only the column menu's filter section is shown).
101
+ */
102
+ filterMode?: "row" | "menu" | "global" | "none";
103
+ showGroupingControls?: boolean;
104
+ showRowSelection?: boolean;
105
+ showPagination?: boolean;
106
+ /** Initial page size when pagination is enabled. Defaults to 10. */
107
+ pageSize?: number;
108
+ virtualization?: boolean;
109
+ /** Row height in pixels. Pass a function `(rowIndex) => px` for
110
+ * per-row variable heights (e.g. an interactive row-resize feature).
111
+ * Defaults to 30. */
112
+ rowHeight?: number | ((rowIndex: number) => number);
113
+ /**
114
+ * Height (px) of a single column-header level row. With multi-level
115
+ * (grouped) headers the total header height is `levels * headerHeight`,
116
+ * since each level renders as its own row. When omitted, header rows size
117
+ * to their content (the default). Does not affect the filter row.
118
+ */
119
+ headerHeight?: number;
120
+ overscan?: number;
121
+ /**
122
+ * Height of the grid's scrollable shell. A number is treated as pixels;
123
+ * a string is used as-is, so callers can pass `'100%'` or `'auto'` to
124
+ * make the grid fill its parent. Defaults to 520 px.
125
+ */
126
+ containerHeight?: number | string;
127
+ columnVirtualization?: boolean;
128
+ columnOverscan?: number;
129
+ columnWidth?: number;
130
+ /**
131
+ * Columns pinned to the left/right edge on mount. Each entry is a
132
+ * column id (matches `ColumnDef.field` when no explicit id is set).
133
+ * The internal pinning state is seeded once at mount; user-driven
134
+ * pinning via the column menu still works and overrides this default.
135
+ * Requires `columnVirtualization={false}` to be visible in the menu
136
+ * UI (sticky positioning can't co-exist with column virtualization
137
+ * since the virtualizer recycles DOM nodes).
138
+ */
139
+ initialColumnPinning?: {
140
+ left?: ReadonlyArray<string>;
141
+ right?: ReadonlyArray<string>;
142
+ };
143
+ /**
144
+ * When `true`, columns are scaled proportionally so their total width
145
+ * fills the viewport (no empty space on the right). Disabled by
146
+ * default - explicit `width` values are used as-is. User resizes still
147
+ * win once they happen.
148
+ */
149
+ fitColumns?: boolean;
150
+ showFilterMenu?: boolean;
151
+ showFilterRow?: boolean;
152
+ enableCellSelection?: boolean;
153
+ /**
154
+ * Prepend a header row (the column labels) to copied cell ranges, so pasting
155
+ * into Excel / Sheets includes the headers. Applies per copied range.
156
+ */
157
+ copyHeadersToClipboard?: boolean;
158
+ /**
159
+ * Transform each cell value on its way to the clipboard - e.g. strip
160
+ * currency symbols, expand codes to labels, or redact. Receives the display
161
+ * value plus the row/column context; return the string (or value) to copy.
162
+ */
163
+ processCellForClipboard?: (params: {
164
+ value: unknown;
165
+ column: unknown;
166
+ row: TData;
167
+ rowIndex: number;
168
+ columnId: string;
169
+ }) => unknown;
170
+ enableInlineEditing?: boolean;
171
+ /**
172
+ * Full-row editing. When `true`, starting an edit puts the WHOLE row into
173
+ * edit mode - every editable cell shows an inline editor at once - and a
174
+ * single Enter (or focus leaving the row) commits all of them; Esc cancels
175
+ * the whole row. Requires `enableInlineEditing`. The full-row editor covers
176
+ * text / number / date / datetime / checkbox / list-select editor types.
177
+ */
178
+ fullRowEditing?: boolean;
179
+ enableRowSummaries?: boolean;
180
+ /**
181
+ * Excel-style status bar under the grid showing live aggregates of the
182
+ * selected cell range (count, numeric count, sum, average, min, max).
183
+ * `true` shows the default set; pass `{ aggregates: [...] }` to choose
184
+ * which. Requires `enableCellSelection`.
185
+ */
186
+ statusBar?:
187
+ | boolean
188
+ | {
189
+ aggregates?: ReadonlyArray<
190
+ "count" | "numericCount" | "sum" | "avg" | "min" | "max"
191
+ >;
192
+ };
193
+ /**
194
+ * Show the docked tool panel - the enterprise sidebar with Columns and
195
+ * Filters tabs. A "Columns & Filters" button appears in a toolbar above the
196
+ * grid; the panel docks on the right edge.
197
+ */
198
+ toolPanel?: boolean;
199
+ /**
200
+ * Render the header column menu (⋮) as a tabbed popover - **General**,
201
+ * **Filter**, and **Columns** tabs (the AG-Grid layout). Defaults to `false`,
202
+ * which keeps the flat menu (actions list + "Choose columns" submenu).
203
+ */
204
+ columnMenuTabs?: boolean;
205
+ /** Open the tool panel on first render (instead of collapsed). */
206
+ toolPanelDefaultOpen?: boolean;
207
+ /** Which tab the tool panel starts on. Defaults to `'columns'`. */
208
+ toolPanelDefaultTab?: "columns" | "filters";
209
+ /**
210
+ * Quick way to pick which selection surfaces are active. `'row'` shows the
211
+ * selection checkbox column only, `'cell'` allows rectangle/range cell
212
+ * selection only, `'both'` (default) enables both, `'none'` disables both.
213
+ * Overridden per-surface by `showRowSelection` / `enableCellSelection`.
214
+ */
215
+ selectionMode?: "row" | "cell" | "both" | "none";
216
+ /**
217
+ * Render a leading row-number column (1-based) before any selection
218
+ * column. Useful as a permanent anchor when scrolling wide grids.
219
+ */
220
+ showRowNumbers?: boolean;
221
+ /**
222
+ * Paint alternating data rows with the `--sg-row-alt-bg` color (zebra
223
+ * striping). Only data rows stripe - pinned, group, detail, and summary
224
+ * rows keep their single background. Defaults to `false`.
225
+ */
226
+ zebraRows?: boolean;
227
+ /**
228
+ * Width (px) of the row-number column. Defaults to 56, which fits up
229
+ * to "99,999"; bump this when the dataset crosses six digits so the
230
+ * largest row number stays fully visible at the bottom of a scroll.
231
+ */
232
+ rowNumberWidth?: number;
233
+ /** Receives the imperative grid API once the component has mounted. */
234
+ onApiReady?: (api: SvGridApi<TFeatures, TData>) => void;
235
+ /**
236
+ * Fires whenever the row-selection state changes. The first argument
237
+ * is the new selection record `{ [rowId]: true }`; the second is the
238
+ * array of selected `TData` rows.
239
+ */
240
+ onRowSelectionChange?: (
241
+ selection: Record<string, boolean>,
242
+ rows: TData[],
243
+ ) => void;
244
+ /**
245
+ * Fires whenever the cell-selection rectangle changes (mouse, keyboard,
246
+ * or `api.selectCells()`). `ranges` matches `api.getSelected()` -
247
+ * `[rowStart, colStart, rowEnd, colEnd]` rectangles in grid coords.
248
+ * Empty array when the user clears the selection.
249
+ */
250
+ onCellSelectionChange?: (
251
+ ranges: Array<[number, number, number, number]>,
252
+ ) => void;
253
+ /**
254
+ * When `true`, the grid records sort state (and renders sort indicators
255
+ * + cycling on headers) but does NOT actually re-order the rows. The
256
+ * consumer is expected to sort `data` themselves - typically via
257
+ * `onSortingChange`. Use this for tree/hierarchical data, where a flat
258
+ * global sort would break parent-child adjacency. Defaults to `false`.
259
+ */
260
+ externalSort?: boolean;
261
+ /**
262
+ * Fires whenever the sort clauses change. Receives the new array of
263
+ * `{ id, desc }` entries. Pair with `externalSort={true}` when the
264
+ * consumer wants to own the row ordering.
265
+ */
266
+ onSortingChange?: (sorting: Array<{ id: string; desc: boolean }>) => void;
267
+ /**
268
+ * When `true`, the grid still records column-filter / global-filter /
269
+ * facet state (so the menu UI works and indicators light up) but does
270
+ * NOT actually filter the rows. The consumer is expected to fetch / sort
271
+ * / filter the data themselves - typically via `onFiltersChange`. Used
272
+ * by server-side data sources. Defaults to `false`.
273
+ */
274
+ externalFilter?: boolean;
275
+ /**
276
+ * Fires whenever any of the in-grid filter state changes - global
277
+ * search, per-column operator filters, or facet (value-checklist)
278
+ * filters. Pair with `externalFilter={true}` when the consumer wants to
279
+ * push the query to the server.
280
+ */
281
+ onFiltersChange?: (filters: {
282
+ global: string;
283
+ columns: Array<{
284
+ id: string;
285
+ operator: FilterOperator;
286
+ value: string;
287
+ /**
288
+ * Upper bound for the `between` operator. Only set when
289
+ * `operator === 'between'` AND the user has typed both values.
290
+ */
291
+ valueTo?: string;
292
+ selectedValues?: Array<string>;
293
+ }>;
294
+ }) => void;
295
+ /**
296
+ * Fires when an inline edit is committed (Enter / Tab / blur). Useful
297
+ * for cascade-recompute pipelines: a parent listens, then refreshes
298
+ * derived columns or aggregates. The wrapper has already written the
299
+ * parsed value back into the row by the time this fires.
300
+ */
301
+ /**
302
+ * Resolve a stable id per row. Drives selection, expansion, edit,
303
+ * and active-cell state. When omitted, the row's array index is
304
+ * used - fine for read-only views but the wrong choice if `data`
305
+ * gets reordered or filtered outside the grid (selection would
306
+ * follow positions, not actual rows). Use a database PK, a UUID,
307
+ * or any stable string.
308
+ */
309
+ getRowId?: (row: TData, index: number) => string;
310
+ /**
311
+ * Conditional class(es) added to every `<tr>` body row. Receives
312
+ * the row's `original` data + its data-array index. Return a
313
+ * string, an array of strings, or an object mapping class names to
314
+ * booleans. Useful for "highlight overdue rows", "tint cancelled
315
+ * orders", and similar row-level state mappings.
316
+ */
317
+ rowClass?: (ctx: {
318
+ row: TData;
319
+ rowIndex: number;
320
+ }) => string | ReadonlyArray<string> | Record<string, boolean> | undefined | null;
321
+ /**
322
+ * Per-cell notes - longer free-form comments shown as a corner
323
+ * indicator + tooltip on hover. Keyed by row id then column id;
324
+ * empty / missing entries mean "no note". The grid owns rendering;
325
+ * you own storage (write your own callbacks to add / edit notes).
326
+ */
327
+ notes?: Record<string, Record<string, string>>;
328
+ /**
329
+ * Allow editing per-cell notes/comments through the UI: the context menu
330
+ * gains an "Edit comment" item that opens a popover editor. Edits are
331
+ * applied to an internal overlay for immediate feedback and emitted via
332
+ * `onNoteChange` so you can persist them back into `notes`.
333
+ */
334
+ editableComments?: boolean;
335
+ /** Fires when a comment is saved or removed (removed = empty `note`). */
336
+ onNoteChange?: (event: { rowId: string; columnId: string; note: string }) => void;
337
+ /**
338
+ * Excel-style conditional formatting. A list of value-driven rules that
339
+ * color cells: `colorScale` (gradient across the column range),
340
+ * `dataBar` (in-cell proportional bar), `iconSet` (arrows / traffic /
341
+ * triangles by threshold), and `rule` (apply a style when a predicate
342
+ * matches). Scope a format to specific columns with `columns: [...]`,
343
+ * or omit it to apply to every column. Later entries win on conflict.
344
+ */
345
+ conditionalFormats?: ReadonlyArray<ConditionalFormat<TData>>;
346
+ onCellValueChange?: (event: {
347
+ rowIndex: number;
348
+ columnId: string;
349
+ oldValue: unknown;
350
+ newValue: unknown;
351
+ row: TData;
352
+ }) => void;
353
+ /**
354
+ * Fires whenever the active cell changes - click, keyboard move,
355
+ * tab, page-up/down, etc. Consumers (toolbars, ribbon UIs) use this
356
+ * to stay synced with the grid's selection without polling the DOM.
357
+ */
358
+ onActiveCellChange?: (cell: {
359
+ rowIndex: number;
360
+ colIndex: number;
361
+ columnId: string;
362
+ }) => void;
363
+ /**
364
+ * Fires when a data cell (and therefore a row) is single-clicked.
365
+ * Group-header rows are excluded. `value` is the displayed cell value.
366
+ */
367
+ onCellClick?: (event: {
368
+ rowIndex: number;
369
+ colIndex: number;
370
+ columnId: string;
371
+ value: unknown;
372
+ row: TData;
373
+ }) => void;
374
+ /** Fires when a data row is single-clicked (any cell). Group rows excluded. */
375
+ onRowClick?: (event: {
376
+ rowIndex: number;
377
+ columnId: string;
378
+ row: TData;
379
+ }) => void;
380
+ /**
381
+ * Fires when a data cell is double-clicked - independent of whether the
382
+ * cell is editable, so it fires even on read-only grids. Group rows excluded.
383
+ */
384
+ onCellDoubleClick?: (event: {
385
+ rowIndex: number;
386
+ colIndex: number;
387
+ columnId: string;
388
+ value: unknown;
389
+ row: TData;
390
+ }) => void;
391
+ /** Fires when a data row is double-clicked (any cell). Group rows excluded. */
392
+ onRowDoubleClick?: (event: {
393
+ rowIndex: number;
394
+ columnId: string;
395
+ row: TData;
396
+ }) => void;
397
+ /**
398
+ * Fires once each time the body is scrolled to (within ~32px of) the
399
+ * bottom. Re-arms after the user scrolls back up. The canonical hook for
400
+ * infinite / lazy loading - append more rows to `data` when it fires.
401
+ */
402
+ onScrollBottomReached?: (event: {
403
+ scrollTop: number;
404
+ scrollHeight: number;
405
+ clientHeight: number;
406
+ }) => void;
407
+ /**
408
+ * Marks a row as an expandable "detail row". When this returns true the
409
+ * grid renders that row as a SINGLE full-width cell (colspan across every
410
+ * column) using `renderDetailRow`, instead of the normal per-column cells
411
+ * - the canonical Stripe / GitHub "expand a rich panel beneath the row"
412
+ * pattern. Insert the detail rows into `data` yourself (typically right
413
+ * after the row they belong to) and toggle them with your own expanded
414
+ * state. Pair with `virtualization={false}` so the variable-height detail
415
+ * isn't clipped by the fixed-row-height virtualizer.
416
+ */
417
+ isDetailRow?: (row: TData, rowIndex: number) => boolean;
418
+ /**
419
+ * Snippet rendered inside the full-width detail cell for rows where
420
+ * `isDetailRow` is true. Receives the row's data and its index.
421
+ */
422
+ renderDetailRow?: Snippet<[{ row: TData; rowIndex: number }]>;
423
+ /**
424
+ * Rows to pin to the TOP of the grid - rendered above the regular
425
+ * rows and sticky-positioned so they stay visible while the user
426
+ * scrolls. Typical use: a "totals" or "headline" row that should
427
+ * always be in view. Rows are read-only (no inline editing, no
428
+ * row-selection checkbox). They share the column schema with the
429
+ * main grid; field/format/cell/cellClass all apply.
430
+ */
431
+ pinnedTopRows?: ReadonlyArray<TData>;
432
+ /**
433
+ * Rows to pin to the BOTTOM of the grid - rendered below the regular
434
+ * rows and sticky-positioned (sticks to the bottom of the viewport
435
+ * while the user scrolls). Typical use: a "page totals" or "grand
436
+ * total" row computed from `getDisplayedRows()`.
437
+ */
438
+ pinnedBottomRows?: ReadonlyArray<TData>;
439
+ /**
440
+ * Enables drag-to-reorder on the grid's column headers. When `true`,
441
+ * every header gets `draggable=true` and a drop indicator paints
442
+ * between headers during a drag. On drop the grid mutates its
443
+ * internal column order and fires `onColumnOrderChange` with the
444
+ * new order. Defaults to `false`.
445
+ */
446
+ enableColumnReorder?: boolean;
447
+ /**
448
+ * Initial column order, by `id` (falls back to `field`). When the
449
+ * user reorders columns, this is the starting state. After mount,
450
+ * the grid owns the order internally and emits `onColumnOrderChange`
451
+ * on every change - persist that to `localStorage` to restore.
452
+ */
453
+ columnOrder?: ReadonlyArray<string>;
454
+ /** Fires every time the column order changes (drag or `api.setColumnOrder`). */
455
+ onColumnOrderChange?: (order: ReadonlyArray<string>) => void;
456
+ /**
457
+ * Infer each column's data type (number / boolean / date / ISO date-string /
458
+ * text) from the first data row, for columns that declare neither an
459
+ * explicit `editorType` nor a `cellDataType`. Sets the matching editor,
460
+ * alignment, date format, and filter operators automatically. Explicit
461
+ * column config always wins. Defaults to `false`.
462
+ */
463
+ inferColumnTypes?: boolean;
464
+ /**
465
+ * Enables managed row dragging. When `true`, every row becomes a drag
466
+ * source (grab cursor + a grip in the row-number cell) and a drop
467
+ * indicator paints between rows during a drag. On drop the grid mutates
468
+ * its own internal data - reordering within the grid, or moving the row
469
+ * across grids that share the same {@link rowDragGroup}. Defaults to
470
+ * `false`.
471
+ */
472
+ rowDragManaged?: boolean;
473
+ /**
474
+ * Connection group for cross-grid row dragging. Grids that share the same
475
+ * non-empty `rowDragGroup` string (and have `rowDragManaged` on) can
476
+ * exchange rows: dragging a row out of one and dropping it into another
477
+ * removes it from the source and inserts it into the target. Omit to keep
478
+ * dragging confined to reordering within a single grid.
479
+ */
480
+ rowDragGroup?: string;
481
+ /**
482
+ * Fires on the TARGET grid after a managed row drag settles, with the
483
+ * moved row, its landing index, whether it stayed in the same grid, and
484
+ * the source / target grid ids. Use it to mirror the move into your own
485
+ * state (persistence, server sync). The grid has already applied the
486
+ * change to its internal data by the time this fires.
487
+ */
488
+ onRowDragEnd?: (event: {
489
+ row: TData;
490
+ toIndex: number;
491
+ sameGrid: boolean;
492
+ fromGridId: number;
493
+ toGridId: number;
494
+ }) => void;
495
+ /**
496
+ * Align this grid with others that share the same non-empty
497
+ * `alignedGridGroup` string: horizontal scroll and column-resize widths are
498
+ * kept in lockstep across every grid in the group. Use for a totals/header
499
+ * grid above a body grid, or side-by-side comparison grids that must line up.
500
+ * The grids should declare the same columns (matched by id) for widths to map.
501
+ */
502
+ alignedGridGroup?: string;
503
+ /**
504
+ * BCP-47 locale tag (or array of fallbacks) used for accent- and
505
+ * case-insensitive text filtering / sorting / search. Powered by
506
+ * `Intl.Collator` with `sensitivity: 'base'`, so "cafe", "Café"
507
+ * and "CAFÉ" all match "cafe" without strain. Defaults to the
508
+ * browser's locale.
509
+ */
510
+ filterLocale?: string | ReadonlyArray<string>;
511
+ };
512
+
513
+ export type SelectionPoint = { rowIndex: number; colIndex: number };
514
+ export type SelectionRange = {
515
+ anchor: SelectionPoint | null;
516
+ focus: SelectionPoint | null;
517
+ };
518
+ export type CellEditState = {
519
+ rowId: string;
520
+ columnId: string;
521
+ editorType: CellEditorType;
522
+ value: unknown;
523
+ } | null;
524
+ export type FilterOperator =
525
+ | "contains"
526
+ | "equals"
527
+ | "startsWith"
528
+ | "greaterThan"
529
+ | "lessThan"
530
+ | "between"
531
+ | "isBlank";
532
+ export type FilterOption = {
533
+ value: FilterOperator;
534
+ label: string;
535
+ iconName: string;
536
+ };
537
+ export type MenuPosition = { x: number; y: number };