@toclocoinc/lattice-grid 1.19.0 → 1.20.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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  dependencies, no build step required. Optional adapters for React, Vue, Svelte
5
5
  and Web Components ship alongside it.
6
6
 
7
- Version 1.19.0 · [latticegrid.dev](https://www.latticegrid.dev) · TOCLOCO Inc
7
+ Version 1.20.0 · [latticegrid.dev](https://www.latticegrid.dev) · TOCLOCO Inc
8
8
 
9
9
  ---
10
10
 
package/docs/API.html CHANGED
@@ -4126,6 +4126,36 @@ grid.destroy();
4126
4126
  translated.total,
4127
4127
  ].join('|');</code></pre>
4128
4128
 
4129
+ <h3 id="dhtmlx-spans-example">Cell spans, executed</h3>
4130
+ <p class="section-note">dhtmlx's imperative <code>addSpan</code> maintains a span table, and that table drives
4131
+ Lattice's own per-cell span functions — installed on each column's <code>cell</code> definition. A span
4132
+ declared through the shim is read back through the very functions the renderer calls.</p>
4133
+ <pre data-run="js" data-expect="3|2|1|1" data-covers="adapterKey:cell"><code><span class="cmt">// Aliased on import: the shim's span factory, bound to a local name.</span>
4134
+ <span class="kw">const</span> { createSpans: installSpans } = <span class="kw">await</span> import('../packages/modules/dhtmlx-compat/spans.js');
4135
+
4136
+ <span class="cmt">// A minimal stand-in for a grid: it just holds its columns, which is all the</span>
4137
+ <span class="cmt">// span shim touches. `createSpans` installs `cell.spanRows`/`cell.spanColumns`</span>
4138
+ <span class="cmt">// on each column by re-setting them through its own wrapper.</span>
4139
+ <span class="kw">let</span> columns = [{ id: 'name', cell: {} }];
4140
+ <span class="kw">const</span> grid = {
4141
+ get: () =&gt; columns,
4142
+ set: (_, next) =&gt; { columns = next; },
4143
+ };
4144
+
4145
+ <span class="kw">const</span> spans = installSpans(grid);
4146
+ spans.addSpan('R0', 'name', 3, 2); <span class="cmt">// rowspan 3, colspan 2</span>
4147
+
4148
+ <span class="cmt">// The column's own cell functions now read the maintained table.</span>
4149
+ <span class="kw">const</span> { cell } = columns[0];
4150
+ <span class="kw">const</span> spanned = { row: { key: 'R0' }, colId: 'name' };
4151
+ <span class="kw">const</span> plain = { row: { key: 'R1' }, colId: 'name' };
4152
+ <span class="kw">return</span> [
4153
+ cell.spanRows(spanned),
4154
+ cell.spanColumns(spanned),
4155
+ cell.spanRows(plain),
4156
+ cell.spanColumns(plain),
4157
+ ].join('|');</code></pre>
4158
+
4129
4159
  <h3 id="module-exports-example">Every module export, executed</h3>
4130
4160
  <p class="section-note">Nine shipped modules, each export resolved against its own barrel on every build.</p>
4131
4161
  <pre data-run="js" data-expect="60" data-covers="export:ContextMenu export:Messages export:Registry export:autoInit export:createGrid export:createLocalViewStorage export:createMessages export:createStat export:deltaOf export:gridElementsWithin export:hydrateTable export:mountPanel export:readTable export:toneOf export:Chart export:PALETTE export:SCHEMES export:TYPES export:createChart export:chartRange export:canChartRange export:deriveRangeSpec export:registerScheme export:resolveScheme export:schemeNames export:setDefaultScheme export:HTML_ROW_WARNING_THRESHOLD export:QUERY_CHANGED_EVENT export:SCROLL_NEAR_END_EVENT export:attach export:destroyWithin export:driveInfiniteScroll export:driveOobUpdates export:driveServerMode export:ingestResponse export:initWithin export:queryParams export:restoreStateWithin export:rowsFromFragment export:rowsFromJson export:saveStateWithin export:ATTRIBUTE_CONFIG export:EVENT_PREFIX export:GridElementController export:LatticeGrid export:TAG_NAME export:createLatticeGridElement export:defineLatticeGrid export:domEventName export:observedAttributeNames export:CONSOLE_ACTIVATION export:createDevtools export:expose export:EVENT_NAMES export:handlerName export:createLatticeGrid export:dashedName export:createLatticeAction export:Grid export:warnIfLargeHtmlPayload"><code><span class="cmt">// Every declared export of every shipped module, resolved against its own</span>
@@ -4550,6 +4580,17 @@ grid.destroy();
4550
4580
  </tbody>
4551
4581
  </table>
4552
4582
  </div>
4583
+ <h3 id="type-ApproximateEntry">ApproximateEntry</h3>
4584
+ <p class="section-note">One entry of the approximate maintenance tier.</p>
4585
+ <div class="table-wrap">
4586
+ <table>
4587
+ <thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
4588
+ <tbody>
4589
+ <tr><td class="name">sketch</td><td class="type">string</td><td class="desc">The sketch that backs this kernel: `HyperLogLog`, `KLL`, `SpaceSaving`.</td></tr>
4590
+ <tr><td class="name">bound</td><td class="type">ErrorBound</td><td class="desc">The error bound the sketch is verified to meet.</td></tr>
4591
+ </tbody>
4592
+ </table>
4593
+ </div>
4553
4594
  <h3 id="type-BooleanFormat">BooleanFormat</h3>
4554
4595
  <div class="table-wrap">
4555
4596
  <table>
@@ -4833,6 +4874,24 @@ grid.destroy();
4833
4874
  </tbody>
4834
4875
  </table>
4835
4876
  </div>
4877
+ <h3 id="type-ColumnDifference">ColumnDifference</h3>
4878
+ <p class="section-note">How one column differs between the filtered subset and its population.</p>
4879
+ <div class="table-wrap">
4880
+ <table>
4881
+ <thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
4882
+ <tbody>
4883
+ <tr><td class="name">column</td><td class="type">string</td><td class="desc">The column id.</td></tr>
4884
+ <tr><td class="name">name</td><td class="type">string</td><td class="desc">The column's display name, or its id.</td></tr>
4885
+ <tr><td class="name">measure</td><td class="type">'standardizedMeanDifference' | 'categoricalTotalVariation'</td><td class="desc">The effect size reported for this column's family: the standardized mean difference for a numeric column, the total variation of the category mix for a categorical one. Never a p-value.</td></tr>
4886
+ <tr><td class="name">magnitude</td><td class="type">number | null</td><td class="desc">The effect size in its own terms, or null when it has no scale here.</td></tr>
4887
+ <tr><td class="name">distance</td><td class="type">number</td><td class="desc">The total variation distance between subset and population, 0 to 1 — the common scale both families reduce to, and what the ranking sorts by.</td></tr>
4888
+ <tr><td class="name">direction</td><td class="type">number</td><td class="desc">+1 when the subset sits above the population, −1 below, 0 for a mix.</td></tr>
4889
+ <tr><td class="name">subsetN</td><td class="type">number</td><td class="desc">How many rows the subset comparison stood on.</td></tr>
4890
+ <tr><td class="name">populationN</td><td class="type">number</td><td class="desc">How many rows the population comparison stood on.</td></tr>
4891
+ <tr><td class="name">reliable</td><td class="type">boolean</td><td class="desc">False when the subset is too small to read the difference from.</td></tr>
4892
+ </tbody>
4893
+ </table>
4894
+ </div>
4836
4895
  <h3 id="type-ColumnDistribution">ColumnDistribution</h3>
4837
4896
  <div class="table-wrap">
4838
4897
  <table>
@@ -5505,6 +5564,19 @@ grid.destroy();
5505
5564
  </tbody>
5506
5565
  </table>
5507
5566
  </div>
5567
+ <h3 id="type-ErrorBound">ErrorBound</h3>
5568
+ <p class="section-note">How an approximate reduction's error bound holds, and what it measures.</p>
5569
+ <div class="table-wrap">
5570
+ <table>
5571
+ <thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
5572
+ <tbody>
5573
+ <tr><td class="name">kind</td><td class="type">'deterministic' | 'probabilistic' | 'exact'</td><td class="desc">`deterministic` every run, `probabilistic` in expectation, `exact` to float rounding.</td></tr>
5574
+ <tr><td class="name">metric</td><td class="type">'absolute' | 'relative' | 'rank' | 'none'</td><td class="desc">What the number measures. `rank` is a fraction of the rank, for quantiles.</td></tr>
5575
+ <tr><td class="name">value</td><td class="type">number</td><td class="desc">The bound itself, in the unit `metric` names.</td></tr>
5576
+ <tr><td class="name">statement</td><td class="type">string</td><td class="desc">A one-line human reading of the guarantee.</td></tr>
5577
+ </tbody>
5578
+ </table>
5579
+ </div>
5508
5580
  <h3 id="type-ExcelBorderSpec">ExcelBorderSpec</h3>
5509
5581
  <p class="section-note">A cell border, per edge. `true` means a thin line; a string names the style.</p>
5510
5582
  <div class="table-wrap">
@@ -5887,8 +5959,8 @@ grid.destroy();
5887
5959
  <tr><td class="name">facets</td><td class="type">FacetConfig | boolean</td><td class="desc">Column header histograms and the filters clicking them creates. Off by default: the band roughly doubles header height, which is a cost no grid should pay without asking. Per-column settings layer over these. <small>(optional)</small></td></tr>
5888
5960
  <tr><td class="name">hostFilter</td><td class="type">{ active(): boolean; passes(row: Row): boolean }</td><td class="desc">A filter your application owns, applied alongside the grid's own and invisible to its filter UI. <small>(optional)</small></td></tr>
5889
5961
  <tr><td class="name">context</td><td class="type">unknown</td><td class="desc">Anything of yours, passed untouched to renderers, editors and sources. <small>(optional)</small></td></tr>
5890
- <tr><td class="name">workerThreshold</td><td class="type">number</td><td class="desc">Row count above which a column distribution is computed in a Worker. <small>(optional)</small></td></tr>
5891
- <tr><td class="name">useWorker</td><td class="type">boolean</td><td class="desc">Compute column distributions off the main thread. Sorting, filtering and grouping run on the main thread; see the reference for why. <small>(optional)</small></td></tr>
5962
+ <tr><td class="name">workerThreshold</td><td class="type">number</td><td class="desc">Row count above which eligible work is computed in a Worker: column distributions, and a portable sort (a built-in collation with no custom comparator). Below it, everything runs on the main thread. <small>(optional)</small></td></tr>
5963
+ <tr><td class="name">useWorker</td><td class="type">boolean</td><td class="desc">Compute eligible work off the main thread: column distributions, and a portable sort above {@link GridConfig.workerThreshold} (a re-sort recomputes off-thread while the grid keeps showing the prior order, then swaps to the new one when it lands). Filtering and grouping still run on the main thread. <small>(optional)</small></td></tr>
5892
5964
  <tr><td class="name">workerUrl</td><td class="type">string</td><td class="desc">Where to load the worker kernel from, when hosting it yourself. <small>(optional)</small></td></tr>
5893
5965
  <tr><td class="name">sharedMemory</td><td class="type">boolean</td><td class="desc">Use a shared buffer for the worker, where the page's headers allow it. <small>(optional)</small></td></tr>
5894
5966
  <tr><td class="name">groupFooter</td><td class="type">boolean</td><td class="desc">A totals line at the foot of each group as well as the grid. <small>(optional)</small></td></tr>
@@ -6093,6 +6165,18 @@ grid.destroy();
6093
6165
  </tbody>
6094
6166
  </table>
6095
6167
  </div>
6168
+ <h3 id="type-MaintenanceTier">MaintenanceTier</h3>
6169
+ <p class="section-note">The maintenance label for one kernel across both tiers.</p>
6170
+ <div class="table-wrap">
6171
+ <table>
6172
+ <thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
6173
+ <tbody>
6174
+ <tr><td class="name">stat</td><td class="type">string</td><td class="desc">The kernel name.</td></tr>
6175
+ <tr><td class="name">exact</td><td class="type">'maintained' | 'rescan' | null</td><td class="desc">Its exact tier, or null when it is not an exact kernel.</td></tr>
6176
+ <tr><td class="name">approximate</td><td class="type">ApproximateEntry | null</td><td class="desc">The approximate alternative and bound, or null when none exists.</td></tr>
6177
+ </tbody>
6178
+ </table>
6179
+ </div>
6096
6180
  <h3 id="type-MaximiseApi">MaximiseApi</h3>
6097
6181
  <div class="table-wrap">
6098
6182
  <table>
@@ -6969,6 +7053,7 @@ grid.destroy();
6969
7053
  <tr><td class="name">tracking</td><td class="type">(): { columns: string[]; rows: number; forgotten: number }</td><td class="desc">What the shadow histories are costing.</td></tr>
6970
7054
  <tr><td class="name">reduce</td><td class="type">(colId: string, fn: string): unknown</td><td class="desc">Reduce a column by a named kernel over the filtered rows.</td></tr>
6971
7055
  <tr><td class="name">profile</td><td class="type">(colId: string): ColumnProfile | null</td><td class="desc">Everything worth knowing about one column, in one pass each.</td></tr>
7056
+ <tr><td class="name">subsetVsPopulation</td><td class="type">(opts?: { columns?: string[] }): SubsetComparison</td><td class="desc">Which columns differ most between the filtered subset and the whole population it was drawn from, ranked by effect size — never by a p-value. The measure is stated per column; a numeric and a categorical column are put on one bounded scale so they rank against each other.</td></tr>
6972
7057
  <tr><td class="name">correlation</td><td class="type">(a: string, b: string): number | null</td><td class="desc">Pearson's correlation between two columns.</td></tr>
6973
7058
  <tr><td class="name">covariance</td><td class="type">(a: string, b: string, opts?: { population?: boolean }): number | null</td><td class="desc">Covariance, a correlation before the scales are divided out.</td></tr>
6974
7059
  <tr><td class="name">regression</td><td class="type">(a: string, b: string): RegressionFit | null</td><td class="desc">Least-squares fit of `b` on `a`: in finance, beta and alpha.</td></tr>
@@ -6981,6 +7066,8 @@ grid.destroy();
6981
7066
  <tr><td class="name">weightedAverage</td><td class="type">(colId: string, weightId: string): number | null</td><td class="desc">A weighted average of one column by another.</td></tr>
6982
7067
  <tr><td class="name">keyOf</td><td class="type">(data: unknown): string | null</td><td class="desc">The key a row's data resolves to.</td></tr>
6983
7068
  <tr><td class="name">maintenance</td><td class="type">Readonly&lt;Record&lt;string, 'maintained' | 'rescan'&gt;&gt;</td><td class="desc">Which reductions can be maintained against a change, and which rescan. <small>(read-only)</small></td></tr>
7069
+ <tr><td class="name">approximate</td><td class="type">Readonly&lt;Record&lt;string, ApproximateEntry&gt;&gt;</td><td class="desc">The approximate tier: kernels a sketch maintains in constant time per tick, keyed by kernel name, each carrying the sketch that backs it and the error bound that sketch is verified to meet. <small>(read-only)</small></td></tr>
7070
+ <tr><td class="name">maintenanceTier</td><td class="type">(fn: string): MaintenanceTier</td><td class="desc">The honest tier for one kernel across both the exact and approximate maps: its exact tier and, when one exists, the approximate alternative and bound.</td></tr>
6984
7071
  </tbody>
6985
7072
  </table>
6986
7073
  </div>
@@ -7009,6 +7096,20 @@ grid.destroy();
7009
7096
  </tbody>
7010
7097
  </table>
7011
7098
  </div>
7099
+ <h3 id="type-SubsetComparison">SubsetComparison</h3>
7100
+ <p class="section-note">The subset-vs-population ranking (BACKLOG-0000653).</p>
7101
+ <div class="table-wrap">
7102
+ <table>
7103
+ <thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
7104
+ <tbody>
7105
+ <tr><td class="name">ranked</td><td class="type">ColumnDifference[]</td><td class="desc">Every compared column, largest difference first.</td></tr>
7106
+ <tr><td class="name">subsetN</td><td class="type">number</td><td class="desc">How many rows the filtered subset holds.</td></tr>
7107
+ <tr><td class="name">populationN</td><td class="type">number</td><td class="desc">How many rows the whole population holds.</td></tr>
7108
+ <tr><td class="name">filtered</td><td class="type">boolean</td><td class="desc">Whether a filter is actually narrowing the set.</td></tr>
7109
+ <tr><td class="name">measures</td><td class="type">{ numeric: string; categorical: string; common: string }</td><td class="desc">The measure each family reports, and the common scale, named for a legend.</td></tr>
7110
+ </tbody>
7111
+ </table>
7112
+ </div>
7012
7113
  <h3 id="type-TextFormat">TextFormat</h3>
7013
7114
  <div class="table-wrap">
7014
7115
  <table>
@@ -7174,6 +7275,18 @@ grid.destroy();
7174
7275
  </tbody>
7175
7276
  </table>
7176
7277
  </div>
7278
+ <h3 id="type-WindowSpec">WindowSpec</h3>
7279
+ <p class="section-note">The window a windowed aggregate was computed over.</p>
7280
+ <div class="table-wrap">
7281
+ <table>
7282
+ <thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
7283
+ <tbody>
7284
+ <tr><td class="name">kind</td><td class="type">'count' | 'time' | 'session'</td><td class="desc">Which window: last N ticks, last N ms, or the session.</td></tr>
7285
+ <tr><td class="name">span</td><td class="type">number</td><td class="desc">The size: N ticks, N ms, or the session duration in ms.</td></tr>
7286
+ <tr><td class="name">size</td><td class="type">number</td><td class="desc">How many values actually fell inside the window.</td></tr>
7287
+ </tbody>
7288
+ </table>
7289
+ </div>
7177
7290
  <!-- END GENERATED TYPE REFERENCE -->
7178
7291
 
7179
7292
  <footer>
@@ -437,7 +437,7 @@
437
437
  <div class="shell">
438
438
  <aside class="rail">
439
439
  <p class="rail__brand">Lattice Grid</p>
440
- <p class="rail__sub">Developer guide · v1.19.0</p>
440
+ <p class="rail__sub">Developer guide · v1.20.0</p>
441
441
  <nav>
442
442
  <div class="rail__group">
443
443
  <span class="rail__label">Start here</span>
@@ -4307,9 +4307,11 @@ const providerFor = (id) =&gt; ({
4307
4307
  ordinary filters. Pausing the stream brings the charts back, a paused stream is a still
4308
4308
  one: unless you set <code>whilePaused: false</code>.</p>
4309
4309
  <p><strong>Counting runs off the main thread above <code>workerThreshold</code>.</strong>
4310
- Distributions are the only work the grid moves to a Worker. Sorting, filtering and grouping
4311
- run on the main thread; nothing waits on a histogram, which is what makes this one
4312
- offloadable. The column is copied, or shared where cross-origin isolation makes
4310
+ A distribution was the first work the grid moved to a Worker: nothing waits on a histogram,
4311
+ which is what made it offloadable without an async pipeline. A portable sort a built-in
4312
+ collation with no custom comparator now also recomputes off-thread above the threshold,
4313
+ serving the prior order until the new one lands. Filtering and grouping still run on the main
4314
+ thread. The column is copied, or shared where cross-origin isolation makes
4313
4315
  <code>SharedArrayBuffer</code> available; it is never transferred, because transferring would
4314
4316
  detach the buffer the grid is still rendering from.</p>
4315
4317
  <p><strong>The Worker settings.</strong> <code>useWorker</code> and
package/lattice-grid.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.19.0, type declarations
2
+ * Lattice Grid 1.20.0, type declarations
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -1563,11 +1563,17 @@ export interface GridConfig {
1563
1563
  hostFilter?: { active(): boolean; passes(row: Row): boolean };
1564
1564
  /** Anything of yours, passed untouched to renderers, editors and sources. */
1565
1565
  context?: unknown;
1566
- /** Row count above which a column distribution is computed in a Worker. */
1566
+ /**
1567
+ * Row count above which eligible work is computed in a Worker: column
1568
+ * distributions, and a portable sort (a built-in collation with no custom
1569
+ * comparator). Below it, everything runs on the main thread.
1570
+ */
1567
1571
  workerThreshold?: number;
1568
1572
  /**
1569
- * Compute column distributions off the main thread. Sorting, filtering and
1570
- * grouping run on the main thread; see the reference for why.
1573
+ * Compute eligible work off the main thread: column distributions, and a
1574
+ * portable sort above {@link GridConfig.workerThreshold} (a re-sort recomputes
1575
+ * off-thread while the grid keeps showing the prior order, then swaps to the
1576
+ * new one when it lands). Filtering and grouping still run on the main thread.
1571
1577
  */
1572
1578
  useWorker?: boolean;
1573
1579
  /** Where to load the worker kernel from, when hosting it yourself. */
@@ -2216,6 +2222,13 @@ export interface StatisticsApi {
2216
2222
  reduce(colId: string, fn: string): unknown;
2217
2223
  /** Everything worth knowing about one column, in one pass each. */
2218
2224
  profile(colId: string): ColumnProfile | null;
2225
+ /**
2226
+ * Which columns differ most between the filtered subset and the whole
2227
+ * population it was drawn from, ranked by effect size — never by a p-value.
2228
+ * The measure is stated per column; a numeric and a categorical column are put
2229
+ * on one bounded scale so they rank against each other.
2230
+ */
2231
+ subsetVsPopulation(opts?: { columns?: string[] }): SubsetComparison;
2219
2232
  /** Pearson's correlation between two columns. */
2220
2233
  correlation(a: string, b: string): number | null;
2221
2234
  /** Covariance, a correlation before the scales are divided out. */
@@ -2265,6 +2278,57 @@ export interface StatisticsApi {
2265
2278
  keyOf(data: unknown): string | null;
2266
2279
  /** Which reductions can be maintained against a change, and which rescan. */
2267
2280
  readonly maintenance: Readonly<Record<string, 'maintained' | 'rescan'>>;
2281
+ /**
2282
+ * The approximate tier: kernels a sketch maintains in constant time per tick,
2283
+ * keyed by kernel name, each carrying the sketch that backs it and the error
2284
+ * bound that sketch is verified to meet.
2285
+ */
2286
+ readonly approximate: Readonly<Record<string, ApproximateEntry>>;
2287
+ /**
2288
+ * The honest tier for one kernel across both the exact and approximate maps:
2289
+ * its exact tier and, when one exists, the approximate alternative and bound.
2290
+ */
2291
+ maintenanceTier(fn: string): MaintenanceTier;
2292
+ }
2293
+
2294
+ /** How an approximate reduction's error bound holds, and what it measures. */
2295
+ export interface ErrorBound {
2296
+ /** `deterministic` every run, `probabilistic` in expectation, `exact` to float rounding. */
2297
+ kind: 'deterministic' | 'probabilistic' | 'exact';
2298
+ /** What the number measures. `rank` is a fraction of the rank, for quantiles. */
2299
+ metric: 'absolute' | 'relative' | 'rank' | 'none';
2300
+ /** The bound itself, in the unit `metric` names. */
2301
+ value: number;
2302
+ /** A one-line human reading of the guarantee. */
2303
+ statement: string;
2304
+ }
2305
+
2306
+ /** One entry of the approximate maintenance tier. */
2307
+ export interface ApproximateEntry {
2308
+ /** The sketch that backs this kernel: `HyperLogLog`, `KLL`, `SpaceSaving`. */
2309
+ sketch: string;
2310
+ /** The error bound the sketch is verified to meet. */
2311
+ bound: ErrorBound;
2312
+ }
2313
+
2314
+ /** The maintenance label for one kernel across both tiers. */
2315
+ export interface MaintenanceTier {
2316
+ /** The kernel name. */
2317
+ stat: string;
2318
+ /** Its exact tier, or null when it is not an exact kernel. */
2319
+ exact: 'maintained' | 'rescan' | null;
2320
+ /** The approximate alternative and bound, or null when none exists. */
2321
+ approximate: ApproximateEntry | null;
2322
+ }
2323
+
2324
+ /** The window a windowed aggregate was computed over. */
2325
+ export interface WindowSpec {
2326
+ /** Which window: last N ticks, last N ms, or the session. */
2327
+ kind: 'count' | 'time' | 'session';
2328
+ /** The size: N ticks, N ms, or the session duration in ms. */
2329
+ span: number;
2330
+ /** How many values actually fell inside the window. */
2331
+ size: number;
2268
2332
  }
2269
2333
 
2270
2334
  export type ShadowKind =
@@ -2367,6 +2431,49 @@ export interface HistogramBin {
2367
2431
  count: number;
2368
2432
  }
2369
2433
 
2434
+ /** How one column differs between the filtered subset and its population. */
2435
+ export interface ColumnDifference {
2436
+ /** The column id. */
2437
+ column: string;
2438
+ /** The column's display name, or its id. */
2439
+ name: string;
2440
+ /**
2441
+ * The effect size reported for this column's family: the standardized mean
2442
+ * difference for a numeric column, the total variation of the category mix for
2443
+ * a categorical one. Never a p-value.
2444
+ */
2445
+ measure: 'standardizedMeanDifference' | 'categoricalTotalVariation';
2446
+ /** The effect size in its own terms, or null when it has no scale here. */
2447
+ magnitude: number | null;
2448
+ /**
2449
+ * The total variation distance between subset and population, 0 to 1 — the
2450
+ * common scale both families reduce to, and what the ranking sorts by.
2451
+ */
2452
+ distance: number;
2453
+ /** +1 when the subset sits above the population, −1 below, 0 for a mix. */
2454
+ direction: number;
2455
+ /** How many rows the subset comparison stood on. */
2456
+ subsetN: number;
2457
+ /** How many rows the population comparison stood on. */
2458
+ populationN: number;
2459
+ /** False when the subset is too small to read the difference from. */
2460
+ reliable: boolean;
2461
+ }
2462
+
2463
+ /** The subset-vs-population ranking (BACKLOG-0000653). */
2464
+ export interface SubsetComparison {
2465
+ /** Every compared column, largest difference first. */
2466
+ ranked: ColumnDifference[];
2467
+ /** How many rows the filtered subset holds. */
2468
+ subsetN: number;
2469
+ /** How many rows the whole population holds. */
2470
+ populationN: number;
2471
+ /** Whether a filter is actually narrowing the set. */
2472
+ filtered: boolean;
2473
+ /** The measure each family reports, and the common scale, named for a legend. */
2474
+ measures: { numeric: string; categorical: string; common: string };
2475
+ }
2476
+
2370
2477
  export interface FormattingApi {
2371
2478
  list(scope?: FormattingScope): FormattingRule[];
2372
2479
  all(): Record<FormattingScope, FormattingRule[]>;