@toclocoinc/lattice-grid 1.67.0 → 1.68.1
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/angular/package.json +1 -1
- package/docs/API.html +5334 -3788
- package/docs/api-detail.html +40 -5
- package/lattice-grid.d.ts +3368 -2
- package/lattice-grid.esm.min.js +32 -10
- package/lattice-grid.min.cjs +32 -10
- package/lattice-grid.min.js +32 -10
- package/modules/ai.d.ts +64 -1
- package/modules/ai.esm.min.js +3 -3
- package/modules/ai.min.cjs +3 -3
- package/modules/ai.min.js +3 -3
- package/modules/angular.d.ts +1 -1
- 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.d.ts +1 -1
- package/modules/chart-alluvial.esm.min.js +1 -1
- package/modules/chart-alluvial.min.cjs +1 -1
- package/modules/chart-alluvial.min.js +1 -1
- package/modules/chart-arc.d.ts +1 -1
- package/modules/chart-arc.esm.min.js +1 -1
- package/modules/chart-arc.min.cjs +1 -1
- package/modules/chart-arc.min.js +1 -1
- package/modules/chart-bubblemap.d.ts +1 -1
- package/modules/chart-bubblemap.esm.min.js +1 -1
- package/modules/chart-bubblemap.min.cjs +1 -1
- package/modules/chart-bubblemap.min.js +1 -1
- package/modules/chart-bump.d.ts +1 -1
- package/modules/chart-bump.esm.min.js +1 -1
- package/modules/chart-bump.min.cjs +1 -1
- package/modules/chart-bump.min.js +1 -1
- package/modules/chart-calendar.d.ts +1 -1
- package/modules/chart-calendar.esm.min.js +1 -1
- package/modules/chart-calendar.min.cjs +1 -1
- package/modules/chart-calendar.min.js +1 -1
- package/modules/chart-decomposition.d.ts +1 -1
- package/modules/chart-decomposition.esm.min.js +1 -1
- package/modules/chart-decomposition.min.cjs +1 -1
- package/modules/chart-decomposition.min.js +1 -1
- package/modules/chart-diverging.d.ts +1 -1
- package/modules/chart-diverging.esm.min.js +1 -1
- package/modules/chart-diverging.min.cjs +1 -1
- package/modules/chart-diverging.min.js +1 -1
- package/modules/chart-dumbbell.d.ts +1 -1
- package/modules/chart-dumbbell.esm.min.js +1 -1
- package/modules/chart-dumbbell.min.cjs +1 -1
- package/modules/chart-dumbbell.min.js +1 -1
- package/modules/chart-fan.d.ts +1 -1
- package/modules/chart-fan.esm.min.js +1 -1
- package/modules/chart-fan.min.cjs +1 -1
- package/modules/chart-fan.min.js +1 -1
- package/modules/chart-hexbin.d.ts +1 -1
- package/modules/chart-hexbin.esm.min.js +1 -1
- package/modules/chart-hexbin.min.cjs +1 -1
- package/modules/chart-hexbin.min.js +1 -1
- package/modules/chart-hexmap.d.ts +1 -1
- package/modules/chart-hexmap.esm.min.js +1 -1
- package/modules/chart-hexmap.min.cjs +1 -1
- package/modules/chart-hexmap.min.js +1 -1
- package/modules/chart-icicle.d.ts +1 -1
- package/modules/chart-icicle.esm.min.js +1 -1
- package/modules/chart-icicle.min.cjs +1 -1
- package/modules/chart-icicle.min.js +1 -1
- package/modules/chart-markermap.d.ts +1 -1
- package/modules/chart-markermap.esm.min.js +1 -1
- package/modules/chart-markermap.min.cjs +1 -1
- package/modules/chart-markermap.min.js +1 -1
- package/modules/chart-parallel.d.ts +1 -1
- package/modules/chart-parallel.esm.min.js +1 -1
- package/modules/chart-parallel.min.cjs +1 -1
- package/modules/chart-parallel.min.js +1 -1
- package/modules/chart-ridgeline.d.ts +1 -1
- package/modules/chart-ridgeline.esm.min.js +1 -1
- package/modules/chart-ridgeline.min.cjs +1 -1
- package/modules/chart-ridgeline.min.js +1 -1
- package/modules/chart-roc.d.ts +1 -1
- package/modules/chart-roc.esm.min.js +1 -1
- package/modules/chart-roc.min.cjs +1 -1
- package/modules/chart-roc.min.js +1 -1
- package/modules/chart-slope.d.ts +1 -1
- package/modules/chart-slope.esm.min.js +1 -1
- package/modules/chart-slope.min.cjs +1 -1
- package/modules/chart-slope.min.js +1 -1
- package/modules/chart-splom.d.ts +1 -1
- package/modules/chart-splom.esm.min.js +1 -1
- package/modules/chart-splom.min.cjs +1 -1
- package/modules/chart-splom.min.js +1 -1
- package/modules/chart-waffle.d.ts +1 -1
- package/modules/chart-waffle.esm.min.js +1 -1
- package/modules/chart-waffle.min.cjs +1 -1
- package/modules/chart-waffle.min.js +1 -1
- package/modules/charts.d.ts +16 -1
- package/modules/charts.esm.min.js +1391 -1257
- package/modules/charts.min.cjs +1391 -1257
- package/modules/charts.min.js +1391 -1257
- package/modules/data-router.d.ts +227 -1
- package/modules/data-router.esm.min.js +204 -8
- package/modules/data-router.min.cjs +204 -8
- package/modules/data-router.min.js +204 -8
- package/modules/devtools.d.ts +1 -1
- package/modules/devtools.esm.min.js +1 -1
- package/modules/devtools.min.cjs +1 -1
- package/modules/devtools.min.js +1 -1
- package/modules/dhtmlx-compat.d.ts +1 -1
- package/modules/dhtmlx-compat.esm.min.js +3 -3
- package/modules/dhtmlx-compat.min.cjs +3 -3
- package/modules/dhtmlx-compat.min.js +3 -3
- package/modules/gantt.d.ts +302 -1
- package/modules/gantt.esm.min.js +32 -7
- package/modules/gantt.min.cjs +32 -7
- package/modules/gantt.min.js +32 -7
- package/modules/geo-europe-nuts.d.ts +1 -1
- package/modules/geo-europe-nuts.esm.min.js +1 -1
- package/modules/geo-uk.d.ts +1 -1
- package/modules/geo-uk.esm.min.js +1 -1
- package/modules/geo-us-states.d.ts +1 -1
- package/modules/geo-us-states.esm.min.js +1 -1
- package/modules/geo-world-110m.d.ts +1 -1
- package/modules/geo-world-110m.esm.min.js +1 -1
- package/modules/geo-world-50m.d.ts +1 -1
- package/modules/geo-world-50m.esm.min.js +1 -1
- package/modules/htmx.d.ts +1 -1
- package/modules/htmx.esm.min.js +32 -10
- package/modules/htmx.min.cjs +32 -10
- package/modules/htmx.min.js +32 -10
- package/modules/kanban.d.ts +233 -1
- package/modules/kanban.esm.min.js +3 -3
- package/modules/kanban.min.cjs +3 -3
- package/modules/kanban.min.js +3 -3
- package/modules/kpi.d.ts +196 -8
- package/modules/kpi.esm.min.js +32 -7
- package/modules/kpi.min.cjs +32 -7
- package/modules/kpi.min.js +32 -7
- package/modules/layout.d.ts +117 -1
- package/modules/layout.esm.min.js +3 -3
- package/modules/layout.min.cjs +3 -3
- package/modules/layout.min.js +3 -3
- package/modules/mock-socket.d.ts +6 -1
- package/modules/mock-socket.esm.min.js +1 -1
- package/modules/mock-socket.min.cjs +1 -1
- package/modules/mock-socket.min.js +1 -1
- package/modules/react.d.ts +14 -1
- 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.d.ts +1 -1
- package/modules/svelte.esm.min.js +3 -3
- package/modules/svelte.min.cjs +3 -3
- package/modules/svelte.min.js +3 -3
- package/modules/tabs.d.ts +30 -1
- package/modules/tabs.esm.min.js +13 -14
- package/modules/tabs.min.cjs +13 -14
- package/modules/tabs.min.js +13 -14
- package/modules/vue.d.ts +8 -1
- 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.d.ts +113 -1
- package/modules/webcomponent.esm.min.js +32 -10
- package/modules/webcomponent.min.cjs +32 -10
- package/modules/webcomponent.min.js +32 -10
- package/package.json +1 -1
package/modules/kpi.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Lattice Grid 1.
|
|
2
|
+
* Lattice Grid 1.68.1, kpi module type declarations
|
|
3
3
|
* Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
|
|
4
4
|
* https://latticegrid.dev
|
|
5
5
|
*/
|
|
@@ -20,21 +20,47 @@ type KPIFormat =
|
|
|
20
20
|
* below it critical; `lowerIsBetter` mirrors it. Colour is a host concern.
|
|
21
21
|
*/
|
|
22
22
|
interface KPIThresholds {
|
|
23
|
+
/**
|
|
24
|
+
* The cut point between good and warning. With the default `higherIsBetter`, a value at
|
|
25
|
+
* or above it is good.
|
|
26
|
+
*/
|
|
23
27
|
warn: number;
|
|
28
|
+
/**
|
|
29
|
+
* The cut point between warning and critical. With `higherIsBetter`, a value at or
|
|
30
|
+
* above it (but below `warn`) is a warning and anything below it is critical.
|
|
31
|
+
*/
|
|
24
32
|
critical: number;
|
|
33
|
+
/**
|
|
34
|
+
* Which way is good. `higherIsBetter` (the default) grades upwards from the cut points;
|
|
35
|
+
* `lowerIsBetter` mirrors them, so a small value is the healthy one.
|
|
36
|
+
*/
|
|
25
37
|
direction?: 'higherIsBetter' | 'lowerIsBetter';
|
|
26
38
|
}
|
|
27
39
|
|
|
28
40
|
/** An explicit band: the `status` of the first band whose half-open `[min, max)` contains the value. */
|
|
29
41
|
interface KPIBand {
|
|
42
|
+
/** The lower bound, inclusive. Omitted, the band reaches down without limit. */
|
|
30
43
|
min?: number;
|
|
44
|
+
/** The upper bound, exclusive. Omitted, the band reaches up without limit. */
|
|
31
45
|
max?: number;
|
|
46
|
+
/**
|
|
47
|
+
* The status a value inside this band reports. The first matching band in the list
|
|
48
|
+
* wins, so order them from the narrowest.
|
|
49
|
+
*/
|
|
32
50
|
status: 'good' | 'warn' | 'critical';
|
|
33
51
|
}
|
|
34
52
|
|
|
35
53
|
/** An optional sparkline series: the `y` field plotted in order of the `x` field (or insertion). */
|
|
36
54
|
interface KPISparkline {
|
|
55
|
+
/**
|
|
56
|
+
* The field the points are ordered by. Omitted, the rows are plotted in the order the
|
|
57
|
+
* panel holds them.
|
|
58
|
+
*/
|
|
37
59
|
x?: string;
|
|
60
|
+
/**
|
|
61
|
+
* The value plotted — a field name or a function of the row. Anything that is not a
|
|
62
|
+
* finite number is dropped, and a series with no finite points renders no sparkline.
|
|
63
|
+
*/
|
|
38
64
|
y: string | ((row: KPIRow) => unknown);
|
|
39
65
|
}
|
|
40
66
|
|
|
@@ -60,6 +86,15 @@ interface KPIStatTile {
|
|
|
60
86
|
target?: number;
|
|
61
87
|
/** A baseline the tile's delta is measured against. */
|
|
62
88
|
baseline?: number;
|
|
89
|
+
/**
|
|
90
|
+
* What the movement line prints against `baseline` (F-FRED-G): `'absolute'` the difference alone, `'relative'` the
|
|
91
|
+
* percentage alone, `'both'` (the default, unchanged) both together. A
|
|
92
|
+
* rate series (4.10 vs 4.30) makes the percentage a percent-of-a-percent
|
|
93
|
+
* and meaningless, so `'absolute'` is how a host keeps the line without
|
|
94
|
+
* it. The arrow and its colour follow the sign of the difference either
|
|
95
|
+
* way.
|
|
96
|
+
*/
|
|
97
|
+
delta?: 'absolute' | 'relative' | 'both';
|
|
63
98
|
/** Threshold bands, either two cut points or an explicit band list. */
|
|
64
99
|
thresholds?: KPIThresholds;
|
|
65
100
|
/** Explicit status bands (an alternative to `thresholds`). */
|
|
@@ -112,12 +147,15 @@ type KPITile = KPIStatTile | KPIClockTile;
|
|
|
112
147
|
* of top-level items that expand to the indicators beneath them, each parent
|
|
113
148
|
* highlighted with the worst status below it.
|
|
114
149
|
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
150
|
+
* `tree` is an opt-in: omitted or `false`, the panel is
|
|
151
|
+
* flat whatever its tile ids look like, and a dotted id seen with `tree`
|
|
152
|
+
* unset is reported once rather than silently turned into a hierarchy. Given
|
|
153
|
+
* any object (`{}` included), the shape is declared with `path` or
|
|
154
|
+
* `parentKey` — the same two shapes the grid's tree data and the tree-select
|
|
155
|
+
* editor take — over the **tile specs**, not the rows. With neither declared,
|
|
156
|
+
* one is derived by splitting the tile ids on `separator`, so
|
|
157
|
+
* `system.compute.cpu` files itself under Compute under System. A panel
|
|
158
|
+
* whose ids carry no separator stays flat even with `tree` set.
|
|
121
159
|
*
|
|
122
160
|
* A tile's `field` is never a source: a dot there already means a nested
|
|
123
161
|
* object property.
|
|
@@ -153,18 +191,37 @@ interface KPINodeModel {
|
|
|
153
191
|
key: string;
|
|
154
192
|
/** The tile id, or null on a synthesised level. */
|
|
155
193
|
id: string | null;
|
|
194
|
+
/**
|
|
195
|
+
* What the node is called: the tile's own label, or the path segment a synthesised
|
|
196
|
+
* level came from.
|
|
197
|
+
*/
|
|
156
198
|
label: string;
|
|
157
199
|
/** Depth, 0 at the top level. */
|
|
158
200
|
level: number;
|
|
159
201
|
/** Its place among its siblings, from 1, and how many there are. */
|
|
160
202
|
posinset: number;
|
|
203
|
+
/**
|
|
204
|
+
* How many siblings the node sits among — the other half of the screen-reader's "3 of
|
|
205
|
+
* 7".
|
|
206
|
+
*/
|
|
161
207
|
setsize: number;
|
|
208
|
+
/** Whether the node has anything beneath it. A leaf is never expandable. */
|
|
162
209
|
hasChildren: boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Whether the branch is currently open. Always false for a leaf; a collapsed branch's
|
|
212
|
+
* children are not rendered, because its worst status is already on the node that is.
|
|
213
|
+
*/
|
|
163
214
|
expanded: boolean;
|
|
215
|
+
/** The node's children, in order, each a full node model. */
|
|
164
216
|
children: KPINodeModel[];
|
|
165
217
|
/** The node's own tile, or null on a synthesised level. */
|
|
166
218
|
tile: KPITileModel | null;
|
|
219
|
+
/**
|
|
220
|
+
* The node's own reading, from its tile. Null on a synthesised level — no value is
|
|
221
|
+
* invented for a branch from its children.
|
|
222
|
+
*/
|
|
167
223
|
value: unknown;
|
|
224
|
+
/** The node's reading as text, formatted by its tile. Null on a synthesised level. */
|
|
168
225
|
formatted: string | null;
|
|
169
226
|
/** The node's own status. */
|
|
170
227
|
status: 'good' | 'warn' | 'critical' | 'unknown' | null;
|
|
@@ -178,11 +235,21 @@ interface KPINodeModel {
|
|
|
178
235
|
|
|
179
236
|
/** A computed tile, as it appears in the model. */
|
|
180
237
|
interface KPITileModel {
|
|
238
|
+
/** The tile's identity — its configured `id`, else its label, else its index. */
|
|
181
239
|
id: string;
|
|
240
|
+
/** The tile's accessible name, as configured. */
|
|
182
241
|
label: string;
|
|
183
242
|
/** `'stat'` for an aggregate tile, `'clock'` for a clock tile. */
|
|
184
243
|
kind: 'stat' | 'clock';
|
|
244
|
+
/**
|
|
245
|
+
* How the value was reduced: `sum`, `avg`, `min`, `max`, `count`, `countDistinct` or
|
|
246
|
+
* `custom`.
|
|
247
|
+
*/
|
|
185
248
|
aggregation: string;
|
|
249
|
+
/**
|
|
250
|
+
* The row field the aggregation read. Undefined for a `count` or custom tile that names
|
|
251
|
+
* none, and on a clock tile.
|
|
252
|
+
*/
|
|
186
253
|
field?: string;
|
|
187
254
|
/** For a clock tile, the read instant as epoch milliseconds. */
|
|
188
255
|
value: unknown;
|
|
@@ -204,25 +271,64 @@ interface KPITileModel {
|
|
|
204
271
|
* normally. `null` means the tile has no thresholds or bands configured.
|
|
205
272
|
*/
|
|
206
273
|
status: 'good' | 'warn' | 'critical' | 'unknown' | null;
|
|
274
|
+
/**
|
|
275
|
+
* The tile's target, as configured. It also extends the meter's scale when it falls
|
|
276
|
+
* outside the bands. Undefined on a clock tile.
|
|
277
|
+
*/
|
|
207
278
|
target?: number;
|
|
279
|
+
/** The comparison value the movement line is measured from, as configured. */
|
|
208
280
|
baseline?: number;
|
|
281
|
+
/** `value − baseline`. Null when the tile has no baseline or measured no number. */
|
|
209
282
|
delta: number | null;
|
|
283
|
+
/**
|
|
284
|
+
* The delta as a fraction of the baseline. Null when there is no delta, and when the
|
|
285
|
+
* baseline is zero — a percentage of nothing is not reported as infinity.
|
|
286
|
+
*/
|
|
210
287
|
deltaPercent: number | null;
|
|
288
|
+
/**
|
|
289
|
+
* The delta rendered with the tile's own number format. Undefined when there is no
|
|
290
|
+
* delta.
|
|
291
|
+
*/
|
|
211
292
|
deltaFormatted?: string;
|
|
293
|
+
/** What the movement line prints; see `KPIStatTile.delta`. Always present once `baseline` is. */
|
|
294
|
+
deltaMode?: 'absolute' | 'relative' | 'both';
|
|
295
|
+
/**
|
|
296
|
+
* How many of the panel's rows this tile's filter admitted — its own membership, which
|
|
297
|
+
* may be 0 while the panel holds rows. Always 0 on a clock tile.
|
|
298
|
+
*/
|
|
212
299
|
count: number;
|
|
300
|
+
/**
|
|
301
|
+
* The tile's trend series, as the finite numbers it plots, in `x` order. Null when the
|
|
302
|
+
* tile declares no sparkline and when no row yielded a finite value.
|
|
303
|
+
*/
|
|
213
304
|
sparkline: number[] | null;
|
|
214
305
|
}
|
|
215
306
|
|
|
216
307
|
/** The payload every tile event carries. */
|
|
217
308
|
interface KPIEvent {
|
|
309
|
+
/** The tile model the event is about. */
|
|
218
310
|
tile: KPITileModel;
|
|
311
|
+
/** That tile's id, for a host that only needs to switch on it. */
|
|
219
312
|
id: string;
|
|
313
|
+
/**
|
|
314
|
+
* The DOM event behind this one — a click, double-click, context-menu gesture or the
|
|
315
|
+
* Enter/Space keypress that stands in for a click.
|
|
316
|
+
*/
|
|
220
317
|
originalEvent?: unknown;
|
|
221
318
|
}
|
|
222
319
|
|
|
223
320
|
/** KPI panel configuration. */
|
|
224
321
|
interface KPIConfig {
|
|
322
|
+
/**
|
|
323
|
+
* The rows the tiles reduce over. Use this or `grid`; passing both leaves the panel on
|
|
324
|
+
* the array.
|
|
325
|
+
*/
|
|
225
326
|
rows?: KPIRow[];
|
|
327
|
+
/**
|
|
328
|
+
* A Lattice grid to follow instead of `rows`: the panel reads the grid's displayed rows
|
|
329
|
+
* and re-reads them whenever the grid settles, so it never disagrees with the table
|
|
330
|
+
* beneath it. On a bound panel `rows.apply` and `setRows` are ignored with a warning.
|
|
331
|
+
*/
|
|
226
332
|
grid?: unknown;
|
|
227
333
|
/**
|
|
228
334
|
* Row identity (a field or fn, returning a string or number); default
|
|
@@ -239,9 +345,20 @@ interface KPIConfig {
|
|
|
239
345
|
* confident zero. Ignored on a panel over a plain `rows` array.
|
|
240
346
|
*/
|
|
241
347
|
fields?: string[];
|
|
348
|
+
/** The tiles to show, in display order: aggregate stat tiles, or clock tiles. */
|
|
242
349
|
tiles?: KPITile[];
|
|
350
|
+
/**
|
|
351
|
+
* How many tile columns to aim for. Tiles shrink to fit rather than overflow the host,
|
|
352
|
+
* so a narrow panel settles on fewer. Unset, the layout fits as many as the width
|
|
353
|
+
* allows.
|
|
354
|
+
*/
|
|
243
355
|
columns?: number;
|
|
356
|
+
/** The panel's accessible name. Unset, the panel carries none. */
|
|
244
357
|
ariaLabel?: string;
|
|
358
|
+
/**
|
|
359
|
+
* The placeholder printed where a tile has no number — an unknown tile, or one whose
|
|
360
|
+
* aggregation returned nothing. Defaults to an em dash.
|
|
361
|
+
*/
|
|
245
362
|
nullText?: string;
|
|
246
363
|
/**
|
|
247
364
|
* The default locale a clock tile formats in when the tile itself declares
|
|
@@ -249,7 +366,11 @@ interface KPIConfig {
|
|
|
249
366
|
* on a stat tile, which takes its own `format.locale`.
|
|
250
367
|
*/
|
|
251
368
|
locale?: string;
|
|
252
|
-
/**
|
|
369
|
+
/**
|
|
370
|
+
* Arrange the tiles as a hierarchy; unset or `false` keeps the panel flat.
|
|
371
|
+
* Opt-in: a dotted tile id is not a hierarchy until
|
|
372
|
+
* `tree` is set, and warns once while it is not.
|
|
373
|
+
*/
|
|
253
374
|
tree?: KPITreeConfig | false;
|
|
254
375
|
/**
|
|
255
376
|
* The catalogue the panel's own text is read from. A panel routinely has no
|
|
@@ -258,17 +379,41 @@ interface KPIConfig {
|
|
|
258
379
|
* the shape; a key it does not carry falls back to English.
|
|
259
380
|
*/
|
|
260
381
|
messages?: { t(key: string, params?: Record<string, unknown>): string };
|
|
382
|
+
/**
|
|
383
|
+
* Called when a tile is clicked (or activated from the keyboard), with the same payload
|
|
384
|
+
* as the `tile:click` event. Both fire.
|
|
385
|
+
*/
|
|
261
386
|
onTileClick?: (event: KPIEvent) => void;
|
|
387
|
+
/** Called when a tile is double-clicked, alongside the `tile:dblclick` event. */
|
|
262
388
|
onTileDblClick?: (event: KPIEvent) => void;
|
|
389
|
+
/** Called on a tile's context-menu gesture, alongside the `tile:contextmenu` event. */
|
|
263
390
|
onTileContextMenu?: (event: KPIEvent) => void;
|
|
391
|
+
/**
|
|
392
|
+
* Called when a branch of a hierarchical panel opens or closes, with the node's key,
|
|
393
|
+
* its new state and the node model. Alongside the `node:toggle` event.
|
|
394
|
+
*/
|
|
264
395
|
onNodeToggle?: (event: { key: string; expanded: boolean; node?: KPINodeModel }) => void;
|
|
396
|
+
/**
|
|
397
|
+
* Called after every recompute, with the freshly built model — the hook for mirroring
|
|
398
|
+
* the panel's numbers somewhere else. Alongside the `change` event.
|
|
399
|
+
*/
|
|
265
400
|
onChange?: (event: { model: { tiles: KPITileModel[]; nodes?: KPINodeModel[] } }) => void;
|
|
266
401
|
}
|
|
267
402
|
|
|
268
403
|
/** The keyed-diff consumer surface a KPI panel shares with a grid, so a Data Router routes to it directly. */
|
|
269
404
|
interface KPIRows {
|
|
405
|
+
/**
|
|
406
|
+
* Apply a keyed diff: `add` and `update` upsert a row by its key, `remove` drops one.
|
|
407
|
+
* Only the rows in the diff touch each tile's running total, so a live feed costs
|
|
408
|
+
* nothing per unchanged row. Ignored with a warning on a grid-bound panel.
|
|
409
|
+
*/
|
|
270
410
|
apply(change: { add?: KPIRow[]; update?: KPIRow[]; remove?: unknown[] }): void;
|
|
411
|
+
/** Visit every row the panel holds, with its key. */
|
|
271
412
|
forEach(fn: (row: KPIRow, key: unknown) => void): void;
|
|
413
|
+
/**
|
|
414
|
+
* How many rows the panel holds. This is the panel's emptiness test: with none, every
|
|
415
|
+
* stat tile reports `unknown` rather than a healthy zero.
|
|
416
|
+
*/
|
|
272
417
|
readonly count: number;
|
|
273
418
|
}
|
|
274
419
|
|
|
@@ -279,14 +424,25 @@ interface KPIRows {
|
|
|
279
424
|
* updating each tile incrementally from the routed delta.
|
|
280
425
|
*/
|
|
281
426
|
interface KPI {
|
|
427
|
+
/** The element the panel renders into, or null for a headless panel. */
|
|
282
428
|
readonly el: unknown | null;
|
|
283
429
|
/** The resolved row identity; see `KPIConfig.rowKey`. */
|
|
284
430
|
readonly rowKey: string | ((row: KPIRow) => string | number);
|
|
285
431
|
/** Whether the panel renders as a hierarchy rather than a flat tile grid. */
|
|
286
432
|
readonly tree: boolean;
|
|
433
|
+
/**
|
|
434
|
+
* The keyed-diff consumer surface, the same shape a grid exposes — this is what makes a
|
|
435
|
+
* panel a Data Router target.
|
|
436
|
+
*/
|
|
287
437
|
rows: KPIRows;
|
|
438
|
+
/** Every tile model, in configured order. */
|
|
288
439
|
tiles(): KPITileModel[];
|
|
440
|
+
/** One tile model by id, or undefined when no tile has that id. */
|
|
289
441
|
tile(id: string): KPITileModel | undefined;
|
|
442
|
+
/**
|
|
443
|
+
* A tile's computed value. Null for an unknown id, and for a tile that measured
|
|
444
|
+
* nothing.
|
|
445
|
+
*/
|
|
290
446
|
value(id: string): unknown;
|
|
291
447
|
/** The top-level nodes of the hierarchy. Empty on a flat panel. */
|
|
292
448
|
nodes(): KPINodeModel[];
|
|
@@ -294,15 +450,47 @@ interface KPI {
|
|
|
294
450
|
node(key: string): KPINodeModel | undefined;
|
|
295
451
|
/** The nodes on screen: the roots, plus the children of every open branch. */
|
|
296
452
|
visibleNodes(): KPINodeModel[];
|
|
453
|
+
/**
|
|
454
|
+
* Open a branch of a hierarchical panel by node key, re-render, and fire `node:toggle`.
|
|
455
|
+
* A key that is already open changes nothing.
|
|
456
|
+
*/
|
|
297
457
|
expand(key: string): KPI;
|
|
458
|
+
/** Close a branch by node key, re-render, and fire `node:toggle`. */
|
|
298
459
|
collapse(key: string): KPI;
|
|
460
|
+
/** Flip a branch between open and closed, firing `node:toggle` on the change. */
|
|
299
461
|
toggle(key: string): KPI;
|
|
462
|
+
/**
|
|
463
|
+
* Replace the source rows and recompute, and make that array the source again so a
|
|
464
|
+
* later `refresh()` re-reads it. Ignored with a warning on a grid-bound panel.
|
|
465
|
+
*/
|
|
300
466
|
setRows(rows: KPIRow[]): KPI;
|
|
467
|
+
/**
|
|
468
|
+
* Recompute every tile and re-render. A bound panel re-reads the grid now rather than
|
|
469
|
+
* at the end of the turn; a configured panel re-reads its array; once rows have arrived
|
|
470
|
+
* through `rows.apply` nothing is re-read, so a routed feed is never thrown away.
|
|
471
|
+
*/
|
|
301
472
|
refresh(): KPI;
|
|
473
|
+
/**
|
|
474
|
+
* The restorable state: the rows the panel holds, and — on a hierarchical panel only —
|
|
475
|
+
* which branches are open.
|
|
476
|
+
*/
|
|
302
477
|
getState(): object;
|
|
478
|
+
/**
|
|
479
|
+
* Restore a snapshot from `getState`. A snapshot without `expanded` leaves the
|
|
480
|
+
* expansion alone rather than collapsing the rail.
|
|
481
|
+
*/
|
|
303
482
|
setState(snapshot: object): KPI;
|
|
483
|
+
/**
|
|
484
|
+
* Register an event handler; returns a function that removes it. An unrecognised event
|
|
485
|
+
* name is warned about once.
|
|
486
|
+
*/
|
|
304
487
|
on(name: string, fn: (event: KPIEvent) => void): () => void;
|
|
488
|
+
/** Remove a handler registered with `on`. */
|
|
305
489
|
off(name: string, fn: (event: KPIEvent) => void): void;
|
|
490
|
+
/**
|
|
491
|
+
* Drop every listener, stop following the bound grid, stop any clock tile ticking, and
|
|
492
|
+
* empty the element (removing only the class the panel added).
|
|
493
|
+
*/
|
|
306
494
|
destroy(): void;
|
|
307
495
|
}
|
|
308
496
|
|
package/modules/kpi.esm.min.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Lattice Grid 1.
|
|
2
|
+
* Lattice Grid 1.68.1, kpi module
|
|
3
3
|
* Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
|
|
4
4
|
* https://latticegrid.dev
|
|
5
5
|
*/
|
|
@@ -52,12 +52,12 @@ Object.defineProperty(__exports,"frameBatched",{enumerable:true,get:function(){r
|
|
|
52
52
|
Object.defineProperty(__exports,"settleDebounce",{enumerable:true,get:function(){return settleDebounce;}});
|
|
53
53
|
Object.defineProperty(__exports,"whenIdle",{enumerable:true,get:function(){return whenIdle;}});
|
|
54
54
|
Object.defineProperty(__exports,"uid",{enumerable:true,get:function(){return uid;}});
|
|
55
|
-
const STAMPED_VERSION="1.
|
|
55
|
+
const STAMPED_VERSION="1.68.1";
|
|
56
56
|
async function resolveVersion(){
|
|
57
57
|
if(STAMPED_VERSION!=='0.0.0-source')return STAMPED_VERSION;
|
|
58
58
|
return STAMPED_VERSION;
|
|
59
59
|
}
|
|
60
|
-
const VERSION="1.
|
|
60
|
+
const VERSION="1.68.1";
|
|
61
61
|
const warned=new Set();
|
|
62
62
|
const WARNED_LIMIT=2000;
|
|
63
63
|
function rememberWarned(key){
|
|
@@ -825,7 +825,15 @@ const rank=Math.max(SEVERITY[a]||0,SEVERITY[b]||0);
|
|
|
825
825
|
return BY_RANK[rank];
|
|
826
826
|
}
|
|
827
827
|
function resolveHierarchy(config,tiles){
|
|
828
|
-
if(
|
|
828
|
+
if(!tiles.length)return null;
|
|
829
|
+
if(config===false)return null;
|
|
830
|
+
if(config===undefined||config===null){
|
|
831
|
+
if(tiles.some((t)=>t.id.includes(DEFAULT_SEPARATOR))){
|
|
832
|
+
warnOnce('kpi:tree:dotted-id',
|
|
833
|
+
'kpi: tile ids contain dots; set `tree` to render them as a hierarchy.');
|
|
834
|
+
}
|
|
835
|
+
return null;
|
|
836
|
+
}
|
|
829
837
|
const cfg=isObject(config)?config:{};
|
|
830
838
|
const order=tiles.map((_,i)=>i);
|
|
831
839
|
const keyOf=(physical)=>tiles[physical].id;
|
|
@@ -1184,14 +1192,20 @@ return node;
|
|
|
1184
1192
|
function deltaNode(doc,fig,t){
|
|
1185
1193
|
const dir=t.delta>0?'up':(t.delta<0?'down':'flat');
|
|
1186
1194
|
const arrow=t.delta>0?'▲':(t.delta<0?'▼':'■');
|
|
1195
|
+
const abs=t.deltaFormatted??t.delta;
|
|
1187
1196
|
const pct=t.deltaPercent===null||t.deltaPercent===undefined
|
|
1188
|
-
?
|
|
1197
|
+
?null:`${(t.deltaPercent*100).toFixed(1)}%`;
|
|
1198
|
+
const mode=t.deltaMode||'both';
|
|
1199
|
+
let text;
|
|
1200
|
+
if(mode==='absolute'||pct===null)text=`${arrow} ${abs}`;
|
|
1201
|
+
else if(mode==='relative')text=`${arrow} ${pct}`;
|
|
1202
|
+
else text=`${arrow} ${abs} (${pct})`;
|
|
1189
1203
|
const node=childByClass(fig,`${NS}__delta`)||div(doc,`${NS}__delta`);
|
|
1190
1204
|
for(const d of['up','down','flat']){
|
|
1191
1205
|
if(d!==dir)node.classList.remove(`${NS}__delta--${d}`);
|
|
1192
1206
|
}
|
|
1193
1207
|
node.classList.add(`${NS}__delta--${dir}`);
|
|
1194
|
-
setText(node
|
|
1208
|
+
setText(node,text);
|
|
1195
1209
|
return node;
|
|
1196
1210
|
}
|
|
1197
1211
|
function sparkNode(doc,fig,t){
|
|
@@ -5582,7 +5596,7 @@ const columns=this.#columnList();
|
|
|
5582
5596
|
const parts=[];
|
|
5583
5597
|
const hidden=this.#ctx.columnHidden;
|
|
5584
5598
|
for(const column of columns){
|
|
5585
|
-
if(column.
|
|
5599
|
+
if(column.quickFilter===false)continue;
|
|
5586
5600
|
if(isFunction(hidden)&&hidden(column.id))continue;
|
|
5587
5601
|
const custom=column.value&&isFunction(column.value.quickFilterText)
|
|
5588
5602
|
?column.value.quickFilterText({value:undefined,data,row:null,column,colId:column.id,grid:null,context:this.#state('context',null)})
|
|
@@ -5843,6 +5857,7 @@ const readClock=__m7["readClock"];
|
|
|
5843
5857
|
const KPI_EVENTS=Object.freeze([
|
|
5844
5858
|
'tile:click','tile:dblclick','tile:contextmenu','node:toggle','change',
|
|
5845
5859
|
]);
|
|
5860
|
+
const DELTA_MODES=Object.freeze(['absolute','relative','both']);
|
|
5846
5861
|
const GRID_FOLLOW_EVENTS=Object.freeze([
|
|
5847
5862
|
'rows:changed','filter:changed','sort:changed','cell:changed','model:changed',
|
|
5848
5863
|
'stream:chunk','stream:evicted',
|
|
@@ -5908,12 +5923,20 @@ format:spec.format,
|
|
|
5908
5923
|
target:spec.target,
|
|
5909
5924
|
barBounds:barBounds(spec),
|
|
5910
5925
|
baseline:spec.baseline,
|
|
5926
|
+
deltaMode:resolveDeltaMode(spec.delta,id),
|
|
5911
5927
|
spark:normaliseSpark(spec.sparkline),
|
|
5912
5928
|
acc,
|
|
5913
5929
|
members:0,
|
|
5914
5930
|
noColumn:false,
|
|
5915
5931
|
};
|
|
5916
5932
|
}
|
|
5933
|
+
function resolveDeltaMode(raw,id){
|
|
5934
|
+
if(raw===undefined)return'both';
|
|
5935
|
+
if(DELTA_MODES.includes(raw))return raw;
|
|
5936
|
+
warnOnce(`kpi:delta:${id}`,
|
|
5937
|
+
`kpi: tile "${id}" has delta: ${JSON.stringify(raw)}; expected one of ${DELTA_MODES.join(', ')}. Falling back to 'both'.`);
|
|
5938
|
+
return'both';
|
|
5939
|
+
}
|
|
5917
5940
|
function normaliseSpark(s){
|
|
5918
5941
|
if(!s)return null;
|
|
5919
5942
|
if(typeof s==='string')return{x:undefined,y:accessorFor(s)};
|
|
@@ -6160,6 +6183,7 @@ baseline:undefined,
|
|
|
6160
6183
|
delta:null,
|
|
6161
6184
|
deltaPercent:null,
|
|
6162
6185
|
deltaFormatted:undefined,
|
|
6186
|
+
deltaMode:undefined,
|
|
6163
6187
|
count:0,
|
|
6164
6188
|
sparkline:null,
|
|
6165
6189
|
bar:null,
|
|
@@ -6197,6 +6221,7 @@ baseline:t.baseline,
|
|
|
6197
6221
|
delta,
|
|
6198
6222
|
deltaPercent,
|
|
6199
6223
|
deltaFormatted,
|
|
6224
|
+
deltaMode:t.deltaMode,
|
|
6200
6225
|
count:t.members,
|
|
6201
6226
|
sparkline:sparkFor(t),
|
|
6202
6227
|
bar:t.barBounds
|
package/modules/kpi.min.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Lattice Grid 1.
|
|
2
|
+
* Lattice Grid 1.68.1, kpi module
|
|
3
3
|
* Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
|
|
4
4
|
* https://latticegrid.dev
|
|
5
5
|
*/
|
|
@@ -54,12 +54,12 @@ Object.defineProperty(__exports,"frameBatched",{enumerable:true,get:function(){r
|
|
|
54
54
|
Object.defineProperty(__exports,"settleDebounce",{enumerable:true,get:function(){return settleDebounce;}});
|
|
55
55
|
Object.defineProperty(__exports,"whenIdle",{enumerable:true,get:function(){return whenIdle;}});
|
|
56
56
|
Object.defineProperty(__exports,"uid",{enumerable:true,get:function(){return uid;}});
|
|
57
|
-
const STAMPED_VERSION="1.
|
|
57
|
+
const STAMPED_VERSION="1.68.1";
|
|
58
58
|
async function resolveVersion(){
|
|
59
59
|
if(STAMPED_VERSION!=='0.0.0-source')return STAMPED_VERSION;
|
|
60
60
|
return STAMPED_VERSION;
|
|
61
61
|
}
|
|
62
|
-
const VERSION="1.
|
|
62
|
+
const VERSION="1.68.1";
|
|
63
63
|
const warned=new Set();
|
|
64
64
|
const WARNED_LIMIT=2000;
|
|
65
65
|
function rememberWarned(key){
|
|
@@ -827,7 +827,15 @@ const rank=Math.max(SEVERITY[a]||0,SEVERITY[b]||0);
|
|
|
827
827
|
return BY_RANK[rank];
|
|
828
828
|
}
|
|
829
829
|
function resolveHierarchy(config,tiles){
|
|
830
|
-
if(
|
|
830
|
+
if(!tiles.length)return null;
|
|
831
|
+
if(config===false)return null;
|
|
832
|
+
if(config===undefined||config===null){
|
|
833
|
+
if(tiles.some((t)=>t.id.includes(DEFAULT_SEPARATOR))){
|
|
834
|
+
warnOnce('kpi:tree:dotted-id',
|
|
835
|
+
'kpi: tile ids contain dots; set `tree` to render them as a hierarchy.');
|
|
836
|
+
}
|
|
837
|
+
return null;
|
|
838
|
+
}
|
|
831
839
|
const cfg=isObject(config)?config:{};
|
|
832
840
|
const order=tiles.map((_,i)=>i);
|
|
833
841
|
const keyOf=(physical)=>tiles[physical].id;
|
|
@@ -1186,14 +1194,20 @@ return node;
|
|
|
1186
1194
|
function deltaNode(doc,fig,t){
|
|
1187
1195
|
const dir=t.delta>0?'up':(t.delta<0?'down':'flat');
|
|
1188
1196
|
const arrow=t.delta>0?'▲':(t.delta<0?'▼':'■');
|
|
1197
|
+
const abs=t.deltaFormatted??t.delta;
|
|
1189
1198
|
const pct=t.deltaPercent===null||t.deltaPercent===undefined
|
|
1190
|
-
?
|
|
1199
|
+
?null:`${(t.deltaPercent*100).toFixed(1)}%`;
|
|
1200
|
+
const mode=t.deltaMode||'both';
|
|
1201
|
+
let text;
|
|
1202
|
+
if(mode==='absolute'||pct===null)text=`${arrow} ${abs}`;
|
|
1203
|
+
else if(mode==='relative')text=`${arrow} ${pct}`;
|
|
1204
|
+
else text=`${arrow} ${abs} (${pct})`;
|
|
1191
1205
|
const node=childByClass(fig,`${NS}__delta`)||div(doc,`${NS}__delta`);
|
|
1192
1206
|
for(const d of['up','down','flat']){
|
|
1193
1207
|
if(d!==dir)node.classList.remove(`${NS}__delta--${d}`);
|
|
1194
1208
|
}
|
|
1195
1209
|
node.classList.add(`${NS}__delta--${dir}`);
|
|
1196
|
-
setText(node
|
|
1210
|
+
setText(node,text);
|
|
1197
1211
|
return node;
|
|
1198
1212
|
}
|
|
1199
1213
|
function sparkNode(doc,fig,t){
|
|
@@ -5584,7 +5598,7 @@ const columns=this.#columnList();
|
|
|
5584
5598
|
const parts=[];
|
|
5585
5599
|
const hidden=this.#ctx.columnHidden;
|
|
5586
5600
|
for(const column of columns){
|
|
5587
|
-
if(column.
|
|
5601
|
+
if(column.quickFilter===false)continue;
|
|
5588
5602
|
if(isFunction(hidden)&&hidden(column.id))continue;
|
|
5589
5603
|
const custom=column.value&&isFunction(column.value.quickFilterText)
|
|
5590
5604
|
?column.value.quickFilterText({value:undefined,data,row:null,column,colId:column.id,grid:null,context:this.#state('context',null)})
|
|
@@ -5845,6 +5859,7 @@ const readClock=__m7["readClock"];
|
|
|
5845
5859
|
const KPI_EVENTS=Object.freeze([
|
|
5846
5860
|
'tile:click','tile:dblclick','tile:contextmenu','node:toggle','change',
|
|
5847
5861
|
]);
|
|
5862
|
+
const DELTA_MODES=Object.freeze(['absolute','relative','both']);
|
|
5848
5863
|
const GRID_FOLLOW_EVENTS=Object.freeze([
|
|
5849
5864
|
'rows:changed','filter:changed','sort:changed','cell:changed','model:changed',
|
|
5850
5865
|
'stream:chunk','stream:evicted',
|
|
@@ -5910,12 +5925,20 @@ format:spec.format,
|
|
|
5910
5925
|
target:spec.target,
|
|
5911
5926
|
barBounds:barBounds(spec),
|
|
5912
5927
|
baseline:spec.baseline,
|
|
5928
|
+
deltaMode:resolveDeltaMode(spec.delta,id),
|
|
5913
5929
|
spark:normaliseSpark(spec.sparkline),
|
|
5914
5930
|
acc,
|
|
5915
5931
|
members:0,
|
|
5916
5932
|
noColumn:false,
|
|
5917
5933
|
};
|
|
5918
5934
|
}
|
|
5935
|
+
function resolveDeltaMode(raw,id){
|
|
5936
|
+
if(raw===undefined)return'both';
|
|
5937
|
+
if(DELTA_MODES.includes(raw))return raw;
|
|
5938
|
+
warnOnce(`kpi:delta:${id}`,
|
|
5939
|
+
`kpi: tile "${id}" has delta: ${JSON.stringify(raw)}; expected one of ${DELTA_MODES.join(', ')}. Falling back to 'both'.`);
|
|
5940
|
+
return'both';
|
|
5941
|
+
}
|
|
5919
5942
|
function normaliseSpark(s){
|
|
5920
5943
|
if(!s)return null;
|
|
5921
5944
|
if(typeof s==='string')return{x:undefined,y:accessorFor(s)};
|
|
@@ -6162,6 +6185,7 @@ baseline:undefined,
|
|
|
6162
6185
|
delta:null,
|
|
6163
6186
|
deltaPercent:null,
|
|
6164
6187
|
deltaFormatted:undefined,
|
|
6188
|
+
deltaMode:undefined,
|
|
6165
6189
|
count:0,
|
|
6166
6190
|
sparkline:null,
|
|
6167
6191
|
bar:null,
|
|
@@ -6199,6 +6223,7 @@ baseline:t.baseline,
|
|
|
6199
6223
|
delta,
|
|
6200
6224
|
deltaPercent,
|
|
6201
6225
|
deltaFormatted,
|
|
6226
|
+
deltaMode:t.deltaMode,
|
|
6202
6227
|
count:t.members,
|
|
6203
6228
|
sparkline:sparkFor(t),
|
|
6204
6229
|
bar:t.barBounds
|