@toclocoinc/lattice-grid 1.28.0 → 1.30.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.
package/lattice-grid.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.28.0, type declarations
2
+ * Lattice Grid 1.30.0, type declarations
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -20,7 +20,7 @@ export type TypeName =
20
20
  | 'text' | 'number' | 'boolean' | 'date' | 'dateString' | 'object' | 'lookup'
21
21
  | 'image'
22
22
  // Extended catalogue. Never inferred, a column asks for these by name.
23
- | 'time' | 'datetime' | 'duration'
23
+ | 'time' | 'datetime' | 'duration' | 'timestamp'
24
24
  | 'ipv4' | 'ipv6' | 'cidr'
25
25
  | 'json' | 'secret'
26
26
  | 'hex' | 'hex8' | 'hex16' | 'hex32' | 'binary' | 'binary8' | 'octal'
@@ -551,9 +551,19 @@ export interface ColumnLayoutSpec {
551
551
  }
552
552
 
553
553
  export interface ColumnHeaderSpec {
554
+ /** Not read by the header renderer; use `render` to draw a custom heading. */
554
555
  template?: string;
556
+ /**
557
+ * A custom heading renderer: a function, or a component (a class with a
558
+ * `render` method). A string names a registered renderer. Either form draws
559
+ * the same two ways and they are interchangeable — it may append to the passed
560
+ * label element itself and return nothing, or return an `Element` (attached
561
+ * for you) or a `string` (used as the heading text).
562
+ */
555
563
  render?: string | RendererCtor;
564
+ /** Props passed to `render` as `params.props`. */
556
565
  props?: Record<string, unknown>;
566
+ /** A class, or classes, added to the heading cell. */
557
567
  class?: string | string[];
558
568
  tooltip?: string;
559
569
  align?: Align;
@@ -607,8 +617,17 @@ export interface Column {
607
617
  * Row grouping by this column. `index` fixes its place among several;
608
618
  * `explode` gives a multi-value cell one group per value rather than one
609
619
  * group for the combination.
610
- */
611
- group?: { enabled?: boolean; index?: number; explode?: boolean } | boolean;
620
+ *
621
+ * `granularity` and `weekStart` apply to a `timestamp` column: it buckets by
622
+ * civil `day` (the default), `week` or `month` in the display zone, or
623
+ * `instant` for one group per exact moment. `weekStart` is the first weekday,
624
+ * 1=Monday (default) to 7=Sunday.
625
+ */
626
+ group?: {
627
+ enabled?: boolean; index?: number; explode?: boolean;
628
+ granularity?: 'day' | 'week' | 'month' | 'instant';
629
+ weekStart?: number;
630
+ } | boolean;
612
631
  /** Use this column as a pivot dimension, and where it sits among several. */
613
632
  pivot?: { enabled?: boolean; index?: number } | boolean;
614
633
  /** The reduction shown in the totals row and in group footers. */
@@ -659,6 +678,79 @@ export interface Column {
659
678
  upper?: number;
660
679
  warnLower?: number;
661
680
  warnUpper?: number;
681
+ /**
682
+ * For a rolling time-series kind (`rollingSum`/`rollingAvg`/`rollingMin`/
683
+ * `rollingMax`/`windowCoverage`/`cumulativeToDate`/`periodOverPeriod`,
684
+ * BACKLOG-0000748), the column whose order defines the series — dates,
685
+ * sequence numbers, timestamps. **Required**: the screen sort is never used,
686
+ * because a rolling figure would then change on every header click, so a
687
+ * rolling column with no `orderBy` reports null and warns.
688
+ */
689
+ orderBy?: string;
690
+ /**
691
+ * For the rolling window kinds, the window to aggregate over: the last `span`
692
+ * rows (`count`), the last `span` ms — or `minutes` — of the `orderBy` axis
693
+ * (`time`), or everything so far (`session`). The first rows of a series
694
+ * carry a partial window, stamped by a `windowCoverage` companion rather than
695
+ * dressed as full.
696
+ */
697
+ window?: {
698
+ kind: 'count' | 'time' | 'session';
699
+ span?: number;
700
+ minutes?: number;
701
+ };
702
+ /**
703
+ * For a rolling kind, whether the series is computed per group (`'group'`,
704
+ * the default — partitioned by the grid's active grouping) or across the
705
+ * whole dataset (`'all'`).
706
+ */
707
+ within?: 'group' | 'all';
708
+ /**
709
+ * For `kind: 'rollingQuantile'` (and its `windowApproximate` companion), the
710
+ * quantile in `[0, 1]`, defaulting to the median (`0.5`). Exact while the
711
+ * window is small; past an internal span cap, and for a session window, the
712
+ * value comes from a sketch and is stamped by a `windowApproximate` column.
713
+ */
714
+ q?: number;
715
+ /**
716
+ * For a seasonal-decomposition kind (`tsTrend`/`tsSeasonal`/`tsResidual`/
717
+ * `tsCoverage`, BACKLOG-0000873), the season length — **required**, since
718
+ * there is no auto-detection in v1: 7 for a weekly cycle in daily data, 12
719
+ * for a monthly cycle in monthly data. An integer of at least 2.
720
+ */
721
+ period?: number;
722
+ /**
723
+ * For a decomposition kind, the classical model: additive by default, or
724
+ * `multiplicative` (which is undefined on a non-positive series, so those
725
+ * rows report null and the caller is warned).
726
+ */
727
+ decomposition?: 'additive' | 'multiplicative';
728
+ /**
729
+ * For an exponential-smoothing kind (`tsSmoothed`/`tsSmoothingAlpha`/
730
+ * `tsSmoothingBeta`, BACKLOG-0000873), the model: single exponential
731
+ * smoothing (`ses`, the default) or Holt's level+trend (`holt`).
732
+ */
733
+ smoothing?: 'ses' | 'holt';
734
+ /**
735
+ * For a smoothing kind, the level factor in `[0, 1]`. Omit to fit it by
736
+ * minimising in-sample SSE; the chosen value is reported by a
737
+ * `tsSmoothingAlpha` column.
738
+ */
739
+ alpha?: number;
740
+ /**
741
+ * For `smoothing: 'holt'`, the trend factor in `[0, 1]`. Omit to fit it;
742
+ * reported by a `tsSmoothingBeta` column.
743
+ */
744
+ beta?: number;
745
+ /**
746
+ * For a `fit*` kind (BACKLOG-0000812), the regression model the shadow reads
747
+ * — predictors, response, method and confidence. Its predictors/response may
748
+ * also be given directly on this object.
749
+ */
750
+ model?: RegressionSpec;
751
+ predictors?: string[];
752
+ response?: string;
753
+ method?: 'ols' | 'wls' | 'robust' | 'quantile';
662
754
  };
663
755
  /**
664
756
  * A running total down the grid **as it is currently ordered**.
@@ -719,7 +811,7 @@ export interface ResolvedColumn {
719
811
  edit: ColumnEditSpec;
720
812
  sort: ColumnSortSpec;
721
813
  filter: ColumnFilterSpec;
722
- group: { enabled: boolean; index: number; explode: boolean };
814
+ group: { enabled: boolean; index: number; explode: boolean; granularity?: 'day' | 'week' | 'month' | 'instant'; weekStart?: number };
723
815
  pivot: { enabled: boolean; index: number };
724
816
  total: TotalName | TotalFn | null;
725
817
  /**
@@ -2100,10 +2192,25 @@ export interface ColumnState {
2100
2192
  variant?: VariantSpec | null;
2101
2193
  }
2102
2194
 
2195
+ /**
2196
+ * A persisted banded-header node (§15, BACKLOG-0000739): a band with a `columns`
2197
+ * list whose members are leaf ids or nested bands. This is what round-trips a
2198
+ * drag-created group through a saved view.
2199
+ */
2200
+ export interface ColumnGroupState {
2201
+ id: string;
2202
+ title: string;
2203
+ collapsible: boolean;
2204
+ openByDefault: boolean;
2205
+ columns: Array<string | ColumnGroupState>;
2206
+ }
2207
+
2103
2208
  export interface GridState {
2104
2209
  version: number;
2105
2210
  columns?: ColumnState[];
2106
2211
  columnOrder?: string[];
2212
+ /** The banded-header tree, when the grid has one (BACKLOG-0000739). */
2213
+ columnGroups?: ColumnGroupState[];
2107
2214
  filters?: FilterSet;
2108
2215
  quick?: string;
2109
2216
  sort?: SortEntry[];
@@ -2116,6 +2223,12 @@ export interface GridState {
2116
2223
  */
2117
2224
  pivotView?: { rowsCollapsed: string[]; columnsCollapsed: string[] };
2118
2225
  formatting?: Record<string, FormattingRule[]>;
2226
+ /**
2227
+ * Durable annotation marks (BACKLOG-0000813): seeded from here on first paint,
2228
+ * and written back by `getState` so a host can persist and restore them. In
2229
+ * content coordinates, so they track scroll and resize.
2230
+ */
2231
+ annotations?: AnnotationMark[];
2119
2232
  expanded?: string[];
2120
2233
  selection?: string[];
2121
2234
  scroll?: { top: number; left: number };
@@ -2400,6 +2513,14 @@ export interface StatisticsApi {
2400
2513
  */
2401
2514
  shadow(colId: string, kind: ShadowKind, rowKey: string,
2402
2515
  scope?: 'all' | 'filtered', spec?: object): unknown;
2516
+ /**
2517
+ * One regression shadow value for a row, by key (BACKLOG-0000812): the
2518
+ * predicted value, residual, or Cook's-distance influence flag from the fitted
2519
+ * model, over the filtered rows. Null for a row outside the fit.
2520
+ */
2521
+ fitShadow(kind: 'fitPredicted' | 'fitResidual' | 'fitInfluence'
2522
+ | 'fitStdResidual' | 'fitLeverage' | 'fitCooksD',
2523
+ rowKey: string, spec: RegressionSpec): number | boolean | null;
2403
2524
  /** A running total at one row, down the grid as it is currently ordered. */
2404
2525
  running(colId: string, kind: 'total' | 'percent', rowKey: string): number | null;
2405
2526
  /** Make the current values the new baseline: "mark all". */
@@ -2460,6 +2581,32 @@ export interface StatisticsApi {
2460
2581
  covariance(a: string, b: string, opts?: { population?: boolean }): number | null;
2461
2582
  /** Least-squares fit of `b` on `a`: in finance, beta and alpha. */
2462
2583
  regression(a: string, b: string): RegressionFit | null;
2584
+ /**
2585
+ * Fit a multi-predictor linear model over the filtered rows and return the
2586
+ * full diagnostic set — coefficients with standard errors, t and p; R² and
2587
+ * adjusted R²; per-row fitted values, residuals, leverage and Cook's D; VIF
2588
+ * per predictor; a Breusch–Pagan heteroscedasticity flag; and, for a single
2589
+ * predictor, a pointwise confidence band. `method` is `ols`, `wls` (needs a
2590
+ * `weights` column) or `robust`; `quantile` is reserved and the regularised
2591
+ * families refuse. Null on degenerate input (BACKLOG-0000792).
2592
+ */
2593
+ regressionModel(spec: RegressionSpec): RegressionModel | null;
2594
+ /**
2595
+ * The Augmented Dickey-Fuller stationarity test over the `of` series in
2596
+ * `orderBy` order (BACKLOG-0000873), constant+trend form with the lag order
2597
+ * chosen by AIC up to an optional cap. Returns the statistic, the lag used,
2598
+ * MacKinnon's critical values, an approximate (interpolated) p-value and a
2599
+ * plain-language verdict at the 5% level — a scalar readout, not a column.
2600
+ */
2601
+ adf(spec: { of: string; orderBy: string; maxlag?: number }): AdfResult | null;
2602
+ /**
2603
+ * The autocorrelation (ACF) and partial autocorrelation (PACF) of the `of`
2604
+ * series in `orderBy` order out to `maxlag` (BACKLOG-0000873), with the
2605
+ * approximate ±1.96/√n band. A short-series readout; feed the arrays to a bar
2606
+ * chart over explicit points with the band as reference lines. The lag-1
2607
+ * autocorrelation matches `series(...).autocorrelation`.
2608
+ */
2609
+ acf(spec: { of: string; orderBy: string; maxlag?: number }): AcfResult | null;
2463
2610
  /** Spearman's rank correlation, which one outlier cannot drag. */
2464
2611
  spearman(a: string, b: string): number | null;
2465
2612
  /** Kendall's tau-b. Null past 5,000 rows: it is quadratic. */
@@ -2687,7 +2834,67 @@ export type ShadowKind =
2687
2834
  * `{lower, upper}` (and optional inner `{warnLower, warnUpper}`) off the
2688
2835
  * shadow declaration; centred-target ± tolerance is a deliberate follow-up.
2689
2836
  */
2690
- | 'specStatus';
2837
+ | 'specStatus'
2838
+ /**
2839
+ * Rolling time-series aggregates over a stated `orderBy` (BACKLOG-0000748,
2840
+ * Phase 1), computed in one ordered pass the grid caches by row key and never
2841
+ * over the screen sort. `rollingSum`/`rollingAvg`/`rollingMin`/`rollingMax`
2842
+ * reduce the `window`; `windowCoverage` reports how much of the requested
2843
+ * window a row actually covers (so a partial window is never dressed as full);
2844
+ * `cumulativeToDate` is the running total to the row; `periodOverPeriod` is the
2845
+ * change on the previous period (lag-1 in Phase 1). Sortable, filterable,
2846
+ * groupable and exportable like any cell.
2847
+ */
2848
+ | 'rollingSum' | 'rollingAvg' | 'rollingMin' | 'rollingMax'
2849
+ | 'windowCoverage' | 'cumulativeToDate' | 'periodOverPeriod'
2850
+ /**
2851
+ * A rolling quantile over the `orderBy` window (BACKLOG-0000748) — a trailing
2852
+ * median or p95, the quantile set by `q`. Exact while the window is small;
2853
+ * past an internal span cap, and for a session window, it comes from a KLL
2854
+ * sketch and `windowApproximate` reports which rows are approximate, so a
2855
+ * sketched quantile is never presented as exact.
2856
+ */
2857
+ | 'rollingQuantile' | 'windowApproximate'
2858
+ /**
2859
+ * Classical seasonal decomposition over a declared `period` (BACKLOG-0000873),
2860
+ * matching `statsmodels.seasonal_decompose`: `tsTrend` is the centred
2861
+ * moving-average trend, `tsSeasonal` the repeating seasonal index, `tsResidual`
2862
+ * what the two leave behind, and `tsCoverage` the stamp (1 for an interior row,
2863
+ * 0 for a partial edge where the centred window runs off the end, so an edge is
2864
+ * never emitted as full). Additive by default; `decomposition: 'multiplicative'`
2865
+ * is a declared option, undefined on a non-positive series.
2866
+ */
2867
+ | 'tsTrend' | 'tsSeasonal' | 'tsResidual' | 'tsCoverage'
2868
+ /**
2869
+ * Exponential smoothing over the `orderBy` series (BACKLOG-0000873):
2870
+ * `tsSmoothed` is the fitted level from single exponential smoothing (`ses`) or
2871
+ * Holt's level+trend (`holt`) — the signal with the noise removed, not a
2872
+ * forecast. The smoothing factor(s) are caller-set or fit by minimising
2873
+ * in-sample SSE, and reported by the `tsSmoothingAlpha` / `tsSmoothingBeta`
2874
+ * companion columns. Holt-Winters (seasonal) smoothing is deferred; seasonality
2875
+ * is covered by decomposition.
2876
+ */
2877
+ | 'tsSmoothed' | 'tsSmoothingAlpha' | 'tsSmoothingBeta'
2878
+ /**
2879
+ * Model-backed regression shadows (BACKLOG-0000812): the predicted value, the
2880
+ * residual, and a Cook's-distance influence flag for the row, read from the
2881
+ * fitted model named on the shadow declaration (`shadow: { kind:
2882
+ * 'fitResidual', model: { predictors, response, method } }`). They follow the
2883
+ * grid's filters — the model refits over the filtered rows — and are
2884
+ * sortable, filterable, groupable and exportable like any cell. Null for a row
2885
+ * outside the fit. `fitInfluence` flags Cook's D > 4/n by default (overridable
2886
+ * via `threshold`); "not influential" (`false`) and "cannot tell" (`null`)
2887
+ * stay distinct.
2888
+ *
2889
+ * `fitStdResidual`, `fitLeverage` and `fitCooksD` (BACKLOG-0000872) surface
2890
+ * the diagnostics the engine already computes — the internally studentised
2891
+ * residual `eᵢ/(s·√(1−hᵢ))`, the hat-matrix leverage `hᵢ`, and Cook's distance
2892
+ * — as their own numeric columns, so the scale-location and
2893
+ * residuals-vs-leverage plots bind to real columns. Null where there is no
2894
+ * spread to standardise against.
2895
+ */
2896
+ | 'fitPredicted' | 'fitResidual' | 'fitInfluence'
2897
+ | 'fitStdResidual' | 'fitLeverage' | 'fitCooksD';
2691
2898
 
2692
2899
  /** The three verdicts a `specStatus` shadow can report. */
2693
2900
  export type SpecStatus = 'PASS' | 'WARN' | 'FAIL';
@@ -2703,6 +2910,121 @@ export interface RegressionFit {
2703
2910
  n: number;
2704
2911
  }
2705
2912
 
2913
+ /** The specification of a multi-predictor model (BACKLOG-0000792). */
2914
+ export interface RegressionSpec {
2915
+ /** The predictor column ids. */
2916
+ predictors: string[];
2917
+ /** The response column id. */
2918
+ response: string;
2919
+ /** `ols` (default), `wls` or `robust`. `quantile` is reserved (coming next). */
2920
+ method?: 'ols' | 'wls' | 'robust' | 'quantile';
2921
+ /** A weights column id, required for `wls`. */
2922
+ weights?: string;
2923
+ /** The confidence level for the band; 0.95 by default. */
2924
+ confidence?: number;
2925
+ }
2926
+
2927
+ /** One fitted coefficient, with the uncertainty around it. */
2928
+ export interface RegressionCoefficient {
2929
+ /** `(intercept)` or the predictor's column id. */
2930
+ name: string;
2931
+ estimate: number;
2932
+ stdError: number;
2933
+ /** estimate ÷ standard error. */
2934
+ t: number;
2935
+ /** Two-sided Student-t p-value; a number with a documented method, not a verdict. */
2936
+ p: number;
2937
+ /**
2938
+ * The Wald confidence interval at the model's confidence level
2939
+ * (BACKLOG-0000872) — the whiskers a coefficient forest plot draws. Null when
2940
+ * there is no residual degree of freedom to form a critical value.
2941
+ */
2942
+ lower: number | null;
2943
+ upper: number | null;
2944
+ }
2945
+
2946
+ /** A pointwise confidence band for the mean response of a single-predictor fit. */
2947
+ export interface RegressionBand {
2948
+ confidence: number;
2949
+ points: { x: number; yhat: number; lower: number; upper: number }[];
2950
+ }
2951
+
2952
+ /** The Breusch–Pagan heteroscedasticity test result. */
2953
+ export interface Heteroscedasticity {
2954
+ statistic: number;
2955
+ df: number;
2956
+ p: number;
2957
+ /** True when the test rejects homoscedasticity at the 0.05 level. */
2958
+ heteroscedastic: boolean;
2959
+ }
2960
+
2961
+ /** The Augmented Dickey-Fuller stationarity test result (BACKLOG-0000873). */
2962
+ export interface AdfResult {
2963
+ /** The ADF t-statistic on the lagged level. */
2964
+ statistic: number;
2965
+ /** The number of augmenting lags chosen by AIC. */
2966
+ usedLag: number;
2967
+ /** The observations the final regression used. */
2968
+ nobs: number;
2969
+ /** MacKinnon's constant+trend critical values at the 1%, 5% and 10% levels. */
2970
+ criticalValues: { '1%': number; '5%': number; '10%': number };
2971
+ /** An approximate p-value, interpolated across the critical-value ladder. */
2972
+ pValue: number;
2973
+ /** Always true: the p-value is an interpolation, not the MacKinnon surface. */
2974
+ pApproximate: boolean;
2975
+ /** Whether the series is stationary at the 5% level. */
2976
+ stationary: boolean;
2977
+ /** The plain-language verdict: `'stationary'` or `'non-stationary'`. */
2978
+ verdict: string;
2979
+ /** The regression form used — always `'ct'` (constant + trend) in v1. */
2980
+ regression: 'ct';
2981
+ }
2982
+
2983
+ /** Autocorrelation (ACF) and partial autocorrelation (PACF) arrays (BACKLOG-0000873). */
2984
+ export interface AcfResult {
2985
+ /** The autocorrelation at each lag; index 0 is lag 0 and is always 1. */
2986
+ acf: number[];
2987
+ /** The partial autocorrelation at each lag; index 0 is 1, and `pacf[1] === acf[1]`. */
2988
+ pacf: number[];
2989
+ /** The approximate ±1.96/√n white-noise confidence band. */
2990
+ bounds: { upper: number; lower: number };
2991
+ /** The series length the ACF/PACF were computed over. */
2992
+ n: number;
2993
+ /** The maximum lag. */
2994
+ nlags: number;
2995
+ /** Always true: the ±1.96/√n band is an approximation. */
2996
+ approximate: boolean;
2997
+ }
2998
+
2999
+ /** A fitted multi-predictor linear model and its diagnostics (BACKLOG-0000792). */
3000
+ export interface RegressionModel {
3001
+ method: string;
3002
+ coefficients: RegressionCoefficient[];
3003
+ r2: number;
3004
+ adjR2: number;
3005
+ n: number;
3006
+ /** Residual degrees of freedom, n − p. */
3007
+ df: number;
3008
+ /** Residual variance, RSS ÷ df. */
3009
+ sigma2: number;
3010
+ fitted: number[];
3011
+ residuals: number[];
3012
+ /** Hat-diagonal leverage per row. */
3013
+ leverage: number[];
3014
+ /** Cook's distance per row; null where it cannot be computed. */
3015
+ cooksD: (number | null)[];
3016
+ /** Variance-inflation factor per predictor; Infinity when exactly collinear. */
3017
+ vif: number[];
3018
+ heteroscedasticity: Heteroscedasticity | null;
3019
+ band: RegressionBand | null;
3020
+ /** Per-row weights actually used (robust/WLS), or null for OLS. */
3021
+ weights: number[] | null;
3022
+ predictors: string[];
3023
+ response: string;
3024
+ /** The physical rows the diagnostics are aligned to, in order. */
3025
+ rows: number[];
3026
+ }
3027
+
2706
3028
  export interface ProcessCapability {
2707
3029
  n: number;
2708
3030
  mean: number;
@@ -3092,7 +3414,7 @@ export type EventName =
3092
3414
  | 'column:moved' | 'column:resized' | 'column:visible' | 'column:pinned'
3093
3415
  | 'column:grouped' | 'column:pivoted' | 'column:filter:open' | 'column:menu:open'
3094
3416
  | 'pivot:drill'
3095
- | 'columns:changed' | 'columns:tagged' | 'header:contextmenu'
3417
+ | 'columns:changed' | 'columns:tagged' | 'columngroup:changed' | 'header:contextmenu'
3096
3418
  /* Selection and view */
3097
3419
  | 'selection:changed' | 'range:changed' | 'clipboard:copy'
3098
3420
  | 'page:changed' | 'scroll' | 'scroll:end' | 'size:changed'
@@ -3322,6 +3644,22 @@ export interface ColumnsApi {
3322
3644
  show(ids: string | string[]): void;
3323
3645
  hide(ids: string | string[]): void;
3324
3646
  move(id: string, to: number): void;
3647
+ /**
3648
+ * Wrap leaf columns in a banded header, or add them to an existing band
3649
+ * (BACKLOG-0000739). Header banding, not row grouping (see {@link group}); the
3650
+ * band is a {@link ColumnGroup} node so a drag-, keyboard- or config-built band
3651
+ * is the same tree, and it round-trips through a saved view. Emits
3652
+ * `columngroup:changed`.
3653
+ */
3654
+ groupColumns(ids: string | string[], opts?: { title?: string; at?: number; groupId?: string }): string | null;
3655
+ /** Take a leaf out of its band; a band emptied by the move is dissolved. */
3656
+ ungroupColumn(id: string): void;
3657
+ /** Rename a banded header. */
3658
+ renameGroup(groupId: string, title: string): void;
3659
+ /** Dissolve a band, returning its columns to the enclosing level in place. */
3660
+ dissolveGroup(groupId: string): void;
3661
+ /** Move a whole band among its siblings, its columns travelling as a block. */
3662
+ moveGroup(groupId: string, to: number): void;
3325
3663
  pin(id: string, side: 'start' | 'end' | null): void;
3326
3664
  resize(id: string, px: number): void;
3327
3665
  /**
@@ -3594,10 +3932,35 @@ export interface CaptureOptions {
3594
3932
  * they stay with the cells they annotate when the grid scrolls, and are
3595
3933
  * cleared when a presentation ends.
3596
3934
  */
3935
+ /**
3936
+ * A durable annotation mark descriptor (BACKLOG-0000813) — the shape a host
3937
+ * seeds through `state.annotations`, adds through {@link AnnotationApi.add}, and
3938
+ * reads back through {@link AnnotationApi.list} and `getState`.
3939
+ *
3940
+ * `points` are in **content coordinates** (the same space user-drawn marks are
3941
+ * stored in), so a mark tracks scroll and resize rather than hanging over the
3942
+ * viewport. A `freehand` mark is a trail of points; `arrow` and `rect` are their
3943
+ * two endpoints. Text marks are a deliberate follow-up. `pen` is accepted as an
3944
+ * alias for `freehand` on input; `list()` reports `freehand`.
3945
+ */
3946
+ export interface AnnotationMark {
3947
+ type: 'freehand' | 'arrow' | 'rect' | 'highlight';
3948
+ points: { x: number; y: number }[];
3949
+ colour?: string;
3950
+ }
3951
+
3597
3952
  export interface AnnotationApi {
3598
3953
  readonly tool: 'pen' | 'arrow' | 'rect' | 'highlight' | null;
3599
3954
  readonly count: number;
3600
3955
  use(tool: 'pen' | 'arrow' | 'rect' | 'highlight' | null, opts?: { colour?: string }): string | null;
3956
+ /**
3957
+ * Add a durable mark from a descriptor, without synthesising pointer input
3958
+ * (BACKLOG-0000813). The mark is painted, survives a presentation ending, and
3959
+ * round-trips through `getState`. Returns the mark count.
3960
+ */
3961
+ add(mark: AnnotationMark): number;
3962
+ /** Every mark on the layer, as descriptors — the shape `getState` persists. */
3963
+ list(): AnnotationMark[];
3601
3964
  undo(): number;
3602
3965
  clear(): void;
3603
3966
  redraw(): void;
@@ -5100,7 +5463,7 @@ export function resolveCatalogue(tag?: string): Record<string, unknown> | null;
5100
5463
  export type ChartType =
5101
5464
  | 'line' | 'step' | 'area' | 'rangeArea'
5102
5465
  | 'bar' | 'horizontalBar' | 'waterfall'
5103
- | 'scatter' | 'bubble'
5466
+ | 'scatter' | 'bubble' | 'forest'
5104
5467
  | 'combo' | 'pareto'
5105
5468
  | 'histogram' | 'boxplot' | 'heatmap'
5106
5469
  | 'qq' | 'ecdf' | 'lorenz' | 'correlogram' | 'control' | 'capability' | 'movingRange'
@@ -5259,6 +5622,29 @@ export interface ChartSpec {
5259
5622
  * through the order they happened to be listed in.
5260
5623
  */
5261
5624
  fit?: boolean | 'line';
5625
+ /**
5626
+ * A pointwise confidence band, drawn as a varying-width ribbon beneath the fit
5627
+ * line (BACKLOG-0000812). Fed by a fitted model's own interval — the `band`
5628
+ * from {@link StatisticsApi.regressionModel}, or as produced by
5629
+ * {@link regressionPlots} — so the ribbon and the diagnostics report the one
5630
+ * computation rather than a slope redrawn here. `line: false` suppresses the
5631
+ * band's own centre line, for a chart that already draws the fit with `fit`.
5632
+ *
5633
+ * Only where the x axis is numeric, for the same reason `fit` is.
5634
+ */
5635
+ band?: (RegressionBand & { line?: boolean }) | null;
5636
+ /**
5637
+ * An explicit point set, bypassing the by-column binder (BACKLOG-0000872): a
5638
+ * cartesian chart whose values are not a grid column — a scale-location plot's
5639
+ * √|standardised residual|, a coefficient forest's per-coefficient estimate —
5640
+ * hands its points in directly. Each is `{x, y}` with an optional `label`,
5641
+ * `size` (a bubble's third channel) and `lower`/`upper` (interval bounds the
5642
+ * error-bar primitive reads). Numeric `x` throughout gives a continuous axis.
5643
+ */
5644
+ points?: {
5645
+ x: number | string; y?: number; label?: string;
5646
+ size?: number; lower?: number; upper?: number; key?: string;
5647
+ }[];
5262
5648
  /**
5263
5649
  * Whiskers showing the uncertainty in each mark. `true` computes a confidence
5264
5650
  * interval from the readings behind the mark; `of` takes a symmetric margin
@@ -5422,6 +5808,43 @@ declare module 'lattice-grid/modules/charts' {
5422
5808
  columns: string[];
5423
5809
  reason: string | null;
5424
5810
  };
5811
+ /**
5812
+ * Turn a fitted regression model into diagnostic chart specs ready for
5813
+ * `createChart` (BACKLOG-0000812). Pass a precomputed `model`, or a `spec` to
5814
+ * fit one over the grid, and the `fitted` and `residual` fit-shadow column ids
5815
+ * the residual and QQ plots draw over.
5816
+ *
5817
+ * The presets that map onto grid columns come back as drawable specs: `fit`
5818
+ * (the fit line with its confidence band), `residualsFitted`, `qq`, and
5819
+ * `multicollinearity` (a correlogram over the predictors, with the model's
5820
+ * `vif` alongside). The three that need a per-row or per-coefficient quantity
5821
+ * the grid has no column for — `scaleLocation`, `residualsLeverage`,
5822
+ * `coefficientForest` — come back with a null `spec` and a stable `reason`,
5823
+ * rather than silently dropped.
5824
+ */
5825
+ export function regressionPlots(
5826
+ grid: Grid,
5827
+ opts?: {
5828
+ model?: RegressionModel;
5829
+ spec?: RegressionSpec;
5830
+ fitted?: string;
5831
+ residual?: string;
5832
+ rows?: object[] | ((grid: Grid) => object[]);
5833
+ confidence?: number;
5834
+ },
5835
+ ): {
5836
+ model: RegressionModel | null;
5837
+ plots: Record<
5838
+ 'fit' | 'residualsFitted' | 'qq' | 'multicollinearity'
5839
+ | 'scaleLocation' | 'residualsLeverage' | 'coefficientForest',
5840
+ {
5841
+ spec: ChartSpec | null;
5842
+ reason: string | null;
5843
+ vif?: number[] | null;
5844
+ coefficients?: RegressionCoefficient[] | null;
5845
+ }
5846
+ >;
5847
+ };
5425
5848
  export function registerScheme(name: string, colours: readonly string[]): void;
5426
5849
  export function resolveScheme(spec?: object): object;
5427
5850
  export function schemeNames(): string[];
@@ -5486,6 +5909,31 @@ declare module 'lattice-grid/modules/svelte' {
5486
5909
  export default createLatticeAction;
5487
5910
  }
5488
5911
 
5912
+ declare module 'lattice-grid/modules/angular' {
5913
+ /**
5914
+ * Build the Angular standalone component and directive from one shared
5915
+ * controller (BACKLOG-0000805).
5916
+ *
5917
+ * The Angular core namespace and `createGrid` are passed in, for the same
5918
+ * reason as every other adapter: the package ships no dependencies and cannot
5919
+ * import `@angular/core` or the grid. Pass `@angular/common`'s
5920
+ * `isPlatformBrowser` too for an explicit SSR guard; without it the adapter
5921
+ * guards on the presence of a `document`.
5922
+ *
5923
+ * The returned `LatticeGridComponent` (`<lattice-grid [config]="…">`) and
5924
+ * `LatticeGridDirective` (`<div [latticeGrid]="…">`) each expose the live grid
5925
+ * through a `grid` getter — the same `Grid` the vanilla `createGrid` returns,
5926
+ * or null before build — at parity with React's `ref.current.grid`. Grid
5927
+ * events are `@Output`s aliased to their dashed names (`(cell-changed)`).
5928
+ */
5929
+ export function createLatticeGrid(
5930
+ deps: { ng: unknown; createGrid: unknown; isPlatformBrowser?: (id: unknown) => boolean },
5931
+ ): { LatticeGridComponent: unknown; LatticeGridDirective: unknown };
5932
+ export const EVENT_NAMES: readonly string[];
5933
+ export function dashedName(event: string): string;
5934
+ export default createLatticeGrid;
5935
+ }
5936
+
5489
5937
  declare module 'lattice-grid/modules/webcomponent' {
5490
5938
  /**
5491
5939
  * Register `<lattice-grid>`.