@toclocoinc/lattice-grid 1.46.1 → 1.48.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 +131 -1
- package/docs/API.html +197 -7
- package/docs/api-detail.html +100 -3
- package/lattice-grid.d.ts +344 -8
- package/lattice-grid.esm.min.js +1553 -140
- package/lattice-grid.min.cjs +1553 -140
- package/lattice-grid.min.css +1 -1
- package/lattice-grid.min.js +1553 -140
- package/modules/ai.esm.min.js +220 -27
- package/modules/ai.min.cjs +218 -26
- package/modules/ai.min.js +218 -26
- package/modules/angular.esm.min.js +3 -3
- package/modules/angular.min.cjs +3 -3
- package/modules/angular.min.js +3 -3
- package/modules/chart-alluvial.esm.min.js +1 -1
- package/modules/chart-arc.esm.min.js +1 -1
- package/modules/chart-bubblemap.esm.min.js +1 -1
- package/modules/chart-bump.esm.min.js +1 -1
- package/modules/chart-calendar.esm.min.js +1 -1
- package/modules/chart-decomposition.esm.min.js +1 -1
- package/modules/chart-diverging.esm.min.js +1 -1
- package/modules/chart-dumbbell.esm.min.js +1 -1
- package/modules/chart-fan.esm.min.js +1 -1
- package/modules/chart-hexbin.esm.min.js +1 -1
- package/modules/chart-hexmap.esm.min.js +1 -1
- package/modules/chart-icicle.esm.min.js +1 -1
- package/modules/chart-parallel.esm.min.js +8 -3
- package/modules/chart-ridgeline.esm.min.js +1 -1
- package/modules/chart-roc.esm.min.js +1 -1
- package/modules/chart-slope.esm.min.js +1 -1
- package/modules/chart-splom.esm.min.js +1 -1
- package/modules/chart-waffle.esm.min.js +1 -1
- package/modules/charts.esm.min.js +294 -19
- package/modules/charts.min.cjs +294 -19
- package/modules/charts.min.js +294 -19
- package/modules/data-router.esm.min.js +4 -4
- package/modules/data-router.min.cjs +4 -4
- package/modules/data-router.min.js +4 -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/gantt.esm.min.js +13 -4
- package/modules/gantt.min.cjs +13 -4
- package/modules/gantt.min.js +13 -4
- package/modules/htmx.esm.min.js +1553 -140
- package/modules/htmx.min.cjs +1553 -140
- package/modules/htmx.min.js +1553 -140
- package/modules/kanban.esm.min.js +59 -8
- package/modules/kanban.min.cjs +59 -8
- package/modules/kanban.min.js +59 -8
- package/modules/kpi.esm.min.js +4 -4
- package/modules/kpi.min.cjs +4 -4
- package/modules/kpi.min.js +4 -4
- package/modules/mock-socket.esm.min.js +2 -2
- package/modules/mock-socket.min.cjs +2 -2
- package/modules/mock-socket.min.js +2 -2
- package/modules/react.esm.min.js +3 -3
- package/modules/react.min.cjs +3 -3
- package/modules/react.min.js +3 -3
- package/modules/svelte.esm.min.js +3 -3
- package/modules/svelte.min.cjs +3 -3
- package/modules/svelte.min.js +3 -3
- package/modules/vue.esm.min.js +3 -3
- package/modules/vue.min.cjs +3 -3
- package/modules/vue.min.js +3 -3
- package/modules/webcomponent.esm.min.js +1553 -140
- package/modules/webcomponent.min.cjs +1553 -140
- package/modules/webcomponent.min.js +1553 -140
- package/package.json +1 -1
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.48.0</p>
|
|
441
441
|
<nav>
|
|
442
442
|
<div class="rail__group">
|
|
443
443
|
<span class="rail__label">Start here</span>
|
|
@@ -506,6 +506,7 @@
|
|
|
506
506
|
<a href="#rules-guide">Conditional formatting</a>
|
|
507
507
|
<a href="#formatting-guide">Formatting a user can change</a>
|
|
508
508
|
<a href="#quickfilter-guide">Quick filter</a>
|
|
509
|
+
<a href="#find">Find</a>
|
|
509
510
|
<a href="#charts-guide">In-cell charts</a>
|
|
510
511
|
</div>
|
|
511
512
|
<div class="rail__group">
|
|
@@ -2482,7 +2483,10 @@ grid.setPinnedRows([], { edge: 'top' }); <span class="cmt">// clear</span
|
|
|
2482
2483
|
</p>
|
|
2483
2484
|
<div class="why">
|
|
2484
2485
|
<p><strong>The API.</strong> <code>groupColumns(ids, { title, groupId })</code> wraps columns
|
|
2485
|
-
in a new band or adds them to an existing one; <code>
|
|
2486
|
+
in a new band or adds them to an existing one; pass <code>id</code> instead of
|
|
2487
|
+
<code>groupId</code> to create a new band with a caller-chosen, stable id you can address
|
|
2488
|
+
later (<code>groupColumns(ids, { title: 'Traffic', id: 'g-traffic' })</code>).
|
|
2489
|
+
<code>ungroupColumn(id)</code> takes a column
|
|
2486
2490
|
out (dissolving a band it empties); <code>renameGroup(id, title)</code>,
|
|
2487
2491
|
<code>dissolveGroup(id)</code> and <code>moveGroup(id, to)</code> do the rest. Each emits
|
|
2488
2492
|
<code>columngroup:changed</code>. A band's columns are always contiguous, and a nested band
|
|
@@ -3146,8 +3150,17 @@ createGrid(el, {
|
|
|
3146
3150
|
<p>Column and table names are checked against an identifier pattern rather than escaped, and
|
|
3147
3151
|
a name that fails is refused. Integers past the safe range are kept as strings instead of
|
|
3148
3152
|
being rounded into a plausible lie.</p>
|
|
3153
|
+
<p>A timestamp or date filter is bound through a typed placeholder — <code>"ts" >=
|
|
3154
|
+
CAST(? AS TIMESTAMP)</code> — because a prepared statement binds an ISO string as
|
|
3155
|
+
<code>VARCHAR</code> and DuckDB will not compare that with a <code>TIMESTAMP</code>,
|
|
3156
|
+
<code>TIMESTAMP WITH TIME ZONE</code> or <code>DATE</code> column. The adapter reads the
|
|
3157
|
+
column types once from the engine (<code>DESCRIBE</code>) and falls back to the grid column's
|
|
3158
|
+
declared type, so both a typed and an untyped grid column over a timestamp filter correctly,
|
|
3159
|
+
including a time window. Send instants ending in <code>Z</code>, as the grid's date filter
|
|
3160
|
+
does: the cast is the engine's, and its zone rules apply (see the reference for the
|
|
3161
|
+
<code>TIMESTAMPTZ</code> and naive-string cases).</p>
|
|
3149
3162
|
<p><code>demo/duckdb.html</code> runs this against a Parquet file of several million readings
|
|
3150
|
-
with no server involved.</p>
|
|
3163
|
+
with no server involved, including a time-window filter on its <code>TIMESTAMP</code> column.</p>
|
|
3151
3164
|
</div>
|
|
3152
3165
|
|
|
3153
3166
|
<h3 id="fulldataset">Whole-dataset statistics over a remote source</h3>
|
|
@@ -5081,6 +5094,7 @@ grid.annotate.use(null); <span class="cmt">// hand the grid
|
|
|
5081
5094
|
<tr><td class="name"><kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>H</kbd></td><td class="desc">Move focus to the column header</td></tr>
|
|
5082
5095
|
<tr><td class="name"><kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>P</kbd></td><td class="desc">Move focus to the tool panel</td></tr>
|
|
5083
5096
|
<tr><td class="name"><kbd>Shift</kbd>+<kbd>F10</kbd> <span class="sep">or</span> <kbd>ContextMenu</kbd></td><td class="desc">Open the context menu for the focused cell</td></tr>
|
|
5097
|
+
<tr><td class="name"><kbd>Ctrl</kbd>+<kbd>F</kbd></td><td class="desc">Find in the grid</td></tr>
|
|
5084
5098
|
<tr><td class="name"><kbd>Alt</kbd>+<kbd>Shift</kbd>+<kbd>ArrowUp</kbd> <span class="sep">or</span> <kbd>Alt</kbd>+<kbd>Shift</kbd>+<kbd>ArrowDown</kbd></td><td class="desc">Move the focused row, when row reorder is enabled</td></tr>
|
|
5085
5099
|
<tr><th colspan="2">On a column heading</th></tr>
|
|
5086
5100
|
<tr><td class="name"><kbd>ArrowLeft</kbd> <span class="sep">or</span> <kbd>ArrowRight</kbd></td><td class="desc">Move between headings</td></tr>
|
|
@@ -5412,6 +5426,7 @@ grid.edit.pasteInto(text); <span class="cmt">// Excel's t
|
|
|
5412
5426
|
<tr><td class="sig">Enter</td><td class="desc">Start editing; commit and step down.</td></tr>
|
|
5413
5427
|
<tr><td class="sig">Tab</td><td class="desc">Commit and step across.</td></tr>
|
|
5414
5428
|
<tr><td class="sig">Escape</td><td class="desc">Cancel the edit; restore a maximised grid once nothing else wants it.</td></tr>
|
|
5429
|
+
<tr><td class="sig">Ctrl/Cmd + F</td><td class="desc">Open the <a href="#find">find bar</a>; in it, Enter / Shift+Enter step through the matches and Escape closes.</td></tr>
|
|
5415
5430
|
<tr><td class="sig">Space</td><td class="desc">Toggle the row's selection.</td></tr>
|
|
5416
5431
|
<tr><td class="sig">Home / End, Page Up / Down</td><td class="desc">Jump; with Ctrl, to the ends of the grid.</td></tr>
|
|
5417
5432
|
</tbody>
|
|
@@ -6062,6 +6077,86 @@ grid.highlight.clear();</code></pre>
|
|
|
6062
6077
|
it. A highlight belongs to the row rather than the element, so it survives scrolling, sorting
|
|
6063
6078
|
and paging.
|
|
6064
6079
|
</p>
|
|
6080
|
+
|
|
6081
|
+
<h2 id="find">Find</h2>
|
|
6082
|
+
<p class="lead-in">
|
|
6083
|
+
The quick filter answers "show me only the rows that contain X". Find answers a different
|
|
6084
|
+
question — "where is X?" — and leaves every other row exactly where it was, so you keep your
|
|
6085
|
+
place and the neighbours that give a value its meaning. Press <kbd>Ctrl</kbd>+<kbd>F</kbd>
|
|
6086
|
+
(<kbd>Cmd</kbd>+<kbd>F</kbd> on a Mac) with focus in the grid: a bar opens above the header
|
|
6087
|
+
with focus in its input, every cell whose <em>displayed</em> text matches lights up in place,
|
|
6088
|
+
the bar reads "N of M", <kbd>Enter</kbd> and <kbd>Shift</kbd>+<kbd>Enter</kbd> step through
|
|
6089
|
+
the matches with wrap, and <kbd>Escape</kbd> closes it and clears the marks.
|
|
6090
|
+
</p>
|
|
6091
|
+
<div class="example">
|
|
6092
|
+
<p class="example__label">The same thing from code</p>
|
|
6093
|
+
<pre data-run="js" data-expect="2 matches, 3 rows shown, current a, events true" data-covers="method:find config:find config:shortcut config:debounce event:find:changed"><code>const { createHeadlessGrid } = await import('../packages/core/src/index.js');
|
|
6094
|
+
const grid = createHeadlessGrid({
|
|
6095
|
+
rowKey: 'id',
|
|
6096
|
+
find: { shortcut: true, debounce: 0 }, // the bar's settings; `find: false` removes the bar
|
|
6097
|
+
columns: [
|
|
6098
|
+
{ field: 'name' },
|
|
6099
|
+
{ field: 'price', format: (p) => `$${p.value.toFixed(2)}` },
|
|
6100
|
+
],
|
|
6101
|
+
rows: [
|
|
6102
|
+
{ id: 'a', name: 'Acme', price: 3.5 },
|
|
6103
|
+
{ id: 'b', name: 'Beta', price: 13.25 },
|
|
6104
|
+
{ id: 'c', name: 'Acme Two', price: 3.75 },
|
|
6105
|
+
],
|
|
6106
|
+
});
|
|
6107
|
+
let events = 0;
|
|
6108
|
+
grid.on('find:changed', () => { events += 1; });
|
|
6109
|
+
|
|
6110
|
+
const count = grid.find('$3.'); // the formatted text: two prices begin "$3."
|
|
6111
|
+
const first = grid.find.current(); // { key: 'a', colId: 'price', index: 0, pinned: null }
|
|
6112
|
+
grid.find.next(); // row c; next() again wraps back to a
|
|
6113
|
+
const rowsStillShown = grid.rows.count(); // 3 — find never removes a row
|
|
6114
|
+
|
|
6115
|
+
grid.destroy();
|
|
6116
|
+
return `${count.total} matches, ${rowsStillShown} rows shown, current ${first.key}, events ${events > 0}`;</code></pre>
|
|
6117
|
+
</div>
|
|
6118
|
+
<p class="lead-in">
|
|
6119
|
+
<code>grid.find(text, opts)</code> searches now and returns a <code>FindCount</code>; it is
|
|
6120
|
+
callable like <code>grid.highlight</code>. The options are a <code>FindQuery</code>:
|
|
6121
|
+
<code>caseSensitive</code>, <code>wholeCell</code>, <code>columns</code> (an id or a list of
|
|
6122
|
+
ids; omitted searches every visible column) and <code>from</code> (the display index the
|
|
6123
|
+
first current match is chosen at or after). Then <code>find.next()</code>,
|
|
6124
|
+
<code>find.prev()</code> and <code>find.goTo(i)</code> move the current match and scroll it
|
|
6125
|
+
into view; <code>find.matches()</code>, <code>find.count()</code>,
|
|
6126
|
+
<code>find.current()</code> and <code>find.state()</code> read the result;
|
|
6127
|
+
<code>find.open(text?)</code>, <code>find.close()</code> and <code>find.clear()</code> drive
|
|
6128
|
+
the bar; <code>find.stateFor(key, colId)</code> is what the painter asks. Every change fires
|
|
6129
|
+
<code>find:changed</code> with the query, the open flag and the count.
|
|
6130
|
+
</p>
|
|
6131
|
+
<div class="table-wrap">
|
|
6132
|
+
<table>
|
|
6133
|
+
<thead><tr><th>Rule</th><th>What it means</th></tr></thead>
|
|
6134
|
+
<tbody>
|
|
6135
|
+
<tr><td class="sig">Display text</td><td class="desc">Find matches what the cell <em>shows</em> — a column <code>format</code>, a unit type, a lookup label — never the raw value. Searching <code>$3.</code> finds prices formatted that way. There is no regular-expression mode; the quick filter has one.</td></tr>
|
|
6136
|
+
<tr><td class="sig">An overlay, not a filter</td><td class="desc">No row is reordered, removed or edited. Matches are painted as <code>.lat-cell--find</code>, the current one also as <code>.lat-cell--find-current</code>, coloured by <code>--lattice-find-match</code> and <code>--lattice-find-current</code>. Find and the quick filter coexist: both may be active, and find re-runs over whatever the filter leaves.</td></tr>
|
|
6137
|
+
<tr><td class="sig">Pinned rows and columns</td><td class="desc">Rows pinned to either edge (and a bottom grand total) are searched and painted like any other; a pinned match has <code>index: -1</code> and <code>pinned: 'top' | 'bottom'</code>. Pinned columns are cells like any other.</td></tr>
|
|
6138
|
+
<tr><td class="sig">Virtualised rows</td><td class="desc">Matches are computed from the row model, not the DOM, so a match five thousand rows down is counted without rendering it; stepping to it scrolls it into view, and the paint follows the render.</td></tr>
|
|
6139
|
+
<tr><td class="sig">The active cell</td><td class="desc">Stepping to a match makes it the active cell, so <kbd>Enter</kbd> in the grid edits it — except while an edit is already open, when the match is scrolled and painted and the editor is left alone.</td></tr>
|
|
6140
|
+
<tr><td class="sig">Windowed sources</td><td class="desc">A paged pushdown source (OData, DuckDB, REST) holds only its loaded rows client-side, so only those are searched. The count says so — "N of M <em>in loaded rows</em>", and <code>FindCount.windowed</code> is true with <code>loaded</code> and <code>rows</code> beside it — rather than presenting a page-one count as the whole. Pushing find to the adapter is a follow-up, not a v1 promise.</td></tr>
|
|
6141
|
+
<tr><td class="sig">Large grids</td><td class="desc">Typing is scanned in per-frame slices from the row at the top of the viewport, so the matches on screen appear after the first slice and the grid stays interactive; the count reads "N of M so far" and <code>count.complete</code> is false until the scan finishes. <code>grid.find(text)</code> scans to completion before returning, so its answer is final.</td></tr>
|
|
6142
|
+
<tr><td class="sig">The browser's find</td><td class="desc"><kbd>Ctrl</kbd>+<kbd>F</kbd> is claimed only while focus is inside the grid and not in a text field, so the page's own find works everywhere else and an open cell editor keeps it. <code>find: { shortcut: false }</code> leaves the binding to the page and keeps the bar reachable through <code>find.open()</code>; <code>find: false</code> removes the bar altogether.</td></tr>
|
|
6143
|
+
<tr><td class="sig">Accessibility</td><td class="desc">The bar is a <code>role="search"</code> landmark; every control is a native input, button or select with a catalogue name, so nothing needs a mouse. The count is announced through a polite <code>role="status"</code> line once per completed search ("3 of 12 matches", "No matches in loaded rows"); the current match becomes the focused cell when no edit is open, so a screen reader reads it. The strings are in every bundled locale.</td></tr>
|
|
6144
|
+
<tr><td class="sig">Keys in the bar</td><td class="desc">Only <kbd>Escape</kbd> and <kbd>Enter</kbd> in the input are consumed by the bar. Everything else — <kbd>Tab</kbd> between its controls, <kbd>Enter</kbd> and <kbd>Space</kbd> on its buttons, a page's own <kbd>Ctrl</kbd>+<kbd>S</kbd> — propagates as it would from any form control, so a host's document-level shortcuts still see it; the grid's own keyboard and range layers stand aside for a key aimed at the bar, which is what keeps Tab from being read as "next cell" and Enter from opening an editor.</td></tr>
|
|
6145
|
+
<tr><td class="sig">Pinned strips</td><td class="desc">Stepping to a match scrolls it fully into the part of the body the pinned strips do not cover — below pinned-top rows and sticky group headings, above pinned-bottom rows and a bottom grand total. That is <code>grid.scroll.toRow</code>'s behaviour for every caller, not only find.</td></tr>
|
|
6146
|
+
</tbody>
|
|
6147
|
+
</table>
|
|
6148
|
+
</div>
|
|
6149
|
+
<div class="example">
|
|
6150
|
+
<p class="example__label">Configuration</p>
|
|
6151
|
+
<pre><code>find: false <span class="cmt">// no bar, no Ctrl+F; grid.find(text) still works</span>
|
|
6152
|
+
find: { shortcut: false } <span class="cmt">// bar via grid.find.open() only</span>
|
|
6153
|
+
find: { debounce: 250 } <span class="cmt">// a slower typist, or a slower grid</span>
|
|
6154
|
+
|
|
6155
|
+
grid.find('acme', { caseSensitive: true, wholeCell: false, columns: ['customer'] });
|
|
6156
|
+
grid.find.count(); <span class="cmt">// { current, total, complete, windowed, loaded, rows }</span>
|
|
6157
|
+
grid.on('find:changed', (e) => status.textContent = `${e.count.current} of ${e.count.total}`);</code></pre>
|
|
6158
|
+
</div>
|
|
6159
|
+
|
|
6065
6160
|
<h2 id="views-guide">Saved views</h2>
|
|
6066
6161
|
<p class="lead-in">
|
|
6067
6162
|
A view is a named grid state: sort, filters, grouping, column order, widths, visibility.
|
|
@@ -6434,6 +6529,7 @@ grid.import.apply(preview);</code></pre>
|
|
|
6434
6529
|
<tr><td class="name">processCell</td><td class="desc">(optional)</td></tr>
|
|
6435
6530
|
<tr><td class="name">promoteToMemoryBelow</td><td class="desc">(optional)</td></tr>
|
|
6436
6531
|
<tr><td class="name">quickFilterText</td><td class="desc">Initial quick-filter term. Equivalent to grid.filters.quick(text).</td></tr>
|
|
6532
|
+
<tr><td class="name">find</td><td class="desc">The in-grid find bar (Ctrl+F): false removes it, { shortcut, debounce } tunes it. See <a href="#find">Find</a>.</td></tr>
|
|
6437
6533
|
<tr><td class="name">quote</td><td class="desc">(optional)</td></tr>
|
|
6438
6534
|
<tr><td class="name">removeMs</td><td class="desc">Silence after which a peer is dropped. (optional)</td></tr>
|
|
6439
6535
|
<tr><td class="name">showHeader</td><td class="desc">Draw the column headings at all. false removes the row, and removes it from the accessibility tree rather than only from view. Distinct from showColumnFunctions, which keeps the headings and drops only their sort, filter and menu controls.</td></tr>
|
|
@@ -6770,6 +6866,7 @@ el.grid.sort.set([{ col: 'charge', dir: 'desc' }]);</code></pre>
|
|
|
6770
6866
|
<tbody>
|
|
6771
6867
|
<tr><td class="name">formatting:changed</td><td class="desc">A conditional formatting rule was added, edited, reordered or restated.</td></tr>
|
|
6772
6868
|
<tr><td class="name">highlight:changed</td><td class="desc">A highlight was added or cleared.</td></tr>
|
|
6869
|
+
<tr><td class="name">find:changed</td><td class="desc">The find query, its matches, the current match or the bar's open state changed; carries the FindCount, partial while the sliced scan runs.</td></tr>
|
|
6773
6870
|
<tr><td class="name">permissions:changed</td><td class="desc">The context moved and every column re-resolved.</td></tr>
|
|
6774
6871
|
<tr><td class="name">presentation:captured</td><td class="desc">A PNG was taken.</td></tr>
|
|
6775
6872
|
<tr><td class="name">presentation:changed</td><td class="desc">The options of a running presentation changed.</td></tr>
|
package/lattice-grid.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Lattice Grid 1.
|
|
2
|
+
* Lattice Grid 1.48.0, type declarations
|
|
3
3
|
* Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
|
|
4
4
|
* https://latticegrid.dev
|
|
5
5
|
*/
|
|
@@ -2072,6 +2072,15 @@ export interface GridConfig {
|
|
|
2072
2072
|
*/
|
|
2073
2073
|
shortcuts?: boolean;
|
|
2074
2074
|
|
|
2075
|
+
/**
|
|
2076
|
+
* The in-grid find bar (BACKLOG-0001018): Ctrl+F / Cmd+F with focus in the
|
|
2077
|
+
* grid opens it; typing highlights every matching cell in place without
|
|
2078
|
+
* filtering a row away; Enter and Shift+Enter step through the matches.
|
|
2079
|
+
* `false` removes the bar and its shortcut; the `grid.find` API still works.
|
|
2080
|
+
* Default true.
|
|
2081
|
+
*/
|
|
2082
|
+
find?: boolean | FindConfig;
|
|
2083
|
+
|
|
2075
2084
|
/**
|
|
2076
2085
|
* Let a user reorder rows by dragging a handle, or with
|
|
2077
2086
|
* Alt+Shift+Up/Down.
|
|
@@ -3815,7 +3824,7 @@ export type EventName =
|
|
|
3815
3824
|
/* Selection and view */
|
|
3816
3825
|
| 'selection:changed' | 'range:changed' | 'clipboard:copy'
|
|
3817
3826
|
| 'page:changed' | 'scroll' | 'scroll:end' | 'size:changed'
|
|
3818
|
-
| 'detail:toggled' | 'toolpanel:focus' | 'highlight:changed'
|
|
3827
|
+
| 'detail:toggled' | 'toolpanel:focus' | 'highlight:changed' | 'find:changed'
|
|
3819
3828
|
/* Tree data */
|
|
3820
3829
|
| 'tree:loading' | 'tree:loaded' | 'tree:loadFailed' | 'tree:loadAborted'
|
|
3821
3830
|
/* State, history and views */
|
|
@@ -4096,9 +4105,12 @@ export interface ColumnsApi {
|
|
|
4096
4105
|
* (BACKLOG-0000739). Header banding, not row grouping (see {@link group}); the
|
|
4097
4106
|
* band is a {@link ColumnGroup} node so a drag-, keyboard- or config-built band
|
|
4098
4107
|
* is the same tree, and it round-trips through a saved view. Emits
|
|
4099
|
-
* `columngroup:changed`.
|
|
4108
|
+
* `columngroup:changed`. Pass `groupId` to add to the band already carrying
|
|
4109
|
+
* that id, or `id` (BACKLOG-0000985) to create a new band with a caller-chosen
|
|
4110
|
+
* stable id you can reference later; `groupId` wins if both are given and an
|
|
4111
|
+
* `id` already in use warns and no-ops.
|
|
4100
4112
|
*/
|
|
4101
|
-
groupColumns(ids: string | string[], opts?: { title?: string; at?: number; groupId?: string }): string | null;
|
|
4113
|
+
groupColumns(ids: string | string[], opts?: { title?: string; at?: number; groupId?: string; id?: string }): string | null;
|
|
4102
4114
|
/** Take a leaf out of its band; a band emptied by the move is dissolved. */
|
|
4103
4115
|
ungroupColumn(id: string): void;
|
|
4104
4116
|
/** Rename a banded header. */
|
|
@@ -4319,7 +4331,10 @@ export interface ScrollApi {
|
|
|
4319
4331
|
/**
|
|
4320
4332
|
* A row key, or a display index. A key survives a sort and is usually what a
|
|
4321
4333
|
* caller holds; resolving one scans the display order, so prefer an index
|
|
4322
|
-
* when scrolling a very large grid repeatedly.
|
|
4334
|
+
* when scrolling a very large grid repeatedly. The row lands fully visible in
|
|
4335
|
+
* the part of the body the pinned strips (pinned rows, sticky group
|
|
4336
|
+
* headings, a bottom grand total) do not cover: `end` puts it just above the
|
|
4337
|
+
* bottom strip, `start` just below the top one.
|
|
4323
4338
|
*/
|
|
4324
4339
|
toRow(row: string | number, align?: 'start' | 'center' | 'end' | 'auto'): void;
|
|
4325
4340
|
toColumn(id: string): void;
|
|
@@ -4957,6 +4972,106 @@ export interface HighlightApi {
|
|
|
4957
4972
|
colourFor(key: string, colId: string): string | null;
|
|
4958
4973
|
}
|
|
4959
4974
|
|
|
4975
|
+
/**
|
|
4976
|
+
* The in-grid find bar's settings (BACKLOG-0001018). `find: true` or an
|
|
4977
|
+
* omitted key mounts the bar with these defaults; `find: false` removes the
|
|
4978
|
+
* bar and its shortcut while `grid.find` keeps working programmatically.
|
|
4979
|
+
*/
|
|
4980
|
+
export interface FindConfig {
|
|
4981
|
+
/**
|
|
4982
|
+
* Bind Ctrl+F (Cmd+F on a Mac) while focus is in the grid. The browser's
|
|
4983
|
+
* own find is untouched while focus is anywhere else on the page. Default
|
|
4984
|
+
* true.
|
|
4985
|
+
*/
|
|
4986
|
+
shortcut?: boolean;
|
|
4987
|
+
/** Milliseconds of typing quiet before the bar searches. Default 120. */
|
|
4988
|
+
debounce?: number;
|
|
4989
|
+
}
|
|
4990
|
+
|
|
4991
|
+
/**
|
|
4992
|
+
* How `grid.find(text, opts)` matches. Defaults: case-insensitive, substring,
|
|
4993
|
+
* every visible column, starting from the first row. Find matches the
|
|
4994
|
+
* **formatted display text** — what the cell shows, a column `format`
|
|
4995
|
+
* included — never a raw value; there is no regular-expression mode.
|
|
4996
|
+
*/
|
|
4997
|
+
export interface FindQuery {
|
|
4998
|
+
/** Match letter case exactly. Default false. */
|
|
4999
|
+
caseSensitive?: boolean;
|
|
5000
|
+
/** The whole cell text must equal the search text rather than contain it. Default false. */
|
|
5001
|
+
wholeCell?: boolean;
|
|
5002
|
+
/** Search only these column ids. Omitted searches every visible column. */
|
|
5003
|
+
columns?: string[] | string | null;
|
|
5004
|
+
/** The display index to start from: the first match at or after it becomes current. Default 0. */
|
|
5005
|
+
from?: number;
|
|
5006
|
+
}
|
|
5007
|
+
|
|
5008
|
+
/** One matching cell. */
|
|
5009
|
+
export interface FindMatch {
|
|
5010
|
+
key: string;
|
|
5011
|
+
colId: string;
|
|
5012
|
+
/** The display index, or -1 for a row pinned to an edge. */
|
|
5013
|
+
index: number;
|
|
5014
|
+
/** Which sticky strip a pinned row is in; null for a body row. */
|
|
5015
|
+
pinned: 'top' | 'bottom' | null;
|
|
5016
|
+
}
|
|
5017
|
+
|
|
5018
|
+
/**
|
|
5019
|
+
* How many matches there are and which is current. `windowed` is the honest
|
|
5020
|
+
* scope flag: over a paged pushdown source only the loaded rows are searched,
|
|
5021
|
+
* so `total` counts matches in `loaded` rows out of the `rows` the source
|
|
5022
|
+
* reports for the whole matching set.
|
|
5023
|
+
*/
|
|
5024
|
+
export interface FindCount {
|
|
5025
|
+
/** 1-based position of the current match; 0 when there is none. */
|
|
5026
|
+
current: number;
|
|
5027
|
+
total: number;
|
|
5028
|
+
/** False while the bar's sliced scan is still running, so a partial count is never read as final. */
|
|
5029
|
+
complete: boolean;
|
|
5030
|
+
windowed: boolean;
|
|
5031
|
+
/** Rows the search actually read; a windowed source's not-yet-fetched placeholders are not counted. */
|
|
5032
|
+
loaded: number;
|
|
5033
|
+
/** The rows the source reports for the whole matching set, when it can say. */
|
|
5034
|
+
rows: number;
|
|
5035
|
+
}
|
|
5036
|
+
|
|
5037
|
+
/** The current query and whether the bar is showing. */
|
|
5038
|
+
export interface FindState {
|
|
5039
|
+
text: string;
|
|
5040
|
+
caseSensitive: boolean;
|
|
5041
|
+
wholeCell: boolean;
|
|
5042
|
+
columns: string[] | null;
|
|
5043
|
+
open: boolean;
|
|
5044
|
+
}
|
|
5045
|
+
|
|
5046
|
+
/**
|
|
5047
|
+
* In-grid find (BACKLOG-0001018): locate text and step through where it
|
|
5048
|
+
* occurs without filtering anything away. Matches are a visual overlay — no
|
|
5049
|
+
* row is reordered, removed or edited — and coexist with the quick filter.
|
|
5050
|
+
*/
|
|
5051
|
+
export interface FindApi {
|
|
5052
|
+
/** Search now, scanning every loaded row before returning; an empty text clears. */
|
|
5053
|
+
(text: string, opts?: FindQuery): FindCount;
|
|
5054
|
+
/** Show the bar with focus in its input, optionally seeding the text. */
|
|
5055
|
+
open(text?: string): void;
|
|
5056
|
+
/** Hide the bar and clear every match. */
|
|
5057
|
+
close(): void;
|
|
5058
|
+
/** Clear the query and the highlights, leaving the bar as it is. */
|
|
5059
|
+
clear(): void;
|
|
5060
|
+
/** The next match, wrapping from the last to the first, scrolled into view and made the active cell unless an edit is open. */
|
|
5061
|
+
next(): FindMatch | null;
|
|
5062
|
+
/** The previous match, wrapping from the first to the last. */
|
|
5063
|
+
prev(): FindMatch | null;
|
|
5064
|
+
/** Make the match at a position in `matches()` current. */
|
|
5065
|
+
goTo(index: number): FindMatch | null;
|
|
5066
|
+
/** Every match, in display order: pinned-top rows, then the body, then pinned-bottom rows. */
|
|
5067
|
+
matches(): FindMatch[];
|
|
5068
|
+
count(): FindCount;
|
|
5069
|
+
current(): FindMatch | null;
|
|
5070
|
+
state(): FindState;
|
|
5071
|
+
/** How a cell is painted: the current match, another match, or nothing. */
|
|
5072
|
+
stateFor(key: string, colId: string): 'current' | 'match' | null;
|
|
5073
|
+
}
|
|
5074
|
+
|
|
4960
5075
|
export interface StateApi {
|
|
4961
5076
|
get(): GridState;
|
|
4962
5077
|
apply(state: GridState, opts?: { skip?: (keyof GridState)[] }): StateApplyReport;
|
|
@@ -5242,6 +5357,8 @@ export interface Grid {
|
|
|
5242
5357
|
readonly pagination: PaginationApi;
|
|
5243
5358
|
/** Transient emphasis on a row, column or cell. */
|
|
5244
5359
|
readonly highlight: HighlightApi;
|
|
5360
|
+
/** In-grid find: locate text without filtering, and step through the matches. */
|
|
5361
|
+
readonly find: FindApi;
|
|
5245
5362
|
/** Values hidden from view and from export. */
|
|
5246
5363
|
readonly redaction: RedactionApi;
|
|
5247
5364
|
/** An image of the grid as drawn, where the module is installed. */
|
|
@@ -6163,6 +6280,16 @@ export interface ChartTrend {
|
|
|
6163
6280
|
alpha?: number;
|
|
6164
6281
|
/** For Holt's exponential smoothing, the trend factor in `[0, 1]`; omit to fit it. */
|
|
6165
6282
|
beta?: number;
|
|
6283
|
+
/**
|
|
6284
|
+
* The uncertainty band shaded around a linear `forecast` (BACKLOG-0000975).
|
|
6285
|
+
* The Student-t `prediction` band (a future observation) by default;
|
|
6286
|
+
* `confidence` shades the narrower mean-response band; `false` opts out and
|
|
6287
|
+
* leaves the bare dashed line. Ignored where there is no linear forecast to
|
|
6288
|
+
* put a band on.
|
|
6289
|
+
*/
|
|
6290
|
+
band?: boolean | 'prediction' | 'confidence';
|
|
6291
|
+
/** The forecast band's confidence level in `(0, 1)`; 0.95 by default. */
|
|
6292
|
+
confidence?: number;
|
|
6166
6293
|
/** `false` suppresses the R² label on a linear trend. */
|
|
6167
6294
|
label?: boolean;
|
|
6168
6295
|
}
|
|
@@ -7687,6 +7814,16 @@ declare module 'lattice-grid/modules/kanban' {
|
|
|
7687
7814
|
color?: string;
|
|
7688
7815
|
wipLimit?: number;
|
|
7689
7816
|
collapsed?: boolean;
|
|
7817
|
+
/**
|
|
7818
|
+
* A per-column SLA override (BACKLOG-0000960): a lone threshold read as the
|
|
7819
|
+
* breach level, or a `{ warn, breach }` pair. Overrides the global `sla`
|
|
7820
|
+
* thresholds for cards in this column (precedence: lane → column → global).
|
|
7821
|
+
*/
|
|
7822
|
+
sla?: KanbanSlaThreshold | { warn?: KanbanSlaThreshold; breach?: KanbanSlaThreshold };
|
|
7823
|
+
/** A per-column warn threshold — the shorthand for `sla: { warn }`. */
|
|
7824
|
+
slaWarn?: KanbanSlaThreshold;
|
|
7825
|
+
/** A per-column breach threshold — the shorthand for `sla: { breach }`. */
|
|
7826
|
+
slaBreach?: KanbanSlaThreshold;
|
|
7690
7827
|
};
|
|
7691
7828
|
|
|
7692
7829
|
/** A card field editor handle returned by a host editor factory. */
|
|
@@ -7732,6 +7869,112 @@ declare module 'lattice-grid/modules/kanban' {
|
|
|
7732
7869
|
originalEvent?: unknown;
|
|
7733
7870
|
}
|
|
7734
7871
|
|
|
7872
|
+
/**
|
|
7873
|
+
* A card-aging / SLA threshold (BACKLOG-0000960): a raw millisecond count, or
|
|
7874
|
+
* a `{ weeks, days, hours, minutes, seconds, ms }` spec whose fields are summed
|
|
7875
|
+
* (`{ days: 3, hours: 12 }` → 3.5 days). A negative or non-finite value means
|
|
7876
|
+
* "no threshold at this level".
|
|
7877
|
+
*/
|
|
7878
|
+
type KanbanSlaThreshold = number | {
|
|
7879
|
+
weeks?: number; week?: number; w?: number;
|
|
7880
|
+
days?: number; day?: number; d?: number;
|
|
7881
|
+
hours?: number; hour?: number; h?: number;
|
|
7882
|
+
minutes?: number; minute?: number; m?: number; min?: number;
|
|
7883
|
+
seconds?: number; second?: number; s?: number; sec?: number;
|
|
7884
|
+
ms?: number; milliseconds?: number;
|
|
7885
|
+
};
|
|
7886
|
+
|
|
7887
|
+
/**
|
|
7888
|
+
* Card-aging / SLA configuration (BACKLOG-0000960). A card is measured against a
|
|
7889
|
+
* `warn` and a `breach` threshold; the view puts an age chip on aged cards and a
|
|
7890
|
+
* highlight on breached ones, and a rising crossing fires the `card:sla` event
|
|
7891
|
+
* and the matching `onWarn`/`onBreach` callback (signature `(level, rows)`, the
|
|
7892
|
+
* Data Router alert handler's). Thresholds resolve most-specific-first:
|
|
7893
|
+
* lane → column → global. Reached at runtime as {@link Kanban#sla}.
|
|
7894
|
+
*/
|
|
7895
|
+
interface KanbanSlaConfig {
|
|
7896
|
+
/** The global warn threshold. */
|
|
7897
|
+
warn?: KanbanSlaThreshold;
|
|
7898
|
+
/** The global breach threshold. */
|
|
7899
|
+
breach?: KanbanSlaThreshold;
|
|
7900
|
+
/** Per-column overrides by column id (each a threshold or a `{ warn, breach }` pair). */
|
|
7901
|
+
columns?: Record<string, KanbanSlaThreshold | { warn?: KanbanSlaThreshold; breach?: KanbanSlaThreshold }>;
|
|
7902
|
+
/** Per-swimlane overrides by lane id (each a threshold or a `{ warn, breach }` pair). */
|
|
7903
|
+
lanes?: Record<string, KanbanSlaThreshold | { warn?: KanbanSlaThreshold; breach?: KanbanSlaThreshold }>;
|
|
7904
|
+
/**
|
|
7905
|
+
* Where the ageing clock starts: `'column'` (default) measures time in the
|
|
7906
|
+
* card's current column; `'board'` measures age since the card arrived/was
|
|
7907
|
+
* created.
|
|
7908
|
+
*/
|
|
7909
|
+
basis?: 'column' | 'board';
|
|
7910
|
+
/** A row property holding the wall-clock time the card entered its column. */
|
|
7911
|
+
enteredProperty?: string;
|
|
7912
|
+
/** A row property holding the wall-clock time the card was created. */
|
|
7913
|
+
createdProperty?: string;
|
|
7914
|
+
/** Whether cards in a done column are exempt from ageing (default true). */
|
|
7915
|
+
ignoreDone?: boolean;
|
|
7916
|
+
/** Whether the flow transition log drives the ageing basis when present (default true). */
|
|
7917
|
+
useTransitionLog?: boolean;
|
|
7918
|
+
/** Show the age chip on every aged card (`'always'`), or only on warn/breach (`'threshold'`, default). */
|
|
7919
|
+
showAge?: 'always' | 'threshold';
|
|
7920
|
+
/** A wall-clock epoch clock, injectable for deterministic tests (default `Date.now`). */
|
|
7921
|
+
now?: () => number;
|
|
7922
|
+
/** A re-check interval in ms so a card breaching by sitting still still lights up (0 = off). */
|
|
7923
|
+
tick?: number;
|
|
7924
|
+
/** Called on a rising crossing to warn level, `(level, rows)` — the router alert handler's shape. */
|
|
7925
|
+
onWarn?: (level: 'warn' | 'breach', rows: KanbanRow[]) => void;
|
|
7926
|
+
/** Called on a rising crossing to breach level, `(level, rows)` — the router alert handler's shape. */
|
|
7927
|
+
onBreach?: (level: 'warn' | 'breach', rows: KanbanRow[]) => void;
|
|
7928
|
+
}
|
|
7929
|
+
|
|
7930
|
+
/** The computed SLA state of one card (BACKLOG-0000960). */
|
|
7931
|
+
interface KanbanSlaState {
|
|
7932
|
+
key: unknown;
|
|
7933
|
+
columnId: string | null;
|
|
7934
|
+
lane?: unknown;
|
|
7935
|
+
/** The ageing-clock start epoch (ms), or null when no time source could be resolved. */
|
|
7936
|
+
start: number | null;
|
|
7937
|
+
/** The card's age in ms, or null when unknown. */
|
|
7938
|
+
ageMs: number | null;
|
|
7939
|
+
/** A short human age label (`2d`, `5h`, …), '' when unknown. */
|
|
7940
|
+
ageText: string;
|
|
7941
|
+
/** The resolved warn threshold in ms, or null. */
|
|
7942
|
+
warnMs: number | null;
|
|
7943
|
+
/** The resolved breach threshold in ms, or null. */
|
|
7944
|
+
breachMs: number | null;
|
|
7945
|
+
/** The classified level, or null when the card cannot be aged. */
|
|
7946
|
+
level: 'ok' | 'warn' | 'breach' | null;
|
|
7947
|
+
/** True when `level` is `'breach'`. */
|
|
7948
|
+
breached: boolean;
|
|
7949
|
+
}
|
|
7950
|
+
|
|
7951
|
+
/**
|
|
7952
|
+
* The card-aging / SLA monitor (BACKLOG-0000960), reached as {@link Kanban#sla}
|
|
7953
|
+
* when a `sla` config is supplied. Pure and DOM-free: it computes each card's
|
|
7954
|
+
* ageing state from the board's card model and the flow transition log, and the
|
|
7955
|
+
* view paints it.
|
|
7956
|
+
*/
|
|
7957
|
+
interface KanbanSla {
|
|
7958
|
+
/** The normalised SLA config (read-only). */
|
|
7959
|
+
readonly config: object;
|
|
7960
|
+
/** Recompute every card's SLA state without emitting anything. */
|
|
7961
|
+
sync(): KanbanSla;
|
|
7962
|
+
/** Recompute and fire `card:sla`/`onWarn`/`onBreach` on each rising crossing. */
|
|
7963
|
+
evaluate(opts?: { emit?: boolean }): KanbanSlaState[];
|
|
7964
|
+
/** Establish the baseline, notify on the current state, and start the optional tick. */
|
|
7965
|
+
start(): KanbanSla;
|
|
7966
|
+
/** The SLA state of one card (by card model or key), or null when unknown. */
|
|
7967
|
+
stateFor(cardOrKey: KanbanCard | unknown): KanbanSlaState | null;
|
|
7968
|
+
/** Every card's current SLA state. */
|
|
7969
|
+
states(): KanbanSlaState[];
|
|
7970
|
+
/** The cards currently at breach level. */
|
|
7971
|
+
breaches(): KanbanSlaState[];
|
|
7972
|
+
/** The cards currently at warn level (not yet breached). */
|
|
7973
|
+
warnings(): KanbanSlaState[];
|
|
7974
|
+
/** Stop the tick and drop the board subscriptions. */
|
|
7975
|
+
destroy(): void;
|
|
7976
|
+
}
|
|
7977
|
+
|
|
7735
7978
|
/**
|
|
7736
7979
|
* Kanban configuration. Every structural property is named here so the same
|
|
7737
7980
|
* board maps DemandFlow (a status field, `points`, `sprint`, `epic`, a
|
|
@@ -7772,6 +8015,13 @@ declare module 'lattice-grid/modules/kanban' {
|
|
|
7772
8015
|
children?: KanbanChildren;
|
|
7773
8016
|
/** Card virtualization for tall columns: true, or `{ rowHeight, overscan, threshold, viewport }`. */
|
|
7774
8017
|
virtualize?: boolean | { rowHeight?: number; overscan?: number; threshold?: number; viewport?: number };
|
|
8018
|
+
/**
|
|
8019
|
+
* Card aging / SLA highlighting (BACKLOG-0000960): warn/breach thresholds
|
|
8020
|
+
* (globally, per column and/or per lane) that age each card and fire
|
|
8021
|
+
* `card:sla` on a rising crossing. Opt-in; reached at runtime as
|
|
8022
|
+
* {@link Kanban#sla}. See {@link KanbanSlaConfig}.
|
|
8023
|
+
*/
|
|
8024
|
+
sla?: KanbanSlaConfig;
|
|
7775
8025
|
/** A saved board state (from `getState`) to restore on construction. */
|
|
7776
8026
|
state?: object;
|
|
7777
8027
|
/** Show a per-column add-card affordance. */
|
|
@@ -7872,6 +8122,8 @@ declare module 'lattice-grid/modules/kanban' {
|
|
|
7872
8122
|
readonly el: unknown | null;
|
|
7873
8123
|
readonly rowKey: string | ((row: KanbanRow) => unknown);
|
|
7874
8124
|
rows: KanbanRows;
|
|
8125
|
+
/** The card-aging / SLA monitor, present only when a `sla` config was supplied (BACKLOG-0000960). */
|
|
8126
|
+
sla?: KanbanSla;
|
|
7875
8127
|
columns(): KanbanColumn[];
|
|
7876
8128
|
column(id: string): KanbanColumn | undefined;
|
|
7877
8129
|
count(id: string): number;
|
|
@@ -8153,15 +8405,52 @@ declare module 'lattice-grid/modules/ai' {
|
|
|
8153
8405
|
/**
|
|
8154
8406
|
* A narrative target. `view` narrates the current filtered view; `column`
|
|
8155
8407
|
* narrates one column's profile; `forecast` adds its projection; `kpi`/`chart`
|
|
8156
|
-
* narrate figures the caller passes through in `facts
|
|
8408
|
+
* narrate figures the caller passes through in `facts`; `risk` assembles a
|
|
8409
|
+
* project RISK SUMMARY from the separate Gantt / Kanban modules' public outputs
|
|
8410
|
+
* (BACKLOG-0000979).
|
|
8157
8411
|
*/
|
|
8158
8412
|
interface AITarget {
|
|
8159
|
-
kind?: 'view' | 'column' | 'forecast' | 'kpi' | 'chart';
|
|
8413
|
+
kind?: 'view' | 'column' | 'forecast' | 'kpi' | 'chart' | 'risk';
|
|
8160
8414
|
colId?: string;
|
|
8161
8415
|
/** Forecast options, for `kind: 'forecast'`. */
|
|
8162
8416
|
options?: object;
|
|
8163
8417
|
/** Caller-supplied figures for a KPI/chart Explain, grounded like the rest. */
|
|
8164
8418
|
facts?: Array<{ id?: string; label: string; value: unknown; display?: string; kind?: string; colId?: string }>;
|
|
8419
|
+
/**
|
|
8420
|
+
* For `kind: 'risk'`: a Gantt instance (from `createGantt`). Read duck-typed
|
|
8421
|
+
* for `earnedValue()` (SPI/CPI/variances) and `schedule` (critical path,
|
|
8422
|
+
* float). The AI bundle never imports the Gantt module.
|
|
8423
|
+
*/
|
|
8424
|
+
gantt?: unknown;
|
|
8425
|
+
/**
|
|
8426
|
+
* For `kind: 'risk'`: a Kanban board (from `createKanban`). Read for its
|
|
8427
|
+
* `board.sla` monitor (breach / warning counts). The AI bundle never imports
|
|
8428
|
+
* the Kanban module.
|
|
8429
|
+
*/
|
|
8430
|
+
board?: unknown;
|
|
8431
|
+
/** For `kind: 'risk'`: an SLA monitor, if not reached through `board`. */
|
|
8432
|
+
sla?: unknown;
|
|
8433
|
+
/** For `kind: 'risk'`: a precomputed `gantt.earnedValue()` result. */
|
|
8434
|
+
earnedValue?: object;
|
|
8435
|
+
/** For `kind: 'risk'`: a precomputed `gantt.schedule` result. */
|
|
8436
|
+
schedule?: object;
|
|
8437
|
+
/** For `kind: 'risk'`: precomputed SLA breach states. */
|
|
8438
|
+
breaches?: object[];
|
|
8439
|
+
/** For `kind: 'risk'`: precomputed SLA warning states. */
|
|
8440
|
+
warnings?: object[];
|
|
8441
|
+
/** For `kind: 'risk'`: options passed to `gantt.earnedValue()`. */
|
|
8442
|
+
evmOptions?: object;
|
|
8443
|
+
/**
|
|
8444
|
+
* For `kind: 'risk'`: expose the at-risk task NAMES (off by default — a risk
|
|
8445
|
+
* summary carries aggregates only unless the host opts in).
|
|
8446
|
+
*/
|
|
8447
|
+
includeTaskNames?: boolean;
|
|
8448
|
+
/**
|
|
8449
|
+
* For `kind: 'risk'`: expose the money figures BAC/PV/EV/AC (off by default).
|
|
8450
|
+
*/
|
|
8451
|
+
includeCost?: boolean;
|
|
8452
|
+
/** For `kind: 'risk'`: cap on named at-risk tasks (default 10). */
|
|
8453
|
+
maxTasks?: number;
|
|
8165
8454
|
}
|
|
8166
8455
|
|
|
8167
8456
|
/** The facts packet a narrative grounds on. */
|
|
@@ -8170,7 +8459,27 @@ declare module 'lattice-grid/modules/ai' {
|
|
|
8170
8459
|
facts: AIFact[];
|
|
8171
8460
|
/** The numeric values seeding the reconciliation registry. */
|
|
8172
8461
|
groundedValues: number[];
|
|
8173
|
-
meta: {
|
|
8462
|
+
meta: {
|
|
8463
|
+
kind: string; filtered: boolean; factCount: number; redacted?: boolean; colId?: string;
|
|
8464
|
+
/** For `kind: 'risk'`: which module sources resolved. */
|
|
8465
|
+
sources?: { schedule: boolean; earnedValue: boolean; sla: boolean };
|
|
8466
|
+
/** For `kind: 'risk'`: which opt-in exposures were honoured. */
|
|
8467
|
+
exposed?: { taskNames: boolean; cost: boolean };
|
|
8468
|
+
};
|
|
8469
|
+
}
|
|
8470
|
+
|
|
8471
|
+
/**
|
|
8472
|
+
* The risk facts a board / Gantt risk summary grounds on (BACKLOG-0000979),
|
|
8473
|
+
* from {@link buildRiskFacts}: the facts plus which module sources resolved and
|
|
8474
|
+
* which opt-in exposures (task names, cost) were honoured.
|
|
8475
|
+
*/
|
|
8476
|
+
interface AIRiskFacts {
|
|
8477
|
+
facts: AIFact[];
|
|
8478
|
+
meta: {
|
|
8479
|
+
kind: 'risk';
|
|
8480
|
+
sources: { schedule: boolean; earnedValue: boolean; sla: boolean };
|
|
8481
|
+
exposed: { taskNames: boolean; cost: boolean };
|
|
8482
|
+
};
|
|
8174
8483
|
}
|
|
8175
8484
|
|
|
8176
8485
|
/** The result of a narrative: reconciled prose plus what grounded and what did not. */
|
|
@@ -8366,6 +8675,19 @@ declare module 'lattice-grid/modules/ai' {
|
|
|
8366
8675
|
explain(target?: AITarget, opts?: object): Promise<AINarrative>;
|
|
8367
8676
|
/** An alias for {@link AI.explain}. */
|
|
8368
8677
|
narrate(target?: AITarget, opts?: object): Promise<AINarrative>;
|
|
8678
|
+
/**
|
|
8679
|
+
* Produce a grounded, reconciled board / Gantt RISK SUMMARY
|
|
8680
|
+
* (BACKLOG-0000979): a plain-language reading like "3 tasks at risk on the
|
|
8681
|
+
* critical path, SPI 0.67, 2 SLA breaches". A convenience over
|
|
8682
|
+
* `explain({ kind: 'risk', ... })`; the module sources go in `sources`
|
|
8683
|
+
* (`gantt`, `board`/`sla`, or precomputed outputs). Every figure runs through
|
|
8684
|
+
* the same reconciliation guard as {@link AI.explain}.
|
|
8685
|
+
*/
|
|
8686
|
+
riskSummary(sources?: {
|
|
8687
|
+
gantt?: unknown; board?: unknown; sla?: unknown;
|
|
8688
|
+
earnedValue?: object; schedule?: object; breaches?: object[]; warnings?: object[];
|
|
8689
|
+
includeTaskNames?: boolean; includeCost?: boolean; maxTasks?: number; evmOptions?: object;
|
|
8690
|
+
}, opts?: object): Promise<AINarrative>;
|
|
8369
8691
|
/** Mount (or re-target) the insights panel into an element. */
|
|
8370
8692
|
insights(el?: HTMLElement, opts?: object): AI;
|
|
8371
8693
|
/** Build an "Explain" button bound to a target. */
|
|
@@ -8422,5 +8744,19 @@ declare module 'lattice-grid/modules/ai' {
|
|
|
8422
8744
|
* engine and calls only the host's `ask()`.
|
|
8423
8745
|
*/
|
|
8424
8746
|
export function createAI(grid: unknown, config?: AIConfig): AI;
|
|
8747
|
+
|
|
8748
|
+
/**
|
|
8749
|
+
* Build the RISK-SUMMARY facts packet (BACKLOG-0000979) from the separate
|
|
8750
|
+
* Gantt / Kanban modules' public outputs — SPI/CPI and variances from
|
|
8751
|
+
* `gantt.earnedValue()`, tasks at risk / on the critical path from
|
|
8752
|
+
* `gantt.schedule`, and SLA breaches from `board.sla`. Reads the module
|
|
8753
|
+
* instances (or their precomputed outputs) duck-typed off `target`; the AI
|
|
8754
|
+
* bundle imports neither module. This is the exact grounded set
|
|
8755
|
+
* `explain({ kind: 'risk' })` would use, exposed for preview and testing.
|
|
8756
|
+
*/
|
|
8757
|
+
export function buildRiskFacts(target: AITarget, opts?: {
|
|
8758
|
+
locale?: string; fmt?: (value: number) => string;
|
|
8759
|
+
}): AIRiskFacts;
|
|
8760
|
+
|
|
8425
8761
|
export default createAI;
|
|
8426
8762
|
}
|