@toclocoinc/lattice-grid 1.67.0 → 1.68.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.
Files changed (163) hide show
  1. package/README.md +1 -1
  2. package/angular/package.json +1 -1
  3. package/docs/API.html +21 -16
  4. package/docs/api-detail.html +40 -5
  5. package/lattice-grid.d.ts +12 -2
  6. package/lattice-grid.esm.min.js +27 -7
  7. package/lattice-grid.min.cjs +27 -7
  8. package/lattice-grid.min.js +27 -7
  9. package/modules/ai.d.ts +1 -1
  10. package/modules/ai.esm.min.js +3 -3
  11. package/modules/ai.min.cjs +3 -3
  12. package/modules/ai.min.js +3 -3
  13. package/modules/angular.d.ts +1 -1
  14. package/modules/angular.esm.min.js +3 -3
  15. package/modules/angular.min.cjs +3 -3
  16. package/modules/angular.min.js +3 -3
  17. package/modules/chart-alluvial.d.ts +1 -1
  18. package/modules/chart-alluvial.esm.min.js +1 -1
  19. package/modules/chart-alluvial.min.cjs +1 -1
  20. package/modules/chart-alluvial.min.js +1 -1
  21. package/modules/chart-arc.d.ts +1 -1
  22. package/modules/chart-arc.esm.min.js +1 -1
  23. package/modules/chart-arc.min.cjs +1 -1
  24. package/modules/chart-arc.min.js +1 -1
  25. package/modules/chart-bubblemap.d.ts +1 -1
  26. package/modules/chart-bubblemap.esm.min.js +1 -1
  27. package/modules/chart-bubblemap.min.cjs +1 -1
  28. package/modules/chart-bubblemap.min.js +1 -1
  29. package/modules/chart-bump.d.ts +1 -1
  30. package/modules/chart-bump.esm.min.js +1 -1
  31. package/modules/chart-bump.min.cjs +1 -1
  32. package/modules/chart-bump.min.js +1 -1
  33. package/modules/chart-calendar.d.ts +1 -1
  34. package/modules/chart-calendar.esm.min.js +1 -1
  35. package/modules/chart-calendar.min.cjs +1 -1
  36. package/modules/chart-calendar.min.js +1 -1
  37. package/modules/chart-decomposition.d.ts +1 -1
  38. package/modules/chart-decomposition.esm.min.js +1 -1
  39. package/modules/chart-decomposition.min.cjs +1 -1
  40. package/modules/chart-decomposition.min.js +1 -1
  41. package/modules/chart-diverging.d.ts +1 -1
  42. package/modules/chart-diverging.esm.min.js +1 -1
  43. package/modules/chart-diverging.min.cjs +1 -1
  44. package/modules/chart-diverging.min.js +1 -1
  45. package/modules/chart-dumbbell.d.ts +1 -1
  46. package/modules/chart-dumbbell.esm.min.js +1 -1
  47. package/modules/chart-dumbbell.min.cjs +1 -1
  48. package/modules/chart-dumbbell.min.js +1 -1
  49. package/modules/chart-fan.d.ts +1 -1
  50. package/modules/chart-fan.esm.min.js +1 -1
  51. package/modules/chart-fan.min.cjs +1 -1
  52. package/modules/chart-fan.min.js +1 -1
  53. package/modules/chart-hexbin.d.ts +1 -1
  54. package/modules/chart-hexbin.esm.min.js +1 -1
  55. package/modules/chart-hexbin.min.cjs +1 -1
  56. package/modules/chart-hexbin.min.js +1 -1
  57. package/modules/chart-hexmap.d.ts +1 -1
  58. package/modules/chart-hexmap.esm.min.js +1 -1
  59. package/modules/chart-hexmap.min.cjs +1 -1
  60. package/modules/chart-hexmap.min.js +1 -1
  61. package/modules/chart-icicle.d.ts +1 -1
  62. package/modules/chart-icicle.esm.min.js +1 -1
  63. package/modules/chart-icicle.min.cjs +1 -1
  64. package/modules/chart-icicle.min.js +1 -1
  65. package/modules/chart-markermap.d.ts +1 -1
  66. package/modules/chart-markermap.esm.min.js +1 -1
  67. package/modules/chart-markermap.min.cjs +1 -1
  68. package/modules/chart-markermap.min.js +1 -1
  69. package/modules/chart-parallel.d.ts +1 -1
  70. package/modules/chart-parallel.esm.min.js +1 -1
  71. package/modules/chart-parallel.min.cjs +1 -1
  72. package/modules/chart-parallel.min.js +1 -1
  73. package/modules/chart-ridgeline.d.ts +1 -1
  74. package/modules/chart-ridgeline.esm.min.js +1 -1
  75. package/modules/chart-ridgeline.min.cjs +1 -1
  76. package/modules/chart-ridgeline.min.js +1 -1
  77. package/modules/chart-roc.d.ts +1 -1
  78. package/modules/chart-roc.esm.min.js +1 -1
  79. package/modules/chart-roc.min.cjs +1 -1
  80. package/modules/chart-roc.min.js +1 -1
  81. package/modules/chart-slope.d.ts +1 -1
  82. package/modules/chart-slope.esm.min.js +1 -1
  83. package/modules/chart-slope.min.cjs +1 -1
  84. package/modules/chart-slope.min.js +1 -1
  85. package/modules/chart-splom.d.ts +1 -1
  86. package/modules/chart-splom.esm.min.js +1 -1
  87. package/modules/chart-splom.min.cjs +1 -1
  88. package/modules/chart-splom.min.js +1 -1
  89. package/modules/chart-waffle.d.ts +1 -1
  90. package/modules/chart-waffle.esm.min.js +1 -1
  91. package/modules/chart-waffle.min.cjs +1 -1
  92. package/modules/chart-waffle.min.js +1 -1
  93. package/modules/charts.d.ts +1 -1
  94. package/modules/charts.esm.min.js +1376 -1249
  95. package/modules/charts.min.cjs +1376 -1249
  96. package/modules/charts.min.js +1376 -1249
  97. package/modules/data-router.d.ts +1 -1
  98. package/modules/data-router.esm.min.js +204 -8
  99. package/modules/data-router.min.cjs +204 -8
  100. package/modules/data-router.min.js +204 -8
  101. package/modules/devtools.d.ts +1 -1
  102. package/modules/devtools.esm.min.js +1 -1
  103. package/modules/devtools.min.cjs +1 -1
  104. package/modules/devtools.min.js +1 -1
  105. package/modules/dhtmlx-compat.d.ts +1 -1
  106. package/modules/dhtmlx-compat.esm.min.js +3 -3
  107. package/modules/dhtmlx-compat.min.cjs +3 -3
  108. package/modules/dhtmlx-compat.min.js +3 -3
  109. package/modules/gantt.d.ts +1 -1
  110. package/modules/gantt.esm.min.js +32 -7
  111. package/modules/gantt.min.cjs +32 -7
  112. package/modules/gantt.min.js +32 -7
  113. package/modules/geo-europe-nuts.d.ts +1 -1
  114. package/modules/geo-europe-nuts.esm.min.js +1 -1
  115. package/modules/geo-uk.d.ts +1 -1
  116. package/modules/geo-uk.esm.min.js +1 -1
  117. package/modules/geo-us-states.d.ts +1 -1
  118. package/modules/geo-us-states.esm.min.js +1 -1
  119. package/modules/geo-world-110m.d.ts +1 -1
  120. package/modules/geo-world-110m.esm.min.js +1 -1
  121. package/modules/geo-world-50m.d.ts +1 -1
  122. package/modules/geo-world-50m.esm.min.js +1 -1
  123. package/modules/htmx.d.ts +1 -1
  124. package/modules/htmx.esm.min.js +27 -7
  125. package/modules/htmx.min.cjs +27 -7
  126. package/modules/htmx.min.js +27 -7
  127. package/modules/kanban.d.ts +1 -1
  128. package/modules/kanban.esm.min.js +3 -3
  129. package/modules/kanban.min.cjs +3 -3
  130. package/modules/kanban.min.js +3 -3
  131. package/modules/kpi.d.ts +26 -8
  132. package/modules/kpi.esm.min.js +31 -6
  133. package/modules/kpi.min.cjs +31 -6
  134. package/modules/kpi.min.js +31 -6
  135. package/modules/layout.d.ts +1 -1
  136. package/modules/layout.esm.min.js +3 -3
  137. package/modules/layout.min.cjs +3 -3
  138. package/modules/layout.min.js +3 -3
  139. package/modules/mock-socket.d.ts +1 -1
  140. package/modules/mock-socket.esm.min.js +1 -1
  141. package/modules/mock-socket.min.cjs +1 -1
  142. package/modules/mock-socket.min.js +1 -1
  143. package/modules/react.d.ts +1 -1
  144. package/modules/react.esm.min.js +3 -3
  145. package/modules/react.min.cjs +3 -3
  146. package/modules/react.min.js +3 -3
  147. package/modules/svelte.d.ts +1 -1
  148. package/modules/svelte.esm.min.js +3 -3
  149. package/modules/svelte.min.cjs +3 -3
  150. package/modules/svelte.min.js +3 -3
  151. package/modules/tabs.d.ts +1 -1
  152. package/modules/tabs.esm.min.js +13 -14
  153. package/modules/tabs.min.cjs +13 -14
  154. package/modules/tabs.min.js +13 -14
  155. package/modules/vue.d.ts +1 -1
  156. package/modules/vue.esm.min.js +3 -3
  157. package/modules/vue.min.cjs +3 -3
  158. package/modules/vue.min.js +3 -3
  159. package/modules/webcomponent.d.ts +1 -1
  160. package/modules/webcomponent.esm.min.js +27 -7
  161. package/modules/webcomponent.min.cjs +27 -7
  162. package/modules/webcomponent.min.js +27 -7
  163. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, kanban module type declarations
2
+ * Lattice Grid 1.68.0, kanban module type declarations
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, kanban module
2
+ * Lattice Grid 1.68.0, kanban 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.67.0";
55
+ const STAMPED_VERSION="1.68.0";
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.67.0";
60
+ const VERSION="1.68.0";
61
61
  const warned=new Set();
62
62
  const WARNED_LIMIT=2000;
63
63
  function rememberWarned(key){
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, kanban module
2
+ * Lattice Grid 1.68.0, kanban 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.67.0";
57
+ const STAMPED_VERSION="1.68.0";
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.67.0";
62
+ const VERSION="1.68.0";
63
63
  const warned=new Set();
64
64
  const WARNED_LIMIT=2000;
65
65
  function rememberWarned(key){
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, kanban module
2
+ * Lattice Grid 1.68.0, kanban 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.67.0";
57
+ const STAMPED_VERSION="1.68.0";
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.67.0";
62
+ const VERSION="1.68.0";
63
63
  const warned=new Set();
64
64
  const WARNED_LIMIT=2000;
65
65
  function rememberWarned(key){
package/modules/kpi.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, kpi module type declarations
2
+ * Lattice Grid 1.68.0, kpi module type declarations
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -60,6 +60,15 @@ interface KPIStatTile {
60
60
  target?: number;
61
61
  /** A baseline the tile's delta is measured against. */
62
62
  baseline?: number;
63
+ /**
64
+ * What the movement line prints against `baseline` (F-FRED-G): `'absolute'` the difference alone, `'relative'` the
65
+ * percentage alone, `'both'` (the default, unchanged) both together. A
66
+ * rate series (4.10 vs 4.30) makes the percentage a percent-of-a-percent
67
+ * and meaningless, so `'absolute'` is how a host keeps the line without
68
+ * it. The arrow and its colour follow the sign of the difference either
69
+ * way.
70
+ */
71
+ delta?: 'absolute' | 'relative' | 'both';
63
72
  /** Threshold bands, either two cut points or an explicit band list. */
64
73
  thresholds?: KPIThresholds;
65
74
  /** Explicit status bands (an alternative to `thresholds`). */
@@ -112,12 +121,15 @@ type KPITile = KPIStatTile | KPIClockTile;
112
121
  * of top-level items that expand to the indicators beneath them, each parent
113
122
  * highlighted with the worst status below it.
114
123
  *
115
- * The shape is declared with `path` or `parentKey` — the same two shapes the
116
- * grid's tree data and the tree-select editor take — over the **tile specs**,
117
- * not the rows. With neither declared, one is derived by splitting the tile
118
- * ids on `separator`, so `system.compute.cpu` files itself under Compute
119
- * under System. A panel whose ids carry no separator stays flat, and `false`
120
- * keeps it flat whatever they look like.
124
+ * `tree` is an opt-in: omitted or `false`, the panel is
125
+ * flat whatever its tile ids look like, and a dotted id seen with `tree`
126
+ * unset is reported once rather than silently turned into a hierarchy. Given
127
+ * any object (`{}` included), the shape is declared with `path` or
128
+ * `parentKey` — the same two shapes the grid's tree data and the tree-select
129
+ * editor take — over the **tile specs**, not the rows. With neither declared,
130
+ * one is derived by splitting the tile ids on `separator`, so
131
+ * `system.compute.cpu` files itself under Compute under System. A panel
132
+ * whose ids carry no separator stays flat even with `tree` set.
121
133
  *
122
134
  * A tile's `field` is never a source: a dot there already means a nested
123
135
  * object property.
@@ -209,6 +221,8 @@ interface KPITileModel {
209
221
  delta: number | null;
210
222
  deltaPercent: number | null;
211
223
  deltaFormatted?: string;
224
+ /** What the movement line prints; see `KPIStatTile.delta`. Always present once `baseline` is. */
225
+ deltaMode?: 'absolute' | 'relative' | 'both';
212
226
  count: number;
213
227
  sparkline: number[] | null;
214
228
  }
@@ -249,7 +263,11 @@ interface KPIConfig {
249
263
  * on a stat tile, which takes its own `format.locale`.
250
264
  */
251
265
  locale?: string;
252
- /** Arrange the tiles as a hierarchy; `false` keeps the panel flat. */
266
+ /**
267
+ * Arrange the tiles as a hierarchy; unset or `false` keeps the panel flat.
268
+ * Opt-in: a dotted tile id is not a hierarchy until
269
+ * `tree` is set, and warns once while it is not.
270
+ */
253
271
  tree?: KPITreeConfig | false;
254
272
  /**
255
273
  * The catalogue the panel's own text is read from. A panel routinely has no
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, kpi module
2
+ * Lattice Grid 1.68.0, 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.67.0";
55
+ const STAMPED_VERSION="1.68.0";
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.67.0";
60
+ const VERSION="1.68.0";
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(config===false||!tiles.length)return null;
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
- ?'':` (${(t.deltaPercent*100).toFixed(1)}%)`;
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,`${arrow} ${t.deltaFormatted??t.delta}${pct}`);
1208
+ setText(node,text);
1195
1209
  return node;
1196
1210
  }
1197
1211
  function sparkNode(doc,fig,t){
@@ -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
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, kpi module
2
+ * Lattice Grid 1.68.0, 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.67.0";
57
+ const STAMPED_VERSION="1.68.0";
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.67.0";
62
+ const VERSION="1.68.0";
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(config===false||!tiles.length)return null;
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
- ?'':` (${(t.deltaPercent*100).toFixed(1)}%)`;
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,`${arrow} ${t.deltaFormatted??t.delta}${pct}`);
1210
+ setText(node,text);
1197
1211
  return node;
1198
1212
  }
1199
1213
  function sparkNode(doc,fig,t){
@@ -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
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, kpi module
2
+ * Lattice Grid 1.68.0, 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.67.0";
57
+ const STAMPED_VERSION="1.68.0";
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.67.0";
62
+ const VERSION="1.68.0";
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(config===false||!tiles.length)return null;
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
- ?'':` (${(t.deltaPercent*100).toFixed(1)}%)`;
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,`${arrow} ${t.deltaFormatted??t.delta}${pct}`);
1210
+ setText(node,text);
1197
1211
  return node;
1198
1212
  }
1199
1213
  function sparkNode(doc,fig,t){
@@ -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
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, layout module type declarations
2
+ * Lattice Grid 1.68.0, layout module type declarations
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, layout module
2
+ * Lattice Grid 1.68.0, layout 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.67.0";
55
+ const STAMPED_VERSION="1.68.0";
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.67.0";
60
+ const VERSION="1.68.0";
61
61
  const warned=new Set();
62
62
  const WARNED_LIMIT=2000;
63
63
  function rememberWarned(key){
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, layout module
2
+ * Lattice Grid 1.68.0, layout 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.67.0";
57
+ const STAMPED_VERSION="1.68.0";
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.67.0";
62
+ const VERSION="1.68.0";
63
63
  const warned=new Set();
64
64
  const WARNED_LIMIT=2000;
65
65
  function rememberWarned(key){
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, layout module
2
+ * Lattice Grid 1.68.0, layout 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.67.0";
57
+ const STAMPED_VERSION="1.68.0";
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.67.0";
62
+ const VERSION="1.68.0";
63
63
  const warned=new Set();
64
64
  const WARNED_LIMIT=2000;
65
65
  function rememberWarned(key){
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, mock-socket module type declarations
2
+ * Lattice Grid 1.68.0, mock-socket module type declarations
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, mock-socket module
2
+ * Lattice Grid 1.68.0, mock-socket module
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, mock-socket module
2
+ * Lattice Grid 1.68.0, mock-socket module
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, mock-socket module
2
+ * Lattice Grid 1.68.0, mock-socket module
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, react module type declarations
2
+ * Lattice Grid 1.68.0, react module type declarations
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, react module
2
+ * Lattice Grid 1.68.0, react 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.67.0";
55
+ const STAMPED_VERSION="1.68.0";
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.67.0";
60
+ const VERSION="1.68.0";
61
61
  const warned=new Set();
62
62
  const WARNED_LIMIT=2000;
63
63
  function rememberWarned(key){
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, react module
2
+ * Lattice Grid 1.68.0, react 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.67.0";
57
+ const STAMPED_VERSION="1.68.0";
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.67.0";
62
+ const VERSION="1.68.0";
63
63
  const warned=new Set();
64
64
  const WARNED_LIMIT=2000;
65
65
  function rememberWarned(key){
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, react module
2
+ * Lattice Grid 1.68.0, react 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.67.0";
57
+ const STAMPED_VERSION="1.68.0";
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.67.0";
62
+ const VERSION="1.68.0";
63
63
  const warned=new Set();
64
64
  const WARNED_LIMIT=2000;
65
65
  function rememberWarned(key){
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.67.0, svelte module type declarations
2
+ * Lattice Grid 1.68.0, svelte module type declarations
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */