@toclocoinc/lattice-grid 1.28.0 → 1.29.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 +1 -1
- package/docs/API.html +229 -13
- package/docs/api-detail.html +61 -4
- package/lattice-grid.d.ts +321 -8
- package/lattice-grid.esm.min.js +2092 -533
- package/lattice-grid.min.cjs +2092 -533
- package/lattice-grid.min.js +2092 -533
- package/modules/angular.esm.min.js +264 -0
- package/modules/angular.min.cjs +265 -0
- package/modules/angular.min.js +265 -0
- package/modules/charts.esm.min.js +366 -4
- package/modules/charts.min.cjs +365 -4
- package/modules/charts.min.js +365 -4
- package/modules/devtools.esm.min.js +2 -2
- package/modules/devtools.min.cjs +2 -2
- package/modules/devtools.min.js +2 -2
- package/modules/dhtmlx-compat.esm.min.js +4 -4
- package/modules/dhtmlx-compat.min.cjs +4 -4
- package/modules/dhtmlx-compat.min.js +4 -4
- package/modules/htmx.esm.min.js +2092 -533
- package/modules/htmx.min.cjs +2092 -533
- package/modules/htmx.min.js +2092 -533
- package/modules/react.esm.min.js +4 -3
- package/modules/react.min.cjs +4 -3
- package/modules/react.min.js +4 -3
- package/modules/svelte.esm.min.js +4 -3
- package/modules/svelte.min.cjs +4 -3
- package/modules/svelte.min.js +4 -3
- package/modules/vue.esm.min.js +4 -3
- package/modules/vue.min.cjs +4 -3
- package/modules/vue.min.js +4 -3
- package/modules/webcomponent.esm.min.js +2092 -533
- package/modules/webcomponent.min.cjs +2092 -533
- package/modules/webcomponent.min.js +2092 -533
- package/package.json +1 -1
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.
|
|
7
|
+
Version 1.29.0 · [latticegrid.dev](https://www.latticegrid.dev) · TOCLOCO Inc
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
package/docs/API.html
CHANGED
|
@@ -848,7 +848,7 @@ autoInit(document); <span class="cmt">// builds every [data-lattice-grid] under
|
|
|
848
848
|
<tbody>
|
|
849
849
|
<tr><td class="name">statusBar</td><td class="type">boolean | { panels }</td><td class="desc">Composable panels along the bottom. Default set: <code>rowCount</code>, <code>selectedCount</code>, <code>aggregation</code>, <code>comments</code>, <code>updates</code>, <code>progress</code>. Each is silent when it has nothing to report.</td></tr>
|
|
850
850
|
<tr><td class="name">maximise</td><td class="type">boolean</td><td class="dflt">true</td><td class="desc"><code>false</code> removes the rail button and <code>grid.maximise</code>, for an application with its own full-screen mode.</td></tr>
|
|
851
|
-
<tr><td class="name">toolPanel</td><td class="type">boolean | object</td><td class="desc">Side dock. <code>panels</code>: <code>columns</code>, <code>filters</code>, <code>views</code>, <code>quick</code>, <code>formatting</code>, <code>statistics</code>. <code>side: 'left'</code> makes it the icon rail, which also turns on <code>actions</code> (<code>undo</code>, <code>redo</code>, <code>pause</code>, <code>restore</code>, <code>maximise</code>, then the export group: <code>export</code>, <code>excel</code>, <code>clipboard</code>, <code>print</code>: nine in all, and an array takes these names rather than the button labels) and <code>icons</code>. An explicit array <em>replaces</em> that list rather than extending it; a bare <code>'-'</code> in it renders a divider between groups. <code>exportName</code> names the CSV. <code>annotate: true</code> adds the native annotation tools — <code>pen</code>, <code>arrow</code>, <code>rect</code>, <code>highlight</code> — to the rail as toggle buttons (pressed while in use, pressed again to exit); they also appear automatically for the duration of a presentation.</td></tr>
|
|
851
|
+
<tr><td class="name">toolPanel</td><td class="type">boolean | object</td><td class="desc">Side dock. <code>panels</code>: <code>columns</code>, <code>filters</code>, <code>views</code>, <code>quick</code>, <code>formatting</code>, <code>statistics</code>, <code>regression</code>. <code>side: 'left'</code> makes it the icon rail, which also turns on <code>actions</code> (<code>undo</code>, <code>redo</code>, <code>pause</code>, <code>restore</code>, <code>maximise</code>, then the export group: <code>export</code>, <code>excel</code>, <code>clipboard</code>, <code>print</code>: nine in all, and an array takes these names rather than the button labels) and <code>icons</code>. An explicit array <em>replaces</em> that list rather than extending it; a bare <code>'-'</code> in it renders a divider between groups. <code>exportName</code> names the CSV. <code>annotate: true</code> adds the native annotation tools — <code>pen</code>, <code>arrow</code>, <code>rect</code>, <code>highlight</code> — to the rail as toggle buttons (pressed while in use, pressed again to exit); they also appear automatically for the duration of a presentation.</td></tr>
|
|
852
852
|
<tr><td class="name">groupPanel</td><td class="type">boolean | object</td><td class="desc">A drag-and-drop group-by strip above the column header — the row-group panel. Drag a heading into it to group by that column; the active groups show as removable, reorderable chips, and reordering the chips changes the nesting order. It is keyboard-operable — arrows move between chips, <code>Shift</code> with an arrow reorders, <code>Delete</code> ungroups, and an add control groups any column — and every change is announced through the live region. Off by default and non-breaking; it drives the same model as <code>grid.columns.group()</code> and reimplements nothing. The object form takes <code>hint</code>, the placeholder shown while nothing is grouped.</td></tr>
|
|
853
853
|
<tr><td class="name">kpis</td><td class="type">StatConfig[]</td><td class="desc">A built-in KPI/stat strip: a labelled band of stat tiles the grid places for you above the column header. Each entry is a <code>createStat</code> spec — <code>of</code>, <code>fn</code>, <code>title</code>, <code>interval</code>, <code>footer</code>, <code>format</code> and the rest, minus <code>grid</code> and <code>container</code>, which the grid supplies — so a strip tile and a hand-placed one are the same object. The tiles follow the grid's filters, recomputing on every change like a stand-alone stat does. Off by default and non-breaking; it reuses <code>createStat</code> and reimplements no compute.</td></tr>
|
|
854
854
|
<tr><td class="name">timeZone</td><td class="type">string</td><td class="desc">An IANA zone every date column formats and parses in, so a grid shows one zone whatever the viewer's machine says. Individual columns may override it.</td></tr>
|
|
@@ -990,7 +990,7 @@ autoInit(document); <span class="cmt">// builds every [data-lattice-grid] under
|
|
|
990
990
|
<tr><td class="name">sort</td><td class="desc"><code>enabled</code>, <code>direction</code>, <code>order</code>, <code>nullsFirst</code></td></tr>
|
|
991
991
|
<tr><td class="name">filter</td><td class="desc"><code>enabled</code>, <code>type</code>, <code>props</code></td></tr>
|
|
992
992
|
<tr><td class="name">layout</td><td class="desc"><code>width</code>, <code>min</code>, <code>max</code>, <code>flex</code>, <code>pin</code>, <code>hidden</code>, <code>resizable</code>, <code>movable</code>, <code>lockVisible</code>, <code>lockPosition</code>. A <code>pin</code> of <code>'start'</code> or <code>'end'</code> holds the viewport edge while there is something to scroll; where the columns do not fill the grid, spare width falls beyond the last column rather than in front of it.</td></tr>
|
|
993
|
-
<tr><td class="name">header</td><td class="desc"><code>template</code>, <code>render</code>, <code>props</code>, <code>class</code>, <code>tooltip</code>, <code>align</code
|
|
993
|
+
<tr><td class="name">header</td><td class="desc"><code>template</code>, <code>render</code>, <code>props</code>, <code>class</code>, <code>tooltip</code>, <code>align</code>. <code>render</code> draws a custom heading and may be a <strong>function</strong> or a <strong>component</strong> (a class with a <code>render</code> method); the two forms are interchangeable and each may either append to the passed heading element itself (returning nothing) or <em>return</em> an <code>Element</code> (attached for you) or a <code>string</code> (used as the heading text). <code>class</code> adds a class to the heading cell; <code>template</code> is not read.</td></tr>
|
|
994
994
|
</tbody>
|
|
995
995
|
</table>
|
|
996
996
|
</div>
|
|
@@ -1819,6 +1819,8 @@ grid.statistics.shadow('price', 'delta', 'R42'); // one row's shadow value
|
|
|
1819
1819
|
grid.statistics.rebase('price'); // "mark all": today's values become the baseline
|
|
1820
1820
|
grid.statistics.tracking(); // { columns, rows, forgotten }</code></pre>
|
|
1821
1821
|
<p>The <code>statistics</code> tool panel is the end-user half of <code>profile()</code>: a column picker, the twelve figures and a histogram of the column's shape, all following the filters. Add it with <code>toolPanel: { panels: ['columns', 'statistics'] }</code>.</p>
|
|
1822
|
+
<p>The <code>regression</code> tool panel is its multi-column sibling (BACKLOG-0000812): it fits the model you name and shows the coefficient table — each term's estimate ± standard error with its t and p — alongside R² and adjusted R², the variance-inflation factor per predictor, and the Breusch–Pagan heteroscedasticity flag, all over the filtered rows and computed by the one core engine (<code>grid.statistics.regressionModel</code>). Name the model on the panel: <code>toolPanel: { panels: ['columns', { name: 'regression', props: { predictors: ['x1', 'x2'], response: 'y' } }] }</code>. p-values are reported as numbers with a documented method, never a significance verdict.</p>
|
|
1823
|
+
<p>The same fitted model can live in the data as shadow columns (BACKLOG-0000812): <code>shadow: { kind: 'fitPredicted', model: { predictors: ['x'], response: 'y' } }</code>, and likewise <code>fitResidual</code> and <code>fitInfluence</code> — plus <code>fitStdResidual</code>, <code>fitLeverage</code> and <code>fitCooksD</code> (BACKLOG-0000872), which surface the internally studentised residual, the hat-matrix leverage and Cook's distance the engine already computes. They are ordinary numeric/boolean cells — sortable, filterable, groupable, exportable — that read the fit by row key and follow the grid's filters (the model refits over the filtered rows); a row outside the fit reads <code>null</code>. <code>fitInfluence</code> flags Cook's D > 4/n by default (overridable with <code>threshold</code>), keeping "not influential" (<code>false</code>) and "cannot tell" (<code>null</code>) distinct.</p>
|
|
1822
1824
|
<p>It shows the twelve one-pass figures, then <strong>Shape</strong> (skewness, kurtosis, Jarque–Bera), <strong>Robust</strong> (trimmed and winsorized means, MAD, robust outliers), <strong>Concentration</strong> (Gini, HHI, entropy, evenness, top-3 share) and <strong>Capability</strong> where the column declares a <code>spec</code>. A section whose reductions all return null is left out rather than shown as a column of dashes.</p>
|
|
1823
1825
|
<p>Or put it in your own page. <code>mountPanel</code> takes no dock and does not create one: <code>toolPanel</code> may be off entirely, so a statistics readout can sit beside a chart, in your own sidebar, or in a settings dialog, at whatever size you give it. It repaints on the same events the rail does, so it stays in step with filters, edits and saved views without you subscribing to anything.</p>
|
|
1824
1826
|
<pre><code>import { mountPanel } from '@toclocoinc/lattice-grid';
|
|
@@ -1826,7 +1828,7 @@ grid.statistics.tracking(); // { columns, rows, forgotten
|
|
|
1826
1828
|
const stats = mountPanel({ grid, panel: 'statistics', container: sidebar });
|
|
1827
1829
|
stats.refresh(); // for a change the grid does not announce
|
|
1828
1830
|
stats.destroy(); // yours to call: the element belongs to your page</code></pre>
|
|
1829
|
-
<p>Any built-in panel works: <code>columns</code>, <code>filters</code>, <code>views</code>, <code>quick</code>, <code>formatting</code>, <code>statistics</code>, <code>compare</code>, <code>insights</code>, as does a constructor of your own.</p>
|
|
1831
|
+
<p>Any built-in panel works: <code>columns</code>, <code>filters</code>, <code>views</code>, <code>quick</code>, <code>formatting</code>, <code>statistics</code>, <code>regression</code>, <code>compare</code>, <code>insights</code>, as does a constructor of your own.</p>
|
|
1830
1832
|
|
|
1831
1833
|
<h3>The insights panel</h3>
|
|
1832
1834
|
<p>The <code>insights</code> tool panel is the on-screen half of the comparison analytics (§9.9): the API-only <code>subsetVsPopulation()</code>, <code>datasetVsDataset()</code>, <code>capability()</code> and <code>compareGroups()</code> rendered without you building any UI. It is opt-in — off unless you name it. Add it with <code>toolPanel: { panels: ['columns', 'insights'] }</code>.</p>
|
|
@@ -1994,6 +1996,53 @@ createGrid(el, {
|
|
|
1994
1996
|
<div class="note"><p>Positional kinds rank over every <em>tracked</em> row, not over the filtered set: a rank that changed as you filtered would make "the top ten movers" depend on what happened to be on screen, and the column would disagree with itself between two views of the same data. Pass <code>scope: 'filtered'</code> on the shadow spec to rank within what the filters left instead: both answers are legitimate, which is why it is a choice rather than a default.</p></div>
|
|
1995
1997
|
<div class="note"><p>Shadow state is keyed by row key, never by index: after any sort an index-keyed history would report one row's past against another row's present, and the wrong number would be <em>sortable</em>. Memory is capped at 200,000 tracked rows per column; past that the oldest are dropped and <code>tracking().forgotten</code> says how many, rather than a smaller number being reported as though it were the truth.</p></div>
|
|
1996
1998
|
|
|
1999
|
+
<h3 id="rolling-shadows">Rolling time-series columns</h3>
|
|
2000
|
+
<p>A total answers "how much"; a <em>rolling</em> total answers "how much lately, as the series ran" — the seven-day average that smooths a daily figure, the trailing sum, the change on the period before. These are rolling shadow kinds (BACKLOG-0000748): real columns, sortable and filterable and exportable like any other, computed in one ordered pass and cached by row key. They <strong>compose the windowed-aggregate model</strong> the grid already uses for "the average lately" over a live stream, asked instead over a column arranged in a stated order.</p>
|
|
2001
|
+
<p>The order is explicit and required — an <code>orderBy</code> column, never the screen sort, because a rolling figure defined by the current sort would change on every header click and a column sorted on its own rolling value would define itself. The window is the last <code>span</code> rows (<code>count</code>), the last span of the order axis (<code>time</code>), or the whole series so far (<code>session</code>). The first rows carry a <em>partial</em> window; that figure is still emitted, but a <code>windowCoverage</code> companion stamps how much of the window it actually covers, so a two-day average is never shown as a seven-day one. <code>within</code> chooses per-group (the default, partitioned by the grid's grouping) or across the whole dataset.</p>
|
|
2002
|
+
<p>A <code>rollingQuantile</code> (a trailing median, a p95, set by <code>q</code>) is exact while the window is small and comes from a KLL sketch past an internal span cap and for a session window — where a <code>windowApproximate</code> companion reports which rows are approximate, so a sketched quantile is never presented as exact. At a million rows the single ordered pass stays well within the suite's budget (≈380ms for the window aggregates, ≈490ms for the exact rolling median, ≈420ms for the session sketch on the reference bench).</p>
|
|
2003
|
+
<pre><code>columns: [
|
|
2004
|
+
{ field: 'day', type: 'date' },
|
|
2005
|
+
{ field: 'sales', type: 'number' },
|
|
2006
|
+
{ id: 'ma7', title: '7-day avg', shadow: { kind: 'rollingAvg', of: 'sales', orderBy: 'day', window: { kind: 'count', span: 7 } } },
|
|
2007
|
+
{ id: 'cover', title: 'Coverage', shadow: { kind: 'windowCoverage', of: 'sales', orderBy: 'day', window: { kind: 'count', span: 7 } } },
|
|
2008
|
+
{ id: 'p50', title: '30-day median', shadow: { kind: 'rollingQuantile', of: 'sales', orderBy: 'day', window: { kind: 'count', span: 30 }, q: 0.5 } },
|
|
2009
|
+
{ id: 'ytd', title: 'Cumulative', shadow: { kind: 'cumulativeToDate', of: 'sales', orderBy: 'day' } },
|
|
2010
|
+
{ id: 'delta', title: 'vs prev', shadow: { kind: 'periodOverPeriod', of: 'sales', orderBy: 'day' } },
|
|
2011
|
+
]</code></pre>
|
|
2012
|
+
<p>A rolling window is a property of the series, so it is computed over every row before any filter: hiding rows with a filter narrows what you see, never what "the last seven" means. A missing reading is a gap, skipped rather than treated as a zero that would report a plunge and a rebound the series never made.</p>
|
|
2013
|
+
<pre data-run="js" data-expect="11|3.6667|4.6667|0.33|20|2|4" data-covers="export:createHeadlessGrid"><code><span class="kw">const</span> { createHeadlessGrid } = <span class="kw">await</span> import('../packages/core/src/index.js');
|
|
2014
|
+
<span class="cmt">// A short series, ordered by t: values 2,4,5,4,5.</span>
|
|
2015
|
+
<span class="kw">const</span> base = { of: 'v', orderBy: 't', within: 'all' };
|
|
2016
|
+
<span class="kw">const</span> win = { kind: 'count', span: 3 };
|
|
2017
|
+
<span class="kw">const</span> grid = createHeadlessGrid({
|
|
2018
|
+
columns: [
|
|
2019
|
+
{ field: 't', type: 'number' },
|
|
2020
|
+
{ field: 'v', type: 'number' },
|
|
2021
|
+
{ id: 'sum', shadow: { kind: 'rollingSum', window: win, ...base } },
|
|
2022
|
+
{ id: 'avg', shadow: { kind: 'rollingAvg', window: win, ...base } },
|
|
2023
|
+
{ id: 'cov', shadow: { kind: 'windowCoverage', window: win, ...base } },
|
|
2024
|
+
{ id: 'med', shadow: { kind: 'rollingQuantile', window: win, q: 0.5, ...base } },
|
|
2025
|
+
{ id: 'cum', shadow: { kind: 'cumulativeToDate', ...base } },
|
|
2026
|
+
{ id: 'pop', shadow: { kind: 'periodOverPeriod', ...base } },
|
|
2027
|
+
],
|
|
2028
|
+
rows: [
|
|
2029
|
+
{ id: 'r1', t: 1, v: 2 }, { id: 'r2', t: 2, v: 4 }, { id: 'r3', t: 3, v: 5 },
|
|
2030
|
+
{ id: 'r4', t: 4, v: 4 }, { id: 'r5', t: 5, v: 5 },
|
|
2031
|
+
],
|
|
2032
|
+
rowKey: 'id',
|
|
2033
|
+
});
|
|
2034
|
+
<span class="kw">const</span> round4 = (x) => Math.round(x * 10000) / 10000;
|
|
2035
|
+
<span class="kw">const</span> round2 = (x) => Math.round(x * 100) / 100;
|
|
2036
|
+
<span class="kw">return</span> [
|
|
2037
|
+
grid.rows.value('r3', 'sum'), <span class="cmt">// 2+4+5 = 11</span>
|
|
2038
|
+
round4(grid.rows.value('r3', 'avg')), <span class="cmt">// 11/3</span>
|
|
2039
|
+
round4(grid.rows.value('r5', 'avg')), <span class="cmt">// (5+4+5)/3</span>
|
|
2040
|
+
round2(grid.rows.value('r1', 'cov')), <span class="cmt">// 1/3 of the window filled</span>
|
|
2041
|
+
grid.rows.value('r5', 'cum'), <span class="cmt">// running total to the end</span>
|
|
2042
|
+
grid.rows.value('r2', 'pop'), <span class="cmt">// 4 - 2</span>
|
|
2043
|
+
grid.rows.value('r3', 'med'), <span class="cmt">// median of 2,4,5 = 4</span>
|
|
2044
|
+
].join('|');</code></pre>
|
|
2045
|
+
|
|
1997
2046
|
<h2 id="highlight">grid.highlight</h2>
|
|
1998
2047
|
<p>One mechanism for two jobs: the flash a changed cell makes, and a marker you paint deliberately. A target is a cell (<code>{key, colId}</code>), a row (<code>{key}</code>, or a bare row key) or a column (<code>{colId}</code>). Cell beats row beats column, so a specific highlight is never hidden by a broad one laid over it.</p>
|
|
1999
2048
|
<pre><code>createGrid(el, {
|
|
@@ -3404,6 +3453,7 @@ off(); <span class="cmt">// on() returns i
|
|
|
3404
3453
|
<tr><td class="name">licence:changed</td><td class="type">{ info, state }</td><td class="desc">A key was installed, and again when verification settles.</td></tr>
|
|
3405
3454
|
<tr><td class="name">columns:changed</td><td class="desc">The column set was replaced or reordered wholesale.</td></tr>
|
|
3406
3455
|
<tr><td class="name">columns:tagged</td><td class="desc">A column's tags changed.</td></tr>
|
|
3456
|
+
<tr><td class="name">columngroup:changed</td><td class="desc">A banded header was formed, renamed, dissolved, moved, or a column joined or left one — by drag, keyboard or API.</td></tr>
|
|
3407
3457
|
<tr><td class="name">detail:toggled</td><td class="desc">A master-detail row opened or closed.</td></tr>
|
|
3408
3458
|
<tr><td class="name">formatting:changed</td><td class="desc">A conditional formatting rule was added, edited, reordered or restated.</td></tr>
|
|
3409
3459
|
<tr><td class="name">redaction:changed</td><td class="desc">A redaction rule changed.</td></tr>
|
|
@@ -3818,6 +3868,65 @@ createGrid(el, {
|
|
|
3818
3868
|
},
|
|
3819
3869
|
});</code></pre>
|
|
3820
3870
|
|
|
3871
|
+
<h3 id="regression-diagnostics">Regression diagnostics</h3>
|
|
3872
|
+
<p>A regression is not finished when it has coefficients; it is finished when the residuals
|
|
3873
|
+
have been looked at. <code>regressionPlots</code> turns a fitted model — the one
|
|
3874
|
+
<code>grid.statistics.regressionModel</code> returns — into ready chart specs, so the
|
|
3875
|
+
diagnostic pictures are one call rather than a hand-assembled spec each. It reimplements no
|
|
3876
|
+
charting and no statistics: the fit line’s confidence band is the module’s own ribbon
|
|
3877
|
+
primitive fed by the model’s own interval, and the multicollinearity plot is the existing
|
|
3878
|
+
correlogram paired with the model’s VIF.</p>
|
|
3879
|
+
<p>The presets that map onto grid columns are returned as drawable specs: the fit with its
|
|
3880
|
+
band, residuals-vs-fitted (over the <code>fitPredicted</code> and <code>fitResidual</code>
|
|
3881
|
+
shadow columns), a QQ plot of the residuals, the multicollinearity correlogram, and — over the
|
|
3882
|
+
<code>fitStdResidual</code>, <code>fitLeverage</code> and <code>fitCooksD</code> columns
|
|
3883
|
+
(BACKLOG-0000872) — residuals-vs-leverage, a bubble sized by Cook's distance. Scale-location
|
|
3884
|
+
(√|standardised residual| vs fitted) is drawn from explicit points computed off the model,
|
|
3885
|
+
since its y is a transform no column holds; the coefficient <code>forest</code> plot draws one
|
|
3886
|
+
row per coefficient — its estimate with a confidence whisker and a line at zero — through the
|
|
3887
|
+
explicit-bound error-bar primitive. A preset a given model cannot support (no multicollinearity
|
|
3888
|
+
for one predictor, no band for several) is returned as a null spec carrying a machine-readable
|
|
3889
|
+
reason rather than silently dropped.</p>
|
|
3890
|
+
<pre data-run="js" data-expect="scatter|5|scatter|qq|bubble|cook|scatter|forest" data-covers="export:regressionPlots"><code><span class="kw">const</span> { createHeadlessGrid } = <span class="kw">await</span> import('../packages/core/src/index.js');
|
|
3891
|
+
<span class="kw">const</span> { regressionPlots } = <span class="kw">await</span> import('../packages/modules/charts/index.js');
|
|
3892
|
+
|
|
3893
|
+
<span class="cmt">// x=1..5, y=2,4,5,4,5. Shadow columns carry the model's per-row diagnostics —</span>
|
|
3894
|
+
<span class="cmt">// fitted value, residual, standardised residual, leverage and Cook's D — so a</span>
|
|
3895
|
+
<span class="cmt">// diagnostic chart is a plain chart over columns.</span>
|
|
3896
|
+
<span class="kw">const</span> model = { predictors: ['x'], response: 'y' };
|
|
3897
|
+
<span class="kw">const</span> grid = createHeadlessGrid({
|
|
3898
|
+
columns: [
|
|
3899
|
+
{ field: 'x', type: 'number' },
|
|
3900
|
+
{ field: 'y', type: 'number' },
|
|
3901
|
+
{ id: 'yhat', title: 'Fitted', shadow: { kind: 'fitPredicted', model } },
|
|
3902
|
+
{ id: 'resid', title: 'Residual', shadow: { kind: 'fitResidual', model } },
|
|
3903
|
+
{ id: 'sresid', title: 'Std residual', shadow: { kind: 'fitStdResidual', model } },
|
|
3904
|
+
{ id: 'lev', title: 'Leverage', shadow: { kind: 'fitLeverage', model } },
|
|
3905
|
+
{ id: 'cook', title: "Cook's D", shadow: { kind: 'fitCooksD', model } },
|
|
3906
|
+
],
|
|
3907
|
+
rows: [
|
|
3908
|
+
{ id: 'r1', x: 1, y: 2 }, { id: 'r2', x: 2, y: 4 }, { id: 'r3', x: 3, y: 5 },
|
|
3909
|
+
{ id: 'r4', x: 4, y: 4 }, { id: 'r5', x: 5, y: 5 },
|
|
3910
|
+
],
|
|
3911
|
+
rowKey: 'id',
|
|
3912
|
+
source: { mode: 'memory', columnarBelow: 0 },
|
|
3913
|
+
});
|
|
3914
|
+
|
|
3915
|
+
<span class="kw">const</span> { plots } = regressionPlots(grid, {
|
|
3916
|
+
spec: model, fitted: 'yhat', residual: 'resid', stdResidual: 'sresid', leverage: 'lev', cooksD: 'cook',
|
|
3917
|
+
});
|
|
3918
|
+
|
|
3919
|
+
<span class="kw">return</span> [
|
|
3920
|
+
plots.fit.spec.type, <span class="cmt">// scatter, with fit:true and band</span>
|
|
3921
|
+
plots.fit.spec.band.points.length, <span class="cmt">// a band point per row</span>
|
|
3922
|
+
plots.residualsFitted.spec.type, <span class="cmt">// residual vs fitted, a scatter</span>
|
|
3923
|
+
plots.qq.spec.type, <span class="cmt">// a QQ plot of the residuals</span>
|
|
3924
|
+
plots.residualsLeverage.spec.type, <span class="cmt">// bubble, over the diagnostic columns</span>
|
|
3925
|
+
plots.residualsLeverage.spec.size, <span class="cmt">// sized by Cook's D</span>
|
|
3926
|
+
plots.scaleLocation.spec.type, <span class="cmt">// scatter, from explicit points off the model</span>
|
|
3927
|
+
plots.coefficientForest.spec.type, <span class="cmt">// forest, estimate + whisker per coefficient</span>
|
|
3928
|
+
].join('|');</code></pre>
|
|
3929
|
+
|
|
3821
3930
|
<h3>Maps</h3>
|
|
3822
3931
|
<p>A <code>geomap</code> takes an ISO code from one column and a value from another. Alpha-2, alpha-3 and numeric codes are all accepted, and continent codes draw a continent map without any outline data. Country outlines are yours to supply through <code>shapes</code>, because a world atlas is larger than the whole library and this package fetches nothing at runtime.</p>
|
|
3823
3932
|
<p>Codes that match nothing are counted and reported on the chart rather than dropped, a map missing half its data looks exactly like a map of a world where half the data is zero. The full code tables are in <a href="CHART-CODES.md">CHART-CODES.md</a>.</p>
|
|
@@ -4025,7 +4134,7 @@ createGrid(el, {
|
|
|
4025
4134
|
<span class="chip">text</span><span class="chip">number</span><span class="chip">boolean</span><span class="chip">date</span><span class="chip">dateString</span><span class="chip">lookup</span><span class="chip">object</span>
|
|
4026
4135
|
</div>
|
|
4027
4136
|
<div class="chips">
|
|
4028
|
-
<span class="chip chip--new">time</span><span class="chip chip--new">datetime</span><span class="chip chip--new">duration</span>
|
|
4137
|
+
<span class="chip chip--new">time</span><span class="chip chip--new">datetime</span><span class="chip chip--new">timestamp</span><span class="chip chip--new">duration</span>
|
|
4029
4138
|
<span class="chip chip--new">ipv4</span><span class="chip chip--new">cidr</span><span class="chip chip--new">ipv6</span>
|
|
4030
4139
|
<span class="chip chip--new">json</span><span class="chip chip--new">secret</span>
|
|
4031
4140
|
<span class="chip chip--new">hex</span><span class="chip chip--new">hex8</span><span class="chip chip--new">hex16</span><span class="chip chip--new">hex32</span>
|
|
@@ -4213,7 +4322,7 @@ grid.destroy();
|
|
|
4213
4322
|
<h3 id="events-example">Events, executed</h3>
|
|
4214
4323
|
<p class="section-note">Fourteen events raised by ordinary calls, asserted on every build. An event that
|
|
4215
4324
|
stopped firing, or changed name, fails here rather than in a consumer.</p>
|
|
4216
|
-
<pre data-run="js" data-expect="
|
|
4325
|
+
<pre data-run="js" data-expect="15" data-covers="event:sort:changed event:filter:changed event:column:visible event:column:moved event:column:pinned event:columngroup:changed event:config:changed event:rows:changed event:model:changed event:state:reset event:state:changed method:on method:destroy"><code><span class="kw">const</span> { createHeadlessGrid } = <span class="kw">await</span> import('../packages/core/src/index.js');
|
|
4217
4326
|
|
|
4218
4327
|
<span class="kw">const</span> grid = createHeadlessGrid({
|
|
4219
4328
|
rowKey: 'id',
|
|
@@ -4230,6 +4339,7 @@ grid.filters.set({ col: 's', op: 'gt', value: 0 }); <span class="cmt">// filter:
|
|
|
4230
4339
|
grid.columns.hide('n'); <span class="cmt">// column:visible</span>
|
|
4231
4340
|
grid.columns.move('n', 1); <span class="cmt">// column:moved</span>
|
|
4232
4341
|
grid.columns.pin('n', 'left'); <span class="cmt">// column:pinned</span>
|
|
4342
|
+
grid.columns.groupColumns(['n', 's'], { title: 'Both' }); <span class="cmt">// columngroup:changed</span>
|
|
4233
4343
|
grid.set('rowHeight', 30); <span class="cmt">// config:changed</span>
|
|
4234
4344
|
grid.rows.apply({ update: [{ id: '1', s: 9 }] }); <span class="cmt">// rows:changed, model:changed</span>
|
|
4235
4345
|
grid.state.reset(); <span class="cmt">// state:reset, state:changed</span>
|
|
@@ -4372,7 +4482,7 @@ spans.addSpan('R0', 'name', 3, 2); <span class="cmt">// rowspan 3, colspan 2</sp
|
|
|
4372
4482
|
|
|
4373
4483
|
<h3 id="module-exports-example">Every module export, executed</h3>
|
|
4374
4484
|
<p class="section-note">Nine shipped modules, each export resolved against its own barrel on every build.</p>
|
|
4375
|
-
<pre data-run="js" data-expect="
|
|
4485
|
+
<pre data-run="js" data-expect="61" 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:regressionPlots 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>
|
|
4376
4486
|
<span class="cmt">// barrel. A module that stopped exporting something fails here.</span>
|
|
4377
4487
|
<span class="kw">const</span> modules = [
|
|
4378
4488
|
[<span class="kw">await</span> import('../packages/dom/src/index.js'), [
|
|
@@ -4383,7 +4493,7 @@ spans.addSpan('R0', 'name', 3, 2); <span class="cmt">// rowspan 3, colspan 2</sp
|
|
|
4383
4493
|
]],
|
|
4384
4494
|
[<span class="kw">await</span> import('../packages/modules/charts/index.js'), [
|
|
4385
4495
|
'Chart', 'PALETTE', 'SCHEMES', 'TYPES',
|
|
4386
|
-
'createChart', 'chartRange', 'canChartRange', 'deriveRangeSpec',
|
|
4496
|
+
'createChart', 'chartRange', 'canChartRange', 'deriveRangeSpec', 'regressionPlots',
|
|
4387
4497
|
'registerScheme', 'resolveScheme', 'schemeNames',
|
|
4388
4498
|
'setDefaultScheme',
|
|
4389
4499
|
]],
|
|
@@ -5117,6 +5227,8 @@ return `methods ${ANOMALY_METHODS.length}; flagged ${z.flagged}; upper ${fence.u
|
|
|
5117
5227
|
<tr><td class="name">font</td><td class="type">object</td><td class="desc"><small>(optional)</small></td></tr>
|
|
5118
5228
|
<tr><td class="name">margin</td><td class="type">number | { top?: number; right?: number; bottom?: number; left?: number }</td><td class="desc"><small>(optional)</small></td></tr>
|
|
5119
5229
|
<tr><td class="name">fit</td><td class="type">boolean | 'line'</td><td class="desc">A least-squares line through a scatter or bubble chart, one per series. `true` draws the line and its R²; `'line'` draws the line alone. Only where the x axis is numeric: on a band scale the positions are categories in an arbitrary order, and a slope through them would be a slope through the order they happened to be listed in. <small>(optional)</small></td></tr>
|
|
5230
|
+
<tr><td class="name">band</td><td class="type">(RegressionBand & { line?: boolean }) | null</td><td class="desc">A pointwise confidence band, drawn as a varying-width ribbon beneath the fit line (BACKLOG-0000812). Fed by a fitted model's own interval — the `band` from {@link StatisticsApi.regressionModel}, or as produced by {@link regressionPlots} — so the ribbon and the diagnostics report the one computation rather than a slope redrawn here. `line: false` suppresses the band's own centre line, for a chart that already draws the fit with `fit`. Only where the x axis is numeric, for the same reason `fit` is. <small>(optional)</small></td></tr>
|
|
5231
|
+
<tr><td class="name">points</td><td class="type">{</td><td class="desc">An explicit point set, bypassing the by-column binder (BACKLOG-0000872): a cartesian chart whose values are not a grid column — a scale-location plot's √|standardised residual|, a coefficient forest's per-coefficient estimate — hands its points in directly. Each is `{x, y}` with an optional `label`, `size` (a bubble's third channel) and `lower`/`upper` (interval bounds the error-bar primitive reads). Numeric `x` throughout gives a continuous axis. <small>(optional)</small></td></tr>
|
|
5120
5232
|
<tr><td class="name">error</td><td class="type">boolean | { of?: string; confidence?: number }</td><td class="desc">Whiskers showing the uncertainty in each mark. `true` computes a confidence interval from the readings behind the mark; `of` takes a symmetric margin from another column instead. <small>(optional)</small></td></tr>
|
|
5121
5233
|
<tr><td class="name">reference</td><td class="type">{ value: number; label?: string; axis?: 'left' | 'right' }[]</td><td class="desc">Horizontal reference lines. On a dual-axis bar or line chart (see {@link ChartMeasure.axis}) a line naming `axis: 'right'` is placed on the right-hand scale, so it means what the right axis says rather than landing at the same number on the scale it does not belong to. <small>(optional)</small></td></tr>
|
|
5122
5234
|
<tr><td class="name">annotations</td><td class="type">ChartAnnotation[]</td><td class="desc">The declarative annotation layer: reference and target lines, shaded bands and callouts, each naming the axis it reads and each described into the accessible table as a sentence. A value may be a constant or `compute`d from the data it annotates, so it follows the chart as the grid is filtered. <small>(optional)</small></td></tr>
|
|
@@ -5193,7 +5305,7 @@ return `methods ${ANOMALY_METHODS.length}; flagged ${z.flagged}; upper ${fence.u
|
|
|
5193
5305
|
<tr><td class="name">edit</td><td class="type">ColumnEditSpec | boolean | string</td><td class="desc">Whether and how the cell can be edited. A string names an editor. <small>(optional)</small></td></tr>
|
|
5194
5306
|
<tr><td class="name">sort</td><td class="type">ColumnSortSpec | boolean</td><td class="desc">Whether the column sorts, and by what comparison. `false` refuses it. <small>(optional)</small></td></tr>
|
|
5195
5307
|
<tr><td class="name">filter</td><td class="type">ColumnFilterSpec | boolean | FilterName</td><td class="desc">Whether the column filters, and with which filter. A string names one. <small>(optional)</small></td></tr>
|
|
5196
|
-
<tr><td class="name">group</td><td class="type">{
|
|
5308
|
+
<tr><td class="name">group</td><td class="type">{</td><td class="desc">Row grouping by this column. `index` fixes its place among several; `explode` gives a multi-value cell one group per value rather than one group for the combination. `granularity` and `weekStart` apply to a `timestamp` column: it buckets by civil `day` (the default), `week` or `month` in the display zone, or `instant` for one group per exact moment. `weekStart` is the first weekday, 1=Monday (default) to 7=Sunday. <small>(optional)</small></td></tr>
|
|
5197
5309
|
<tr><td class="name">pivot</td><td class="type">{ enabled?: boolean; index?: number } | boolean</td><td class="desc">Use this column as a pivot dimension, and where it sits among several. <small>(optional)</small></td></tr>
|
|
5198
5310
|
<tr><td class="name">total</td><td class="type">TotalName | TotalFn</td><td class="desc">The reduction shown in the totals row and in group footers. <small>(optional)</small></td></tr>
|
|
5199
5311
|
<tr><td class="name">groupTotal</td><td class="type">TotalName | TotalFn</td><td class="desc">The reduction for group subtotals — group footers, tree-node rollups and pivot cells — where it should differ from the grand total. Overrides `total` for those scopes only; when omitted the column's `total` applies to both. Lets a column average within each group while the grand total sums, for example (BACKLOG-0000726). <small>(optional)</small></td></tr>
|
|
@@ -5341,15 +5453,29 @@ return `methods ${ANOMALY_METHODS.length}; flagged ${z.flagged}; upper ${fence.u
|
|
|
5341
5453
|
</tbody>
|
|
5342
5454
|
</table>
|
|
5343
5455
|
</div>
|
|
5456
|
+
<h3 id="type-ColumnGroupState">ColumnGroupState</h3>
|
|
5457
|
+
<p class="section-note">A persisted banded-header node (§15, BACKLOG-0000739): a band with a `columns` list whose members are leaf ids or nested bands. This is what round-trips a drag-created group through a saved view.</p>
|
|
5458
|
+
<div class="table-wrap">
|
|
5459
|
+
<table>
|
|
5460
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
5461
|
+
<tbody>
|
|
5462
|
+
<tr><td class="name">id</td><td class="type">string</td><td class="desc"></td></tr>
|
|
5463
|
+
<tr><td class="name">title</td><td class="type">string</td><td class="desc"></td></tr>
|
|
5464
|
+
<tr><td class="name">collapsible</td><td class="type">boolean</td><td class="desc"></td></tr>
|
|
5465
|
+
<tr><td class="name">openByDefault</td><td class="type">boolean</td><td class="desc"></td></tr>
|
|
5466
|
+
<tr><td class="name">columns</td><td class="type">Array<string | ColumnGroupState></td><td class="desc"></td></tr>
|
|
5467
|
+
</tbody>
|
|
5468
|
+
</table>
|
|
5469
|
+
</div>
|
|
5344
5470
|
<h3 id="type-ColumnHeaderSpec">ColumnHeaderSpec</h3>
|
|
5345
5471
|
<div class="table-wrap">
|
|
5346
5472
|
<table>
|
|
5347
5473
|
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
5348
5474
|
<tbody>
|
|
5349
|
-
<tr><td class="name">template</td><td class="type">string</td><td class="desc"
|
|
5350
|
-
<tr><td class="name">render</td><td class="type">string | RendererCtor</td><td class="desc"
|
|
5351
|
-
<tr><td class="name">props</td><td class="type">Record<string, unknown></td><td class="desc"
|
|
5352
|
-
<tr><td class="name">class</td><td class="type">string | string[]</td><td class="desc"
|
|
5475
|
+
<tr><td class="name">template</td><td class="type">string</td><td class="desc">Not read by the header renderer; use `render` to draw a custom heading. <small>(optional)</small></td></tr>
|
|
5476
|
+
<tr><td class="name">render</td><td class="type">string | RendererCtor</td><td class="desc">A custom heading renderer: a function, or a component (a class with a `render` method). A string names a registered renderer. Either form draws the same two ways and they are interchangeable — it may append to the passed label element itself and return nothing, or return an `Element` (attached for you) or a `string` (used as the heading text). <small>(optional)</small></td></tr>
|
|
5477
|
+
<tr><td class="name">props</td><td class="type">Record<string, unknown></td><td class="desc">Props passed to `render` as `params.props`. <small>(optional)</small></td></tr>
|
|
5478
|
+
<tr><td class="name">class</td><td class="type">string | string[]</td><td class="desc">A class, or classes, added to the heading cell. <small>(optional)</small></td></tr>
|
|
5353
5479
|
<tr><td class="name">tooltip</td><td class="type">string</td><td class="desc"><small>(optional)</small></td></tr>
|
|
5354
5480
|
<tr><td class="name">align</td><td class="type">Align</td><td class="desc"><small>(optional)</small></td></tr>
|
|
5355
5481
|
</tbody>
|
|
@@ -5427,6 +5553,11 @@ return `methods ${ANOMALY_METHODS.length}; flagged ${z.flagged}; upper ${fence.u
|
|
|
5427
5553
|
<tr><td class="name">show</td><td class="type">(ids: string | string[]): void</td><td class="desc"></td></tr>
|
|
5428
5554
|
<tr><td class="name">hide</td><td class="type">(ids: string | string[]): void</td><td class="desc"></td></tr>
|
|
5429
5555
|
<tr><td class="name">move</td><td class="type">(id: string, to: number): void</td><td class="desc"></td></tr>
|
|
5556
|
+
<tr><td class="name">groupColumns</td><td class="type">(ids: string | string[], opts?: { title?: string; at?: number; groupId?: string }): string | null</td><td class="desc">Wrap leaf columns in a banded header, or add them to an existing band (BACKLOG-0000739). Header banding, not row grouping (see {@link group}); the band is a {@link ColumnGroup} node so a drag-, keyboard- or config-built band is the same tree, and it round-trips through a saved view. Emits `columngroup:changed`.</td></tr>
|
|
5557
|
+
<tr><td class="name">ungroupColumn</td><td class="type">(id: string): void</td><td class="desc">Take a leaf out of its band; a band emptied by the move is dissolved.</td></tr>
|
|
5558
|
+
<tr><td class="name">renameGroup</td><td class="type">(groupId: string, title: string): void</td><td class="desc">Rename a banded header.</td></tr>
|
|
5559
|
+
<tr><td class="name">dissolveGroup</td><td class="type">(groupId: string): void</td><td class="desc">Dissolve a band, returning its columns to the enclosing level in place.</td></tr>
|
|
5560
|
+
<tr><td class="name">moveGroup</td><td class="type">(groupId: string, to: number): void</td><td class="desc">Move a whole band among its siblings, its columns travelling as a block.</td></tr>
|
|
5430
5561
|
<tr><td class="name">pin</td><td class="type">(id: string, side: 'start' | 'end' | null): void</td><td class="desc"></td></tr>
|
|
5431
5562
|
<tr><td class="name">resize</td><td class="type">(id: string, px: number): void</td><td class="desc"></td></tr>
|
|
5432
5563
|
<tr><td class="name">decorate</td><td class="type">(id: string, decoration: DecorationName | DecorationSpec | null, opts?: { variant?: VariantSpec }): void</td><td class="desc">Set, change or clear a column's decoration at runtime (§8.7). Pass `null` to clear it back to plain text. Presentation config: it is not on the undo timeline and is not carried in a saved view — use `grid.formatting` for durable, view-persisted conditional styling.</td></tr>
|
|
@@ -6449,6 +6580,7 @@ return `methods ${ANOMALY_METHODS.length}; flagged ${z.flagged}; upper ${fence.u
|
|
|
6449
6580
|
<tr><td class="name">version</td><td class="type">number</td><td class="desc"></td></tr>
|
|
6450
6581
|
<tr><td class="name">columns</td><td class="type">ColumnState[]</td><td class="desc"><small>(optional)</small></td></tr>
|
|
6451
6582
|
<tr><td class="name">columnOrder</td><td class="type">string[]</td><td class="desc"><small>(optional)</small></td></tr>
|
|
6583
|
+
<tr><td class="name">columnGroups</td><td class="type">ColumnGroupState[]</td><td class="desc">The banded-header tree, when the grid has one (BACKLOG-0000739). <small>(optional)</small></td></tr>
|
|
6452
6584
|
<tr><td class="name">filters</td><td class="type">FilterSet</td><td class="desc"><small>(optional)</small></td></tr>
|
|
6453
6585
|
<tr><td class="name">quick</td><td class="type">string</td><td class="desc"><small>(optional)</small></td></tr>
|
|
6454
6586
|
<tr><td class="name">sort</td><td class="type">SortEntry[]</td><td class="desc"><small>(optional)</small></td></tr>
|
|
@@ -6512,6 +6644,19 @@ return `methods ${ANOMALY_METHODS.length}; flagged ${z.flagged}; upper ${fence.u
|
|
|
6512
6644
|
</tbody>
|
|
6513
6645
|
</table>
|
|
6514
6646
|
</div>
|
|
6647
|
+
<h3 id="type-Heteroscedasticity">Heteroscedasticity</h3>
|
|
6648
|
+
<p class="section-note">The Breusch–Pagan heteroscedasticity test result.</p>
|
|
6649
|
+
<div class="table-wrap">
|
|
6650
|
+
<table>
|
|
6651
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
6652
|
+
<tbody>
|
|
6653
|
+
<tr><td class="name">statistic</td><td class="type">number</td><td class="desc"></td></tr>
|
|
6654
|
+
<tr><td class="name">df</td><td class="type">number</td><td class="desc"></td></tr>
|
|
6655
|
+
<tr><td class="name">p</td><td class="type">number</td><td class="desc"></td></tr>
|
|
6656
|
+
<tr><td class="name">heteroscedastic</td><td class="type">boolean</td><td class="desc">True when the test rejects homoscedasticity at the 0.05 level.</td></tr>
|
|
6657
|
+
</tbody>
|
|
6658
|
+
</table>
|
|
6659
|
+
</div>
|
|
6515
6660
|
<h3 id="type-HighlightApi">HighlightApi</h3>
|
|
6516
6661
|
<div class="table-wrap">
|
|
6517
6662
|
<table>
|
|
@@ -7189,6 +7334,33 @@ return `methods ${ANOMALY_METHODS.length}; flagged ${z.flagged}; upper ${fence.u
|
|
|
7189
7334
|
</tbody>
|
|
7190
7335
|
</table>
|
|
7191
7336
|
</div>
|
|
7337
|
+
<h3 id="type-RegressionBand">RegressionBand</h3>
|
|
7338
|
+
<p class="section-note">A pointwise confidence band for the mean response of a single-predictor fit.</p>
|
|
7339
|
+
<div class="table-wrap">
|
|
7340
|
+
<table>
|
|
7341
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
7342
|
+
<tbody>
|
|
7343
|
+
<tr><td class="name">confidence</td><td class="type">number</td><td class="desc"></td></tr>
|
|
7344
|
+
<tr><td class="name">points</td><td class="type">{ x: number; yhat: number; lower: number; upper: number }[]</td><td class="desc"></td></tr>
|
|
7345
|
+
</tbody>
|
|
7346
|
+
</table>
|
|
7347
|
+
</div>
|
|
7348
|
+
<h3 id="type-RegressionCoefficient">RegressionCoefficient</h3>
|
|
7349
|
+
<p class="section-note">One fitted coefficient, with the uncertainty around it.</p>
|
|
7350
|
+
<div class="table-wrap">
|
|
7351
|
+
<table>
|
|
7352
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
7353
|
+
<tbody>
|
|
7354
|
+
<tr><td class="name">name</td><td class="type">string</td><td class="desc">`(intercept)` or the predictor's column id.</td></tr>
|
|
7355
|
+
<tr><td class="name">estimate</td><td class="type">number</td><td class="desc"></td></tr>
|
|
7356
|
+
<tr><td class="name">stdError</td><td class="type">number</td><td class="desc"></td></tr>
|
|
7357
|
+
<tr><td class="name">t</td><td class="type">number</td><td class="desc">estimate ÷ standard error.</td></tr>
|
|
7358
|
+
<tr><td class="name">p</td><td class="type">number</td><td class="desc">Two-sided Student-t p-value; a number with a documented method, not a verdict.</td></tr>
|
|
7359
|
+
<tr><td class="name">lower</td><td class="type">number | null</td><td class="desc">The Wald confidence interval at the model's confidence level (BACKLOG-0000872) — the whiskers a coefficient forest plot draws. Null when there is no residual degree of freedom to form a critical value.</td></tr>
|
|
7360
|
+
<tr><td class="name">upper</td><td class="type">number | null</td><td class="desc"></td></tr>
|
|
7361
|
+
</tbody>
|
|
7362
|
+
</table>
|
|
7363
|
+
</div>
|
|
7192
7364
|
<h3 id="type-RegressionFit">RegressionFit</h3>
|
|
7193
7365
|
<div class="table-wrap">
|
|
7194
7366
|
<table>
|
|
@@ -7202,6 +7374,47 @@ return `methods ${ANOMALY_METHODS.length}; flagged ${z.flagged}; upper ${fence.u
|
|
|
7202
7374
|
</tbody>
|
|
7203
7375
|
</table>
|
|
7204
7376
|
</div>
|
|
7377
|
+
<h3 id="type-RegressionModel">RegressionModel</h3>
|
|
7378
|
+
<p class="section-note">A fitted multi-predictor linear model and its diagnostics (BACKLOG-0000792).</p>
|
|
7379
|
+
<div class="table-wrap">
|
|
7380
|
+
<table>
|
|
7381
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
7382
|
+
<tbody>
|
|
7383
|
+
<tr><td class="name">method</td><td class="type">string</td><td class="desc"></td></tr>
|
|
7384
|
+
<tr><td class="name">coefficients</td><td class="type">RegressionCoefficient[]</td><td class="desc"></td></tr>
|
|
7385
|
+
<tr><td class="name">r2</td><td class="type">number</td><td class="desc"></td></tr>
|
|
7386
|
+
<tr><td class="name">adjR2</td><td class="type">number</td><td class="desc"></td></tr>
|
|
7387
|
+
<tr><td class="name">n</td><td class="type">number</td><td class="desc"></td></tr>
|
|
7388
|
+
<tr><td class="name">df</td><td class="type">number</td><td class="desc">Residual degrees of freedom, n − p.</td></tr>
|
|
7389
|
+
<tr><td class="name">sigma2</td><td class="type">number</td><td class="desc">Residual variance, RSS ÷ df.</td></tr>
|
|
7390
|
+
<tr><td class="name">fitted</td><td class="type">number[]</td><td class="desc"></td></tr>
|
|
7391
|
+
<tr><td class="name">residuals</td><td class="type">number[]</td><td class="desc"></td></tr>
|
|
7392
|
+
<tr><td class="name">leverage</td><td class="type">number[]</td><td class="desc">Hat-diagonal leverage per row.</td></tr>
|
|
7393
|
+
<tr><td class="name">cooksD</td><td class="type">(number | null)[]</td><td class="desc">Cook's distance per row; null where it cannot be computed.</td></tr>
|
|
7394
|
+
<tr><td class="name">vif</td><td class="type">number[]</td><td class="desc">Variance-inflation factor per predictor; Infinity when exactly collinear.</td></tr>
|
|
7395
|
+
<tr><td class="name">heteroscedasticity</td><td class="type">Heteroscedasticity | null</td><td class="desc"></td></tr>
|
|
7396
|
+
<tr><td class="name">band</td><td class="type">RegressionBand | null</td><td class="desc"></td></tr>
|
|
7397
|
+
<tr><td class="name">weights</td><td class="type">number[] | null</td><td class="desc">Per-row weights actually used (robust/WLS), or null for OLS.</td></tr>
|
|
7398
|
+
<tr><td class="name">predictors</td><td class="type">string[]</td><td class="desc"></td></tr>
|
|
7399
|
+
<tr><td class="name">response</td><td class="type">string</td><td class="desc"></td></tr>
|
|
7400
|
+
<tr><td class="name">rows</td><td class="type">number[]</td><td class="desc">The physical rows the diagnostics are aligned to, in order.</td></tr>
|
|
7401
|
+
</tbody>
|
|
7402
|
+
</table>
|
|
7403
|
+
</div>
|
|
7404
|
+
<h3 id="type-RegressionSpec">RegressionSpec</h3>
|
|
7405
|
+
<p class="section-note">The specification of a multi-predictor model (BACKLOG-0000792).</p>
|
|
7406
|
+
<div class="table-wrap">
|
|
7407
|
+
<table>
|
|
7408
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
7409
|
+
<tbody>
|
|
7410
|
+
<tr><td class="name">predictors</td><td class="type">string[]</td><td class="desc">The predictor column ids.</td></tr>
|
|
7411
|
+
<tr><td class="name">response</td><td class="type">string</td><td class="desc">The response column id.</td></tr>
|
|
7412
|
+
<tr><td class="name">method</td><td class="type">'ols' | 'wls' | 'robust' | 'quantile'</td><td class="desc">`ols` (default), `wls` or `robust`. `quantile` is reserved (coming next). <small>(optional)</small></td></tr>
|
|
7413
|
+
<tr><td class="name">weights</td><td class="type">string</td><td class="desc">A weights column id, required for `wls`. <small>(optional)</small></td></tr>
|
|
7414
|
+
<tr><td class="name">confidence</td><td class="type">number</td><td class="desc">The confidence level for the band; 0.95 by default. <small>(optional)</small></td></tr>
|
|
7415
|
+
</tbody>
|
|
7416
|
+
</table>
|
|
7417
|
+
</div>
|
|
7205
7418
|
<h3 id="type-RejectedRow">RejectedRow</h3>
|
|
7206
7419
|
<p class="section-note">A row a change could not apply, and why. Reported, never thrown.</p>
|
|
7207
7420
|
<div class="table-wrap">
|
|
@@ -7288,7 +7501,7 @@ return `methods ${ANOMALY_METHODS.length}; flagged ${z.flagged}; upper ${fence.u
|
|
|
7288
7501
|
<tr><td class="name">edit</td><td class="type">ColumnEditSpec</td><td class="desc"></td></tr>
|
|
7289
7502
|
<tr><td class="name">sort</td><td class="type">ColumnSortSpec</td><td class="desc"></td></tr>
|
|
7290
7503
|
<tr><td class="name">filter</td><td class="type">ColumnFilterSpec</td><td class="desc"></td></tr>
|
|
7291
|
-
<tr><td class="name">group</td><td class="type">{ enabled: boolean; index: number; explode: boolean }</td><td class="desc"></td></tr>
|
|
7504
|
+
<tr><td class="name">group</td><td class="type">{ enabled: boolean; index: number; explode: boolean; granularity?: 'day' | 'week' | 'month' | 'instant'; weekStart?: number }</td><td class="desc"></td></tr>
|
|
7292
7505
|
<tr><td class="name">pivot</td><td class="type">{ enabled: boolean; index: number }</td><td class="desc"></td></tr>
|
|
7293
7506
|
<tr><td class="name">total</td><td class="type">TotalName | TotalFn | null</td><td class="desc"></td></tr>
|
|
7294
7507
|
<tr><td class="name">groupTotal</td><td class="type">TotalName | TotalFn | null</td><td class="desc">The group-subtotal override, or null when group subtotals follow `total` (BACKLOG-0000726).</td></tr>
|
|
@@ -7602,6 +7815,8 @@ return `methods ${ANOMALY_METHODS.length}; flagged ${z.flagged}; upper ${fence.u
|
|
|
7602
7815
|
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
7603
7816
|
<tbody>
|
|
7604
7817
|
<tr><td class="name">shadow</td><td class="type">(colId: string, kind: ShadowKind, rowKey: string,</td><td class="desc">One shadow value for one row, by the column it shadows and the kind. For `kind: 'specStatus'`, `spec` carries the `{lower, upper, warnLower, warnUpper}` limits to judge the row's value against; other kinds ignore it.</td></tr>
|
|
7818
|
+
<tr><td class="name">fitShadow</td><td class="type">(kind: 'fitPredicted' | 'fitResidual' | 'fitInfluence'</td><td class="desc">One regression shadow value for a row, by key (BACKLOG-0000812): the predicted value, residual, or Cook's-distance influence flag from the fitted model, over the filtered rows. Null for a row outside the fit.</td></tr>
|
|
7819
|
+
<tr><td class="name">rowKey</td><td class="type">string, spec: RegressionSpec): number | boolean | null</td><td class="desc"></td></tr>
|
|
7605
7820
|
<tr><td class="name">running</td><td class="type">(colId: string, kind: 'total' | 'percent', rowKey: string): number | null</td><td class="desc">A running total at one row, down the grid as it is currently ordered.</td></tr>
|
|
7606
7821
|
<tr><td class="name">rebase</td><td class="type">(colId?: string): void</td><td class="desc">Make the current values the new baseline: "mark all".</td></tr>
|
|
7607
7822
|
<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>
|
|
@@ -7614,6 +7829,7 @@ return `methods ${ANOMALY_METHODS.length}; flagged ${z.flagged}; upper ${fence.u
|
|
|
7614
7829
|
<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>
|
|
7615
7830
|
<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>
|
|
7616
7831
|
<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>
|
|
7832
|
+
<tr><td class="name">regressionModel</td><td class="type">(spec: RegressionSpec): RegressionModel | null</td><td class="desc">Fit a multi-predictor linear model over the filtered rows and return the full diagnostic set — coefficients with standard errors, t and p; R² and adjusted R²; per-row fitted values, residuals, leverage and Cook's D; VIF per predictor; a Breusch–Pagan heteroscedasticity flag; and, for a single predictor, a pointwise confidence band. `method` is `ols`, `wls` (needs a `weights` column) or `robust`; `quantile` is reserved and the regularised families refuse. Null on degenerate input (BACKLOG-0000792).</td></tr>
|
|
7617
7833
|
<tr><td class="name">spearman</td><td class="type">(a: string, b: string): number | null</td><td class="desc">Spearman's rank correlation, which one outlier cannot drag.</td></tr>
|
|
7618
7834
|
<tr><td class="name">kendall</td><td class="type">(a: string, b: string): number | null</td><td class="desc">Kendall's tau-b. Null past 5,000 rows: it is quadratic.</td></tr>
|
|
7619
7835
|
<tr><td class="name">weightedQuantile</td><td class="type">(colId: string, weightId: string, p?: number): number | null</td><td class="desc">A quantile of one column weighted by another; the median by default.</td></tr>
|
package/docs/api-detail.html
CHANGED
|
@@ -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.
|
|
440
|
+
<p class="rail__sub">Developer guide · v1.29.0</p>
|
|
441
441
|
<nav>
|
|
442
442
|
<div class="rail__group">
|
|
443
443
|
<span class="rail__label">Start here</span>
|
|
@@ -1378,7 +1378,7 @@ LatticeGrid.getVersion(); <span class="cmt">// the same, when you have no grid
|
|
|
1378
1378
|
<thead><tr><th>Family</th><th>Types</th></tr></thead>
|
|
1379
1379
|
<tbody>
|
|
1380
1380
|
<tr><td class="name">Core</td><td class="desc"><code>text</code>, <code>number</code>, <code>boolean</code>, <code>date</code>, <code>dateString</code>, <code>object</code>, <code>lookup</code></td></tr>
|
|
1381
|
-
<tr><td class="name">Temporal</td><td class="desc"><code>datetime</code>, <code>time</code>, <code>duration</code></td></tr>
|
|
1381
|
+
<tr><td class="name">Temporal</td><td class="desc"><code>datetime</code>, <code>timestamp</code>, <code>time</code>, <code>duration</code></td></tr>
|
|
1382
1382
|
<tr><td class="name">Network</td><td class="desc"><code>ipv4</code>, <code>ipv6</code>, <code>cidr</code>, <code>mac</code></td></tr>
|
|
1383
1383
|
<tr><td class="name">Numeric bases</td><td class="desc"><code>hex</code>, <code>hex8</code>, <code>hex16</code>, <code>hex32</code>, <code>binary</code>, <code>binary8</code>, <code>octal</code></td></tr>
|
|
1384
1384
|
<tr><td class="name">Units: computing</td><td class="desc"><code>bytes</code>, <code>megabytes</code>, <code>gigabytes</code>, <code>bitrate</code>, <code>gigabits</code></td></tr>
|
|
@@ -1537,8 +1537,36 @@ dataTypes: {
|
|
|
1537
1537
|
convert.</p>
|
|
1538
1538
|
<p>It is also faster and smaller: ISO 8601 sorts lexicographically in the same order it sorts
|
|
1539
1539
|
chronologically, so a date column sorts as text, and repeated dates dictionary-encode well.</p>
|
|
1540
|
-
<p>When you genuinely mean an instant (a log timestamp
|
|
1541
|
-
<code>
|
|
1540
|
+
<p>When you genuinely mean an instant (a log timestamp, an audit time) use
|
|
1541
|
+
<code>timestamp</code> — see below. <code>datetime</code> stays a wall clock, deliberately.</p>
|
|
1542
|
+
</div>
|
|
1543
|
+
|
|
1544
|
+
<h3 id="timestamp-type">timestamp — an instant, stored UTC, shown in a chosen zone</h3>
|
|
1545
|
+
<p class="lead-in">
|
|
1546
|
+
<code>type: 'timestamp'</code> is the sibling to <code>datetime</code> for data that is one
|
|
1547
|
+
genuine moment everywhere — an audit time, an event <code>created_at</code>, a cross-region log
|
|
1548
|
+
line — rather than a wall clock.
|
|
1549
|
+
</p>
|
|
1550
|
+
<div class="why">
|
|
1551
|
+
<p><strong>Stored as an instant.</strong> A value ingests from epoch-millis, a <code>Date</code>,
|
|
1552
|
+
or a zone-bearing ISO string (<code>…Z</code> / <code>…+01:00</code>) and is stored as
|
|
1553
|
+
epoch-millis UTC. Because storage is numeric, sort, filter and compare operate on the
|
|
1554
|
+
<em>instant</em>, never on rendered text — two rows from different origin zones order by true
|
|
1555
|
+
chronology, and changing the display zone never reorders them.</p>
|
|
1556
|
+
<p><strong>Shown in a display zone you control.</strong> The cell renders in the zone resolved
|
|
1557
|
+
by precedence: the column's <code>typeOptions.timeZone</code>, then the grid's
|
|
1558
|
+
<code>config.timeZone</code>, then the viewer's local zone. The resolved zone is nameable
|
|
1559
|
+
(e.g. <code>Europe/London (BST)</code>) so a reader always knows which clock they are reading;
|
|
1560
|
+
set <code>typeOptions.showOrigin: true</code> to also show the origin zone when it differs, and
|
|
1561
|
+
when no origin was recorded the cell says so rather than assuming local.</p>
|
|
1562
|
+
<p><strong>Grouped by civil day in the display zone.</strong> Grouping a <code>timestamp</code>
|
|
1563
|
+
column buckets by civil day by default — <code>group: { granularity: 'week' | 'month' | 'instant', weekStart: 1 }</code>
|
|
1564
|
+
chooses week (Monday-start by default), month, or the exact instant. Buckets are computed by
|
|
1565
|
+
projecting the instant to a civil date in the display zone, so a 23- or 25-hour daylight-saving
|
|
1566
|
+
day still collapses to one bucket rather than splitting.</p>
|
|
1567
|
+
<p><strong>Excel export.</strong> Excel has no zone, so the display-zone wall clock is written
|
|
1568
|
+
as a plain numeric datetime serial (<code>yyyy-mm-dd hh:mm</code>) — what you saw on screen,
|
|
1569
|
+
with the zone named in the docs and column header, never shifted silently to UTC.</p>
|
|
1542
1570
|
</div>
|
|
1543
1571
|
|
|
1544
1572
|
<h3>Formats</h3>
|
|
@@ -2369,6 +2397,34 @@ grid.setPinnedRows([], { edge: 'top' }); <span class="cmt">// clear</span
|
|
|
2369
2397
|
No second, empty row is rendered underneath it.
|
|
2370
2398
|
</p>
|
|
2371
2399
|
|
|
2400
|
+
<h3 id="banded-header-grouping">Forming banded headers at runtime (BACKLOG-0000739)</h3>
|
|
2401
|
+
<p class="lead-in">
|
|
2402
|
+
Banded headers can be declared in config (<code>columnGroups</code>) and now also formed,
|
|
2403
|
+
renamed, moved and dissolved at runtime through <code>grid.columns</code>, with a keyboard
|
|
2404
|
+
equivalent for every action. The model is the single source of truth: a band made by
|
|
2405
|
+
interaction is the same <code>ColumnGroup</code> tree config drives, and it round-trips through
|
|
2406
|
+
a saved view.
|
|
2407
|
+
</p>
|
|
2408
|
+
<div class="why">
|
|
2409
|
+
<p><strong>The API.</strong> <code>groupColumns(ids, { title, groupId })</code> wraps columns
|
|
2410
|
+
in a new band or adds them to an existing one; <code>ungroupColumn(id)</code> takes a column
|
|
2411
|
+
out (dissolving a band it empties); <code>renameGroup(id, title)</code>,
|
|
2412
|
+
<code>dissolveGroup(id)</code> and <code>moveGroup(id, to)</code> do the rest. Each emits
|
|
2413
|
+
<code>columngroup:changed</code>. A band's columns are always contiguous, and a nested band
|
|
2414
|
+
dissolves into its parent, not the root.</p>
|
|
2415
|
+
<p><strong>The keyboard (WCAG 2.1.1).</strong> From a focused header cell:
|
|
2416
|
+
<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>←</kbd>/<kbd>→</kbd> groups the column with its
|
|
2417
|
+
neighbour on that side (joining an adjacent band, or forming a new one);
|
|
2418
|
+
<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>↑</kbd> takes it out of its band; and
|
|
2419
|
+
<kbd>Alt</kbd>+<kbd>Shift</kbd>+<kbd>←</kbd>/<kbd>→</kbd> moves the whole band as a
|
|
2420
|
+
unit. Every action is announced through the live region, and a refusal — "not in a band",
|
|
2421
|
+
"cannot be moved there" — is announced too, never silent.</p>
|
|
2422
|
+
<p><strong>Pinning and visibility.</strong> A band lives in one pin region and draws over its
|
|
2423
|
+
visible columns there: hiding a column shrinks the band's span without changing the band
|
|
2424
|
+
definition, and hiding the last visible column hides the band. A band is exposed to assistive
|
|
2425
|
+
technology as one <code>role="columnheader"</code> cell with an <code>aria-colspan</code>.</p>
|
|
2426
|
+
</div>
|
|
2427
|
+
|
|
2372
2428
|
<h2 id="row-reorder">Row reorder</h2>
|
|
2373
2429
|
<p class="lead-in">
|
|
2374
2430
|
<code>rowReorder: true</code> puts a drag handle in the first visible column and lets a user
|
|
@@ -6179,6 +6235,7 @@ grid.state.apply(savedView.state);
|
|
|
6179
6235
|
<tr><td class="name">chartRange</td><td class="desc">Chart a selected cell range — the spreadsheet gesture. Derives the chart from the range’s shape (a leading text column is the categories, the numeric columns the measures), respects hidden and unreadable columns, and returns the live chart or null when there is nothing to measure.</td></tr>
|
|
6180
6236
|
<tr><td class="name">canChartRange</td><td class="desc">Whether <code>chartRange</code> would draw something for the grid’s current selection — the question a menu asks before offering the item.</td></tr>
|
|
6181
6237
|
<tr><td class="name">deriveRangeSpec</td><td class="desc">Decide what a chart of a range should be without drawing it: the type, the category column, the measures, and a spec ready for <code>createChart</code>.</td></tr>
|
|
6238
|
+
<tr><td class="name">regressionPlots</td><td class="desc">Turn a fitted regression model into diagnostic chart specs ready for <code>createChart</code>: the fit line with its confidence band, residuals-vs-fitted, a QQ plot of the residuals, and a multicollinearity correlogram with the model’s VIF. The plots that need a per-row or per-coefficient quantity the grid has no column for (scale-location, residuals-vs-leverage, the coefficient forest) are returned as a null spec carrying the reason rather than dropped.</td></tr>
|
|
6182
6239
|
<tr><td class="name">createDevtools</td><td class="desc">Mount the devtools panel against a grid, including its accessibility checks.</td></tr>
|
|
6183
6240
|
<tr><td class="name">createLatticeGridElement</td><td class="desc">Build the element class without registering it, for a custom registry.</td></tr>
|
|
6184
6241
|
<tr><td class="name">createMessages</td><td class="desc">Build a message catalogue. A partial set lays over the built-in British English one.</td></tr>
|