@mindfiredigital/pivothead
Version:
PivotHead is a powerful and flexible library for creating interactive pivot tables in JavaScript applications. It provides a core engine for data manipulation and, in the future, will be compatible with wrappers for React, Vue, Svelte, and Angular, making
92 lines (88 loc) • 76.1 kB
JavaScript
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ye=require("xlsx"),be=require("jspdf"),Se=require("jspdf-autotable");var E=typeof document<"u"?document.currentScript:null;function Ce(c){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(c){for(const t in c)if(t!=="default"){const r=Object.getOwnPropertyDescriptor(c,t);Object.defineProperty(e,t,r.get?r:{enumerable:!0,get:()=>c[t]})}}return e.default=c,Object.freeze(e)}const T=Ce(ye);function ae(c,e,t){if(!c||c.length===0)return 0;const r=c.map(s=>Number(s[e])||0);switch(t){case"sum":return r.reduce((s,a)=>s+a,0);case"avg":return r.reduce((s,a)=>s+a,0)/r.length;case"min":return Math.min(...r);case"max":return Math.max(...r);case"count":return r.length;default:return 0}}function De(c,e,t){return!e||e.length===0?c:[...c].sort((r,s)=>{for(const a of e){const{field:n,direction:i,type:o,aggregation:u}=a;if(o==="measure"){const d=ne(r,n),h=ne(s,n);if(d!==h)return i==="asc"?d-h:h-d}else{const d=r[n],h=s[n];if(d!==h)return i==="asc"?d<h?-1:1:d>h?-1:1}}return 0})}function ne(c,e,t){return Number(c[e])||0}function ve(c,e=null,t=null){let r=[...c.data||[]];e&&(r=De(r,[e]));let s=[];if(t){const{rowFields:a,columnFields:n,grouper:i}=t,o=[...a,...n];s=ue(r,o,i)}return{rawData:r,groups:s}}function ue(c,e,t){if(!e||e.length===0)return[{key:"All",items:c,subgroups:[],aggregates:{}}];const r={};return c.forEach(s=>{const a=t(s,e);r[a]||(r[a]={key:a,items:[],subgroups:[],aggregates:{}}),r[a].items.push(s)}),e.length>1&&Object.values(r).forEach(s=>{s.subgroups=ue(s.items,e.slice(1),t)}),Object.values(r)}const ke="@mindfiredigital/pivothead",de=1*1024*1024,B=5*1024*1024,O=8*1024*1024,K=10*1024*1024,Fe=256*1024,ie=1*1024*1024,Ne=2*1024*1024,Ee=5*1024*1024,Ae=10*1024*1024,Me=100*1024*1024,_e=100,Le=["region","country","state","city","category","department"],Re=["product","item","month","quarter","year","type"],Pe=40,xe=10,Te=50,$e=10,We="#f8f9fa",he=ke,Q={error:0,warn:1,info:2,debug:3};function qe(){const c=typeof process<"u"?process.env.LOG_LEVEL??"info":"info";return Q[c]??Q.info}function ze(){const c=qe(),e=(t,r,s,...a)=>{(Q[r]??99)<=c&&t(`[${he}] ${r.toUpperCase()}: ${s}`,...a)};return{error:(t,...r)=>e(console.error.bind(console),"error",t,...r),warn:(t,...r)=>e(console.warn.bind(console),"warn",t,...r),info:(t,...r)=>e(console.info.bind(console),"info",t,...r),debug:(t,...r)=>e(console.debug.bind(console),"debug",t,...r)}}function Oe(){if(typeof window<"u")return null;try{const c=require("winston"),{combine:e,label:t,colorize:r,printf:s,timestamp:a}=c.format,n=s(({level:i,message:o,label:u,timestamp:d,...h})=>{const g=Object.keys(h).length?` ${JSON.stringify(h)}`:"";return`${String(d)} [${String(u)}] ${String(i)}: ${String(o)}${g}`});return c.createLogger({level:(typeof process<"u"?process.env.LOG_LEVEL:void 0)??"info",format:e(t({label:he}),a({format:"YYYY-MM-DD HH:mm:ss"}),r({all:!1}),n),transports:[new c.transports.Console]})}catch{return null}}const l=Oe()??ze();function $(c){return(c==null?"":String(c)).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}class A{static convertToHtml(e){const{rows:t,columns:r,selectedMeasures:s,formatting:a,rawData:n}=e;if(n.length===0||!t.length||!r.length)return"<div>No data to display</div>";const i=[...new Set(n.map(g=>g[r[0].uniqueName]))],o=[...new Set(n.map(g=>g[t[0].uniqueName]))],u=(g,m)=>g===0?"$0.00":!g&&g!==0?"":m&&m.type==="currency"?new Intl.NumberFormat(m.locale,{style:"currency",currency:m.currency,minimumFractionDigits:m.decimals,maximumFractionDigits:m.decimals}).format(g):m&&m.type==="number"?new Intl.NumberFormat(m.locale,{minimumFractionDigits:m.decimals,maximumFractionDigits:m.decimals}).format(g):String(g),d=(g,m)=>"";let h=`
<div class="pivot-export">
<style>
.pivot-table {
border-collapse: collapse;
width: 100%;
font-family: Arial, sans-serif;
}
.pivot-table th, .pivot-table td {
border: 1px solid #ddd;
padding: 8px;
text-align: right;
}
.pivot-table th {
background-color: #f2f2f2;
font-weight: bold;
text-align: center;
position: relative;
}
.pivot-table .sort-icon::after {
content: "↕";
position: absolute;
right: 4px;
opacity: 0.5;
}
.pivot-table th.region-header {
border-bottom: none;
}
.pivot-table th.measure-header {
border-top: none;
}
.pivot-table .row-header {
text-align: left;
font-weight: bold;
background-color: #f9f9f9;
}
.pivot-table .corner-header {
background-color: #f2f2f2;
border-bottom: 1px solid #ddd;
}
.pagination {
margin-top: 15px;
font-family: Arial, sans-serif;
}
.export-info {
margin-top: 15px;
font-size: 0.8em;
color: #666;
font-family: Arial, sans-serif;
}
</style>
<table class="pivot-table">
<thead>
<tr>
<th rowspan="2" class="corner-header">${$(t[0]?.caption||t[0]?.uniqueName||"")} /<br>Region</th>`;return i.forEach(g=>{h+=`<th colspan="${s.length}" class="region-header">${$(g)}</th>`}),h+=`
</tr>
<tr>`,i.forEach(()=>{s.forEach(g=>{h+=`<th class="measure-header sort-icon">${$(g.caption||g.uniqueName)}</th>`})}),h+=`
</tr>
</thead>
<tbody>`,o.forEach(g=>{h+=`<tr>
<td class="row-header">${$(g)}</td>`,i.forEach(m=>{s.forEach(C=>{const S=n.filter(w=>w[t[0].uniqueName]===g&&w[r[0].uniqueName]===m);let b=0;if(S.length>0)switch(C.aggregation){case"sum":b=S.reduce((w,y)=>w+(Number(y[C.uniqueName])||0),0);break;case"avg":C?.formula&&typeof C.formula=="function"?b=S.reduce((w,y)=>w+(C.formula?.(y)||0),0)/S.length:b=S.reduce((w,y)=>w+(Number(y[C.uniqueName])||0),0)/S.length;break;case"max":b=Math.max(...S.map(w=>Number(w[C.uniqueName])||0));break;case"min":b=Math.min(...S.map(w=>Number(w[C.uniqueName])||0));break;case"count":b=S.length;break;default:b=0}const f=d(b,C.uniqueName),p=u(b,a[C.uniqueName]);h+=`<td${f}>${$(p)}</td>`})}),h+="</tr>"}),h+=`
</tbody>
</table>
<div class="pagination">
Page ${e.paginationConfig?.currentPage||1} of ${e.paginationConfig?.totalPages||1}
</div>
<div class="export-info">
<p>Generated: ${new Date().toLocaleString()}</p>
</div>
</div>`,h}static exportToHTML(e,t="pivot-table"){l.info("PivotExportService.exportToHTML called with fileName:",t),l.info("State rawData length:",e.rawData?.length||0);const r=A.convertToHtml(e);l.info("HTML content length:",r.length);const s=`<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${$(t)}</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.pivot-export { max-width: 100%; overflow-x: auto; }
</style>
</head>
<body>
${r}
</body>
</html>`;l.info("Full HTML length:",s.length);const a="data:text/html;charset=utf-8,"+encodeURIComponent(s);l.info("Data URL created, length:",a.length);const n=document.createElement("a");n.href=a,n.download=`${t}.html`,document.body.appendChild(n),l.info("Clicking download link..."),n.click(),document.body.removeChild(n),l.info("HTML export completed")}static exportToPDF(e,t="pivot-table"){l.info("PivotExportService.exportToPDF called with fileName:",t),l.info("State rawData length:",e.rawData?.length||0);const r=A.convertToHtml(e);l.info("HTML content length for PDF:",r.length);const s=document.createElement("div");s.style.position="absolute",s.style.left="-9999px",s.innerHTML=r,document.body.appendChild(s);const a=s.querySelector("table");if(!a){l.error("No table found in the generated HTML"),document.body.removeChild(s);return}l.info("Table element found, proceeding with PDF generation");try{l.info("Creating jsPDF instance...");const n=new be.jsPDF;n.setFontSize(16),n.text(t,n.internal.pageSize.getWidth()/2,15,{align:"center"}),Se.autoTable(n,{html:a,startY:25,styles:{fontSize:10,cellPadding:3,overflow:"linebreak"},headStyles:{fillColor:[66,139,202],textColor:255,fontStyle:"bold"},columnStyles:{},margin:{top:25,right:15,bottom:25,left:15},didDrawPage:i=>{n.setFontSize(10),n.text(`Page ${i.pageNumber}`,n.internal.pageSize.getWidth()-20,n.internal.pageSize.getHeight()-10)}}),n.save(`${t}.pdf`),document.body.removeChild(s)}catch(n){l.error("Error exporting to PDF:",n),document.body.removeChild(s)}}static exportToExcel(e,t="pivot-table"){l.info("PivotExportService.exportToExcel called with fileName:",t),l.info("State rawData length:",e.rawData?.length||0);try{A.generateExcel(e,t)}catch(r){l.error("Error exporting to Excel:",r)}}static generateExcel(e,t){if(!e.data||e.data.length===0){l.info("No data to export!");return}const r=e.rows||[],s=e.columns||[],a=e.measures||[],n=r[0]?.uniqueName,i=s[0]?.uniqueName;if(!n||!i){l.info("Missing row or column dimension");return}const o=[...new Set(e.data.map(f=>f[n]))],u=[...new Set(e.data.map(f=>f[i]))],d=[r[0]?.caption||"Dimension",...u.flatMap(f=>a.map(p=>`${f} - ${p.caption||p.uniqueName}`))],h=o.map(f=>{const p=[f];return u.forEach(w=>{a.forEach(y=>{const D=e.data.filter(v=>v[n]===f&&v[i]===w);let k=0;if(D.length>0)switch(y.aggregation){case"sum":k=D.reduce((v,F)=>v+(Number(F[y.uniqueName])||0),0);break;case"avg":y?.formula&&typeof y.formula=="function"&&D.length>0?k=D.reduce((v,F)=>v+(y.formula?.(F)||0),0)/D.length:k=D.reduce((v,F)=>v+(Number(F[y.uniqueName])||0),0)/D.length;break;case"max":k=Math.max(...D.map(v=>Number(v[y.uniqueName])||0));break;case"min":k=Math.min(...D.map(v=>Number(v[y.uniqueName])||0));break;case"count":k=D.length;break;default:k=0}p.push(k)})}),p});if(e.processedData&&e.processedData.totals){const f=["Total"];u.forEach(()=>{a.forEach(p=>{const w=e.processedData.totals[p.uniqueName]||0;f.push(w)})}),h.push(f)}const g=[d,...h],m=T.utils.aoa_to_sheet(g),C=T.utils.decode_range(m["!ref"]??"A1:A1"),S=[];for(let f=0;f<=C.e.c;f++)S[f]={wch:f===0?15:12};m["!cols"]=S;for(let f=1;f<=h.length;f++)for(let p=1;p<=u.length*a.length;p++){const w=T.utils.encode_cell({r:f,c:p}),y=(p-1)%a.length,D=a[y];if(D&&D.format&&m[w])if(D.format.type==="currency")m[w].z=D.format.currency==="USD"?'"$"#,##0.00':`"${D.format.currency}"#,##0.00`;else if(D.format.type==="number"&&D.format.decimals!==void 0){const k="#,##0"+(D.format.decimals>0?"."+"0".repeat(D.format.decimals):"");m[w].z=k}else D.format.type==="percentage"&&(m[w].z="0.00%",typeof m[w].v=="number"&&(m[w].v=m[w].v/100))}const b=T.utils.book_new();T.utils.book_append_sheet(b,m,"Pivot Table"),T.writeFile(b,`${t}.xlsx`)}static openPrintDialog(e){const t=A.convertToHtml(e),r=window.open("","_blank");if(!r){l.error("Failed to open print dialog");return}r.document.write(t),r.document.close(),r.print()}}class Ve{constructor(e){if(this.filterConfig=[],this.paginationConfig={currentPage:1,pageSize:10,totalPages:1},this.autoAllColumnEnabled=!1,this.cache=new Map,this.listeners=new Set,!this.validateConfig(e))throw new Error("Invalid pivot table configuration");this.config={...e,defaultAggregation:e.defaultAggregation||"sum",isResponsive:e.isResponsive??!0},this.state=this.initializeState(e),this.loadData()}setColumns(e){throw new Error("Method not implemented.")}setRows(e){throw new Error("Method not implemented.")}setData(e){throw new Error("Method not implemented.")}validateConfig(e){if(!e)return!1;if(e.dataSource){const{type:t,url:r,file:s}=e.dataSource;if(t==="remote"&&!r||t==="file"&&!s)return!1}return!0}initializeState(e){return{data:e.data||[],dataHandlingMode:"processed",rawData:e.data||[],processedData:{headers:[],rows:[],totals:{}},rows:e.rows||[],columns:e.columns||[],measures:this.normalizeMeasures(e.measures||[]),sortConfig:[],rowSizes:this.initializeRowSizes(e.data||[]),expandedRows:{},groupConfig:e.groupConfig||null,groups:[],selectedMeasures:this.normalizeMeasures(e.measures||[]),selectedDimensions:e.dimensions||[],selectedAggregation:e.defaultAggregation||"sum",formatting:e.formatting||{},columnWidths:{},isResponsive:e.isResponsive??!0,rowGroups:[],columnGroups:[],filterConfig:[],paginationConfig:{currentPage:1,pageSize:e.pageSize||10,totalPages:1}}}async loadData(){if(this.config.dataSource){const{type:e,url:t,file:r}=this.config.dataSource;e==="remote"&&t?this.state.rawData=await this.fetchRemoteData(t):e==="file"&&r?this.state.rawData=await this.readFileData(r):l.error("Invalid data source configuration")}else this.config.data&&(this.state.rawData=this.config.data);this.state.rowSizes=this.initializeRowSizes(this.state.rawData),this.ensureSyntheticAllColumn(),this.state.processedData=this.generateProcessedDataForDisplay(),this.state.groupConfig&&this.applyGrouping()}ensureSyntheticAllColumn(){if(!this.autoAllColumnEnabled)return;const e=!this.state.columns||this.state.columns.length===0,t=!!this.state.columns?.some(r=>r.uniqueName==="__all__");if(e&&(this.state.columns=[{uniqueName:"__all__",caption:"All"}]),e||t){const r=s=>{const a=Array.isArray(s)?s:[];let n=!1;const i=a.map(o=>o&&o.__all__===void 0?(n=!0,{...o,__all__:"All"}):o);return n?i:a};this.config.data=r(this.config.data),this.state.rawData=r(this.state.rawData),this.state.data=r(this.state.data)}}setDataHandlingMode(e){this.state.dataHandlingMode=e,this.refreshData(),this._emit()}getDataHandlingMode(){return this.state.dataHandlingMode}setAutoAllColumn(e){this.autoAllColumnEnabled=e,e&&(this.ensureSyntheticAllColumn(),this.state.processedData=this.generateProcessedDataForDisplay(),this._emit())}updateDataSource(e,t=!0){this.config.data=[...e],this.state.data=[...e],this.state.rawData=[...e],t&&(this.filterConfig=[],this.state.filterConfig=[]),this.ensureSyntheticAllColumn(),this.refreshData(),this._emit()}async fetchRemoteData(e){try{const t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch data from ${e}`);return await t.json()}catch(t){return l.error("Error fetching remote data:",t),[]}}async readFileData(e){return new Promise((t,r)=>{const s=new FileReader;s.onload=a=>{try{const n=JSON.parse(a.target?.result);t(n)}catch(n){r(n)}},s.onerror=a=>r(a),s.readAsText(e)})}initializeRowSizes(e){return e.map((t,r)=>({index:r,height:40}))}generateProcessedDataForDisplay(){let e=this.state.rawData;if(this.state.dataHandlingMode==="processed"&&this.state.sortConfig.length>0){const t=this.state.sortConfig[0];this.state.groups.length>0?e=this.state.groups.flatMap(r=>r.items):e=this.sortData(this.state.rawData,t)}return{headers:this.generateHeaders(),rows:this.generateRows(e),totals:this.calculateTotals(e)}}generateHeaders(){const e=this.state.dataHandlingMode==="raw",t=this.state.rows?this.state.rows.map(s=>e?s.uniqueName:s.caption||s.uniqueName):[],r=this.state.columns?this.state.columns.map(s=>e?s.uniqueName:s.caption||s.uniqueName):[];return[...t,...r]}generateRows(e){return!e||!this.state.rows||!this.state.columns?[]:e.map(t=>[...this.state.rows.map(r=>t[r.uniqueName]),...this.state.columns.map(r=>t[r.uniqueName]),...this.state.measures.map(r=>{const s=this.calculateMeasureValue(t,r);return this.formatValue(s,r.uniqueName)})])}calculateMeasureValue(e,t){return t.formula&&typeof t.formula=="function"?t.formula(e):e[t.uniqueName]||0}calculateTotals(e){const t={};return this.state.measures.forEach(r=>{const{uniqueName:s,aggregation:a}=r;let n=0;a==="sum"?n=e.reduce((i,o)=>i+(o[s]||0),0):a==="avg"?n=e.reduce((i,o)=>i+(o[s]||0),0)/e.length:a==="max"?n=Math.max(...e.map(i=>i[s]||0)):a==="min"?n=Math.min(...e.map(i=>i[s]||0)):a==="count"&&(n=e.length),t[s]=n}),t}subscribe(e){return this.listeners.add(e),e(this.getState()),()=>this.listeners.delete(e)}_emit(){const e=this.getState();this.listeners.forEach(t=>{try{t(e)}catch(r){l.error("Error in pivot engine subscriber:",r)}})}setMeasures(e){this.state.selectedMeasures=this.normalizeMeasures(e),this.state.processedData=this.generateProcessedDataForDisplay(),this.updateAggregates(),this._emit()}setDimensions(e){this.state.selectedDimensions=e,this.state.processedData=this.generateProcessedDataForDisplay(),this.updateAggregates(),this.refreshData(),this._emit()}setAggregation(e){this.state.selectedAggregation=e,this.state.processedData=this.generateProcessedDataForDisplay(),this.updateAggregates(),this.refreshData(),this._emit()}setRowGroups(e){this.state.rowGroups=e,this.state.processedData=this.generateProcessedDataForDisplay(),this.updateAggregates(),this._emit()}setColumnGroups(e){this.state.columnGroups=e,this.state.processedData=this.generateProcessedDataForDisplay(),this.updateAggregates(),this._emit()}formatValue(e,t){if(e==null||typeof e=="number"&&isNaN(e)){const a=this.getFieldFormat(t);return a&&a.nullValue!==void 0?a.nullValue===null?"":String(a.nullValue):""}const r=this.getFieldFormat(t),s=this.state.measures.find(a=>a.uniqueName===t);if(!r){if(s?.aggregation==="avg"){const a=Number(e);return Number.isFinite(a)?String(Math.round(a)):String(e)}return String(e)}try{const a=s?.aggregation==="avg"&&typeof r.decimals!="number"?{...r,decimals:0}:r;return this.applyFormatting(e,a)}catch(a){return l.error(`Error formatting value for field ${t}:`,a),String(e)}}getFieldFormat(e){const t=this.state.measures.find(s=>s.uniqueName===e);if(t&&t.format)return t.format;const r=this.state.formatting[e];return r||null}applyFormatting(e,t){let r=parseFloat(String(e));if(isNaN(r))return String(e);t.percent&&(r=r*100);const s=typeof t.decimals=="number"?t.decimals:2;let a;switch(t.type){case"currency":a=this.formatCurrency(r,t,s);break;case"percentage":a=this.formatPercentage(r,t,s);break;case"date":a=this.formatDate(e,t);break;case"number":default:a=this.formatNumber(r,t,s);break}return a=this.applyCustomSeparators(a,t),a}formatCurrency(e,t,r){const s=t.currency||"USD",a=t.locale||"en-US";let n=new Intl.NumberFormat(a,{style:"currency",currency:s,minimumFractionDigits:r,maximumFractionDigits:r}).format(e);if(t.align==="right"||t.currencyAlign==="right"){const i=n.replace(/[\d.,\s]/g,"");n=n.replace(i,"").trim()+" "+i}else t.align==="left"||t.currencyAlign;return n}formatPercentage(e,t,r){const s=t.locale||"en-US";return new Intl.NumberFormat(s,{style:"percent",minimumFractionDigits:r,maximumFractionDigits:r}).format(e/100)}formatNumber(e,t,r){const s=t.locale||"en-US";return new Intl.NumberFormat(s,{minimumFractionDigits:r,maximumFractionDigits:r}).format(e)}formatDate(e,t){const r=t.locale||"en-US";try{return new Date(e).toLocaleDateString(r,{dateStyle:"medium"})}catch{return String(e)}}applyCustomSeparators(e,t){let r=e;if(t.decimalSeparator&&t.decimalSeparator!=="."){const s=r.lastIndexOf(".");s!==-1&&(r=r.substring(0,s)+t.decimalSeparator+r.substring(s+1))}return t.thousandSeparator!==void 0&&(t.thousandSeparator===""?r=r.replace(/,/g,""):t.thousandSeparator!==","&&(r=r.replace(/,/g,t.thousandSeparator))),r}calculateCellValue(e,t,r,s,a){const i=(this.config.data||this.state.rawData).filter(u=>u[s]===e&&u[a]===t);if(i.length===0)return 0;let o=0;switch(r.aggregation){case"sum":o=i.reduce((u,d)=>u+(d[r.uniqueName]||0),0);break;case"avg":o=i.reduce((u,d)=>u+(d[r.uniqueName]||0),0)/i.length;break;case"max":o=Math.max(...i.map(u=>u[r.uniqueName]||0));break;case"min":o=Math.min(...i.map(u=>u[r.uniqueName]||0));break;case"count":o=i.length;break;default:o=0}return o}getFieldAlignment(e){const t=`alignment:${e}`;if(this.cache.has(t))return this.cache.get(t);const r=this.getFieldFormat(e);let s;return r&&r.align?s=r.align:r&&r.type==="currency"&&r.currencyAlign?s=r.currencyAlign:s=this.state.measures.find(n=>n.uniqueName===e)?"right":"left",this.cache.set(t,s),s}updateFieldFormatting(e,t){const r=this.state.measures.find(a=>a.uniqueName===e);r&&(r.format=t),this.state.formatting[e]=t;const s=`alignment:${e}`;this.cache.delete(s),this.state.processedData=this.generateProcessedDataForDisplay(),this._emit()}sort(e,t){const r=this.state.measures.find(a=>a.uniqueName===e),s={field:e,direction:t,type:r?"measure":"dimension",aggregation:r?.aggregation};this.state.sortConfig=[s],this.applySort()}applySort(){if(this.state.dataHandlingMode==="raw"){const e=this.sortData(this.state.rawData,this.state.sortConfig[0]);this.state.data=e,this.state.rawData=e,this.state.processedData=this.generateProcessedDataForDisplay(),this.updateAggregates()}else if(this.state.groups.length>0)this.state.groups=this.sortGroups(this.state.groups,this.state.sortConfig[0]),this.state.processedData=this.generateProcessedDataForDisplay(),this.updateAggregates();else{const e=this.sortData(this.state.rawData,this.state.sortConfig[0]);this.state.data=e,this.state.rawData=e,this.state.processedData=this.generateProcessedDataForDisplay(),this.updateAggregates()}this._emit()}sortData(e,t){return[...e].sort((r,s)=>{let a=this.getFieldValue(r,t),n=this.getFieldValue(s,t);return typeof a=="string"&&(a=a.toLowerCase()),typeof n=="string"&&(n=n.toLowerCase()),a<n?t.direction==="asc"?-1:1:a>n?t.direction==="asc"?1:-1:0})}getFieldValue(e,t){if(t.type==="measure"){const r=this.state.measures.find(s=>s.uniqueName===t.field);if(r&&r.formula)return r.formula(e)}return e[t.field]}sortGroups(e,t){return[...e].sort((r,s)=>{let a,n;if(t.type==="measure")a=r.aggregates[`${t.aggregation}_${t.field}`]||0,n=s.aggregates[`${t.aggregation}_${t.field}`]||0;else{const i=r.key?r.key.split("|"):[],o=s.key?s.key.split("|"):[],u=this.state.rows?.[0]?.uniqueName,d=this.state.columns?.[0]?.uniqueName;t.field===u?(a=i[0]||"",n=o[0]||""):t.field===d?(a=i[1]||"",n=o[1]||""):(a=r.items[0]?.[t.field]||"",n=s.items[0]?.[t.field]||""),typeof a=="string"&&(a=a.toLowerCase()),typeof n=="string"&&(n=n.toLowerCase())}return a<n?t.direction==="asc"?-1:1:a>n?t.direction==="asc"?1:-1:0})}updateAggregates(){const e=t=>{this.state.measures.forEach(r=>{const s=`${this.state.selectedAggregation}_${r.uniqueName}`;if(r.formula&&typeof r.formula=="function"){const a=t.items.map(n=>r.formula?r.formula(n):0);t.aggregates[s]=ae(a.map(n=>({value:n})),"value",r.aggregation||this.state.selectedAggregation)}else t.aggregates[s]=ae(t.items,r.uniqueName,r.aggregation||this.state.selectedAggregation)}),t.subgroups&&t.subgroups.forEach(e)};this.state.groups.forEach(e)}applyGrouping(e){if(!this.state.groupConfig)return;const{rowFields:t,columnFields:r,grouper:s}=this.state.groupConfig;if(!t||!r||!s){l.error("Invalid groupConfig:",this.state.groupConfig);return}const a=e||this.config.data||[],n={...this.config,data:a},{rawData:i,groups:o}=ve(n,this.state.sortConfig[0]||null,this.state.groupConfig);this.state.rawData=i,this.state.groups=o,this.updateAggregates(),this.state.processedData=this.generateProcessedDataForDisplay()}setGroupConfig(e){this.state.groupConfig=e,e?this.applyGrouping():(this.state.groups=[],this.state.processedData=this.generateProcessedDataForDisplay()),this._emit()}getGroupedData(){return this.state.groups}getState(){return{...this.state}}reset(){this.state={...this.state,rawData:this.config.data||[],processedData:this.generateProcessedDataForDisplay(),sortConfig:[],rowSizes:this.initializeRowSizes(this.config.data||[]),expandedRows:{},groupConfig:this.config.groupConfig||null,groups:[]},this.state.groupConfig&&this.applyGrouping(),this._emit()}resizeRow(e,t){const r=this.state.rowSizes.findIndex(s=>s.index===e);r!==-1&&(this.state.rowSizes[r].height=Math.max(20,t),this._emit())}toggleRowExpansion(e){this.state.expandedRows[e]=!this.state.expandedRows[e],this._emit()}isRowExpanded(e){return!!this.state.expandedRows[e]}dragRow(e,t){if(!this.validateDragOperation(e,t,this.state.rowGroups.length))return;const r=[...this.state.rowGroups],[s]=r.splice(e,1);r.splice(t,0,s),this.state.rowGroups=r,typeof this.config.onRowDragEnd=="function"&&this.config.onRowDragEnd(e,t,this.state.rowGroups),this._emit()}dragColumn(e,t){if(this.validateDragOperation(e,t,this.state.columnGroups.length))try{const r=[...this.state.columnGroups],[s]=r.splice(e,1);if(r.splice(t,0,s),this.state.columnGroups=r,typeof this.config.onColumnDragEnd=="function"){const a=r.map(n=>({uniqueName:n.uniqueName??n.key??"",caption:n.caption??n.key??""}));this.config.onColumnDragEnd(e,t,a)}this._emit()}catch(r){l.error("Error during column drag operation:",r)}}validateDragOperation(e,t,r){if(e===t)return!1;const s=e>=0&&t>=0&&e<r&&t<r;return s||l.warn(`Invalid drag indices: from ${e} to ${t} with length ${r}`),s}applyFilters(e){this.filterConfig=e,this.refreshData(),this._emit()}setPagination(e){this.paginationConfig={...this.paginationConfig,...e},this.refreshData(),this._emit()}getPagination(){return this.paginationConfig}refreshData(){const e=this.getDataForCurrentMode();let t;this.state.dataHandlingMode==="processed"&&this.hasAggregatedFilters()?t=this.filterProcessedData(e):t=this.filterData(e),this.paginationConfig.totalPages=Math.ceil(t.length/this.paginationConfig.pageSize),t=this.paginateData(t),this.state.dataHandlingMode==="raw"?(this.state.data=t,this.state.rawData=t,this.state.processedData=this.generateProcessedDataForDisplay()):(this.state.data=t,this.state.rawData=t,this.state.groupConfig&&this.applyGrouping(t),this.state.processedData=this.generateProcessedDataForDisplay())}getDataForCurrentMode(){return[...this.config.data||[]]}filterData(e){return this.filterConfig.length?e.filter(t=>this.filterConfig.every(r=>{const s=t[r.field],a=typeof s=="number"?Number(r.value):r.value;switch(r.operator){case"equals":return typeof s=="string"&&typeof a=="string"?s.toLowerCase()===a.toLowerCase():s===a;case"contains":return String(s).toLowerCase().includes(String(a).toLowerCase());case"greaterThan":return Number(s)>Number(a);case"lessThan":return Number(s)<Number(a);case"between":{const n=a;return s>=n[0]&&s<=n[1]}default:return!0}})):e}paginateData(e){const{currentPage:t,pageSize:r}=this.paginationConfig,s=(t-1)*r;return e.slice(s,s+r)}getPaginationState(){return{...this.paginationConfig}}getFilterState(){return[...this.filterConfig]}exportToHTML(e="pivot-table"){l.info("PivotEngine.exportToHTML called with fileName:",e),l.info("PivotEngine state rawData length:",this.state.rawData?.length||0),A.exportToHTML(this.getState(),e)}exportToPDF(e="pivot-table"){l.info("PivotEngine.exportToPDF called with fileName:",e),l.info("PivotEngine state rawData length:",this.state.rawData?.length||0),A.exportToPDF(this.getState(),e)}exportToExcel(e="pivot-table"){l.info("PivotEngine.exportToExcel called with fileName:",e),l.info("PivotEngine state rawData length:",this.state.rawData?.length||0),A.exportToExcel(this.getState(),e)}openPrintDialog(){A.openPrintDialog(this.getState())}dragDataRow(e,t){const r=[...new Set(this.state.data.map(s=>s.product))].filter(s=>typeof s=="string");if(this.validateDragOperation(e,t,r.length))try{const s=r[e],a=r[t];l.info(`Reordering products: ${s} -> ${a}`);const n=[...this.state.data],i=[...r],[o]=i.splice(e,1);i.splice(t,0,o),n.sort((u,d)=>{const h=i.indexOf(u.product),g=i.indexOf(d.product);return h-g}),this.state.data=n,this.state.rawData=n,this.state.processedData=this.generateProcessedDataForDisplay(),this.state.groups.length>0&&this.updateAggregates(),typeof this.config.onRowDragEnd=="function"&&this.config.onRowDragEnd(e,t,this.state.rowGroups)}catch(s){l.error("Error during data row drag operation:",s)}}dragDataColumn(e,t){const r=[...new Set(this.state.data.map(s=>s.region))].filter(s=>typeof s=="string");if(this.validateDragOperation(e,t,r.length))try{const s=[...this.state.data],a=[...r],[n]=a.splice(e,1);if(a.splice(t,0,n),this.state.columns&&this.state.columns.length>0){const i=[...this.state.columns];i.sort((o,u)=>{const d=a.indexOf(o.uniqueName),h=a.indexOf(u.uniqueName);return d===-1?1:h===-1?-1:d-h}),this.state.columns=i}if(this.state.data=s,this.state.rawData=s,this.state.processedData=this.generateProcessedDataForDisplay(),this.state.groups.length>0&&this.updateAggregates(),typeof this.config.onColumnDragEnd=="function"){const i=a.map(o=>({uniqueName:o,caption:o}));this.config.onColumnDragEnd(e,t,i)}}catch(s){l.error("Error during data column drag operation:",s)}}reorderProductsByName(e,t,r="before"){try{const s=[...new Set(this.state.data.map(o=>o.product))],a=s.indexOf(e),n=s.indexOf(t);if(a===-1||n===-1){l.warn("Invalid product names for reordering:",{fromProduct:e,toProduct:t});return}const i=r==="after"?n+1:n;this.dragDataRow(a,i)}catch(s){l.error("Error reordering products by name:",s)}}getCustomRegionOrder(){return this.state.customRegionOrder??null}swapDataRows(e,t){const r=this.state.rows&&this.state.rows.length>0?this.state.rows[0]:null;if(!r){l.warn("No row field configured for swapping");return}const s=r.uniqueName,a=this.state.customRowOrder;let n;if(a&&a.fieldName===s&&a.order?n=[...a.order]:n=[...new Set((this.config.data||[]).map(i=>i[s]))].filter(i=>typeof i=="string"&&i!==null&&i!==void 0),l.info(`Row swap validation: ${s} has ${n.length} unique values:`,n),e<0||t<0||e>=n.length||t>=n.length){l.warn("Invalid indices for row swap operation:",{fromIndex:e,toIndex:t,totalRows:n.length,fieldName:s});return}if(e!==t)try{const i=n[e],o=n[t],u=[...this.config.data||[]],d=[...n];d[e]=o,d[t]=i,this.state.customRowOrder={fieldName:s,order:d},u.sort((h,g)=>{const m=d.indexOf(h[s]),C=d.indexOf(g[s]);return m-C}),this.config.data=u,this.state.rawData=u,this.state.data=u,this.state.processedData=this.generateProcessedDataForDisplay(),this.state.groups.length>0&&this.updateAggregates(),typeof this.config.onRowDragEnd=="function"&&this.config.onRowDragEnd(e,t,this.state.rowGroups),l.info(`Row swap completed successfully for field: ${s}`),this._emit()}catch(i){l.error("Error during row swap operation:",i)}}swapDataColumns(e,t){const r=this.state.columns&&this.state.columns.length>0?this.state.columns[0]:null;if(!r){l.warn("No column field configured for swapping");return}const s=r.uniqueName,a=this.state.customColumnOrder;let n;if(a&&a.fieldName===s&&a.order?n=[...a.order]:n=[...new Set((this.config.data||[]).map(i=>i[s]))].filter(i=>typeof i=="string"&&i!==null&&i!==void 0),l.info(`Column swap validation: ${s} has ${n.length} unique values:`,n),e<0||t<0||e>=n.length||t>=n.length){l.warn("Invalid indices for column swap operation:",{fromIndex:e,toIndex:t,totalColumns:n.length,fieldName:s});return}if(e!==t)try{const i=n[e],o=n[t],u=[...n];if(u[e]=o,u[t]=i,this.state.columns&&this.state.columns.length>0){const d=[...this.state.columns],h=d.findIndex(m=>m.uniqueName===i),g=d.findIndex(m=>m.uniqueName===o);h!==-1&&g!==-1&&([d[h],d[g]]=[d[g],d[h]],this.state.columns=d,l.info("Updated column configurations"))}if(this.state.customColumnOrder={fieldName:s,order:u},this.state.processedData=this.generateProcessedDataForDisplay(),this.state.groups.length>0&&this.updateAggregates(),typeof this.config.onColumnDragEnd=="function"){const d=u.map(h=>({uniqueName:h,caption:h}));this.config.onColumnDragEnd(e,t,d)}l.info(`Column swap completed successfully for field: ${s}`),this._emit()}catch(i){l.error("Error during column swap operation:",i)}}getUniqueFieldValues(e){const t=this.config.data||[];l.info(`Getting unique values for field: ${e} from ${t.length} total items`);const r=[...new Set(t.map(s=>s[e]))].filter(s=>typeof s=="string"&&s!==null&&s!==void 0);return l.info(`Found ${r.length} unique values for ${e}:`,r),r}getOrderedUniqueFieldValues(e,t=!1){const r=t?this.state.customRowOrder:this.state.customColumnOrder;return r&&r.fieldName===e&&r.order?(l.info(`Using custom order for ${e}:`,r.order),r.order):this.getUniqueFieldValues(e)}getRowFieldName(){return this.state.rows&&this.state.rows.length>0?this.state.rows[0].uniqueName:null}getColumnFieldName(){return this.state.columns&&this.state.columns.length>0?this.state.columns[0].uniqueName:null}setCustomFieldOrder(e,t,r=!0){const s={fieldName:e,order:t};r?this.state.customRowOrder=s:this.state.customColumnOrder=s,this.state.processedData=this.generateProcessedDataForDisplay(),this._emit()}getOrderedColumnValues(){const e=this.state.customColumnOrder;return e&&e.order&&e.order.length>0?(l.info("Engine returning custom column order:",e.order),e.order):(l.info("Engine has no custom column order"),null)}getOrderedRowValues(){const e=this.state.customRowOrder;return e&&e.order&&e.order.length>0?(l.info("Engine returning custom row order:",e.order),e.order):(l.info("Engine has no custom row order"),null)}swapRawDataRows(e,t){if(!this.state.data||this.state.data.length===0){l.warn("No data available for raw row swap");return}if(e<0||t<0||e>=this.state.data.length||t>=this.state.data.length){l.warn("Invalid indices for raw row swap operation:",{fromIndex:e,toIndex:t,totalRows:this.state.data.length});return}if(e!==t)try{const r=[...this.state.data],s=r[e];r[e]=r[t],r[t]=s,this.state.data=r,this.state.rawData=r,this.state.dataHandlingMode==="raw"?this.state.processedData=this.generateProcessedDataForDisplay():this.state.processedData=this.generateProcessedDataForDisplay(),this._emit()}catch(r){l.error("Error during raw row swap operation:",r)}}hasAggregatedFilters(){return this.filterConfig.some(e=>e.field.includes("_")&&this.state.measures.some(t=>e.field===`${t.aggregation}_${t.uniqueName}`))}filterProcessedData(e){this.state.groupConfig&&this.applyGrouping(e);const t=this.filterConfig.filter(a=>a.field.includes("_")&&this.state.measures.some(n=>a.field===`${n.aggregation}_${n.uniqueName}`)),r=this.filterConfig.filter(a=>!a.field.includes("_")||!this.state.measures.some(n=>a.field===`${n.aggregation}_${n.uniqueName}`));let s=e;return r.length>0&&(s=s.filter(a=>r.every(n=>{const i=a[n.field],o=typeof i=="number"?Number(n.value):n.value;switch(n.operator){case"equals":return typeof i=="string"&&typeof o=="string"?i.toLowerCase()===o.toLowerCase():i===o;case"contains":return String(i).toLowerCase().includes(String(o).toLowerCase());case"greaterThan":return Number(i)>Number(o);case"lessThan":return Number(i)<Number(o);case"between":{const u=o;return i>=u[0]&&i<=u[1]}default:return!0}}))),t.length>0&&(this.state.groupConfig&&this.applyGrouping(s),s=this.state.groups.filter(n=>t.every(i=>{const o=n.aggregates[i.field],u=typeof i.value=="string"?Number(i.value):i.value;switch(i.operator){case"equals":return o===u;case"greaterThan":return o>u;case"lessThan":return o<u;case"between":{const d=Array.isArray(u)?u:[u,u];return o>=Number(d[0])&&o<=Number(d[1])}default:return!0}})).flatMap(n=>n.items)),s}setLayout(e,t,r){this.state.rows=e||[],this.state.columns=t||[],this.state.measures=this.normalizeMeasures(r||[]),this.state.selectedMeasures=[...this.state.measures],this.state.selectedDimensions=[...e.map(s=>({field:s.uniqueName,label:s.caption||s.uniqueName,type:"string"})),...t.map(s=>({field:s.uniqueName,label:s.caption||s.uniqueName,type:"string"}))],this.ensureSyntheticAllColumn(),this.state.processedData=this.generateProcessedDataForDisplay(),this.updateAggregates(),this._emit()}setRowsAndColumns(e,t){this.state.rows=e||[],this.state.columns=t||[],this.ensureSyntheticAllColumn(),this.state.processedData=this.generateProcessedDataForDisplay(),this.updateAggregates(),this._emit()}normalizeMeasures(e=[]){return(e||[]).map(t=>!(!!t.caption&&t.caption.trim().toLowerCase()!==t.uniqueName.toLowerCase())&&(t.aggregation||this.config.defaultAggregation)==="sum"?{...t,caption:`sum of ${t.uniqueName}`}:t)}}class Ue{static getAvailableFields(e){const r=e.getState().rawData||[];if(!Array.isArray(r)||r.length===0)return[];const s=r.slice(0,Math.min(200,r.length)),a=new Set;s.forEach(i=>Object.keys(i||{}).forEach(o=>a.add(o)));const n=[];return a.forEach(i=>{n.push({name:i,type:this.inferFieldType(s,i)})}),n.sort((i,o)=>i.name.localeCompare(o.name))}static getSupportedAggregations(){return["sum","avg","min","max","count"]}static setMeasureAggregation(e,t,r){const a=[...e.getState().measures],n=a.findIndex(i=>i.uniqueName===t);n===-1?a.push(this.buildMeasure(t,r)):a[n]={...a[n],aggregation:r},e.setMeasures(a)}static buildLayout(e){const t=(e.rows||[]).map(a=>({uniqueName:a,caption:this.toCaption(a)})),r=(e.columns||[]).map(a=>({uniqueName:a,caption:this.toCaption(a)})),s=(e.values||[]).map(a=>this.buildMeasure(a.field,a.aggregation));return{rows:t,columns:r,measures:s}}static buildMeasure(e,t){const r=t||"sum";return{uniqueName:e,caption:`${this.capitalize(r)} of ${this.toCaption(e)}`,aggregation:r}}static inferFieldType(e,t){let r=0,s=0;return e.forEach(a=>{const n=a?.[t];if(n==null)return;typeof n=="number"||!isNaN(Number(n))&&n!==""?r++:this.looksLikeDate(n)&&s++}),r>0&&r>=s?"number":s>0?"date":"string"}static looksLikeDate(e){if(typeof e!="string"&&!(e instanceof Date))return!1;const t=Date.parse(String(e));return!isNaN(t)}static toCaption(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/[_-]+/g," ").replace(/^\w/,t=>t.toUpperCase())}static capitalize(e){return e.charAt(0).toUpperCase()+e.slice(1)}}class He{constructor(e,t){this.workers=[],this.taskQueue=[],this.nextTaskId=0,this.workerUrl=e,this.workerCount=t||Math.max(1,navigator.hardwareConcurrency-1),this.initializeWorkers()}initializeWorkers(){for(let e=0;e<this.workerCount;e++){const t=new Worker(this.workerUrl,{type:"module"});this.workers.push({worker:t,busy:!1})}}execute(e){return new Promise((t,r)=>{const a={id:this.nextTaskId++,data:e,resolve:t,reject:r};this.taskQueue.push(a),this.processQueue()})}processQueue(){const e=this.workers.find(a=>!a.busy);if(!e||this.taskQueue.length===0)return;const t=this.taskQueue.shift();if(!t)return;e.busy=!0,e.currentTaskId=t.id;const r=a=>{const n=a.data;n.type==="CHUNK_PARSED"?(e.worker.removeEventListener("message",r),e.worker.removeEventListener("error",s),e.busy=!1,e.currentTaskId=void 0,n.error?t.reject(new Error(n.error)):t.resolve(n),this.processQueue()):n.type},s=a=>{e.worker.removeEventListener("message",r),e.worker.removeEventListener("error",s),e.busy=!1,e.currentTaskId=void 0,t.reject(a),this.processQueue()};e.worker.addEventListener("message",r),e.worker.addEventListener("error",s),e.worker.postMessage(t.data)}terminate(){this.workers.forEach(({worker:e})=>e.terminate()),this.workers=[],this.taskQueue=[]}getWorkerCount(){return this.workers.length}getBusyCount(){return this.workers.filter(e=>e.busy).length}getQueuedCount(){return this.taskQueue.length}}const te=class te{static async readFileInChunks(e,t={}){const r=t.chunkSizeBytes||this.DEFAULT_CHUNK_SIZE,s=e.size;let a=0,n=0;if(!e.stream)return this.readFileInChunksLegacy(e,t);try{const o=e.stream().getReader(),u=new TextDecoder(t.encoding||"utf-8");let d="",h=!1,g=!1;for(;!h&&!g;){if(t.signal?.aborted){g=!0,o.cancel();break}const{value:m,done:C}=await o.read();if(h=C,m)for(a+=m.length,d+=u.decode(m,{stream:!h});d.length>=r||h&&d.length>0;){if(t.signal?.aborted){g=!0,h||o.cancel();break}const S=d.slice(0,r);d=d.slice(r);const b=Math.min(100,a/s*100),f={chunkId:n++,text:S,isFirstChunk:n===1,isLastChunk:h&&d.length===0,progress:b};if(t.onChunk&&await t.onChunk(f),t.onProgress&&t.onProgress(b),h&&d.length===0)break}}if(d.length>0){const m={chunkId:n++,text:d,isFirstChunk:n===1,isLastChunk:!0,progress:100};t.onChunk&&await t.onChunk(m),t.onProgress&&t.onProgress(100)}}catch(i){throw l.error("Error reading file stream:",i),i}}static async readFileInChunksLegacy(e,t={}){const r=t.chunkSizeBytes||this.DEFAULT_CHUNK_SIZE,s=e.size;let a=0,n=0;for(;a<s&&!t.signal?.aborted;){const i=Math.min(a+r,s),o=e.slice(a,i),u=await this.readBlobAsText(o,t.encoding),d=Math.min(100,i/s*100),h={chunkId:n++,text:u,isFirstChunk:a===0,isLastChunk:i>=s,progress:d};t.onChunk&&await t.onChunk(h),t.onProgress&&t.onProgress(d),a=i}}static readBlobAsText(e,t){return new Promise((r,s)=>{const a=new FileReader;a.onload=()=>{r(a.result)},a.onerror=()=>{s(new Error("Failed to read blob"))},a.readAsText(e,t||"utf-8")})}static getOptimalChunkSize(e){return e<1024*1024?256*1024:e<10*1024*1024?1024*1024:e<100*1024*1024?2*1024*1024:5*1024*1024}};te.DEFAULT_CHUNK_SIZE=1024*1024;let W=te;function fe(){return typeof process<"u"&&process.versions!=null&&process.versions.node!=null}function Ie(){try{if(typeof __dirname<"u")return new Function("module","return require(module)")("path").join(__dirname,"wasm","csvParser.wasm")}catch(c){l.warn("Could not resolve __dirname:",c)}return"./dist/wasm/csvParser.wasm"}function me(){if(fe())return Ie();try{if(typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:E&&E.tagName.toUpperCase()==="SCRIPT"&&E.src||new URL("pivothead-core.js",document.baseURI).href}<"u"&&(typeof document>"u"?require("url").pathToFileURL(__filename).href:E&&E.tagName.toUpperCase()==="SCRIPT"&&E.src||new URL("pivothead-core.js",document.baseURI).href)){const c=typeof document>"u"?require("url").pathToFileURL(__filename).href:E&&E.tagName.toUpperCase()==="SCRIPT"&&E.src||new URL("pivothead-core.js",document.baseURI).href,t=`${c.substring(0,c.lastIndexOf("/"))}/csvParser.wasm`;return l.info(`Computed WASM URL: ${t}`),t}}catch(c){l.warn("import.meta.url not available:",c)}return l.warn("Using fallback WASM path"),"/wasm/csvParser.wasm"}function J(c){return c.length>=4&&c[0]===0&&c[1]===97&&c[2]===115&&c[3]===109}function Ge(c){const e=new Function("module","return require(module)"),t=e("fs"),r=e("path"),s=[c,r.resolve(c),r.join(__dirname,"wasm","csvParser.wasm"),r.join(__dirname,"csvParser.wasm"),r.join(__dirname,"../wasm/csvParser.wasm"),r.join(process.cwd(),"node_modules/@mindfiredigital/pivothead/dist/wasm/csvParser.wasm")];for(const a of s)try{if(t.existsSync(a)){l.info(`✅ Loading WASM from: ${a}`);const n=t.readFileSync(a),i=n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength),o=new Uint8Array(i);if(J(o))return i;l.warn(`Invalid WASM file at ${a}`)}}catch{}throw new Error(`WASM file not found. Tried paths:
${s.join(`
`)}
Make sure the package is properly installed.`)}async function je(){const c=me();if(fe())try{return Ge(c)}catch(e){throw l.error("Failed to load WASM in Node.js:",e),e}try{const e=await fetch(c);if(!e.ok)throw new Error(`HTTP ${e.status}: ${e.statusText}`);const t=await e.arrayBuffer(),r=new Uint8Array(t);if(J(r))return t;{const s=String.fromCharCode(...r.slice(0,4));throw s==="<!DO"||s==="<htm"?new Error(`Received HTML instead of WASM binary from ${c} - likely a 404 error`):new Error(`Invalid WASM file format from ${c}`)}}catch(e){l.warn(`Failed to fetch WASM from ${c}:`,e);const t=["/wasm/csvParser.wasm","/node_modules/@mindfiredigital/pivothead/dist/wasm/csvParser.wasm"];for(const r of t)if(r!==c)try{l.info(`Trying fallback URL: ${r}`);const s=await fetch(r);if(!s.ok)continue;const a=await s.arrayBuffer(),n=new Uint8Array(a);if(J(n))return l.info(`✅ Successfully loaded WASM from fallback: ${r}`),a}catch(s){l.warn(`Fallback ${r} failed:`,s)}throw new Error(`Failed to fetch WASM from ${c} and all fallback URLs. Make sure to run 'pnpm build:wasm' in the core package.`)}}let V=null;async function Be(){if(V)return V;try{return V=(await Promise.resolve().then(()=>require("./index-CWmb6Rej.js"))).instantiate,V}catch(c){return l.warn("AssemblyScript loader not available:",c),null}}const _=class _{constructor(){this.wasmModule=null,this.isLoaded=!1,this.loadPromise=null}static getInstance(){return _.instance||(_.instance=new _),_.instance}static isSupported(){try{return typeof WebAssembly<"u"&&typeof WebAssembly.instantiate=="function"}catch{return!1}}async load(){if(!this.isLoaded)return this.loadPromise?this.loadPromise:(this.loadPromise=this._loadModule(),this.loadPromise)}async _loadModule(){try{const e=await Be();if(!e)throw new Error("@assemblyscript/loader not available. Install with: pnpm add @assemblyscript/loader");if(!_.isSupported())throw new Error("WebAssembly is not supported in this browser");l.info("🚀 Loading WebAssembly CSV parser...");const t=me();l.info(`Loading WASM from: ${t}`);let r;try{r=await je(),l.info(`✅ WASM file loaded successfully (${r.byteLength} bytes)`)}catch(a){throw l.error(`❌ Failed to fetch WASM file from ${t}:`,a),new Error(`WASM file not found at ${t}. Make sure to run 'npm run build:wasm' in the core package.`)}this.wasmModule=await e(r,{env:{abort:(a,n,i,o)=>{l.error(`WASM abort: ${a} at ${n}:${i}:${o}`)}}}),this.isLoaded=!0;const s=this.wasmModule.exports.getVersion();l.info(`✅ WebAssembly CSV parser loaded successfully (v${s})`)}catch(e){throw this.isLoaded=!1,this.loadPromise=null,l.error("❌ Failed to load WASM module:",e),e}}isModuleLoaded(){return this.isLoaded}parseCSVChunk(e,t={}){if(!this.isLoaded||!this.wasmModule)throw new Error("WASM module not loaded. Call load() first.");const r=t.delimiter?.charCodeAt(0)??44,s=t.hasHeader??!0,a=t.trimValues??!0;try{const n=this.wasmModule.exports.parseCSVChunk(this.wasmModule.exports.__newString(e),r,s?1:0,a?1:0),i=this.wasmModule.exports.getLastRowCount(),o=this.wasmModule.exports.getLastColCount(),u=this.wasmModule.exports.getLastErrorMessage(),d=this.wasmModule.exports.__getString(u);return{rowCount:i,colCount:o,errorCode:n,errorMessage:d}}catch(n){throw l.error("Error in WASM parseCSVChunk:",n),n}}extractField(e,t,r,s=!0){if(!this.isLoaded||!this.wasmModule)throw new Error("WASM module not loaded. Call load() first.");const a=this.wasmModule.exports.extractField(this.wasmModule.exports.__newString(e),t,r,s?1:0);return this.wasmModule.exports.__getString(a)}parseNumber(e){if(!this.isLoaded||!this.wasmModule)throw new Error("WASM module not loaded. Call load() first.");return this.wasmModule.exports.parseNumber(this.wasmModule.exports.__newString(e))}detectFieldType(e){if(!this.isLoaded||!this.wasmModule)throw new Error("WASM module not loaded. Call load() first.");return this.wasmModule.exports.detectFieldType(this.wasmModule.exports.__newString(e))}estimateMemory(e,t){if(!this.isLoaded||!this.wasmModule)throw new Error("WASM module not loaded. Call load() first.");return this.wasmModule.exports.estimateMemory(e,t)}getVersion(){if(!this.isLoaded||!this.wasmModule)throw new Error("WASM module not loaded. Call load() first.");const e=this.wasmModule.exports.getVersion();return this.wasmModule.exports.__getString(e)}benchmark(e){if(!this.isLoaded||!this.wasmModule)throw new Error("WASM module not loaded. Call load() first.");return this.wasmModule.exports.benchmark(this.wasmModule.exports.__newString(e))}unload(){this.wasmModule&&this.wasmModule.exports.__release&&this.wasmModule.exports.__release(),this.wasmModule=null,this.isLoaded=!1,this.loadPromise=null}};_.instance=null;let L=_;const ge=()=>L.getInstance();class Ke{constructor(){this.isInitialized=!1,this.wasmLoader=ge()}async initialize(){if(this.isInitialized)return!0;try{return L.isSupported()?(await this.wasmLoader.load(),this.isInitialized=!0,!0):(l.warn("⚠️ WebAssembly not supported, falling back to Web Workers"),!1)}catch(e){return l.warn("⚠️ Failed to initialize WASM:",e),!1}}isReady(){return this.isInitialized&&this.wasmLoader.isModuleLoaded()}async processCSV(e,t={}){const r=performance.now();try{if(!this.isReady())throw new Error("WASM module not initialized");const{delimiter:s=",",hasHeader:a=!0,trimValues:n=!0,skipEmptyLines:i=!0}=t;l.info("🚀 Processing CSV with WebAssembly...");const o=this.wasmLoader.parseCSVChunk(e,{delimiter:s,hasHeader:a,trimValues:n});if(o.errorCode!==0)throw new Error(o.errorMessage||"WASM parsing failed");l.info(`📊 WASM parsed: ${o.rowCount} rows, ${o.colCount} columns`);const u=this.parseCSVRows(e,{delimiter:s,hasHeader:a,trimValues:n,skipEmptyLines:i});let d,h;t.providedHeaders&&t.providedHeaders.length>0?(d=t.providedHeaders,h=u):a&&u.length>0?(d=u[0],h=u.slice(1)):(d=void 0,h=u);const g=this.rowsToObjects(h,d),m=performance.now()-r;return l.info(`✅ WASM processing completed in ${m.toFixed(2)}ms`),{success:!0,data:g,headers:d,rowCount:h.length,colCount:o.colCount,parseTime:m}}catch(s){const a=performance.now()-r;return l.error("❌ WASM processing error:",s),{success:!1,data:[],rowCount:0,colCount:0,parseTime:a,error:s instanceof Error?s.message:"Unknown error"}}}parseCSVRows(e,t){const{delimiter:r=",",trimValues:s=!0,skipEmptyLines:a=!0}=t,n=[];let i=[],o="",u=!1;for(let d=0;d<e.length;d++){const h=e[d],g=d+1<e.length?e[d+1]:"";u?h==='"'?g==='"'?(o+='"',d++):u=!1:o+=h:h==='"'?u=!0:h===r?(i.push(s?o.trim():o),o=""):h===`
`||h==="\r"?(h==="\r"&&g===`
`&&d++,i.push(s?o.trim():o),o="",(!a||i.some(m=>m!==""))&&n.push(i),i=[]):o+=h}return(o!==""||i.length>0)&&(i.push(s?o.trim():o),(!a||i.some(d=>d!==""))&&n.push(i)),n}rowsToObjects(e,t){return!t||t.length===0?e.map(r=>({...r})):e.map(r=>{const s={};return t.forEach((a,n)=>{const i=r[n]??"";if(this.isReady()&&i!=="")switch(this.wasmLoader.detectFieldType(i)){case 1:s[a]=this.wasmLoader.parseNumber(i);break;case 2:s[a]=i.toLowerCase()==="true";break;case 3:s[a]=null;break;default:s[a]=i}else s[a]=i}),s})}async processFile(e,t={}){try{if(e.size>O)return l.warn(`⚠️ File too large for WASM (${(e.size/1024/1024).toFixed(2)}MB > 8MB). Should use Web Workers instead.`),{success:!1,data:[],rowCount:0,colCount:0,parseTime:0,error:`File too large for WASM processing (${(e.size/1024/1024).toFixed(2)}MB). Falling back to Web Workers.`};const r=await e.text();return this.processCSV(r,t)}catch(r){return{success:!1,data:[],rowCount:0,colCount:0,parseTime:0,error:r instanceof Error?r.message:"Unknown error"}}}estimateMemory(e,t){return this.isReady()?this.wasmLoader.estimateMemory(e,t):e*t*64}getVersion(){return this.isReady()?this.wasmLoader.getVersion():"N/A"}cleanup(){this.wasmLoader&&this.wasmLoader.unload(),this.isInitialized=!1}}let I=null;const oe=()=>(I||(I=new Ke),I);function pe(c){if(c==null)return null;if(typeof c=="number")return isFinite(c)?c:null;if(typeof c!="string")return null;let e=c.trim();if(!e)return null;const t=/[€£¥₹$]/.test(e),r=/[A-Za-z]/.test(e),s=/[.,]/.test(e),a=e.startsWith("(")&&e.endsWith(")");if(r&&!t||!t&&!s&&!a)return null;let n=!1;if(a&&(n=!0,e=e.slice(1,-1)),e=e.replace(/[^0-9,.-]/g,""),(e.match(/-/g)||[]).length>1)return null;e=e.replace(/(.*)-(.*)/,"-$1$2");const i=e.includes("."),o=e.includes(","),u=e.lastIndexOf("."),d=e.lastIndexOf(",");let h=e;if(i&&o){const m=u>d?".":",",C=m==="."?",":".";h=h.split(C).join(""),h=h.replace(m,".")}else if(o&&!i){const m=e.split(",");if(m.length>2)h=m.join("");else if(m.length===2){const C=m[1];C.length===2||C.length===3?h=m[0