@toclocoinc/lattice-grid 1.9.1 → 1.11.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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.9.1 — core + DOM renderer
2
+ * Lattice Grid 1.11.0 — core + DOM renderer
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -12817,7 +12817,10 @@ this.invalidate('filter');
12817
12817
  }else{
12818
12818
  this.invalidate('total');
12819
12819
  }
12820
- this.#emit('rows:changed',{added:result.added.length,updated:result.updated.length,removed:result.removed.length});
12820
+ this.#emit('rows:changed',{
12821
+ companion:true,
12822
+ added:result.added.length,updated:result.updated.length,removed:result.removed.length,
12823
+ });
12821
12824
  return result;
12822
12825
  }
12823
12826
  groupHeadingsAt(index){
@@ -12854,7 +12857,9 @@ this.#dropTotalState();
12854
12857
  this.#handles.invalidate();
12855
12858
  this.#view=null;
12856
12859
  this.invalidate('filter');
12857
- this.#emit('rows:changed',{added:0,updated:0,removed:0,moved:1});
12860
+ this.#emit('rows:changed',{
12861
+ companion:true,added:0,updated:0,removed:0,moved:1,
12862
+ });
12858
12863
  return true;
12859
12864
  }
12860
12865
  reload(_opts){
@@ -13050,6 +13055,15 @@ return out;
13050
13055
  facetIndices(colId){
13051
13056
  return this.#runFilter(colId||null);
13052
13057
  }
13058
+ facetRows(colId){
13059
+ const indices=this.facetIndices(colId);
13060
+ const out=[];
13061
+ for(let i=0;i<indices.length;i++){
13062
+ const row=this.#leafRow(indices[i]);
13063
+ if(row)out.push(row);
13064
+ }
13065
+ return out;
13066
+ }
13053
13067
  invalidateRows(){
13054
13068
  this.#rowCache.clear();
13055
13069
  this.#quickText.clear();
@@ -15047,6 +15061,759 @@ if(isFunction(emit))emit(type,payload);
15047
15061
  }
15048
15062
  }
15049
15063
  });
15064
+ __def("packages/core/src/source/derive.js",function(__exports,__req){
15065
+ 'use strict';
15066
+ Object.defineProperty(__exports,"FOLLOW_MODES",{enumerable:true,get:function(){return FOLLOW_MODES;}});
15067
+ Object.defineProperty(__exports,"BUCKETS",{enumerable:true,get:function(){return BUCKETS;}});
15068
+ Object.defineProperty(__exports,"DERIVED_ROW_KEY",{enumerable:true,get:function(){return DERIVED_ROW_KEY;}});
15069
+ Object.defineProperty(__exports,"readPath",{enumerable:true,get:function(){return readPath;}});
15070
+ Object.defineProperty(__exports,"unnest",{enumerable:true,get:function(){return unnest;}});
15071
+ Object.defineProperty(__exports,"bucketOf",{enumerable:true,get:function(){return bucketOf;}});
15072
+ Object.defineProperty(__exports,"reduceValues",{enumerable:true,get:function(){return reduceValues;}});
15073
+ Object.defineProperty(__exports,"applyLimit",{enumerable:true,get:function(){return applyLimit;}});
15074
+ Object.defineProperty(__exports,"applyCumulative",{enumerable:true,get:function(){return applyCumulative;}});
15075
+ Object.defineProperty(__exports,"groupRows",{enumerable:true,get:function(){return groupRows;}});
15076
+ Object.defineProperty(__exports,"finishGroups",{enumerable:true,get:function(){return finishGroups;}});
15077
+ Object.defineProperty(__exports,"derive",{enumerable:true,get:function(){return derive;}});
15078
+ Object.defineProperty(__exports,"joinRows",{enumerable:true,get:function(){return joinRows;}});
15079
+ Object.defineProperty(__exports,"preGroup",{enumerable:true,get:function(){return preGroup;}});
15080
+ Object.defineProperty(__exports,"buildJoinIndex",{enumerable:true,get:function(){return buildJoinIndex;}});
15081
+ Object.defineProperty(__exports,"joinOne",{enumerable:true,get:function(){return joinOne;}});
15082
+ Object.defineProperty(__exports,"joinKeyOf",{enumerable:true,get:function(){return joinKeyOf;}});
15083
+ const __m0=__req("packages/core/src/internal/util.js");
15084
+ const isFunction=__m0["isFunction"];
15085
+ const isObject=__m0["isObject"];
15086
+ const __m1=__req("packages/core/src/compute/total.js");
15087
+ const TOTAL_FNS=__m1["TOTAL_FNS"];
15088
+ const FOLLOW_MODES=Object.freeze(['filtered','all','selected','grouped']);
15089
+ const BUCKETS=Object.freeze(['day','week','month','quarter','year']);
15090
+ const DERIVED_ROW_KEY='__key';
15091
+ function readPath(obj,path){
15092
+ if(!isObject(obj)||typeof path!=='string')return undefined;
15093
+ if(!path.includes('.'))return(obj)[path];
15094
+ let cursor=(obj);
15095
+ for(const part of path.split('.')){
15096
+ if(!isObject(cursor))return undefined;
15097
+ cursor=(cursor)[part];
15098
+ }
15099
+ return cursor;
15100
+ }
15101
+ function unnest(rows,path){
15102
+ const out=[];
15103
+ for(const row of rows){
15104
+ const list=readPath(row,path);
15105
+ if(!Array.isArray(list)||!list.length)continue;
15106
+ for(const item of list)out.push({...((row)),[path]:item});
15107
+ }
15108
+ return out;
15109
+ }
15110
+ function bucketOf(value,by){
15111
+ const at=value instanceof Date?value:new Date((value));
15112
+ const time=at.getTime();
15113
+ if(!Number.isFinite(time))return null;
15114
+ const y=at.getUTCFullYear();
15115
+ const m=at.getUTCMonth();
15116
+ const d=at.getUTCDate();
15117
+ const iso=(date)=>date.toISOString().slice(0,10);
15118
+ switch(by){
15119
+ case'year':return iso(new Date(Date.UTC(y,0,1)));
15120
+ case'quarter':return iso(new Date(Date.UTC(y,Math.floor(m/3)*3,1)));
15121
+ case'month':return iso(new Date(Date.UTC(y,m,1)));
15122
+ case'week':{
15123
+ const day=(at.getUTCDay()+6)%7;
15124
+ return iso(new Date(Date.UTC(y,m,d-day)));
15125
+ }
15126
+ default:return iso(new Date(Date.UTC(y,m,d)));
15127
+ }
15128
+ }
15129
+ function groupKeyOf(row,by,bucket){
15130
+ const values=by.map((path)=>(
15131
+ bucket&&bucket.of===path?bucketOf(readPath(row,path),bucket.by):readPath(row,path)
15132
+ ));
15133
+ return{key:values.map((v)=>(v===undefined||v===null?'\u0000':String(v))).join('\u001f'),values};
15134
+ }
15135
+ function reduceValues(values,fn){
15136
+ const kernel=TOTAL_FNS[fn];
15137
+ if(!kernel)return null;
15138
+ return kernel({get:(i)=>values[i]},ROW_INDICES(values.length));
15139
+ }
15140
+ function reduceGroup(rows,select){
15141
+ const out={};
15142
+ const indices=ROW_INDICES(rows.length);
15143
+ for(const[id,spec]of Object.entries(select)){
15144
+ const fn=spec.fn||'count';
15145
+ const kernel=TOTAL_FNS[fn];
15146
+ if(!kernel){out[id]=null;continue;}
15147
+ const values=spec.of?rows.map((row)=>readPath(row,spec.of)):[];
15148
+ out[id]=kernel({get:(i)=>values[i]},indices);
15149
+ }
15150
+ return out;
15151
+ }
15152
+ const ROW_INDICES=(()=>{
15153
+ const cache=new Map();
15154
+ return(n)=>{
15155
+ let hit=cache.get(n);
15156
+ if(!hit){
15157
+ hit=new Uint32Array(n);
15158
+ for(let i=0;i<n;i++)hit[i]=i;
15159
+ if(cache.size<512)cache.set(n,hit);
15160
+ }
15161
+ return hit;
15162
+ };
15163
+ })();
15164
+ function applyLimit(rows,limit,per){
15165
+ if(!Number.isFinite(limit)||limit<=0)return rows;
15166
+ if(!per)return rows.slice(0,limit);
15167
+ const seen=new Map();
15168
+ const out=[];
15169
+ for(const row of rows){
15170
+ const key=String(readPath(row,per));
15171
+ const taken=seen.get(key)||0;
15172
+ if(taken>=limit)continue;
15173
+ seen.set(key,taken+1);
15174
+ out.push(row);
15175
+ }
15176
+ return out;
15177
+ }
15178
+ function applyCumulative(rows,spec){
15179
+ const total=rows.reduce((sum,row)=>sum+(Number(readPath(row,spec.of))||0),0);
15180
+ if(!total)return rows;
15181
+ const cutoff=total*spec.upTo;
15182
+ let running=0;
15183
+ const out=[];
15184
+ for(const row of rows){
15185
+ out.push(row);
15186
+ running+=Number(readPath(row,spec.of))||0;
15187
+ if(running>=cutoff)break;
15188
+ }
15189
+ return out;
15190
+ }
15191
+ function sortRows(rows,spec){
15192
+ if(!Array.isArray(spec)||!spec.length)return rows;
15193
+ return[...rows].sort((a,b)=>{
15194
+ for(const entry of spec){
15195
+ const av=readPath(a,entry.col);
15196
+ const bv=readPath(b,entry.col);
15197
+ if(av===bv)continue;
15198
+ if(av===null||av===undefined)return 1;
15199
+ if(bv===null||bv===undefined)return-1;
15200
+ const less=typeof av==='number'&&typeof bv==='number'
15201
+ ?av<bv
15202
+ :String(av)<String(bv);
15203
+ return(less?-1:1)*(entry.dir==='desc'?-1:1);
15204
+ }
15205
+ return 0;
15206
+ });
15207
+ }
15208
+ function groupRows(rows,spec,keyOf){
15209
+ const by=spec.groupBy
15210
+ ?(Array.isArray(spec.groupBy)?spec.groupBy:[spec.groupBy])
15211
+ :null;
15212
+ const bucket=isObject(spec.bucket)?spec.bucket:null;
15213
+ const groups=new Map();
15214
+ const rowGroup=new Map();
15215
+ if(!by)return{groups,rowGroup};
15216
+ for(const row of rows){
15217
+ const{key,values}=groupKeyOf(row,by,bucket);
15218
+ let group=groups.get(key);
15219
+ if(!group){group={values,rows:new Map()};groups.set(key,group);}
15220
+ const rowKey=keyOf(row);
15221
+ group.rows.set(rowKey,row);
15222
+ rowGroup.set(rowKey,key);
15223
+ }
15224
+ return{groups,rowGroup};
15225
+ }
15226
+ function finishGroups(groups,spec,cache=null,dirty=null){
15227
+ const by=Array.isArray(spec.groupBy)?spec.groupBy:[spec.groupBy];
15228
+ let out=[...groups.entries()].map(([key,group])=>{
15229
+ if(cache&&dirty&&!dirty.has(key)){
15230
+ const kept=cache.get(key);
15231
+ if(kept)return kept;
15232
+ }
15233
+ const row={[DERIVED_ROW_KEY]:key};
15234
+ by.forEach((path,i)=>{
15235
+ row[path.includes('.')?path.split('.').pop():path]=group.values[i];
15236
+ });
15237
+ Object.assign(row,reduceGroup([...group.rows.values()],spec.select||{}));
15238
+ if(cache)cache.set(key,row);
15239
+ return row;
15240
+ });
15241
+ out=sortRows(out,spec.sort);
15242
+ if(isObject(spec.cumulative))out=applyCumulative(out,spec.cumulative);
15243
+ return applyLimit(out,spec.limit,spec.limitPer||null);
15244
+ }
15245
+ function derive(rows,spec){
15246
+ const working=preGroup(rows,spec);
15247
+ const by=spec.groupBy
15248
+ ?(Array.isArray(spec.groupBy)?spec.groupBy:[spec.groupBy])
15249
+ :null;
15250
+ const bucket=isObject(spec.bucket)?spec.bucket:null;
15251
+ let out;
15252
+ if(!by){
15253
+ out=working.map((row,i)=>({
15254
+ ...((row)),
15255
+ [DERIVED_ROW_KEY]:String(readPath(row,spec.rowKey||'id')??i),
15256
+ }));
15257
+ }else{
15258
+ const groups=new Map();
15259
+ for(const row of working){
15260
+ const{key,values}=groupKeyOf(row,by,bucket);
15261
+ let bucketed=groups.get(key);
15262
+ if(!bucketed){bucketed={values,rows:[]};groups.set(key,bucketed);}
15263
+ bucketed.rows.push(row);
15264
+ }
15265
+ out=[...groups.entries()].map(([key,group])=>{
15266
+ const row={[DERIVED_ROW_KEY]:key};
15267
+ by.forEach((path,i)=>{row[path.includes('.')?path.split('.').pop():path]=group.values[i];});
15268
+ Object.assign(row,reduceGroup(group.rows,spec.select||{}));
15269
+ return row;
15270
+ });
15271
+ }
15272
+ out=sortRows(out,spec.sort);
15273
+ if(isObject(spec.cumulative))out=applyCumulative(out,spec.cumulative);
15274
+ return applyLimit(out,spec.limit,spec.limitPer||null);
15275
+ }
15276
+ function joinRows(rows,spec){
15277
+ const on=spec.on;
15278
+ const leftKey=isObject(on)?String(on.left||on.right||''):String(on||'');
15279
+ const rightKey=isObject(on)?String(on.right||on.left||''):String(on||'');
15280
+ if(!leftKey||!rightKey)return(rows);
15281
+ const index=spec.index instanceof Map
15282
+ ?spec.index
15283
+ :buildJoinIndex(Array.isArray(spec.rows)?spec.rows:[],rightKey);
15284
+ const fields=Array.isArray(spec.select)?spec.select.map(String):null;
15285
+ const prefix=spec.prefix?String(spec.prefix):'';
15286
+ const keep=String(spec.type||'inner')==='left';
15287
+ const out=[];
15288
+ for(const row of rows){
15289
+ const value=readPath(row,leftKey);
15290
+ const match=value==null?undefined:index.get(String(value));
15291
+ if(!match){if(keep)out.push((row));continue;}
15292
+ const merged={...((row))};
15293
+ const names=fields||Object.keys(match);
15294
+ for(const name of names){
15295
+ if(!prefix&&name===leftKey)continue;
15296
+ merged[prefix?prefix+name:name]=readPath(match,name);
15297
+ }
15298
+ out.push(merged);
15299
+ }
15300
+ return out;
15301
+ }
15302
+ function preGroup(rows,spec){
15303
+ let working=Array.isArray(rows)?rows:[];
15304
+ if(spec.unnest)working=unnest(working,spec.unnest);
15305
+ if(isObject(spec.join)&&(Array.isArray(spec.join.rows)||spec.join.index instanceof Map)){
15306
+ working=joinRows(working,spec.join);
15307
+ }
15308
+ if(isFunction(spec.where))working=working.filter((row)=>!!spec.where(row));
15309
+ return working;
15310
+ }
15311
+ function buildJoinIndex(rows,rightKey){
15312
+ const index=new Map();
15313
+ for(const row of rows){
15314
+ const value=readPath(row,rightKey);
15315
+ if(value==null)continue;
15316
+ const key=String(value);
15317
+ if(!index.has(key))index.set(key,(row));
15318
+ }
15319
+ return index;
15320
+ }
15321
+ function joinOne(row,spec){
15322
+ const on=spec.on;
15323
+ const leftKey=isObject(on)?String(on.left||on.right||''):String(on||'');
15324
+ const rightKey=isObject(on)?String(on.right||on.left||''):String(on||'');
15325
+ if(!leftKey||!rightKey)return(row);
15326
+ const index=spec.index instanceof Map?spec.index:new Map();
15327
+ const value=readPath(row,leftKey);
15328
+ const match=value==null?undefined:index.get(String(value));
15329
+ if(!match)return String(spec.type||'inner')==='left'?(row):null;
15330
+ const fields=Array.isArray(spec.select)?spec.select.map(String):null;
15331
+ const prefix=spec.prefix?String(spec.prefix):'';
15332
+ const merged={...((row))};
15333
+ for(const name of fields||Object.keys(match)){
15334
+ if(!prefix&&name===leftKey)continue;
15335
+ merged[prefix?prefix+name:name]=readPath(match,name);
15336
+ }
15337
+ return merged;
15338
+ }
15339
+ function joinKeyOf(row,path){
15340
+ const value=readPath(row,path);
15341
+ return value==null?null:String(value);
15342
+ }
15343
+ });
15344
+ __def("packages/core/src/source/derived.js",function(__exports,__req){
15345
+ 'use strict';
15346
+ Object.defineProperty(__exports,"IDLE_REFRESH_MS",{enumerable:true,get:function(){return IDLE_REFRESH_MS;}});
15347
+ Object.defineProperty(__exports,"PROFILE_FIELDS",{enumerable:true,get:function(){return PROFILE_FIELDS;}});
15348
+ Object.defineProperty(__exports,"DerivedSource",{enumerable:true,get:function(){return DerivedSource;}});
15349
+ Object.defineProperty(__exports,"createDerivedSource",{enumerable:true,get:function(){return createDerivedSource;}});
15350
+ const __m0=__req("packages/core/src/internal/util.js");
15351
+ const isFunction=__m0["isFunction"];
15352
+ const isObject=__m0["isObject"];
15353
+ const warnOnce=__m0["warnOnce"];
15354
+ const __m1=__req("packages/core/src/source/memory.js");
15355
+ const MemorySource=__m1["MemorySource"];
15356
+ const __m2=__req("packages/core/src/source/derive.js");
15357
+ const derive=__m2["derive"];
15358
+ const preGroup=__m2["preGroup"];
15359
+ const groupRows=__m2["groupRows"];
15360
+ const finishGroups=__m2["finishGroups"];
15361
+ const readPath=__m2["readPath"];
15362
+ const buildJoinIndex=__m2["buildJoinIndex"];
15363
+ const joinOne=__m2["joinOne"];
15364
+ const joinKeyOf=__m2["joinKeyOf"];
15365
+ const FOLLOW_MODES=__m2["FOLLOW_MODES"];
15366
+ const DERIVED_ROW_KEY=__m2["DERIVED_ROW_KEY"];
15367
+ const IDLE_REFRESH_MS=16;
15368
+ const PROFILE_FIELDS=Object.freeze([
15369
+ 'column','rows','present','missing','distinct',
15370
+ 'min','max','mean','median','q1','q3','iqr','stddev','outliers',
15371
+ ]);
15372
+ class DerivedSource extends MemorySource{
15373
+ #from=null;
15374
+ #spec={};
15375
+ #off=[];
15376
+ #pending=null;
15377
+ #gone=false;
15378
+ #ctx={};
15379
+ #deriving=false;
15380
+ #index=null;
15381
+ #filterCols=null;
15382
+ #coalesced=false;
15383
+ #cross=[];
15384
+ #rightIndex=null;
15385
+ constructor(config,ctx){
15386
+ super({mode:'memory',rows:[]},ctx);
15387
+ this.#ctx=ctx||{};
15388
+ this.#spec=isObject(config)?config:{};
15389
+ this.#from=(this.#spec.from)||null;
15390
+ if(!this.#from){
15391
+ warnOnce('source.derived.from','source.mode "derived" needs `from`: the grid to derive from.');
15392
+ return;
15393
+ }
15394
+ if(this.#spec.follow&&!FOLLOW_MODES.includes(String(this.#spec.follow))){
15395
+ warnOnce(
15396
+ `source.derived.follow.${this.#spec.follow}`,
15397
+ `unknown follow "${this.#spec.follow}"; using "filtered". Known: ${FOLLOW_MODES.join(', ')}.`,
15398
+ );
15399
+ }
15400
+ this.#watch();
15401
+ this.refresh();
15402
+ }
15403
+ #watch(){
15404
+ const grid=this.#from;
15405
+ if(!grid||!isFunction(grid.on))return;
15406
+ const follow=String(this.#spec.follow||'filtered');
15407
+ const events=['rows:changed'];
15408
+ if(follow==='filtered'||follow==='grouped')events.push('filter:changed');
15409
+ if(follow==='selected')events.push('selection:changed');
15410
+ if(follow==='grouped')events.push('column:grouped');
15411
+ for(const name of events){
15412
+ const handler=(payload)=>{
15413
+ if(name==='rows:changed'&&skipCompanion(payload))return;
15414
+ this.schedule(name==='rows:changed'?payload:null);
15415
+ };
15416
+ grid.on(name,handler);
15417
+ this.#off.push(()=>isFunction(grid.off)&&grid.off(name,handler));
15418
+ }
15419
+ this.#watchJoin();
15420
+ }
15421
+ #watchJoin(){
15422
+ const join=this.#spec.join;
15423
+ const partner=join&&join.with;
15424
+ if(!partner||!isFunction(partner.on))return;
15425
+ const follow=String(join.follow||'all');
15426
+ const events=follow==='all'?['rows:changed']:['rows:changed','filter:changed'];
15427
+ for(const name of events){
15428
+ const handler=(payload)=>{
15429
+ if(name==='rows:changed'&&skipCompanion(payload))return;
15430
+ this.schedule({partner:true});
15431
+ };
15432
+ partner.on(name,handler);
15433
+ this.#off.push(()=>isFunction(partner.off)&&partner.off(name,handler));
15434
+ }
15435
+ }
15436
+ #joinPaths(){
15437
+ const join=this.#spec.join;
15438
+ if(!join||!join.with)return null;
15439
+ const on=join.on;
15440
+ const left=isObject(on)?String(on.left||on.right||''):String(on||'');
15441
+ const right=isObject(on)?String(on.right||on.left||''):String(on||'');
15442
+ return left&&right?{left,right}:null;
15443
+ }
15444
+ #refreshRight(){
15445
+ const paths=this.#joinPaths();
15446
+ if(!paths){this.#rightIndex=null;return null;}
15447
+ const previous=this.#rightIndex;
15448
+ this.#rightIndex=buildJoinIndex(this.#joinRows(),paths.right);
15449
+ if(!previous)return null;
15450
+ const join=this.#spec.join||{};
15451
+ const fields=Array.isArray(join.select)?join.select.map(String):null;
15452
+ const signature=(row)=>{
15453
+ if(!row)return null;
15454
+ const names=fields||Object.keys(row);
15455
+ return names.map((name)=>String(readPath(row,name))).join('\u0001');
15456
+ };
15457
+ const affected=new Set();
15458
+ const gained=new Set();
15459
+ for(const[key,row]of this.#rightIndex){
15460
+ if(signature(row)===signature(previous.get(key)))continue;
15461
+ affected.add(key);
15462
+ if(!previous.has(key))gained.add(key);
15463
+ }
15464
+ for(const key of previous.keys())if(!this.#rightIndex.has(key))affected.add(key);
15465
+ return{affected,gained};
15466
+ }
15467
+ #patchPartner(keys,spec){
15468
+ const index=this.#index;
15469
+ if(!index||!index.leftByJoinKey)return null;
15470
+ const touched=[];
15471
+ for(const key of keys){
15472
+ const rows=index.leftByJoinKey.get(key);
15473
+ if(!rows)continue;
15474
+ for(const rowKey of rows){
15475
+ const data=index.rowData.get(rowKey);
15476
+ if(data!==undefined)touched.push({key:rowKey,data});
15477
+ }
15478
+ }
15479
+ return this.#applyPatch({updated:touched,added:[],removed:[]},spec);
15480
+ }
15481
+ #partnerPatchable(spec,gained){
15482
+ if(!this.#index||!this.#index.leftByJoinKey)return false;
15483
+ if(spec.unnest||spec.where||String(spec.follow||'filtered')==='grouped')return false;
15484
+ const join=spec.join||{};
15485
+ if(String(join.type||'inner')==='left')return true;
15486
+ return gained.size===0;
15487
+ }
15488
+ #joinRows(){
15489
+ const join=this.#spec.join;
15490
+ const partner=join&&join.with;
15491
+ if(!partner||!partner.rows)return[];
15492
+ const out=[];
15493
+ const take=(row)=>{if(!row.group)out.push(unwrap(row));};
15494
+ if(String(join.follow||'all')==='filtered'&&isFunction(partner.rows.forEach)){
15495
+ partner.rows.forEach(take);
15496
+ }else if(isFunction(partner.rows.forEachAll)){
15497
+ partner.rows.forEachAll(take);
15498
+ }
15499
+ return out;
15500
+ }
15501
+ schedule(change){
15502
+ const mode=this.#spec.refresh===undefined?'idle':this.#spec.refresh;
15503
+ if(mode==='manual')return;
15504
+ if(mode==='live'){this.refresh(change);return;}
15505
+ const wait=typeof mode==='number'&&Number.isFinite(mode)?mode:IDLE_REFRESH_MS;
15506
+ if(this.#pending){this.#coalesced=true;return;}
15507
+ this.#coalesced=false;
15508
+ this.#pending=setTimeout(()=>{
15509
+ this.#pending=null;
15510
+ this.refresh(this.#coalesced?null:change);
15511
+ },wait);
15512
+ }
15513
+ refresh(change){
15514
+ if(this.#gone||!this.#from)return;
15515
+ if(this.#deriving){
15516
+ warnOnce(
15517
+ 'source.derived.cycle',
15518
+ 'a derived grid is deriving from itself, directly or through a chain. '
15519
+ +'The cycle was refused; check the `from` of each grid in the chain.',
15520
+ );
15521
+ return;
15522
+ }
15523
+ this.#deriving=true;
15524
+ try{
15525
+ const rows=this.#spec.profile
15526
+ ?this.#deriveProfile()
15527
+ :this.#deriveRows(change);
15528
+ this.setRows(rows);
15529
+ this.invalidate('filter');
15530
+ if(isFunction(this.#ctx.emit)){
15531
+ (this.#ctx.emit)('rows:changed',{},'derived');
15532
+ }
15533
+ }finally{
15534
+ this.#deriving=false;
15535
+ }
15536
+ }
15537
+ #deriveRows(change){
15538
+ const partnerMoved=isObject(change)&&change.partner===true;
15539
+ const delta=partnerMoved?this.#refreshRight():null;
15540
+ const spec=this.#resolvedSpec();
15541
+ if(delta&&this.#index){
15542
+ if(!delta.affected.size){
15543
+ return finishGroups(this.#index.groups,spec,this.#index.reduced,new Set());
15544
+ }
15545
+ if(this.#partnerPatchable(spec,delta.gained)){
15546
+ const dirty=this.#patchPartner(delta.affected,spec);
15547
+ if(dirty)return finishGroups(this.#index.groups,spec,this.#index.reduced,dirty);
15548
+ }
15549
+ }
15550
+ const patch=this.#patchable(spec,change);
15551
+ if(patch&&this.#index){
15552
+ const dirty=this.#applyPatch(patch,spec);
15553
+ return finishGroups(this.#index.groups,spec,this.#index.reduced,dirty);
15554
+ }
15555
+ const rows=preGroup(this.#sourceRows(),spec);
15556
+ this.#filterCols=this.#sourceFilterColumns();
15557
+ if(!spec.groupBy){this.#index=null;return derive(rows,spec);}
15558
+ const keyOf=this.#keyOf();
15559
+ const{groups,rowGroup}=groupRows(rows,spec,keyOf);
15560
+ const rowData=new Map();
15561
+ for(const[key,groupKey]of rowGroup){
15562
+ const group=groups.get(groupKey);
15563
+ if(group)rowData.set(key,group.rows.get(key));
15564
+ }
15565
+ const reduced=new Map();
15566
+ const paths=this.#joinPaths();
15567
+ const leftJoinKey=new Map();
15568
+ const leftByJoinKey=new Map();
15569
+ if(paths){
15570
+ for(const[key,data]of rowData){
15571
+ const jk=joinKeyOf(data,paths.left);
15572
+ if(jk===null)continue;
15573
+ leftJoinKey.set(key,jk);
15574
+ let bucket=leftByJoinKey.get(jk);
15575
+ if(!bucket){bucket=new Set();leftByJoinKey.set(jk,bucket);}
15576
+ bucket.add(key);
15577
+ }
15578
+ }
15579
+ this.#index={groups,rowGroup,rowData,reduced,leftJoinKey,leftByJoinKey};
15580
+ return finishGroups(groups,spec,reduced,null);
15581
+ }
15582
+ #patchable(spec,change){
15583
+ if(!this.#index||!spec.groupBy)return null;
15584
+ if(spec.unnest||spec.where||String(spec.follow||'filtered')==='grouped')return null;
15585
+ if(isObject(spec.join)&&spec.join.with&&!(spec.join.index instanceof Map))return null;
15586
+ if(!isObject(change))return null;
15587
+ const updated=Array.isArray(change.updated)?change.updated:null;
15588
+ const added=Array.isArray(change.added)?change.added:null;
15589
+ const removed=Array.isArray(change.removed)?change.removed:null;
15590
+ if(!updated&&!added&&!removed)return null;
15591
+ const cols=this.#filterCols;
15592
+ if(cols&&cols.size&&String(spec.follow||'filtered')!=='all'){
15593
+ for(const row of updated||[]){
15594
+ const key=row&&row.key;
15595
+ const before=key===undefined?undefined:this.#index.rowData.get(String(key));
15596
+ const after=unwrap(row);
15597
+ for(const col of cols){
15598
+ if(readPath(before,col)!==readPath(after,col))return null;
15599
+ }
15600
+ }
15601
+ }
15602
+ return{updated:updated||[],added:added||[],removed:removed||[]};
15603
+ }
15604
+ #applyPatch(patch,spec){
15605
+ const index=
15606
+ (this.#index);
15607
+ const keyOf=this.#keyOf();
15608
+ const dirty=new Set();
15609
+ const join=isObject(spec.join)&&spec.join.index instanceof Map?spec.join:null;
15610
+ const paths=this.#joinPaths();
15611
+ const drop=(key)=>{
15612
+ const was=index.rowGroup.get(key);
15613
+ if(was===undefined)return;
15614
+ dirty.add(was);
15615
+ const group=index.groups.get(was);
15616
+ if(group){
15617
+ group.rows.delete(key);
15618
+ if(!group.rows.size)index.groups.delete(was);
15619
+ }
15620
+ index.rowGroup.delete(key);
15621
+ index.rowData.delete(key);
15622
+ if(index.leftJoinKey){
15623
+ const jk=index.leftJoinKey.get(key);
15624
+ if(jk!==undefined){
15625
+ const bucket=index.leftByJoinKey.get(jk);
15626
+ if(bucket){bucket.delete(key);if(!bucket.size)index.leftByJoinKey.delete(jk);}
15627
+ index.leftJoinKey.delete(key);
15628
+ }
15629
+ }
15630
+ };
15631
+ const place=(raw)=>{
15632
+ const row=join?joinOne(raw,join):raw;
15633
+ if(!row)return;
15634
+ const key=keyOf(row);
15635
+ const single=groupRows([row],spec,keyOf);
15636
+ for(const[groupKey,built]of single.groups){
15637
+ let group=index.groups.get(groupKey);
15638
+ if(!group){group={values:built.values,rows:new Map()};index.groups.set(groupKey,group);}
15639
+ group.rows.set(key,row);
15640
+ index.rowGroup.set(key,groupKey);
15641
+ dirty.add(groupKey);
15642
+ }
15643
+ index.rowData.set(key,row);
15644
+ if(paths&&index.leftByJoinKey){
15645
+ const jk=joinKeyOf(row,paths.left);
15646
+ if(jk!==null){
15647
+ index.leftJoinKey.set(key,jk);
15648
+ let bucket=index.leftByJoinKey.get(jk);
15649
+ if(!bucket){bucket=new Set();index.leftByJoinKey.set(jk,bucket);}
15650
+ bucket.add(key);
15651
+ }
15652
+ }
15653
+ };
15654
+ for(const key of patch.removed)drop(String(key));
15655
+ for(const row of patch.updated){drop(String(row.key));place(unwrap(row));}
15656
+ for(const row of patch.added)place(unwrap(row));
15657
+ return dirty;
15658
+ }
15659
+ #keyOf(){
15660
+ const grid=this.#from;
15661
+ const field=(grid&&grid.config&&grid.config.rowKey)||'id';
15662
+ return(row)=>String(readPath(row,typeof field==='string'?field:'id')??'');
15663
+ }
15664
+ #sourceFilterColumns(){
15665
+ const grid=this.#from;
15666
+ const state=grid&&grid.state&&isFunction(grid.state.get)?grid.state.get():null;
15667
+ const ids=new Set();
15668
+ const walk=(node)=>{
15669
+ if(!node)return;
15670
+ if(Array.isArray(node.conditions)){node.conditions.forEach(walk);return;}
15671
+ if(node.col)ids.add(String(node.col));
15672
+ };
15673
+ if(state)walk(state.filters);
15674
+ return ids;
15675
+ }
15676
+ #resolvedSpec(){
15677
+ let spec=this.#spec;
15678
+ if(spec.join&&spec.join.with){
15679
+ if(!this.#rightIndex)this.#refreshRight();
15680
+ spec={...spec,join:{...spec.join,index:this.#rightIndex}};
15681
+ }
15682
+ if(String(spec.follow||'filtered')!=='grouped')return spec;
15683
+ const grid=this.#from;
15684
+ const state=grid&&grid.state&&isFunction(grid.state.get)?grid.state.get():null;
15685
+ const grouped=state&&Array.isArray(state.group)?state.group:[];
15686
+ if(!grouped.length)return spec;
15687
+ return{...spec,groupBy:[...grouped]};
15688
+ }
15689
+ #sourceRows(){
15690
+ const grid=this.#from;
15691
+ const follow=String(this.#spec.follow||'filtered');
15692
+ if(!grid||!grid.rows)return[];
15693
+ if(follow==='all'){
15694
+ const every=[];
15695
+ if(isFunction(grid.rows.forEachAll)){
15696
+ grid.rows.forEachAll((row)=>{if(!row.group)every.push(unwrap(row));});
15697
+ }
15698
+ return every;
15699
+ }
15700
+ if(follow==='selected'){
15701
+ const rows=grid.selection&&isFunction(grid.selection.rows)?grid.selection.rows():[];
15702
+ return rows.filter(Boolean).map(unwrap);
15703
+ }
15704
+ const cross=this.#crossColumn();
15705
+ const out=[];
15706
+ if(cross&&this.#cross.length&&isFunction(grid.rows.forEachExcept)){
15707
+ grid.rows.forEachExcept(cross,(row)=>{if(!row.group)out.push(unwrap(row));});
15708
+ return out;
15709
+ }
15710
+ if(isFunction(grid.rows.forEach)){
15711
+ grid.rows.forEach((row)=>{if(!row.group)out.push(unwrap(row));});
15712
+ }
15713
+ return out;
15714
+ }
15715
+ #crossColumn(){
15716
+ const cfg=this.#spec.crossFilter;
15717
+ if(!cfg)return null;
15718
+ if(typeof cfg==='string')return cfg;
15719
+ if(cfg.col)return String(cfg.col);
15720
+ const by=this.#spec.groupBy;
15721
+ const first=Array.isArray(by)?by[0]:by;
15722
+ return first?String(first):null;
15723
+ }
15724
+ #pushCross(){
15725
+ const col=this.#crossColumn();
15726
+ const grid=this.#from;
15727
+ if(!col||!grid||!grid.filters||!isFunction(grid.filters.set))return;
15728
+ const compute=this.#ctx.compute||{};
15729
+ const current=isFunction(grid.filters.get)?grid.filters.get():null;
15730
+ const others=isFunction(compute.pruneColumn)?compute.pruneColumn(current,col):null;
15731
+ const keys=this.#cross;
15732
+ if(!keys.length){grid.filters.set(others||null);return;}
15733
+ const mine=keys.length===1
15734
+ ?{col,op:'eq',value:keys[0]}
15735
+ :{col,op:'in',value:keys.slice()};
15736
+ const rest=others?(others.conditions&&others.op?others.conditions:[others]):[];
15737
+ grid.filters.set(rest.length?{op:'and',conditions:[...rest,mine]}:mine);
15738
+ }
15739
+ crossFilter(){
15740
+ const self=this;
15741
+ return{
15742
+ enabled(){return!!self.#crossColumn();},
15743
+ column(){return self.#crossColumn();},
15744
+ get(){return self.#cross.slice();},
15745
+ set(keys){
15746
+ const next=keys==null?[]:(Array.isArray(keys)?keys:[keys]);
15747
+ self.#cross=next.map((k)=>String(k));
15748
+ self.#pushCross();
15749
+ },
15750
+ toggle(key){
15751
+ const k=String(key);
15752
+ const at=self.#cross.indexOf(k);
15753
+ if(at>=0)self.#cross.splice(at,1);else self.#cross.push(k);
15754
+ self.#pushCross();
15755
+ },
15756
+ clear(){self.#cross=[];self.#pushCross();},
15757
+ };
15758
+ }
15759
+ #deriveProfile(){
15760
+ const grid=this.#from;
15761
+ if(!grid||!grid.statistics||!isFunction(grid.statistics.profile))return[];
15762
+ const wanted=Array.isArray(this.#spec.profile)?this.#spec.profile:[this.#spec.profile];
15763
+ const rows=wanted.filter(Boolean).map((colId)=>{
15764
+ const stats=grid.statistics.profile(String(colId))||{};
15765
+ const row={[DERIVED_ROW_KEY]:String(colId)};
15766
+ for(const field of PROFILE_FIELDS){
15767
+ row[field]=field==='column'?String(colId):(stats[field]??null);
15768
+ }
15769
+ row.outliers=Array.isArray(stats.outliers)?stats.outliers.length:(stats.outliers??null);
15770
+ return row;
15771
+ });
15772
+ if(this.#spec.orient!=='metrics')return rows;
15773
+ const first=rows[0];
15774
+ if(!first)return[];
15775
+ return PROFILE_FIELDS.filter((f)=>f!=='column').map((field)=>({
15776
+ [DERIVED_ROW_KEY]:field,metric:field,value:first[field],
15777
+ }));
15778
+ }
15779
+ apply(change){
15780
+ const ops=['add','update','remove'];
15781
+ const rejected=[];
15782
+ for(const op of ops){
15783
+ for(const row of(change&&change[op])||[]){
15784
+ rejected.push({operation:op,id:row&&row.id,reason:'derived-read-only'});
15785
+ }
15786
+ }
15787
+ if(rejected.length){
15788
+ warnOnce(
15789
+ 'source.derived.readonly',
15790
+ 'a derived grid is read-only: its rows are computed from another grid. '
15791
+ +'Write to the source grid instead, and the derived one follows.',
15792
+ );
15793
+ }
15794
+ return{added:[],updated:[],removed:[],rejected};
15795
+ }
15796
+ destroy(){
15797
+ this.#gone=true;
15798
+ if(this.#pending){clearTimeout(this.#pending);this.#pending=null;}
15799
+ for(const off of this.#off){try{off();}catch{}}
15800
+ this.#off=[];
15801
+ this.#from=null;
15802
+ super.destroy();
15803
+ }
15804
+ }
15805
+ function skipCompanion(payload){
15806
+ return isObject(payload)&&payload.companion===true;
15807
+ }
15808
+ function unwrap(row){
15809
+ return isObject(row)&&'data'in(row)
15810
+ ?(row).data
15811
+ :row;
15812
+ }
15813
+ function createDerivedSource(config,ctx){
15814
+ return new DerivedSource(config,ctx);
15815
+ }
15816
+ });
15050
15817
  __def("packages/core/src/source/index.js",function(__exports,__req){
15051
15818
  'use strict';
15052
15819
  Object.defineProperty(__exports,"createMemorySource",{enumerable:true,get:function(){return createMemorySource;}});
@@ -15060,6 +15827,10 @@ Object.defineProperty(__exports,"PROTOCOL",{enumerable:true,get:function(){retur
15060
15827
  Object.defineProperty(__exports,"createStreamSource",{enumerable:true,get:function(){return createStreamSource;}});
15061
15828
  Object.defineProperty(__exports,"StreamSource",{enumerable:true,get:function(){return StreamSource;}});
15062
15829
  Object.defineProperty(__exports,"DEFAULT_PROMOTE_BELOW",{enumerable:true,get:function(){return DEFAULT_PROMOTE_BELOW;}});
15830
+ Object.defineProperty(__exports,"createDerivedSource",{enumerable:true,get:function(){return createDerivedSource;}});
15831
+ Object.defineProperty(__exports,"DerivedSource",{enumerable:true,get:function(){return DerivedSource;}});
15832
+ Object.defineProperty(__exports,"IDLE_REFRESH_MS",{enumerable:true,get:function(){return IDLE_REFRESH_MS;}});
15833
+ Object.defineProperty(__exports,"PROFILE_FIELDS",{enumerable:true,get:function(){return PROFILE_FIELDS;}});
15063
15834
  Object.defineProperty(__exports,"MODES",{enumerable:true,get:function(){return MODES;}});
15064
15835
  Object.defineProperty(__exports,"createSource",{enumerable:true,get:function(){return createSource;}});
15065
15836
  const __m0=__req("packages/core/src/internal/util.js");
@@ -15081,41 +15852,57 @@ const __m4=__req("packages/core/src/source/stream.js");
15081
15852
  const createStreamSource=__m4["createStreamSource"];
15082
15853
  const StreamSource=__m4["StreamSource"];
15083
15854
  const DEFAULT_PROMOTE_BELOW=__m4["DEFAULT_PROMOTE_BELOW"];
15084
- const __m5=__req("packages/core/src/source/abort.js");
15085
- Object.defineProperty(__exports,"AbortScope",{enumerable:true,get:function(){return __m5["AbortScope"];}});
15086
- Object.defineProperty(__exports,"RequestToken",{enumerable:true,get:function(){return __m5["RequestToken"];}});
15087
- Object.defineProperty(__exports,"SupersededError",{enumerable:true,get:function(){return __m5["SupersededError"];}});
15088
- Object.defineProperty(__exports,"createAbortScope",{enumerable:true,get:function(){return __m5["createAbortScope"];}});
15089
- Object.defineProperty(__exports,"isAbortError",{enumerable:true,get:function(){return __m5["isAbortError"];}});
15090
- const __m6=__req("packages/core/src/source/filterwire.js");
15091
- Object.defineProperty(__exports,"RELATIVE_TOKENS",{enumerable:true,get:function(){return __m6["RELATIVE_TOKENS"];}});
15092
- Object.defineProperty(__exports,"parseRelativeToken",{enumerable:true,get:function(){return __m6["parseRelativeToken"];}});
15093
- Object.defineProperty(__exports,"resolveRelativeRange",{enumerable:true,get:function(){return __m6["resolveRelativeRange"];}});
15094
- Object.defineProperty(__exports,"resolveRelativeCondition",{enumerable:true,get:function(){return __m6["resolveRelativeCondition"];}});
15095
- Object.defineProperty(__exports,"relativeTokenOf",{enumerable:true,get:function(){return __m6["relativeTokenOf"];}});
15096
- Object.defineProperty(__exports,"buildFilterSet",{enumerable:true,get:function(){return __m6["buildFilterSet"];}});
15097
- Object.defineProperty(__exports,"normaliseFilterSet",{enumerable:true,get:function(){return __m6["normaliseFilterSet"];}});
15098
- Object.defineProperty(__exports,"wireFilters",{enumerable:true,get:function(){return __m6["wireFilters"];}});
15099
- Object.defineProperty(__exports,"querySignature",{enumerable:true,get:function(){return __m6["querySignature"];}});
15100
- Object.defineProperty(__exports,"mapConditions",{enumerable:true,get:function(){return __m6["mapConditions"];}});
15101
- Object.defineProperty(__exports,"forEachCondition",{enumerable:true,get:function(){return __m6["forEachCondition"];}});
15102
- Object.defineProperty(__exports,"isGroup",{enumerable:true,get:function(){return __m6["isGroup"];}});
15103
- const __m7=__req("packages/core/src/source/blockcache.js");
15104
- Object.defineProperty(__exports,"BlockCache",{enumerable:true,get:function(){return __m7["BlockCache"];}});
15105
- Object.defineProperty(__exports,"DEFAULT_PAGE_SIZE",{enumerable:true,get:function(){return __m7["DEFAULT_PAGE_SIZE"];}});
15106
- Object.defineProperty(__exports,"DEFAULT_MAX_CACHED_PAGES",{enumerable:true,get:function(){return __m7["DEFAULT_MAX_CACHED_PAGES"];}});
15107
- const __m8=__req("packages/core/src/source/gapbuffer.js");
15108
- Object.defineProperty(__exports,"GapBuffer",{enumerable:true,get:function(){return __m8["GapBuffer"];}});
15109
- const __m9=__req("packages/core/src/source/rows.js");
15110
- Object.defineProperty(__exports,"RowFactory",{enumerable:true,get:function(){return __m9["RowFactory"];}});
15111
- Object.defineProperty(__exports,"createRowFactory",{enumerable:true,get:function(){return __m9["createRowFactory"];}});
15112
- Object.defineProperty(__exports,"groupKey",{enumerable:true,get:function(){return __m9["groupKey"];}});
15113
- Object.defineProperty(__exports,"lazyRowView",{enumerable:true,get:function(){return __m9["lazyRowView"];}});
15114
- Object.defineProperty(__exports,"DEFAULT_ROW_HEIGHT",{enumerable:true,get:function(){return __m9["DEFAULT_ROW_HEIGHT"];}});
15115
- const __m10=__req("packages/core/src/source/handles.js");
15116
- Object.defineProperty(__exports,"HandleProvider",{enumerable:true,get:function(){return __m10["HandleProvider"];}});
15117
- Object.defineProperty(__exports,"createHandleProvider",{enumerable:true,get:function(){return __m10["createHandleProvider"];}});
15118
- const MODES=Object.freeze(['memory','paged','remote','stream']);
15855
+ const __m5=__req("packages/core/src/source/derived.js");
15856
+ const createDerivedSource=__m5["createDerivedSource"];
15857
+ const DerivedSource=__m5["DerivedSource"];
15858
+ const IDLE_REFRESH_MS=__m5["IDLE_REFRESH_MS"];
15859
+ const PROFILE_FIELDS=__m5["PROFILE_FIELDS"];
15860
+ const __m6=__req("packages/core/src/source/derive.js");
15861
+ Object.defineProperty(__exports,"derive",{enumerable:true,get:function(){return __m6["derive"];}});
15862
+ Object.defineProperty(__exports,"unnest",{enumerable:true,get:function(){return __m6["unnest"];}});
15863
+ Object.defineProperty(__exports,"readPath",{enumerable:true,get:function(){return __m6["readPath"];}});
15864
+ Object.defineProperty(__exports,"bucketOf",{enumerable:true,get:function(){return __m6["bucketOf"];}});
15865
+ Object.defineProperty(__exports,"applyLimit",{enumerable:true,get:function(){return __m6["applyLimit"];}});
15866
+ Object.defineProperty(__exports,"applyCumulative",{enumerable:true,get:function(){return __m6["applyCumulative"];}});
15867
+ Object.defineProperty(__exports,"reduceValues",{enumerable:true,get:function(){return __m6["reduceValues"];}});
15868
+ Object.defineProperty(__exports,"FOLLOW_MODES",{enumerable:true,get:function(){return __m6["FOLLOW_MODES"];}});
15869
+ Object.defineProperty(__exports,"BUCKETS",{enumerable:true,get:function(){return __m6["BUCKETS"];}});
15870
+ Object.defineProperty(__exports,"DERIVED_ROW_KEY",{enumerable:true,get:function(){return __m6["DERIVED_ROW_KEY"];}});
15871
+ const __m7=__req("packages/core/src/source/abort.js");
15872
+ Object.defineProperty(__exports,"AbortScope",{enumerable:true,get:function(){return __m7["AbortScope"];}});
15873
+ Object.defineProperty(__exports,"RequestToken",{enumerable:true,get:function(){return __m7["RequestToken"];}});
15874
+ Object.defineProperty(__exports,"SupersededError",{enumerable:true,get:function(){return __m7["SupersededError"];}});
15875
+ Object.defineProperty(__exports,"createAbortScope",{enumerable:true,get:function(){return __m7["createAbortScope"];}});
15876
+ Object.defineProperty(__exports,"isAbortError",{enumerable:true,get:function(){return __m7["isAbortError"];}});
15877
+ const __m8=__req("packages/core/src/source/filterwire.js");
15878
+ Object.defineProperty(__exports,"RELATIVE_TOKENS",{enumerable:true,get:function(){return __m8["RELATIVE_TOKENS"];}});
15879
+ Object.defineProperty(__exports,"parseRelativeToken",{enumerable:true,get:function(){return __m8["parseRelativeToken"];}});
15880
+ Object.defineProperty(__exports,"resolveRelativeRange",{enumerable:true,get:function(){return __m8["resolveRelativeRange"];}});
15881
+ Object.defineProperty(__exports,"resolveRelativeCondition",{enumerable:true,get:function(){return __m8["resolveRelativeCondition"];}});
15882
+ Object.defineProperty(__exports,"relativeTokenOf",{enumerable:true,get:function(){return __m8["relativeTokenOf"];}});
15883
+ Object.defineProperty(__exports,"buildFilterSet",{enumerable:true,get:function(){return __m8["buildFilterSet"];}});
15884
+ Object.defineProperty(__exports,"normaliseFilterSet",{enumerable:true,get:function(){return __m8["normaliseFilterSet"];}});
15885
+ Object.defineProperty(__exports,"wireFilters",{enumerable:true,get:function(){return __m8["wireFilters"];}});
15886
+ Object.defineProperty(__exports,"querySignature",{enumerable:true,get:function(){return __m8["querySignature"];}});
15887
+ Object.defineProperty(__exports,"mapConditions",{enumerable:true,get:function(){return __m8["mapConditions"];}});
15888
+ Object.defineProperty(__exports,"forEachCondition",{enumerable:true,get:function(){return __m8["forEachCondition"];}});
15889
+ Object.defineProperty(__exports,"isGroup",{enumerable:true,get:function(){return __m8["isGroup"];}});
15890
+ const __m9=__req("packages/core/src/source/blockcache.js");
15891
+ Object.defineProperty(__exports,"BlockCache",{enumerable:true,get:function(){return __m9["BlockCache"];}});
15892
+ Object.defineProperty(__exports,"DEFAULT_PAGE_SIZE",{enumerable:true,get:function(){return __m9["DEFAULT_PAGE_SIZE"];}});
15893
+ Object.defineProperty(__exports,"DEFAULT_MAX_CACHED_PAGES",{enumerable:true,get:function(){return __m9["DEFAULT_MAX_CACHED_PAGES"];}});
15894
+ const __m10=__req("packages/core/src/source/gapbuffer.js");
15895
+ Object.defineProperty(__exports,"GapBuffer",{enumerable:true,get:function(){return __m10["GapBuffer"];}});
15896
+ const __m11=__req("packages/core/src/source/rows.js");
15897
+ Object.defineProperty(__exports,"RowFactory",{enumerable:true,get:function(){return __m11["RowFactory"];}});
15898
+ Object.defineProperty(__exports,"createRowFactory",{enumerable:true,get:function(){return __m11["createRowFactory"];}});
15899
+ Object.defineProperty(__exports,"groupKey",{enumerable:true,get:function(){return __m11["groupKey"];}});
15900
+ Object.defineProperty(__exports,"lazyRowView",{enumerable:true,get:function(){return __m11["lazyRowView"];}});
15901
+ Object.defineProperty(__exports,"DEFAULT_ROW_HEIGHT",{enumerable:true,get:function(){return __m11["DEFAULT_ROW_HEIGHT"];}});
15902
+ const __m12=__req("packages/core/src/source/handles.js");
15903
+ Object.defineProperty(__exports,"HandleProvider",{enumerable:true,get:function(){return __m12["HandleProvider"];}});
15904
+ Object.defineProperty(__exports,"createHandleProvider",{enumerable:true,get:function(){return __m12["createHandleProvider"];}});
15905
+ const MODES=Object.freeze(['memory','paged','remote','stream','derived']);
15119
15906
  function createSource(config,ctx){
15120
15907
  if(!ctx)fail('createSource requires a SourceContext');
15121
15908
  const resolved=isObject(config)?config:{mode:'memory'};
@@ -15125,6 +15912,7 @@ case'memory':return createMemorySource((resolved),ctx);
15125
15912
  case'paged':return createPagedSource((resolved),ctx);
15126
15913
  case'remote':return createRemoteSource((resolved),ctx);
15127
15914
  case'stream':return createStreamSource((resolved),ctx);
15915
+ case'derived':return createDerivedSource((resolved),ctx);
15128
15916
  default:
15129
15917
  warnOnce(
15130
15918
  `source.mode.${mode}`,
@@ -22563,6 +23351,7 @@ result.rejected=rejected;
22563
23351
  if(this.#run)this.#run(plan,change);
22564
23352
  if(!opts.silent){
22565
23353
  this.#emit('rows:changed',{
23354
+ identified:true,
22566
23355
  added:result.added,updated:result.updated,removed:result.removed,
22567
23356
  rejected:result.rejected,plan,
22568
23357
  },opts.origin||'api');
@@ -25215,6 +26004,7 @@ const __m19=__req("packages/core/src/compute/index.js");
25215
26004
  const compute=__m19;
25216
26005
  const __m20=__req("packages/core/src/source/index.js");
25217
26006
  const createSource=__m20["createSource"];
26007
+ const DERIVED_ROW_KEY=__m20["DERIVED_ROW_KEY"];
25218
26008
  const __m21=__req("packages/core/src/source/rows.js");
25219
26009
  const pinnedRow=__m21["pinnedRow"];
25220
26010
  const DEFAULT_ROW_HEIGHT=__m21["DEFAULT_ROW_HEIGHT"];
@@ -25471,6 +26261,10 @@ for(const[name,fn]of Object.entries(this.#config.totalFns||{})){
25471
26261
  if(isFunction(fn))this.#registry.register('totalFn',name,fn);
25472
26262
  }
25473
26263
  this.#pool=new MaskPool();
26264
+ if(this.#config.rowKey===undefined&&isObject(this.#config.source)
26265
+ &&(this.#config.source).mode==='derived'){
26266
+ this.#config.rowKey=DERIVED_ROW_KEY;
26267
+ }
25474
26268
  this.#rowKeyResolver=createRowKey(this.#config.rowKey);
25475
26269
  this.#rowKey=(data,index)=>this.#rowKeyResolver.key(data,index);
25476
26270
  if(Array.isArray(this.#config.pinnedTopRows))this.#pinnedTop=this.#config.pinnedTopRows.slice();
@@ -27037,7 +27831,7 @@ const before=flash?grid.#captureCells(change):null;
27037
27831
  const result=grid.#changes.apply(change);
27038
27832
  if(before)grid.#flashChanged(before,result.updated,flash);
27039
27833
  grid.#refresh('rows');
27040
- grid.#bus.emit('rows:changed',{change},'api');
27834
+ grid.#bus.emit('rows:changed',{companion:true,change},'api');
27041
27835
  return result;
27042
27836
  },
27043
27837
  queue(change){return grid.#changes.queue(change);},
@@ -27096,6 +27890,16 @@ const row=source.at(i);
27096
27890
  if(row&&!row.group)fn(row,i);
27097
27891
  }
27098
27892
  },
27893
+ forEachExcept(colId,fn){
27894
+ if(!isFunction(fn))return;
27895
+ const source=grid.#source;
27896
+ if(colId&&isFunction(source.facetRows)){
27897
+ const rows=source.facetRows(colId);
27898
+ for(let i=0;i<rows.length;i++)fn(rows[i],i);
27899
+ return;
27900
+ }
27901
+ this.forEach(fn);
27902
+ },
27099
27903
  value(key,colId){
27100
27904
  const row=grid.#rowByKey(key);
27101
27905
  return grid.#cellValue(row,grid.#columnsView().get(colId)||colId);
@@ -27150,6 +27954,7 @@ if(target===from)return{moved:false,from,to:target,reason:'unchanged'};
27150
27954
  if(!grid.#source.moveRow(from,target))return refuse('unchanged');
27151
27955
  grid.#rebuildStore();
27152
27956
  grid.#refresh('rows');
27957
+ grid.#bus.emit('rows:changed',{moved:1,key,from,to:target},'api');
27153
27958
  grid.#bus.emit('row:moved',{key,from,to:target,data:row.data});
27154
27959
  return{moved:true,from,to:target};
27155
27960
  },
@@ -28090,6 +28895,18 @@ return grid.#detail.inline?'inline':'target';
28090
28895
  config(){return grid.#detail?grid.#detail.config:null;},
28091
28896
  };
28092
28897
  }
28898
+ get crossFilter(){
28899
+ const source=(this.#source);
28900
+ if(source&&isFunction(source.crossFilter))return source.crossFilter();
28901
+ return{
28902
+ enabled(){return false;},
28903
+ column(){return null;},
28904
+ get(){return[];},
28905
+ set(){},
28906
+ toggle(){},
28907
+ clear(){},
28908
+ };
28909
+ }
28093
28910
  get facets(){
28094
28911
  const grid=this;
28095
28912
  return{
@@ -38448,6 +39265,7 @@ const PREFIX='lat';
38448
39265
  const NAMESPACE='lattice';
38449
39266
  const CLASS={
38450
39267
  root:`${PREFIX}-grid-root`,
39268
+ title:`${PREFIX}-title`,
38451
39269
  header:`${PREFIX}-header`,
38452
39270
  headerStart:`${PREFIX}-header-left-pinned`,
38453
39271
  headerCentreClip:`${PREFIX}-header-centre-clip`,
@@ -38503,6 +39321,8 @@ fail('DomRenderer needs a DOM. Use createHeadlessGrid() on the server.');
38503
39321
  this.#document=document;
38504
39322
  this.#host=element;
38505
39323
  this.root=el(document,`${NAMESPACE} ${CLASS.root}`);
39324
+ this.title=el(document,CLASS.title);
39325
+ this.title.hidden=true;
38506
39326
  this.header=el(document,CLASS.header);
38507
39327
  this.headerStart=el(document,CLASS.headerStart);
38508
39328
  this.headerCentreClip=el(document,CLASS.headerCentreClip);
@@ -38532,6 +39352,7 @@ this.stickyBottom=el(document,CLASS.stickyBottom);
38532
39352
  this.overlays=el(document,CLASS.overlays);
38533
39353
  this.statusBar=el(document,CLASS.statusBar);
38534
39354
  this.measureLayer=el(document,CLASS.measure);
39355
+ this.root.appendChild(this.title);
38535
39356
  this.root.appendChild(this.header);
38536
39357
  this.root.appendChild(this.bodyViewport);
38537
39358
  this.root.appendChild(this.stickyTop);
@@ -38541,6 +39362,14 @@ this.root.appendChild(this.statusBar);
38541
39362
  this.root.appendChild(this.measureLayer);
38542
39363
  }
38543
39364
  get document(){return this.#document;}
39365
+ setTitle(text){
39366
+ const value=text===null||text===undefined?'':String(text);
39367
+ this.title.textContent=value;
39368
+ this.title.hidden=value==='';
39369
+ }
39370
+ setHeaderVisible(visible){
39371
+ this.header.hidden=!visible;
39372
+ }
38544
39373
  mount(){
38545
39374
  this.#host.appendChild(this.root);
38546
39375
  }
@@ -42288,6 +43117,7 @@ this.#host=host;
42288
43117
  this.#cellLayer=host.cellLayer||textCellLayer;
42289
43118
  this.#overscan=Number.isFinite(host.config?.overscan)?host.config.overscan:DEFAULT_OVERSCAN;
42290
43119
  this.#viewport=new Viewport(element,{document:host.document});
43120
+ this.#applyChrome(host.config);
42291
43121
  this.#layout=new ColumnLayout({
42292
43122
  columns:()=>this.#visibleColumns(),
42293
43123
  threshold:host.config?.columnVirtualisationAbove,
@@ -42357,6 +43187,11 @@ onFrame:(ctx)=>this.#frame(ctx),
42357
43187
  onScrollEnd:()=>this.#host.emit('scroll:end',this.scrollPosition()),
42358
43188
  });
42359
43189
  }
43190
+ #applyChrome(config){
43191
+ const title=config&&config.title;
43192
+ this.#viewport.setTitle(typeof title==='string'?title:null);
43193
+ this.#viewport.setHeaderVisible(!(config&&config.showHeader===false));
43194
+ }
42360
43195
  mount(){
42361
43196
  if(this.#mountedOnce)return;
42362
43197
  this.#mountedOnce=true;
@@ -63033,6 +63868,229 @@ grids.push(el.tagName==='TABLE'?hydrateTable(el,config):createGrid(el,config));
63033
63868
  return grids;
63034
63869
  }
63035
63870
  });
63871
+ __def("packages/dom/src/stat.js",function(__exports,__req){
63872
+ 'use strict';
63873
+ Object.defineProperty(__exports,"deltaOf",{enumerable:true,get:function(){return deltaOf;}});
63874
+ Object.defineProperty(__exports,"toneOf",{enumerable:true,get:function(){return toneOf;}});
63875
+ Object.defineProperty(__exports,"createStat",{enumerable:true,get:function(){return createStat;}});
63876
+ const __m0=__req("packages/core/src/internal/util.js");
63877
+ const isFunction=__m0["isFunction"];
63878
+ const isObject=__m0["isObject"];
63879
+ const warnOnce=__m0["warnOnce"];
63880
+ const __m1=__req("packages/core/src/source/derive.js");
63881
+ const reduceValues=__m1["reduceValues"];
63882
+ const CLS={
63883
+ root:'lat-stat',
63884
+ title:'lat-stat__title',
63885
+ value:'lat-stat__value',
63886
+ delta:'lat-stat__delta',
63887
+ footer:'lat-stat__footer',
63888
+ };
63889
+ const UNIT_PRESERVING=new Set([
63890
+ 'sum','min','max','avg','first','last','mode',
63891
+ 'median','p25','p75','p90','p95','p99',
63892
+ 'stddev','stddevP','mad','range','iqr',
63893
+ 'trimmedMean','winsorizedMean','geomean','harmean',
63894
+ ]);
63895
+ const NO_DELTA=Object.freeze({direction:'flat',change:null,percent:null});
63896
+ function deltaOf(value,baseline){
63897
+ if(!Number.isFinite((value))
63898
+ ||!Number.isFinite((baseline)))return NO_DELTA;
63899
+ const change=(value)-(baseline);
63900
+ const direction=change>0?'up':(change<0?'down':'flat');
63901
+ const percent=baseline===0?null:(change/Math.abs((baseline)))*100;
63902
+ return{direction,change,percent};
63903
+ }
63904
+ function toneOf(direction,goodWhen){
63905
+ if(direction==='flat'||goodWhen==='neither')return'flat';
63906
+ return direction===goodWhen?'good':'bad';
63907
+ }
63908
+ function createStat(spec){
63909
+ const config=isObject(spec)?spec:{};
63910
+ const grid=config.grid||null;
63911
+ const host=resolveContainer(config.container,grid);
63912
+ if(!host){
63913
+ warnOnce('stat.container','createStat needs a `container`: an element or a selector.');
63914
+ return inert();
63915
+ }
63916
+ const doc=host.ownerDocument||(typeof document==='undefined'?null:document);
63917
+ if(!doc){
63918
+ warnOnce('stat.document','createStat needs a document; it draws DOM.');
63919
+ return inert();
63920
+ }
63921
+ const root=doc.createElement('div');
63922
+ root.className=['lattice',CLS.root,config.class].filter(Boolean).join(' ');
63923
+ root.setAttribute('role','group');
63924
+ const titleEl=doc.createElement('div');
63925
+ titleEl.className=CLS.title;
63926
+ const valueEl=doc.createElement('div');
63927
+ valueEl.className=CLS.value;
63928
+ const deltaEl=doc.createElement('div');
63929
+ deltaEl.className=CLS.delta;
63930
+ const footerEl=doc.createElement('div');
63931
+ footerEl.className=CLS.footer;
63932
+ root.appendChild(titleEl);
63933
+ root.appendChild(valueEl);
63934
+ root.appendChild(deltaEl);
63935
+ root.appendChild(footerEl);
63936
+ host.appendChild(root);
63937
+ let current=null;
63938
+ const off=[];
63939
+ let gone=false;
63940
+ function compute(){
63941
+ if(isFunction(config.value))return config.value(grid);
63942
+ if(config.value!==undefined&&!isObject(config.value))return config.value;
63943
+ const from=isObject(config.value)?config.value:config;
63944
+ const col=from.of;
63945
+ const fn=from.fn||'sum';
63946
+ const show=from.show;
63947
+ if(!grid)return null;
63948
+ if(fn==='count')return rowsInScope().length;
63949
+ if(!col)return null;
63950
+ if(show)return pick(String(col),String(fn),String(show));
63951
+ if(scope()==='filtered'&&grid.statistics&&isFunction(grid.statistics.reduce)){
63952
+ return grid.statistics.reduce(String(col),String(fn));
63953
+ }
63954
+ return reduceValues(rowsInScope().map((row)=>valueOf(row,String(col))),String(fn));
63955
+ }
63956
+ function scope(){
63957
+ return String(config.scope||'filtered');
63958
+ }
63959
+ function rowsInScope(){
63960
+ if(!grid||!grid.rows)return[];
63961
+ const want=scope();
63962
+ if(want==='all'){
63963
+ const every=[];
63964
+ if(isFunction(grid.rows.forEachAll))grid.rows.forEachAll((row)=>{if(!row.group)every.push(plain(row));});
63965
+ return every;
63966
+ }
63967
+ if(want==='selected'){
63968
+ const rows=grid.selection&&isFunction(grid.selection.rows)?grid.selection.rows():[];
63969
+ return rows.filter(Boolean).map(plain);
63970
+ }
63971
+ const out=[];
63972
+ if(isFunction(grid.rows.forEach)){
63973
+ grid.rows.forEach((row)=>{if(!row.group)out.push(plain(row));});
63974
+ }
63975
+ return out;
63976
+ }
63977
+ function pick(col,fn,show){
63978
+ if(fn!=='min'&&fn!=='max'){
63979
+ warnOnce(
63980
+ `stat.show.${fn}`,
63981
+ `\`show\` needs \`fn: 'min'\` or \`fn: 'max'\`: "${fn}" reduces to a value that no single `
63982
+ +'row holds, so there is no row to report from.',
63983
+ );
63984
+ return null;
63985
+ }
63986
+ let best=null;
63987
+ let bestRow=null;
63988
+ for(const row of rowsInScope()){
63989
+ const value=Number(valueOf(row,col));
63990
+ if(!Number.isFinite(value))continue;
63991
+ if(best===null||(fn==='max'?value>best:value<best)){
63992
+ best=value;
63993
+ bestRow=row;
63994
+ }
63995
+ }
63996
+ return bestRow===null?null:valueOf(bestRow,show);
63997
+ }
63998
+ function render(value){
63999
+ if(isFunction(config.format))return String(config.format(value,grid));
64000
+ if(value===null||value===undefined)return config.empty??'—';
64001
+ const from=isObject(config.value)?config.value:config;
64002
+ const source=from.show||from.of;
64003
+ const borrow=from.show?true:UNIT_PRESERVING.has(String(from.fn||'sum'));
64004
+ if(borrow&&grid&&source&&isFunction(grid.columns?.get)){
64005
+ const column=grid.columns.get(String(source));
64006
+ if(column&&isFunction(column.formatValue))return column.formatValue(value);
64007
+ }
64008
+ if(typeof value==='number'){
64009
+ return Number.isInteger(value)?String(value):value.toFixed(config.decimals??2);
64010
+ }
64011
+ return String(value);
64012
+ }
64013
+ function refresh(){
64014
+ if(gone)return;
64015
+ const value=compute();
64016
+ const baseline=isFunction(config.baseline)?config.baseline(grid):config.baseline;
64017
+ current=value;
64018
+ titleEl.textContent=config.title??'';
64019
+ titleEl.hidden=!config.title;
64020
+ valueEl.textContent=render(value);
64021
+ const delta=baseline===undefined||baseline===null
64022
+ ?NO_DELTA
64023
+ :deltaOf(typeof value==='number'?value:null,Number(baseline));
64024
+ const tone=toneOf(delta.direction,config.goodWhen||'up');
64025
+ deltaEl.hidden=delta.change===null;
64026
+ if(delta.change!==null){
64027
+ const arrow=delta.direction==='up'?'↑':(delta.direction==='down'?'↓':'→');
64028
+ const size=delta.percent===null
64029
+ ?render(Math.abs(delta.change))
64030
+ :`${Math.abs(delta.percent).toFixed(1)}%`;
64031
+ deltaEl.textContent=`${arrow} ${size}`;
64032
+ deltaEl.setAttribute('data-tone',tone);
64033
+ deltaEl.setAttribute('data-direction',delta.direction);
64034
+ }
64035
+ footerEl.textContent=isFunction(config.footer)?String(config.footer(value,grid)):(config.footer??'');
64036
+ footerEl.hidden=!footerEl.textContent;
64037
+ root.setAttribute('aria-label',[
64038
+ config.title,valueEl.textContent,
64039
+ delta.change===null?'':deltaEl.textContent,
64040
+ footerEl.textContent,
64041
+ ].filter(Boolean).join(', '));
64042
+ }
64043
+ if(grid&&isFunction(grid.on)&&config.live!==false){
64044
+ for(const event of['rows:changed','filter:changed','selection:changed']){
64045
+ const handler=()=>refresh();
64046
+ grid.on(event,handler);
64047
+ off.push(()=>isFunction(grid.off)&&grid.off(event,handler));
64048
+ }
64049
+ }
64050
+ refresh();
64051
+ return{
64052
+ element:()=>root,
64053
+ value:()=>current,
64054
+ refresh,
64055
+ destroy(){
64056
+ gone=true;
64057
+ for(const remove of off){try{remove();}catch{}}
64058
+ off.length=0;
64059
+ root.remove();
64060
+ },
64061
+ };
64062
+ }
64063
+ function plain(row){
64064
+ return isObject(row)&&'data'in(row)
64065
+ ?(row).data
64066
+ :row;
64067
+ }
64068
+ function valueOf(row,path){
64069
+ if(!isObject(row))return undefined;
64070
+ if(!path.includes('.'))return(row)[path];
64071
+ let cursor=(row);
64072
+ for(const part of path.split('.')){
64073
+ if(!isObject(cursor))return undefined;
64074
+ cursor=(cursor)[part];
64075
+ }
64076
+ return cursor;
64077
+ }
64078
+ function resolveContainer(container,grid){
64079
+ if(container&&typeof container==='object')return(container);
64080
+ if(typeof container!=='string')return null;
64081
+ const doc=(grid&&grid.element&&grid.element.ownerDocument)
64082
+ ||(typeof document==='undefined'?null:document);
64083
+ return doc?doc.querySelector(container):null;
64084
+ }
64085
+ function inert(){
64086
+ return{
64087
+ element:()=>null,
64088
+ value:()=>null,
64089
+ refresh(){},
64090
+ destroy(){},
64091
+ };
64092
+ }
64093
+ });
63036
64094
  __def("packages/dom/src/index.js",function(__exports,__req){
63037
64095
  'use strict';
63038
64096
  Object.defineProperty(__exports,"LatticeGrid",{enumerable:true,get:function(){return LatticeGrid;}});
@@ -63055,6 +64113,10 @@ const serialiseState=__m4["serialiseState"];
63055
64113
  const restoreState=__m4["restoreState"];
63056
64114
  Object.defineProperty(__exports,"createGrid",{enumerable:true,get:function(){return __m0["createGrid"];}});
63057
64115
  Object.defineProperty(__exports,"gridElementsWithin",{enumerable:true,get:function(){return __m0["gridElementsWithin"];}});
64116
+ const __m5=__req("packages/dom/src/stat.js");
64117
+ Object.defineProperty(__exports,"createStat",{enumerable:true,get:function(){return __m5["createStat"];}});
64118
+ Object.defineProperty(__exports,"deltaOf",{enumerable:true,get:function(){return __m5["deltaOf"];}});
64119
+ Object.defineProperty(__exports,"toneOf",{enumerable:true,get:function(){return __m5["toneOf"];}});
63058
64120
  Object.defineProperty(__exports,"readTable",{enumerable:true,get:function(){return __m1["readTable"];}});
63059
64121
  Object.defineProperty(__exports,"hydrateTable",{enumerable:true,get:function(){return __m1["hydrateTable"];}});
63060
64122
  Object.defineProperty(__exports,"autoInit",{enumerable:true,get:function(){return __m2["autoInit"];}});
@@ -63163,71 +64225,71 @@ Object.defineProperty(__exports,"STATE_VERSION",{enumerable:true,get:function(){
63163
64225
  Object.defineProperty(__exports,"serialiseState",{enumerable:true,get:function(){return __m4["serialiseState"];}});
63164
64226
  Object.defineProperty(__exports,"restoreState",{enumerable:true,get:function(){return __m4["restoreState"];}});
63165
64227
  Object.defineProperty(__exports,"VERSION",{enumerable:true,get:function(){return __m4["VERSION"];}});
63166
- const __m5=__req("packages/dom/src/renderer/index.js");
63167
- Object.defineProperty(__exports,"DomRenderer",{enumerable:true,get:function(){return __m5["DomRenderer"];}});
63168
- const __m6=__req("packages/dom/src/filtermenu.js");
63169
- Object.defineProperty(__exports,"FilterMenu",{enumerable:true,get:function(){return __m6["FilterMenu"];}});
63170
- Object.defineProperty(__exports,"mergeColumnFilter",{enumerable:true,get:function(){return __m6["mergeColumnFilter"];}});
63171
- Object.defineProperty(__exports,"branchFor",{enumerable:true,get:function(){return __m6["branchFor"];}});
63172
- const __m7=__req("packages/dom/src/columnmenu.js");
63173
- Object.defineProperty(__exports,"ColumnMenu",{enumerable:true,get:function(){return __m7["ColumnMenu"];}});
63174
- Object.defineProperty(__exports,"columnMenuItems",{enumerable:true,get:function(){return __m7["columnMenuItems"];}});
63175
- Object.defineProperty(__exports,"cellMenuItems",{enumerable:true,get:function(){return __m7["cellMenuItems"];}});
63176
- Object.defineProperty(__exports,"autoGroupMenuItems",{enumerable:true,get:function(){return __m7["autoGroupMenuItems"];}});
63177
- const __m8=__req("packages/dom/src/alignedgrids.js");
63178
- Object.defineProperty(__exports,"AlignedGrids",{enumerable:true,get:function(){return __m8["AlignedGrids"];}});
63179
- Object.defineProperty(__exports,"alignGrids",{enumerable:true,get:function(){return __m8["alignGrids"];}});
63180
- Object.defineProperty(__exports,"layoutState",{enumerable:true,get:function(){return __m8["layoutState"];}});
63181
- const __m9=__req("packages/dom/src/toolpanelmount.js");
63182
- Object.defineProperty(__exports,"ToolPanelDock",{enumerable:true,get:function(){return __m9["ToolPanelDock"];}});
63183
- Object.defineProperty(__exports,"panelHost",{enumerable:true,get:function(){return __m9["panelHost"];}});
63184
- Object.defineProperty(__exports,"mountPanel",{enumerable:true,get:function(){return __m9["mountPanel"];}});
63185
- const __m10=__req("packages/dom/src/celledit.js");
63186
- Object.defineProperty(__exports,"CellEditController",{enumerable:true,get:function(){return __m10["CellEditController"];}});
63187
- const __m11=__req("packages/dom/src/editbar.js");
63188
- Object.defineProperty(__exports,"EditBar",{enumerable:true,get:function(){return __m11["EditBar"];}});
63189
- const __m12=__req("packages/dom/src/historybar.js");
63190
- Object.defineProperty(__exports,"HistoryBar",{enumerable:true,get:function(){return __m12["HistoryBar"];}});
63191
- Object.defineProperty(__exports,"HISTORY_CLS",{enumerable:true,get:function(){return __m12["HISTORY_CLS"];}});
63192
- const __m13=__req("packages/dom/src/diffpaint.js");
63193
- Object.defineProperty(__exports,"DiffPainter",{enumerable:true,get:function(){return __m13["DiffPainter"];}});
63194
- const __m14=__req("packages/dom/src/viewpicker.js");
63195
- Object.defineProperty(__exports,"ViewPicker",{enumerable:true,get:function(){return __m14["ViewPicker"];}});
63196
- Object.defineProperty(__exports,"VIEW_CLS",{enumerable:true,get:function(){return __m14["VIEW_CLS"];}});
63197
- Object.defineProperty(__exports,"summariseDiff",{enumerable:true,get:function(){return __m14["summariseDiff"];}});
63198
- const __m15=__req("packages/dom/src/promptbar.js");
63199
- Object.defineProperty(__exports,"PromptBar",{enumerable:true,get:function(){return __m15["PromptBar"];}});
63200
- Object.defineProperty(__exports,"PROMPT_CLASS",{enumerable:true,get:function(){return __m15["PROMPT_CLASS"];}});
63201
- const __m16=__req("packages/dom/src/cell/index.js");
63202
- Object.defineProperty(__exports,"createCellLayer",{enumerable:true,get:function(){return __m16["createCellLayer"];}});
63203
- Object.defineProperty(__exports,"compileTemplate",{enumerable:true,get:function(){return __m16["compileTemplate"];}});
63204
- Object.defineProperty(__exports,"compileVariant",{enumerable:true,get:function(){return __m16["compileVariant"];}});
63205
- Object.defineProperty(__exports,"checkVariant",{enumerable:true,get:function(){return __m16["checkVariant"];}});
63206
- Object.defineProperty(__exports,"VariantRegistry",{enumerable:true,get:function(){return __m16["VariantRegistry"];}});
63207
- Object.defineProperty(__exports,"BUILTIN_RENDERERS",{enumerable:true,get:function(){return __m16["BUILTIN_RENDERERS"];}});
63208
- Object.defineProperty(__exports,"BUILTIN_VARIANTS",{enumerable:true,get:function(){return __m16["BUILTIN_VARIANTS"];}});
63209
- Object.defineProperty(__exports,"BUILTIN_PIPES",{enumerable:true,get:function(){return __m16["BUILTIN_PIPES"];}});
63210
- const __m17=__req("packages/dom/src/editors/index.js");
63211
- Object.defineProperty(__exports,"editors",{enumerable:true,get:function(){return __m17["editors"];}});
63212
- Object.defineProperty(__exports,"createEditor",{enumerable:true,get:function(){return __m17["createEditor"];}});
63213
- Object.defineProperty(__exports,"editorFor",{enumerable:true,get:function(){return __m17["editorFor"];}});
63214
- Object.defineProperty(__exports,"BaseEditor",{enumerable:true,get:function(){return __m17["BaseEditor"];}});
63215
- const __m18=__req("packages/dom/src/filters/index.js");
63216
- Object.defineProperty(__exports,"filters",{enumerable:true,get:function(){return __m18["filters"];}});
63217
- Object.defineProperty(__exports,"createFilter",{enumerable:true,get:function(){return __m18["createFilter"];}});
63218
- Object.defineProperty(__exports,"filterFor",{enumerable:true,get:function(){return __m18["filterFor"];}});
63219
- Object.defineProperty(__exports,"parseExpression",{enumerable:true,get:function(){return __m18["parseExpression"];}});
63220
- const __m19=__req("packages/dom/src/ui/index.js");
63221
- Object.defineProperty(__exports,"StatusBar",{enumerable:true,get:function(){return __m19["StatusBar"];}});
63222
- Object.defineProperty(__exports,"ContextMenu",{enumerable:true,get:function(){return __m19["ContextMenu"];}});
63223
- Object.defineProperty(__exports,"ToolPanel",{enumerable:true,get:function(){return __m19["ToolPanel"];}});
63224
- Object.defineProperty(__exports,"TooltipManager",{enumerable:true,get:function(){return __m19["TooltipManager"];}});
63225
- Object.defineProperty(__exports,"Pagination",{enumerable:true,get:function(){return __m19["Pagination"];}});
63226
- Object.defineProperty(__exports,"OverlayLayer",{enumerable:true,get:function(){return __m19["OverlayLayer"];}});
63227
- const __m20=__req("packages/core/src/registry/licence.js");
63228
- Object.defineProperty(__exports,"setLicense",{enumerable:true,get:function(){return __m20["setLicence"];}});
63229
- Object.defineProperty(__exports,"licenseInfo",{enumerable:true,get:function(){return __m20["licenceInfo"];}});
63230
- Object.defineProperty(__exports,"licenseState",{enumerable:true,get:function(){return __m20["licenceState"];}});
64228
+ const __m6=__req("packages/dom/src/renderer/index.js");
64229
+ Object.defineProperty(__exports,"DomRenderer",{enumerable:true,get:function(){return __m6["DomRenderer"];}});
64230
+ const __m7=__req("packages/dom/src/filtermenu.js");
64231
+ Object.defineProperty(__exports,"FilterMenu",{enumerable:true,get:function(){return __m7["FilterMenu"];}});
64232
+ Object.defineProperty(__exports,"mergeColumnFilter",{enumerable:true,get:function(){return __m7["mergeColumnFilter"];}});
64233
+ Object.defineProperty(__exports,"branchFor",{enumerable:true,get:function(){return __m7["branchFor"];}});
64234
+ const __m8=__req("packages/dom/src/columnmenu.js");
64235
+ Object.defineProperty(__exports,"ColumnMenu",{enumerable:true,get:function(){return __m8["ColumnMenu"];}});
64236
+ Object.defineProperty(__exports,"columnMenuItems",{enumerable:true,get:function(){return __m8["columnMenuItems"];}});
64237
+ Object.defineProperty(__exports,"cellMenuItems",{enumerable:true,get:function(){return __m8["cellMenuItems"];}});
64238
+ Object.defineProperty(__exports,"autoGroupMenuItems",{enumerable:true,get:function(){return __m8["autoGroupMenuItems"];}});
64239
+ const __m9=__req("packages/dom/src/alignedgrids.js");
64240
+ Object.defineProperty(__exports,"AlignedGrids",{enumerable:true,get:function(){return __m9["AlignedGrids"];}});
64241
+ Object.defineProperty(__exports,"alignGrids",{enumerable:true,get:function(){return __m9["alignGrids"];}});
64242
+ Object.defineProperty(__exports,"layoutState",{enumerable:true,get:function(){return __m9["layoutState"];}});
64243
+ const __m10=__req("packages/dom/src/toolpanelmount.js");
64244
+ Object.defineProperty(__exports,"ToolPanelDock",{enumerable:true,get:function(){return __m10["ToolPanelDock"];}});
64245
+ Object.defineProperty(__exports,"panelHost",{enumerable:true,get:function(){return __m10["panelHost"];}});
64246
+ Object.defineProperty(__exports,"mountPanel",{enumerable:true,get:function(){return __m10["mountPanel"];}});
64247
+ const __m11=__req("packages/dom/src/celledit.js");
64248
+ Object.defineProperty(__exports,"CellEditController",{enumerable:true,get:function(){return __m11["CellEditController"];}});
64249
+ const __m12=__req("packages/dom/src/editbar.js");
64250
+ Object.defineProperty(__exports,"EditBar",{enumerable:true,get:function(){return __m12["EditBar"];}});
64251
+ const __m13=__req("packages/dom/src/historybar.js");
64252
+ Object.defineProperty(__exports,"HistoryBar",{enumerable:true,get:function(){return __m13["HistoryBar"];}});
64253
+ Object.defineProperty(__exports,"HISTORY_CLS",{enumerable:true,get:function(){return __m13["HISTORY_CLS"];}});
64254
+ const __m14=__req("packages/dom/src/diffpaint.js");
64255
+ Object.defineProperty(__exports,"DiffPainter",{enumerable:true,get:function(){return __m14["DiffPainter"];}});
64256
+ const __m15=__req("packages/dom/src/viewpicker.js");
64257
+ Object.defineProperty(__exports,"ViewPicker",{enumerable:true,get:function(){return __m15["ViewPicker"];}});
64258
+ Object.defineProperty(__exports,"VIEW_CLS",{enumerable:true,get:function(){return __m15["VIEW_CLS"];}});
64259
+ Object.defineProperty(__exports,"summariseDiff",{enumerable:true,get:function(){return __m15["summariseDiff"];}});
64260
+ const __m16=__req("packages/dom/src/promptbar.js");
64261
+ Object.defineProperty(__exports,"PromptBar",{enumerable:true,get:function(){return __m16["PromptBar"];}});
64262
+ Object.defineProperty(__exports,"PROMPT_CLASS",{enumerable:true,get:function(){return __m16["PROMPT_CLASS"];}});
64263
+ const __m17=__req("packages/dom/src/cell/index.js");
64264
+ Object.defineProperty(__exports,"createCellLayer",{enumerable:true,get:function(){return __m17["createCellLayer"];}});
64265
+ Object.defineProperty(__exports,"compileTemplate",{enumerable:true,get:function(){return __m17["compileTemplate"];}});
64266
+ Object.defineProperty(__exports,"compileVariant",{enumerable:true,get:function(){return __m17["compileVariant"];}});
64267
+ Object.defineProperty(__exports,"checkVariant",{enumerable:true,get:function(){return __m17["checkVariant"];}});
64268
+ Object.defineProperty(__exports,"VariantRegistry",{enumerable:true,get:function(){return __m17["VariantRegistry"];}});
64269
+ Object.defineProperty(__exports,"BUILTIN_RENDERERS",{enumerable:true,get:function(){return __m17["BUILTIN_RENDERERS"];}});
64270
+ Object.defineProperty(__exports,"BUILTIN_VARIANTS",{enumerable:true,get:function(){return __m17["BUILTIN_VARIANTS"];}});
64271
+ Object.defineProperty(__exports,"BUILTIN_PIPES",{enumerable:true,get:function(){return __m17["BUILTIN_PIPES"];}});
64272
+ const __m18=__req("packages/dom/src/editors/index.js");
64273
+ Object.defineProperty(__exports,"editors",{enumerable:true,get:function(){return __m18["editors"];}});
64274
+ Object.defineProperty(__exports,"createEditor",{enumerable:true,get:function(){return __m18["createEditor"];}});
64275
+ Object.defineProperty(__exports,"editorFor",{enumerable:true,get:function(){return __m18["editorFor"];}});
64276
+ Object.defineProperty(__exports,"BaseEditor",{enumerable:true,get:function(){return __m18["BaseEditor"];}});
64277
+ const __m19=__req("packages/dom/src/filters/index.js");
64278
+ Object.defineProperty(__exports,"filters",{enumerable:true,get:function(){return __m19["filters"];}});
64279
+ Object.defineProperty(__exports,"createFilter",{enumerable:true,get:function(){return __m19["createFilter"];}});
64280
+ Object.defineProperty(__exports,"filterFor",{enumerable:true,get:function(){return __m19["filterFor"];}});
64281
+ Object.defineProperty(__exports,"parseExpression",{enumerable:true,get:function(){return __m19["parseExpression"];}});
64282
+ const __m20=__req("packages/dom/src/ui/index.js");
64283
+ Object.defineProperty(__exports,"StatusBar",{enumerable:true,get:function(){return __m20["StatusBar"];}});
64284
+ Object.defineProperty(__exports,"ContextMenu",{enumerable:true,get:function(){return __m20["ContextMenu"];}});
64285
+ Object.defineProperty(__exports,"ToolPanel",{enumerable:true,get:function(){return __m20["ToolPanel"];}});
64286
+ Object.defineProperty(__exports,"TooltipManager",{enumerable:true,get:function(){return __m20["TooltipManager"];}});
64287
+ Object.defineProperty(__exports,"Pagination",{enumerable:true,get:function(){return __m20["Pagination"];}});
64288
+ Object.defineProperty(__exports,"OverlayLayer",{enumerable:true,get:function(){return __m20["OverlayLayer"];}});
64289
+ const __m21=__req("packages/core/src/registry/licence.js");
64290
+ Object.defineProperty(__exports,"setLicense",{enumerable:true,get:function(){return __m21["setLicence"];}});
64291
+ Object.defineProperty(__exports,"licenseInfo",{enumerable:true,get:function(){return __m21["licenceInfo"];}});
64292
+ Object.defineProperty(__exports,"licenseState",{enumerable:true,get:function(){return __m21["licenceState"];}});
63231
64293
  const LatticeGrid={
63232
64294
  createGrid,
63233
64295
  createHeadlessGrid,
@@ -63249,6 +64311,9 @@ const __entry=__req("packages/dom/src/index.js");
63249
64311
  export const
63250
64312
  createGrid=__entry.createGrid,
63251
64313
  gridElementsWithin=__entry.gridElementsWithin,
64314
+ createStat=__entry.createStat,
64315
+ deltaOf=__entry.deltaOf,
64316
+ toneOf=__entry.toneOf,
63252
64317
  readTable=__entry.readTable,
63253
64318
  hydrateTable=__entry.hydrateTable,
63254
64319
  autoInit=__entry.autoInit,