@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.
- package/README.md +6 -5
- package/docs/API.html +330 -3
- package/lattice-grid.d.ts +255 -4
- package/lattice-grid.esm.min.js +1169 -104
- package/lattice-grid.min.cjs +1166 -104
- package/lattice-grid.min.css +1 -1
- package/lattice-grid.min.js +1166 -104
- package/modules/charts.esm.min.js +1 -1
- package/modules/devtools.esm.min.js +1 -1
- package/modules/dhtmlx-compat.esm.min.js +1166 -104
- package/modules/htmx.esm.min.js +874 -39
- package/modules/htmx.min.cjs +874 -39
- package/modules/htmx.min.js +874 -39
- package/modules/react.esm.min.js +1 -1
- package/modules/svelte.esm.min.js +1 -1
- package/modules/vue.esm.min.js +1 -1
- package/modules/webcomponent.esm.min.js +1166 -104
- package/package.json +1 -1
package/modules/htmx.esm.min.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Lattice Grid 1.
|
|
2
|
+
* Lattice Grid 1.11.0 — htmx module
|
|
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',{
|
|
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',{
|
|
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/
|
|
15085
|
-
|
|
15086
|
-
|
|
15087
|
-
|
|
15088
|
-
|
|
15089
|
-
|
|
15090
|
-
|
|
15091
|
-
Object.defineProperty(__exports,"
|
|
15092
|
-
Object.defineProperty(__exports,"
|
|
15093
|
-
Object.defineProperty(__exports,"
|
|
15094
|
-
Object.defineProperty(__exports,"
|
|
15095
|
-
Object.defineProperty(__exports,"
|
|
15096
|
-
Object.defineProperty(__exports,"
|
|
15097
|
-
Object.defineProperty(__exports,"
|
|
15098
|
-
Object.defineProperty(__exports,"
|
|
15099
|
-
Object.defineProperty(__exports,"
|
|
15100
|
-
|
|
15101
|
-
Object.defineProperty(__exports,"
|
|
15102
|
-
Object.defineProperty(__exports,"
|
|
15103
|
-
|
|
15104
|
-
Object.defineProperty(__exports,"
|
|
15105
|
-
Object.defineProperty(__exports,"
|
|
15106
|
-
|
|
15107
|
-
|
|
15108
|
-
Object.defineProperty(__exports,"
|
|
15109
|
-
|
|
15110
|
-
Object.defineProperty(__exports,"
|
|
15111
|
-
Object.defineProperty(__exports,"
|
|
15112
|
-
Object.defineProperty(__exports,"
|
|
15113
|
-
Object.defineProperty(__exports,"
|
|
15114
|
-
Object.defineProperty(__exports,"
|
|
15115
|
-
|
|
15116
|
-
Object.defineProperty(__exports,"
|
|
15117
|
-
Object.defineProperty(__exports,"
|
|
15118
|
-
|
|
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;
|