PageSourceSearch

https://ai-energy-planning.netlify.app/assets/BuildingTable-CBMD9IlM.js

js ai-energy-planning.netlify.app collected 2026-10-03 10:25:54 UTC 89,278 bytes, 37 lines download raw bytes

1import{r as T,j as _}from"./vendor-react-DVrBU6_x.js";import{c as ne,B as He,o as De}from"./index-DM7KUgsE.js";import"./vendor-d3-CGnuPtl4.js";import"./vendor-sweetalert-CRdFYMG-.js";import"./vendor-duckdb-DncbAeEm.js";/**
2 * @license lucide-react v0.344.0 - ISC
3 *
4 * This source code is licensed under the ISC license.
5 * See the LICENSE file in the root directory of this source tree.
6 */const je=ne("Database",[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3",key:"msslwz"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5",key:"1wlel7"}],["path",{d:"M3 12A9 3 0 0 0 21 12",key:"mv7ke4"}]]);/**
7 * @license lucide-react v0.344.0 - ISC
8 *
9 * This source code is licensed under the ISC license.
10 * See the LICENSE file in the root directory of this source tree.
11 */const Oe=ne("Download",[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["polyline",{points:"7 10 12 15 17 10",key:"2ggqvy"}],["line",{x1:"12",x2:"12",y1:"15",y2:"3",key:"1vk2je"}]]);/**
12 * @license lucide-react v0.344.0 - ISC
13 *
14 * This source code is licensed under the ISC license.
15 * See the LICENSE file in the root directory of this source tree.
16 */const ze=ne("FileSpreadsheet",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M8 13h2",key:"yr2amv"}],["path",{d:"M14 13h2",key:"un5t4a"}],["path",{d:"M8 17h2",key:"2yhykz"}],["path",{d:"M14 17h2",key:"10kma7"}]]);/**
17 * @license lucide-react v0.344.0 - ISC
18 *
19 * This source code is licensed under the ISC license.
20 * See the LICENSE file in the root directory of this source tree.
21 */const Ue=ne("GitCompareArrows",[["circle",{cx:"5",cy:"6",r:"3",key:"1qnov2"}],["path",{d:"M12 6h5a2 2 0 0 1 2 2v7",key:"1yj91y"}],["path",{d:"m15 9-3-3 3-3",key:"1lwv8l"}],["circle",{cx:"19",cy:"18",r:"3",key:"1qljk2"}],["path",{d:"M12 18H7a2 2 0 0 1-2-2V9",key:"16sdep"}],["path",{d:"m9 15 3 3-3 3",key:"1m3kbl"}]]);class b{static _AGGREGATORS=new Map;static registerAggregator(e){if(!e||!e.id)throw new Error("DataStats.registerAggregator: missing id");b._AGGREGATORS.set(e.id,{...e})}static getAggregators(){return Array.from(b._AGGREGATORS.values()).map(e=>({...e}))}static getAggregatorById(e){const n=b._AGGREGATORS.get(e);return n?{...n}:null}static inferType(e){const n=(e||[]).filter(r=>r!=null),o=new Set(n),t=n[0];return n.length===0?"unknown":typeof t=="number"?"numeric":typeof t=="string"&&o.size<=15?"categorical":typeof t=="string"?"id":typeof t=="object"&&t!==null?"timeseries":"unknown"}static average(e,n={}){const{nullReplacement:o=void 0,warnIfAllNull:t=!0,colName:r=""}=n;let s;return o!==void 0?s=e.map(i=>i===null?o:i).filter(i=>typeof i=="number"&&!isNaN(i)):s=(e||[]).filter(i=>typeof i=="number"&&!isNaN(i)),s.length===0?(t&&typeof console<"u"&&console.warn&&console.warn(`average(): All values null/non-numeric${r?` in "${r}"`:""}. Returning null.`),null):s.reduce((i,a)=>
21i+a,0)/s.length}static deterministicMode(e){const n=(e||[]).filter(s=>s!=null);if(!n.length)return null;const o=new Map;for(const s of n)o.set(s,(o.get(s)||0)+1);let t=null,r=-1;for(const[s,i]of o){if(i>r){t=s,r=i;continue}i===r&&String(s).localeCompare(String(t))<0&&(t=s)}return t}static median(e){const n=(e||[]).filter(r=>r!=null).sort(),o=n.length;if(o===0)return null;const t=Math.floor(o/2);return o%2===0?n[t-1]:n[t]}static medianByOrder(e,n){const o=Array.isArray(n)?n:[];if(!o.length)return b.median(e);const t=new Map(o.map((i,a)=>[i,a])),r=(e||[]).filter(i=>i!=null&&t.has(i)).sort((i,a)=>t.get(i)-t.get(a));if(!r.length)return null;const s=Math.floor(r.length/2);return r.length%2===0?r[s-1]:r[s]}static percentTrue(e){const n=(e||[]).filter(t=>t!=null);return n.length?n.reduce((t,r)=>t+(r===!0?1:0),0)/n.length*100:null}static uniformConstant(e){const n=(e||[]).filter(o=>o!=null);return n.length&&new Set(n).size===1?n[0]:"—"}static count(e){return(e||[]).length}static countNonNull(e){return(e||[]).filter(n=>n!=null).length}static getSum(e){const n=(e||[]).filter(t=>typeof t=="number"&&!isNaN(t));if(n.length===0)return 0;let o=0;for(let t=0;t<n.length;t++)o+=n[t];return o}
21static getMin(e,n){return Math.min(...b.getColumnValues(e,n))}static getMax(e,n){return Math.max(...b.getColumnValues(e,n))}static getStdDev(e,n){const o=b.getColumnValues(e,n),t=b.getMean(e,n),r=o.reduce((s,i)=>s+(i-t)**2,0)/o.length;return Math.sqrt(r)}static getColumnStats(e,n){const o=b.getColumnValues(e,n),t=o.length,r=o.reduce((d,h)=>d+h,0),s=r/t,i=Math.min(...o),a=Math.max(...o),l=Math.sqrt(o.reduce((d,h)=>d+(h-s)**2,0)/t);return{count:t,sum:r,mean:s,min:i,max:a,stddev:l}}static getNumericalHistogram(e,{bins:n=null,maxBins:o=10,binGenerator:t=null}={}){const r=(e||[]).filter(l=>typeof l=="number"&&!isNaN(l));if(r.length===0)return[];const s=Math.min(...r),i=Math.max(...r);if(s===i){const l=Math.max(1,Math.abs(s)*.01),d=[s-l/2,s+l/2];return b.getHistogramByBoundaries(r,d)}let a;return n?a=Array.isArray(n)?n:b.generateNiceLinearBins(s,i,typeof n=="number"?n:o):t?a=t(s,i,o):a=(s>0?Math.log10(i)-Math.log10(s):0)>2.5&&s>0?b.generateNiceLogBins(s,i,o):b.generateNiceLinearBins(s,i,o),b.getHistogramByBoundaries(r,a)}static getCategoricalHistogram(e){const n={};let o=!0;for(const r of e||[])typeof r!="number"&&(o=!1),n[r]=(n[r]||0)+1;const t=Object.entries(n);return t.sort((r,s)=>{const i=r[0],a=s[0];return o?Number(i)-Number(a):String(i).localeCompare(String(a))}),t.map(([r,s])=>({label:r,count:s}))}static getOrdinalHistogram(e,n){new Map((n||[]).map((t,r)=>[t,r]));const o={};for(const t of e||[])o[t]=(o[t]||0)+1;return(n||[]).map(t=>({label:t,count:o[t]||0}))}static getHistogramByBoundaries(e,n){const o=Array(n.length-1).fill(0),t=o.length-1;for(const r of e||[])for(let s=0;s<n.length-1;s++)if(s===t?r>=n[s]:r>=n[s]&&r<n[s+1]){o[s]++;break}return o.map((r,s)=>({range:[n[s],n[s+1]],count:r}))}static getHistogram(e,{dataType:n=null,order:o=null,bins:t=null,maxBins:r=10,binGenerator:s=null,classifier:i=null}={}){const a=(e||[]).filter(d=>d!=null);if(n==="numeric")return b.getNumericalHistogram(a,{bins:t,maxBins:r,binGenerator:s});if(n==="ordinal")return b.getOrdinalHistogram(a,o||[]);if(n==="categorical")return b.getCategoricalHistogram(a,{classifier:i});const l=b.inferType(a);return l==="numeric"?b.getNumericalHistogram(a,{bins:t,maxBins:r,binGenerator:s}):l==="ordinal"?o?b.getOrdinalHistogram(a,o):b.getCategoricalHistogram(a,{classifier:i}):b.getCategoricalHistogram(a,{classifier:i})}static generateNiceLinearBins(e,n,o=10){const t=(n-e)/o,r=Math.floor(Math.log10(t)),s=Math.pow(10,r),i=[1,2,5,10].map(m=>m*s),a=i.find(m=>(n-e)/m<=o)||i[i.length-1],l=Math.floor(e/a)*a,d=Math.ceil(n/a)*a,h=[];for(let m=l;m<=d;m+=a)h.push(m);return h}static generateNiceLogBins(e,n,o=6){const t=Math.floor(Math.log10(e)),r=Math.ceil(Math.log10(n)),s=Math.max(1,Math.ceil((r-t)/o)),i=[];for(let a=t;a<=r;a+=s)i.push(Math.pow(10,a));return i}static _seedDefaultAggregatorsOnce(){b._seeded||(b._seeded=!0,b.registerAggregator({id:"count",label:"count",resultType:"numeric",sortable:!0,fn:e=>(e||[]).length,tooltip:()=>"Aggregator: count"}),b.registerAggregator({id:"total",label:"total",resultType:"numeric",sortable:!0,fn:e=>b.getSum(e),tooltip:()=>"Aggregator: total (sum of numeric values)"}),b.registerAggregator({id:"mean",label:"mean",resultType:"numeric",sortable:!0,fn:(e,n)=>b.average(e,{colName:n?.column}),tooltip:()=>"Aggregator: mean (non-null numeric values)"}),b.registerAggregator({id:"mode",label:"mode",resultType:"categorical",sortable:!0,fn:e=>b.deterministicMode(e),tooltip:()=>"Aggregator: mode (ties broken alphabetically)"}),b.registerAggregator({id:"median",label:"median",resultType:"ordinal",sortable:!0,fn:(e,n)=>b.medianByOrder(e,n?.ordinalOrder),tooltip:()=>"Aggregator: median (by ordinal order)"}),b.registerAggregator({id:"uniform",label:"id",resultType:"id",sortable:!0,fn:e=>b.uniformConstant(e),tooltip:()=>"Aggregator: id (shows value if all non-null equal; otherwise —)"}),b.registerAggregator({id:"pct_true",label:"% true",resultType:"numeric",sortable:!0,fn:e=>b.percentTrue(e),tooltip:()=>"Aggregator: % true (non-null values)"}),b.registerAggregator({id:"na",label:"N/A",resultType:"id",sortable:!1,fn:()=>"—",tooltip:()=>"Not aggregated (N/A)"}))}}b._seedDefaultAggregatorsOnce();function Ke(){return"df_"+Math.random().toString(36).substr(2,9)}class I{constructor({table:e,parent:n=null,name:o=null,description:t=null}){if(this.id=Ke(),this.table=e,this.parent=n,this.name=o,this._description=t,this.isVirtual=!1,this.virtualRows=null,this.virtualMemberLinks=null,this.columnProps=new Map,this.aggColumnProvenance=new Map,n){if(this.rowMap=[...n.rowMap],this.colMap=[...n.colMap],this.colNames=[...n.colNames],this.ordinals={...n.ordinals},this.sorted=n.sorted,this.operations=[...n.operations],this.columnTypes={...n.columnTypes},this.isVirtual=n.isVirtual||!1,this.virtualRows=n.isVirtual&&n.virtualRows?n.virtualRows.slice():null,this.virtualMemberLinks=n.isVirtual&&n.virtualMemberLinks?n.virtualMemberLinks.slice():null,this._groupByColumns=n._groupByColumns?n._groupByColumns.slice():void 0,this._sortedColumns=n._sortedColumns?n._sortedColumns.map(r=>({...r})):void 0,n.columnProps instanceof Map)for(const[r,s]of n.columnProps.entries())this.columnProps.set(r,s&&typeof s=="object"?{...s}:s);if(n.aggColumnProvenance instanceof Map)for(const[r,s]of n.aggColumnProvenance.entries())this.aggColumnProvenance.set(r,{...s})}else this.rowMap=e.data.map((r,s)=>s),this.colMap=e.columns.map((r,s)=>s),this.colNames=[...e.columns],this.ordinals={},this.sorted="unsorted",this.operations=[],this.columnTypes={}
21,this.colMap.forEach((r,s)=>{const i=this.getColumnName(s);this.columnTypes[i]=this._inferTypeForMasterColumn(r)}),this.colMap.forEach((r,s)=>{const i=this.getColumnName(s);if(!(this.getColumnProps(i)||{}).aggregator){const l=this._resolveDefaultAggregator(i);this.setColumnProps(i,{aggregator:l,_aggExplicit:!1})}})}_inferTypeForMasterColumn(e,{maxScanRows:n=5e3}={}){const o=this.table?.data;if(!Array.isArray(o)||o.length===0)return"unknown";let t=null,r=null;const s=new Set,i=Math.min(o.length,Math.max(1,n|0));for(let a=0;a<i;a++){const l=o[a];if(!l)continue;const d=l[e];if(d!=null){if(t==null&&(t=d,r=typeof d),typeof d=="number")return"numeric";if(typeof d=="object")return"timeseries";if(typeof d=="string"&&(s.add(d),s.size>15))return"id"}}return t==null?"unknown":r==="number"?"numeric":r==="object"?"timeseries":r==="string"?s.size<=15?"categorical":"id":"unknown"}getStateHints(){const e=this.getRowCount(),n=this.getColumnNames(),o=n.length,t=Math.min(3,e),r=[];for(let s=0;s<t;s++)r.push(this.getRow(s));return{rowCount:e,columnCount:o,columnNames:n,sampleRows:r,isVirtual:this.isVirtual||!1,groupByColumns:this.isVirtual?this._groupByColumns||[]:void 0}}static _fromTable(e){return new I({table:e})}getIdentifier(){return this.getDescriptor("short")}getDescriptor(e="short"){const n=this.getRowCount?.()??0,o=this.getColumnNames?.()||[],t=o.length||0,r=!!this.isVirtual;return e==="short"?`${this.id} (${t}col x ${n}row), name: ${this.name}`:`id : ${this.id}, name : name: ${this.name}, ${t} cols x ${n} rows, virtual = ${r}; columns = [${o.join(", ")}]`}setName(e){return this.name=e,this}getName(){return this.name}setDescription(e){return this._description=e,this}getDescription(e=!1){return e?this._description||(Array.isArray(this.operations)?this.operations.join(`
22`):""):this._description||(Array.isArray(this.operations)?this.operations.join(`
23`):"")}identity(){return new I({table:this.table,parent:this})}setColumnTypes(e,n={}){const o=new I({table:this.table,parent:this});for(const[t,r]of Object.entries(e)){if(!o.colNames.includes(t))throw new Error(`Column "${t}" not found in this facet.`);if(!["numeric","categorical","ordinal","id","timeseries"].includes(r))throw new Error(`Invalid type "${r}" for "${t}". Use "numeric", "categorical", or "ordinal".`);if(o.columnTypes[t]=r,r==="ordinal"){const i=n[t];if(!Array.isArray(i)||i.length===0)throw new Error(`Ordinal type for column "${t}" requires a non-empty order array.`);o.ordinals[t]=i}else o.ordinals&&delete o.ordinals[t];if((o.getColumnProps(t)||{})._aggExplicit!==!0){const i=o._resolveDefaultAggregator(t);o.setColumnProps(t,{aggregator:i,_aggExplicit:!1})}}return o._rebuildIndexCaches(),o}getColumnType(e){return this.ordinals&&this.ordinals[e]?"ordinal":this.columnTypes&&this.columnTypes[e]?this.columnTypes[e]:null}getOrdinalOrder(e){return this.ordinals&&this.ordinals[e]||null}setAggregator(e,n){if(n&&typeof n=="object"&&n.id)this.setColumnProps(e,{aggregator:{...n},_aggExplicit:!0});else throw new Error("setAggregator: expected { id, ... }");return this}getAggregator(e){return this.getColumnProp(e,"aggregator")||null}fromFacetToMasterRow(e){if(!this.isVirtual)return this.rowMap[e]}fromMasterToFacetRow(e){return this.isVirtual?-1:(this._rowIndexByMaster||this._rebuildIndexCaches(),this._rowIndexByMaster.get(e)??-1)}fromMasterToFacetColumn(e){return this.colMap.indexOf(e)}fromFacetToMasterColumn(e){return this.colMap[e]}fromMasterToFacetColumnName(e){const n=this.table.columns.indexOf(e),o=this.colMap.indexOf(n);return o>=0?this.colNames[o]:e}fromFacetToMasterColumnName(e){const n=this.colNames.indexOf(e),o=this.colMap[n];return this.table.columns[o]}_resolveMasterColIndex(e){if(typeof e=="number"&&Number.isInteger(e))return e>=0&&e<this.table.columns.length?e:-1;if(typeof e=="string"){if(this.colNames.indexOf(e)>=0){const o=this.aggColumnProvenance.get(e)||this._aggInfo&&this._aggInfo[e]||null;if(o&&o.sourceMasterColIndex!=null)return o.sourceMasterColIndex;const t=this.fromFacetToMasterColumnName(e);return this.table.columns.indexOf(t)}return this.table.columns.indexOf(e)}return-1}setColumnProp(e,n,o){const t=this._resolveMasterColIndex(e);if(t<0)throw new Error(`setColumnProp: cannot resolve column "${e}"`);const s={...this.columnProps.get(t)||{},[n]:o};return this.columnProps.set(t,s),this}deleteColumnProp(e,n){const o=this._resolveMasterColIndex(e);if(o<0)throw new Error(`deleteColumnProp: cannot resolve column "${e}"`);const t=this.columnProps.get(o);if(!t)return this;const{[n]:r,...s}=t;return this.columnProps.set(o,s),this}getColumnProp(e,n,{followAggregates:o=!0}={}){const t=this._resolveMasterColIndex(e);if(t<0)return;const r=this.columnProps.get(t);return r?r[n]:void 0}getColumnProps(e,{followAggregates:n=!0}={}){const o=this._resolveMasterColIndex(e);if(o<0)return null;const t=this.columnProps.get(o);return t?{...t}:null}setColumnProps(e,n={},{merge:o=!0}={}){const t=this._resolveMasterColIndex(e);if(t<0)throw new Error(`setColumnProps: cannot resolve column "${e}"`);const r=this.columnProps.get(t)||{};return this.columnProps.set(t,o?{...r,...n}:{...n}),this}getRowCount(){return this.isVirtual?this.virtualRows?this.virtualRows.length:0:this.rowMap.length}getColumnCount(){return this.colMap.length}getColumnNames(){return this.colNames}containsColumn(e){return this.getColumnNames().indexOf(e)>=0}getColumnName(e){return this.colNames[e]}getRow(e){if(this.isVirtual)return this.virtualRows[e];const n=this.rowMap[e],o=this.table.data[n],t={};
23return this.colMap.forEach((r,s)=>{const i=this.colNames[s];t[i]=o[r]}),t}getColumn(e){const n=typeof e=="number"?this.getColumnName(e):e;if(this.isVirtual)return this.virtualRows&&this.virtualRows.length>0&&!(n in this.virtualRows[0])?null:(this.virtualRows||[]).map(r=>r[n]);const o=typeof e=="number"?e:this.colNames.indexOf(e);if(o===-1||o==null)return null;const t=this.colMap[o];return t==null?null:this.rowMap.map(r=>this.table.data[r][t])}getData(e,n){if(this.isVirtual){const s=typeof n=="number"?this.getColumnName(n):n,i=this.virtualRows[e];if(!i||!(s in i))throw new Error(`Column name not found: "${s}"`);return i[s]}const o=typeof n=="number"?n:this._colIndexByName?.get(n)??this.colNames.indexOf(n);if(o<0)throw new Error(`Column name not found: "${n}"`);const t=this.rowMap[e],r=this.colMap[o];return this.table.data[t][r]}filterRows(e,n=null,o=!0){const t=new I({table:this.table,parent:this});if(this.isVirtual){const r=[],s=[];for(let i=0;i<this.getRowCount();i++){const a=this.getRow(i),l=!!e(a,i);(o&&l||!o&&!l)&&(r.push(this.virtualRows[i]),this.virtualMemberLinks&&s.push(this.virtualMemberLinks[i]))}t.isVirtual=!0,t.virtualRows=r,t.virtualMemberLinks=this.virtualMemberLinks?s:null}else{const r=this.rowMap.filter((s,i)=>o?e(this.getRow(i),i):!e(this.getRow(i),i));t.rowMap=r}return t.operations.push(n||(o?"kept rows where predicate is true":"removed rows where predicate is true")),t._rebuildIndexCaches(),t}filterToMasterIndices(e,n="filter:keep by master set"){if(this.isVirtual)return console.error("filterToMasterIndices: call this on a base (non-virtual) facet."),this;const o=new I({table:this.table,parent:this}),t=this.rowMap??this.table.data.map((r,s)=>s);o.rowMap=[];for(let r=0;r<t.length;r++){const s=t[r];e.has(s)&&o.rowMap.push(s)}return o.operations.push(n),o._rebuildIndexCaches(),o}removeMasterIndices(e,n="filter:remove by master set"){if(this.isVirtual)return console.error("removeMasterIndices: call this on a base (non-virtual) facet."),this;const o=new I({table:this.table,parent:this}),t=this.rowMap??this.table.data.map((r,s)=>s);o.rowMap=[];for(let r=0;r<t.length;r++){const s=t[r];e.has(s)||o.rowMap.push(s)}return o.operations.push(n),o._rebuildIndexCaches(),o}filterColumns(e,n=null,o=!0){const t=this.colMap.map((a,l)=>({i:l,name:this.colNames[l],masterColIndex:a}));let r;typeof e=="function"?r=t.filter(a=>o?e(a.name,a.i):!e(a.name,a.i)):r=t.filter(a=>o?e.includes(a.name):!e.includes(a.name));const s=new I({table:this.table,parent:this});s.colMap=r.map(a=>a.masterColIndex),s.colNames=r.map(a=>a.name),s.columnTypes={},r.forEach(a=>s.columnTypes[a.name]=this.columnTypes[a.name]),s.ordinals={},r.forEach(a=>s.ordinals[a.name]=this.ordinals[a.name]);let i;return typeof e=="function"?i=o?"kept columns where predicate is true":"removed columns where predicate is true":i=o?`showing columns: ${r.map(a=>a.name).join(", ")}`:`removed columns: ${t.filter(a=>!r.includes(a)).map(a=>a.name).join(", ")}`,s.operations.push(n||i),s._rebuildIndexCaches(),s}renameColumns(e,n=null){const o=Object.entries(e).filter(([s,i])=>s!==i&&this.colNames.includes(s));if(o.length===0)return this;const t=new I({table:this.table,parent:this});t.colNames=t.colNames.map(s=>e[s]??s);for(const[s,i]of o)t.columnTypes[s]!==void 0&&(t.columnTypes[i]=t.columnTypes[s],delete t.columnTypes[s]),t.ordinals[s]!==void 0&&(t.ordinals[i]=t.ordinals[s],delete t.ordinals[s]);this.isVirtual&&this.virtualRows&&(t.isVirtual=!0,t.virtualRows=this.virtualRows.map(s=>{const i={...s};for(const[a,l]of o)a in i&&(i[l]=i[a],delete i[a]);return i}),t.virtualMemberLinks=this.virtualMemberLinks?this.virtualMemberLinks.slice():null);const r=o.map(([s,i])=>`${s}→${i}`).join(", ");return t.operations.push(n||`renamed columns: ${r}`),t._rebuildIndexCaches(),t}sortRows(e,n=null){const o=this.getRowCount(),t=Array.from({length:o},(a,l)=>l),r=t.map(a=>this.getRow(a)),s=t.sort((a,l)=>e(r[a],r[l])),i=new I({table:this.table,parent:this});return this.isVirtual?(i.isVirtual=!0,i.virtualRows=s.map(a=>this.virtualRows[a]),i.virtualMemberLinks=this.virtualMemberLinks?s.map(a=>this.virtualMemberLinks[a]):null):i.rowMap=s.map(a=>this.rowMap[a]),i.operations.push(n||"sorted rows using custom comparator"),i._lastSortKind="predicate",i._sortedColumns=[],i._rebuildIndexCaches(),i}sortRowsBy(e,n=[],o=null){for(Array.isArray(e)||(e=[e]),Array.isArray(n)||(n=[n]);n.length<e.length;)n.push("asc");const t=e.map(l=>typeof l=="number"?this.getColumnName(l):l),r=(l,d)=>{for(let h=0;h<t.length;h++){const m=t[h],g=n[h]===!0||n[h]==="asc",u=l[m],p=d[m];if(u==null&&p!=null)return g?-1:1;if(p==null&&u!=null)return g?1:-1;if(!(u==null&&p==null)){if(u<p)return g?-1:1;if(u>p)return g?1:-1}}return 0},s=this.sortRows(r),a=`sorted ${t.map((l,d)=>`${n[d]===!0||n[d]==="asc"?"asc":"desc"} by ${l}`).join(", ")}`;return s.operations.push(o||a),s._lastSortKind="columns",s._sortedColumns=t.map((l,d)=>({columnName:l,dir:n[d]===!0||n[d]==="asc"?"asc":"desc"})),s}sortColumns(e,n=null){const o=new I({table:this.table,parent:this}),r=this.colMap.map((i,a)=>({name:this.colNames[a],index:a,master:i})).sort((i,a)=>e(i.name,a.name,i.index,a.index));return o.colMap=r.map(i=>i.master),o.colNames=r.map(i=>i.name),o.operations.push(n||"sorted columns using custom comparator"),o._rebuildIndexCaches(),o}moveColumn(e,n,o=null){const t=new I({table:this.table,parent:this}),r=typeof e=="number"?e:this.colNames.indexOf(e);if(r===-1)return this;const s=Math.max(0,Math.min(this.colMap.length-1,r+n)),i=[...this.colMap],a=[...this.colNames],[l]=i.splice(r,1),[d]=a.splice(r,1);i.splice(s,0,l),a.splice(s,0,d),t.colMap=i,t.colNames=a;const h=`moved column ${d} from index ${r} to ${s}`;return t.operations.push(o||h),t._rebuildIndexCaches(),t}addColumns(e,n,o=null){if(this.isVirtual)return console.error("addColumns: not allowed on a virtual (grouped) facet. Do this on a base facet."),this;const t=new I({table:this.table,parent:this}),r=this.getRowCount();if(!Array.isArray(e)||!Array.isArray(n)||e.length!==n.length)throw new Error("columnNames and columnsValues must be arrays of the same length.");e.forEach((a,l)=>{if(n[l].length!==r)throw new Error(`Column "${a}" must have ${r} values, but got ${n[l].length}`);if(this.colNames.includes(a))throw new Error(`Column "${a}" already exists in this facet.`)});const s=[];for(let a=0;a<e.length;a++){let l=e[a],d=1;for(;this.table.columns.includes(l);)l=`${e[a]}_${d++}`;s.push(l),t.table.columns.push(l);const h=t.table.columns.length-1;t.table.columnOrigins||(t.table.columnOrigins=new Map),t.table.columnOrigins.set(h,this.id);for(let g=0;g<r;g++){const u=t.fromFacetToMasterRow(g);t.table.data[u].push(n[a][g])}
23t.colMap.push(h),t.colNames.push(l),t.columnTypes[l]=b.inferType(n[a]);const m=t._resolveDefaultAggregator(l);t.setColumnProps(l,{aggregator:m,_aggExplicit:!1})}const i=`added columns: ${s.join(", ")}`;return t.operations.push(o||i),t._rebuildIndexCaches(),t}addRows(e,n=null){if(this.isVirtual)return console.error("addRows: not allowed on a virtual (grouped) facet. Do this on a base facet."),this;const o=new I({table:this.table,parent:this}),t=this.colNames,r=t.map(a=>this.table.columns.indexOf(a)),s=[];o.table.rowOrigins||(o.table.rowOrigins=new Map);for(const a of e){const l=this.table.columns.map(()=>null);for(let h=0;h<t.length;h++){const m=t[h],g=r[h];l[g]=a[m]!==void 0?a[m]:null}o.table.data.push(l);const d=o.table.data.length-1;o.table.rowOrigins.set(d,o.id),s.push(d)}o.rowMap=[...o.rowMap,...s];const i=`added ${e.length} rows`;return o.operations.push(n||i),o._rebuildIndexCaches(),o}groupBy(e,n={},o=null){if(!Array.isArray(e)||!e.length)throw new Error("groupBy: groupColumns must be a non-empty array of column names");const t=new I({table:this.table,parent:this}),r=this.colNames.slice(),s=new Set(e),i=u=>e.map(p=>u[p]).join("||"),a=new Map;for(let u=0;u<this.getRowCount();u++){const p=this.getRow(u),f=i(p);a.has(f)||a.set(f,{rows:[],masters:[]});const y=a.get(f);if(y.rows.push(p),this.isVirtual&&Array.isArray(this.virtualMemberLinks)){const C=this.virtualMemberLinks[u]||[];C.length&&y.masters.push(...C)}else{const C=this.fromFacetToMasterRow(u);C!==void 0&&y.masters.push(C)}}const l=r.map((u,p)=>{const f=this.colMap[p];if(s.has(u))return{kind:"group",origName:u,displayName:u,masterColIndex:f,spec:null,ordinalOrder:this.ordinals&&this.ordinals[u]?this.ordinals[u].slice():void 0};let y=null;if(n&&n[u]&&typeof n[u]=="object"&&n[u].id&&(y={...n[u]}),!y){const x=this.getAggregator(u);x&&x.id&&(y={...x})}y||(y={id:this._resolveDefaultAggregator(u).id});let C=b.getAggregatorById(y.id);C||(C=b.getAggregatorById("mode")),typeof y.fn=="function"?C={...C,id:"custom",label:y.label||"custom",fn:y.fn}:y.label&&(C={...C,label:y.label});const w=`${u} (${C.label||C.id})`,v=(C.resultType||this.getColumnType(u)||null)==="ordinal"&&this.ordinals&&this.ordinals[u]?this.ordinals[u].slice():void 0;return{kind:"agg",origName:u,displayName:w,masterColIndex:f,spec:C,ordinalOrder:v}}),d=[],h=[];for(const{rows:u,masters:p}of a.values()){const f={};for(const y of l)if(y.kind==="group")f[y.displayName]=u[0][y.origName];else{const C=u.map(w=>w[y.origName]).filter(w=>w!=null);f[y.displayName]=y.spec.fn(C,{ordinalOrder:y.ordinalOrder,column:y.origName})}d.push(f),p&&p.length&&h.push(Array.from(new Set(p)))}const m=l.map(u=>u.displayName);t.colNames=m;const g=new Map(l.map(u=>[u.displayName,u]));t.colMap=m.map(u=>g.get(u).masterColIndex),t.columnTypes={};for(const u of l)t.columnTypes[u.displayName]=u.kind==="agg"?u.spec.resultType||this.getColumnType(u.origName)||null:this.getColumnType(u.origName);t.ordinals={};for(const u of l)u.kind==="agg"&&u.spec.resultType==="ordinal"&&u.ordinalOrder&&(t.ordinals[u.displayName]=u.ordinalOrder.slice());t.isVirtual=!0,t.virtualRows=d,t.virtualMemberLinks=h.length?h:null,t._groupByColumns=e.slice(),t._aggInfo={},t.aggColumnProvenance=new Map;for(const u of l)u.kind==="agg"&&(t._aggInfo[u.displayName]={kind:u.spec.id,source:u.origName,tooltip:typeof u.spec.tooltip=="function"?u.spec.tooltip():`Aggregator: ${u.spec.label||u.spec.id}`},t.aggColumnProvenance.set(u.displayName,{sourceMasterColIndex:u.masterColIndex,agg:u.spec.id}));t._dispToBaseName=new Map;for(const u of l)t._dispToBaseName.set(u.displayName,u.origName);return t.operations.push(o||`grouped by: ${e.join(", ")}`),t._rebuildIndexCaches(),t}expandMembers(e){if(this.isVirtual)return this.virtualMemberLinks&&this.virtualMemberLinks[e]?this.virtualMemberLinks[e]:[];const n=this.fromFacetToMasterRow(e);return n==null?[]:[n]}reorderColumns(e,n=null){if(!Array.isArray(e))throw new Error("reorderColumns expects an array of column names.");const o=this.colNames.slice();for(const l of e)if(!o.includes(l))throw new Error(`Column "${l}" is not present in this facet.`);const t=new Set(e),r=o.filter(l=>!t.has(l)),s=[...e,...r],i=new I({table:this.table,parent:this});
23return i.colNames=s,i.colMap=s.map(l=>{const d=this.colNames.indexOf(l);return this.colMap[d]}),i.operations.push(n||"reordered columns"),i._rebuildIndexCaches(),i}reorderRowsByMasterIndices(e,n="reordered (Down)"){if(this.isVirtual)throw new Error("reorderRowsByMasterIndices: call on base facet");const o=new I({table:this.table,parent:this}),t=new Set(this.rowMap??this.table.data.map((s,i)=>i)),r=new Set;o.rowMap=[];for(const s of e)!r.has(s)&&t.has(s)&&(r.add(s),o.rowMap.push(s));return o.operations.push(n),o._rebuildIndexCaches(),o}_rebuildIndexCaches(){if(this._rowIndexByMaster=null,!this.isVirtual&&Array.isArray(this.rowMap)){this._rowIndexByMaster=new Map;for(let e=0;e<this.rowMap.length;e++)this._rowIndexByMaster.set(this.rowMap[e],e)}if(this._colIndexByName=new Map,Array.isArray(this.colNames))for(let e=0;e<this.colNames.length;e++)this._colIndexByName.set(this.colNames[e],e);if(this._facetIndexByMasterCol=new Map,Array.isArray(this.colMap))for(let e=0;e<this.colMap.length;e++)this._facetIndexByMasterCol.set(this.colMap[e],e)}getMasterIndexAtRow(e){return this.isVirtual?void 0:this.rowMap[e]}_resolveDefaultAggregator(e){const n=this.getColumnType(e),o=n==="id"?"count":n==="numeric"?"mean":n==="ordinal"?"median":n==="categorical"?"mode":typeof(this.getColumn(e)||[]).find(s=>s!=null)=="number"?"mean":"mode",t=b.getAggregatorById(o);return t||b.getAggregatorById("mode")}toPlainTable(){const e=this.getColumnNames().slice(),n=this.getRowCount(),o=Array.from({length:n},(t,r)=>e.map(s=>this.getData(r,s)));return{columns:e,data:o}}toDelimited(e="csv",n={}){const o=n.includeHeader!==!1,t=n.delimiter||(e==="tsv"?"	":","),r=this.getColumnNames(),s=a=>{if(a==null)return"";const l=String(a);return l.includes(t)||l.includes('"')||l.includes(`
24`)||l.includes("\r")?`"${l.replace(/"/g,'""')}"`:l},i=[];o&&i.push(r.map(s).join(t));for(let a=0;a<this.getRowCount();a++){const l=r.map(d=>this.getData(a,d));i.push(l.map(s).join(t))}return i.join(`
25`)}getId(){return this.id}getParentId(){return this.parent?this.parent.id:null}getHistory(){return this.operations?this.operations.slice():[]}isVirtual(){return!!this.isVirtual}getGroupByColumns(){return this._groupByColumns?this._groupByColumns.slice():void 0}getAggregateProvenance(e){const n=this.aggColumnProvenance?.get(e)||null;return n?{...n}:null}getIsVirtual(){return!!this.isVirtual}sample(e=5,n=null){const o=Array.from({length:Math.min(e,this.getRowCount())},(t,r)=>this.getRow?.(r)||null);return n?o.map(t=>{if(!t||typeof t!="object")return t;const r={};for(const s of n)s in t&&(r[s]=t[s]);return r}):o}}class Y{constructor(e,n){this.columns=e,this.data=n}static fromIndexed(e){if(!e||typeof e!="object")throw new Error("DataTable.fromIndexed: expected an object like { columns, data }");const{columns:n,data:o}=e;if(!Array.isArray(n)||!Array.isArray(o))throw new Error("DataTable.fromIndexed: expected { columns: string[], data: any[][] }");return new Y(n,o)}static async loadIndexed(e,{fetchFn:n=fetch,signal:o}={}){if(typeof e!="string"||!e.length)throw new Error("DataTable.loadIndexed: expected a non-empty url");const t=await n(e,{signal:o});if(!t.ok)throw new Error(`DataTable.loadIndexed: failed to fetch ${e} (${t.status})`);const r=await t.json();return Y.fromIndexed(r)}static async loadIndexedSharded(e,{fetchFn:n=fetch,signal:o,onProgress:t=null}={}){if(typeof e!="string"||!e.length)throw new Error("DataTable.loadIndexedSharded: expected a non-empty manifestUrl");const r=await n(e,{signal:o});if(!r.ok)throw new Error(`DataTable.loadIndexedSharded: failed to fetch ${e} (${r.status})`);const s=await r.json(),i=s.shardUrls||s.shards||s.dataShards||[];if(!Array.isArray(i)||i.length===0)throw new Error("DataTable.loadIndexedSharded: manifest missing shardUrls/shards");const a=(()=>{try{const m=typeof window<"u"&&window.location?window.location.href:"http://localhost/";return new URL(e,m).toString()}catch{return e}})(),l=m=>{if(typeof m!="string")return m;try{return new URL(m,a).toString()}catch{return m}};let d=s.columns;if(!d&&s.columnsUrl){const m=l(s.columnsUrl),g=await n(m,{signal:o});if(!g.ok)throw new Error(`DataTable.loadIndexedSharded: failed to fetch ${m} (${g.status})`);const u=await g.json();d=u.columns||u}if(!Array.isArray(d))throw new Error("DataTable.loadIndexedSharded: manifest missing columns or columnsUrl");const h=[];for(let m=0;m<i.length;m++){const g=l(i[m]),u=await n(g,{signal:o});if(!u.ok)throw new Error(`DataTable.loadIndexedSharded: failed to fetch shard ${g} (${u.status})`);const p=await u.json(),f=Array.isArray(p)?p:p.data;if(!Array.isArray(f))throw new Error(`DataTable.loadIndexedSharded: shard ${g} must be an array or { data: [...] }`);h.push(...f),typeof t=="function"&&t({shardsLoaded:m+1,shardsTotal:i.length,rowsLoaded:h.length})}return new Y(d,h)}static fromObjects(e){if(!e||e.length===0)return new Y([],[]);const n=Object.keys(e[0]),o=e.map(t=>n.map(r=>t[r]));return new Y(n,o)}identityFacet(){return I._fromTable(this)}}class We{constructor(e,n){this.data=e,this.onBrush=n,this.selected=new Set}render(){const e=Math.max(...this.data.map(a=>a.count)),n=document.createElement("div");n.className="sorter-histogram";const o=this.data.length,t=0,r=0,s=o>20?0:o>10?1:2;n.style.gap=`${t}px`;const i=this.data.totalCount||this.data.reduce((a,l)=>a+l.count,0);return this.data.forEach((a,l)=>{const d=document.createElement("div");d.className="histogram-bar-wrapper",d.style.padding=`0 ${r}px`;const h=document.createElement("div");h.className="histogram-bar-hitbox";const m=a.label||_e(a.range),g=a.count||0,u=i>0?(g/i*100).toFixed(1):"0.0";h.title=`${m} (n=${g}, ${u}%)`,h.style.padding=`0 ${s}px`;const p=document.createElement("div");p.className="histogram-bar",p.style.height=`${a.count/e*100}%`,h.appendChild(p);const f=document.createElement("div");f.className="histogram-bar-label";const y=a.label||_e(a.range);f.textContent=y,f.title=y,d.appendChild(h),this.data.length<=10&&d.appendChild(f),h.addEventListener("click",()=>
25{if(this.selected.has(l)?(this.selected.delete(l),h.classList.remove("selected")):(this.selected.add(l),h.classList.add("selected")),typeof this.onBrush=="function"){const C=x=>{for(let M of this.selected){const P=this.data[M];if(P.label!==void 0&&x+""===P.label)return!0;if(Array.isArray(P.range)&&typeof x=="number"){const j=M===this.data.length-1;if(x>=P.range[0]&&(j||x<P.range[1]))return!0}}return!1};let w=[],N=[];for(let x of this.selected){const M=this.data[x];M.label!==void 0&&w.push(M.label),Array.isArray(M.range)&&N.push(M.range)}let v="";w.length&&N.length?v=`Values in categories: ${w.join(", ")} or in ranges: ${N.map(x=>`[${x[0]}, ${x[1]})`).join(", ")}`:w.length?v=`Values in categories: ${w.join(", ")}`:N.length?v=`Values in ranges: ${N.map(x=>`[${x[0]}, ${x[1]})`).join(", ")}`:v="No values selected",this.onBrush(C,[...this.selected],v)}}),n.appendChild(d)}),n}clearSelection(e=!1){if(this.selected.clear(),document.querySelectorAll(".histogram-bar-hitbox.selected").forEach(o=>o.classList.remove("selected")),!e&&typeof this.onBrush=="function"){const o=()=>!1;this.onBrush(o,[])}}}function _e(c){if(!Array.isArray(c)||c.length!==2)return"";const[e,n]=c,o=Me(e),t=Me(n);return o.suffix===t.suffix?`${o.value}–${t.value}${o.suffix}`:`${o.value}${o.suffix}–${t.value}${t.suffix}`}function Me(c){return c>=1e6?{value:Re(c/1e6),suffix:"m"}:c>=1e3?{value:Re(c/1e3),suffix:"k"}:{value:c,suffix:""}}function Re(c){return Number.isInteger(c)?c:c.toFixed(1)}const pe="http://www.w3.org/2000/svg",Ne={save:[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"}],["path",{d:"M17 21v-7H7v7"}],["path",{d:"M7 3v5h8"}]],filter:[["path",{d:"M22 3H2l8 9.46V19l4 2v-8.54z"}]],undo:[["path",{d:"M9 14 4 9l5-5"}],["path",{d:"M4 9h10.5a5.5 5.5 0 0 1 0 11H11"}]],redo:[["path",{d:"m15 14 5-5-5-5"}],["path",{d:"M20 9H9.5a5.5 5.5 0 0 0 0 11H13"}]],reset:[["path",{d:"M21 12a9 9 0 1 1-2.64-6.36"}],["path",{d:"M21 3v6h-6"}]],settings:[["path",{d:"M20 7h-9"}],["path",{d:"M14 17H5"}],["circle",{cx:"17",cy:"17",r:"3"}],["circle",{cx:"7",cy:"7",r:"3"}]],map:[["path",{d:"M14.1 5.55a2 2 0 0 0-1.8 0L6.66 8.38a2 2 0 0 1-1.79 0L3.45 7.67A1 1 0 0 0 2 8.56v10.88a1 1 0 0 0 .55.89l2.31 1.16a2 2 0 0 0 1.79 0l5.66-2.83a2 2 0 0 1 1.79 0l5.45 2.72a1 1 0 0 0 1.45-.89V9.61a1 1 0 0 0-.55-.89z"}],["path",{d:"M7 8.5v12"}],["path",{d:"M14 5.5v12"}]],tag:[["path",{d:"M12.59 2.59A2 2 0 0 0 11.17 2H4a2 2 0 0 0-2 2v7.17a2 2 0 0 0 .59 1.42l8.7 8.7a2.43 2.43 0 0 0 3.42 0l6.58-6.58a2.43 2.43 0 0 0 0-3.42z"}],["circle",{cx:"7.5",cy:"7.5",r:".5",fill:"currentColor"}]],eye:[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"}],["circle",{cx:"12",cy:"12",r:"3"}]],eyeOff:[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"}],["path",{d:"m2 2 20 20"}]],chevronLeft:[["path",{d:"m15 18-6-6 6-6"}]],chevronRight:[["path",{d:"m9 18 6-6-6-6"}]]};function X(c,{size:e=16,title:n=null}={}){const o=document.createElementNS(pe,"svg");if(o.setAttribute("viewBox","0 0 24 24"),o.setAttribute("width",String(e)),o.setAttribute("height",String(e)),o.setAttribute("fill","none"),o.setAttribute("stroke","currentColor"),o.setAttribute("stroke-width","2"),o.setAttribute("stroke-linecap","round"),o.setAttribute("stroke-linejoin","round"),o.setAttribute("aria-hidden",n?"false":"true"),o.setAttribute("focusable","false"),o.classList.add("sorter-table-icon"),n){const t=document.createElementNS(pe,"title");t.textContent=n,o.appendChild(t)}for(const[t,r]of Ne[c]||Ne.settings){const s=document.createElementNS(pe,t);for(const[i,a]of Object.entries(r))s.setAttribute(i,a);o.appendChild(s)}return o}class Ye{constructor({container:e,facet:n,onSelectionChange:o,onSaveFacet:t,onSortIntent:r,isSpatialColumn:s=null,onHowSetChanged:i=null,onColumnPropChange:a=null,onVisualizeChanged:l=null}){this.container=e,this.facet=n,this.columns=n.getColumnNames(),this.onSelectionChange=o||(()=>{}),this.onSaveFacet=t||(()=>{}),this.onSortIntent=r||null,this.onColumnPropChange=typeof a=="function"?a:null,this.overviewStats=null,this.headerRow=null,this.bodyRow=null,this.isSpatialColumn=typeof s=="function"?s:()=>!1,this.onHowSetChanged=typeof i=="function"?i:()=>{},this.howSet=new Set,this.onVisualizeChanged=typeof l=="function"?l:()=>{},this.selectedRows=new Set,this.lastSelectedRowIndex=null,this.selectionDescription=null,this.histograms=[],this.hiddenColumns=new Set,this.visualizeColumns=new Set,this.sortedColumns=[],this.predicateSortActive=!1,this.onFacetChanged=null,this.columnWidth="110px",this.headerControlsVisible=!1,this.render()}getMapEncodingForColumn(e){const n=this.columns.indexOf(e);let o=[];try{o=n>=0?this.facet.getColumn(n):[]}catch{o=[]}const r=this.facet.getColumnType(e)||b.inferType(o),s=[...new Set((o||[]).filter(f=>f!=null&&f!==""))],i=s.map(f=>String(f).trim().toLowerCase()),a=new Set(["0","1","true","false","yes","no"]),l=s.length>0&&s.length<=2&&i.every(f=>a.has(f)),d=/\b(epc|energy rating)\b/i.test(String(e||"")),h=["A","B","C","D","E","F","G","U"],m=l?"boolean":d?"ordinal":r==="ordinal"||r==="categorical"?r:r==="numeric"?"numeric":"unsupported",g=m==="ordinal"?this.facet.getOrdinalOrder(e)||(d?h:null):null,u=["No","Yes"],p=m==="numeric"?null:m==="ordinal"&&g?g:m==="boolean"?u:s.slice().sort((f,y)=>String(f).localeCompare(String(y)));return{field:e,type:m,mode:m==="numeric"?"magnitude":"composition",aggregation:m==="numeric"?"sum":"count",uniqueCount:s.length,categories:p,order:m==="ordinal"?g:m==="boolean"?u:null}}getMapEncodingsForVisualizeColumns(){return Array.from(this.visualizeColumns||[]).map(e=>this.getMapEncodingForColumn(e)).filter(e=>e.type!=="unsupported")}setFacet(e,n=!1,o="replace"){if(this.facet=e,this.columns=e.getColumnNames(),Array.isArray(e._sortedColumns)?this.sortedColumns=e._sortedColumns.map(t=>({columnName:t.columnName,facetColIndex:this.columns.indexOf(t.columnName),dir:t.dir,buttonEl:null})).filter(t=>t.facetColIndex>=0):this.sortedColumns=[],this.overviewStats&&this.renderOverviewStats(),n&&this.renderHeader(),this.renderBody(),this.setPredicateSortActive?.(e?._lastSortKind==="predicate"),typeof this.onFacetChanged=="function")try{this.onFacetChanged(e,o)}catch(t){console.error(t)}}setHeaderControlsVisible(e){this.headerControlsVisible=!!e,this.headerRow&&(this.headerControlsVisible?this.headerRow.classList.remove("collapsed"):this.headerRow.classList.add("collapsed")),this.hiddenColumns&&this.hiddenColumns.size>0&&(this.renderHeader(),this.renderBody())}setPredicateSortActive(e){this.predicateSortActive=!!e,(this.headerRow?.querySelectorAll?.(".sort-toggle")||[]).forEac
25h(o=>{const t=o.querySelector(".sort-icon-up"),r=o.querySelector(".sort-icon-down"),s=o.querySelector(".sort-icon-fx");this.predicateSortActive?(t&&(t.style.display="none"),r&&(r.style.display="none"),s&&(s.style.display="inline"),o.title="Sorted by custom predicate"):(t&&(t.style.display=""),r&&(r.style.display=""),s&&(s.style.display="none"))})}setSelectedRows(e,n=null){this.selectionDescription=n;const o=[];for(const t of e){const r=typeof this.facet.expandMembers=="function"?this.facet.expandMembers(t):[this.facet.fromFacetToMasterRow(t)];o.push(...r)}this.selectedRows=new Set(o),this.lastSelectedRowIndex=e.length>0?e[e.length-1]:null,this.renderBody(),typeof this.onSelectionChange=="function"&&this.onSelectionChange([...this.selectedRows])}getSelectedRows(){if(!this.facet||!this.selectedRows||this.selectedRows.size===0)return[];const e=this.facet,n=[],o=e.getRowCount?.()??0;for(let t=0;t<o;t++)(typeof e.expandMembers=="function"?e.expandMembers(t):[e.fromFacetToMasterRow(t)]).some(s=>this.selectedRows.has(s))&&n.push(t);return n}renderOverviewStats(){this.overviewStats||(this.overviewStats=document.createElement("div"),this.overviewStats.className="table-overview-stats",this.overviewStats.style.cssText=`
26                padding: 4px 12px;
27                background: #f8f9fa;
28                border-bottom: 1px solid #eee;
29                font-size: 13px;
30                color: #495057;
31                display: flex;
32                gap: 12px;
33                align-items: center;
34            `);const e=this.facet?.getRowCount?.()??0,n=this.columns?.length??0,o=this.selectedRows?this.selectedRows.size:0,t=[`<strong>${e}</strong> rows`,`<strong>${n}</strong> cols`];return o>0&&t.push(`<strong style="color:#28a745">${o}</strong> selected`),this.overviewStats.innerHTML=t.join(' <span style="color:#dee2e6">|</span> '),this.overviewStats.title=`Rows: ${e}
35Columns: ${n}${o?`
36Selected: ${o}`:""}`,this.overviewStats}createHistogram(e,n){let o=typeof e=="number"&&e>=0?this.facet.fromMasterToFacetColumn(e):n;if(o<0){const u=document.createElement("div");return u.textContent="N/A",u.className="histogram-na",u}const t=this.facet.getColumnName(o),r=this.facet.getColumn(o),s=this.facet.getColumnType(t);if(s==="id"||s==="timeseries"){const u=document.createElement("div");return u.textContent="N/A",u.className="histogram-na",u}const i=new Set(["0","1","true","false","yes","no"]),a=(r||[]).filter(u=>u!=null&&u!==""),l=new Set(a.map(u=>String(u).trim().toLowerCase())),d=l.size>0&&l.size<=2&&[...l].every(u=>i.has(u));let h;if(d)h=b.getCategoricalHistogram(a);else if(!s)h=b.getHistogram(r);else if(s==="numeric")h=b.getNumericalHistogram(r);else if(s==="categorical")h=b.getCategoricalHistogram(r);else if(s==="ordinal"){const u=this.facet.getOrdinalOrder&&this.facet.getOrdinalOrder(t);h=u?b.getOrdinalHistogram(r,u):b.getCategoricalHistogram(r)}else h=b.getCategoricalHistogram(r);const m=h.reduce((u,p)=>u+p.count,0);h.totalCount=m;const g=new We(h,(u,p,f)=>{const y=this.facet.getColumn(o).map((C,w)=>[C,w]).filter(([C])=>u(C)).map(([C,w])=>w);this.setSelectedRows(y,this.facet.getColumnName(o)+" has "+f)});return this.histograms.push(g),g.render()}render(){this.container.innerHTML="";const e=this.renderOverviewStats();this.container.appendChild(e),this.bodyScrollContainer=document.createElement("div"),this.bodyScrollContainer.classList.add("sorter-table-scroll");const n=document.createElement("div");n.classList.add("sorter-table-inner"),this.headerRow=document.createElement("div"),this.headerRow.classList.add("sorter-table-header"),this.bodyContent=document.createElement("div"),this.bodyContent.classList.add("sorter-table-content"),this.bodyContent.style.position="relative",this.bodyContent.style.height=`${this.facet.getRowCount()*24}px`,this.bodyRow=document.createElement("div"),this.bodyRow.classList.add("sorter-table-body"),this.bodyRow.style.position="absolute",this.bodyRow.style.left="0",this.bodyRow.style.right="0",this.bodyRow.style.display="flex",this.bodyContent.appendChild(this.bodyRow),n.appendChild(this.headerRow),n.appendChild(this.bodyContent),this.bodyScrollContainer.appendChild(n),this.container.appendChild(this.bodyScrollContainer),this.bodyScrollContainer.addEventListener("scroll",()=>this.renderBody()),this.renderHeader(),this.renderBody()}
36renderHeader(){if(!this.headerRow)return;this.headerControlsVisible===!1?this.headerRow.classList.add("collapsed"):this.headerRow.classList.remove("collapsed"),this.overviewStats&&this.renderOverviewStats(),this.histograms=[],this.headerRow.innerHTML="";const e=this.columnWidth,n=(o,t)=>{t&&t.nodeType===Node.ELEMENT_NODE&&o.appendChild(t)};for(let o=0;o<this.columns.length;o++){const t=this.columns[o],r=this.hiddenColumns.has(t);if(r&&!this.headerControlsVisible)continue;const s=this.facet.fromFacetToMasterColumn(o),i=document.createElement("div");i.classList.add("sorter-table-column","sorter-table-header-col"),r&&i.classList.add("sorter-column-hidden"),i.style.width=e;const a=document.createElement("div");a.className="sorter-table-header-label-row";const l=document.createElement("div");l.classList.add("sorter-table-header-label"),l.textContent=t,l.title=t,l.setAttribute("tabindex","0"),l.style.cursor="pointer";const d=(this.sortedColumns||[]).find(f=>f.columnName===t);if(d){const f=document.createElement("span");f.className="header-sort-indicator",f.textContent=d.dir==="asc"?" ▲":" ▼",f.style.marginLeft="6px",f.style.fontSize="10px",f.setAttribute("aria-hidden","true"),l.appendChild(f);const y=this.sortedColumns||[];if(y.length>1){const C=y.findIndex(w=>w.columnName===t);if(C>=0){const w=document.createElement("span");w.className="sort-priority-badge",w.textContent=String(C+1),w.setAttribute("aria-hidden","true"),l.appendChild(w)}}l.setAttribute("aria-sort",d.dir==="asc"?"ascending":"descending")}else l.setAttribute("aria-sort","none");l.addEventListener("click",f=>{try{f.preventDefault(),f.stopPropagation();const y=f.shiftKey,C=(this.sortedColumns||[]).find(N=>N.columnName===t),w=N=>{let v=N;for(;v&&v._sortedColumns&&v._sortedColumns.length>0;)v=v.parent;return v||(N&&N.table?N.table.identityFacet():N)};if(y){const N=(this.sortedColumns||[]).map(M=>M.columnName),v=(this.sortedColumns||[]).map(M=>M.dir==="asc"?"asc":"desc"),x=N.indexOf(t);if(x===-1?(N.push(t),v.push("asc")):v[x]==="asc"?v[x]="desc":(N.splice(x,1),v.splice(x,1)),N.length===0){const M=w(this.facet.parent||this.facet);this.setFacet(M,!0,"header_multi_sort_remove")}else{const M=this.facet.sortRowsBy(N,v,`sorted by ${N.join(",")}`);this.setFacet(M,!0,"header_multi_sort")}}else if((this.sortedColumns||[]).length===1&&C)if(C.dir==="asc"){const v=this.facet.sortRowsBy(t,"desc",`sorted by ${t} desc`);this.setFacet(v,!0,"header_sort_desc")}else{const v=w(this.facet.parent||this.facet);this.setFacet(v,!0,"header_unsort")}else{const v=C&&C.dir==="asc"?"desc":"asc",x=this.facet.sortRowsBy(t,v,`sorted by ${t} ${v}`);this.setFacet(x,!0,"header_sort")}}catch(y){console.error("header sort click failed",y)}}),l.addEventListener("keydown",f=>{(f.key==="Enter"||f.key===" ")&&(f.preventDefault(),l.click())}),a.appendChild(l),i.appendChild(a);const h=document.createElement("div");h.className="column-histogram-wrap";const m=this.createHistogram(s,o);h.appendChild(m);const g=document.createElement("button");g.className="move-toggle column-histogram-move column-histogram-move-left",g.title="Move column left",g.setAttribute("aria-label",`Move ${t} column left`),g.disabled=o===0,g.appendChild(X("chevronLeft",{size:13})),g.addEventListener("click",f=>{if(f.preventDefault(),f.stopPropagation(),!this.facet||typeof this.facet.moveColumn!="function")return;const y=this.facet.moveColumn(o,-1,`moved column ${t} left`);this.setFacet(y,!0,"move_column")}),h.appendChild(g);const u=document.createElement("button");u.className="move-toggle column-histogram-move column-histogram-move-right",u.title="Move column right",u.setAttribute("aria-label",`Move ${t} column right`),u.disabled=o===this.columns.length-1,u.appendChild(X("chevronRight",{size:13})),u.addEventListener("click",f=>{if(f.preventDefault(),f.stopPropagation(),!this.facet||typeof this.facet.moveColumn!="function")return;const y=this.facet.moveColumn(o,1,`moved column ${t} right`);this.setFacet(y,!0,"move_column")}),h.appendChild(u),i.appendChild(h);const p=document.createElement("div");
36p.classList.add("sorter-table-header-controls"),n(p,this.createSortButton?.(o,t)),n(p,this.createGroupButton?.(o,t)),n(p,this.createAggregatorButton?.(o,t)),n(p,this.createVisualizeButton?.(o,t)),n(p,this.createHideButton?.(o,t)),p.childElementCount>0&&i.appendChild(p),this.headerRow.appendChild(i)}this.rebindSortedButtons?.()}createVisualizeButton(e,n){const t=this.getMapEncodingForColumn(n).type,r=t==="unsupported",s=t==="categorical"||t==="ordinal"||t==="boolean",i=document.createElement("button");i.className="stv-visualize-btn",i.style.width="28px",i.style.height="28px",i.style.padding="0",i.style.display="inline-flex",i.style.alignItems="center",i.style.justifyContent="center",i.style.border="1px solid #ddd",i.style.borderRadius="6px",i.style.background="#fff",i.style.cursor="pointer",i.style.fontSize="12px",i.setAttribute("aria-label",s?`Show ${n} categories on map`:`Show ${n} on map`);const a=X(s?"tag":"map",{size:14});if(a.style.pointerEvents="none",i.appendChild(a),r)return i.disabled=!0,i.style.opacity="0.3",i.style.cursor="not-allowed",i.title=`Cannot visualize "${n}" on map (${t||"text"} — too many unique values)`,i;const l=()=>{const d=this.visualizeColumns&&this.visualizeColumns.has(n);d?(i.style.background=s?"#4338ca":"#0f172a",i.style.color="#fff",i.title="Remove from map"):(i.style.background="#fff",i.style.color="#444",i.title=s?`Show "${n}" on map (by category)`:"Show column on map"),i.setAttribute("aria-pressed",d?"true":"false")};return i.addEventListener("click",d=>{d.preventDefault(),d.stopPropagation();try{this.visualizeColumns||(this.visualizeColumns=new Set),this.visualizeColumns.has(n)?this.visualizeColumns.delete(n):this.visualizeColumns.add(n);try{this.onVisualizeChanged(Array.from(this.visualizeColumns),this.getMapEncodingsForVisualizeColumns())}catch{}l()}catch(h){console.error("visualize toggle failed",h)}}),l(),i}createHideButton(e,n){const o=this.hiddenColumns.has(n),t=document.createElement("button");t.className="stv-hide-btn",t.style.width="28px",t.style.height="28px",t.style.padding="0",t.style.display="inline-flex",t.style.alignItems="center",t.style.justifyContent="center",t.style.border="1px solid #ddd",t.style.borderRadius="6px",t.style.background="#fff",t.style.color="#444",t.style.cursor="pointer",t.style.fontSize="12px",t.title=o?`Show "${n}"`:`Hide "${n}"`,t.setAttribute("aria-label",o?`Show ${n} column`:`Hide ${n} column`),t.setAttribute("aria-pressed",o?"true":"false");const r=X(o?"eye":"eyeOff",{size:14});return r.style.pointerEvents="none",t.appendChild(r),t.addEventListener("click",s=>{s.preventDefault(),s.stopPropagation(),this.hiddenColumns.has(n)?this.hiddenColumns.delete(n):this.hiddenColumns.add(n),this.renderHeader(),this.renderBody()}),t}renderBody(){this.overviewStats&&this.renderOverviewStats(),this.bodyContent.style.height=`${this.facet.getRowCount()*24}px`;const e=this.columnWidth,n=24,o=this.facet.getRowCount(),t=this.rowWindowSize||100,r=this.bodyScrollContainer.scrollTop,s=Math.floor(r/n),i=Math.min(o,s+t);this.bodyRow.style.top=`${s*n}px`,this.bodyRow.innerHTML="";for(let a=0;a<this.columns.length;a++){const l=this.facet.getColumnName(a),d=this.hiddenColumns.has(l);if(d&&!this.headerControlsVisible)continue;const h=document.createElement("div");h.classList.add("sorter-table-column"),d&&h.classList.add("sorter-column-hidden"),h.style.width=e,h.style.display="flex",h.style.flexDirection="column";let m=this.facet.getColumnType(l);for(let g=s;g<i;g++){const u=this.facet.getData(g,a),p=document.createElement("div");p.classList.add("sorter-table-cell"),u!=null&&(p.title=String(u)),m==="id"||m==="categorical"||m==="ordinal"?p.textContent=u==null?"":String(u):m==="numeric"?(p.textContent=this.formatValue(u),p.style.textAlign="right"):m==="timeseries"?p.appendChild(Ge(u)):typeof u=="number"?(p.textContent=this.formatValue(u),p.style.textAlign="right"):typeof u=="string"?p.textContent=u:typeof u=="object"&&u!=null?p.textContent=JSON.stringify(u):p.textContent=u==null?"":String(u);const f=g,y=typeof this.facet.expandMembers=="function"?this.facet.expandMembers(f):[this.facet.fromFacetToMasterRow(f)];y.some(w=>this.selectedRows.has(w))&&p.classList.add("selected"),p.addEventListener("click",w=>{const N=w.ctrlKey||w.metaKey;if(w.shiftKey&&this.lastSelectedRowIndex!=null){const[x,M]=[this.lastSelectedRowIndex,f].sort((P,j)=>P-j);for(let P=x;P<=M;P++)(typeof this.facet.expandMembers=="function"?this.facet.expandMembers(P):[this.facet.fromFacetToMasterRow(P)]
36).forEach(oe=>this.selectedRows.add(oe))}else N?(y.every(M=>this.selectedRows.has(M))?y.forEach(M=>this.selectedRows.delete(M)):y.forEach(M=>this.selectedRows.add(M)),this.lastSelectedRowIndex=f):(this.selectedRows.clear(),y.forEach(x=>this.selectedRows.add(x)),this.lastSelectedRowIndex=f);this.selectionDescription=null,this.histograms.map(x=>x.clearSelection(!0)),typeof this.onSelectionChange=="function"&&this.onSelectionChange([...this.selectedRows]),this.renderBody()}),h.appendChild(p)}this.bodyRow.appendChild(h)}}formatValue(e){if(typeof e!="number"||!isFinite(e))return e;const n=Math.abs(e);let o;return n>=1e9?o=(e/1e9).toFixed(2).replace(/\.?0+$/,"")+"b":n>=1e6?o=(e/1e6).toFixed(2).replace(/\.?0+$/,"")+"m":n>=1e3?o=(e/1e3).toFixed(2).replace(/\.?0+$/,"")+"k":o=e.toFixed(2).replace(/\.?0+$/,""),o}}function Ge(c,e,n){const o=document.createElement("div");if(o.style.display="flex",o.style.height="18px",!c||typeof c!="object")return o;const t=Object.keys(c);if(t.length===0)return o;for(const r of t){const s=c[r],i=0,a=document.createElement("div");a.style.height="100%",a.style.width=`${Math.floor(100/t.length)}%`,a.style.backgroundColor=`rgba(118,185,0,${.2+i*.8})`,a.title=`${r}: ${s}`,o.appendChild(a)}return o}class qe{constructor({container:e,initialFacet:n,onSaveFacet:o=()=>{},onVizUpdate:t=null,onSelectionChange:r=null,onFacetChange:s=null}){if(this.container=e,this.currentFacet=n,this.initialFacet=n,this.onSaveFacet=o,this.onSelectionChange=typeof r=="function"?r:()=>{},this.onFacetChange=typeof s=="function"?s:()=>{},this.activeLevel="building",this.sortIntents=new Map,this.onVizUpdate=t,this.identityLevelKey="building",this.viewHistory=[],this.redoHistory=[],this._suspendHistory=!1,this._lastFacet=null,!this.currentFacet)throw new Error("SmartTableView: missing initialFacet/facet");this.selectedMasterIds=new Set,this.howSet=new Set,this.visualizeColumns=new Set,this.headerControlsVisible=!1,this.render(),this._eventLog=[],this.lastUsedAt=Date.now()}get facet(){return this.table&&this.table.facet||this.currentFacet}isSpatialColumn(e){const n=this.facet;return!n||typeof e!="string"||!e.length?!1:!!n.getColumnProp(e,"isSpatial")}render(){this.container.innerHTML="";const e=document.createElement("div");e.className="sorter-table-layout",e.style.height="100%",e.style.width="100%";const n=document.createElement("div");n.className="sorter-sidebar";const o=(r,s,i)=>{const a=document.createElement("button");a.title=r,a.className="stv-btn",a.style.width="30px",a.style.height="30px",a.style.padding="0",a.style.display="inline-flex",a.style.alignItems="center",a.style.justifyContent="center",a.style.border="1px solid #ddd",a.style.borderRadius="6px",a.style.background="#fff",a.style.color="#334155",a.style.cursor="pointer",a.setAttribute("aria-label",r),a.addEventListener("click",d=>i(d));const l=X(s||"settings",{size:15});return l.style.pointerEvents="none",a.appendChild(l),a};n.appendChild(o("Save Facet","save",()=>{const r=this._getSelectedMasterIds(),s=this.table&&this.table.facet?this.table.facet:this.currentFacet;if(s){if(r.size>0){const i=s&&!s.isVirtual?s:this.getBaseFacet?.();if(i&&typeof i.filterToMasterIndices=="function"){const a=i.filterToMasterIndices(r,"saved selected rows");this.onSaveFacet(a);return}}this.onSaveFacet(s)}})),n.appendChild(o("Filter (Click=Keep, Shift=Remove)","filter",r=>r&&r.shiftKey?this.applyDeleteSelection():this.applyKeepSelection())),n.appendChild(o("Undo","undo",()=>this.undo())),n.appendChild(o("Redo","redo",()=>this.redo())),n.appendChild(o("Reset","reset",()=>this.reset())),n.appendChild(o("Toggle Column Buttons (Add to Map / Hide Column)","settings",()=>this.toggleHeaderControls()));const t=document.createElement("div");t.className="sorter-table",t.style.height="100%",t.style.overflow="hidden",e.appendChild(n),e.appendChild(t),this.container.appendChild(e),this.table=new Ye({container:t,facet:this.currentFacet,onSaveFacet:r=>this.onSaveFacet(r),onSelectionChange:r=>{this.selectedMasterIds=new Set(r),this.onSelectionChange(r)},isSpatialColumn:r=>this.isSpatialColumn(r),onHowSetChanged:r=>{this.updateGrouping({howOverride:r,reason:"howset_changed"})},onColumnPropChange:(r,s,i)=>this._applyColumnPropFromFacet(r,s,i),onVisualizeChanged:(r,s=[])=>{this.visualizeColumns=new Set(r);try{this.table.visualizeColumns=new Set(this.visualizeColumns)}catch{}if(typeof this.onVizUpdate=="function")try{this.onVizUpdate(Array.from(this.visualizeColumns),s)}catch(i){console.error("onVizUpdate callback failed",i)}}})}_applyColumnPropFromFacet(e,n,o){try{const t=this.getBaseFacet?.();if(!t)return;const r=this._dispToBaseName(e);
36if(n==="aggregator"&&typeof t.setAggregator=="function"){t.setAggregator(r,o),this.currentFacet&&this.currentFacet.isVirtual===!0||this.activeLevel&&this.activeLevel!==this.identityLevelKey||this.howSet&&this.howSet.size>0?this.updateGrouping({nextLevel:this.activeLevel||this.identityLevelKey,reason:"aggregator_changed",force:!0}):this._setFacetInternal(this.currentFacet,!0,!0,"aggregator_changed");return}typeof t.setColumnProp=="function"&&t.setColumnProp(r,n,o)}catch(t){console.error("STV: _applyColumnPropFromFacet failed",{facetColName:e,key:n,e:t})}}getBaseFacet(){let e=this.table&&this.table.facet?this.table.facet:this.currentFacet;for(;e&&e.isVirtual;)e=e.parent;return e||this.currentFacet}_dispToBaseName(e){const n=this.facet,o=this.getBaseFacet?.();if(!n||!o)return e;const t=typeof n.fromFacetToMasterColumnName=="function"?n.fromFacetToMasterColumnName(e):e;return typeof o.fromMasterToFacetColumnName=="function"&&o.fromMasterToFacetColumnName(t)||t}setFacet(e,n=!0){e&&(this.clearSelection?.(),this.sortIntents=new Map,this.visualizeColumns.clear(),this.howSet.clear(),this.activeLevel="building",this.table&&(this.table.visualizeColumns=new Set,this.table.howSet=new Set),this.updateLevelButtonHighlights(this.activeLevel),this._setFacetInternal(e,n,!1,"data_change"),this._triggerVizUpdate("data_change"))}_setFacetInternal(e,n=!0,o=!0,t="internal"){const r=this.currentFacet;if(this.currentFacet=e,o&&r&&e&&typeof this._copyColumnProps=="function")try{this._copyColumnProps(r,e)}catch(s){console.warn("STV: copy props on setFacet failed",s)}this.table&&(this.table.setFacet(e,n),this.table.visualizeColumns=new Set(this.visualizeColumns),this.table.howSet=new Set(this.howSet)),this.onFacetChange(e,t)}_copyColumnProps(e,n){if(!(!e||!n||!e._columnProps)){n._columnProps||(n._columnProps=new Map);for(const[o,t]of e._columnProps.entries())n._columnProps.set(o,new Map(t))}}_clearSelectionState(){this.selectedMasterIds=new Set,this.table?.setSelectedRows?.([],null),this.table?.histograms?.forEach?.(e=>e?.clearSelection?.(!0))}_pushHistory(e){this._suspendHistory||!e||(this.viewHistory.push(e),this.redoHistory=[])}_applyFacetChange(e,n="facet_change"){if(!e||e===this.currentFacet)return;const o=this.currentFacet;this._pushHistory(o),this._clearSelectionState(),this._setFacetInternal(e,!0,!0,n),this._triggerVizUpdate?.(n)}_getSelectedMasterIds(){return!this.selectedMasterIds||this.selectedMasterIds.size===0?new Set:new Set([...this.selectedMasterIds].map(e=>Number(e)).filter(e=>Number.isFinite(e)))}applyKeepSelection(){const e=this._getSelectedMasterIds();if(!e.size)return;const n=this.facet&&!this.facet.isVirtual?this.facet:this.getBaseFacet?.();if(!n||typeof n.filterToMasterIndices!="function")return;const o=n.filterToMasterIndices(e,"kept selected rows");this._applyFacetChange(o,"keep_selection")}applyDeleteSelection(){const e=this._getSelectedMasterIds();if(!e.size)return;const n=this.facet&&!this.facet.isVirtual?this.facet:this.getBaseFacet?.();if(!n||typeof n.removeMasterIndices!="function")return;const o=n.removeMasterIndices(e,"removed selected rows");this._applyFacetChange(o,"remove_selection")}undo(){if(!this.viewHistory.length)return;const e=this.viewHistory.pop();e&&(this.currentFacet&&this.redoHistory.push(this.currentFacet),this._clearSelectionState(),this._setFacetInternal(e,!0,!0,"undo"),this._triggerVizUpdate?.("undo"))}redo(){if(!this.redoHistory.length)return;const e=this.redoHistory.pop();e&&(this.currentFacet&&this.viewHistory.push(this.currentFacet),this._clearSelectionState(),this._setFacetInternal(e,!0,!0,"redo"),this._triggerVizUpdate?.("redo"))}reset(){this.initialFacet&&this._applyFacetChange(this.initialFacet,"reset")}toggleHeaderControls(){this.headerControlsVisible=!this.headerControlsVisible,this.table&&this.table.setHeaderControlsVisible(this.headerControlsVisible)}}const Ae={uprn:"UPRN",area:"Postcode area",priorityScore:"Priority score",fuelPoorPct:"Fuel poor (%)",imdRank:"IMD rank",epc:"EPC",epcRating:"EPC rating",sqm:"Floor area (m2)",income:"Net annual income",gas:"Mains gas",ashpKW:"ASHP capacity (kW)",pvKW:"PV capacity (kW)",gshpKW:"GSHP capacity (kW)",suitableTech:"Suitable technologies",carbonBaseline:"Carbon baseline",yearUpgraded:"Upgrade year",deployedTech:"Deployed technology",estimatedCost:"Estimated costs",location:"Location",primary_code_description:"Primary code description",primary_description:"Primary description",post_code:"Postcode",household_data_epc_rating:"EPC rating (source)",household_data_epc_property_type:"Property type",household_data_epc_mains_gas_flag:"Mains gas flag",proportion_of_households_fuel_poor:"Households fuel poor (%)",index_of_multiple_deprivation_imd_rank:"IMD rank (raw)",current_energy_rating:"Current EPC rating",current_energy_cost:"Current energy cost",building_area_m2:"Building area (m2)",net_annual_income:"Net annual income",latitude:"Latitude",longitude:"Longitude",ashp_suitability:"ASHP suitable",rooftop_pv_suitability:"Rooftop PV suitable",district_heating_suitability:"District heating suitable",gshp_suitability:"GSHP suitable",hydrogen_boiler_suitability:"Hydrogen boiler suitable",ashp_capacity:"ASHP capacity (kW)",rooftop_pv_capacity:"Rooftop PV capacity (kW)",as
36hp_total_cost:"ASHP total cost",rooftop_pv_total_cost:"Rooftop PV total cost",gshp_total_cost:"GSHP total cost",hydrogen_boiler_total_cost:"Hydrogen boiler total cost",district_heating_total_cost:"District heating total cost",insulation_cavity_wall_suitability:"Cavity wall insulation suitable",insulation_external_wall_suitability:"External wall insulation suitable",insulation_roof_suitability:"Roof insulation suitable",insulation_under_floor_suitability:"Under-floor insulation suitable",insulation_cavity_wall:"Cavity wall state",insulation_external_wall:"External wall state",insulation_roof:"Roof insulation state",insulation_under_floor:"Under-floor insulation state",insulation_cavity_wall_total_cost:"Cavity wall insulation cost",insulation_external_wall_total_cost:"External wall insulation cost",insulation_roof_total_cost:"Roof insulation cost",insulation_under_floor_total_cost:"Under-floor insulation cost",gspName:"GSP",bspName:"BSP",primarySubstation:"Primary substation",primaryHeadroomMva:"Primary headroom (MVA)",primaryDemandMva:"Primary demand (MVA)",secondarySubstation:"Secondary substation",secondaryCapacityMva:"Secondary capacity (MVA)",secondaryPeakLoadMva:"Secondary peak load (MVA)",secondaryHeadroomMva:"Secondary headroom (MVA)",gsp_name:"GSP",gsp_headroom_mva:"GSP headroom (MVA)",gsp_demand_mva:"GSP demand (MVA)",bsp_name:"BSP",bsp_headroom_mva:"BSP headroom (MVA)",bsp_gen_headroom_mva:"BSP generation headroom (MVA)",primary_id:"Primary substation ID",primary_name:"Primary substation",primary_headroom_mva:"Primary headroom (MVA)",primary_demand_mva:"Primary demand (MVA)",secondary_id:"Secondary substation ID",secondary_name:"Secondary substation",secondary_capacity_mva:"Secondary capacity (MVA)",secondary_peak_load_mva:"Secondary peak load (MVA)",secondary_headroom_mva:"Secondary headroom (MVA)",primary_potential_ground_pv_gwh:"Primary ground PV potential (GWh)",primary_potential_ground_pv_mw:"Primary ground PV potential (MW)",primary_potential_wind_gwh:"Primary wind potential (GWh)",primary_potential_wind_mw:"Primary wind potential (MW)",total_demand_kw_in_lsoa:"LSOA demand (kW)",total_generation_kw_in_lsoa:"LSOA generation (kW)",evchargepoints_total_in_grid_max:"EV chargepoints nearby"},Ze=["uprn","area","priorityScore","fuelPoorPct","imdRank","epc","type","sqm","income","gas","primarySubstation","secondarySubstation","secondaryHeadroomMva","secondaryPeakLoadMva","secondaryCapacityMva","primaryHeadroomMva","ashpKW","pvKW","gshpKW","suitableTech","carbonBaseline","upgraded","yearUpgraded","deployedTech"],Qe=new Set(["toid","northing","easting","suitableTech","suitable technologies","district_heating_material_cost","district heating material costs","district_heating_labour_cost","district heating labour costs","uprn_text","uprn text","battery_kw_in_lsoa","battery kW in LSOA","property_type","property type","region_code","region code","gsp_id","gsp id","bsp_id","bsp id","ashp_capacity","ashp capacity","rooftop_pv_capacity","rooftop pv capacity","gshp_capacity","gshp capacity","ashp_total_cost","ashp total cost","rooftop_pv_total_cost","rooftop pv total cost","gshp_total_cost","gshp total cost","hydrogen_boiler_total_cost","hydrogen boiler total cost","district_heating_total_cost","district heating total cost","total_cost","total cost"]),Je=["uprn","area","latitude","longitude","epcRating","primarySubstation","secondarySubstation","secondaryHeadroomMva","technologiesProposed","deploymentYears","interventionsCount","totalCost","totalCarbonSaved","totalDemandChange","firstDeploymentYear","lastDeploymentYear"],Xe={uprn:"UPRN",area:"Postcode area",latitude:"Latitude",longitude:"Longitude",epcRating:"EPC rating",technologiesProposed:"Technologies proposed",deploymentYears:"Deployment years",interventionsCount:"Interventions",totalCost:"Total cost",totalCarbonSaved:"Total carbon saved",totalDemandChange:"Total demand change",firstDeploymentYear:"First deployment year",lastDeploymentYear:"Last deployment year"},et=["diffType","uprn","area","epcRating","primarySubstation","secondarySubstation","currentStatus","comparisonStatus","currentTechnologies","comparisonTechnologies","currentYears","comparisonYears","yearDelta","currentTotalCost","comparisonTotalCost","costDelta","currentCarbonSaved","comparisonCarbonSaved","carbonDelta","currentDemandChange","comparisonDemandChange","demandDelta","currentInterventions","comparisonInterventions","latitude","longitude"],tt={diffType:"Difference",uprn:"UPRN",area:"Postcode area",epcRating:"EPC rating",currentStatus:"Current status",comparisonStatus:"Comparison status",currentTechnologies:"Current technologies",comparisonTechnologies:"Comparison technologies",currentYears:"Current years",comparisonYears:"Comparison years",yearDelta:"Year delta",currentTotalCost:"Current cost",comparisonTotalCost:"Comparison cost",costDelta:"Cost delta",currentCarbonSaved:"Current carbon saved",comparisonCarbonSaved:"Comparison carbon saved",carbonDelta:"Carbon delta",currentDemandChange:"Current demand change",comparisonDemandChange:"Comparison demand change",demandDelta:"Demand delta",currentInterventions:"Current interventions",comparisonInterventions:"Comparison interventions",latitude:"Latitude",longitude:"Longitude"};function fe(c){if(Ae[c])return Ae[c];const e=new Set(["epc","imd","uprn","ashp","pv","gshp","co2"]);return c.replace(/^household_data_/,"").replace(/^household_/,"").replace(/^index_of_multiple_deprivation_/,"imd_").replace(/^proportion_of_/,"").replace(/^current_/,"").replace(/_/g," ").replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/\s+/g," ").trim().split(" ").map(r=>{const s=r.toLowerCase();return e.has(s)?s.toUpperCase():s==="m2"?"m2":s==="kw"?"kW":s==="pct"?"(%)":s.charAt(0).toUpperCase()+s.slice(1)}).join(" ")}function ye(c){if(!c?.getRowCount||!c?.getRow)return[];const e=[],o=(c.getColumnNames?c.getColumnNames():[]).find(t=>String(t).toLowerCase().replace(/\s+/g,"")==="uprn");for(let t=0;t<c.getRowCount();t++){const r=c.getRow(t),s=o?r?.[o]:r?.uprn;s&&e.push(String(s))}return e}function nt(c,e,n){if(typeof e!="function")return;const o=c?.getRowCount?.()||0;n!=null&&o>=n?e(null):e(ye(c))}function ot(c,e){if(!c?.getRowCount||!c?.getRow||!Array.isArray(e))return[];const n=new Set(e.filter(i=>i!=null).map(i=>String(i)));if(n.size===0)return[];const t=(c.getColumnNames?c.getColumnNames():[]).find(i=>String(i).toLowerCase().replace(/\s+/g,"")==="uprn");if(!t)return[];const r=[],s=c.getRowCount();for(let i=0;i<s;i+=1){const a=c.getRow(i),l=a?.[t]??a?.uprn;l!=null&&n.has(String(l))&&r.push(i)}return r}function ge(c,e){const n=c?.table,o=c?.facet;if(!n?.setSelectedRows||!o)return;const t=ot(o,e);n.setSelectedRows(t,t.length?"Selected on map":null),t.length>0&&n.bodyScrollContainer&&(n.bodyScrollContainer.scrollTop=t[0]*24)}function F(c){return String(c||"").toLowerCase().replace(/[^a-z0-9]+/g," ").trim()}function we(c){const e=c?.location?.lat??c?.latitude??c?.lat,n=c?.location?.lon??c?.longitude??c?.lon??c?.lng,o=Number(e),t=Number(n);return{latitude:Number.isFinite(o)?Math.round(o*1e6)/1e6:"",longitude:Number.isFinite(t)?Math.round(t*1e6)/1e6:""}}function st(c){return(c||[]).map(e=>{const n={};for(const[o,t]of Object.entries(e||{})){const r=F(o);Qe.has(r)||(n[o]=t)}return n})}const Ce=Object.freeze({totalCost:0,totalCarbonSaved:0,totalDemandChange:0});function te(){return{totalCost:0,totalCarbonSaved:0,totalDemandChange:0}}function be(c,e){c.totalCost+=Number(e?.stats?.cost||0),c.totalCarbonSaved+=Number(e?.stats?.carbonSaved||0),c.totalDemandChange+=Number(e?.stats?.demandChange||0)}function E(c){return Math.round(Number(c||0)*100)/100}function rt(c,e,n){const o=e.map(i=>Number(i.year)).filter(Number.isFinite),t=e.map(i=>
36String(i.interventionId??"")).filter(Boolean),r=new Set(t.map(i=>F(i)).filter(Boolean)),s={uprn:c.uprn,area:c.area,latitude:c.latitude,longitude:c.longitude,epcRating:c.epcRating,primarySubstation:c.primarySubstation,secondarySubstation:c.secondarySubstation,secondaryHeadroomMva:c.secondaryHeadroomMva,technologiesProposed:c.technologiesProposed,deploymentYears:o.length?[...new Set(o)].sort((i,a)=>i-a).join(", "):"",interventionsCount:c.interventionsCount,totalCost:E(n.totalCost),totalCarbonSaved:E(n.totalCarbonSaved),totalDemandChange:E(n.totalDemandChange),firstDeploymentYear:o.length?String(Math.min(...o)):"",lastDeploymentYear:o.length?String(Math.max(...o)):""};return Object.defineProperty(s,"__interventionKeys",{value:r,enumerable:!1}),s}function it(c){const e=c?.finalBuildings||[],n=c?.rawResults||[],o=new Map,t=new Map,r=new Set;for(const i of n)for(const[a,l]of Object.entries(i?.result?.metrics||{})){const d=Number(a);Number.isFinite(d)&&r.add(d);for(const h of l||[]){const m=String(h?.stats?.building??h?.building??"");if(m&&(o.has(m)||o.set(m,te()),be(o.get(m),h),Number.isFinite(d))){t.has(m)||t.set(m,new Map);const g=t.get(m);g.has(d)||g.set(d,te()),be(g.get(d),h)}}}const s=[];for(const i of e){const a=String(i?.uprn??"");if(!a)continue;const l=Array.isArray(i.interventionHistory)?i.interventionHistory:[];if(l.length===0)continue;const d=new Map;for(const u of l){const p=Number(u?.year);Number.isFinite(p)&&(r.add(p),d.has(p)||d.set(p,[]),d.get(p).push(u))}const h=Array.isArray(i.deployedTechs)?i.deployedTechs:i.deployedTech?[i.deployedTech]:[],{latitude:m,longitude:g}=we(i);s.push({uprn:a,area:i.area??"",latitude:m,longitude:g,epcRating:i.epcRating??i.epc??"",primarySubstation:i.primarySubstation??i.primary_name??"",secondarySubstation:i.secondarySubstation??i.secondary_name??"",secondaryHeadroomMva:E(i.secondaryHeadroomMva??i.secondary_headroom_mva??0),technologiesProposed:h.join(", "),interventionsCount:l.length,history:l,historyByYear:d,metrics:o.get(a)||Ce,metricsByYear:t.get(a)||new Map})}return{baseRows:s,knownYears:r,rowCache:new Map}}function at(c,e=null){if(!c)return[];const n=e==null?null:Number(e),o=n==null||!Number.isFinite(n)?"__all__":String(n);if(c.rowCache.has(o))return c.rowCache.get(o);const t=c.baseRows.map(r=>{const s=n==null?r.history:r.historyByYear.get(n)||[],i=n==null?r.metrics:r.metricsByYear.get(n)||Ce;return rt(r,s,i)});return c.rowCache.set(o,t),t}function Te(c,e=null,n=null,o=null){const t=at(c,n);if(!e&&!o)return t;const r=F(e||""),s=F(o||"");return t.filter(i=>{const a=i.__interventionKeys;return r&&a?.has(r)||s&&a?.has(s)})}function G(c=[]){return new Set((c||[]).map(e=>String(e??"").trim()).filter(Boolean))}function Ee(c,e){if(c.size!==e.size)return!1;for(const n of c)if(!e.has(n))return!1;return!0}function Z(c=[]){return[...G(c)].sort((e,n)=>e.localeCompare(n)).join(", ")}function lt(c){const e=new Map;for(const n of c?.rawResults||[])for(const o of Object.values(n?.result?.metrics||{}))for(const t of o||[]){const r=String(t?.stats?.building??t?.building??"");r&&(e.has(r)||e.set(r,te()),be(e.get(r),t))}return e}function Ie(c){const e=lt(c),n=new Map;for(const o of c?.finalBuildings||[]){const t=String(o?.uprn??"");if(!t)continue;const r=Array.isArray(o?.interventionHistory)?o.interventionHistory:[];if(!r.length)continue;const s=r.map(p=>Number(p?.year)).filter(Number.isFinite),i=r.map(p=>p?.technology||p?.tech).filter(Boolean),a=r.map(p=>p?.interventionLabel||p?.interventionId).filter(Boolean),l=r.reduce((p,f)=>(p.totalCost+=Number(f?.cost||0),p.totalCarbonSaved+=Number(f?.carbonSaved||0),p.totalDemandChange+=Number(f?.demandChange||0),p),te()),d=e.get(t)||Ce,m=!!(d.totalCost||d.totalCarbonSaved||d.totalDemandChange)?d:l,{latitude:g,longitude:u}=we(o);n.set(t,{uprn:t,area:o?.area??"",latitude:g,longitude:u,epcRating:o?.epcRating??o?.epc??"",primarySubstation:o?.primarySubstation??o?.primary_name??"",secondarySubstation:o?.secondarySubstation??o?.secondary_name??"",secondaryHeadroomMva:E(o?.secondaryHeadroomMva??o?.secondary_headroom_mva??0),status:"Deployed",years:[...new Set(s)].sort((p,f)=>p-f),technologies:[...G(i)],interventions:[...G(a)],totalCost:E(m.totalCost),totalCarbonSaved:E(m.totalCarbonSaved),totalDemandChange:E(m.totalDemandChange)})}return n}function ke(c=[]){for(const e of c){const n=Number(e);if(Number.isFinite(n))return n}return null}function ct(c,e){if(c&&!e)return"Current only";if(!c&&e)return"Comparison only";if(!c&&!e)return"No intervention";const n=G(c.technologies),o=G(e.technologies);if(!Ee(n,o))return"Different technology";const t=G(c.years),r=G(e.years);if(!Ee(t,r))return"Different year";const s=E((e.totalCost||0)-(c.totalCost||0)),i=E((e.totalCarbonSaved||0)-(c.totalCarbonSaved||0)),a=E((e.totalDemandChange||0)-(c.totalDemandChange||0));return s||i||a?"Different impact":"Same in both"}function ut(c,e,n="changed"){const o=Ie(c),t=Ie(e),s=[...new Set([...o.keys(),...t.keys()])].sort((i,a)=>i.localeCompare(a)).map(i=>{const a=o.get(i)||null,l=t.get(i)||null,d=ct(a,l),h=ke(a?.years),m=ke(l?.years),g=h!=null&&m!=null?m-h:"";return{diffType:d,uprn:i,area:a?.area||l?.area||"",epcRating:a?.epcRating||l?.epcRating||"",primarySub
36station:a?.primarySubstation||l?.primarySubstation||"",secondarySubstation:a?.secondarySubstation||l?.secondarySubstation||"",currentStatus:a?"Deployed":"No intervention",comparisonStatus:l?"Deployed":"No intervention",currentTechnologies:Z(a?.technologies),comparisonTechnologies:Z(l?.technologies),currentYears:Z(a?.years),comparisonYears:Z(l?.years),yearDelta:g,currentTotalCost:E(a?.totalCost||0),comparisonTotalCost:E(l?.totalCost||0),costDelta:E((l?.totalCost||0)-(a?.totalCost||0)),currentCarbonSaved:E(a?.totalCarbonSaved||0),comparisonCarbonSaved:E(l?.totalCarbonSaved||0),carbonDelta:E((l?.totalCarbonSaved||0)-(a?.totalCarbonSaved||0)),currentDemandChange:E(a?.totalDemandChange||0),comparisonDemandChange:E(l?.totalDemandChange||0),demandDelta:E((l?.totalDemandChange||0)-(a?.totalDemandChange||0)),currentInterventions:Z(a?.interventions),comparisonInterventions:Z(l?.interventions),latitude:a?.latitude||l?.latitude||"",longitude:a?.longitude||l?.longitude||""}});return n==="all"?s:n==="current-only"?s.filter(i=>i.diffType==="Current only"):n==="comparison-only"?s.filter(i=>i.diffType==="Comparison only"):s.filter(i=>i.diffType!=="Same in both")}function Pe(c){const e=Array.isArray(c)?c:[];if(!e.length)return"";const n=[],o=new Set;for(const s of e)for(const i of Object.keys(s||{}))o.has(i)||(o.add(i),n.push(i));const t=s=>{if(s==null)return"";const i=String(s);return/[",\n\r]/.test(i)?`"${i.replace(/"/g,'""')}"`:i},r=[n.map(t).join(",")];for(const s of e)r.push(n.map(i=>t(s?.[i])).join(","));return r.join(`
37`)}function Le(c,e){if(!c)return;const n=new Blob([c],{type:"text/csv;charset=utf-8;"}),o=URL.createObjectURL(n),t=document.createElement("a");t.href=o,t.download=e,document.body.appendChild(t),t.click(),document.body.removeChild(t),URL.revokeObjectURL(o)}function dt(c){if(!c)return"";if(typeof c.toDelimited=="function")return c.toDelimited("csv",{includeHeader:!0});if(typeof c.getColumnNames!="function"||typeof c.getRowCount!="function"||typeof c.getRow!="function")return"";const e=c.getColumnNames(),n=[];for(let o=0;o<c.getRowCount();o+=1){const t=c.getRow(o)||{},r={};for(const s of e)r[s]=t?.[s];n.push(r)}return Pe(n)}function ht(c){if(!c?.getColumnNames||!c?.getRowCount||!c?.getRow)return null;const n=c.getColumnNames().find(t=>F(t)==="uprn");if(!n)return null;const o=new Set;for(let t=0;t<c.getRowCount();t+=1){const s=c.getRow(t)?.[n];s!=null&&s!==""&&o.add(String(s))}return o}function mt(c){const e=c?.finalBuildings||[],n=c?.rawResults||[],o=new Map,t=new Map;for(const s of e){const i=String(s?.uprn??"");if(!i)continue;o.set(i,{area:s?.area??"",epcRating:s?.epcRating??s?.epc??"",...we(s)});const a=Array.isArray(s?.interventionHistory)?s.interventionHistory:[];for(const l of a){const d=Number(l?.year);if(!Number.isFinite(d))continue;const h=`${i}::${d}`;t.has(h)||t.set(h,[]),t.get(h).push(l)}}const r=[];for(const s of n){const i=String(s?.name??"");for(const[a,l]of Object.entries(s?.result?.metrics||{})){const d=Number(a);if(Number.isFinite(d))for(const h of l||[]){const m=String(h?.stats?.building??h?.building??"");if(!m)continue;const g=t.get(`${m}::${d}`)||[],u=g.find(f=>{const y=F(f?.interventionLabel||""),C=F(f?.interventionId||""),w=F(i||"");return y&&y===w||C&&C===w})||g[0]||null,p=o.get(m)||{};r.push({uprn:m,area:p.area??"",latitude:p.latitude??"",longitude:p.longitude??"",epcRating:p.epcRating??"",year:d,interventionId:u?.interventionId||i,interventionLabel:u?.interventionLabel||i,technology:u?.technology||"",cost:Number(h?.stats?.cost||0),carbonSaved:Number(h?.stats?.carbonSaved||0),demandChange:Number(h?.stats?.demandChange||0)})}}}return r}function pt(c,e="year"){const n=new Map,o=t=>String(t??"unknown").trim().replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"").toLowerCase()||"unknown";for(const t of c||[]){const r=String(t?.uprn??"");if(!r)continue;const s=n.get(r)||{uprn:r,area:t?.area??"",latitude:t?.latitude??"",longitude:t?.longitude??"",epcRating:t?.epcRating??"",totalDeployments:0,totalCost:0,totalCarbonSaved:0,totalDemandChange:0},i=t?.[e]??"unknown",a=o(i),l=`deployments_${a}`,d=`cost_${a}`,h=`carbonSaved_${a}`,m=`demandChange_${a}`,g=Number(t?.cost||0),u=Number(t?.carbonSaved||0),p=Number(t?.demandChange||0);
37s.totalDeployments+=1,s.totalCost+=g,s.totalCarbonSaved+=u,s.totalDemandChange+=p,s[l]=Number(s[l]||0)+1,s[d]=Number(s[d]||0)+g,s[h]=Number(s[h]||0)+u,s[m]=Number(s[m]||0)+p,n.set(r,s)}return[...n.values()].map(t=>({...t,totalCost:Math.round(t.totalCost*100)/100,totalCarbonSaved:Math.round(t.totalCarbonSaved*100)/100,totalDemandChange:Math.round(t.totalDemandChange*100)/100}))}async function ft(c,e="info"){try{(await De()).fire({toast:!0,position:"top-end",icon:e,title:c,showConfirmButton:!1,timer:2800,timerProgressBar:!0})}catch(n){console.warn("Toast unavailable",n)}}const Mt=({simulationOutput:c,buildingStock:e=[],isDataLoading:n=!1,parquetCounts:o=null,activeTab:t,onActiveTabChange:r,onSaveFacet:s,onSelectionChange:i,onFacetSummaryChange:a,selectedInterventionId:l=null,selectedInterventionLabel:d="",currentYear:h=null,selectedUprns:m=null,onOpenFieldCalculator:g,comparisonOutput:u=null,comparisonScenarioName:p="",isComparisonEnabled:f=!1})=>{const[y,C]=T.useState(t||"raw"),[w,N]=T.useState(!1),[v,x]=T.useState("table"),[M,P]=T.useState("year"),[j,oe]=T.useState("changed"),S=t??y,$e=T.useDeferredValue(h),ee=S==="results"?$e:h,Ve=S==="results"&&ee!==h,se=A=>{r&&r(A),C(A)},H=T.useRef(null),k=T.useRef(null),re=T.useRef([]),ve=T.useMemo(()=>st(e),[e]),ie=T.useMemo(()=>it(c),[c]),Se=T.useMemo(()=>ut(c,u,j),[c,u,j]),ae=T.useRef(s),le=T.useRef(i),ce=T.useRef(a),ue=T.useRef(!1);T.useEffect(()=>{ae.current=s},[s]),T.useEffect(()=>{le.current=i},[i]),T.useEffect(()=>{ce.current=a},[a]);const xe=(A,$,O)=>{if(!ce.current||!A?.getRowCount)return;const B=typeof A.getHistory=="function"?A.getHistory().filter(U=>U&&!String(U).includes("ordered columns")&&!String(U).includes("friendly field labels")):[];ce.current({visibleRows:A.getRowCount(),totalRows:O,operations:B,activeTab:$})};T.useEffect(()=>{if(!H.current)return;const A=typeof process<"u"&&process?.env?.NODE_ENV==="test"?0:150;H.current.style.transition="opacity 120ms ease-out";const $=setTimeout(()=>{if(!H.current)return;H.current.style.opacity="1",H.current.style.pointerEvents="auto",H.current.innerHTML="";const O=S==="results"&&!w&&!!(l||d);let B=[];if(S==="raw"?B=ve:S==="comparison"?B=f?Se:[]:B=Te(ie,O?l:null,ee,d),S==="results"&&O&&B.length===0&&(B=Te(ie,l||null,null,d)),re.current=B,n){H.current.innerHTML='<div class="p-8 text-center laep-soft italic">Loading building data…</div>';return}if(B.length===0){le.current?.([]);const he=S==="comparison"?f?"No building-level differences matched the current comparison filter.":"Enable comparison and choose a scenario to compare building-level results.":S==="results"?!!c?"No buildings matched the current filters. Try adjusting the selected intervention or year.":"Simulation running — results will appear here automatically.":"No data available";H.current.innerHTML=`<div class="p-8 text-center laep-soft italic">${he}</div>`;return}let D=Y.fromObjects(B).identityFacet(),V=D.getColumnNames();S==="results"&&(V=V.filter(R=>R!=="interventionIds"));const z=S==="raw"?Ze:S==="comparison"?et:Je,Q=[...z.filter(R=>V.includes(R)),...V.filter(R=>!z.includes(R))];D=D.reorderColumns(Q,"ordered columns for building table");const K={},q={};for(const R of Q){const W=S==="comparison"?tt[R]||fe(R):S==="results"&&Xe[R]||fe(R);K[R]=W,q[W]=R}D=D.renameColumns(K,"friendly field labels"),k.current=new qe({container:H.current,initialFacet:D,onSaveFacet:ae.current?R=>{const W=ye(R);ae.current?.({facet:R,uprns:W})}:void 0,onSelectionChange:void 0,onFacetChange:R=>{ue.current=!0,xe(R,S,re.current.length),nt(R,le.current,re.current.length)},onVizUpdate:(R,W=[])=>{try{const J=L=>{if(q[L])return q[L];try{return D.fromFacetToMasterColumnName?.(L)||L}catch{return L}},he=(R||[]).map(L=>J(L)),me=[...new Set(he.filter(Boolean))],Fe=(W||[]).map(L=>({...L,field:J(L.field),label:L.field})).filter(L=>L.field&&me.includes(L.field));try{typeof window.__LAEP_setMapGlyphs__=="function"&&window.__LAEP_setMapGlyphs__(me)}catch{}try{window.dispatchEvent(new CustomEvent("laep:table:visualize",{detail:{fields:me,encodings:Fe}}))}catch{}}catch(J){console.error("onVizUpdate handler failed",J)}}}),xe(D,S,B.length);const de=(S==="comparison"?["costDelta","carbonDelta","demandDelta"]:S==="results"?["totalCost","totalCarbonSaved","totalDemandChange"]:["pvKW","ashpKW","gshpKW"]).filter(R=>K[R]).map(R=>K[R]);if(de.length>0&&k.current){k.current.visualizeColumns=new Set(de),k.current.table&&(k.current.table.visualizeColumns=new Set(de),k.current.table.renderHeader());try{k.current.onVizUpdate?.(Array.from(k.current.visualizeColumns))}catch{}}ge(k.current,m)},A);return()=>{clearTimeout($),k.current&&(k.current=null)}},[S,ve,ie,Se,f,n,l,w,ee,d]),T.useEffect(()=>{if(k.current){if(ue.current){ue.current=!1;return}if(ye(k.current.facet),!Array.isArray(m)||m.length===0){ge(k.current,null);return}ge(k.current,m)}},[m]),T.useEffect(()=>{S!=="results"&&v!=="table"&&x("table")},[S,v]);const Be=async()=>{const A=k.current?.facet;if(S!=="results"||v==="table"){const V=dt(A);if(!V)return;Le(V,`${S==="comparison"?"scenario-comparison-table":S==="results"?"scenario-results-table":"raw-building-table"}.csv`);return}let $=mt(c);const O=ht(A);if(O&&O.size>0&&($=$.filter(V=>O.has(String(V?.uprn??"")))),!w&&(l||d)){const V=F(l||""),z=F(d||"");$=$.filter(Q=>{const K=F(Q?.interventionId||""),q=F(Q?.interventionLabel||"");return V&&K===V||z&&q===z||z&&K===z||V&&q===V})}if($.length===0){await ft("No scenario deployment rows are available for the current filters.","info");return}const B=v==="pivot"?pt($,M):$,U=Pe(B);if(!U)return;const D=v==="pivot"?`pivot-${M}`:"unpivot";Le(U,`scenario-results-${D}.csv`)};return _.jsxs("div",{className:"flex flex-col h-full laep-panel border rounded-lg overflow-hidden shadow-sm",children:[_.jsxs("div",{className:"flex items-center justify-between px-3 py-2 bg-[var(--laep-surface-raised)] border-bottom border-[var(--laep-border-subtle)] shrink-0",children:[_.jsxs("div",{className:"flex gap-2 items-center",children:[_.jsxs("button",{onClick:()=>se("raw"),type:"button","aria-label":"Show raw building stock table","aria-pressed":S==="raw",className:`flex items-center gap-1.5 px-3 py-1 rounded text-xs font-bold transition-all ${S==="raw"?"bg-[var(--laep-action)] text-[var(--laep-action-contrast)] shadow-sm":"text-[var(--laep-text-muted)] hover:text-[var(--laep-text)] hover:bg-[var(--laep-surface-muted)]"}`,children:[_.jsx(je,{className:"w-3.5 h-3.5"}),"Raw Data (Stock)"]}),_.jsxs("button",{onClick:()=>
37se("results"),type:"button","aria-label":"Show scenario results table","aria-pressed":S==="results",className:`flex items-center gap-1.5 px-3 py-1 rounded text-xs font-bold transition-all ${S==="results"?"bg-[var(--laep-action)] text-[var(--laep-action-contrast)] shadow-sm":"text-[var(--laep-text-muted)] hover:text-[var(--laep-text)] hover:bg-[var(--laep-surface-muted)]"}`,children:[_.jsx(ze,{className:"w-3.5 h-3.5"}),"Scenario Results"]}),f&&_.jsxs("button",{onClick:()=>se("comparison"),type:"button","aria-label":"Show scenario comparison table","aria-pressed":S==="comparison",className:`flex items-center gap-1.5 px-3 py-1 rounded text-xs font-bold transition-all ${S==="comparison"?"bg-[var(--laep-action)] text-[var(--laep-action-contrast)] shadow-sm":"text-[var(--laep-text-muted)] hover:text-[var(--laep-text)] hover:bg-[var(--laep-surface-muted)]"}`,children:[_.jsx(Ue,{className:"w-3.5 h-3.5"}),"Comparison"]}),S==="results"&&l&&_.jsxs(_.Fragment,{children:[_.jsx("span",{className:"text-[10px] px-2 py-1 rounded bg-[var(--laep-surface-muted)] text-[var(--laep-text)]",children:w?"Showing all deployments":`Filtered: ${d||"Selected intervention"}`}),_.jsx("button",{onClick:()=>N(A=>!A),type:"button","aria-label":w?"Filter deployment rows to selected intervention":"Show all deployment rows",className:"text-[10px] px-2 py-1 rounded laep-control border",children:w?"Filter to selected":"Show all"})]}),S==="comparison"&&_.jsx("div",{className:"flex items-center gap-1",children:[["changed","Changed"],["all","All"],["current-only","Current only"],["comparison-only","Comparison only"]].map(([A,$])=>_.jsx("button",{onClick:()=>oe(A),type:"button","aria-label":`Show ${$.toLowerCase()} comparison rows`,"aria-pressed":j===A,className:`text-[10px] px-2 py-1 rounded border transition-colors ${j===A?"bg-[var(--laep-surface-selected)] text-[var(--laep-text)] border-[var(--laep-border-strong)]":"laep-control"}`,children:$},A))})]}),_.jsxs("div",{className:"text-[10px] font-mono uppercase tracking-wider flex items-center gap-2",children:[S==="results"&&_.jsxs(_.Fragment,{children:[_.jsxs("select",{value:v,onChange:A=>x(A.target.value),"aria-label":"CSV export layout",className:"text-[10px] px-1.5 py-0.5 rounded laep-control border normal-case",title:"CSV export layout",children:[_.jsx("option",{value:"table",children:"Current table"}),_.jsx("option",{value:"unpivot",children:"Unpivot deployments"}),_.jsx("option",{value:"pivot",children:"Pivot deployments"})]}),v==="pivot"&&_.jsxs("select",{value:M,onChange:A=>P(A.target.value),"aria-label":"CSV pivot field",className:"text-[10px] px-1.5 py-0.5 rounded laep-control border normal-case",title:"Pivot field",children:[_.jsx("option",{value:"year",children:"Pivot: year"}),_.jsx("option",{value:"interventionId",children:"Pivot: intervention"}),_.jsx("option",{value:"technology",children:"Pivot: technology"})]})]}),S==="raw"&&g&&_.jsxs("button",{onClick:g,type:"button","aria-label":"Open field calculator",className:"inline-flex items-center gap-1 text-[10px] px-2 py-1 rounded laep-control border normal-case",title:"Add computed fields to the table",children:[_.jsx(He,{className:"w-3 h-3"}),"Fields"]}),_.jsxs("button",{onClick:Be,type:"button","aria-label":"Export current table to CSV",className:"inline-flex items-center gap-1 text-[10px] px-2 py-1 rounded laep-control border normal-case",title:"Export table to CSV",children:[_.jsx(Oe,{className:"w-3 h-3"}),"Export CSV"]}),_.jsx("span",{className:"laep-soft",children:S==="raw"?"Winchester Building Stock":S==="comparison"?`Comparison${p?`: ${p}`:""}`:`Simulated Impacts (${ee??"-"})${Ve?" · updating":""}`}),S==="raw"&&o&&_.jsxs("span",{className:"laep-muted",title:`Parquet: ${o.total.toLocaleString()} total | ${o.residential.toLocaleString()} residential (in bounds) | ${o.withSuitability.toLocaleString()} with tech suitability`,children:[e.length.toLocaleString(),o.residential!==o.withSuitability&&_.jsxs("span",{className:"laep-soft",children:[" / ",o.residential.toLocaleString()," residential"]})]})]})]}),_.jsx("div",{className:"flex-1 min-h-0 relative",children:_.jsx("div",{ref:H,className:"absolute inset-0"})})]})};export{Mt as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.