@svgrid/grid 2.6.19 → 2.6.21

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 (65) hide show
  1. package/dist/SvGrid.controller.svelte.d.ts +1 -0
  2. package/dist/SvGrid.controller.svelte.js +64 -2
  3. package/dist/SvGrid.svelte +2 -1
  4. package/dist/SvGrid.types.d.ts +150 -0
  5. package/dist/ai.d.ts +28 -0
  6. package/dist/ai.js +6 -0
  7. package/dist/cdn/{GridMenus-B0F9iBrG.js → GridMenus-BfTAKn84.js} +1 -1
  8. package/dist/cdn/{GridMenus-IHK_l7m6.js → GridMenus-C3bJd7w8.js} +1 -1
  9. package/dist/cdn/{src-Cd0tearp.js → src-BYq-qyrp.js} +1012 -999
  10. package/dist/cdn/{src-B1TdiyS8.js → src-DBel9wRZ.js} +1324 -1311
  11. package/dist/cdn/svgrid.js +1 -1
  12. package/dist/cdn/svgrid.svelte-external.js +1 -1
  13. package/dist/cdn/validate-_CDJzgIo.js +75 -0
  14. package/dist/cell-formatting.d.ts +2 -0
  15. package/dist/cell-formatting.js +2 -0
  16. package/dist/chart-export.d.ts +1 -0
  17. package/dist/chart.d.ts +31 -5
  18. package/dist/chart.js +9 -3
  19. package/dist/core.d.ts +197 -0
  20. package/dist/core.js +72 -0
  21. package/dist/createTree.svelte.d.ts +3 -0
  22. package/dist/createTree.svelte.js +1 -0
  23. package/dist/datetime/date-core.d.ts +2 -0
  24. package/dist/datetime/date-restrict.d.ts +1 -0
  25. package/dist/datetime/timezone.d.ts +1 -0
  26. package/dist/dock-manager-model.d.ts +3 -0
  27. package/dist/dock-manager-model.js +1 -0
  28. package/dist/dock-model.d.ts +6 -0
  29. package/dist/dock-model.js +3 -0
  30. package/dist/editor-contract.d.ts +1 -0
  31. package/dist/list-option.d.ts +1 -0
  32. package/dist/positioning.d.ts +2 -0
  33. package/dist/scheduler-ical.d.ts +1 -0
  34. package/dist/scheduler-model.d.ts +1 -0
  35. package/dist/summaries.js +22 -0
  36. package/dist/svgrid-wrapper.types.d.ts +5 -0
  37. package/dist/toast-store.svelte.d.ts +4 -0
  38. package/dist/validate.d.ts +50 -0
  39. package/dist/validate.js +187 -0
  40. package/package.json +4 -1
  41. package/src/SvGrid.controller.svelte.ts +68 -2
  42. package/src/SvGrid.svelte +2 -1
  43. package/src/SvGrid.types.ts +150 -0
  44. package/src/ai.ts +28 -0
  45. package/src/cell-formatting.ts +2 -0
  46. package/src/chart-export.ts +1 -0
  47. package/src/chart.ts +31 -5
  48. package/src/core.ts +207 -0
  49. package/src/createTree.svelte.ts +3 -0
  50. package/src/datetime/date-core.ts +2 -0
  51. package/src/datetime/date-restrict.ts +1 -0
  52. package/src/datetime/timezone.ts +1 -0
  53. package/src/dock-manager-model.ts +3 -0
  54. package/src/dock-model.ts +6 -0
  55. package/src/editor-contract.ts +1 -0
  56. package/src/list-option.ts +1 -0
  57. package/src/positioning.ts +2 -0
  58. package/src/scheduler-ical.ts +1 -0
  59. package/src/scheduler-model.ts +1 -0
  60. package/src/summaries.ts +21 -0
  61. package/src/svgrid-wrapper.types.ts +5 -0
  62. package/src/svgrid.summaries.test.ts +217 -0
  63. package/src/toast-store.svelte.ts +4 -0
  64. package/src/validate.test.ts +207 -0
  65. package/src/validate.ts +269 -0
@@ -1029,7 +1029,21 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1029
1029
  * work; the shortcut wins only when it is explicitly set.
1030
1030
  */
1031
1031
  sortable?: boolean;
1032
+ /**
1033
+ * Click a header to filter that column. Injects `columnFilteringFeature`,
1034
+ * so you do not import it yourself. Which filter surface appears is a
1035
+ * separate question - see `filterMode` (default `'menu'`).
1036
+ *
1037
+ * <SvGrid {data} {columns} filterable />
1038
+ */
1032
1039
  filterable?: boolean;
1040
+ /**
1041
+ * Inline cell editing. Alias of `enableInlineEditing`, and wins over it when
1042
+ * both are set. A column also needs an `editorType` to be editable; without
1043
+ * one it falls back to a text editor.
1044
+ *
1045
+ * <SvGrid {data} {columns} editable />
1046
+ */
1033
1047
  editable?: boolean;
1034
1048
  /**
1035
1049
  * Cell selection - click a cell to select it, drag or shift-click to extend
@@ -1081,6 +1095,16 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1081
1095
  /** Indent per depth level, in px. Default `12`. */
1082
1096
  indentPx?: number;
1083
1097
  };
1098
+ /**
1099
+ * Show the grouping controls: "Group by this column" in the column menu, and
1100
+ * the group panel when `showGroupPanel` is on. Alias of
1101
+ * `showGroupingControls`, and also injects `columnGroupingFeature`.
1102
+ *
1103
+ * This turns on the UI for grouping. To group without asking the user, set
1104
+ * `groupBy` instead.
1105
+ *
1106
+ * <SvGrid {data} {columns} groupable />
1107
+ */
1084
1108
  groupable?: boolean;
1085
1109
  /**
1086
1110
  * Group the rows by these column ids, outermost first - `['region',
@@ -1158,7 +1182,19 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1158
1182
  autoGroupColumnHeader?: string;
1159
1183
  /** Width (px) of each auto-group column. Default `220`. */
1160
1184
  autoGroupColumnWidth?: number;
1185
+ /**
1186
+ * Show the pagination footer. Alias of `showPagination`, and wins over it
1187
+ * when both are set. Page size starts at `pageSize` (default 10).
1188
+ *
1189
+ * <SvGrid {data} {columns} pageable pageSize={25} />
1190
+ */
1161
1191
  pageable?: boolean;
1192
+ /**
1193
+ * Show the loading state instead of the rows. By default this replaces the
1194
+ * grid body with "Loading..."; set `loadingOverlay` to keep the current rows
1195
+ * visible under a dimmed overlay instead, which is what you usually want for
1196
+ * a server-paged grid.
1197
+ */
1162
1198
  loading?: boolean;
1163
1199
  /**
1164
1200
  * Render `loading` as a non-blocking overlay instead of replacing the
@@ -1170,7 +1206,16 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1170
1206
  loadingOverlay?: boolean;
1171
1207
  /** Skeleton placeholder rows to show on first load. Defaults to 8. */
1172
1208
  loadingSkeletonRows?: number;
1209
+ /**
1210
+ * Render an error message in place of the rows. `null` or omitted means no
1211
+ * error. Takes precedence over `loading` and over the empty state.
1212
+ */
1173
1213
  error?: string | null;
1214
+ /**
1215
+ * Text shown when there are no rows to display - either the data is empty or
1216
+ * a filter matched nothing. Defaults to the localized `noRows` string, so
1217
+ * prefer `localization.text.noRows` when you are translating the whole grid.
1218
+ */
1174
1219
  emptyMessage?: string;
1175
1220
  /**
1176
1221
  * The single place to localize the grid. One object with two fields:
@@ -1190,7 +1235,21 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1190
1235
  * Omitting it (or any field) is a no-op. See {@link GridMessages}.
1191
1236
  */
1192
1237
  localization?: GridLocalization;
1238
+ /**
1239
+ * Show the single search box that filters across every column. Explicitly
1240
+ * setting this wins over `filterMode`; leaving it unset means it appears only
1241
+ * when `filterMode` is `'global'`.
1242
+ */
1193
1243
  showGlobalFilter?: boolean;
1244
+ /**
1245
+ * Show the filter section inside each column's menu. Explicitly setting this
1246
+ * wins over `filterMode`; unset, it follows `filterMode` (default `'menu'`,
1247
+ * so this is normally on).
1248
+ *
1249
+ * Setting it `true` also adds the inline "floating filter" input under each
1250
+ * header - that surface requires the explicit opt-in, since it otherwise
1251
+ * duplicates the menu's own filter popover.
1252
+ */
1194
1253
  showColumnFilters?: boolean;
1195
1254
  /**
1196
1255
  * Quick way to pick a single filtering UI. When set it controls which of
@@ -1199,8 +1258,23 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1199
1258
  * Defaults to `'menu'` (only the column menu's filter section is shown).
1200
1259
  */
1201
1260
  filterMode?: "row" | "menu" | "global" | "none";
1261
+ /**
1262
+ * Show the grouping affordances (the column menu's "Group by this column",
1263
+ * and the group panel). The `groupable` shortcut sets this and registers the
1264
+ * grouping feature in one go; prefer that unless you have already registered
1265
+ * `columnGroupingFeature` yourself.
1266
+ */
1202
1267
  showGroupingControls?: boolean;
1268
+ /**
1269
+ * Show the row-selection checkbox column, including the select-all checkbox
1270
+ * in the header. Unset, it follows `selectionMode` (default `'both'`, so
1271
+ * row selection is on).
1272
+ */
1203
1273
  showRowSelection?: boolean;
1274
+ /**
1275
+ * Show the pagination footer. Off by default. `pageable` is the shortcut
1276
+ * alias and wins when both are set.
1277
+ */
1204
1278
  showPagination?: boolean;
1205
1279
  /** Initial page size when pagination is enabled. Defaults to 10. */
1206
1280
  pageSize?: number;
@@ -1230,6 +1304,14 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1230
1304
  * is on. Fetch that page and update `data` / `rowCount` / `pageIndex`.
1231
1305
  */
1232
1306
  onPaginationChange?: (pagination: { pageIndex: number; pageSize: number }) => void;
1307
+ /**
1308
+ * Render only the rows in view instead of all of them. **On by default** -
1309
+ * this is what keeps a 100,000-row grid responsive.
1310
+ *
1311
+ * Turn it off when a row's height cannot be known up front and must not be
1312
+ * clipped, such as a variable-height master-detail panel. Expect the DOM to
1313
+ * hold every row when you do.
1314
+ */
1233
1315
  virtualization?: boolean;
1234
1316
  /** Row height in pixels. Pass a function `(rowIndex) => px` for
1235
1317
  * per-row variable heights (e.g. an interactive row-resize feature).
@@ -1254,6 +1336,11 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1254
1336
  * to their content (the default). Does not affect the filter row.
1255
1337
  */
1256
1338
  headerHeight?: number;
1339
+ /**
1340
+ * Extra rows rendered above and below the viewport, so fast scrolling does
1341
+ * not reach empty space before the next batch renders. Defaults to 8.
1342
+ * Raise it for very tall rows, lower it to trim DOM work.
1343
+ */
1257
1344
  overscan?: number;
1258
1345
  /**
1259
1346
  * Height of the grid's scrollable shell. A number is treated as pixels;
@@ -1261,8 +1348,24 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1261
1348
  * make the grid fill its parent. Defaults to 520 px.
1262
1349
  */
1263
1350
  containerHeight?: number | string;
1351
+ /**
1352
+ * Render only the columns in view, the horizontal counterpart of
1353
+ * `virtualization`. **On by default**, which is what makes a 100-column grid
1354
+ * scroll smoothly.
1355
+ *
1356
+ * It recycles column DOM nodes, so it cannot coexist with sticky pinned
1357
+ * columns - turn it off if you need pinning to survive horizontal scrolling.
1358
+ */
1264
1359
  columnVirtualization?: boolean;
1360
+ /**
1361
+ * Extra columns rendered either side of the viewport when
1362
+ * `columnVirtualization` is on. Defaults to 3.
1363
+ */
1265
1364
  columnOverscan?: number;
1365
+ /**
1366
+ * Fallback width in pixels for columns whose `ColumnDef` sets no `width`.
1367
+ * Defaults to 140.
1368
+ */
1266
1369
  columnWidth?: number;
1267
1370
  /**
1268
1371
  * Columns pinned to the left/right edge on mount. Each entry is a
@@ -1293,8 +1396,24 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1293
1396
  * breakpoint; pass `{ breakpoint }` to change it. Off by default.
1294
1397
  */
1295
1398
  responsive?: boolean | { breakpoint?: number };
1399
+ /**
1400
+ * @deprecated Has no effect - nothing in the grid reads this prop. It is kept
1401
+ * only so existing code keeps compiling. The column menu's filter section is
1402
+ * controlled by `showColumnFilters`, or by `filterMode="menu"` (the default).
1403
+ */
1296
1404
  showFilterMenu?: boolean;
1405
+ /**
1406
+ * Show the always-visible filter row under the header. Explicitly setting
1407
+ * this wins over `filterMode`; unset, it appears only when `filterMode` is
1408
+ * `'row'`.
1409
+ */
1297
1410
  showFilterRow?: boolean;
1411
+ /**
1412
+ * Cell selection - click to select, drag or shift-click to extend to a range,
1413
+ * which is what clipboard copy and the range fill handle operate on. Unset,
1414
+ * it follows `selectionMode` (default `'both'`, so this is on). `selectable`
1415
+ * is the shortcut alias and wins over it.
1416
+ */
1298
1417
  enableCellSelection?: boolean;
1299
1418
  /**
1300
1419
  * Highlight the row under the pointer. Default **false** - the hover tint can
@@ -1320,6 +1439,14 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1320
1439
  rowIndex: number;
1321
1440
  columnId: string;
1322
1441
  }) => unknown;
1442
+ /**
1443
+ * Inline cell editing: F2 or double-click opens an editor in the active cell,
1444
+ * Enter commits, Esc cancels. Off by default.
1445
+ *
1446
+ * A column still needs an `editorType` to pick its editor (text, number,
1447
+ * date, checkbox, list, ...); without one it gets a plain text editor.
1448
+ * `editable` is the shortcut alias and wins over this.
1449
+ */
1323
1450
  enableInlineEditing?: boolean;
1324
1451
  /**
1325
1452
  * Full-row editing. When `true`, starting an edit puts the WHOLE row into
@@ -1329,7 +1456,22 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1329
1456
  * text / number / date / datetime / checkbox / list-select editor types.
1330
1457
  */
1331
1458
  fullRowEditing?: boolean;
1459
+ /**
1460
+ * Append a sticky footer row aggregating every filtered row: the sum of a
1461
+ * numeric column, `Count: N` otherwise. Choose a different aggregate per
1462
+ * column with that column's own `summary` option, or set it to `false` there
1463
+ * to leave the cell blank.
1464
+ *
1465
+ * Off by default. `summary` is the shortcut alias and wins when both are set.
1466
+ *
1467
+ * <SvGrid {data} {columns} summary />
1468
+ */
1332
1469
  enableRowSummaries?: boolean;
1470
+ /**
1471
+ * Shortcut alias for {@link enableRowSummaries}. Wins over it when both are
1472
+ * set, the same precedence `selectable` has over `enableCellSelection`.
1473
+ */
1474
+ summary?: boolean;
1333
1475
  /**
1334
1476
  * Excel-style status bar under the grid showing live aggregates of the
1335
1477
  * selected cell range (count, numeric count, sum, average, min, max).
@@ -1544,6 +1686,14 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1544
1686
  * filter.
1545
1687
  */
1546
1688
  conditionalStatScope?: "filtered" | "visible" | "all";
1689
+ /**
1690
+ * Fires after an inline edit commits, with the cell's old and new value and
1691
+ * the row it belongs to. This is where you persist the change.
1692
+ *
1693
+ * The grid has already applied the edit to its own state by the time this
1694
+ * runs, so it is a notification, not a veto - reject a value with the
1695
+ * column's `valueParser` or a validation rule instead.
1696
+ */
1547
1697
  onCellValueChange?: (event: {
1548
1698
  rowIndex: number;
1549
1699
  columnId: string;
package/src/ai.ts CHANGED
@@ -48,6 +48,7 @@ type ExportFormat = 'xlsx' | 'xls' | 'pdf' | 'csv' | 'tsv' | 'html' | 'json' | '
48
48
  */
49
49
  export type AIProvider = (request: AIRequest) => Promise<string>
50
50
 
51
+ /** One call out to the model, as the grid builds it. Providers receive this. */
51
52
  export type AIRequest = {
52
53
  /** Full prompt the grid built for the model. Already includes column
53
54
  * schema and any sampled rows where applicable. */
@@ -66,6 +67,7 @@ export type AIRequest = {
66
67
  maxOutputTokens?: number
67
68
  }
68
69
 
70
+ /** Which helper produced a request - carried on {@link AIRequest} for routing and telemetry. */
69
71
  export type AITask = 'filter' | 'smart-fill' | 'summarize' | 'classify' | 'export' | 'anomaly' | 'chart'
70
72
 
71
73
  let provider: AIProvider | null = null
@@ -79,10 +81,12 @@ export function setAIProvider(p: AIProvider | null): void {
79
81
  provider = p
80
82
  }
81
83
 
84
+ /** The provider registered with `setAIProvider`, or null when none is. */
82
85
  export function getAIProvider(): AIProvider | null {
83
86
  return provider
84
87
  }
85
88
 
89
+ /** Whether an AI provider is registered. Gate AI affordances on this so the UI stays honest. */
86
90
  export function hasAIProvider(): boolean {
87
91
  return provider != null
88
92
  }
@@ -198,13 +202,16 @@ function schemaToPromptBlock(schema: ColumnSchemaEntry[]): string {
198
202
  // 1. Natural-language filter / sort
199
203
  // ---------------------------------------------------------------------------
200
204
 
205
+ /** One condition in a filter plan: a column, a comparison, and the value to match. */
201
206
  export type AIFilterClause = {
202
207
  field: string
203
208
  operator: 'contains' | 'equals' | 'startsWith' | 'greaterThan' | 'lessThan' | 'isBlank'
204
209
  value?: string
205
210
  }
211
+ /** One ordering clause in a filter plan. */
206
212
  export type AISortClause = { field: string; desc: boolean }
207
213
 
214
+ /** A natural-language query turned into filters and sorting, plus the model's reasoning. */
208
215
  export type AIFilterResult = {
209
216
  filters: AIFilterClause[]
210
217
  sort: AISortClause[]
@@ -213,6 +220,7 @@ export type AIFilterResult = {
213
220
  rationale: string
214
221
  }
215
222
 
223
+ /** Options for `aiFilter` - preview the plan, or apply it straight to the grid. */
216
224
  export type AIFilterOptions = {
217
225
  /**
218
226
  * When true, the helper not only RETURNS the plan but also applies it
@@ -284,14 +292,17 @@ export async function aiFilter<
284
292
  // 2. Smart fill
285
293
  // ---------------------------------------------------------------------------
286
294
 
295
+ /** One worked example teaching smart-fill what to produce for a row. */
287
296
  export type AISmartFillExample = { input: Record<string, unknown>; output: unknown }
288
297
 
298
+ /** Proposed values for the blank cells of one column, each with a confidence score. */
289
299
  export type AISmartFillResult<TValue = unknown> = {
290
300
  field: string
291
301
  predictions: Array<{ rowIndex: number; value: TValue; confidence: number }>
292
302
  rationale: string
293
303
  }
294
304
 
305
+ /** Options for `aiSmartFill` - which column to fill, which rows, and the examples to learn from. */
295
306
  export type AISmartFillOptions = {
296
307
  /** Target column - the one whose values we want filled. */
297
308
  field: string
@@ -379,12 +390,14 @@ export async function aiSmartFill<
379
390
  // 3. Summarise
380
391
  // ---------------------------------------------------------------------------
381
392
 
393
+ /** What to summarise: one row, the selection, a group, or the whole set. */
382
394
  export type AISummarizeTarget =
383
395
  | { kind: 'row'; rowIndex: number }
384
396
  | { kind: 'all' }
385
397
  | { kind: 'selection'; rowIndices: number[] }
386
398
  | { kind: 'group'; field: string; value: unknown }
387
399
 
400
+ /** A generated summary: prose, bullets, and the columns the model leaned on. */
388
401
  export type AISummary = {
389
402
  text: string
390
403
  bullets: string[]
@@ -393,6 +406,7 @@ export type AISummary = {
393
406
  highlightedFields: string[]
394
407
  }
395
408
 
409
+ /** Options for `aiSummarize` - the target, and optionally the question to answer. */
396
410
  export type AISummarizeOptions = {
397
411
  target: AISummarizeTarget
398
412
  /** Optional question the user is trying to answer. Helps the model
@@ -468,6 +482,7 @@ export async function aiSummarize<
468
482
  // 4. Classify (free-text -> bucketed value)
469
483
  // ---------------------------------------------------------------------------
470
484
 
485
+ /** Options for `aiClassify` - the column to label and the categories to choose from. */
471
486
  export type AIClassifyOptions = {
472
487
  /** Column whose free-text we're classifying. */
473
488
  inputField: string
@@ -482,6 +497,7 @@ export type AIClassifyOptions = {
482
497
  signal?: AbortSignal
483
498
  }
484
499
 
500
+ /** Proposed category labels per row, with the model's reasoning. */
485
501
  export type AIClassifyResult = {
486
502
  inputField: string
487
503
  outputField: string
@@ -545,6 +561,7 @@ export async function aiClassify<
545
561
 
546
562
  const EXPORT_FORMATS: ExportFormat[] = ['xlsx', 'xls', 'pdf', 'csv', 'tsv', 'html', 'json', 'xml', 'md']
547
563
 
564
+ /** An export the model derived from a request: format, columns, and scope. */
548
565
  export type AIExportPlan = {
549
566
  format: ExportFormat
550
567
  filters: AIFilterClause[]
@@ -554,6 +571,7 @@ export type AIExportPlan = {
554
571
  rationale: string
555
572
  }
556
573
 
574
+ /** Options for `aiExport` - preview the plan, or run the export it describes. */
557
575
  export type AIExportOptions = {
558
576
  /**
559
577
  * Also apply the filter / sort / grouping to the grid (mutating the view) so
@@ -719,6 +737,7 @@ function applyPlanToRows<TData extends RowData>(
719
737
  // 6. Find anomalies
720
738
  // ---------------------------------------------------------------------------
721
739
 
740
+ /** One flagged value, with why it stands out and how strongly. */
722
741
  export type AIAnomaly = {
723
742
  /** Index into the SCANNED rows (target order), when the model pins one row. */
724
743
  rowIndex?: number
@@ -728,11 +747,13 @@ export type AIAnomaly = {
728
747
  severity: 'low' | 'medium' | 'high'
729
748
  }
730
749
 
750
+ /** Everything an anomaly scan flagged across the rows it looked at. */
731
751
  export type AIAnomalyResult = {
732
752
  anomalies: AIAnomaly[]
733
753
  summary: string
734
754
  }
735
755
 
756
+ /** Options for `aiFindAnomalies` - which rows and columns to scan. */
736
757
  export type AIAnomalyOptions = {
737
758
  /** Which rows to scan. Defaults to the whole dataset. */
738
759
  target?: AISummarizeTarget
@@ -814,8 +835,10 @@ export async function aiFindAnomalies<
814
835
  // 7. Natural-language chart ("chart this")
815
836
  // ---------------------------------------------------------------------------
816
837
 
838
+ /** Chart shapes the model may choose from when planning a visualisation. */
817
839
  export type AIChartType = 'bar' | 'line' | 'area' | 'pie'
818
840
 
841
+ /** A chart the model proposed: its type, and the fields to plot. */
819
842
  export type AIChartPlan = {
820
843
  type: AIChartType
821
844
  /** Group-by (category-axis) column field, or null. */
@@ -832,6 +855,7 @@ export type AIChartPlan = {
832
855
  rationale: string
833
856
  }
834
857
 
858
+ /** Options for `aiChart` - preview the plan, or render it into the grid. */
835
859
  export type AIChartOptions = {
836
860
  /** Apply the plan to the grid's chart panel (open + configure). Default false. */
837
861
  apply?: boolean
@@ -951,6 +975,10 @@ export function enableAiCharting<
951
975
  })
952
976
  }
953
977
 
978
+ /**
979
+ * Remove the natural-language chart handler, hiding the AI button in the chart
980
+ * panel. The inverse of `enableAiCharting`; safe to call when none was set.
981
+ */
954
982
  export function disableAiCharting<
955
983
  TFeatures extends TableFeatures,
956
984
  TData extends RowData,
@@ -106,6 +106,8 @@ function getNumberFormatter(
106
106
 
107
107
  /** Cache of `Intl.DateTimeFormat` by `(locale, options)` signature. */
108
108
  const dateFormatterCache = new Map<string, Intl.DateTimeFormat>()
109
+ /** A cached `Intl.DateTimeFormat` for the locale and options given. Cached because
110
+ * constructing one per cell is the dominant cost when formatting a date column. */
109
111
  export function getDateFormatter(
110
112
  locales: string | readonly string[] | undefined,
111
113
  options: Intl.DateTimeFormatOptions,
@@ -21,6 +21,7 @@ function cssVar(el: Element, name: string, fallback: string): string {
21
21
  return v || fallback
22
22
  }
23
23
 
24
+ /** Options for exporting a chart: the filename, and the background to paint behind it. */
24
25
  export type ChartExportOptions = {
25
26
  /** Background color of the exported image. Default: the grid background. */
26
27
  background?: string
package/src/chart.ts CHANGED
@@ -36,9 +36,8 @@ export type SeriesOverlay = 'linear' | `sma:${number}` | `ema:${number}`
36
36
  /** A texture fill applied in addition to (and on top of) the series color.
37
37
  * Helps colorblind readers distinguish series at a glance. */
38
38
  export type SeriesPattern = 'solid' | 'stripe' | 'crosshatch' | 'dots' | 'diagonal'
39
- /** Cycle used when `ChartSpec.patternFallback` is true and a series has no
40
- * explicit `pattern` set. Skips `'solid'` so every series gets a texture. */
41
39
 
40
+ /** One plotted series: its label, its values (one per category), and how to draw it. */
42
41
  export type ChartSeries = {
43
42
  label: string
44
43
  values: number[]
@@ -95,6 +94,12 @@ export type ChartReferenceLine = {
95
94
  dashed?: boolean
96
95
  }
97
96
 
97
+ /**
98
+ * What to plot - the input you build and hand to a chart. Categories are the
99
+ * x-axis labels and every series supplies one value per category.
100
+ *
101
+ * {@link buildChart} turns this into a {@link ChartGeometry} for rendering.
102
+ */
98
103
  export type ChartSpec = {
99
104
  /** Default type for series that don't set their own `type`. */
100
105
  type: ChartType
@@ -326,6 +331,7 @@ export type ChartHeatmapCell = {
326
331
  colLabel: string
327
332
  }
328
333
 
334
+ /** A computed bar rectangle in SVG coordinates. Output of {@link buildChart}, not an input. */
329
335
  export type ChartBar = {
330
336
  x: number
331
337
  y: number
@@ -338,6 +344,7 @@ export type ChartBar = {
338
344
  series: string
339
345
  value: number
340
346
  }
347
+ /** One computed point on a line, with whether the series has a value there. */
341
348
  export type ChartLinePoint = {
342
349
  x: number
343
350
  y: number
@@ -346,6 +353,7 @@ export type ChartLinePoint = {
346
353
  /** False for null / NaN values - the line breaks (gap), no dot is drawn. */
347
354
  defined: boolean
348
355
  }
356
+ /** A computed line series: its points and the path drawn through them. */
349
357
  export type ChartLine = {
350
358
  path: string
351
359
  areaPath: string
@@ -356,6 +364,7 @@ export type ChartLine = {
356
364
  * series, when both arrays are supplied. Empty otherwise. */
357
365
  bandPath?: string
358
366
  }
367
+ /** A computed pie slice, as an SVG arc plus its label placement. */
359
368
  export type ChartPieSlice = {
360
369
  path: string
361
370
  color: string
@@ -366,12 +375,17 @@ export type ChartPieSlice = {
366
375
  cx: number
367
376
  cy: number
368
377
  }
378
+ /** A value-axis tick: the number, where it sits vertically, and its label. */
369
379
  export type ChartAxisTick = { value: number; y: number; label: string }
380
+ /** A category-axis tick: the label and its horizontal position. */
370
381
  export type ChartCategoryTick = { label: string; x: number }
382
+ /** One legend entry, paired with the series colour it stands for. */
371
383
  export type ChartLegendItem = { label: string; color: string }
384
+ /** A computed reference line (target, average, threshold) at its plotted height. */
372
385
  export type ChartRefLineGeo = { y: number; label: string; color: string; dashed: boolean }
373
386
  /** A vertical reference line (horizontal bar charts) positioned by `x`. */
374
387
  export type ChartRefLineGeoV = { x: number; label: string; color: string; dashed: boolean }
388
+ /** A computed scatter point in SVG coordinates. */
375
389
  export type ChartScatterDot = {
376
390
  cx: number
377
391
  cy: number
@@ -383,6 +397,11 @@ export type ChartScatterDot = {
383
397
  y: number
384
398
  }
385
399
 
400
+ /**
401
+ * Everything needed to render a chart: the plot rectangle plus every mark
402
+ * already positioned in SVG coordinates. Produced by {@link buildChart} from a
403
+ * {@link ChartSpec}, so a renderer does no maths of its own.
404
+ */
386
405
  export type ChartGeometry = {
387
406
  type: ChartType
388
407
  width: number
@@ -455,6 +474,7 @@ export type ChartGeometry = {
455
474
  sankeyLinks: ChartSankeyLink[]
456
475
  }
457
476
 
477
+ /** Series colours used when a {@link ChartSeries} sets none, in order. */
458
478
  export const DEFAULT_PALETTE = [
459
479
  '#2563eb',
460
480
  '#16a34a',
@@ -480,6 +500,7 @@ function niceNum(range: number, roundIt: boolean): number {
480
500
  return nf * Math.pow(10, exp)
481
501
  }
482
502
 
503
+ /** An axis range rounded to human-friendly bounds and tick spacing. */
483
504
  export type NiceScale = { min: number; max: number; step: number; ticks: number[] }
484
505
 
485
506
  // ---- Color helpers for heatmap / pattern fills ----------------------
@@ -574,9 +595,6 @@ function project(value: number, min: number, max: number, isLog: boolean): numbe
574
595
 
575
596
  // ---- Overlay math: trendline + moving averages -----------------------
576
597
 
577
- /** Ordinary least-squares regression on (i, values[i]) pairs (i = x index).
578
- * Returns the fitted value at each x index, or NaN where the source value
579
- * was non-finite. */
580
598
  /** Build an SVG path from a list of (x,y) pairs, optionally smoothed via
581
599
  * monotone cubic interpolation (preserves local extrema - no overshoots).
582
600
  * Breaks the path at `defined === false` gaps. */
@@ -655,6 +673,9 @@ function monotoneCubicPath(pts: Array<{ x: number; y: number }>): string {
655
673
  return path
656
674
  }
657
675
 
676
+ /** Ordinary least-squares regression on (i, values[i]) pairs (i = x index).
677
+ * Returns the fitted value at each x index, or NaN where the source value
678
+ * was non-finite. */
658
679
  export function linearTrend(values: number[]): number[] {
659
680
  let n = 0, sumX = 0, sumY = 0, sumXX = 0, sumXY = 0
660
681
  for (let i = 0; i < values.length; i += 1) {
@@ -835,6 +856,11 @@ function axisDomain(
835
856
  return isLog ? niceLogScale(dMin, dMax) : niceScale(dMin, dMax)
836
857
  }
837
858
 
859
+ /**
860
+ * Lay out a {@link ChartSpec} into renderable {@link ChartGeometry} - scales,
861
+ * ticks, and the position of every bar, line, slice and dot. Pure: no DOM, so
862
+ * it runs during SSR and can be unit-tested directly.
863
+ */
838
864
  export function buildChart(spec: ChartSpec, theme: 'light' | 'dark' = 'light'): ChartGeometry {
839
865
  const width = spec.width ?? 520
840
866
  const height = spec.height ?? 300