@cristianmpx/react-import-sheet-headless 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,6 +12,73 @@ npm install @cristianmpx/react-import-sheet-headless
12
12
 
13
13
  **Peer dependencies:** React 18+ (`react` and `react-dom`).
14
14
 
15
+ ### ⚙️ Framework Setup
16
+
17
+ **Important:** Web Workers require specific configuration depending on your framework. See [FRAMEWORK-SETUP.md](./FRAMEWORK-SETUP.md) for detailed instructions.
18
+
19
+ **Quick config:**
20
+
21
+ <details>
22
+ <summary><strong>Vite + React</strong></summary>
23
+
24
+ ```typescript
25
+ // vite.config.ts
26
+ export default defineConfig({
27
+ optimizeDeps: {
28
+ exclude: ['@cristianmpx/react-import-sheet-headless'],
29
+ },
30
+ worker: {
31
+ format: 'es',
32
+ },
33
+ });
34
+ ```
35
+
36
+ </details>
37
+
38
+ <details>
39
+ <summary><strong>Next.js</strong></summary>
40
+
41
+ ```javascript
42
+ // next.config.js
43
+ module.exports = {
44
+ webpack: (config, { isServer }) => {
45
+ if (!isServer) {
46
+ config.module.rules.push({
47
+ test: /\.worker\.js$/,
48
+ use: { loader: 'worker-loader' },
49
+ });
50
+ }
51
+ return config;
52
+ },
53
+ };
54
+ ```
55
+
56
+ **Important:** Use `dynamic` import with `ssr: false`:
57
+
58
+ ```typescript
59
+ const Importer = dynamic(() => import('./Importer'), { ssr: false });
60
+ ```
61
+
62
+ </details>
63
+
64
+ <details>
65
+ <summary><strong>Storybook</strong></summary>
66
+
67
+ ```typescript
68
+ // .storybook/main.ts
69
+ async viteFinal(config) {
70
+ config.optimizeDeps = {
71
+ exclude: ['@cristianmpx/react-import-sheet-headless'],
72
+ };
73
+ config.worker = { format: 'es' };
74
+ return config;
75
+ }
76
+ ```
77
+
78
+ </details>
79
+
80
+ See [FRAMEWORK-SETUP.md](./FRAMEWORK-SETUP.md) for CRA, Remix, and Webpack configurations.
81
+
15
82
  ## Why Headless
16
83
 
17
84
  Bring your own components; we provide the logic, Web Worker performance, and bulk validation. No prebuilt `<Table />`—you own the UI and the UX.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import{a as Q,b as he,c as ye}from"./chunk-UCBBDF6X.js";import{a as V}from"./chunk-YETPLYYC.js";import{useEffect as tt,useMemo as F,useRef as be,useState as re}from"react";var k="react-import-sheet-persist",Z="react-import-sheet-session";import{createContext as $e}from"react";var N=$e(null);var ge={file:null,rawData:null,documentHash:null,status:"idle",result:null,convertedSheet:null,sanitizedSheet:null,convertResultData:null,metrics:null,changeLog:[],submitDone:!1};import{useCallback as T,useMemo as Ge}from"react";function _(t){return t<.01&&t>=0?"0.00ms":t<1?`${(t*1e3).toFixed(2)}\u03BCs`:`${t.toFixed(2)}ms`}function ee(t,e,r){let s=t.parse+t.sanitize+t.validate+t.transform,o=s>2e3,i=`${(e>0?s/e:0).toFixed(4)}ms/row`,n;if(s>0){let u=r??0,c=s+u;n={parse:t.parse/c*100,sanitize:t.sanitize/c*100,validate:t.validate/c*100,transform:t.transform/c*100,overhead:c>0?u/c*100:0}}return{timings:{...t},percentages:n,totalMs:s,isSlow:o,parseTime:_(t.parse),sanitizeTime:_(t.sanitize),validateTime:_(t.validate),transformTime:_(t.transform),totalTime:_(s),efficiency:i,rowCount:e,...r!==void 0&&r>=0?{overheadMs:r}:{}}}function U(t){let e=[];for(let r of t)if(r.type==="cell_edit"){let s=r.previousValue!==void 0?` (previous: ${String(r.previousValue)})`:"";e.push(`Row ${r.rowIndex+1}, cell "${r.cellKey}": set to ${JSON.stringify(r.value)}${s}`)}else e.push(`Row ${r.rowIndex+1}: removed`);return e.join(`
2
- `)}var O="importer-progress",B="importer-aborted";import{useCallback as P}from"react";function q(t){let{setState:e,setLayoutState:r,setEngineState:s}=t,o=P(d=>{e(f=>({...f,file:d}))},[e]),a=P(d=>{e(f=>({...f,rawData:d}))},[e]),i=P(d=>{e(f=>({...f,documentHash:d}))},[e]),n=P(d=>{e(f=>({...f,status:d}))},[e]),u=P(d=>{e(f=>({...f,result:d}))},[e]),c=P(d=>{e(f=>({...f,convertedSheet:d,convertResultData:null}))},[e]),p=P(d=>{e(f=>({...f,sanitizedSheet:d}))},[e]),S=P(d=>{e(f=>({...f,convertResultData:typeof d=="function"?d(f.convertResultData):d,convertedSheet:typeof d=="function"?f.convertedSheet:null}))},[e]),l=P(d=>{e(f=>({...f,metrics:d}))},[e]),m=P(d=>{e(f=>({...f,submitDone:d}))},[e]),y=P(d=>{r(d)},[r]),x=P(d=>{s(d)},[s]);return{setLayout:y,setEngine:x,setFile:o,setRawData:a,setDocumentHash:i,setStatus:n,setResult:u,setConvertedSheet:c,setSanitizedSheet:p,setConvertResultData:S,setMetrics:l,setSubmitDone:m}}var Ye={parse:0,sanitize:0,validate:0,transform:0};function Se(t){let{setState:e,setLayoutState:r,setEngineState:s,progressEventTarget:o,validatorRegistry:a,sanitizerRegistry:i,transformRegistry:n,activeWorkerRef:u,phaseTimingsRef:c}=t,p=q({setState:e,setLayoutState:r,setEngineState:s}),S=T(h=>{o.dispatchEvent(new CustomEvent(O,{detail:h}))},[o]),l=T(h=>{u.current=h},[u]),m=T(()=>{let h=u.current;h&&(h.terminate(),u.current=null),e(R=>({...R,status:"cancelled"})),o.dispatchEvent(new CustomEvent(B))},[u,o,e]),y=T((h,R)=>{c.current={...c.current,[h]:R}},[c]),x=T(h=>{let R={...c.current},v=ee(R,h);p.setMetrics(v)},[c,p]),d=T(h=>{e(R=>({...R,changeLog:[...R.changeLog,h]}))},[e]),f=T(h=>{c.current={...Ye},e(R=>({...R,file:h,status:"loading",rawData:null,documentHash:null,result:null,convertedSheet:null,sanitizedSheet:null,convertResultData:null,metrics:null,changeLog:[],submitDone:!1}))},[c,e]),b=T((h,R,v)=>{a.register(h,R,v)},[a]),C=T((h,R,v)=>{i.register(h,R,v)},[i]),g=T((h,R,v)=>{n.register(h,R,v)},[n]);return Ge(()=>({...p,addChangeLogEntry:d,setPhaseTiming:y,finalizeMetrics:x,processFile:f,registerValidator:b,registerSanitizer:C,registerTransform:g,abort:m,dispatchProgress:S,setActiveWorker:l}),[p,d,y,x,f,b,C,g,m,S,l])}import{useCallback as Ee,useEffect as Pe,useRef as Qe,useState as Ze}from"react";function te(){return new Promise((t,e)=>{let r=indexedDB.open("react-import-sheet-db",1);r.onerror=()=>e(r.error),r.onsuccess=()=>t(r.result),r.onupgradeneeded=()=>{r.result.createObjectStore(k,{keyPath:"key"})}})}async function we(t,e){let r=await te();return new Promise((s,o)=>{let a=r.transaction(k,"readwrite"),i=a.objectStore(k),n={key:t,...e},u=i.put(n);u.onsuccess=()=>s(),u.onerror=()=>o(u.error),a.oncomplete=()=>r.close()})}async function xe(t){let e=await te();return new Promise((r,s)=>{let i=e.transaction(k,"readonly").objectStore(k).get(t);i.onsuccess=()=>{e.close();let n=i.result;if(n==null){r(null);return}let u=n.savedAt;if(Date.now()-u>6048e5){r(null);return}let{key:c,...p}=n;r(p)},i.onerror=()=>s(i.error)})}async function ve(t){let e=await te();return new Promise((r,s)=>{let o=e.transaction(k,"readwrite"),i=o.objectStore(k).delete(t);i.onsuccess=()=>r(),i.onerror=()=>s(i.error),o.oncomplete=()=>e.close()})}var et=2500;function Ce(t,e,r,s,o,a,i){let[n,u]=Ze(null),c=Qe(null);Pe(()=>{t&&xe(e).then(l=>{l&&(l.layoutVersion!=null&&i!=null&&String(l.layoutVersion)!==String(i)||u(l))})},[t,e,i]),Pe(()=>{if(!(!t||!r||!s))return c.current&&clearTimeout(c.current),c.current=setTimeout(()=>{c.current=null;let l={rawData:r,sheet:s,savedAt:Date.now(),layoutVersion:i??void 0,stateSchemaVersion:1};we(e,l).catch(()=>{})},et),()=>{c.current&&clearTimeout(c.current)}},[t,e,r,s,i]);let p=Ee(async()=>{if(!t)return;let l=n;l&&(o(l.rawData),a(l.sheet),u(null))},[t,n,o,a]),S=Ee(async()=>{t&&(await ve(e),u(null))},[t,e]);return{hasRecoverableSession:t&&n!=null,recoverSession:p,clearPersistedState:S}}import{jsx as rt}from"react/jsx-runtime";function oe({children:t,layout:e,engine:r,persist:s=!1,persistKey:o=Z,onSubmit:a=null,submitKeyMap:i=null}){let[n,u]=re(ge),[c,p]=re(e??null),[S,l]=re(r??null),m=F(()=>new EventTarget,[]),y=F(()=>new V,[]),x=F(()=>new V,[]),d=F(()=>new V,[]),f=be(null),b=be({parse:0,sanitize:0,validate:0,transform:0}),C=q({setState:u,setLayoutState:p,setEngineState:l}),g=Ce(s,o,n.rawData,n.result,C.setRawData,C.setResult,c?.version??null),h=Se({setState:u,setLayoutState:p,setEngineState:l,progressEventTarget:m,validatorRegistry:y,sanitizerRegistry:x,transformRegistry:d,activeWorkerRef:f,phaseTimingsRef:b});tt(()=>()=>{let v=f.current;v&&(v.terminate(),f.current=null)},[]);let R=F(()=>({...n,layout:c,engine:S,progressEventTarget:m,...h,onSubmit:a??null,submitKeyMap:i??null,persist:s,persistKey:o,hasRecoverableSession:g.hasRecoverableSession,recoverSession:g.recoverSession,clearPersistedState:g.clearPersistedState}),[n,c,S,m,a,i,h,s,o,g.hasRecoverableSession,g.recoverSession,g.clearPersistedState]);return rt(N.Provider,{value:R,children:t})}import{useContext as ot}from"react";function w(){let t=ot(N);if(t===null)throw new Error("useImporter must be used within an ImporterProvider");return t}import{useCallback as nt,useEffect as Te,useMemo as Ie}from"react";function A(t){return t.rows.filter(e=>e.errors.length>0)}function H(t){return t?K(t).totalErrors>0:!1}function K(t){let e=t.rows.length,r=A(t),s=t.errors.length+t.rows.reduce((o,a)=>o+a.errors.length+a.cells.reduce((i,n)=>i+n.errors.length,0),0);return{totalRows:e,rowsWithErrors:r.length,totalErrors:s}}function ne(t,e){return t.cells.find(s=>s.key===e)?.value}function se(t,e){return t.map(e)}function W(t,e){return t?t.rows.map(r=>{let s={};for(let[o,a]of Object.entries(e))s[a]=ne(r,o);return s}):[]}function st(t){return t.rows.map(e=>e.cells.reduce((r,s)=>({...r,[s.key]:s.value}),{}))}function ke(t={}){let e=w(),{layout:r,engine:s}=t;Te(()=>{r!==void 0&&e.setLayout(r)},[e,r]),Te(()=>{s!==void 0&&e.setEngine(s)},[e,s]);let o=Ie(()=>!!(e.result&&e.status==="success"&&!e.submitDone&&!H(e.result)),[e.result,e.status,e.submitDone]),a=nt(()=>{if(!e.result||e.submitDone||H(e.result)||!e.onSubmit)return;let i=e.submitKeyMap?W(e.result,e.submitKeyMap):st(e.result);e.onSubmit(i),e.setSubmitDone(!0)},[e]);return Ie(()=>({processFile:e.processFile,registerValidator:e.registerValidator,registerSanitizer:e.registerSanitizer,registerTransform:e.registerTransform,abort:e.abort,metrics:e.metrics,submit:a,canSubmit:o,submitDone:e.submitDone}),[e.processFile,e.registerValidator,e.registerSanitizer,e.registerTransform,e.abort,e.metrics,a,o,e.submitDone])}import{useCallback as ut,useEffect as ct}from"react";import{useCallback as Me,useEffect as it,useRef as at,useState as lt}from"react";import*as J from"comlink";function je(){return new URL("./parser.worker.js",import.meta.url).href}function Oe(){let{setActiveWorker:t,dispatchProgress:e}=w(),[r,s]=lt(null),o=at(null);it(()=>{let n=new Worker(je(),{type:"module"});o.current=n,t(n);let u=J.wrap(n);return queueMicrotask(()=>s(u)),()=>{n.terminate(),o.current=null,t(null)}},[t]);let a=Me(async(n,u={})=>{if(!r)throw new Error("Parser worker not ready");return r.load(n,u)},[r]),i=Me(async n=>{if(!r)throw new Error("Parser worker not ready");let u=n?J.proxy(n):void 0;return r.parseAll(u)},[r]);return{load:a,parseAll:i,dispatchProgress:e,isReady:!!r}}function Le(t){let e=Object.keys(t.sheets);return e.length===0?null:t.sheets[e[0]??""]??null}function De(){let t=w(),{load:e,parseAll:r,isReady:s}=Oe();return ct(()=>{let{file:a,status:i,engine:n}=t;!s||!a||i!=="loading"||e(a,{maxRows:10,fileName:a.name,engine:n??void 0}).then(u=>{if(!Le(u)){t.setStatus("error");return}let p=u.sheets[Object.keys(u.sheets)[0]??""];if(!p){t.setStatus("error");return}t.setRawData(p),t.setDocumentHash(p.documentHash),t.setStatus("success")}).catch(()=>{t.setStatus("error")})},[s,t.file,t.status,t.setRawData,t.setDocumentHash,t.setStatus,e]),{startFullImport:ut(()=>{let{file:a}=t;if(!a)return Promise.reject(new Error("No file loaded"));t.setStatus("loading");let i=performance.now();return r(n=>t.dispatchProgress(n)).then(n=>{let u=performance.now();if(t.setPhaseTiming("parse",u-i),!Le(n))return t.setStatus("error"),n;let p=n.sheets[Object.keys(n.sheets)[0]??""];return p?(t.setRawData(p),t.setDocumentHash(p.documentHash),t.setStatus("success"),n):(t.setStatus("error"),n)})},[t,r])}}import{useCallback as G,useMemo as Fe}from"react";function ie(t,e,r,s){let o=[...r],a=new Map;t.headers.forEach((n,u)=>a.set(n,u));let i=t.rows.map(n=>{let u=r.map(c=>{let p=s[c],S=p!=null?(()=>{let l=a.get(p);return l==null?null:n.cells[l]?.value??null})():null;return{key:c,value:S??null}});return{index:n.index,cells:u}});return{name:t.name,filesize:t.filesize,documentHash:t.documentHash,rowsCount:t.rowsCount,headersCount:t.headersCount,headers:o,rows:i}}function Ve(t){return t.trim().toLowerCase().normalize("NFD").replace(/\p{Diacritic}/gu,"")}function pt(t,e){if(t.length===0)return e.length;if(e.length===0)return t.length;let r=Array.from({length:e.length+1},(s,o)=>o);for(let s=1;s<=t.length;s++){let o=[s];for(let a=1;a<=e.length;a++){let i=t[s-1]===e[a-1]?0:1;o[a]=Math.min(o[a-1]+1,r[a]+1,r[a-1]+i)}r=o}return r[e.length]}function mt(t,e){let r=Ve(t),s=Ve(e),o=r.length>=s.length?r:s,a=r.length<s.length?r:s;if(o.length===0)return 1;let i=pt(o,a);return(o.length-i)/o.length}var dt=.8;function _e(t,e,r={}){let s=r.threshold??dt,o=[];for(let u of e)for(let c of t){let p=mt(u,c);p>=s&&o.push({key:u,header:c,score:p})}o.sort((u,c)=>c.score-u.score);let a=new Set,i=new Set,n={};for(let u of e)n[u]=null;for(let{key:u,header:c,score:p}of o)a.has(u)||i.has(c)||(n[u]=c,a.add(u),i.add(c));return e.map(u=>({key:u,matchedHeader:n[u]??null}))}function ft(t,e){let r=t.trim();return e?r:r.toLowerCase()}function ae(t,e,r={},s={}){let o=s.caseSensitive??!1,a=s.normalizer??(l=>ft(l,o)),i=Object.keys(e.fields),n=t.headers,u=new Map;for(let l of n)u.set(a(l),l);let c={},p=new Set;for(let[l,m]of Object.entries(r))i.includes(m)&&(c[m]=n.includes(l)?l:null,c[m]&&p.add(l));for(let l of i){if(c[l]!=null)continue;let m=a(l),y=u.get(m);y!=null&&!p.has(y)?(c[l]=y,p.add(y)):c[l]=null}if(s.fuzzyHeaders===!0){let l=i.filter(d=>c[d]==null),m=n.filter(d=>!p.has(d)),y=s.fuzzyThreshold??.8,x=_e(m,l,{threshold:y});for(let{key:d,matchedHeader:f}of x)f!=null&&!p.has(f)&&(c[d]=f,p.add(f))}let S=[];for(let l of i)if(c[l]==null){let x=e.fields[l]?.required!==!1;S.push({expected:l,found:null,message:`Column '${l}' not found in file`,required:x})}return{fieldToHeader:c,mismatches:S}}function $(t,e,r={},s){let o=Object.keys(e.fields),a=s?.columnOrder?.length?s.columnOrder:o,i=s?.headerToFieldMap??{},{fieldToHeader:n,mismatches:u}=ae(t,e,i,r),p=o.filter(m=>e.fields[m]?.required!==!1).every(m=>n[m]!=null);if(u.length===0||p)return{kind:"success",sheet:ie(t,e,a,n)};let l=u.some(m=>m.required===!0);return{kind:"mismatch",headersFound:[...t.headers],mismatches:u,columnOrder:[...a],headerToFieldMap:{...i},layoutError:l}}function Y(){let t=w(),{rawData:e,layout:r,convertedSheet:s,convertResultData:o,setConvertedSheet:a,setConvertResultData:i}=t,n=G(l=>{if(!e||!r)return;let m=$(e,r,l,o??void 0);m.kind==="success"?a(m.sheet):i({headersFound:m.headersFound,mismatches:m.mismatches,columnOrder:m.columnOrder,headerToFieldMap:m.headerToFieldMap})},[e,r,o,a,i]),u=G(()=>{if(!e||!r||!o)return;let l=$(e,r,{},{columnOrder:o.columnOrder,headerToFieldMap:o.headerToFieldMap});return l.kind==="success"?(a(l.sheet),{kind:"success",sheet:l.sheet}):(i({headersFound:l.headersFound,mismatches:l.mismatches,columnOrder:l.columnOrder,headerToFieldMap:l.headerToFieldMap}),{kind:"mismatch",result:l})},[e,r,o,a,i]),c=G(l=>{i(m=>m&&{...m,columnOrder:l})},[i]),p=G((l,m)=>{i(y=>y&&{...y,headerToFieldMap:{...y.headerToFieldMap,[l]:m}})},[i]),S=Fe(()=>o?{kind:"mismatch",headersFound:o.headersFound,mismatches:o.mismatches,columnOrder:[...o.columnOrder],headerToFieldMap:{...o.headerToFieldMap},reorderColumns:c,renameColumn:p,applyMapping:()=>u()??{kind:"mismatch",result:{...o,kind:"mismatch"}}}:null,[o,c,p,u]);return Fe(()=>({convert:n,convertedSheet:s,convertResult:S}),[n,s,S])}import{useMemo as ht}from"react";function Ae(){let t=w();return ht(()=>({status:t.status,progressEventTarget:t.progressEventTarget}),[t.status,t.progressEventTarget])}import{useCallback as He,useMemo as We}from"react";function ze(){let e=w().result,r=We(()=>e?[...e.errors]:[],[e]),s=He(a=>e?se(e.rows,a):[],[e]),o=He(a=>W(e,a),[e]);return We(()=>({sheet:e,errors:r,toObjects:s,toObjectsWithKeyMap:o}),[e,r,s,o])}import{useCallback as ue,useMemo as ce,useRef as wt}from"react";import{useCallback as yt,useEffect as gt,useRef as St,useState as Rt}from"react";import*as Ue from"comlink";function Ne(){return new URL("./edit.worker.js",import.meta.url).href}function Be(){let[t,e]=Rt(null),r=St(null);return gt(()=>{let o=new Worker(Ne(),{type:"module"});r.current=o;let a=Ue.wrap(o);return queueMicrotask(()=>e(a)),()=>{o.terminate(),r.current=null}},[]),{runEdit:yt(async(o,a,i,n,u,c)=>{if(!t)throw new Error("Edit worker not ready");return t.runEdit(o,a,i,n,u,c??{})},[t]),isReady:!!t}}function qe(t,e,r){return le(t.rows,e,r)}function le(t,e,r){let s=t.length,o=r<=0?0:Math.max(1,Math.ceil(s/r)),a=Math.max(1,Math.min(e,o)),i=(a-1)*r,n=Math.min(i+r,s),u=t.slice(i,n);return{page:a,pageSize:r,totalCount:s,totalPages:o,rows:u}}function X(t={}){let{result:e,setResult:r,layout:s,changeLog:o,addChangeLogEntry:a,submitDone:i}=w(),{runEdit:n,isReady:u}=Be(),c=!i,{page:p=1,pageSize:S=25,debounceMs:l}=t,m=wt(null),y=ce(()=>e?qe(e,p,S):{page:1,pageSize:S,totalCount:0,totalPages:0,rows:[]},[e,p,S]),x=y.totalPages,d=ue(g=>{if(!e||!s||i)return Promise.resolve();let h=Q(e,g.rowIndex)&&he(Q(e,g.rowIndex),g.cellKey)?.value;return n(e,s,g.rowIndex,g.cellKey,g.value).then(R=>{r(R),queueMicrotask(()=>{let v={type:"cell_edit",rowIndex:g.rowIndex,cellKey:g.cellKey,value:g.value,previousValue:h,timestamp:Date.now()};a(v)})})},[e,s,i,n,r,a]),f=ue(g=>{if(l!=null&&l>0){m.current&&clearTimeout(m.current),m.current=setTimeout(()=>{m.current=null,d(g)},l);return}return d(g)},[l,d]),b=ue(g=>{if(!e||i)return;let h=ye(e,g);r(h),queueMicrotask(()=>{let R={type:"row_remove",rowIndex:g,timestamp:Date.now()};a(R)})},[e,i,r,a]),C=ce(()=>U(o),[o]);return ce(()=>({sheet:e,editCell:f,removeRow:b,pageData:y,totalPages:x,isReady:u,canEdit:c,changeLog:o,changeLogAsText:C}),[e,f,b,y,x,u,c,o,C])}import{useCallback as D,useMemo as z,useState as Et}from"react";function Ke(t,e){return t.includes(e)||t.includes('"')||t.includes(`
3
- `)||t.includes("\r")?'"'+t.replace(/"/g,'""')+'"':t}function xt(t,e){return t==null?"":t instanceof Date?e?t.toLocaleString():t.toISOString():String(t)}function pe(t,e,r={}){let{includeHeaders:s=!0,csvSeparator:o=",",formatDatesForExport:a=!1}=r,i=e!=null?Object.keys(e.fields):[],n=i.length>0?i:t.rows[0]?.cells.map(p=>p.key)??t.headers.slice(),u=[];s&&n.length>0&&u.push(n.map(p=>Ke(p,o)).join(o));for(let p of t.rows){let S=n.map(l=>{let y=p.cells.find(x=>x.key===l)?.value??"";return Ke(xt(y,a),o)});u.push(S.join(o))}return"\uFEFF"+u.join(`\r
4
- `)}function vt(t,e){return t==null?null:t instanceof Date?e?t.toLocaleString():t.toISOString():t}function me(t,e,r={}){let{formatDatesForExport:s=!1}=r,o=t.rows.map(a=>{let i={};for(let n of a.cells)i[n.key]=vt(n.value,s);return i});return JSON.stringify(o,null,0)}function de(t={}){let{page:e=1,defaultPageSize:r=25,filterMode:s="all"}=t,[o,a]=Et(e),i=r,{sheet:n,editCell:u,removeRow:c,changeLog:p,changeLogAsText:S}=X({}),l=w(),m=z(()=>n?A(n):[],[n]),y=z(()=>s==="errors-only"?m:n?.rows??[],[s,m,n]),x=y.length,d=D((E,I)=>le(y,E??o,I??i),[o,i,y]),f=z(()=>d(o,i).rows,[d,o,i]),b=D((E,I)=>{let j=(E-1)*I;return y.slice(j,j+I)},[y]),C=z(()=>n?K(n):{totalRows:0,rowsWithErrors:0,totalErrors:0},[n]),g=D(E=>!n||!l.layout?"":pe(n,l.layout,E??{}),[n,l.layout]),h=D(E=>n?me(n,l.layout??null,E??{}):"[]",[n,l.layout]),R=D(async E=>{let I=g(E);if(!I)return;let j=new Blob([I],{type:"text/csv;charset=utf-8"}),L=URL.createObjectURL(j),M=document.createElement("a");M.href=L,M.download=(E?.filename??"export")+".csv",M.click(),URL.revokeObjectURL(L)},[g]),v=D(async E=>{let I=h(E),j=new Blob([I],{type:"application/json"}),L=URL.createObjectURL(j),M=document.createElement("a");M.href=L,M.download=(E?.filename??"export")+".json",M.click(),URL.revokeObjectURL(L)},[h]);return z(()=>({sheet:n,getPaginatedResult:d,paginatedRows:f,page:o,setPage:a,pageSize:i,totalRows:x,getRows:b,rowsWithErrors:m,counts:C,editCell:u,removeRow:c,changeLog:p,changeLogAsText:S,exportToCSV:g,exportToJSON:h,downloadCSV:R,downloadJSON:v,hasRecoverableSession:l.hasRecoverableSession,recoverSession:l.recoverSession,clearPersistedState:l.clearPersistedState}),[n,d,f,o,i,x,b,m,C,u,c,p,S,g,h,R,v,l.hasRecoverableSession,l.recoverSession,l.clearPersistedState])}import{useCallback as Pt,useEffect as Ct}from"react";function fe(){let e=w().progressEventTarget,r=Pt(s=>{let o=a=>{s(a.detail)};return e.addEventListener(O,o),()=>{e.removeEventListener(O,o)}},[e]);return{progressEventTarget:e,subscribeToProgress:r}}function Je(t){let{subscribeToProgress:e}=fe();Ct(()=>e(t),[e,t])}export{B as IMPORTER_ABORTED_EVENT,O as IMPORTER_PROGRESS_EVENT,oe as ImportProvider,oe as ImporterProvider,V as Registry,U as formatChangeLogAsText,ne as getCellValue,H as hasValidationErrors,Y as useConvert,De as useImportSheet,ke as useImporter,fe as useImporterEventTarget,Je as useImporterProgressSubscription,Ae as useImporterStatus,ze as useSheetData,X as useSheetEditor,de as useSheetView};
1
+ import{a as Z,b as ye,c as ge}from"./chunk-UCBBDF6X.js";import{a as V}from"./chunk-YETPLYYC.js";import{useEffect as it,useMemo as F,useRef as Me,useState as oe}from"react";var k="react-import-sheet-persist",ee="react-import-sheet-session";import{createContext as $e}from"react";var N=$e(null);var Se={file:null,rawData:null,documentHash:null,status:"idle",result:null,convertedSheet:null,sanitizedSheet:null,convertResultData:null,metrics:null,changeLog:[],submitDone:!1};import{useCallback as T,useMemo as Ge}from"react";function _(t){return t<.01&&t>=0?"0.00ms":t<1?`${(t*1e3).toFixed(2)}\u03BCs`:`${t.toFixed(2)}ms`}function te(t,e,r){let s=t.parse+t.sanitize+t.validate+t.transform,o=s>2e3,i=`${(e>0?s/e:0).toFixed(4)}ms/row`,n;if(s>0){let u=r??0,c=s+u;n={parse:t.parse/c*100,sanitize:t.sanitize/c*100,validate:t.validate/c*100,transform:t.transform/c*100,overhead:c>0?u/c*100:0}}return{timings:{...t},percentages:n,totalMs:s,isSlow:o,parseTime:_(t.parse),sanitizeTime:_(t.sanitize),validateTime:_(t.validate),transformTime:_(t.transform),totalTime:_(s),efficiency:i,rowCount:e,...r!==void 0&&r>=0?{overheadMs:r}:{}}}function U(t){let e=[];for(let r of t)if(r.type==="cell_edit"){let s=r.previousValue!==void 0?` (previous: ${String(r.previousValue)})`:"";e.push(`Row ${r.rowIndex+1}, cell "${r.cellKey}": set to ${JSON.stringify(r.value)}${s}`)}else e.push(`Row ${r.rowIndex+1}: removed`);return e.join(`
2
+ `)}var O="importer-progress",B="importer-aborted";import{useCallback as P}from"react";function q(t){let{setState:e,setLayoutState:r,setEngineState:s}=t,o=P(d=>{e(f=>({...f,file:d}))},[e]),a=P(d=>{e(f=>({...f,rawData:d}))},[e]),i=P(d=>{e(f=>({...f,documentHash:d}))},[e]),n=P(d=>{e(f=>({...f,status:d}))},[e]),u=P(d=>{e(f=>({...f,result:d}))},[e]),c=P(d=>{e(f=>({...f,convertedSheet:d,convertResultData:null}))},[e]),p=P(d=>{e(f=>({...f,sanitizedSheet:d}))},[e]),S=P(d=>{e(f=>({...f,convertResultData:typeof d=="function"?d(f.convertResultData):d,convertedSheet:typeof d=="function"?f.convertedSheet:null}))},[e]),l=P(d=>{e(f=>({...f,metrics:d}))},[e]),m=P(d=>{e(f=>({...f,submitDone:d}))},[e]),y=P(d=>{r(d)},[r]),x=P(d=>{s(d)},[s]);return{setLayout:y,setEngine:x,setFile:o,setRawData:a,setDocumentHash:i,setStatus:n,setResult:u,setConvertedSheet:c,setSanitizedSheet:p,setConvertResultData:S,setMetrics:l,setSubmitDone:m}}var Ye={parse:0,sanitize:0,validate:0,transform:0};function Re(t){let{setState:e,setLayoutState:r,setEngineState:s,progressEventTarget:o,validatorRegistry:a,sanitizerRegistry:i,transformRegistry:n,activeWorkerRef:u,phaseTimingsRef:c}=t,p=q({setState:e,setLayoutState:r,setEngineState:s}),S=T(h=>{o.dispatchEvent(new CustomEvent(O,{detail:h}))},[o]),l=T(h=>{u.current=h},[u]),m=T(()=>{let h=u.current;h&&(h.terminate(),u.current=null),e(R=>({...R,status:"cancelled"})),o.dispatchEvent(new CustomEvent(B))},[u,o,e]),y=T((h,R)=>{c.current={...c.current,[h]:R}},[c]),x=T(h=>{let R={...c.current},v=te(R,h);p.setMetrics(v)},[c,p]),d=T(h=>{e(R=>({...R,changeLog:[...R.changeLog,h]}))},[e]),f=T(h=>{c.current={...Ye},e(R=>({...R,file:h,status:"loading",rawData:null,documentHash:null,result:null,convertedSheet:null,sanitizedSheet:null,convertResultData:null,metrics:null,changeLog:[],submitDone:!1}))},[c,e]),b=T((h,R,v)=>{a.register(h,R,v)},[a]),C=T((h,R,v)=>{i.register(h,R,v)},[i]),g=T((h,R,v)=>{n.register(h,R,v)},[n]);return Ge(()=>({...p,addChangeLogEntry:d,setPhaseTiming:y,finalizeMetrics:x,processFile:f,registerValidator:b,registerSanitizer:C,registerTransform:g,abort:m,dispatchProgress:S,setActiveWorker:l}),[p,d,y,x,f,b,C,g,m,S,l])}import{useCallback as Pe,useEffect as Ce,useRef as Qe,useState as Ze}from"react";function re(){return new Promise((t,e)=>{let r=indexedDB.open("react-import-sheet-db",1);r.onerror=()=>e(r.error),r.onsuccess=()=>t(r.result),r.onupgradeneeded=()=>{r.result.createObjectStore(k,{keyPath:"key"})}})}async function xe(t,e){let r=await re();return new Promise((s,o)=>{let a=r.transaction(k,"readwrite"),i=a.objectStore(k),n={key:t,...e},u=i.put(n);u.onsuccess=()=>s(),u.onerror=()=>o(u.error),a.oncomplete=()=>r.close()})}async function ve(t){let e=await re();return new Promise((r,s)=>{let i=e.transaction(k,"readonly").objectStore(k).get(t);i.onsuccess=()=>{e.close();let n=i.result;if(n==null){r(null);return}let u=n.savedAt;if(Date.now()-u>6048e5){r(null);return}let{key:c,...p}=n;r(p)},i.onerror=()=>s(i.error)})}async function Ee(t){let e=await re();return new Promise((r,s)=>{let o=e.transaction(k,"readwrite"),i=o.objectStore(k).delete(t);i.onsuccess=()=>r(),i.onerror=()=>s(i.error),o.oncomplete=()=>e.close()})}var et=2500;function be(t,e,r,s,o,a,i){let[n,u]=Ze(null),c=Qe(null);Ce(()=>{t&&ve(e).then(l=>{l&&(l.layoutVersion!=null&&i!=null&&String(l.layoutVersion)!==String(i)||u(l))})},[t,e,i]),Ce(()=>{if(!(!t||!r||!s))return c.current&&clearTimeout(c.current),c.current=setTimeout(()=>{c.current=null;let l={rawData:r,sheet:s,savedAt:Date.now(),layoutVersion:i??void 0,stateSchemaVersion:1};xe(e,l).catch(()=>{})},et),()=>{c.current&&clearTimeout(c.current)}},[t,e,r,s,i]);let p=Pe(async()=>{if(!t)return;let l=n;l&&(o(l.rawData),a(l.sheet),u(null))},[t,n,o,a]),S=Pe(async()=>{t&&(await Ee(e),u(null))},[t,e]);return{hasRecoverableSession:t&&n!=null,recoverSession:p,clearPersistedState:S}}import{useCallback as nt,useEffect as st}from"react";import{useCallback as Ie,useEffect as tt,useRef as rt,useState as ot}from"react";import*as K from"comlink";function Te(){return new URL("./parser.worker.js",import.meta.url).href}function ke(){let{setActiveWorker:t,dispatchProgress:e}=w(),[r,s]=ot(null),o=rt(null);tt(()=>{let n=new Worker(Te(),{type:"module"});o.current=n,t(n);let u=K.wrap(n);return queueMicrotask(()=>s(u)),()=>{n.terminate(),o.current=null,t(null)}},[t]);let a=Ie(async(n,u={})=>{if(!r)throw new Error("Parser worker not ready");return r.load(n,u)},[r]),i=Ie(async n=>{if(!r)throw new Error("Parser worker not ready");let u=n?K.proxy(n):void 0;return r.parseAll(u)},[r]);return{load:a,parseAll:i,dispatchProgress:e,isReady:!!r}}function je(t){let e=Object.keys(t.sheets);return e.length===0?null:t.sheets[e[0]??""]??null}function J(){let t=w(),{load:e,parseAll:r,isReady:s}=ke();return st(()=>{let{file:a,status:i,engine:n}=t;!s||!a||i!=="loading"||e(a,{maxRows:10,fileName:a.name,engine:n??void 0}).then(u=>{if(!je(u)){t.setStatus("error");return}let p=u.sheets[Object.keys(u.sheets)[0]??""];if(!p){t.setStatus("error");return}t.setRawData(p),t.setDocumentHash(p.documentHash),t.setStatus("success")}).catch(()=>{t.setStatus("error")})},[s,t.file,t.status,t.setRawData,t.setDocumentHash,t.setStatus,e]),{startFullImport:nt(()=>{let{file:a}=t;if(!a)return Promise.reject(new Error("No file loaded"));t.setStatus("loading");let i=performance.now();return r(n=>t.dispatchProgress(n)).then(n=>{let u=performance.now();if(t.setPhaseTiming("parse",u-i),!je(n))return t.setStatus("error"),n;let p=n.sheets[Object.keys(n.sheets)[0]??""];return p?(t.setRawData(p),t.setDocumentHash(p.documentHash),t.setStatus("success"),n):(t.setStatus("error"),n)})},[t,r])}}import{jsx as lt,jsxs as ut}from"react/jsx-runtime";function at(){return J(),null}function ne({children:t,layout:e,engine:r,persist:s=!1,persistKey:o=ee,onSubmit:a=null,submitKeyMap:i=null}){let[n,u]=oe(Se),[c,p]=oe(e??null),[S,l]=oe(r??null),m=F(()=>new EventTarget,[]),y=F(()=>new V,[]),x=F(()=>new V,[]),d=F(()=>new V,[]),f=Me(null),b=Me({parse:0,sanitize:0,validate:0,transform:0}),C=q({setState:u,setLayoutState:p,setEngineState:l}),g=be(s,o,n.rawData,n.result,C.setRawData,C.setResult,c?.version??null),h=Re({setState:u,setLayoutState:p,setEngineState:l,progressEventTarget:m,validatorRegistry:y,sanitizerRegistry:x,transformRegistry:d,activeWorkerRef:f,phaseTimingsRef:b});it(()=>()=>{let v=f.current;v&&(v.terminate(),f.current=null)},[]);let R=F(()=>({...n,layout:c,engine:S,progressEventTarget:m,...h,onSubmit:a??null,submitKeyMap:i??null,persist:s,persistKey:o,hasRecoverableSession:g.hasRecoverableSession,recoverSession:g.recoverSession,clearPersistedState:g.clearPersistedState}),[n,c,S,m,a,i,h,s,o,g.hasRecoverableSession,g.recoverSession,g.clearPersistedState]);return ut(N.Provider,{value:R,children:[lt(at,{}),t]})}import{useContext as ct}from"react";function w(){let t=ct(N);if(t===null)throw new Error("useImporter must be used within an ImporterProvider");return t}import{useCallback as pt,useEffect as Oe,useMemo as Le}from"react";function A(t){return t.rows.filter(e=>e.errors.length>0)}function H(t){return t?$(t).totalErrors>0:!1}function $(t){let e=t.rows.length,r=A(t),s=t.errors.length+t.rows.reduce((o,a)=>o+a.errors.length+a.cells.reduce((i,n)=>i+n.errors.length,0),0);return{totalRows:e,rowsWithErrors:r.length,totalErrors:s}}function se(t,e){return t.cells.find(s=>s.key===e)?.value}function ie(t,e){return t.map(e)}function W(t,e){return t?t.rows.map(r=>{let s={};for(let[o,a]of Object.entries(e))s[a]=se(r,o);return s}):[]}function mt(t){return t.rows.map(e=>e.cells.reduce((r,s)=>({...r,[s.key]:s.value}),{}))}function De(t={}){let e=w(),{layout:r,engine:s}=t;Oe(()=>{r!==void 0&&e.setLayout(r)},[e,r]),Oe(()=>{s!==void 0&&e.setEngine(s)},[e,s]);let o=Le(()=>!!(e.result&&e.status==="success"&&!e.submitDone&&!H(e.result)),[e.result,e.status,e.submitDone]),a=pt(()=>{if(!e.result||e.submitDone||H(e.result)||!e.onSubmit)return;let i=e.submitKeyMap?W(e.result,e.submitKeyMap):mt(e.result);e.onSubmit(i),e.setSubmitDone(!0)},[e]);return Le(()=>({processFile:e.processFile,registerValidator:e.registerValidator,registerSanitizer:e.registerSanitizer,registerTransform:e.registerTransform,abort:e.abort,metrics:e.metrics,submit:a,canSubmit:o,submitDone:e.submitDone}),[e.processFile,e.registerValidator,e.registerSanitizer,e.registerTransform,e.abort,e.metrics,a,o,e.submitDone])}import{useCallback as Y,useMemo as Fe}from"react";function ae(t,e,r,s){let o=[...r],a=new Map;t.headers.forEach((n,u)=>a.set(n,u));let i=t.rows.map(n=>{let u=r.map(c=>{let p=s[c],S=p!=null?(()=>{let l=a.get(p);return l==null?null:n.cells[l]?.value??null})():null;return{key:c,value:S??null}});return{index:n.index,cells:u}});return{name:t.name,filesize:t.filesize,documentHash:t.documentHash,rowsCount:t.rowsCount,headersCount:t.headersCount,headers:o,rows:i}}function Ve(t){return t.trim().toLowerCase().normalize("NFD").replace(/\p{Diacritic}/gu,"")}function dt(t,e){if(t.length===0)return e.length;if(e.length===0)return t.length;let r=Array.from({length:e.length+1},(s,o)=>o);for(let s=1;s<=t.length;s++){let o=[s];for(let a=1;a<=e.length;a++){let i=t[s-1]===e[a-1]?0:1;o[a]=Math.min(o[a-1]+1,r[a]+1,r[a-1]+i)}r=o}return r[e.length]}function ft(t,e){let r=Ve(t),s=Ve(e),o=r.length>=s.length?r:s,a=r.length<s.length?r:s;if(o.length===0)return 1;let i=dt(o,a);return(o.length-i)/o.length}var ht=.8;function _e(t,e,r={}){let s=r.threshold??ht,o=[];for(let u of e)for(let c of t){let p=ft(u,c);p>=s&&o.push({key:u,header:c,score:p})}o.sort((u,c)=>c.score-u.score);let a=new Set,i=new Set,n={};for(let u of e)n[u]=null;for(let{key:u,header:c,score:p}of o)a.has(u)||i.has(c)||(n[u]=c,a.add(u),i.add(c));return e.map(u=>({key:u,matchedHeader:n[u]??null}))}function yt(t,e){let r=t.trim();return e?r:r.toLowerCase()}function le(t,e,r={},s={}){let o=s.caseSensitive??!1,a=s.normalizer??(l=>yt(l,o)),i=Object.keys(e.fields),n=t.headers,u=new Map;for(let l of n)u.set(a(l),l);let c={},p=new Set;for(let[l,m]of Object.entries(r))i.includes(m)&&(c[m]=n.includes(l)?l:null,c[m]&&p.add(l));for(let l of i){if(c[l]!=null)continue;let m=a(l),y=u.get(m);y!=null&&!p.has(y)?(c[l]=y,p.add(y)):c[l]=null}if(s.fuzzyHeaders===!0){let l=i.filter(d=>c[d]==null),m=n.filter(d=>!p.has(d)),y=s.fuzzyThreshold??.8,x=_e(m,l,{threshold:y});for(let{key:d,matchedHeader:f}of x)f!=null&&!p.has(f)&&(c[d]=f,p.add(f))}let S=[];for(let l of i)if(c[l]==null){let x=e.fields[l]?.required!==!1;S.push({expected:l,found:null,message:`Column '${l}' not found in file`,required:x})}return{fieldToHeader:c,mismatches:S}}function G(t,e,r={},s){let o=Object.keys(e.fields),a=s?.columnOrder?.length?s.columnOrder:o,i=s?.headerToFieldMap??{},{fieldToHeader:n,mismatches:u}=le(t,e,i,r),p=o.filter(m=>e.fields[m]?.required!==!1).every(m=>n[m]!=null);if(u.length===0||p)return{kind:"success",sheet:ae(t,e,a,n)};let l=u.some(m=>m.required===!0);return{kind:"mismatch",headersFound:[...t.headers],mismatches:u,columnOrder:[...a],headerToFieldMap:{...i},layoutError:l}}function X(){let t=w(),{rawData:e,layout:r,convertedSheet:s,convertResultData:o,setConvertedSheet:a,setConvertResultData:i}=t,n=Y(l=>{if(!e||!r)return;let m=G(e,r,l,o??void 0);m.kind==="success"?a(m.sheet):i({headersFound:m.headersFound,mismatches:m.mismatches,columnOrder:m.columnOrder,headerToFieldMap:m.headerToFieldMap})},[e,r,o,a,i]),u=Y(()=>{if(!e||!r||!o)return;let l=G(e,r,{},{columnOrder:o.columnOrder,headerToFieldMap:o.headerToFieldMap});return l.kind==="success"?(a(l.sheet),{kind:"success",sheet:l.sheet}):(i({headersFound:l.headersFound,mismatches:l.mismatches,columnOrder:l.columnOrder,headerToFieldMap:l.headerToFieldMap}),{kind:"mismatch",result:l})},[e,r,o,a,i]),c=Y(l=>{i(m=>m&&{...m,columnOrder:l})},[i]),p=Y((l,m)=>{i(y=>y&&{...y,headerToFieldMap:{...y.headerToFieldMap,[l]:m}})},[i]),S=Fe(()=>o?{kind:"mismatch",headersFound:o.headersFound,mismatches:o.mismatches,columnOrder:[...o.columnOrder],headerToFieldMap:{...o.headerToFieldMap},reorderColumns:c,renameColumn:p,applyMapping:()=>u()??{kind:"mismatch",result:{...o,kind:"mismatch"}}}:null,[o,c,p,u]);return Fe(()=>({convert:n,convertedSheet:s,convertResult:S}),[n,s,S])}import{useMemo as gt}from"react";function Ae(){let t=w();return gt(()=>({status:t.status,progressEventTarget:t.progressEventTarget}),[t.status,t.progressEventTarget])}import{useCallback as He,useMemo as We}from"react";function ze(){let e=w().result,r=We(()=>e?[...e.errors]:[],[e]),s=He(a=>e?ie(e.rows,a):[],[e]),o=He(a=>W(e,a),[e]);return We(()=>({sheet:e,errors:r,toObjects:s,toObjectsWithKeyMap:o}),[e,r,s,o])}import{useCallback as ce,useMemo as pe,useRef as vt}from"react";import{useCallback as St,useEffect as Rt,useRef as wt,useState as xt}from"react";import*as Ue from"comlink";function Ne(){return new URL("./edit.worker.js",import.meta.url).href}function Be(){let[t,e]=xt(null),r=wt(null);return Rt(()=>{let o=new Worker(Ne(),{type:"module"});r.current=o;let a=Ue.wrap(o);return queueMicrotask(()=>e(a)),()=>{o.terminate(),r.current=null}},[]),{runEdit:St(async(o,a,i,n,u,c)=>{if(!t)throw new Error("Edit worker not ready");return t.runEdit(o,a,i,n,u,c??{})},[t]),isReady:!!t}}function qe(t,e,r){return ue(t.rows,e,r)}function ue(t,e,r){let s=t.length,o=r<=0?0:Math.max(1,Math.ceil(s/r)),a=Math.max(1,Math.min(e,o)),i=(a-1)*r,n=Math.min(i+r,s),u=t.slice(i,n);return{page:a,pageSize:r,totalCount:s,totalPages:o,rows:u}}function Q(t={}){let{result:e,setResult:r,layout:s,changeLog:o,addChangeLogEntry:a,submitDone:i}=w(),{runEdit:n,isReady:u}=Be(),c=!i,{page:p=1,pageSize:S=25,debounceMs:l}=t,m=vt(null),y=pe(()=>e?qe(e,p,S):{page:1,pageSize:S,totalCount:0,totalPages:0,rows:[]},[e,p,S]),x=y.totalPages,d=ce(g=>{if(!e||!s||i)return Promise.resolve();let h=Z(e,g.rowIndex)&&ye(Z(e,g.rowIndex),g.cellKey)?.value;return n(e,s,g.rowIndex,g.cellKey,g.value).then(R=>{r(R),queueMicrotask(()=>{let v={type:"cell_edit",rowIndex:g.rowIndex,cellKey:g.cellKey,value:g.value,previousValue:h,timestamp:Date.now()};a(v)})})},[e,s,i,n,r,a]),f=ce(g=>{if(l!=null&&l>0){m.current&&clearTimeout(m.current),m.current=setTimeout(()=>{m.current=null,d(g)},l);return}return d(g)},[l,d]),b=ce(g=>{if(!e||i)return;let h=ge(e,g);r(h),queueMicrotask(()=>{let R={type:"row_remove",rowIndex:g,timestamp:Date.now()};a(R)})},[e,i,r,a]),C=pe(()=>U(o),[o]);return pe(()=>({sheet:e,editCell:f,removeRow:b,pageData:y,totalPages:x,isReady:u,canEdit:c,changeLog:o,changeLogAsText:C}),[e,f,b,y,x,u,c,o,C])}import{useCallback as D,useMemo as z,useState as Ct}from"react";function Ke(t,e){return t.includes(e)||t.includes('"')||t.includes(`
3
+ `)||t.includes("\r")?'"'+t.replace(/"/g,'""')+'"':t}function Et(t,e){return t==null?"":t instanceof Date?e?t.toLocaleString():t.toISOString():String(t)}function me(t,e,r={}){let{includeHeaders:s=!0,csvSeparator:o=",",formatDatesForExport:a=!1}=r,i=e!=null?Object.keys(e.fields):[],n=i.length>0?i:t.rows[0]?.cells.map(p=>p.key)??t.headers.slice(),u=[];s&&n.length>0&&u.push(n.map(p=>Ke(p,o)).join(o));for(let p of t.rows){let S=n.map(l=>{let y=p.cells.find(x=>x.key===l)?.value??"";return Ke(Et(y,a),o)});u.push(S.join(o))}return"\uFEFF"+u.join(`\r
4
+ `)}function Pt(t,e){return t==null?null:t instanceof Date?e?t.toLocaleString():t.toISOString():t}function de(t,e,r={}){let{formatDatesForExport:s=!1}=r,o=t.rows.map(a=>{let i={};for(let n of a.cells)i[n.key]=Pt(n.value,s);return i});return JSON.stringify(o,null,0)}function fe(t={}){let{page:e=1,defaultPageSize:r=25,filterMode:s="all"}=t,[o,a]=Ct(e),i=r,{sheet:n,editCell:u,removeRow:c,changeLog:p,changeLogAsText:S}=Q({}),l=w(),m=z(()=>n?A(n):[],[n]),y=z(()=>s==="errors-only"?m:n?.rows??[],[s,m,n]),x=y.length,d=D((E,I)=>ue(y,E??o,I??i),[o,i,y]),f=z(()=>d(o,i).rows,[d,o,i]),b=D((E,I)=>{let j=(E-1)*I;return y.slice(j,j+I)},[y]),C=z(()=>n?$(n):{totalRows:0,rowsWithErrors:0,totalErrors:0},[n]),g=D(E=>!n||!l.layout?"":me(n,l.layout,E??{}),[n,l.layout]),h=D(E=>n?de(n,l.layout??null,E??{}):"[]",[n,l.layout]),R=D(async E=>{let I=g(E);if(!I)return;let j=new Blob([I],{type:"text/csv;charset=utf-8"}),L=URL.createObjectURL(j),M=document.createElement("a");M.href=L,M.download=(E?.filename??"export")+".csv",M.click(),URL.revokeObjectURL(L)},[g]),v=D(async E=>{let I=h(E),j=new Blob([I],{type:"application/json"}),L=URL.createObjectURL(j),M=document.createElement("a");M.href=L,M.download=(E?.filename??"export")+".json",M.click(),URL.revokeObjectURL(L)},[h]);return z(()=>({sheet:n,getPaginatedResult:d,paginatedRows:f,page:o,setPage:a,pageSize:i,totalRows:x,getRows:b,rowsWithErrors:m,counts:C,editCell:u,removeRow:c,changeLog:p,changeLogAsText:S,exportToCSV:g,exportToJSON:h,downloadCSV:R,downloadJSON:v,hasRecoverableSession:l.hasRecoverableSession,recoverSession:l.recoverSession,clearPersistedState:l.clearPersistedState}),[n,d,f,o,i,x,b,m,C,u,c,p,S,g,h,R,v,l.hasRecoverableSession,l.recoverSession,l.clearPersistedState])}import{useCallback as bt,useEffect as Tt}from"react";function he(){let e=w().progressEventTarget,r=bt(s=>{let o=a=>{s(a.detail)};return e.addEventListener(O,o),()=>{e.removeEventListener(O,o)}},[e]);return{progressEventTarget:e,subscribeToProgress:r}}function Je(t){let{subscribeToProgress:e}=he();Tt(()=>e(t),[e,t])}export{B as IMPORTER_ABORTED_EVENT,O as IMPORTER_PROGRESS_EVENT,ne as ImportProvider,ne as ImporterProvider,V as Registry,U as formatChangeLogAsText,se as getCellValue,H as hasValidationErrors,X as useConvert,J as useImportSheet,De as useImporter,he as useImporterEventTarget,Je as useImporterProgressSubscription,Ae as useImporterStatus,ze as useSheetData,Q as useSheetEditor,fe as useSheetView};
5
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/providers/ImporterProvider.tsx","../src/core/view/types/persisted-state.ts","../src/providers/ImporterContext.ts","../src/providers/state.ts","../src/providers/useImporterActions.ts","../src/types/metrics.ts","../src/types/change-log.ts","../src/types/importer-state.ts","../src/providers/useImporterStateSetters.ts","../src/providers/usePersistSession.ts","../src/core/view/persist/indexed-db.ts","../src/providers/useImporterContext.ts","../src/hooks/useImporter.ts","../src/core/view/get-rows-with-errors.ts","../src/core/view/get-view-counts.ts","../src/core/view/export/sheet-to-objects.ts","../src/hooks/useImportSheet.ts","../src/core/parser/hooks/useParserWorker.ts","../src/core/parser/worker/worker-url.ts","../src/core/convert/hooks/useConvert.ts","../src/core/convert/build-converted-sheet.ts","../src/core/parser/utils/fuzzy-match.ts","../src/core/convert/match-headers.ts","../src/core/convert/run-convert.ts","../src/hooks/useImporterStatus.ts","../src/hooks/useSheetData.ts","../src/hooks/useSheetEditor.ts","../src/core/editor/hooks/useEditWorker.ts","../src/core/editor/worker/worker-url.ts","../src/core/editor/get-paginated-result.ts","../src/core/view/hooks/useSheetView.ts","../src/core/view/export/sheet-to-csv.ts","../src/core/view/export/sheet-to-json.ts","../src/hooks/useImporterEventTarget.ts"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\nimport { Registry } from '../shared/registry/index.js';\nimport type { ParserEngine, SheetLayout } from '../types/index.js';\nimport { DEFAULT_PERSIST_KEY } from '../core/view/types/persisted-state.js';\nimport { ImporterContext } from './ImporterContext.js';\nimport { initialState } from './state.js';\nimport type { ImporterContextValue, ImporterProviderProps } from './types.js';\nimport { useImporterActions } from './useImporterActions.js';\nimport { useImporterStateSetters } from './useImporterStateSetters.js';\nimport { usePersistSession } from './usePersistSession.js';\n\nexport function ImporterProvider({\n children,\n layout: layoutProp,\n engine: engineProp,\n persist = false,\n persistKey = DEFAULT_PERSIST_KEY,\n onSubmit = null,\n submitKeyMap = null,\n}: ImporterProviderProps) {\n const [state, setState] = useState(initialState);\n const [layout, setLayoutState] = useState<SheetLayout | null>(layoutProp ?? null);\n const [engine, setEngineState] = useState<ParserEngine | null>(engineProp ?? null);\n const progressEventTarget = useMemo(() => new EventTarget(), []);\n const validatorRegistry = useMemo(() => new Registry<(...args: unknown[]) => unknown>(), []);\n const sanitizerRegistry = useMemo(() => new Registry<(...args: unknown[]) => unknown>(), []);\n const transformRegistry = useMemo(() => new Registry<(...args: unknown[]) => unknown>(), []);\n const activeWorkerRef = useRef<Worker | null>(null);\n const phaseTimingsRef = useRef({\n parse: 0,\n sanitize: 0,\n validate: 0,\n transform: 0,\n });\n\n const stateSetters = useImporterStateSetters({ setState, setLayoutState, setEngineState });\n const persistSession = usePersistSession(\n persist,\n persistKey,\n state.rawData,\n state.result,\n stateSetters.setRawData,\n stateSetters.setResult,\n layout?.version ?? null\n );\n\n const actions = useImporterActions({\n setState,\n setLayoutState,\n setEngineState,\n progressEventTarget,\n validatorRegistry,\n sanitizerRegistry,\n transformRegistry,\n activeWorkerRef,\n phaseTimingsRef,\n });\n\n useEffect(() => {\n return () => {\n const worker = activeWorkerRef.current;\n if (worker) {\n worker.terminate();\n activeWorkerRef.current = null;\n }\n };\n }, []);\n\n const value = useMemo<ImporterContextValue>(\n () => ({\n ...state,\n layout,\n engine,\n progressEventTarget,\n ...actions,\n onSubmit: onSubmit ?? null,\n submitKeyMap: submitKeyMap ?? null,\n persist,\n persistKey,\n hasRecoverableSession: persistSession.hasRecoverableSession,\n recoverSession: persistSession.recoverSession,\n clearPersistedState: persistSession.clearPersistedState,\n }),\n [\n state,\n layout,\n engine,\n progressEventTarget,\n onSubmit,\n submitKeyMap,\n actions,\n persist,\n persistKey,\n persistSession.hasRecoverableSession,\n persistSession.recoverSession,\n persistSession.clearPersistedState,\n ]\n );\n\n return <ImporterContext.Provider value={value}>{children}</ImporterContext.Provider>;\n}\n","import type { RawSheet } from '../../../types/raw-sheet.js';\nimport type { Sheet } from '../../../types/sheet.js';\n\nexport const PERSIST_SESSION_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;\n\nexport const PERSIST_STORE_NAME = 'react-import-sheet-persist';\n\nexport const DEFAULT_PERSIST_KEY = 'react-import-sheet-session';\n\nexport const STATE_SCHEMA_VERSION = 1;\n\nexport interface PersistedState {\n readonly rawData: RawSheet;\n readonly sheet: Sheet;\n readonly savedAt: number;\n readonly fileName?: string;\n readonly persistKey?: string;\n readonly layoutVersion?: string | number;\n readonly stateSchemaVersion?: number;\n}\n","import { createContext } from 'react';\r\nimport type { ImporterContextValue } from './types.js';\r\n\r\nexport const ImporterContext = createContext<ImporterContextValue | null>(null);\r\n","import type { ImporterState } from '../types/index.js';\n\nexport const initialState: ImporterState = {\n file: null,\n rawData: null,\n documentHash: null,\n status: 'idle',\n result: null,\n convertedSheet: null,\n sanitizedSheet: null,\n convertResultData: null,\n metrics: null,\n changeLog: [],\n submitDone: false,\n};\n","import { useCallback, useMemo } from 'react';\nimport type { RegistryLevel } from '../shared/registry/index.js';\nimport type { ChangeLogEntry } from '../types/change-log.js';\nimport {\n buildPipelineMetrics,\n IMPORTER_ABORTED_EVENT,\n IMPORTER_PROGRESS_EVENT,\n type ImporterProgressDetail,\n type PipelinePhase,\n} from '../types/index.js';\nimport type { ImporterContextValue, UseImporterActionsDeps } from './types.js';\nimport { useImporterStateSetters } from './useImporterStateSetters.js';\n\nconst INITIAL_PHASE_TIMINGS = {\n parse: 0,\n sanitize: 0,\n validate: 0,\n transform: 0,\n};\n\nexport function useImporterActions(\n deps: UseImporterActionsDeps\n): Omit<\n ImporterContextValue,\n | 'file'\n | 'rawData'\n | 'documentHash'\n | 'status'\n | 'result'\n | 'layout'\n | 'engine'\n | 'progressEventTarget'\n | 'onSubmit'\n | 'submitKeyMap'\n | 'persist'\n | 'persistKey'\n | 'hasRecoverableSession'\n | 'recoverSession'\n | 'clearPersistedState'\n> {\n const {\n setState,\n setLayoutState,\n setEngineState,\n progressEventTarget,\n validatorRegistry,\n sanitizerRegistry,\n transformRegistry,\n activeWorkerRef,\n phaseTimingsRef,\n } = deps;\n\n const stateSetters = useImporterStateSetters({ setState, setLayoutState, setEngineState });\n\n const dispatchProgress = useCallback(\n (detail: ImporterProgressDetail) => {\n progressEventTarget.dispatchEvent(new CustomEvent(IMPORTER_PROGRESS_EVENT, { detail }));\n },\n [progressEventTarget]\n );\n\n const setActiveWorker = useCallback(\n (worker: Worker | null) => {\n activeWorkerRef.current = worker;\n },\n [activeWorkerRef]\n );\n\n const abort = useCallback(() => {\n const worker = activeWorkerRef.current;\n if (worker) {\n worker.terminate();\n activeWorkerRef.current = null;\n }\n setState((prev) => ({ ...prev, status: 'cancelled' }));\n progressEventTarget.dispatchEvent(new CustomEvent(IMPORTER_ABORTED_EVENT));\n }, [activeWorkerRef, progressEventTarget, setState]);\n\n const setPhaseTiming = useCallback(\n (phase: PipelinePhase, ms: number) => {\n phaseTimingsRef.current = { ...phaseTimingsRef.current, [phase]: ms };\n },\n [phaseTimingsRef]\n );\n\n const finalizeMetrics = useCallback(\n (rowCount: number) => {\n const timings = { ...phaseTimingsRef.current };\n const metrics = buildPipelineMetrics(timings, rowCount);\n stateSetters.setMetrics(metrics);\n },\n [phaseTimingsRef, stateSetters]\n );\n\n const addChangeLogEntry = useCallback(\n (entry: ChangeLogEntry) => {\n setState((prev) => ({\n ...prev,\n changeLog: [...prev.changeLog, entry],\n }));\n },\n [setState]\n );\n\n const processFile = useCallback(\n (file: File) => {\n phaseTimingsRef.current = { ...INITIAL_PHASE_TIMINGS };\n setState((prev) => ({\n ...prev,\n file,\n status: 'loading',\n rawData: null,\n documentHash: null,\n result: null,\n convertedSheet: null,\n sanitizedSheet: null,\n convertResultData: null,\n metrics: null,\n changeLog: [],\n submitDone: false,\n }));\n },\n [phaseTimingsRef, setState]\n );\n\n const registerValidator = useCallback(\n (name: string, fn: (...args: unknown[]) => unknown, options: { type: RegistryLevel }) => {\n validatorRegistry.register(name, fn, options);\n },\n [validatorRegistry]\n );\n\n const registerSanitizer = useCallback(\n (name: string, fn: (...args: unknown[]) => unknown, options: { type: RegistryLevel }) => {\n sanitizerRegistry.register(name, fn, options);\n },\n [sanitizerRegistry]\n );\n\n const registerTransform = useCallback(\n (name: string, fn: (...args: unknown[]) => unknown, options: { type: RegistryLevel }) => {\n transformRegistry.register(name, fn, options);\n },\n [transformRegistry]\n );\n\n return useMemo(\n () => ({\n ...stateSetters,\n addChangeLogEntry,\n setPhaseTiming,\n finalizeMetrics,\n processFile,\n registerValidator,\n registerSanitizer,\n registerTransform,\n abort,\n dispatchProgress,\n setActiveWorker,\n }),\n [\n stateSetters,\n addChangeLogEntry,\n setPhaseTiming,\n finalizeMetrics,\n processFile,\n registerValidator,\n registerSanitizer,\n registerTransform,\n abort,\n dispatchProgress,\n setActiveWorker,\n ]\n );\n}\n","export interface PipelineMetricsTimings {\n readonly parse: number;\n readonly sanitize: number;\n readonly validate: number;\n readonly transform: number;\n}\n\nexport interface PipelineMetricsPercentages {\n readonly parse: number;\n readonly sanitize: number;\n readonly validate: number;\n readonly transform: number;\n readonly overhead?: number;\n}\n\nexport interface PipelineMetrics {\n readonly timings: PipelineMetricsTimings;\n readonly percentages?: PipelineMetricsPercentages;\n readonly totalMs: number;\n readonly isSlow: boolean;\n readonly parseTime: string;\n readonly sanitizeTime: string;\n readonly validateTime: string;\n readonly transformTime: string;\n readonly totalTime: string;\n readonly efficiency: string;\n readonly rowCount: number;\n readonly overheadMs?: number;\n}\n\nexport const SLOW_THRESHOLD_MS = 2000;\n\nfunction formatMs(ms: number): string {\n if (ms < 0.01 && ms >= 0) return '0.00ms';\n if (ms < 1) return `${(ms * 1000).toFixed(2)}μs`;\n return `${ms.toFixed(2)}ms`;\n}\n\nexport function buildPipelineMetrics(\n timings: PipelineMetricsTimings,\n rowCount: number,\n overheadMs?: number,\n): PipelineMetrics {\n const totalMs =\n timings.parse + timings.sanitize + timings.validate + timings.transform;\n const isSlow = totalMs > SLOW_THRESHOLD_MS;\n const efficiencyMsPerRow = rowCount > 0 ? totalMs / rowCount : 0;\n const efficiency = `${efficiencyMsPerRow.toFixed(4)}ms/row`;\n\n let percentages: PipelineMetricsPercentages | undefined;\n if (totalMs > 0) {\n const overhead = overheadMs ?? 0;\n const totalWithOverhead = totalMs + overhead;\n percentages = {\n parse: (timings.parse / totalWithOverhead) * 100,\n sanitize: (timings.sanitize / totalWithOverhead) * 100,\n validate: (timings.validate / totalWithOverhead) * 100,\n transform: (timings.transform / totalWithOverhead) * 100,\n overhead: totalWithOverhead > 0 ? (overhead / totalWithOverhead) * 100 : 0,\n };\n }\n\n return {\n timings: { ...timings },\n percentages,\n totalMs,\n isSlow,\n parseTime: formatMs(timings.parse),\n sanitizeTime: formatMs(timings.sanitize),\n validateTime: formatMs(timings.validate),\n transformTime: formatMs(timings.transform),\n totalTime: formatMs(totalMs),\n efficiency,\n rowCount,\n ...(overheadMs !== undefined && overheadMs >= 0 ? { overheadMs } : {}),\n };\n}\n","export interface ChangeLogEntryCellEdit {\n readonly type: 'cell_edit';\n readonly rowIndex: number;\n readonly cellKey: string;\n readonly value: unknown;\n readonly previousValue?: unknown;\n readonly timestamp: number;\n}\n\nexport interface ChangeLogEntryRowRemove {\n readonly type: 'row_remove';\n readonly rowIndex: number;\n readonly timestamp: number;\n}\n\nexport type ChangeLogEntry = ChangeLogEntryCellEdit | ChangeLogEntryRowRemove;\n\nexport function formatChangeLogAsText(entries: readonly ChangeLogEntry[]): string {\n const lines: string[] = [];\n for (const e of entries) {\n if (e.type === 'cell_edit') {\n const prev = e.previousValue !== undefined ? ` (previous: ${String(e.previousValue)})` : '';\n lines.push(\n `Row ${e.rowIndex + 1}, cell \"${e.cellKey}\": set to ${JSON.stringify(e.value)}${prev}`\n );\n } else {\n lines.push(`Row ${e.rowIndex + 1}: removed`);\n }\n }\n return lines.join('\\n');\n}\n","import type { ConvertedSheet } from '../core/convert/types/converted-sheet.js';\nimport type { SanitizedSheet } from '../core/sanitizer/types/sanitized-sheet.js';\nimport type { ChangeLogEntry } from './change-log.js';\nimport type { PipelineMetrics } from './metrics.js';\nimport type { RawSheet } from './raw-sheet.js';\nimport type { Sheet } from './sheet.js';\n\nexport type ImporterStatus =\n | 'idle'\n | 'loading'\n | 'parsing'\n | 'validating'\n | 'transforming'\n | 'success'\n | 'error'\n | 'cancelled';\n\nexport interface ConvertResultData {\n readonly headersFound: readonly string[];\n readonly mismatches: readonly { expected: string; found: string | null; message?: string }[];\n readonly columnOrder: readonly string[];\n readonly headerToFieldMap: Readonly<Record<string, string>>;\n}\n\nexport type PipelinePhase = 'parse' | 'sanitize' | 'validate' | 'transform';\n\nexport interface ImporterState {\n readonly file: File | null;\n readonly rawData: RawSheet | null;\n readonly documentHash: string | null;\n readonly status: ImporterStatus;\n readonly result: Sheet | null;\n readonly convertedSheet: ConvertedSheet | null;\n readonly sanitizedSheet: SanitizedSheet | null;\n readonly convertResultData: ConvertResultData | null;\n readonly metrics: PipelineMetrics | null;\n readonly changeLog: readonly ChangeLogEntry[];\n readonly submitDone: boolean;\n}\n\nexport const IMPORTER_PROGRESS_EVENT = 'importer-progress';\nexport const IMPORTER_ABORTED_EVENT = 'importer-aborted';\n\nexport interface ImporterProgressDetail {\n readonly phase?: string;\n readonly globalPercent?: number;\n readonly localPercent?: number;\n readonly currentRow?: number;\n readonly totalRows?: number;\n readonly rowsProcessed?: number;\n}\n","import { useCallback } from 'react';\nimport type { ImporterState, ImporterStatus } from '../types/index.js';\nimport type { PipelineMetrics } from '../types/index.js';\nimport type { ParserEngine, SheetLayout } from '../types/index.js';\nimport type { ImporterContextValue, UseImporterStateSettersDeps } from './types.js';\n\nexport function useImporterStateSetters(\n deps: UseImporterStateSettersDeps\n): Pick<\n ImporterContextValue,\n | 'setLayout'\n | 'setEngine'\n | 'setFile'\n | 'setRawData'\n | 'setDocumentHash'\n | 'setStatus'\n | 'setResult'\n | 'setConvertedSheet'\n | 'setSanitizedSheet'\n | 'setConvertResultData'\n | 'setMetrics'\n | 'setSubmitDone'\n> {\n const { setState, setLayoutState, setEngineState } = deps;\n\n const setFile = useCallback(\n (file: File | null) => {\n setState((prev) => ({ ...prev, file }));\n },\n [setState]\n );\n\n const setRawData = useCallback(\n (rawData: ImporterState['rawData']) => {\n setState((prev) => ({ ...prev, rawData }));\n },\n [setState]\n );\n\n const setDocumentHash = useCallback(\n (documentHash: string | null) => {\n setState((prev) => ({ ...prev, documentHash }));\n },\n [setState]\n );\n\n const setStatus = useCallback(\n (status: ImporterStatus) => {\n setState((prev) => ({ ...prev, status }));\n },\n [setState]\n );\n\n const setResult = useCallback(\n (result: ImporterState['result']) => {\n setState((prev) => ({ ...prev, result }));\n },\n [setState]\n );\n\n const setConvertedSheet = useCallback(\n (convertedSheet: ImporterState['convertedSheet']) => {\n setState((prev) => ({ ...prev, convertedSheet, convertResultData: null }));\n },\n [setState]\n );\n\n const setSanitizedSheet = useCallback(\n (sanitizedSheet: ImporterState['sanitizedSheet']) => {\n setState((prev) => ({ ...prev, sanitizedSheet }));\n },\n [setState]\n );\n\n const setConvertResultData = useCallback(\n (\n dataOrUpdater:\n | ImporterState['convertResultData']\n | ((prev: ImporterState['convertResultData']) => ImporterState['convertResultData'])\n ) => {\n setState((prev) => ({\n ...prev,\n convertResultData:\n typeof dataOrUpdater === 'function'\n ? dataOrUpdater(prev.convertResultData)\n : dataOrUpdater,\n convertedSheet: typeof dataOrUpdater === 'function' ? prev.convertedSheet : null,\n }));\n },\n [setState]\n );\n\n const setMetrics = useCallback(\n (metrics: PipelineMetrics | null) => {\n setState((prev) => ({ ...prev, metrics }));\n },\n [setState]\n );\n\n const setSubmitDone = useCallback(\n (submitDone: boolean) => {\n setState((prev) => ({ ...prev, submitDone }));\n },\n [setState]\n );\n\n const setLayout = useCallback(\n (next: SheetLayout | null) => {\n setLayoutState(next);\n },\n [setLayoutState]\n );\n\n const setEngine = useCallback(\n (next: ParserEngine | null) => {\n setEngineState(next);\n },\n [setEngineState]\n );\n\n return {\n setLayout,\n setEngine,\n setFile,\n setRawData,\n setDocumentHash,\n setStatus,\n setResult,\n setConvertedSheet,\n setSanitizedSheet,\n setConvertResultData,\n setMetrics,\n setSubmitDone,\n };\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport type { RawSheet } from '../types/raw-sheet.js';\nimport type { Sheet } from '../types/sheet.js';\nimport {\n savePersistedState,\n loadPersistedState,\n clearPersistedState as clearPersistedStateStorage,\n} from '../core/view/persist/indexed-db.js';\nimport {\n STATE_SCHEMA_VERSION,\n type PersistedState as PersistedStateType,\n} from '../core/view/types/persisted-state.js';\n\nconst DEBOUNCE_MS = 2500;\n\nexport function usePersistSession(\n persist: boolean,\n persistKey: string,\n rawData: RawSheet | null,\n result: Sheet | null,\n setRawData: (v: RawSheet | null) => void,\n setResult: (v: Sheet | null) => void,\n layoutVersion: string | number | null,\n) {\n const [recoverableSession, setRecoverableSession] = useState<PersistedStateType | null>(null);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (!persist) return;\n loadPersistedState(persistKey).then((state) => {\n if (!state) return;\n if (\n state.layoutVersion != null &&\n layoutVersion != null &&\n String(state.layoutVersion) !== String(layoutVersion)\n ) {\n return;\n }\n setRecoverableSession(state);\n });\n }, [persist, persistKey, layoutVersion]);\n\n useEffect(() => {\n if (!persist || !rawData || !result) return;\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(() => {\n debounceRef.current = null;\n const payload: PersistedStateType = {\n rawData,\n sheet: result,\n savedAt: Date.now(),\n layoutVersion: layoutVersion ?? undefined,\n stateSchemaVersion: STATE_SCHEMA_VERSION,\n };\n savePersistedState(persistKey, payload).catch(() => {});\n }, DEBOUNCE_MS);\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n };\n }, [persist, persistKey, rawData, result, layoutVersion]);\n\n const recoverSession = useCallback(async () => {\n if (!persist) return;\n const state = recoverableSession;\n if (!state) return;\n setRawData(state.rawData);\n setResult(state.sheet);\n setRecoverableSession(null);\n }, [persist, recoverableSession, setRawData, setResult]);\n\n const clearPersistedState = useCallback(async () => {\n if (!persist) return;\n await clearPersistedStateStorage(persistKey);\n setRecoverableSession(null);\n }, [persist, persistKey]);\n\n return {\n hasRecoverableSession: persist && recoverableSession != null,\n recoverSession,\n clearPersistedState,\n };\n}\n","import type { PersistedState } from '../types/persisted-state.js';\nimport {\n PERSIST_STORE_NAME,\n PERSIST_SESSION_MAX_AGE_MS,\n} from '../types/persisted-state.js';\n\nfunction openDb(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.open('react-import-sheet-db', 1);\n req.onerror = () => reject(req.error);\n req.onsuccess = () => resolve(req.result);\n req.onupgradeneeded = () => {\n req.result.createObjectStore(PERSIST_STORE_NAME, { keyPath: 'key' });\n };\n });\n}\n\nexport async function savePersistedState(\n key: string,\n state: PersistedState,\n): Promise<void> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(PERSIST_STORE_NAME, 'readwrite');\n const store = tx.objectStore(PERSIST_STORE_NAME);\n const record = { key, ...state };\n const req = store.put(record);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error);\n tx.oncomplete = () => db.close();\n });\n}\n\nexport async function loadPersistedState(\n key: string,\n): Promise<PersistedState | null> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(PERSIST_STORE_NAME, 'readonly');\n const store = tx.objectStore(PERSIST_STORE_NAME);\n const req = store.get(key);\n req.onsuccess = () => {\n db.close();\n const row = req.result as (PersistedState & { key: string }) | undefined;\n if (row == null) {\n resolve(null);\n return;\n }\n const savedAt = row.savedAt;\n if (Date.now() - savedAt > PERSIST_SESSION_MAX_AGE_MS) {\n resolve(null);\n return;\n }\n const { key: _k, ...state } = row;\n resolve(state as PersistedState);\n };\n req.onerror = () => reject(req.error);\n });\n}\n\nexport async function clearPersistedState(key: string): Promise<void> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(PERSIST_STORE_NAME, 'readwrite');\n const store = tx.objectStore(PERSIST_STORE_NAME);\n const req = store.delete(key);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error);\n tx.oncomplete = () => db.close();\n });\n}\n","import { useContext } from 'react';\r\nimport { ImporterContext } from './ImporterContext.js';\r\nimport type { ImporterContextValue } from './types.js';\r\n\r\nexport function useImporterContext(): ImporterContextValue {\r\n const context = useContext(ImporterContext);\r\n if (context === null) {\r\n throw new Error('useImporter must be used within an ImporterProvider');\r\n }\r\n return context;\r\n}\r\n","import { useCallback, useEffect, useMemo } from 'react';\nimport { useImporterContext } from '../providers/index.js';\nimport { hasValidationErrors } from '../core/view/get-view-counts.js';\nimport { sheetToObjectsWithKeyMap } from '../core/view/export/sheet-to-objects.js';\nimport type { Sheet } from '../types/sheet.js';\nimport type { UseImporterOptions } from './types.js';\n\nfunction rowsToLayoutObjects(sheet: Sheet): Record<string, unknown>[] {\n return sheet.rows.map((row) =>\n row.cells.reduce((acc, c) => ({ ...acc, [c.key]: c.value }), {} as Record<string, unknown>)\n );\n}\n\nexport function useImporter(options: UseImporterOptions = {}) {\n const ctx = useImporterContext();\n const { layout: layoutOption, engine: engineOption } = options;\n\n useEffect(() => {\n if (layoutOption !== undefined) {\n ctx.setLayout(layoutOption);\n }\n }, [ctx, layoutOption]);\n\n useEffect(() => {\n if (engineOption !== undefined) {\n ctx.setEngine(engineOption);\n }\n }, [ctx, engineOption]);\n\n const canSubmit = useMemo(\n () =>\n Boolean(\n ctx.result &&\n ctx.status === 'success' &&\n !ctx.submitDone &&\n !hasValidationErrors(ctx.result)\n ),\n [ctx.result, ctx.status, ctx.submitDone]\n );\n\n const submit = useCallback(() => {\n if (!ctx.result || ctx.submitDone || hasValidationErrors(ctx.result) || !ctx.onSubmit) return;\n const data = ctx.submitKeyMap\n ? sheetToObjectsWithKeyMap(ctx.result, ctx.submitKeyMap)\n : rowsToLayoutObjects(ctx.result);\n ctx.onSubmit(data);\n ctx.setSubmitDone(true);\n }, [ctx]);\n\n return useMemo(\n () => ({\n processFile: ctx.processFile,\n registerValidator: ctx.registerValidator,\n registerSanitizer: ctx.registerSanitizer,\n registerTransform: ctx.registerTransform,\n abort: ctx.abort,\n metrics: ctx.metrics,\n submit,\n canSubmit,\n submitDone: ctx.submitDone,\n }),\n [\n ctx.processFile,\n ctx.registerValidator,\n ctx.registerSanitizer,\n ctx.registerTransform,\n ctx.abort,\n ctx.metrics,\n submit,\n canSubmit,\n ctx.submitDone,\n ]\n );\n}\n","import type { Sheet, ValidatedRow } from '../../types/sheet.js';\n\nexport function getRowsWithErrors(sheet: Sheet): ValidatedRow[] {\n return sheet.rows.filter((row) => row.errors.length > 0);\n}\n","import type { Sheet } from '../../types/sheet.js';\nimport type { ViewCounts } from './types/index.js';\nimport { getRowsWithErrors } from './get-rows-with-errors.js';\n\nexport function hasValidationErrors(sheet: Sheet | null): boolean {\n if (!sheet) return false;\n return getViewCounts(sheet).totalErrors > 0;\n}\n\nexport function getViewCounts(sheet: Sheet): ViewCounts {\n const totalRows = sheet.rows.length;\n const rowsWithErrors = getRowsWithErrors(sheet);\n const totalErrors =\n sheet.errors.length +\n sheet.rows.reduce(\n (sum, row) =>\n sum + row.errors.length + row.cells.reduce((c, cell) => c + cell.errors.length, 0),\n 0\n );\n return {\n totalRows,\n rowsWithErrors: rowsWithErrors.length,\n totalErrors,\n };\n}\n","import type { Sheet, ValidatedRow } from '../../../types/sheet.js';\n\nexport function getCellValue(row: ValidatedRow, key: string): unknown {\n const cell = row.cells.find((c) => c.key === key);\n return cell?.value;\n}\n\nexport function sheetRowsToObjects<T>(\n rows: readonly ValidatedRow[],\n mapRow: (row: ValidatedRow) => T\n): T[] {\n return rows.map(mapRow);\n}\n\nexport function sheetToObjectsWithKeyMap(\n sheet: Sheet | null,\n keyMap: Readonly<Record<string, string>>\n): Record<string, unknown>[] {\n if (!sheet) return [];\n return sheet.rows.map((row) => {\n const obj: Record<string, unknown> = {};\n for (const [sheetKey, outputKey] of Object.entries(keyMap)) {\n obj[outputKey] = getCellValue(row, sheetKey);\n }\n return obj;\n });\n}\n","import { useCallback, useEffect } from 'react';\nimport { useImporterContext } from '../providers/index.js';\nimport { useParserWorker } from '../core/parser/hooks/useParserWorker.js';\n\nfunction firstSheetFromResult(\n result: { sheets: Readonly<Record<string, { documentHash: string }>> },\n): { documentHash: string } | null {\n const names = Object.keys(result.sheets);\n if (names.length === 0) return null;\n return result.sheets[names[0] ?? ''] ?? null;\n}\n\nexport function useImportSheet() {\n const ctx = useImporterContext();\n const { load, parseAll, isReady } = useParserWorker();\n\n useEffect(() => {\n const { file, status, engine } = ctx;\n if (!isReady || !file || status !== 'loading') return;\n load(file, { maxRows: 10, fileName: file.name, engine: engine ?? undefined })\n .then((result) => {\n const first = firstSheetFromResult(result);\n if (!first) {\n ctx.setStatus('error');\n return;\n }\n const sheet = result.sheets[Object.keys(result.sheets)[0] ?? ''];\n if (!sheet) {\n ctx.setStatus('error');\n return;\n }\n ctx.setRawData(sheet);\n ctx.setDocumentHash(sheet.documentHash);\n ctx.setStatus('success');\n })\n .catch(() => {\n ctx.setStatus('error');\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps -- run only when file/status/isReady/load change; ctx setters are stable\n }, [isReady, ctx.file, ctx.status, ctx.setRawData, ctx.setDocumentHash, ctx.setStatus, load]);\n\n const startFullImport = useCallback(() => {\n const { file } = ctx;\n if (!file) return Promise.reject(new Error('No file loaded'));\n ctx.setStatus('loading');\n const t0 = performance.now();\n return parseAll((detail) => ctx.dispatchProgress(detail)).then((result) => {\n const t1 = performance.now();\n ctx.setPhaseTiming('parse', t1 - t0);\n const first = firstSheetFromResult(result);\n if (!first) {\n ctx.setStatus('error');\n return result;\n }\n const sheet = result.sheets[Object.keys(result.sheets)[0] ?? ''];\n if (!sheet) {\n ctx.setStatus('error');\n return result;\n }\n ctx.setRawData(sheet);\n ctx.setDocumentHash(sheet.documentHash);\n ctx.setStatus('success');\n return result;\n });\n }, [ctx, parseAll]);\n\n return { startFullImport };\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport * as Comlink from 'comlink';\nimport type { RawParseResult } from '../../../types/raw-sheet.js';\nimport type { ParseOptions } from '../types/index.js';\nimport type { ImporterProgressDetail } from '../../../types/importer-state.js';\nimport { useImporterContext } from '../../../providers/index.js';\nimport { getParserWorkerUrl } from '../worker/worker-url.js';\n\ntype ParserWorkerApi = {\n load: (blob: Blob, options?: ParseOptions) => Promise<RawParseResult>;\n parseAll: (onProgress?: (d: ImporterProgressDetail) => void) => Promise<RawParseResult>;\n};\n\nexport function useParserWorker() {\n const { setActiveWorker, dispatchProgress } = useImporterContext();\n const [workerProxy, setWorkerProxy] = useState<Comlink.Remote<ParserWorkerApi> | null>(null);\n const workerRef = useRef<Worker | null>(null);\n\n useEffect(() => {\n const worker = new Worker(getParserWorkerUrl(), { type: 'module' });\n workerRef.current = worker;\n setActiveWorker(worker);\n const proxy = Comlink.wrap<ParserWorkerApi>(worker);\n queueMicrotask(() => setWorkerProxy(proxy));\n return () => {\n worker.terminate();\n workerRef.current = null;\n setActiveWorker(null);\n };\n }, [setActiveWorker]);\n\n const load = useCallback(\n async (blob: Blob, options: ParseOptions = {}): Promise<RawParseResult> => {\n if (!workerProxy) throw new Error('Parser worker not ready');\n return workerProxy.load(blob, options);\n },\n [workerProxy],\n );\n\n const parseAll = useCallback(\n async (onProgress?: (d: ImporterProgressDetail) => void): Promise<RawParseResult> => {\n if (!workerProxy) throw new Error('Parser worker not ready');\n const progressProxy = onProgress ? Comlink.proxy(onProgress) : undefined;\n return workerProxy.parseAll(progressProxy);\n },\n [workerProxy],\n );\n\n return { load, parseAll, dispatchProgress, isReady: !!workerProxy };\n}\n","export function getParserWorkerUrl(): string {\n return new URL('./parser.worker.js', import.meta.url).href;\n}\n","import { useCallback, useMemo } from 'react';\nimport { useImporterContext } from '../../../providers/index.js';\nimport { runConvert } from '../run-convert.js';\nimport type { ConvertOptions } from '../types/convert-options.js';\nimport type { ConvertResult, ConvertResultApplyResult } from '../types/convert-result.js';\n\nexport function useConvert() {\n const ctx = useImporterContext();\n const { rawData, layout, convertedSheet, convertResultData, setConvertedSheet, setConvertResultData } = ctx;\n\n const convert = useCallback(\n (options?: ConvertOptions) => {\n if (!rawData || !layout) return;\n const result = runConvert(rawData, layout, options, convertResultData ?? undefined);\n if (result.kind === 'success') {\n setConvertedSheet(result.sheet);\n } else {\n setConvertResultData({\n headersFound: result.headersFound,\n mismatches: result.mismatches,\n columnOrder: result.columnOrder,\n headerToFieldMap: result.headerToFieldMap,\n });\n }\n },\n [rawData, layout, convertResultData, setConvertedSheet, setConvertResultData],\n );\n\n const applyMappingImpl = useCallback((): ConvertResultApplyResult | undefined => {\n if (!rawData || !layout || !convertResultData) return undefined;\n const result = runConvert(rawData, layout, {}, {\n columnOrder: convertResultData.columnOrder,\n headerToFieldMap: convertResultData.headerToFieldMap,\n });\n if (result.kind === 'success') {\n setConvertedSheet(result.sheet);\n return { kind: 'success', sheet: result.sheet };\n }\n setConvertResultData({\n headersFound: result.headersFound,\n mismatches: result.mismatches,\n columnOrder: result.columnOrder,\n headerToFieldMap: result.headerToFieldMap,\n });\n return { kind: 'mismatch', result };\n }, [rawData, layout, convertResultData, setConvertedSheet, setConvertResultData]);\n\n const reorderColumns = useCallback(\n (fieldNames: string[]) => {\n setConvertResultData((prev) =>\n prev ? { ...prev, columnOrder: fieldNames } : prev,\n );\n },\n [setConvertResultData],\n );\n\n const renameColumn = useCallback(\n (fileHeader: string, layoutFieldName: string) => {\n setConvertResultData((prev) =>\n prev\n ? {\n ...prev,\n headerToFieldMap: { ...prev.headerToFieldMap, [fileHeader]: layoutFieldName },\n }\n : prev,\n );\n },\n [setConvertResultData],\n );\n\n const convertResult: ConvertResult | null = useMemo(() => {\n if (!convertResultData) return null;\n return {\n kind: 'mismatch',\n headersFound: convertResultData.headersFound,\n mismatches: convertResultData.mismatches,\n columnOrder: [...convertResultData.columnOrder],\n headerToFieldMap: { ...convertResultData.headerToFieldMap },\n reorderColumns,\n renameColumn,\n applyMapping: () =>\n applyMappingImpl() ?? {\n kind: 'mismatch' as const,\n result: { ...convertResultData, kind: 'mismatch' as const },\n },\n };\n }, [convertResultData, reorderColumns, renameColumn, applyMappingImpl]);\n\n return useMemo(\n () => ({\n convert,\n convertedSheet,\n convertResult,\n }),\n [convert, convertedSheet, convertResult],\n );\n}\n","import type { RawSheet } from '../../types/raw-sheet.js';\nimport type { SheetLayout } from '../../types/sheet-layout.js';\nimport type { ConvertedSheet, ConvertedSheetCell, ConvertedSheetRow } from './types/converted-sheet.js';\n\nexport function buildConvertedSheet(\n rawSheet: RawSheet,\n _sheetLayout: SheetLayout,\n columnOrder: readonly string[],\n fieldToHeader: Readonly<Record<string, string | null>>,\n): ConvertedSheet {\n const headers = [...columnOrder];\n const headerIndex = new Map<string, number>();\n rawSheet.headers.forEach((h, i) => headerIndex.set(h, i));\n\n const rows: ConvertedSheetRow[] = rawSheet.rows.map((row) => {\n const cells: ConvertedSheetCell[] = columnOrder.map((fieldName) => {\n const fileHeader = fieldToHeader[fieldName];\n const value =\n fileHeader != null\n ? (() => {\n const idx = headerIndex.get(fileHeader);\n if (idx == null) return null;\n const cell = row.cells[idx];\n return cell?.value ?? null;\n })()\n : null;\n return { key: fieldName, value: value ?? null };\n });\n return { index: row.index, cells };\n });\n\n return {\n name: rawSheet.name,\n filesize: rawSheet.filesize,\n documentHash: rawSheet.documentHash,\n rowsCount: rawSheet.rowsCount,\n headersCount: rawSheet.headersCount,\n headers,\n rows,\n };\n}\n","export function normalize(s: string): string {\n const t = s.trim().toLowerCase();\n return t.normalize('NFD').replace(/\\p{Diacritic}/gu, '');\n}\n\nfunction levenshteinDistance(a: string, b: string): number {\n if (a.length === 0) return b.length;\n if (b.length === 0) return a.length;\n let prev = Array.from({ length: b.length + 1 }, (_, i) => i);\n for (let i = 1; i <= a.length; i++) {\n const curr: number[] = [i];\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n curr[j] = Math.min(\n curr[j - 1]! + 1,\n prev[j]! + 1,\n prev[j - 1]! + cost,\n );\n }\n prev = curr;\n }\n return prev[b.length]!;\n}\n\nexport function getSimilarity(s1: string, s2: string): number {\n const a = normalize(s1);\n const b = normalize(s2);\n const longer = a.length >= b.length ? a : b;\n const shorter = a.length < b.length ? a : b;\n if (longer.length === 0) return 1;\n const distance = levenshteinDistance(longer, shorter);\n return (longer.length - distance) / longer.length;\n}\n\nconst DEFAULT_FUZZY_THRESHOLD = 0.8;\n\nexport interface MapHeadersOptions {\n threshold?: number;\n}\n\nexport interface MapHeadersItem {\n key: string;\n matchedHeader: string | null;\n}\n\nexport function mapHeaders(\n rawHeaders: string[],\n expectedKeys: string[],\n options: MapHeadersOptions = {},\n): MapHeadersItem[] {\n const threshold = options.threshold ?? DEFAULT_FUZZY_THRESHOLD;\n const keyScores: { key: string; header: string; score: number }[] = [];\n for (const key of expectedKeys) {\n for (const header of rawHeaders) {\n const score = getSimilarity(key, header);\n if (score >= threshold) {\n keyScores.push({ key, header, score });\n }\n }\n }\n keyScores.sort((x, y) => y.score - x.score);\n\n const assignedKeys = new Set<string>();\n const assignedHeaders = new Set<string>();\n const keyToHeader: Record<string, string | null> = {};\n for (const k of expectedKeys) {\n keyToHeader[k] = null;\n }\n for (const { key, header, score: _ } of keyScores) {\n if (assignedKeys.has(key) || assignedHeaders.has(header)) continue;\n keyToHeader[key] = header;\n assignedKeys.add(key);\n assignedHeaders.add(header);\n }\n\n return expectedKeys.map((key) => ({\n key,\n matchedHeader: keyToHeader[key] ?? null,\n }));\n}\n","import type { RawSheet } from '../../types/raw-sheet.js';\nimport type { SheetLayout } from '../../types/sheet-layout.js';\nimport { mapHeaders } from '../parser/utils/fuzzy-match.js';\nimport type { ColumnMismatch } from './types/column-mismatch.js';\nimport type { ConvertOptions } from './types/convert-options.js';\n\nexport interface MatchHeadersResult {\n readonly fieldToHeader: Readonly<Record<string, string | null>>;\n readonly mismatches: readonly ColumnMismatch[];\n}\n\nfunction defaultNormalize(header: string, caseSensitive: boolean): string {\n const trimmed = header.trim();\n return caseSensitive ? trimmed : trimmed.toLowerCase();\n}\n\nexport function matchHeadersToLayout(\n rawSheet: RawSheet,\n sheetLayout: SheetLayout,\n headerToFieldMap: Readonly<Record<string, string>> = {},\n options: ConvertOptions = {}\n): MatchHeadersResult {\n const caseSensitive = options.caseSensitive ?? false;\n const normalizer = options.normalizer ?? ((h: string) => defaultNormalize(h, caseSensitive));\n const layoutFieldNames = Object.keys(sheetLayout.fields) as string[];\n const fileHeaders = rawSheet.headers as string[];\n const normalizedToFileHeader = new Map<string, string>();\n for (const h of fileHeaders) {\n normalizedToFileHeader.set(normalizer(h), h);\n }\n\n const fieldToHeader: Record<string, string | null> = {};\n const usedFileHeaders = new Set<string>();\n\n for (const [fileHeader, fieldName] of Object.entries(headerToFieldMap)) {\n if (layoutFieldNames.includes(fieldName)) {\n fieldToHeader[fieldName] = fileHeaders.includes(fileHeader) ? fileHeader : null;\n if (fieldToHeader[fieldName]) usedFileHeaders.add(fileHeader);\n }\n }\n\n for (const fieldName of layoutFieldNames) {\n if (fieldToHeader[fieldName] != null) continue;\n const key = normalizer(fieldName);\n const fileHeader = normalizedToFileHeader.get(key);\n if (fileHeader != null && !usedFileHeaders.has(fileHeader)) {\n fieldToHeader[fieldName] = fileHeader;\n usedFileHeaders.add(fileHeader);\n } else {\n fieldToHeader[fieldName] = null;\n }\n }\n\n if (options.fuzzyHeaders === true) {\n const unmatchedFields = layoutFieldNames.filter((f) => fieldToHeader[f] == null);\n const availableHeaders = fileHeaders.filter((h) => !usedFileHeaders.has(h));\n const threshold = options.fuzzyThreshold ?? 0.8;\n const fuzzyResults = mapHeaders(availableHeaders, unmatchedFields, { threshold });\n for (const { key, matchedHeader } of fuzzyResults) {\n if (matchedHeader != null && !usedFileHeaders.has(matchedHeader)) {\n fieldToHeader[key] = matchedHeader;\n usedFileHeaders.add(matchedHeader);\n }\n }\n }\n\n const mismatches: ColumnMismatch[] = [];\n for (const fieldName of layoutFieldNames) {\n const found = fieldToHeader[fieldName];\n if (found == null) {\n const field = sheetLayout.fields[fieldName];\n const required = field?.required !== false;\n mismatches.push({\n expected: fieldName,\n found: null,\n message: `Column '${fieldName}' not found in file`,\n required,\n });\n }\n }\n\n return { fieldToHeader, mismatches };\n}\n","import type { RawSheet } from '../../types/raw-sheet.js';\nimport type { SheetLayout } from '../../types/sheet-layout.js';\nimport { buildConvertedSheet } from './build-converted-sheet.js';\nimport { matchHeadersToLayout } from './match-headers.js';\nimport type { ConvertMismatchData } from './types/convert-mismatch-data.js';\nimport type { ConvertOptions } from './types/convert-options.js';\nimport type { ConvertSuccess } from './types/convert-success.js';\n\nexport type RunConvertExisting = {\n readonly columnOrder: readonly string[];\n readonly headerToFieldMap: Readonly<Record<string, string>>;\n};\n\nexport type RunConvertResult = ConvertSuccess | ConvertMismatchData;\n\nexport function runConvert(\n rawSheet: RawSheet,\n sheetLayout: SheetLayout,\n options: ConvertOptions = {},\n existing?: RunConvertExisting\n): RunConvertResult {\n const layoutFieldNames = Object.keys(sheetLayout.fields) as string[];\n const columnOrder = existing?.columnOrder?.length\n ? (existing.columnOrder as string[])\n : layoutFieldNames;\n const headerToFieldMap = existing?.headerToFieldMap ?? {};\n\n const { fieldToHeader, mismatches } = matchHeadersToLayout(\n rawSheet,\n sheetLayout,\n headerToFieldMap,\n options\n );\n\n const requiredFieldNames = layoutFieldNames.filter(\n (f) => sheetLayout.fields[f]?.required !== false\n );\n const allRequiredMatched = requiredFieldNames.every((f) => fieldToHeader[f] != null);\n const allMatched = mismatches.length === 0;\n\n if (allMatched || allRequiredMatched) {\n const sheet = buildConvertedSheet(rawSheet, sheetLayout, columnOrder, fieldToHeader);\n return { kind: 'success', sheet };\n }\n\n const layoutError = mismatches.some((m) => m.required === true);\n return {\n kind: 'mismatch',\n headersFound: [...rawSheet.headers],\n mismatches,\n columnOrder: [...columnOrder],\n headerToFieldMap: { ...headerToFieldMap },\n layoutError,\n };\n}\n","import { useMemo } from 'react';\r\nimport { useImporterContext } from '../providers/index.js';\r\n\r\nexport function useImporterStatus() {\r\n const ctx = useImporterContext();\r\n return useMemo(\r\n () => ({\r\n status: ctx.status,\r\n progressEventTarget: ctx.progressEventTarget,\r\n }),\r\n [ctx.status, ctx.progressEventTarget],\r\n );\r\n}\r\n","import { useCallback, useMemo } from 'react';\r\nimport type { ValidatedRow } from '../types/sheet.js';\r\nimport { useImporterContext } from '../providers/index.js';\r\nimport {\r\n sheetRowsToObjects,\r\n sheetToObjectsWithKeyMap,\r\n} from '../core/view/export/sheet-to-objects.js';\r\n\r\nexport function useSheetData() {\r\n const ctx = useImporterContext();\r\n const sheet = ctx.result;\r\n const errors = useMemo(() => {\r\n if (!sheet) return [];\r\n return [...sheet.errors];\r\n }, [sheet]);\r\n const toObjects = useCallback(\r\n <T>(mapRow: (row: ValidatedRow) => T): T[] => {\r\n if (!sheet) return [];\r\n return sheetRowsToObjects(sheet.rows, mapRow);\r\n },\r\n [sheet]\r\n );\r\n const toObjectsWithKeyMap = useCallback(\r\n (keyMap: Readonly<Record<string, string>>): Record<string, unknown>[] => {\r\n return sheetToObjectsWithKeyMap(sheet, keyMap);\r\n },\r\n [sheet]\r\n );\r\n return useMemo(\r\n () => ({ sheet, errors, toObjects, toObjectsWithKeyMap }),\r\n [sheet, errors, toObjects, toObjectsWithKeyMap]\r\n );\r\n}\r\n","import { useCallback, useMemo, useRef } from 'react';\nimport { type ChangeLogEntry, formatChangeLogAsText } from '../types/change-log.js';\nimport type { EditCellParams } from '../types/edit.js';\nimport type { PaginatedResult } from '../types/paginated-result.js';\nimport type { ValidatedRow } from '../types/sheet.js';\nimport { useImporterContext } from '../providers/index.js';\nimport { removeRow as removeRowSheet } from '../core/editor/immutable-update.js';\nimport { useEditWorker } from '../core/editor/hooks/useEditWorker.js';\nimport { getPaginatedResult } from '../core/editor/get-paginated-result.js';\nimport { getCellByKey, getRowByIndex } from '../core/editor/resolve.js';\n\nexport interface UseSheetEditorOptions {\n page?: number;\n pageSize?: number;\n debounceMs?: number;\n}\n\nexport function useSheetEditor(options: UseSheetEditorOptions = {}) {\n const {\n result: sheet,\n setResult,\n layout,\n changeLog,\n addChangeLogEntry,\n submitDone,\n } = useImporterContext();\n const { runEdit, isReady } = useEditWorker();\n const canEdit = !submitDone;\n const { page = 1, pageSize = 25, debounceMs } = options;\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const pageData = useMemo((): PaginatedResult<ValidatedRow> => {\n if (!sheet) {\n return { page: 1, pageSize, totalCount: 0, totalPages: 0, rows: [] };\n }\n return getPaginatedResult(sheet, page, pageSize);\n }, [sheet, page, pageSize]);\n\n const totalPages = pageData.totalPages;\n\n const applyEdit = useCallback(\n (params: EditCellParams) => {\n if (!sheet || !layout || submitDone) return Promise.resolve();\n const previousValue =\n getRowByIndex(sheet, params.rowIndex) &&\n getCellByKey(getRowByIndex(sheet, params.rowIndex)!, params.cellKey)?.value;\n return runEdit(sheet, layout, params.rowIndex, params.cellKey, params.value).then(\n (newSheet) => {\n setResult(newSheet);\n queueMicrotask(() => {\n const entry: ChangeLogEntry = {\n type: 'cell_edit',\n rowIndex: params.rowIndex,\n cellKey: params.cellKey,\n value: params.value,\n previousValue,\n timestamp: Date.now(),\n };\n addChangeLogEntry(entry);\n });\n }\n );\n },\n [sheet, layout, submitDone, runEdit, setResult, addChangeLogEntry]\n );\n\n const editCell = useCallback(\n (params: EditCellParams): void | Promise<void> => {\n if (debounceMs != null && debounceMs > 0) {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(() => {\n debounceRef.current = null;\n applyEdit(params);\n }, debounceMs);\n return;\n }\n return applyEdit(params);\n },\n [debounceMs, applyEdit]\n );\n\n const removeRow = useCallback(\n (rowIndex: number): void => {\n if (!sheet || submitDone) return;\n const newSheet = removeRowSheet(sheet, rowIndex);\n setResult(newSheet);\n queueMicrotask(() => {\n const entry: ChangeLogEntry = {\n type: 'row_remove',\n rowIndex,\n timestamp: Date.now(),\n };\n addChangeLogEntry(entry);\n });\n },\n [sheet, submitDone, setResult, addChangeLogEntry]\n );\n\n const changeLogAsText = useMemo(() => formatChangeLogAsText(changeLog), [changeLog]);\n\n return useMemo(\n () => ({\n sheet,\n editCell,\n removeRow,\n pageData,\n totalPages,\n isReady,\n canEdit,\n changeLog,\n changeLogAsText,\n }),\n [sheet, editCell, removeRow, pageData, totalPages, isReady, canEdit, changeLog, changeLogAsText]\n );\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport * as Comlink from 'comlink';\nimport type { SheetLayout } from '../../../types/sheet-layout.js';\nimport type { Sheet } from '../../../types/sheet.js';\nimport { getEditWorkerUrl } from '../worker/worker-url.js';\n\nexport interface EditWorkerOptions {\n signal?: AbortSignal;\n}\n\ntype EditWorkerApi = {\n runEdit: (\n sheet: Sheet,\n sheetLayout: SheetLayout,\n rowIndex: number,\n cellKey: string,\n value: unknown,\n options?: EditWorkerOptions,\n ) => Promise<Sheet>;\n};\n\nexport function useEditWorker() {\n const [workerProxy, setWorkerProxy] = useState<Comlink.Remote<EditWorkerApi> | null>(null);\n const workerRef = useRef<Worker | null>(null);\n\n useEffect(() => {\n const worker = new Worker(getEditWorkerUrl(), { type: 'module' });\n workerRef.current = worker;\n const proxy = Comlink.wrap<EditWorkerApi>(worker);\n queueMicrotask(() => setWorkerProxy(proxy));\n return () => {\n worker.terminate();\n workerRef.current = null;\n };\n }, []);\n\n const runEdit = useCallback(\n async (\n sheet: Sheet,\n sheetLayout: SheetLayout,\n rowIndex: number,\n cellKey: string,\n value: unknown,\n options?: EditWorkerOptions,\n ): Promise<Sheet> => {\n if (!workerProxy) throw new Error('Edit worker not ready');\n return workerProxy.runEdit(\n sheet,\n sheetLayout,\n rowIndex,\n cellKey,\n value,\n options ?? {},\n );\n },\n [workerProxy],\n );\n\n return { runEdit, isReady: !!workerProxy };\n}\n","export function getEditWorkerUrl(): string {\n return new URL('./edit.worker.js', import.meta.url).href;\n}\n","import type { PaginatedResult } from '../../types/paginated-result.js';\nimport type { Sheet, ValidatedRow } from '../../types/sheet.js';\n\nexport function getPaginatedResult(\n sheet: Sheet,\n page: number,\n pageSize: number,\n): PaginatedResult<ValidatedRow> {\n return getPaginatedResultFromRows(sheet.rows, page, pageSize);\n}\n\nexport function getPaginatedResultFromRows<TRow>(\n rows: readonly TRow[],\n page: number,\n pageSize: number,\n): PaginatedResult<TRow> {\n const totalCount = rows.length;\n const totalPages =\n pageSize <= 0 ? 0 : Math.max(1, Math.ceil(totalCount / pageSize));\n const safePage = Math.max(1, Math.min(page, totalPages));\n const start = (safePage - 1) * pageSize;\n const end = Math.min(start + pageSize, totalCount);\n const slice = rows.slice(start, end);\n return {\n page: safePage,\n pageSize,\n totalCount,\n totalPages,\n rows: slice,\n };\n}\n","import { useCallback, useMemo, useState } from 'react';\nimport type { ValidatedRow } from '../../../types/sheet.js';\nimport { useImporterContext } from '../../../providers/index.js';\nimport { useSheetEditor } from '../../../hooks/useSheetEditor.js';\nimport { getPaginatedResultFromRows } from '../../editor/get-paginated-result.js';\nimport { getRowsWithErrors } from '../get-rows-with-errors.js';\nimport { getViewCounts } from '../get-view-counts.js';\nimport { sheetToCSV } from '../export/sheet-to-csv.js';\nimport { sheetToJSON } from '../export/sheet-to-json.js';\nimport type { UseSheetViewOptions, UseSheetViewReturn } from '../types/index.js';\n\nexport function useSheetView(options: UseSheetViewOptions = {}): UseSheetViewReturn<ValidatedRow> {\n const { page: initialPage = 1, defaultPageSize = 25, filterMode = 'all' } = options;\n const [page, setPage] = useState(initialPage);\n const pageSize = defaultPageSize;\n const { sheet, editCell, removeRow, changeLog, changeLogAsText } = useSheetEditor({});\n const ctx = useImporterContext();\n\n const rowsWithErrors = useMemo(() => (sheet ? getRowsWithErrors(sheet) : []), [sheet]);\n const sourceRows = useMemo(\n () => (filterMode === 'errors-only' ? rowsWithErrors : (sheet?.rows ?? [])),\n [filterMode, rowsWithErrors, sheet]\n );\n const totalRows = sourceRows.length;\n\n const getPaginatedResult = useCallback(\n (p?: number, ps?: number) => {\n const pp = p ?? page;\n const pps = ps ?? pageSize;\n return getPaginatedResultFromRows(sourceRows, pp, pps);\n },\n [page, pageSize, sourceRows]\n );\n const paginatedRows = useMemo(\n () => getPaginatedResult(page, pageSize).rows,\n [getPaginatedResult, page, pageSize]\n );\n const getRows = useCallback(\n (page: number, limit: number) => {\n // 1-based page → 0-based start index\n const start = (page - 1) * limit;\n return sourceRows.slice(start, start + limit);\n },\n [sourceRows]\n );\n const counts = useMemo(\n () => (sheet ? getViewCounts(sheet) : { totalRows: 0, rowsWithErrors: 0, totalErrors: 0 }),\n [sheet]\n );\n\n const exportToCSV = useCallback(\n (opts?: Parameters<UseSheetViewReturn['exportToCSV']>[0]) => {\n if (!sheet || !ctx.layout) return '';\n return sheetToCSV(sheet, ctx.layout, opts ?? {});\n },\n [sheet, ctx.layout]\n );\n const exportToJSON = useCallback(\n (opts?: Parameters<UseSheetViewReturn['exportToJSON']>[0]) => {\n if (!sheet) return '[]';\n return sheetToJSON(sheet, ctx.layout ?? null, opts ?? {});\n },\n [sheet, ctx.layout]\n );\n\n const downloadCSV = useCallback(\n async (opts?: Parameters<UseSheetViewReturn['downloadCSV']>[0]) => {\n const content = exportToCSV(opts);\n if (!content) return;\n const blob = new Blob([content], { type: 'text/csv;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = (opts?.filename ?? 'export') + '.csv';\n a.click();\n URL.revokeObjectURL(url);\n },\n [exportToCSV]\n );\n const downloadJSON = useCallback(\n async (opts?: Parameters<UseSheetViewReturn['downloadJSON']>[0]) => {\n const content = exportToJSON(opts);\n const blob = new Blob([content], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = (opts?.filename ?? 'export') + '.json';\n a.click();\n URL.revokeObjectURL(url);\n },\n [exportToJSON]\n );\n\n return useMemo(\n () => ({\n sheet,\n getPaginatedResult,\n paginatedRows,\n page,\n setPage,\n pageSize,\n totalRows,\n getRows,\n rowsWithErrors,\n counts,\n editCell,\n removeRow,\n changeLog,\n changeLogAsText,\n exportToCSV,\n exportToJSON,\n downloadCSV,\n downloadJSON,\n hasRecoverableSession: ctx.hasRecoverableSession,\n recoverSession: ctx.recoverSession,\n clearPersistedState: ctx.clearPersistedState,\n }),\n [\n sheet,\n getPaginatedResult,\n paginatedRows,\n page,\n pageSize,\n totalRows,\n getRows,\n rowsWithErrors,\n counts,\n editCell,\n removeRow,\n changeLog,\n changeLogAsText,\n exportToCSV,\n exportToJSON,\n downloadCSV,\n downloadJSON,\n ctx.hasRecoverableSession,\n ctx.recoverSession,\n ctx.clearPersistedState,\n ]\n );\n}\n","import type { SheetLayout } from '../../../types/sheet-layout.js';\nimport type { Sheet } from '../../../types/sheet.js';\nimport type { ExportOptions } from '../types/export-options.js';\n\nconst BOM = '\\uFEFF';\n\nfunction escapeCsvValue(value: string, separator: string): string {\n const needsQuotes =\n value.includes(separator) || value.includes('\"') || value.includes('\\n') || value.includes('\\r');\n if (!needsQuotes) return value;\n return '\"' + value.replace(/\"/g, '\"\"') + '\"';\n}\n\nfunction cellValueToString(value: unknown, formatDates: boolean): string {\n if (value === null || value === undefined) return '';\n if (value instanceof Date) return formatDates ? value.toLocaleString() : value.toISOString();\n return String(value);\n}\n\nexport function sheetToCSV(\n sheet: Sheet,\n sheetLayout: SheetLayout | null,\n options: ExportOptions = {},\n): string {\n const {\n includeHeaders = true,\n csvSeparator = ',',\n formatDatesForExport = false,\n } = options;\n const fieldOrder =\n sheetLayout != null ? Object.keys(sheetLayout.fields) : [];\n const effectiveOrder =\n fieldOrder.length > 0\n ? fieldOrder\n : (sheet.rows[0]?.cells.map((c) => c.key) ?? sheet.headers.slice());\n\n const lines: string[] = [];\n if (includeHeaders && effectiveOrder.length > 0) {\n lines.push(effectiveOrder.map((h) => escapeCsvValue(h, csvSeparator)).join(csvSeparator));\n }\n for (const row of sheet.rows) {\n const values = effectiveOrder.map((key) => {\n const cell = row.cells.find((c) => c.key === key);\n const raw = cell?.value ?? '';\n return escapeCsvValue(cellValueToString(raw, formatDatesForExport), csvSeparator);\n });\n lines.push(values.join(csvSeparator));\n }\n const body = lines.join('\\r\\n');\n return BOM + body;\n}\n","import type { SheetLayout } from '../../../types/sheet-layout.js';\nimport type { Sheet } from '../../../types/sheet.js';\nimport type { ExportOptions } from '../types/export-options.js';\n\nfunction cellValueToJson(value: unknown, formatDates: boolean): unknown {\n if (value === null || value === undefined) return null;\n if (value instanceof Date) return formatDates ? value.toLocaleString() : value.toISOString();\n return value;\n}\n\nexport function sheetToJSON(\n sheet: Sheet,\n _sheetLayout: SheetLayout | null,\n options: ExportOptions = {},\n): string {\n const { formatDatesForExport = false } = options;\n const rows = sheet.rows.map((row) => {\n const obj: Record<string, unknown> = {};\n for (const cell of row.cells) {\n obj[cell.key] = cellValueToJson(cell.value, formatDatesForExport);\n }\n return obj;\n });\n return JSON.stringify(rows, null, 0);\n}\n","import { useCallback, useEffect } from 'react';\r\nimport { IMPORTER_PROGRESS_EVENT } from '../types/index.js';\r\nimport type { ImporterProgressDetail } from '../types/index.js';\r\nimport { useImporterContext } from '../providers/index.js';\r\n\r\nexport function useImporterEventTarget() {\r\n const ctx = useImporterContext();\r\n const target = ctx.progressEventTarget;\r\n\r\n const subscribeToProgress = useCallback(\r\n (callback: (detail: ImporterProgressDetail) => void) => {\r\n const handler = (e: Event) => {\r\n callback((e as CustomEvent<ImporterProgressDetail>).detail);\r\n };\r\n target.addEventListener(IMPORTER_PROGRESS_EVENT, handler);\r\n return () => {\r\n target.removeEventListener(IMPORTER_PROGRESS_EVENT, handler);\r\n };\r\n },\r\n [target],\r\n );\r\n\r\n return { progressEventTarget: target, subscribeToProgress };\r\n}\r\n\r\nexport function useImporterProgressSubscription(\r\n callback: (detail: ImporterProgressDetail) => void,\r\n) {\r\n const { subscribeToProgress } = useImporterEventTarget();\r\n useEffect(() => {\r\n return subscribeToProgress(callback);\r\n }, [subscribeToProgress, callback]);\r\n}\r\n"],"mappings":"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","names":["useEffect","useMemo","useRef","useState","PERSIST_STORE_NAME","DEFAULT_PERSIST_KEY","createContext","ImporterContext","initialState","useCallback","useMemo","formatMs","ms","buildPipelineMetrics","timings","rowCount","overheadMs","totalMs","isSlow","efficiency","percentages","overhead","totalWithOverhead","formatChangeLogAsText","entries","lines","e","prev","IMPORTER_PROGRESS_EVENT","IMPORTER_ABORTED_EVENT","useCallback","useImporterStateSetters","deps","setState","setLayoutState","setEngineState","setFile","file","prev","setRawData","rawData","setDocumentHash","documentHash","setStatus","status","setResult","result","setConvertedSheet","convertedSheet","setSanitizedSheet","sanitizedSheet","setConvertResultData","dataOrUpdater","setMetrics","metrics","setSubmitDone","submitDone","setLayout","next","setEngine","INITIAL_PHASE_TIMINGS","useImporterActions","deps","setState","setLayoutState","setEngineState","progressEventTarget","validatorRegistry","sanitizerRegistry","transformRegistry","activeWorkerRef","phaseTimingsRef","stateSetters","useImporterStateSetters","dispatchProgress","useCallback","detail","IMPORTER_PROGRESS_EVENT","setActiveWorker","worker","abort","prev","IMPORTER_ABORTED_EVENT","setPhaseTiming","phase","ms","finalizeMetrics","rowCount","timings","metrics","buildPipelineMetrics","addChangeLogEntry","entry","processFile","file","registerValidator","name","fn","options","registerSanitizer","registerTransform","useMemo","useCallback","useEffect","useRef","useState","openDb","resolve","reject","req","PERSIST_STORE_NAME","savePersistedState","key","state","db","tx","store","record","loadPersistedState","row","savedAt","_k","clearPersistedState","DEBOUNCE_MS","usePersistSession","persist","persistKey","rawData","result","setRawData","setResult","layoutVersion","recoverableSession","setRecoverableSession","useState","debounceRef","useRef","useEffect","loadPersistedState","state","payload","savePersistedState","recoverSession","useCallback","clearPersistedState","jsx","ImporterProvider","children","layoutProp","engineProp","persist","persistKey","DEFAULT_PERSIST_KEY","onSubmit","submitKeyMap","state","setState","useState","initialState","layout","setLayoutState","engine","setEngineState","progressEventTarget","useMemo","validatorRegistry","Registry","sanitizerRegistry","transformRegistry","activeWorkerRef","useRef","phaseTimingsRef","stateSetters","useImporterStateSetters","persistSession","usePersistSession","actions","useImporterActions","useEffect","worker","value","ImporterContext","useContext","useImporterContext","context","useContext","ImporterContext","useCallback","useEffect","useMemo","getRowsWithErrors","sheet","row","hasValidationErrors","sheet","getViewCounts","totalRows","rowsWithErrors","getRowsWithErrors","totalErrors","sum","row","c","cell","getCellValue","row","key","c","sheetRowsToObjects","rows","mapRow","sheetToObjectsWithKeyMap","sheet","keyMap","obj","sheetKey","outputKey","rowsToLayoutObjects","sheet","row","acc","c","useImporter","options","ctx","useImporterContext","layoutOption","engineOption","useEffect","canSubmit","useMemo","hasValidationErrors","submit","useCallback","data","sheetToObjectsWithKeyMap","useCallback","useEffect","useCallback","useEffect","useRef","useState","Comlink","getParserWorkerUrl","useParserWorker","setActiveWorker","dispatchProgress","useImporterContext","workerProxy","setWorkerProxy","useState","workerRef","useRef","useEffect","worker","getParserWorkerUrl","proxy","load","useCallback","blob","options","parseAll","onProgress","progressProxy","firstSheetFromResult","result","names","useImportSheet","ctx","useImporterContext","load","parseAll","isReady","useParserWorker","useEffect","file","status","engine","sheet","useCallback","t0","detail","t1","useCallback","useMemo","buildConvertedSheet","rawSheet","_sheetLayout","columnOrder","fieldToHeader","headers","headerIndex","h","i","rows","row","cells","fieldName","fileHeader","value","idx","normalize","s","levenshteinDistance","a","b","prev","_","i","curr","j","cost","getSimilarity","s1","s2","longer","shorter","distance","DEFAULT_FUZZY_THRESHOLD","mapHeaders","rawHeaders","expectedKeys","options","threshold","keyScores","key","header","score","x","y","assignedKeys","assignedHeaders","keyToHeader","k","defaultNormalize","header","caseSensitive","trimmed","matchHeadersToLayout","rawSheet","sheetLayout","headerToFieldMap","options","normalizer","h","layoutFieldNames","fileHeaders","normalizedToFileHeader","fieldToHeader","usedFileHeaders","fileHeader","fieldName","key","unmatchedFields","f","availableHeaders","threshold","fuzzyResults","mapHeaders","matchedHeader","mismatches","required","runConvert","rawSheet","sheetLayout","options","existing","layoutFieldNames","columnOrder","headerToFieldMap","fieldToHeader","mismatches","matchHeadersToLayout","allRequiredMatched","f","buildConvertedSheet","layoutError","useConvert","ctx","useImporterContext","rawData","layout","convertedSheet","convertResultData","setConvertedSheet","setConvertResultData","convert","useCallback","options","result","runConvert","applyMappingImpl","reorderColumns","fieldNames","prev","renameColumn","fileHeader","layoutFieldName","convertResult","useMemo","useMemo","useImporterStatus","ctx","useImporterContext","useMemo","useCallback","useMemo","useSheetData","sheet","useImporterContext","errors","useMemo","toObjects","useCallback","mapRow","sheetRowsToObjects","toObjectsWithKeyMap","keyMap","sheetToObjectsWithKeyMap","useCallback","useMemo","useRef","useCallback","useEffect","useRef","useState","Comlink","getEditWorkerUrl","useEditWorker","workerProxy","setWorkerProxy","useState","workerRef","useRef","useEffect","worker","getEditWorkerUrl","proxy","useCallback","sheet","sheetLayout","rowIndex","cellKey","value","options","getPaginatedResult","sheet","page","pageSize","getPaginatedResultFromRows","rows","totalCount","totalPages","safePage","start","end","slice","useSheetEditor","options","sheet","setResult","layout","changeLog","addChangeLogEntry","submitDone","useImporterContext","runEdit","isReady","useEditWorker","canEdit","page","pageSize","debounceMs","debounceRef","useRef","pageData","useMemo","getPaginatedResult","totalPages","applyEdit","useCallback","params","previousValue","getRowByIndex","getCellByKey","newSheet","entry","editCell","removeRow","rowIndex","changeLogAsText","formatChangeLogAsText","useCallback","useMemo","useState","escapeCsvValue","value","separator","cellValueToString","formatDates","sheetToCSV","sheet","sheetLayout","options","includeHeaders","csvSeparator","formatDatesForExport","fieldOrder","effectiveOrder","c","lines","h","row","values","key","raw","cellValueToJson","value","formatDates","sheetToJSON","sheet","_sheetLayout","options","formatDatesForExport","rows","row","obj","cell","useSheetView","options","initialPage","defaultPageSize","filterMode","page","setPage","useState","pageSize","sheet","editCell","removeRow","changeLog","changeLogAsText","useSheetEditor","ctx","useImporterContext","rowsWithErrors","useMemo","getRowsWithErrors","sourceRows","totalRows","getPaginatedResult","useCallback","p","ps","getPaginatedResultFromRows","paginatedRows","getRows","limit","start","counts","getViewCounts","exportToCSV","opts","sheetToCSV","exportToJSON","sheetToJSON","downloadCSV","content","blob","url","a","downloadJSON","useCallback","useEffect","useImporterEventTarget","target","useImporterContext","subscribeToProgress","useCallback","callback","handler","e","IMPORTER_PROGRESS_EVENT","useImporterProgressSubscription","useEffect"]}
1
+ {"version":3,"sources":["../src/providers/ImporterProvider.tsx","../src/core/view/types/persisted-state.ts","../src/providers/ImporterContext.ts","../src/providers/state.ts","../src/providers/useImporterActions.ts","../src/types/metrics.ts","../src/types/change-log.ts","../src/types/importer-state.ts","../src/providers/useImporterStateSetters.ts","../src/providers/usePersistSession.ts","../src/core/view/persist/indexed-db.ts","../src/hooks/useImportSheet.ts","../src/core/parser/hooks/useParserWorker.ts","../src/core/parser/worker/worker-url.ts","../src/providers/useImporterContext.ts","../src/hooks/useImporter.ts","../src/core/view/get-rows-with-errors.ts","../src/core/view/get-view-counts.ts","../src/core/view/export/sheet-to-objects.ts","../src/core/convert/hooks/useConvert.ts","../src/core/convert/build-converted-sheet.ts","../src/core/parser/utils/fuzzy-match.ts","../src/core/convert/match-headers.ts","../src/core/convert/run-convert.ts","../src/hooks/useImporterStatus.ts","../src/hooks/useSheetData.ts","../src/hooks/useSheetEditor.ts","../src/core/editor/hooks/useEditWorker.ts","../src/core/editor/worker/worker-url.ts","../src/core/editor/get-paginated-result.ts","../src/core/view/hooks/useSheetView.ts","../src/core/view/export/sheet-to-csv.ts","../src/core/view/export/sheet-to-json.ts","../src/hooks/useImporterEventTarget.ts"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\nimport { Registry } from '../shared/registry/index.js';\nimport type { ParserEngine, SheetLayout } from '../types/index.js';\nimport { DEFAULT_PERSIST_KEY } from '../core/view/types/persisted-state.js';\nimport { ImporterContext } from './ImporterContext.js';\nimport { initialState } from './state.js';\nimport type { ImporterContextValue, ImporterProviderProps } from './types.js';\nimport { useImporterActions } from './useImporterActions.js';\nimport { useImporterStateSetters } from './useImporterStateSetters.js';\nimport { usePersistSession } from './usePersistSession.js';\nimport { useImportSheet } from '../hooks/useImportSheet.js';\n\nfunction ImporterOrchestrator() {\n useImportSheet();\n return null;\n}\n\nexport function ImporterProvider({\n children,\n layout: layoutProp,\n engine: engineProp,\n persist = false,\n persistKey = DEFAULT_PERSIST_KEY,\n onSubmit = null,\n submitKeyMap = null,\n}: ImporterProviderProps) {\n const [state, setState] = useState(initialState);\n const [layout, setLayoutState] = useState<SheetLayout | null>(layoutProp ?? null);\n const [engine, setEngineState] = useState<ParserEngine | null>(engineProp ?? null);\n const progressEventTarget = useMemo(() => new EventTarget(), []);\n const validatorRegistry = useMemo(() => new Registry<(...args: unknown[]) => unknown>(), []);\n const sanitizerRegistry = useMemo(() => new Registry<(...args: unknown[]) => unknown>(), []);\n const transformRegistry = useMemo(() => new Registry<(...args: unknown[]) => unknown>(), []);\n const activeWorkerRef = useRef<Worker | null>(null);\n const phaseTimingsRef = useRef({\n parse: 0,\n sanitize: 0,\n validate: 0,\n transform: 0,\n });\n\n const stateSetters = useImporterStateSetters({ setState, setLayoutState, setEngineState });\n const persistSession = usePersistSession(\n persist,\n persistKey,\n state.rawData,\n state.result,\n stateSetters.setRawData,\n stateSetters.setResult,\n layout?.version ?? null\n );\n\n const actions = useImporterActions({\n setState,\n setLayoutState,\n setEngineState,\n progressEventTarget,\n validatorRegistry,\n sanitizerRegistry,\n transformRegistry,\n activeWorkerRef,\n phaseTimingsRef,\n });\n\n useEffect(() => {\n return () => {\n const worker = activeWorkerRef.current;\n if (worker) {\n worker.terminate();\n activeWorkerRef.current = null;\n }\n };\n }, []);\n\n const value = useMemo<ImporterContextValue>(\n () => ({\n ...state,\n layout,\n engine,\n progressEventTarget,\n ...actions,\n onSubmit: onSubmit ?? null,\n submitKeyMap: submitKeyMap ?? null,\n persist,\n persistKey,\n hasRecoverableSession: persistSession.hasRecoverableSession,\n recoverSession: persistSession.recoverSession,\n clearPersistedState: persistSession.clearPersistedState,\n }),\n [\n state,\n layout,\n engine,\n progressEventTarget,\n onSubmit,\n submitKeyMap,\n actions,\n persist,\n persistKey,\n persistSession.hasRecoverableSession,\n persistSession.recoverSession,\n persistSession.clearPersistedState,\n ]\n );\n\n return (\n <ImporterContext.Provider value={value}>\n <ImporterOrchestrator />\n {children}\n </ImporterContext.Provider>\n );\n}\n","import type { RawSheet } from '../../../types/raw-sheet.js';\nimport type { Sheet } from '../../../types/sheet.js';\n\nexport const PERSIST_SESSION_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;\n\nexport const PERSIST_STORE_NAME = 'react-import-sheet-persist';\n\nexport const DEFAULT_PERSIST_KEY = 'react-import-sheet-session';\n\nexport const STATE_SCHEMA_VERSION = 1;\n\nexport interface PersistedState {\n readonly rawData: RawSheet;\n readonly sheet: Sheet;\n readonly savedAt: number;\n readonly fileName?: string;\n readonly persistKey?: string;\n readonly layoutVersion?: string | number;\n readonly stateSchemaVersion?: number;\n}\n","import { createContext } from 'react';\r\nimport type { ImporterContextValue } from './types.js';\r\n\r\nexport const ImporterContext = createContext<ImporterContextValue | null>(null);\r\n","import type { ImporterState } from '../types/index.js';\n\nexport const initialState: ImporterState = {\n file: null,\n rawData: null,\n documentHash: null,\n status: 'idle',\n result: null,\n convertedSheet: null,\n sanitizedSheet: null,\n convertResultData: null,\n metrics: null,\n changeLog: [],\n submitDone: false,\n};\n","import { useCallback, useMemo } from 'react';\nimport type { RegistryLevel } from '../shared/registry/index.js';\nimport type { ChangeLogEntry } from '../types/change-log.js';\nimport {\n buildPipelineMetrics,\n IMPORTER_ABORTED_EVENT,\n IMPORTER_PROGRESS_EVENT,\n type ImporterProgressDetail,\n type PipelinePhase,\n} from '../types/index.js';\nimport type { ImporterContextValue, UseImporterActionsDeps } from './types.js';\nimport { useImporterStateSetters } from './useImporterStateSetters.js';\n\nconst INITIAL_PHASE_TIMINGS = {\n parse: 0,\n sanitize: 0,\n validate: 0,\n transform: 0,\n};\n\nexport function useImporterActions(\n deps: UseImporterActionsDeps\n): Omit<\n ImporterContextValue,\n | 'file'\n | 'rawData'\n | 'documentHash'\n | 'status'\n | 'result'\n | 'layout'\n | 'engine'\n | 'progressEventTarget'\n | 'onSubmit'\n | 'submitKeyMap'\n | 'persist'\n | 'persistKey'\n | 'hasRecoverableSession'\n | 'recoverSession'\n | 'clearPersistedState'\n> {\n const {\n setState,\n setLayoutState,\n setEngineState,\n progressEventTarget,\n validatorRegistry,\n sanitizerRegistry,\n transformRegistry,\n activeWorkerRef,\n phaseTimingsRef,\n } = deps;\n\n const stateSetters = useImporterStateSetters({ setState, setLayoutState, setEngineState });\n\n const dispatchProgress = useCallback(\n (detail: ImporterProgressDetail) => {\n progressEventTarget.dispatchEvent(new CustomEvent(IMPORTER_PROGRESS_EVENT, { detail }));\n },\n [progressEventTarget]\n );\n\n const setActiveWorker = useCallback(\n (worker: Worker | null) => {\n activeWorkerRef.current = worker;\n },\n [activeWorkerRef]\n );\n\n const abort = useCallback(() => {\n const worker = activeWorkerRef.current;\n if (worker) {\n worker.terminate();\n activeWorkerRef.current = null;\n }\n setState((prev) => ({ ...prev, status: 'cancelled' }));\n progressEventTarget.dispatchEvent(new CustomEvent(IMPORTER_ABORTED_EVENT));\n }, [activeWorkerRef, progressEventTarget, setState]);\n\n const setPhaseTiming = useCallback(\n (phase: PipelinePhase, ms: number) => {\n phaseTimingsRef.current = { ...phaseTimingsRef.current, [phase]: ms };\n },\n [phaseTimingsRef]\n );\n\n const finalizeMetrics = useCallback(\n (rowCount: number) => {\n const timings = { ...phaseTimingsRef.current };\n const metrics = buildPipelineMetrics(timings, rowCount);\n stateSetters.setMetrics(metrics);\n },\n [phaseTimingsRef, stateSetters]\n );\n\n const addChangeLogEntry = useCallback(\n (entry: ChangeLogEntry) => {\n setState((prev) => ({\n ...prev,\n changeLog: [...prev.changeLog, entry],\n }));\n },\n [setState]\n );\n\n const processFile = useCallback(\n (file: File) => {\n phaseTimingsRef.current = { ...INITIAL_PHASE_TIMINGS };\n setState((prev) => ({\n ...prev,\n file,\n status: 'loading',\n rawData: null,\n documentHash: null,\n result: null,\n convertedSheet: null,\n sanitizedSheet: null,\n convertResultData: null,\n metrics: null,\n changeLog: [],\n submitDone: false,\n }));\n },\n [phaseTimingsRef, setState]\n );\n\n const registerValidator = useCallback(\n (name: string, fn: (...args: unknown[]) => unknown, options: { type: RegistryLevel }) => {\n validatorRegistry.register(name, fn, options);\n },\n [validatorRegistry]\n );\n\n const registerSanitizer = useCallback(\n (name: string, fn: (...args: unknown[]) => unknown, options: { type: RegistryLevel }) => {\n sanitizerRegistry.register(name, fn, options);\n },\n [sanitizerRegistry]\n );\n\n const registerTransform = useCallback(\n (name: string, fn: (...args: unknown[]) => unknown, options: { type: RegistryLevel }) => {\n transformRegistry.register(name, fn, options);\n },\n [transformRegistry]\n );\n\n return useMemo(\n () => ({\n ...stateSetters,\n addChangeLogEntry,\n setPhaseTiming,\n finalizeMetrics,\n processFile,\n registerValidator,\n registerSanitizer,\n registerTransform,\n abort,\n dispatchProgress,\n setActiveWorker,\n }),\n [\n stateSetters,\n addChangeLogEntry,\n setPhaseTiming,\n finalizeMetrics,\n processFile,\n registerValidator,\n registerSanitizer,\n registerTransform,\n abort,\n dispatchProgress,\n setActiveWorker,\n ]\n );\n}\n","export interface PipelineMetricsTimings {\n readonly parse: number;\n readonly sanitize: number;\n readonly validate: number;\n readonly transform: number;\n}\n\nexport interface PipelineMetricsPercentages {\n readonly parse: number;\n readonly sanitize: number;\n readonly validate: number;\n readonly transform: number;\n readonly overhead?: number;\n}\n\nexport interface PipelineMetrics {\n readonly timings: PipelineMetricsTimings;\n readonly percentages?: PipelineMetricsPercentages;\n readonly totalMs: number;\n readonly isSlow: boolean;\n readonly parseTime: string;\n readonly sanitizeTime: string;\n readonly validateTime: string;\n readonly transformTime: string;\n readonly totalTime: string;\n readonly efficiency: string;\n readonly rowCount: number;\n readonly overheadMs?: number;\n}\n\nexport const SLOW_THRESHOLD_MS = 2000;\n\nfunction formatMs(ms: number): string {\n if (ms < 0.01 && ms >= 0) return '0.00ms';\n if (ms < 1) return `${(ms * 1000).toFixed(2)}μs`;\n return `${ms.toFixed(2)}ms`;\n}\n\nexport function buildPipelineMetrics(\n timings: PipelineMetricsTimings,\n rowCount: number,\n overheadMs?: number,\n): PipelineMetrics {\n const totalMs =\n timings.parse + timings.sanitize + timings.validate + timings.transform;\n const isSlow = totalMs > SLOW_THRESHOLD_MS;\n const efficiencyMsPerRow = rowCount > 0 ? totalMs / rowCount : 0;\n const efficiency = `${efficiencyMsPerRow.toFixed(4)}ms/row`;\n\n let percentages: PipelineMetricsPercentages | undefined;\n if (totalMs > 0) {\n const overhead = overheadMs ?? 0;\n const totalWithOverhead = totalMs + overhead;\n percentages = {\n parse: (timings.parse / totalWithOverhead) * 100,\n sanitize: (timings.sanitize / totalWithOverhead) * 100,\n validate: (timings.validate / totalWithOverhead) * 100,\n transform: (timings.transform / totalWithOverhead) * 100,\n overhead: totalWithOverhead > 0 ? (overhead / totalWithOverhead) * 100 : 0,\n };\n }\n\n return {\n timings: { ...timings },\n percentages,\n totalMs,\n isSlow,\n parseTime: formatMs(timings.parse),\n sanitizeTime: formatMs(timings.sanitize),\n validateTime: formatMs(timings.validate),\n transformTime: formatMs(timings.transform),\n totalTime: formatMs(totalMs),\n efficiency,\n rowCount,\n ...(overheadMs !== undefined && overheadMs >= 0 ? { overheadMs } : {}),\n };\n}\n","export interface ChangeLogEntryCellEdit {\n readonly type: 'cell_edit';\n readonly rowIndex: number;\n readonly cellKey: string;\n readonly value: unknown;\n readonly previousValue?: unknown;\n readonly timestamp: number;\n}\n\nexport interface ChangeLogEntryRowRemove {\n readonly type: 'row_remove';\n readonly rowIndex: number;\n readonly timestamp: number;\n}\n\nexport type ChangeLogEntry = ChangeLogEntryCellEdit | ChangeLogEntryRowRemove;\n\nexport function formatChangeLogAsText(entries: readonly ChangeLogEntry[]): string {\n const lines: string[] = [];\n for (const e of entries) {\n if (e.type === 'cell_edit') {\n const prev = e.previousValue !== undefined ? ` (previous: ${String(e.previousValue)})` : '';\n lines.push(\n `Row ${e.rowIndex + 1}, cell \"${e.cellKey}\": set to ${JSON.stringify(e.value)}${prev}`\n );\n } else {\n lines.push(`Row ${e.rowIndex + 1}: removed`);\n }\n }\n return lines.join('\\n');\n}\n","import type { ConvertedSheet } from '../core/convert/types/converted-sheet.js';\nimport type { SanitizedSheet } from '../core/sanitizer/types/sanitized-sheet.js';\nimport type { ChangeLogEntry } from './change-log.js';\nimport type { PipelineMetrics } from './metrics.js';\nimport type { RawSheet } from './raw-sheet.js';\nimport type { Sheet } from './sheet.js';\n\nexport type ImporterStatus =\n | 'idle'\n | 'loading'\n | 'parsing'\n | 'validating'\n | 'transforming'\n | 'success'\n | 'error'\n | 'cancelled';\n\nexport interface ConvertResultData {\n readonly headersFound: readonly string[];\n readonly mismatches: readonly { expected: string; found: string | null; message?: string }[];\n readonly columnOrder: readonly string[];\n readonly headerToFieldMap: Readonly<Record<string, string>>;\n}\n\nexport type PipelinePhase = 'parse' | 'sanitize' | 'validate' | 'transform';\n\nexport interface ImporterState {\n readonly file: File | null;\n readonly rawData: RawSheet | null;\n readonly documentHash: string | null;\n readonly status: ImporterStatus;\n readonly result: Sheet | null;\n readonly convertedSheet: ConvertedSheet | null;\n readonly sanitizedSheet: SanitizedSheet | null;\n readonly convertResultData: ConvertResultData | null;\n readonly metrics: PipelineMetrics | null;\n readonly changeLog: readonly ChangeLogEntry[];\n readonly submitDone: boolean;\n}\n\nexport const IMPORTER_PROGRESS_EVENT = 'importer-progress';\nexport const IMPORTER_ABORTED_EVENT = 'importer-aborted';\n\nexport interface ImporterProgressDetail {\n readonly phase?: string;\n readonly globalPercent?: number;\n readonly localPercent?: number;\n readonly currentRow?: number;\n readonly totalRows?: number;\n readonly rowsProcessed?: number;\n}\n","import { useCallback } from 'react';\nimport type { ImporterState, ImporterStatus } from '../types/index.js';\nimport type { PipelineMetrics } from '../types/index.js';\nimport type { ParserEngine, SheetLayout } from '../types/index.js';\nimport type { ImporterContextValue, UseImporterStateSettersDeps } from './types.js';\n\nexport function useImporterStateSetters(\n deps: UseImporterStateSettersDeps\n): Pick<\n ImporterContextValue,\n | 'setLayout'\n | 'setEngine'\n | 'setFile'\n | 'setRawData'\n | 'setDocumentHash'\n | 'setStatus'\n | 'setResult'\n | 'setConvertedSheet'\n | 'setSanitizedSheet'\n | 'setConvertResultData'\n | 'setMetrics'\n | 'setSubmitDone'\n> {\n const { setState, setLayoutState, setEngineState } = deps;\n\n const setFile = useCallback(\n (file: File | null) => {\n setState((prev) => ({ ...prev, file }));\n },\n [setState]\n );\n\n const setRawData = useCallback(\n (rawData: ImporterState['rawData']) => {\n setState((prev) => ({ ...prev, rawData }));\n },\n [setState]\n );\n\n const setDocumentHash = useCallback(\n (documentHash: string | null) => {\n setState((prev) => ({ ...prev, documentHash }));\n },\n [setState]\n );\n\n const setStatus = useCallback(\n (status: ImporterStatus) => {\n setState((prev) => ({ ...prev, status }));\n },\n [setState]\n );\n\n const setResult = useCallback(\n (result: ImporterState['result']) => {\n setState((prev) => ({ ...prev, result }));\n },\n [setState]\n );\n\n const setConvertedSheet = useCallback(\n (convertedSheet: ImporterState['convertedSheet']) => {\n setState((prev) => ({ ...prev, convertedSheet, convertResultData: null }));\n },\n [setState]\n );\n\n const setSanitizedSheet = useCallback(\n (sanitizedSheet: ImporterState['sanitizedSheet']) => {\n setState((prev) => ({ ...prev, sanitizedSheet }));\n },\n [setState]\n );\n\n const setConvertResultData = useCallback(\n (\n dataOrUpdater:\n | ImporterState['convertResultData']\n | ((prev: ImporterState['convertResultData']) => ImporterState['convertResultData'])\n ) => {\n setState((prev) => ({\n ...prev,\n convertResultData:\n typeof dataOrUpdater === 'function'\n ? dataOrUpdater(prev.convertResultData)\n : dataOrUpdater,\n convertedSheet: typeof dataOrUpdater === 'function' ? prev.convertedSheet : null,\n }));\n },\n [setState]\n );\n\n const setMetrics = useCallback(\n (metrics: PipelineMetrics | null) => {\n setState((prev) => ({ ...prev, metrics }));\n },\n [setState]\n );\n\n const setSubmitDone = useCallback(\n (submitDone: boolean) => {\n setState((prev) => ({ ...prev, submitDone }));\n },\n [setState]\n );\n\n const setLayout = useCallback(\n (next: SheetLayout | null) => {\n setLayoutState(next);\n },\n [setLayoutState]\n );\n\n const setEngine = useCallback(\n (next: ParserEngine | null) => {\n setEngineState(next);\n },\n [setEngineState]\n );\n\n return {\n setLayout,\n setEngine,\n setFile,\n setRawData,\n setDocumentHash,\n setStatus,\n setResult,\n setConvertedSheet,\n setSanitizedSheet,\n setConvertResultData,\n setMetrics,\n setSubmitDone,\n };\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport type { RawSheet } from '../types/raw-sheet.js';\nimport type { Sheet } from '../types/sheet.js';\nimport {\n savePersistedState,\n loadPersistedState,\n clearPersistedState as clearPersistedStateStorage,\n} from '../core/view/persist/indexed-db.js';\nimport {\n STATE_SCHEMA_VERSION,\n type PersistedState as PersistedStateType,\n} from '../core/view/types/persisted-state.js';\n\nconst DEBOUNCE_MS = 2500;\n\nexport function usePersistSession(\n persist: boolean,\n persistKey: string,\n rawData: RawSheet | null,\n result: Sheet | null,\n setRawData: (v: RawSheet | null) => void,\n setResult: (v: Sheet | null) => void,\n layoutVersion: string | number | null,\n) {\n const [recoverableSession, setRecoverableSession] = useState<PersistedStateType | null>(null);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (!persist) return;\n loadPersistedState(persistKey).then((state) => {\n if (!state) return;\n if (\n state.layoutVersion != null &&\n layoutVersion != null &&\n String(state.layoutVersion) !== String(layoutVersion)\n ) {\n return;\n }\n setRecoverableSession(state);\n });\n }, [persist, persistKey, layoutVersion]);\n\n useEffect(() => {\n if (!persist || !rawData || !result) return;\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(() => {\n debounceRef.current = null;\n const payload: PersistedStateType = {\n rawData,\n sheet: result,\n savedAt: Date.now(),\n layoutVersion: layoutVersion ?? undefined,\n stateSchemaVersion: STATE_SCHEMA_VERSION,\n };\n savePersistedState(persistKey, payload).catch(() => {});\n }, DEBOUNCE_MS);\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n };\n }, [persist, persistKey, rawData, result, layoutVersion]);\n\n const recoverSession = useCallback(async () => {\n if (!persist) return;\n const state = recoverableSession;\n if (!state) return;\n setRawData(state.rawData);\n setResult(state.sheet);\n setRecoverableSession(null);\n }, [persist, recoverableSession, setRawData, setResult]);\n\n const clearPersistedState = useCallback(async () => {\n if (!persist) return;\n await clearPersistedStateStorage(persistKey);\n setRecoverableSession(null);\n }, [persist, persistKey]);\n\n return {\n hasRecoverableSession: persist && recoverableSession != null,\n recoverSession,\n clearPersistedState,\n };\n}\n","import type { PersistedState } from '../types/persisted-state.js';\nimport {\n PERSIST_STORE_NAME,\n PERSIST_SESSION_MAX_AGE_MS,\n} from '../types/persisted-state.js';\n\nfunction openDb(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.open('react-import-sheet-db', 1);\n req.onerror = () => reject(req.error);\n req.onsuccess = () => resolve(req.result);\n req.onupgradeneeded = () => {\n req.result.createObjectStore(PERSIST_STORE_NAME, { keyPath: 'key' });\n };\n });\n}\n\nexport async function savePersistedState(\n key: string,\n state: PersistedState,\n): Promise<void> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(PERSIST_STORE_NAME, 'readwrite');\n const store = tx.objectStore(PERSIST_STORE_NAME);\n const record = { key, ...state };\n const req = store.put(record);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error);\n tx.oncomplete = () => db.close();\n });\n}\n\nexport async function loadPersistedState(\n key: string,\n): Promise<PersistedState | null> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(PERSIST_STORE_NAME, 'readonly');\n const store = tx.objectStore(PERSIST_STORE_NAME);\n const req = store.get(key);\n req.onsuccess = () => {\n db.close();\n const row = req.result as (PersistedState & { key: string }) | undefined;\n if (row == null) {\n resolve(null);\n return;\n }\n const savedAt = row.savedAt;\n if (Date.now() - savedAt > PERSIST_SESSION_MAX_AGE_MS) {\n resolve(null);\n return;\n }\n const { key: _k, ...state } = row;\n resolve(state as PersistedState);\n };\n req.onerror = () => reject(req.error);\n });\n}\n\nexport async function clearPersistedState(key: string): Promise<void> {\n const db = await openDb();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(PERSIST_STORE_NAME, 'readwrite');\n const store = tx.objectStore(PERSIST_STORE_NAME);\n const req = store.delete(key);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error);\n tx.oncomplete = () => db.close();\n });\n}\n","import { useCallback, useEffect } from 'react';\nimport { useImporterContext } from '../providers/index.js';\nimport { useParserWorker } from '../core/parser/hooks/useParserWorker.js';\n\nfunction firstSheetFromResult(\n result: { sheets: Readonly<Record<string, { documentHash: string }>> },\n): { documentHash: string } | null {\n const names = Object.keys(result.sheets);\n if (names.length === 0) return null;\n return result.sheets[names[0] ?? ''] ?? null;\n}\n\nexport function useImportSheet() {\n const ctx = useImporterContext();\n const { load, parseAll, isReady } = useParserWorker();\n\n useEffect(() => {\n const { file, status, engine } = ctx;\n if (!isReady || !file || status !== 'loading') return;\n load(file, { maxRows: 10, fileName: file.name, engine: engine ?? undefined })\n .then((result) => {\n const first = firstSheetFromResult(result);\n if (!first) {\n ctx.setStatus('error');\n return;\n }\n const sheet = result.sheets[Object.keys(result.sheets)[0] ?? ''];\n if (!sheet) {\n ctx.setStatus('error');\n return;\n }\n ctx.setRawData(sheet);\n ctx.setDocumentHash(sheet.documentHash);\n ctx.setStatus('success');\n })\n .catch(() => {\n ctx.setStatus('error');\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps -- run only when file/status/isReady/load change; ctx setters are stable\n }, [isReady, ctx.file, ctx.status, ctx.setRawData, ctx.setDocumentHash, ctx.setStatus, load]);\n\n const startFullImport = useCallback(() => {\n const { file } = ctx;\n if (!file) return Promise.reject(new Error('No file loaded'));\n ctx.setStatus('loading');\n const t0 = performance.now();\n return parseAll((detail) => ctx.dispatchProgress(detail)).then((result) => {\n const t1 = performance.now();\n ctx.setPhaseTiming('parse', t1 - t0);\n const first = firstSheetFromResult(result);\n if (!first) {\n ctx.setStatus('error');\n return result;\n }\n const sheet = result.sheets[Object.keys(result.sheets)[0] ?? ''];\n if (!sheet) {\n ctx.setStatus('error');\n return result;\n }\n ctx.setRawData(sheet);\n ctx.setDocumentHash(sheet.documentHash);\n ctx.setStatus('success');\n return result;\n });\n }, [ctx, parseAll]);\n\n return { startFullImport };\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport * as Comlink from 'comlink';\nimport type { RawParseResult } from '../../../types/raw-sheet.js';\nimport type { ParseOptions } from '../types/index.js';\nimport type { ImporterProgressDetail } from '../../../types/importer-state.js';\nimport { useImporterContext } from '../../../providers/index.js';\nimport { getParserWorkerUrl } from '../worker/worker-url.js';\n\ntype ParserWorkerApi = {\n load: (blob: Blob, options?: ParseOptions) => Promise<RawParseResult>;\n parseAll: (onProgress?: (d: ImporterProgressDetail) => void) => Promise<RawParseResult>;\n};\n\nexport function useParserWorker() {\n const { setActiveWorker, dispatchProgress } = useImporterContext();\n const [workerProxy, setWorkerProxy] = useState<Comlink.Remote<ParserWorkerApi> | null>(null);\n const workerRef = useRef<Worker | null>(null);\n\n useEffect(() => {\n const worker = new Worker(getParserWorkerUrl(), { type: 'module' });\n workerRef.current = worker;\n setActiveWorker(worker);\n const proxy = Comlink.wrap<ParserWorkerApi>(worker);\n queueMicrotask(() => setWorkerProxy(proxy));\n return () => {\n worker.terminate();\n workerRef.current = null;\n setActiveWorker(null);\n };\n }, [setActiveWorker]);\n\n const load = useCallback(\n async (blob: Blob, options: ParseOptions = {}): Promise<RawParseResult> => {\n if (!workerProxy) throw new Error('Parser worker not ready');\n return workerProxy.load(blob, options);\n },\n [workerProxy],\n );\n\n const parseAll = useCallback(\n async (onProgress?: (d: ImporterProgressDetail) => void): Promise<RawParseResult> => {\n if (!workerProxy) throw new Error('Parser worker not ready');\n const progressProxy = onProgress ? Comlink.proxy(onProgress) : undefined;\n return workerProxy.parseAll(progressProxy);\n },\n [workerProxy],\n );\n\n return { load, parseAll, dispatchProgress, isReady: !!workerProxy };\n}\n","export function getParserWorkerUrl(): string {\n return new URL('./parser.worker.js', import.meta.url).href;\n}\n","import { useContext } from 'react';\r\nimport { ImporterContext } from './ImporterContext.js';\r\nimport type { ImporterContextValue } from './types.js';\r\n\r\nexport function useImporterContext(): ImporterContextValue {\r\n const context = useContext(ImporterContext);\r\n if (context === null) {\r\n throw new Error('useImporter must be used within an ImporterProvider');\r\n }\r\n return context;\r\n}\r\n","import { useCallback, useEffect, useMemo } from 'react';\nimport { useImporterContext } from '../providers/index.js';\nimport { hasValidationErrors } from '../core/view/get-view-counts.js';\nimport { sheetToObjectsWithKeyMap } from '../core/view/export/sheet-to-objects.js';\nimport type { Sheet } from '../types/sheet.js';\nimport type { UseImporterOptions } from './types.js';\n\nfunction rowsToLayoutObjects(sheet: Sheet): Record<string, unknown>[] {\n return sheet.rows.map((row) =>\n row.cells.reduce((acc, c) => ({ ...acc, [c.key]: c.value }), {} as Record<string, unknown>)\n );\n}\n\nexport function useImporter(options: UseImporterOptions = {}) {\n const ctx = useImporterContext();\n const { layout: layoutOption, engine: engineOption } = options;\n\n useEffect(() => {\n if (layoutOption !== undefined) {\n ctx.setLayout(layoutOption);\n }\n }, [ctx, layoutOption]);\n\n useEffect(() => {\n if (engineOption !== undefined) {\n ctx.setEngine(engineOption);\n }\n }, [ctx, engineOption]);\n\n const canSubmit = useMemo(\n () =>\n Boolean(\n ctx.result &&\n ctx.status === 'success' &&\n !ctx.submitDone &&\n !hasValidationErrors(ctx.result)\n ),\n [ctx.result, ctx.status, ctx.submitDone]\n );\n\n const submit = useCallback(() => {\n if (!ctx.result || ctx.submitDone || hasValidationErrors(ctx.result) || !ctx.onSubmit) return;\n const data = ctx.submitKeyMap\n ? sheetToObjectsWithKeyMap(ctx.result, ctx.submitKeyMap)\n : rowsToLayoutObjects(ctx.result);\n ctx.onSubmit(data);\n ctx.setSubmitDone(true);\n }, [ctx]);\n\n return useMemo(\n () => ({\n processFile: ctx.processFile,\n registerValidator: ctx.registerValidator,\n registerSanitizer: ctx.registerSanitizer,\n registerTransform: ctx.registerTransform,\n abort: ctx.abort,\n metrics: ctx.metrics,\n submit,\n canSubmit,\n submitDone: ctx.submitDone,\n }),\n [\n ctx.processFile,\n ctx.registerValidator,\n ctx.registerSanitizer,\n ctx.registerTransform,\n ctx.abort,\n ctx.metrics,\n submit,\n canSubmit,\n ctx.submitDone,\n ]\n );\n}\n","import type { Sheet, ValidatedRow } from '../../types/sheet.js';\n\nexport function getRowsWithErrors(sheet: Sheet): ValidatedRow[] {\n return sheet.rows.filter((row) => row.errors.length > 0);\n}\n","import type { Sheet } from '../../types/sheet.js';\nimport type { ViewCounts } from './types/index.js';\nimport { getRowsWithErrors } from './get-rows-with-errors.js';\n\nexport function hasValidationErrors(sheet: Sheet | null): boolean {\n if (!sheet) return false;\n return getViewCounts(sheet).totalErrors > 0;\n}\n\nexport function getViewCounts(sheet: Sheet): ViewCounts {\n const totalRows = sheet.rows.length;\n const rowsWithErrors = getRowsWithErrors(sheet);\n const totalErrors =\n sheet.errors.length +\n sheet.rows.reduce(\n (sum, row) =>\n sum + row.errors.length + row.cells.reduce((c, cell) => c + cell.errors.length, 0),\n 0\n );\n return {\n totalRows,\n rowsWithErrors: rowsWithErrors.length,\n totalErrors,\n };\n}\n","import type { Sheet, ValidatedRow } from '../../../types/sheet.js';\n\nexport function getCellValue(row: ValidatedRow, key: string): unknown {\n const cell = row.cells.find((c) => c.key === key);\n return cell?.value;\n}\n\nexport function sheetRowsToObjects<T>(\n rows: readonly ValidatedRow[],\n mapRow: (row: ValidatedRow) => T\n): T[] {\n return rows.map(mapRow);\n}\n\nexport function sheetToObjectsWithKeyMap(\n sheet: Sheet | null,\n keyMap: Readonly<Record<string, string>>\n): Record<string, unknown>[] {\n if (!sheet) return [];\n return sheet.rows.map((row) => {\n const obj: Record<string, unknown> = {};\n for (const [sheetKey, outputKey] of Object.entries(keyMap)) {\n obj[outputKey] = getCellValue(row, sheetKey);\n }\n return obj;\n });\n}\n","import { useCallback, useMemo } from 'react';\nimport { useImporterContext } from '../../../providers/index.js';\nimport { runConvert } from '../run-convert.js';\nimport type { ConvertOptions } from '../types/convert-options.js';\nimport type { ConvertResult, ConvertResultApplyResult } from '../types/convert-result.js';\n\nexport function useConvert() {\n const ctx = useImporterContext();\n const { rawData, layout, convertedSheet, convertResultData, setConvertedSheet, setConvertResultData } = ctx;\n\n const convert = useCallback(\n (options?: ConvertOptions) => {\n if (!rawData || !layout) return;\n const result = runConvert(rawData, layout, options, convertResultData ?? undefined);\n if (result.kind === 'success') {\n setConvertedSheet(result.sheet);\n } else {\n setConvertResultData({\n headersFound: result.headersFound,\n mismatches: result.mismatches,\n columnOrder: result.columnOrder,\n headerToFieldMap: result.headerToFieldMap,\n });\n }\n },\n [rawData, layout, convertResultData, setConvertedSheet, setConvertResultData],\n );\n\n const applyMappingImpl = useCallback((): ConvertResultApplyResult | undefined => {\n if (!rawData || !layout || !convertResultData) return undefined;\n const result = runConvert(rawData, layout, {}, {\n columnOrder: convertResultData.columnOrder,\n headerToFieldMap: convertResultData.headerToFieldMap,\n });\n if (result.kind === 'success') {\n setConvertedSheet(result.sheet);\n return { kind: 'success', sheet: result.sheet };\n }\n setConvertResultData({\n headersFound: result.headersFound,\n mismatches: result.mismatches,\n columnOrder: result.columnOrder,\n headerToFieldMap: result.headerToFieldMap,\n });\n return { kind: 'mismatch', result };\n }, [rawData, layout, convertResultData, setConvertedSheet, setConvertResultData]);\n\n const reorderColumns = useCallback(\n (fieldNames: string[]) => {\n setConvertResultData((prev) =>\n prev ? { ...prev, columnOrder: fieldNames } : prev,\n );\n },\n [setConvertResultData],\n );\n\n const renameColumn = useCallback(\n (fileHeader: string, layoutFieldName: string) => {\n setConvertResultData((prev) =>\n prev\n ? {\n ...prev,\n headerToFieldMap: { ...prev.headerToFieldMap, [fileHeader]: layoutFieldName },\n }\n : prev,\n );\n },\n [setConvertResultData],\n );\n\n const convertResult: ConvertResult | null = useMemo(() => {\n if (!convertResultData) return null;\n return {\n kind: 'mismatch',\n headersFound: convertResultData.headersFound,\n mismatches: convertResultData.mismatches,\n columnOrder: [...convertResultData.columnOrder],\n headerToFieldMap: { ...convertResultData.headerToFieldMap },\n reorderColumns,\n renameColumn,\n applyMapping: () =>\n applyMappingImpl() ?? {\n kind: 'mismatch' as const,\n result: { ...convertResultData, kind: 'mismatch' as const },\n },\n };\n }, [convertResultData, reorderColumns, renameColumn, applyMappingImpl]);\n\n return useMemo(\n () => ({\n convert,\n convertedSheet,\n convertResult,\n }),\n [convert, convertedSheet, convertResult],\n );\n}\n","import type { RawSheet } from '../../types/raw-sheet.js';\nimport type { SheetLayout } from '../../types/sheet-layout.js';\nimport type { ConvertedSheet, ConvertedSheetCell, ConvertedSheetRow } from './types/converted-sheet.js';\n\nexport function buildConvertedSheet(\n rawSheet: RawSheet,\n _sheetLayout: SheetLayout,\n columnOrder: readonly string[],\n fieldToHeader: Readonly<Record<string, string | null>>,\n): ConvertedSheet {\n const headers = [...columnOrder];\n const headerIndex = new Map<string, number>();\n rawSheet.headers.forEach((h, i) => headerIndex.set(h, i));\n\n const rows: ConvertedSheetRow[] = rawSheet.rows.map((row) => {\n const cells: ConvertedSheetCell[] = columnOrder.map((fieldName) => {\n const fileHeader = fieldToHeader[fieldName];\n const value =\n fileHeader != null\n ? (() => {\n const idx = headerIndex.get(fileHeader);\n if (idx == null) return null;\n const cell = row.cells[idx];\n return cell?.value ?? null;\n })()\n : null;\n return { key: fieldName, value: value ?? null };\n });\n return { index: row.index, cells };\n });\n\n return {\n name: rawSheet.name,\n filesize: rawSheet.filesize,\n documentHash: rawSheet.documentHash,\n rowsCount: rawSheet.rowsCount,\n headersCount: rawSheet.headersCount,\n headers,\n rows,\n };\n}\n","export function normalize(s: string): string {\n const t = s.trim().toLowerCase();\n return t.normalize('NFD').replace(/\\p{Diacritic}/gu, '');\n}\n\nfunction levenshteinDistance(a: string, b: string): number {\n if (a.length === 0) return b.length;\n if (b.length === 0) return a.length;\n let prev = Array.from({ length: b.length + 1 }, (_, i) => i);\n for (let i = 1; i <= a.length; i++) {\n const curr: number[] = [i];\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n curr[j] = Math.min(\n curr[j - 1]! + 1,\n prev[j]! + 1,\n prev[j - 1]! + cost,\n );\n }\n prev = curr;\n }\n return prev[b.length]!;\n}\n\nexport function getSimilarity(s1: string, s2: string): number {\n const a = normalize(s1);\n const b = normalize(s2);\n const longer = a.length >= b.length ? a : b;\n const shorter = a.length < b.length ? a : b;\n if (longer.length === 0) return 1;\n const distance = levenshteinDistance(longer, shorter);\n return (longer.length - distance) / longer.length;\n}\n\nconst DEFAULT_FUZZY_THRESHOLD = 0.8;\n\nexport interface MapHeadersOptions {\n threshold?: number;\n}\n\nexport interface MapHeadersItem {\n key: string;\n matchedHeader: string | null;\n}\n\nexport function mapHeaders(\n rawHeaders: string[],\n expectedKeys: string[],\n options: MapHeadersOptions = {},\n): MapHeadersItem[] {\n const threshold = options.threshold ?? DEFAULT_FUZZY_THRESHOLD;\n const keyScores: { key: string; header: string; score: number }[] = [];\n for (const key of expectedKeys) {\n for (const header of rawHeaders) {\n const score = getSimilarity(key, header);\n if (score >= threshold) {\n keyScores.push({ key, header, score });\n }\n }\n }\n keyScores.sort((x, y) => y.score - x.score);\n\n const assignedKeys = new Set<string>();\n const assignedHeaders = new Set<string>();\n const keyToHeader: Record<string, string | null> = {};\n for (const k of expectedKeys) {\n keyToHeader[k] = null;\n }\n for (const { key, header, score: _ } of keyScores) {\n if (assignedKeys.has(key) || assignedHeaders.has(header)) continue;\n keyToHeader[key] = header;\n assignedKeys.add(key);\n assignedHeaders.add(header);\n }\n\n return expectedKeys.map((key) => ({\n key,\n matchedHeader: keyToHeader[key] ?? null,\n }));\n}\n","import type { RawSheet } from '../../types/raw-sheet.js';\nimport type { SheetLayout } from '../../types/sheet-layout.js';\nimport { mapHeaders } from '../parser/utils/fuzzy-match.js';\nimport type { ColumnMismatch } from './types/column-mismatch.js';\nimport type { ConvertOptions } from './types/convert-options.js';\n\nexport interface MatchHeadersResult {\n readonly fieldToHeader: Readonly<Record<string, string | null>>;\n readonly mismatches: readonly ColumnMismatch[];\n}\n\nfunction defaultNormalize(header: string, caseSensitive: boolean): string {\n const trimmed = header.trim();\n return caseSensitive ? trimmed : trimmed.toLowerCase();\n}\n\nexport function matchHeadersToLayout(\n rawSheet: RawSheet,\n sheetLayout: SheetLayout,\n headerToFieldMap: Readonly<Record<string, string>> = {},\n options: ConvertOptions = {}\n): MatchHeadersResult {\n const caseSensitive = options.caseSensitive ?? false;\n const normalizer = options.normalizer ?? ((h: string) => defaultNormalize(h, caseSensitive));\n const layoutFieldNames = Object.keys(sheetLayout.fields) as string[];\n const fileHeaders = rawSheet.headers as string[];\n const normalizedToFileHeader = new Map<string, string>();\n for (const h of fileHeaders) {\n normalizedToFileHeader.set(normalizer(h), h);\n }\n\n const fieldToHeader: Record<string, string | null> = {};\n const usedFileHeaders = new Set<string>();\n\n for (const [fileHeader, fieldName] of Object.entries(headerToFieldMap)) {\n if (layoutFieldNames.includes(fieldName)) {\n fieldToHeader[fieldName] = fileHeaders.includes(fileHeader) ? fileHeader : null;\n if (fieldToHeader[fieldName]) usedFileHeaders.add(fileHeader);\n }\n }\n\n for (const fieldName of layoutFieldNames) {\n if (fieldToHeader[fieldName] != null) continue;\n const key = normalizer(fieldName);\n const fileHeader = normalizedToFileHeader.get(key);\n if (fileHeader != null && !usedFileHeaders.has(fileHeader)) {\n fieldToHeader[fieldName] = fileHeader;\n usedFileHeaders.add(fileHeader);\n } else {\n fieldToHeader[fieldName] = null;\n }\n }\n\n if (options.fuzzyHeaders === true) {\n const unmatchedFields = layoutFieldNames.filter((f) => fieldToHeader[f] == null);\n const availableHeaders = fileHeaders.filter((h) => !usedFileHeaders.has(h));\n const threshold = options.fuzzyThreshold ?? 0.8;\n const fuzzyResults = mapHeaders(availableHeaders, unmatchedFields, { threshold });\n for (const { key, matchedHeader } of fuzzyResults) {\n if (matchedHeader != null && !usedFileHeaders.has(matchedHeader)) {\n fieldToHeader[key] = matchedHeader;\n usedFileHeaders.add(matchedHeader);\n }\n }\n }\n\n const mismatches: ColumnMismatch[] = [];\n for (const fieldName of layoutFieldNames) {\n const found = fieldToHeader[fieldName];\n if (found == null) {\n const field = sheetLayout.fields[fieldName];\n const required = field?.required !== false;\n mismatches.push({\n expected: fieldName,\n found: null,\n message: `Column '${fieldName}' not found in file`,\n required,\n });\n }\n }\n\n return { fieldToHeader, mismatches };\n}\n","import type { RawSheet } from '../../types/raw-sheet.js';\nimport type { SheetLayout } from '../../types/sheet-layout.js';\nimport { buildConvertedSheet } from './build-converted-sheet.js';\nimport { matchHeadersToLayout } from './match-headers.js';\nimport type { ConvertMismatchData } from './types/convert-mismatch-data.js';\nimport type { ConvertOptions } from './types/convert-options.js';\nimport type { ConvertSuccess } from './types/convert-success.js';\n\nexport type RunConvertExisting = {\n readonly columnOrder: readonly string[];\n readonly headerToFieldMap: Readonly<Record<string, string>>;\n};\n\nexport type RunConvertResult = ConvertSuccess | ConvertMismatchData;\n\nexport function runConvert(\n rawSheet: RawSheet,\n sheetLayout: SheetLayout,\n options: ConvertOptions = {},\n existing?: RunConvertExisting\n): RunConvertResult {\n const layoutFieldNames = Object.keys(sheetLayout.fields) as string[];\n const columnOrder = existing?.columnOrder?.length\n ? (existing.columnOrder as string[])\n : layoutFieldNames;\n const headerToFieldMap = existing?.headerToFieldMap ?? {};\n\n const { fieldToHeader, mismatches } = matchHeadersToLayout(\n rawSheet,\n sheetLayout,\n headerToFieldMap,\n options\n );\n\n const requiredFieldNames = layoutFieldNames.filter(\n (f) => sheetLayout.fields[f]?.required !== false\n );\n const allRequiredMatched = requiredFieldNames.every((f) => fieldToHeader[f] != null);\n const allMatched = mismatches.length === 0;\n\n if (allMatched || allRequiredMatched) {\n const sheet = buildConvertedSheet(rawSheet, sheetLayout, columnOrder, fieldToHeader);\n return { kind: 'success', sheet };\n }\n\n const layoutError = mismatches.some((m) => m.required === true);\n return {\n kind: 'mismatch',\n headersFound: [...rawSheet.headers],\n mismatches,\n columnOrder: [...columnOrder],\n headerToFieldMap: { ...headerToFieldMap },\n layoutError,\n };\n}\n","import { useMemo } from 'react';\r\nimport { useImporterContext } from '../providers/index.js';\r\n\r\nexport function useImporterStatus() {\r\n const ctx = useImporterContext();\r\n return useMemo(\r\n () => ({\r\n status: ctx.status,\r\n progressEventTarget: ctx.progressEventTarget,\r\n }),\r\n [ctx.status, ctx.progressEventTarget],\r\n );\r\n}\r\n","import { useCallback, useMemo } from 'react';\r\nimport type { ValidatedRow } from '../types/sheet.js';\r\nimport { useImporterContext } from '../providers/index.js';\r\nimport {\r\n sheetRowsToObjects,\r\n sheetToObjectsWithKeyMap,\r\n} from '../core/view/export/sheet-to-objects.js';\r\n\r\nexport function useSheetData() {\r\n const ctx = useImporterContext();\r\n const sheet = ctx.result;\r\n const errors = useMemo(() => {\r\n if (!sheet) return [];\r\n return [...sheet.errors];\r\n }, [sheet]);\r\n const toObjects = useCallback(\r\n <T>(mapRow: (row: ValidatedRow) => T): T[] => {\r\n if (!sheet) return [];\r\n return sheetRowsToObjects(sheet.rows, mapRow);\r\n },\r\n [sheet]\r\n );\r\n const toObjectsWithKeyMap = useCallback(\r\n (keyMap: Readonly<Record<string, string>>): Record<string, unknown>[] => {\r\n return sheetToObjectsWithKeyMap(sheet, keyMap);\r\n },\r\n [sheet]\r\n );\r\n return useMemo(\r\n () => ({ sheet, errors, toObjects, toObjectsWithKeyMap }),\r\n [sheet, errors, toObjects, toObjectsWithKeyMap]\r\n );\r\n}\r\n","import { useCallback, useMemo, useRef } from 'react';\nimport { type ChangeLogEntry, formatChangeLogAsText } from '../types/change-log.js';\nimport type { EditCellParams } from '../types/edit.js';\nimport type { PaginatedResult } from '../types/paginated-result.js';\nimport type { ValidatedRow } from '../types/sheet.js';\nimport { useImporterContext } from '../providers/index.js';\nimport { removeRow as removeRowSheet } from '../core/editor/immutable-update.js';\nimport { useEditWorker } from '../core/editor/hooks/useEditWorker.js';\nimport { getPaginatedResult } from '../core/editor/get-paginated-result.js';\nimport { getCellByKey, getRowByIndex } from '../core/editor/resolve.js';\n\nexport interface UseSheetEditorOptions {\n page?: number;\n pageSize?: number;\n debounceMs?: number;\n}\n\nexport function useSheetEditor(options: UseSheetEditorOptions = {}) {\n const {\n result: sheet,\n setResult,\n layout,\n changeLog,\n addChangeLogEntry,\n submitDone,\n } = useImporterContext();\n const { runEdit, isReady } = useEditWorker();\n const canEdit = !submitDone;\n const { page = 1, pageSize = 25, debounceMs } = options;\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const pageData = useMemo((): PaginatedResult<ValidatedRow> => {\n if (!sheet) {\n return { page: 1, pageSize, totalCount: 0, totalPages: 0, rows: [] };\n }\n return getPaginatedResult(sheet, page, pageSize);\n }, [sheet, page, pageSize]);\n\n const totalPages = pageData.totalPages;\n\n const applyEdit = useCallback(\n (params: EditCellParams) => {\n if (!sheet || !layout || submitDone) return Promise.resolve();\n const previousValue =\n getRowByIndex(sheet, params.rowIndex) &&\n getCellByKey(getRowByIndex(sheet, params.rowIndex)!, params.cellKey)?.value;\n return runEdit(sheet, layout, params.rowIndex, params.cellKey, params.value).then(\n (newSheet) => {\n setResult(newSheet);\n queueMicrotask(() => {\n const entry: ChangeLogEntry = {\n type: 'cell_edit',\n rowIndex: params.rowIndex,\n cellKey: params.cellKey,\n value: params.value,\n previousValue,\n timestamp: Date.now(),\n };\n addChangeLogEntry(entry);\n });\n }\n );\n },\n [sheet, layout, submitDone, runEdit, setResult, addChangeLogEntry]\n );\n\n const editCell = useCallback(\n (params: EditCellParams): void | Promise<void> => {\n if (debounceMs != null && debounceMs > 0) {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(() => {\n debounceRef.current = null;\n applyEdit(params);\n }, debounceMs);\n return;\n }\n return applyEdit(params);\n },\n [debounceMs, applyEdit]\n );\n\n const removeRow = useCallback(\n (rowIndex: number): void => {\n if (!sheet || submitDone) return;\n const newSheet = removeRowSheet(sheet, rowIndex);\n setResult(newSheet);\n queueMicrotask(() => {\n const entry: ChangeLogEntry = {\n type: 'row_remove',\n rowIndex,\n timestamp: Date.now(),\n };\n addChangeLogEntry(entry);\n });\n },\n [sheet, submitDone, setResult, addChangeLogEntry]\n );\n\n const changeLogAsText = useMemo(() => formatChangeLogAsText(changeLog), [changeLog]);\n\n return useMemo(\n () => ({\n sheet,\n editCell,\n removeRow,\n pageData,\n totalPages,\n isReady,\n canEdit,\n changeLog,\n changeLogAsText,\n }),\n [sheet, editCell, removeRow, pageData, totalPages, isReady, canEdit, changeLog, changeLogAsText]\n );\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport * as Comlink from 'comlink';\nimport type { SheetLayout } from '../../../types/sheet-layout.js';\nimport type { Sheet } from '../../../types/sheet.js';\nimport { getEditWorkerUrl } from '../worker/worker-url.js';\n\nexport interface EditWorkerOptions {\n signal?: AbortSignal;\n}\n\ntype EditWorkerApi = {\n runEdit: (\n sheet: Sheet,\n sheetLayout: SheetLayout,\n rowIndex: number,\n cellKey: string,\n value: unknown,\n options?: EditWorkerOptions,\n ) => Promise<Sheet>;\n};\n\nexport function useEditWorker() {\n const [workerProxy, setWorkerProxy] = useState<Comlink.Remote<EditWorkerApi> | null>(null);\n const workerRef = useRef<Worker | null>(null);\n\n useEffect(() => {\n const worker = new Worker(getEditWorkerUrl(), { type: 'module' });\n workerRef.current = worker;\n const proxy = Comlink.wrap<EditWorkerApi>(worker);\n queueMicrotask(() => setWorkerProxy(proxy));\n return () => {\n worker.terminate();\n workerRef.current = null;\n };\n }, []);\n\n const runEdit = useCallback(\n async (\n sheet: Sheet,\n sheetLayout: SheetLayout,\n rowIndex: number,\n cellKey: string,\n value: unknown,\n options?: EditWorkerOptions,\n ): Promise<Sheet> => {\n if (!workerProxy) throw new Error('Edit worker not ready');\n return workerProxy.runEdit(\n sheet,\n sheetLayout,\n rowIndex,\n cellKey,\n value,\n options ?? {},\n );\n },\n [workerProxy],\n );\n\n return { runEdit, isReady: !!workerProxy };\n}\n","export function getEditWorkerUrl(): string {\n return new URL('./edit.worker.js', import.meta.url).href;\n}\n","import type { PaginatedResult } from '../../types/paginated-result.js';\nimport type { Sheet, ValidatedRow } from '../../types/sheet.js';\n\nexport function getPaginatedResult(\n sheet: Sheet,\n page: number,\n pageSize: number,\n): PaginatedResult<ValidatedRow> {\n return getPaginatedResultFromRows(sheet.rows, page, pageSize);\n}\n\nexport function getPaginatedResultFromRows<TRow>(\n rows: readonly TRow[],\n page: number,\n pageSize: number,\n): PaginatedResult<TRow> {\n const totalCount = rows.length;\n const totalPages =\n pageSize <= 0 ? 0 : Math.max(1, Math.ceil(totalCount / pageSize));\n const safePage = Math.max(1, Math.min(page, totalPages));\n const start = (safePage - 1) * pageSize;\n const end = Math.min(start + pageSize, totalCount);\n const slice = rows.slice(start, end);\n return {\n page: safePage,\n pageSize,\n totalCount,\n totalPages,\n rows: slice,\n };\n}\n","import { useCallback, useMemo, useState } from 'react';\nimport type { ValidatedRow } from '../../../types/sheet.js';\nimport { useImporterContext } from '../../../providers/index.js';\nimport { useSheetEditor } from '../../../hooks/useSheetEditor.js';\nimport { getPaginatedResultFromRows } from '../../editor/get-paginated-result.js';\nimport { getRowsWithErrors } from '../get-rows-with-errors.js';\nimport { getViewCounts } from '../get-view-counts.js';\nimport { sheetToCSV } from '../export/sheet-to-csv.js';\nimport { sheetToJSON } from '../export/sheet-to-json.js';\nimport type { UseSheetViewOptions, UseSheetViewReturn } from '../types/index.js';\n\nexport function useSheetView(options: UseSheetViewOptions = {}): UseSheetViewReturn<ValidatedRow> {\n const { page: initialPage = 1, defaultPageSize = 25, filterMode = 'all' } = options;\n const [page, setPage] = useState(initialPage);\n const pageSize = defaultPageSize;\n const { sheet, editCell, removeRow, changeLog, changeLogAsText } = useSheetEditor({});\n const ctx = useImporterContext();\n\n const rowsWithErrors = useMemo(() => (sheet ? getRowsWithErrors(sheet) : []), [sheet]);\n const sourceRows = useMemo(\n () => (filterMode === 'errors-only' ? rowsWithErrors : (sheet?.rows ?? [])),\n [filterMode, rowsWithErrors, sheet]\n );\n const totalRows = sourceRows.length;\n\n const getPaginatedResult = useCallback(\n (p?: number, ps?: number) => {\n const pp = p ?? page;\n const pps = ps ?? pageSize;\n return getPaginatedResultFromRows(sourceRows, pp, pps);\n },\n [page, pageSize, sourceRows]\n );\n const paginatedRows = useMemo(\n () => getPaginatedResult(page, pageSize).rows,\n [getPaginatedResult, page, pageSize]\n );\n const getRows = useCallback(\n (page: number, limit: number) => {\n // 1-based page → 0-based start index\n const start = (page - 1) * limit;\n return sourceRows.slice(start, start + limit);\n },\n [sourceRows]\n );\n const counts = useMemo(\n () => (sheet ? getViewCounts(sheet) : { totalRows: 0, rowsWithErrors: 0, totalErrors: 0 }),\n [sheet]\n );\n\n const exportToCSV = useCallback(\n (opts?: Parameters<UseSheetViewReturn['exportToCSV']>[0]) => {\n if (!sheet || !ctx.layout) return '';\n return sheetToCSV(sheet, ctx.layout, opts ?? {});\n },\n [sheet, ctx.layout]\n );\n const exportToJSON = useCallback(\n (opts?: Parameters<UseSheetViewReturn['exportToJSON']>[0]) => {\n if (!sheet) return '[]';\n return sheetToJSON(sheet, ctx.layout ?? null, opts ?? {});\n },\n [sheet, ctx.layout]\n );\n\n const downloadCSV = useCallback(\n async (opts?: Parameters<UseSheetViewReturn['downloadCSV']>[0]) => {\n const content = exportToCSV(opts);\n if (!content) return;\n const blob = new Blob([content], { type: 'text/csv;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = (opts?.filename ?? 'export') + '.csv';\n a.click();\n URL.revokeObjectURL(url);\n },\n [exportToCSV]\n );\n const downloadJSON = useCallback(\n async (opts?: Parameters<UseSheetViewReturn['downloadJSON']>[0]) => {\n const content = exportToJSON(opts);\n const blob = new Blob([content], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = (opts?.filename ?? 'export') + '.json';\n a.click();\n URL.revokeObjectURL(url);\n },\n [exportToJSON]\n );\n\n return useMemo(\n () => ({\n sheet,\n getPaginatedResult,\n paginatedRows,\n page,\n setPage,\n pageSize,\n totalRows,\n getRows,\n rowsWithErrors,\n counts,\n editCell,\n removeRow,\n changeLog,\n changeLogAsText,\n exportToCSV,\n exportToJSON,\n downloadCSV,\n downloadJSON,\n hasRecoverableSession: ctx.hasRecoverableSession,\n recoverSession: ctx.recoverSession,\n clearPersistedState: ctx.clearPersistedState,\n }),\n [\n sheet,\n getPaginatedResult,\n paginatedRows,\n page,\n pageSize,\n totalRows,\n getRows,\n rowsWithErrors,\n counts,\n editCell,\n removeRow,\n changeLog,\n changeLogAsText,\n exportToCSV,\n exportToJSON,\n downloadCSV,\n downloadJSON,\n ctx.hasRecoverableSession,\n ctx.recoverSession,\n ctx.clearPersistedState,\n ]\n );\n}\n","import type { SheetLayout } from '../../../types/sheet-layout.js';\nimport type { Sheet } from '../../../types/sheet.js';\nimport type { ExportOptions } from '../types/export-options.js';\n\nconst BOM = '\\uFEFF';\n\nfunction escapeCsvValue(value: string, separator: string): string {\n const needsQuotes =\n value.includes(separator) || value.includes('\"') || value.includes('\\n') || value.includes('\\r');\n if (!needsQuotes) return value;\n return '\"' + value.replace(/\"/g, '\"\"') + '\"';\n}\n\nfunction cellValueToString(value: unknown, formatDates: boolean): string {\n if (value === null || value === undefined) return '';\n if (value instanceof Date) return formatDates ? value.toLocaleString() : value.toISOString();\n return String(value);\n}\n\nexport function sheetToCSV(\n sheet: Sheet,\n sheetLayout: SheetLayout | null,\n options: ExportOptions = {},\n): string {\n const {\n includeHeaders = true,\n csvSeparator = ',',\n formatDatesForExport = false,\n } = options;\n const fieldOrder =\n sheetLayout != null ? Object.keys(sheetLayout.fields) : [];\n const effectiveOrder =\n fieldOrder.length > 0\n ? fieldOrder\n : (sheet.rows[0]?.cells.map((c) => c.key) ?? sheet.headers.slice());\n\n const lines: string[] = [];\n if (includeHeaders && effectiveOrder.length > 0) {\n lines.push(effectiveOrder.map((h) => escapeCsvValue(h, csvSeparator)).join(csvSeparator));\n }\n for (const row of sheet.rows) {\n const values = effectiveOrder.map((key) => {\n const cell = row.cells.find((c) => c.key === key);\n const raw = cell?.value ?? '';\n return escapeCsvValue(cellValueToString(raw, formatDatesForExport), csvSeparator);\n });\n lines.push(values.join(csvSeparator));\n }\n const body = lines.join('\\r\\n');\n return BOM + body;\n}\n","import type { SheetLayout } from '../../../types/sheet-layout.js';\nimport type { Sheet } from '../../../types/sheet.js';\nimport type { ExportOptions } from '../types/export-options.js';\n\nfunction cellValueToJson(value: unknown, formatDates: boolean): unknown {\n if (value === null || value === undefined) return null;\n if (value instanceof Date) return formatDates ? value.toLocaleString() : value.toISOString();\n return value;\n}\n\nexport function sheetToJSON(\n sheet: Sheet,\n _sheetLayout: SheetLayout | null,\n options: ExportOptions = {},\n): string {\n const { formatDatesForExport = false } = options;\n const rows = sheet.rows.map((row) => {\n const obj: Record<string, unknown> = {};\n for (const cell of row.cells) {\n obj[cell.key] = cellValueToJson(cell.value, formatDatesForExport);\n }\n return obj;\n });\n return JSON.stringify(rows, null, 0);\n}\n","import { useCallback, useEffect } from 'react';\r\nimport { IMPORTER_PROGRESS_EVENT } from '../types/index.js';\r\nimport type { ImporterProgressDetail } from '../types/index.js';\r\nimport { useImporterContext } from '../providers/index.js';\r\n\r\nexport function useImporterEventTarget() {\r\n const ctx = useImporterContext();\r\n const target = ctx.progressEventTarget;\r\n\r\n const subscribeToProgress = useCallback(\r\n (callback: (detail: ImporterProgressDetail) => void) => {\r\n const handler = (e: Event) => {\r\n callback((e as CustomEvent<ImporterProgressDetail>).detail);\r\n };\r\n target.addEventListener(IMPORTER_PROGRESS_EVENT, handler);\r\n return () => {\r\n target.removeEventListener(IMPORTER_PROGRESS_EVENT, handler);\r\n };\r\n },\r\n [target],\r\n );\r\n\r\n return { progressEventTarget: target, subscribeToProgress };\r\n}\r\n\r\nexport function useImporterProgressSubscription(\r\n callback: (detail: ImporterProgressDetail) => void,\r\n) {\r\n const { subscribeToProgress } = useImporterEventTarget();\r\n useEffect(() => {\r\n return subscribeToProgress(callback);\r\n }, [subscribeToProgress, callback]);\r\n}\r\n"],"mappings":"gGAAA,OAAS,aAAAA,GAAW,WAAAC,EAAS,UAAAC,GAAQ,YAAAC,OAAgB,QCK9C,IAAMC,EAAqB,6BAErBC,GAAsB,6BCPnC,OAAS,iBAAAC,OAAqB,QAGvB,IAAMC,EAAkBD,GAA2C,IAAI,ECDvE,IAAME,GAA8B,CACzC,KAAM,KACN,QAAS,KACT,aAAc,KACd,OAAQ,OACR,OAAQ,KACR,eAAgB,KAChB,eAAgB,KAChB,kBAAmB,KACnB,QAAS,KACT,UAAW,CAAC,EACZ,WAAY,EACd,ECdA,OAAS,eAAAC,EAAa,WAAAC,OAAe,QCgCrC,SAASC,EAASC,EAAoB,CACpC,OAAIA,EAAK,KAAQA,GAAM,EAAU,SAC7BA,EAAK,EAAU,IAAIA,EAAK,KAAM,QAAQ,CAAC,CAAC,UACrC,GAAGA,EAAG,QAAQ,CAAC,CAAC,IACzB,CAEO,SAASC,GACdC,EACAC,EACAC,EACiB,CACjB,IAAMC,EACJH,EAAQ,MAAQA,EAAQ,SAAWA,EAAQ,SAAWA,EAAQ,UAC1DI,EAASD,EAAU,IAEnBE,EAAa,IADQJ,EAAW,EAAIE,EAAUF,EAAW,GACtB,QAAQ,CAAC,CAAC,SAE/CK,EACJ,GAAIH,EAAU,EAAG,CACf,IAAMI,EAAWL,GAAc,EACzBM,EAAoBL,EAAUI,EACpCD,EAAc,CACZ,MAAQN,EAAQ,MAAQQ,EAAqB,IAC7C,SAAWR,EAAQ,SAAWQ,EAAqB,IACnD,SAAWR,EAAQ,SAAWQ,EAAqB,IACnD,UAAYR,EAAQ,UAAYQ,EAAqB,IACrD,SAAUA,EAAoB,EAAKD,EAAWC,EAAqB,IAAM,CAC3E,CACF,CAEA,MAAO,CACL,QAAS,CAAE,GAAGR,CAAQ,EACtB,YAAAM,EACA,QAAAH,EACA,OAAAC,EACA,UAAWP,EAASG,EAAQ,KAAK,EACjC,aAAcH,EAASG,EAAQ,QAAQ,EACvC,aAAcH,EAASG,EAAQ,QAAQ,EACvC,cAAeH,EAASG,EAAQ,SAAS,EACzC,UAAWH,EAASM,CAAO,EAC3B,WAAAE,EACA,SAAAJ,EACA,GAAIC,IAAe,QAAaA,GAAc,EAAI,CAAE,WAAAA,CAAW,EAAI,CAAC,CACtE,CACF,CC3DO,SAASO,EAAsBC,EAA4C,CAChF,IAAMC,EAAkB,CAAC,EACzB,QAAWC,KAAKF,EACd,GAAIE,EAAE,OAAS,YAAa,CAC1B,IAAMC,EAAOD,EAAE,gBAAkB,OAAY,eAAe,OAAOA,EAAE,aAAa,CAAC,IAAM,GACzFD,EAAM,KACJ,OAAOC,EAAE,SAAW,CAAC,WAAWA,EAAE,OAAO,aAAa,KAAK,UAAUA,EAAE,KAAK,CAAC,GAAGC,CAAI,EACtF,CACF,MACEF,EAAM,KAAK,OAAOC,EAAE,SAAW,CAAC,WAAW,EAG/C,OAAOD,EAAM,KAAK;AAAA,CAAI,CACxB,CCUO,IAAMG,EAA0B,oBAC1BC,EAAyB,mBCzCtC,OAAS,eAAAC,MAAmB,QAMrB,SAASC,EACdC,EAeA,CACA,GAAM,CAAE,SAAAC,EAAU,eAAAC,EAAgB,eAAAC,CAAe,EAAIH,EAE/CI,EAAUN,EACbO,GAAsB,CACrBJ,EAAUK,IAAU,CAAE,GAAGA,EAAM,KAAAD,CAAK,EAAE,CACxC,EACA,CAACJ,CAAQ,CACX,EAEMM,EAAaT,EAChBU,GAAsC,CACrCP,EAAUK,IAAU,CAAE,GAAGA,EAAM,QAAAE,CAAQ,EAAE,CAC3C,EACA,CAACP,CAAQ,CACX,EAEMQ,EAAkBX,EACrBY,GAAgC,CAC/BT,EAAUK,IAAU,CAAE,GAAGA,EAAM,aAAAI,CAAa,EAAE,CAChD,EACA,CAACT,CAAQ,CACX,EAEMU,EAAYb,EACfc,GAA2B,CAC1BX,EAAUK,IAAU,CAAE,GAAGA,EAAM,OAAAM,CAAO,EAAE,CAC1C,EACA,CAACX,CAAQ,CACX,EAEMY,EAAYf,EACfgB,GAAoC,CACnCb,EAAUK,IAAU,CAAE,GAAGA,EAAM,OAAAQ,CAAO,EAAE,CAC1C,EACA,CAACb,CAAQ,CACX,EAEMc,EAAoBjB,EACvBkB,GAAoD,CACnDf,EAAUK,IAAU,CAAE,GAAGA,EAAM,eAAAU,EAAgB,kBAAmB,IAAK,EAAE,CAC3E,EACA,CAACf,CAAQ,CACX,EAEMgB,EAAoBnB,EACvBoB,GAAoD,CACnDjB,EAAUK,IAAU,CAAE,GAAGA,EAAM,eAAAY,CAAe,EAAE,CAClD,EACA,CAACjB,CAAQ,CACX,EAEMkB,EAAuBrB,EAEzBsB,GAGG,CACHnB,EAAUK,IAAU,CAClB,GAAGA,EACH,kBACE,OAAOc,GAAkB,WACrBA,EAAcd,EAAK,iBAAiB,EACpCc,EACN,eAAgB,OAAOA,GAAkB,WAAad,EAAK,eAAiB,IAC9E,EAAE,CACJ,EACA,CAACL,CAAQ,CACX,EAEMoB,EAAavB,EAChBwB,GAAoC,CACnCrB,EAAUK,IAAU,CAAE,GAAGA,EAAM,QAAAgB,CAAQ,EAAE,CAC3C,EACA,CAACrB,CAAQ,CACX,EAEMsB,EAAgBzB,EACnB0B,GAAwB,CACvBvB,EAAUK,IAAU,CAAE,GAAGA,EAAM,WAAAkB,CAAW,EAAE,CAC9C,EACA,CAACvB,CAAQ,CACX,EAEMwB,EAAY3B,EACf4B,GAA6B,CAC5BxB,EAAewB,CAAI,CACrB,EACA,CAACxB,CAAc,CACjB,EAEMyB,EAAY7B,EACf4B,GAA8B,CAC7BvB,EAAeuB,CAAI,CACrB,EACA,CAACvB,CAAc,CACjB,EAEA,MAAO,CACL,UAAAsB,EACA,UAAAE,EACA,QAAAvB,EACA,WAAAG,EACA,gBAAAE,EACA,UAAAE,EACA,UAAAE,EACA,kBAAAE,EACA,kBAAAE,EACA,qBAAAE,EACA,WAAAE,EACA,cAAAE,CACF,CACF,CJzHA,IAAMK,GAAwB,CAC5B,MAAO,EACP,SAAU,EACV,SAAU,EACV,UAAW,CACb,EAEO,SAASC,GACdC,EAkBA,CACA,GAAM,CACJ,SAAAC,EACA,eAAAC,EACA,eAAAC,EACA,oBAAAC,EACA,kBAAAC,EACA,kBAAAC,EACA,kBAAAC,EACA,gBAAAC,EACA,gBAAAC,CACF,EAAIT,EAEEU,EAAeC,EAAwB,CAAE,SAAAV,EAAU,eAAAC,EAAgB,eAAAC,CAAe,CAAC,EAEnFS,EAAmBC,EACtBC,GAAmC,CAClCV,EAAoB,cAAc,IAAI,YAAYW,EAAyB,CAAE,OAAAD,CAAO,CAAC,CAAC,CACxF,EACA,CAACV,CAAmB,CACtB,EAEMY,EAAkBH,EACrBI,GAA0B,CACzBT,EAAgB,QAAUS,CAC5B,EACA,CAACT,CAAe,CAClB,EAEMU,EAAQL,EAAY,IAAM,CAC9B,IAAMI,EAAST,EAAgB,QAC3BS,IACFA,EAAO,UAAU,EACjBT,EAAgB,QAAU,MAE5BP,EAAUkB,IAAU,CAAE,GAAGA,EAAM,OAAQ,WAAY,EAAE,EACrDf,EAAoB,cAAc,IAAI,YAAYgB,CAAsB,CAAC,CAC3E,EAAG,CAACZ,EAAiBJ,EAAqBH,CAAQ,CAAC,EAE7CoB,EAAiBR,EACrB,CAACS,EAAsBC,IAAe,CACpCd,EAAgB,QAAU,CAAE,GAAGA,EAAgB,QAAS,CAACa,CAAK,EAAGC,CAAG,CACtE,EACA,CAACd,CAAe,CAClB,EAEMe,EAAkBX,EACrBY,GAAqB,CACpB,IAAMC,EAAU,CAAE,GAAGjB,EAAgB,OAAQ,EACvCkB,EAAUC,GAAqBF,EAASD,CAAQ,EACtDf,EAAa,WAAWiB,CAAO,CACjC,EACA,CAAClB,EAAiBC,CAAY,CAChC,EAEMmB,EAAoBhB,EACvBiB,GAA0B,CACzB7B,EAAUkB,IAAU,CAClB,GAAGA,EACH,UAAW,CAAC,GAAGA,EAAK,UAAWW,CAAK,CACtC,EAAE,CACJ,EACA,CAAC7B,CAAQ,CACX,EAEM8B,EAAclB,EACjBmB,GAAe,CACdvB,EAAgB,QAAU,CAAE,GAAGX,EAAsB,EACrDG,EAAUkB,IAAU,CAClB,GAAGA,EACH,KAAAa,EACA,OAAQ,UACR,QAAS,KACT,aAAc,KACd,OAAQ,KACR,eAAgB,KAChB,eAAgB,KAChB,kBAAmB,KACnB,QAAS,KACT,UAAW,CAAC,EACZ,WAAY,EACd,EAAE,CACJ,EACA,CAACvB,EAAiBR,CAAQ,CAC5B,EAEMgC,EAAoBpB,EACxB,CAACqB,EAAcC,EAAqCC,IAAqC,CACvF/B,EAAkB,SAAS6B,EAAMC,EAAIC,CAAO,CAC9C,EACA,CAAC/B,CAAiB,CACpB,EAEMgC,EAAoBxB,EACxB,CAACqB,EAAcC,EAAqCC,IAAqC,CACvF9B,EAAkB,SAAS4B,EAAMC,EAAIC,CAAO,CAC9C,EACA,CAAC9B,CAAiB,CACpB,EAEMgC,EAAoBzB,EACxB,CAACqB,EAAcC,EAAqCC,IAAqC,CACvF7B,EAAkB,SAAS2B,EAAMC,EAAIC,CAAO,CAC9C,EACA,CAAC7B,CAAiB,CACpB,EAEA,OAAOgC,GACL,KAAO,CACL,GAAG7B,EACH,kBAAAmB,EACA,eAAAR,EACA,gBAAAG,EACA,YAAAO,EACA,kBAAAE,EACA,kBAAAI,EACA,kBAAAC,EACA,MAAApB,EACA,iBAAAN,EACA,gBAAAI,CACF,GACA,CACEN,EACAmB,EACAR,EACAG,EACAO,EACAE,EACAI,EACAC,EACApB,EACAN,EACAI,CACF,CACF,CACF,CK9KA,OAAS,eAAAwB,GAAa,aAAAC,GAAW,UAAAC,GAAQ,YAAAC,OAAgB,QCMzD,SAASC,IAA+B,CACtC,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtC,IAAMC,EAAM,UAAU,KAAK,wBAAyB,CAAC,EACrDA,EAAI,QAAU,IAAMD,EAAOC,EAAI,KAAK,EACpCA,EAAI,UAAY,IAAMF,EAAQE,EAAI,MAAM,EACxCA,EAAI,gBAAkB,IAAM,CAC1BA,EAAI,OAAO,kBAAkBC,EAAoB,CAAE,QAAS,KAAM,CAAC,CACrE,CACF,CAAC,CACH,CAEA,eAAsBC,GACpBC,EACAC,EACe,CACf,IAAMC,EAAK,MAAMR,GAAO,EACxB,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtC,IAAMO,EAAKD,EAAG,YAAYJ,EAAoB,WAAW,EACnDM,EAAQD,EAAG,YAAYL,CAAkB,EACzCO,EAAS,CAAE,IAAAL,EAAK,GAAGC,CAAM,EACzBJ,EAAMO,EAAM,IAAIC,CAAM,EAC5BR,EAAI,UAAY,IAAMF,EAAQ,EAC9BE,EAAI,QAAU,IAAMD,EAAOC,EAAI,KAAK,EACpCM,EAAG,WAAa,IAAMD,EAAG,MAAM,CACjC,CAAC,CACH,CAEA,eAAsBI,GACpBN,EACgC,CAChC,IAAME,EAAK,MAAMR,GAAO,EACxB,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CAGtC,IAAMC,EAFKK,EAAG,YAAYJ,EAAoB,UAAU,EACvC,YAAYA,CAAkB,EAC7B,IAAIE,CAAG,EACzBH,EAAI,UAAY,IAAM,CACpBK,EAAG,MAAM,EACT,IAAMK,EAAMV,EAAI,OAChB,GAAIU,GAAO,KAAM,CACfZ,EAAQ,IAAI,EACZ,MACF,CACA,IAAMa,EAAUD,EAAI,QACpB,GAAI,KAAK,IAAI,EAAIC,EAAU,OAA4B,CACrDb,EAAQ,IAAI,EACZ,MACF,CACA,GAAM,CAAE,IAAKc,EAAI,GAAGR,CAAM,EAAIM,EAC9BZ,EAAQM,CAAuB,CACjC,EACAJ,EAAI,QAAU,IAAMD,EAAOC,EAAI,KAAK,CACtC,CAAC,CACH,CAEA,eAAsBa,GAAoBV,EAA4B,CACpE,IAAME,EAAK,MAAMR,GAAO,EACxB,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtC,IAAMO,EAAKD,EAAG,YAAYJ,EAAoB,WAAW,EAEnDD,EADQM,EAAG,YAAYL,CAAkB,EAC7B,OAAOE,CAAG,EAC5BH,EAAI,UAAY,IAAMF,EAAQ,EAC9BE,EAAI,QAAU,IAAMD,EAAOC,EAAI,KAAK,EACpCM,EAAG,WAAa,IAAMD,EAAG,MAAM,CACjC,CAAC,CACH,CDzDA,IAAMS,GAAc,KAEb,SAASC,GACdC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACA,CACA,GAAM,CAACC,EAAoBC,CAAqB,EAAIC,GAAoC,IAAI,EACtFC,EAAcC,GAA6C,IAAI,EAErEC,GAAU,IAAM,CACTZ,GACLa,GAAmBZ,CAAU,EAAE,KAAMa,GAAU,CACxCA,IAEHA,EAAM,eAAiB,MACvBR,GAAiB,MACjB,OAAOQ,EAAM,aAAa,IAAM,OAAOR,CAAa,GAItDE,EAAsBM,CAAK,EAC7B,CAAC,CACH,EAAG,CAACd,EAASC,EAAYK,CAAa,CAAC,EAEvCM,GAAU,IAAM,CACd,GAAI,GAACZ,GAAW,CAACE,GAAW,CAACC,GAC7B,OAAIO,EAAY,SAAS,aAAaA,EAAY,OAAO,EACzDA,EAAY,QAAU,WAAW,IAAM,CACrCA,EAAY,QAAU,KACtB,IAAMK,EAA8B,CAClC,QAAAb,EACA,MAAOC,EACP,QAAS,KAAK,IAAI,EAClB,cAAeG,GAAiB,OAChC,mBAAoB,CACtB,EACAU,GAAmBf,EAAYc,CAAO,EAAE,MAAM,IAAM,CAAC,CAAC,CACxD,EAAGjB,EAAW,EACP,IAAM,CACPY,EAAY,SAAS,aAAaA,EAAY,OAAO,CAC3D,CACF,EAAG,CAACV,EAASC,EAAYC,EAASC,EAAQG,CAAa,CAAC,EAExD,IAAMW,EAAiBC,GAAY,SAAY,CAC7C,GAAI,CAAClB,EAAS,OACd,IAAMc,EAAQP,EACTO,IACLV,EAAWU,EAAM,OAAO,EACxBT,EAAUS,EAAM,KAAK,EACrBN,EAAsB,IAAI,EAC5B,EAAG,CAACR,EAASO,EAAoBH,EAAYC,CAAS,CAAC,EAEjDc,EAAsBD,GAAY,SAAY,CAC7ClB,IACL,MAAMmB,GAA2BlB,CAAU,EAC3CO,EAAsB,IAAI,EAC5B,EAAG,CAACR,EAASC,CAAU,CAAC,EAExB,MAAO,CACL,sBAAuBD,GAAWO,GAAsB,KACxD,eAAAU,EACA,oBAAAE,CACF,CACF,CEjFA,OAAS,eAAAC,GAAa,aAAAC,OAAiB,QCAvC,OAAS,eAAAC,GAAa,aAAAC,GAAW,UAAAC,GAAQ,YAAAC,OAAgB,QACzD,UAAYC,MAAa,UCDlB,SAASC,IAA6B,CAC3C,OAAO,IAAI,IAAI,qBAAsB,YAAY,GAAG,EAAE,IACxD,CDWO,SAASC,IAAkB,CAChC,GAAM,CAAE,gBAAAC,EAAiB,iBAAAC,CAAiB,EAAIC,EAAmB,EAC3D,CAACC,EAAaC,CAAc,EAAIC,GAAiD,IAAI,EACrFC,EAAYC,GAAsB,IAAI,EAE5CC,GAAU,IAAM,CACd,IAAMC,EAAS,IAAI,OAAOC,GAAmB,EAAG,CAAE,KAAM,QAAS,CAAC,EAClEJ,EAAU,QAAUG,EACpBT,EAAgBS,CAAM,EACtB,IAAME,EAAgB,OAAsBF,CAAM,EAClD,sBAAe,IAAML,EAAeO,CAAK,CAAC,EACnC,IAAM,CACXF,EAAO,UAAU,EACjBH,EAAU,QAAU,KACpBN,EAAgB,IAAI,CACtB,CACF,EAAG,CAACA,CAAe,CAAC,EAEpB,IAAMY,EAAOC,GACX,MAAOC,EAAYC,EAAwB,CAAC,IAA+B,CACzE,GAAI,CAACZ,EAAa,MAAM,IAAI,MAAM,yBAAyB,EAC3D,OAAOA,EAAY,KAAKW,EAAMC,CAAO,CACvC,EACA,CAACZ,CAAW,CACd,EAEMa,EAAWH,GACf,MAAOI,GAA8E,CACnF,GAAI,CAACd,EAAa,MAAM,IAAI,MAAM,yBAAyB,EAC3D,IAAMe,EAAgBD,EAAqB,QAAMA,CAAU,EAAI,OAC/D,OAAOd,EAAY,SAASe,CAAa,CAC3C,EACA,CAACf,CAAW,CACd,EAEA,MAAO,CAAE,KAAAS,EAAM,SAAAI,EAAU,iBAAAf,EAAkB,QAAS,CAAC,CAACE,CAAY,CACpE,CD7CA,SAASgB,GACPC,EACiC,CACjC,IAAMC,EAAQ,OAAO,KAAKD,EAAO,MAAM,EACvC,OAAIC,EAAM,SAAW,EAAU,KACxBD,EAAO,OAAOC,EAAM,CAAC,GAAK,EAAE,GAAK,IAC1C,CAEO,SAASC,GAAiB,CAC/B,IAAMC,EAAMC,EAAmB,EACzB,CAAE,KAAAC,EAAM,SAAAC,EAAU,QAAAC,CAAQ,EAAIC,GAAgB,EAEpD,OAAAC,GAAU,IAAM,CACd,GAAM,CAAE,KAAAC,EAAM,OAAAC,EAAQ,OAAAC,CAAO,EAAIT,EAC7B,CAACI,GAAW,CAACG,GAAQC,IAAW,WACpCN,EAAKK,EAAM,CAAE,QAAS,GAAI,SAAUA,EAAK,KAAM,OAAQE,GAAU,MAAU,CAAC,EACzE,KAAMZ,GAAW,CAEhB,GAAI,CADUD,GAAqBC,CAAM,EAC7B,CACVG,EAAI,UAAU,OAAO,EACrB,MACF,CACA,IAAMU,EAAQb,EAAO,OAAO,OAAO,KAAKA,EAAO,MAAM,EAAE,CAAC,GAAK,EAAE,EAC/D,GAAI,CAACa,EAAO,CACVV,EAAI,UAAU,OAAO,EACrB,MACF,CACAA,EAAI,WAAWU,CAAK,EACpBV,EAAI,gBAAgBU,EAAM,YAAY,EACtCV,EAAI,UAAU,SAAS,CACzB,CAAC,EACA,MAAM,IAAM,CACXA,EAAI,UAAU,OAAO,CACvB,CAAC,CAEL,EAAG,CAACI,EAASJ,EAAI,KAAMA,EAAI,OAAQA,EAAI,WAAYA,EAAI,gBAAiBA,EAAI,UAAWE,CAAI,CAAC,EA2BrF,CAAE,gBAzBeS,GAAY,IAAM,CACxC,GAAM,CAAE,KAAAJ,CAAK,EAAIP,EACjB,GAAI,CAACO,EAAM,OAAO,QAAQ,OAAO,IAAI,MAAM,gBAAgB,CAAC,EAC5DP,EAAI,UAAU,SAAS,EACvB,IAAMY,EAAK,YAAY,IAAI,EAC3B,OAAOT,EAAUU,GAAWb,EAAI,iBAAiBa,CAAM,CAAC,EAAE,KAAMhB,GAAW,CACzE,IAAMiB,EAAK,YAAY,IAAI,EAG3B,GAFAd,EAAI,eAAe,QAASc,EAAKF,CAAE,EAE/B,CADUhB,GAAqBC,CAAM,EAEvC,OAAAG,EAAI,UAAU,OAAO,EACdH,EAET,IAAMa,EAAQb,EAAO,OAAO,OAAO,KAAKA,EAAO,MAAM,EAAE,CAAC,GAAK,EAAE,EAC/D,OAAKa,GAILV,EAAI,WAAWU,CAAK,EACpBV,EAAI,gBAAgBU,EAAM,YAAY,EACtCV,EAAI,UAAU,SAAS,EAChBH,IANLG,EAAI,UAAU,OAAO,EACdH,EAMX,CAAC,CACH,EAAG,CAACG,EAAKG,CAAQ,CAAC,CAEO,CAC3B,CXuCI,OACE,OAAAY,GADF,QAAAC,OAAA,oBA9FJ,SAASC,IAAuB,CAC9B,OAAAC,EAAe,EACR,IACT,CAEO,SAASC,GAAiB,CAC/B,SAAAC,EACA,OAAQC,EACR,OAAQC,EACR,QAAAC,EAAU,GACV,WAAAC,EAAaC,GACb,SAAAC,EAAW,KACX,aAAAC,EAAe,IACjB,EAA0B,CACxB,GAAM,CAACC,EAAOC,CAAQ,EAAIC,GAASC,EAAY,EACzC,CAACC,EAAQC,CAAc,EAAIH,GAA6BT,GAAc,IAAI,EAC1E,CAACa,EAAQC,CAAc,EAAIL,GAA8BR,GAAc,IAAI,EAC3Ec,EAAsBC,EAAQ,IAAM,IAAI,YAAe,CAAC,CAAC,EACzDC,EAAoBD,EAAQ,IAAM,IAAIE,EAA6C,CAAC,CAAC,EACrFC,EAAoBH,EAAQ,IAAM,IAAIE,EAA6C,CAAC,CAAC,EACrFE,EAAoBJ,EAAQ,IAAM,IAAIE,EAA6C,CAAC,CAAC,EACrFG,EAAkBC,GAAsB,IAAI,EAC5CC,EAAkBD,GAAO,CAC7B,MAAO,EACP,SAAU,EACV,SAAU,EACV,UAAW,CACb,CAAC,EAEKE,EAAeC,EAAwB,CAAE,SAAAjB,EAAU,eAAAI,EAAgB,eAAAE,CAAe,CAAC,EACnFY,EAAiBC,GACrBzB,EACAC,EACAI,EAAM,QACNA,EAAM,OACNiB,EAAa,WACbA,EAAa,UACbb,GAAQ,SAAW,IACrB,EAEMiB,EAAUC,GAAmB,CACjC,SAAArB,EACA,eAAAI,EACA,eAAAE,EACA,oBAAAC,EACA,kBAAAE,EACA,kBAAAE,EACA,kBAAAC,EACA,gBAAAC,EACA,gBAAAE,CACF,CAAC,EAEDO,GAAU,IACD,IAAM,CACX,IAAMC,EAASV,EAAgB,QAC3BU,IACFA,EAAO,UAAU,EACjBV,EAAgB,QAAU,KAE9B,EACC,CAAC,CAAC,EAEL,IAAMW,EAAQhB,EACZ,KAAO,CACL,GAAGT,EACH,OAAAI,EACA,OAAAE,EACA,oBAAAE,EACA,GAAGa,EACH,SAAUvB,GAAY,KACtB,aAAcC,GAAgB,KAC9B,QAAAJ,EACA,WAAAC,EACA,sBAAuBuB,EAAe,sBACtC,eAAgBA,EAAe,eAC/B,oBAAqBA,EAAe,mBACtC,GACA,CACEnB,EACAI,EACAE,EACAE,EACAV,EACAC,EACAsB,EACA1B,EACAC,EACAuB,EAAe,sBACfA,EAAe,eACfA,EAAe,mBACjB,CACF,EAEA,OACE/B,GAACsC,EAAgB,SAAhB,CAAyB,MAAOD,EAC/B,UAAAtC,GAACE,GAAA,EAAqB,EACrBG,GACH,CAEJ,Cc/GA,OAAS,cAAAmC,OAAkB,QAIpB,SAASC,GAA2C,CACzD,IAAMC,EAAUC,GAAWC,CAAe,EAC1C,GAAIF,IAAY,KACd,MAAM,IAAI,MAAM,qDAAqD,EAEvE,OAAOA,CACT,CCVA,OAAS,eAAAG,GAAa,aAAAC,GAAW,WAAAC,OAAe,QCEzC,SAASC,EAAkBC,EAA8B,CAC9D,OAAOA,EAAM,KAAK,OAAQC,GAAQA,EAAI,OAAO,OAAS,CAAC,CACzD,CCAO,SAASC,EAAoBC,EAA8B,CAChE,OAAKA,EACEC,EAAcD,CAAK,EAAE,YAAc,EADvB,EAErB,CAEO,SAASC,EAAcD,EAA0B,CACtD,IAAME,EAAYF,EAAM,KAAK,OACvBG,EAAiBC,EAAkBJ,CAAK,EACxCK,EACJL,EAAM,OAAO,OACbA,EAAM,KAAK,OACT,CAACM,EAAKC,IACJD,EAAMC,EAAI,OAAO,OAASA,EAAI,MAAM,OAAO,CAACC,EAAGC,IAASD,EAAIC,EAAK,OAAO,OAAQ,CAAC,EACnF,CACF,EACF,MAAO,CACL,UAAAP,EACA,eAAgBC,EAAe,OAC/B,YAAAE,CACF,CACF,CCtBO,SAASK,GAAaC,EAAmBC,EAAsB,CAEpE,OADaD,EAAI,MAAM,KAAME,GAAMA,EAAE,MAAQD,CAAG,GACnC,KACf,CAEO,SAASE,GACdC,EACAC,EACK,CACL,OAAOD,EAAK,IAAIC,CAAM,CACxB,CAEO,SAASC,EACdC,EACAC,EAC2B,CAC3B,OAAKD,EACEA,EAAM,KAAK,IAAKP,GAAQ,CAC7B,IAAMS,EAA+B,CAAC,EACtC,OAAW,CAACC,EAAUC,CAAS,IAAK,OAAO,QAAQH,CAAM,EACvDC,EAAIE,CAAS,EAAIZ,GAAaC,EAAKU,CAAQ,EAE7C,OAAOD,CACT,CAAC,EAPkB,CAAC,CAQtB,CHnBA,SAASG,GAAoBC,EAAyC,CACpE,OAAOA,EAAM,KAAK,IAAKC,GACrBA,EAAI,MAAM,OAAO,CAACC,EAAKC,KAAO,CAAE,GAAGD,EAAK,CAACC,EAAE,GAAG,EAAGA,EAAE,KAAM,GAAI,CAAC,CAA4B,CAC5F,CACF,CAEO,SAASC,GAAYC,EAA8B,CAAC,EAAG,CAC5D,IAAMC,EAAMC,EAAmB,EACzB,CAAE,OAAQC,EAAc,OAAQC,CAAa,EAAIJ,EAEvDK,GAAU,IAAM,CACVF,IAAiB,QACnBF,EAAI,UAAUE,CAAY,CAE9B,EAAG,CAACF,EAAKE,CAAY,CAAC,EAEtBE,GAAU,IAAM,CACVD,IAAiB,QACnBH,EAAI,UAAUG,CAAY,CAE9B,EAAG,CAACH,EAAKG,CAAY,CAAC,EAEtB,IAAME,EAAYC,GAChB,IACE,GACEN,EAAI,QACJA,EAAI,SAAW,WACf,CAACA,EAAI,YACL,CAACO,EAAoBP,EAAI,MAAM,GAEnC,CAACA,EAAI,OAAQA,EAAI,OAAQA,EAAI,UAAU,CACzC,EAEMQ,EAASC,GAAY,IAAM,CAC/B,GAAI,CAACT,EAAI,QAAUA,EAAI,YAAcO,EAAoBP,EAAI,MAAM,GAAK,CAACA,EAAI,SAAU,OACvF,IAAMU,EAAOV,EAAI,aACbW,EAAyBX,EAAI,OAAQA,EAAI,YAAY,EACrDP,GAAoBO,EAAI,MAAM,EAClCA,EAAI,SAASU,CAAI,EACjBV,EAAI,cAAc,EAAI,CACxB,EAAG,CAACA,CAAG,CAAC,EAER,OAAOM,GACL,KAAO,CACL,YAAaN,EAAI,YACjB,kBAAmBA,EAAI,kBACvB,kBAAmBA,EAAI,kBACvB,kBAAmBA,EAAI,kBACvB,MAAOA,EAAI,MACX,QAASA,EAAI,QACb,OAAAQ,EACA,UAAAH,EACA,WAAYL,EAAI,UAClB,GACA,CACEA,EAAI,YACJA,EAAI,kBACJA,EAAI,kBACJA,EAAI,kBACJA,EAAI,MACJA,EAAI,QACJQ,EACAH,EACAL,EAAI,UACN,CACF,CACF,CIzEA,OAAS,eAAAY,EAAa,WAAAC,OAAe,QCI9B,SAASC,GACdC,EACAC,EACAC,EACAC,EACgB,CAChB,IAAMC,EAAU,CAAC,GAAGF,CAAW,EACzBG,EAAc,IAAI,IACxBL,EAAS,QAAQ,QAAQ,CAACM,EAAGC,IAAMF,EAAY,IAAIC,EAAGC,CAAC,CAAC,EAExD,IAAMC,EAA4BR,EAAS,KAAK,IAAKS,GAAQ,CAC3D,IAAMC,EAA8BR,EAAY,IAAKS,GAAc,CACjE,IAAMC,EAAaT,EAAcQ,CAAS,EACpCE,EACJD,GAAc,MACT,IAAM,CACL,IAAME,EAAMT,EAAY,IAAIO,CAAU,EACtC,OAAIE,GAAO,KAAa,KACXL,EAAI,MAAMK,CAAG,GACb,OAAS,IACxB,GAAG,EACH,KACN,MAAO,CAAE,IAAKH,EAAW,MAAOE,GAAS,IAAK,CAChD,CAAC,EACD,MAAO,CAAE,MAAOJ,EAAI,MAAO,MAAAC,CAAM,CACnC,CAAC,EAED,MAAO,CACL,KAAMV,EAAS,KACf,SAAUA,EAAS,SACnB,aAAcA,EAAS,aACvB,UAAWA,EAAS,UACpB,aAAcA,EAAS,aACvB,QAAAI,EACA,KAAAI,CACF,CACF,CCxCO,SAASO,GAAUC,EAAmB,CAE3C,OADUA,EAAE,KAAK,EAAE,YAAY,EACtB,UAAU,KAAK,EAAE,QAAQ,kBAAmB,EAAE,CACzD,CAEA,SAASC,GAAoBC,EAAWC,EAAmB,CACzD,GAAID,EAAE,SAAW,EAAG,OAAOC,EAAE,OAC7B,GAAIA,EAAE,SAAW,EAAG,OAAOD,EAAE,OAC7B,IAAIE,EAAO,MAAM,KAAK,CAAE,OAAQD,EAAE,OAAS,CAAE,EAAG,CAACE,EAAGC,IAAMA,CAAC,EAC3D,QAASA,EAAI,EAAGA,GAAKJ,EAAE,OAAQI,IAAK,CAClC,IAAMC,EAAiB,CAACD,CAAC,EACzB,QAASE,EAAI,EAAGA,GAAKL,EAAE,OAAQK,IAAK,CAClC,IAAMC,EAAOP,EAAEI,EAAI,CAAC,IAAMH,EAAEK,EAAI,CAAC,EAAI,EAAI,EACzCD,EAAKC,CAAC,EAAI,KAAK,IACbD,EAAKC,EAAI,CAAC,EAAK,EACfJ,EAAKI,CAAC,EAAK,EACXJ,EAAKI,EAAI,CAAC,EAAKC,CACjB,CACF,CACAL,EAAOG,CACT,CACA,OAAOH,EAAKD,EAAE,MAAM,CACtB,CAEO,SAASO,GAAcC,EAAYC,EAAoB,CAC5D,IAAMV,EAAIH,GAAUY,CAAE,EAChBR,EAAIJ,GAAUa,CAAE,EAChBC,EAASX,EAAE,QAAUC,EAAE,OAASD,EAAIC,EACpCW,EAAUZ,EAAE,OAASC,EAAE,OAASD,EAAIC,EAC1C,GAAIU,EAAO,SAAW,EAAG,MAAO,GAChC,IAAME,EAAWd,GAAoBY,EAAQC,CAAO,EACpD,OAAQD,EAAO,OAASE,GAAYF,EAAO,MAC7C,CAEA,IAAMG,GAA0B,GAWzB,SAASC,GACdC,EACAC,EACAC,EAA6B,CAAC,EACZ,CAClB,IAAMC,EAAYD,EAAQ,WAAaJ,GACjCM,EAA8D,CAAC,EACrE,QAAWC,KAAOJ,EAChB,QAAWK,KAAUN,EAAY,CAC/B,IAAMO,EAAQf,GAAca,EAAKC,CAAM,EACnCC,GAASJ,GACXC,EAAU,KAAK,CAAE,IAAAC,EAAK,OAAAC,EAAQ,MAAAC,CAAM,CAAC,CAEzC,CAEFH,EAAU,KAAK,CAACI,EAAGC,IAAMA,EAAE,MAAQD,EAAE,KAAK,EAE1C,IAAME,EAAe,IAAI,IACnBC,EAAkB,IAAI,IACtBC,EAA6C,CAAC,EACpD,QAAWC,KAAKZ,EACdW,EAAYC,CAAC,EAAI,KAEnB,OAAW,CAAE,IAAAR,EAAK,OAAAC,EAAQ,MAAOnB,CAAE,IAAKiB,EAClCM,EAAa,IAAIL,CAAG,GAAKM,EAAgB,IAAIL,CAAM,IACvDM,EAAYP,CAAG,EAAIC,EACnBI,EAAa,IAAIL,CAAG,EACpBM,EAAgB,IAAIL,CAAM,GAG5B,OAAOL,EAAa,IAAKI,IAAS,CAChC,IAAAA,EACA,cAAeO,EAAYP,CAAG,GAAK,IACrC,EAAE,CACJ,CCpEA,SAASS,GAAiBC,EAAgBC,EAAgC,CACxE,IAAMC,EAAUF,EAAO,KAAK,EAC5B,OAAOC,EAAgBC,EAAUA,EAAQ,YAAY,CACvD,CAEO,SAASC,GACdC,EACAC,EACAC,EAAqD,CAAC,EACtDC,EAA0B,CAAC,EACP,CACpB,IAAMN,EAAgBM,EAAQ,eAAiB,GACzCC,EAAaD,EAAQ,aAAgBE,GAAcV,GAAiBU,EAAGR,CAAa,GACpFS,EAAmB,OAAO,KAAKL,EAAY,MAAM,EACjDM,EAAcP,EAAS,QACvBQ,EAAyB,IAAI,IACnC,QAAWH,KAAKE,EACdC,EAAuB,IAAIJ,EAAWC,CAAC,EAAGA,CAAC,EAG7C,IAAMI,EAA+C,CAAC,EAChDC,EAAkB,IAAI,IAE5B,OAAW,CAACC,EAAYC,CAAS,IAAK,OAAO,QAAQV,CAAgB,EAC/DI,EAAiB,SAASM,CAAS,IACrCH,EAAcG,CAAS,EAAIL,EAAY,SAASI,CAAU,EAAIA,EAAa,KACvEF,EAAcG,CAAS,GAAGF,EAAgB,IAAIC,CAAU,GAIhE,QAAWC,KAAaN,EAAkB,CACxC,GAAIG,EAAcG,CAAS,GAAK,KAAM,SACtC,IAAMC,EAAMT,EAAWQ,CAAS,EAC1BD,EAAaH,EAAuB,IAAIK,CAAG,EAC7CF,GAAc,MAAQ,CAACD,EAAgB,IAAIC,CAAU,GACvDF,EAAcG,CAAS,EAAID,EAC3BD,EAAgB,IAAIC,CAAU,GAE9BF,EAAcG,CAAS,EAAI,IAE/B,CAEA,GAAIT,EAAQ,eAAiB,GAAM,CACjC,IAAMW,EAAkBR,EAAiB,OAAQS,GAAMN,EAAcM,CAAC,GAAK,IAAI,EACzEC,EAAmBT,EAAY,OAAQF,GAAM,CAACK,EAAgB,IAAIL,CAAC,CAAC,EACpEY,EAAYd,EAAQ,gBAAkB,GACtCe,EAAeC,GAAWH,EAAkBF,EAAiB,CAAE,UAAAG,CAAU,CAAC,EAChF,OAAW,CAAE,IAAAJ,EAAK,cAAAO,CAAc,IAAKF,EAC/BE,GAAiB,MAAQ,CAACV,EAAgB,IAAIU,CAAa,IAC7DX,EAAcI,CAAG,EAAIO,EACrBV,EAAgB,IAAIU,CAAa,EAGvC,CAEA,IAAMC,EAA+B,CAAC,EACtC,QAAWT,KAAaN,EAEtB,GADcG,EAAcG,CAAS,GACxB,KAAM,CAEjB,IAAMU,EADQrB,EAAY,OAAOW,CAAS,GAClB,WAAa,GACrCS,EAAW,KAAK,CACd,SAAUT,EACV,MAAO,KACP,QAAS,WAAWA,CAAS,sBAC7B,SAAAU,CACF,CAAC,CACH,CAGF,MAAO,CAAE,cAAAb,EAAe,WAAAY,CAAW,CACrC,CCnEO,SAASE,EACdC,EACAC,EACAC,EAA0B,CAAC,EAC3BC,EACkB,CAClB,IAAMC,EAAmB,OAAO,KAAKH,EAAY,MAAM,EACjDI,EAAcF,GAAU,aAAa,OACtCA,EAAS,YACVC,EACEE,EAAmBH,GAAU,kBAAoB,CAAC,EAElD,CAAE,cAAAI,EAAe,WAAAC,CAAW,EAAIC,GACpCT,EACAC,EACAK,EACAJ,CACF,EAKMQ,EAHqBN,EAAiB,OACzCO,GAAMV,EAAY,OAAOU,CAAC,GAAG,WAAa,EAC7C,EAC8C,MAAOA,GAAMJ,EAAcI,CAAC,GAAK,IAAI,EAGnF,GAFmBH,EAAW,SAAW,GAEvBE,EAEhB,MAAO,CAAE,KAAM,UAAW,MADZE,GAAoBZ,EAAUC,EAAaI,EAAaE,CAAa,CACnD,EAGlC,IAAMM,EAAcL,EAAW,KAAM,GAAM,EAAE,WAAa,EAAI,EAC9D,MAAO,CACL,KAAM,WACN,aAAc,CAAC,GAAGR,EAAS,OAAO,EAClC,WAAAQ,EACA,YAAa,CAAC,GAAGH,CAAW,EAC5B,iBAAkB,CAAE,GAAGC,CAAiB,EACxC,YAAAO,CACF,CACF,CJhDO,SAASC,GAAa,CAC3B,IAAMC,EAAMC,EAAmB,EACzB,CAAE,QAAAC,EAAS,OAAAC,EAAQ,eAAAC,EAAgB,kBAAAC,EAAmB,kBAAAC,EAAmB,qBAAAC,CAAqB,EAAIP,EAElGQ,EAAUC,EACbC,GAA6B,CAC5B,GAAI,CAACR,GAAW,CAACC,EAAQ,OACzB,IAAMQ,EAASC,EAAWV,EAASC,EAAQO,EAASL,GAAqB,MAAS,EAC9EM,EAAO,OAAS,UAClBL,EAAkBK,EAAO,KAAK,EAE9BJ,EAAqB,CACnB,aAAcI,EAAO,aACrB,WAAYA,EAAO,WACnB,YAAaA,EAAO,YACpB,iBAAkBA,EAAO,gBAC3B,CAAC,CAEL,EACA,CAACT,EAASC,EAAQE,EAAmBC,EAAmBC,CAAoB,CAC9E,EAEMM,EAAmBJ,EAAY,IAA4C,CAC/E,GAAI,CAACP,GAAW,CAACC,GAAU,CAACE,EAAmB,OAC/C,IAAMM,EAASC,EAAWV,EAASC,EAAQ,CAAC,EAAG,CAC7C,YAAaE,EAAkB,YAC/B,iBAAkBA,EAAkB,gBACtC,CAAC,EACD,OAAIM,EAAO,OAAS,WAClBL,EAAkBK,EAAO,KAAK,EACvB,CAAE,KAAM,UAAW,MAAOA,EAAO,KAAM,IAEhDJ,EAAqB,CACnB,aAAcI,EAAO,aACrB,WAAYA,EAAO,WACnB,YAAaA,EAAO,YACpB,iBAAkBA,EAAO,gBAC3B,CAAC,EACM,CAAE,KAAM,WAAY,OAAAA,CAAO,EACpC,EAAG,CAACT,EAASC,EAAQE,EAAmBC,EAAmBC,CAAoB,CAAC,EAE1EO,EAAiBL,EACpBM,GAAyB,CACxBR,EAAsBS,GACpBA,GAAO,CAAE,GAAGA,EAAM,YAAaD,CAAW,CAC5C,CACF,EACA,CAACR,CAAoB,CACvB,EAEMU,EAAeR,EACnB,CAACS,EAAoBC,IAA4B,CAC/CZ,EAAsBS,GACpBA,GACI,CACE,GAAGA,EACH,iBAAkB,CAAE,GAAGA,EAAK,iBAAkB,CAACE,CAAU,EAAGC,CAAgB,CAC9E,CAEN,CACF,EACA,CAACZ,CAAoB,CACvB,EAEMa,EAAsCC,GAAQ,IAC7ChB,EACE,CACL,KAAM,WACN,aAAcA,EAAkB,aAChC,WAAYA,EAAkB,WAC9B,YAAa,CAAC,GAAGA,EAAkB,WAAW,EAC9C,iBAAkB,CAAE,GAAGA,EAAkB,gBAAiB,EAC1D,eAAAS,EACA,aAAAG,EACA,aAAc,IACZJ,EAAiB,GAAK,CACpB,KAAM,WACN,OAAQ,CAAE,GAAGR,EAAmB,KAAM,UAAoB,CAC5D,CACJ,EAd+B,KAe9B,CAACA,EAAmBS,EAAgBG,EAAcJ,CAAgB,CAAC,EAEtE,OAAOQ,GACL,KAAO,CACL,QAAAb,EACA,eAAAJ,EACA,cAAAgB,CACF,GACA,CAACZ,EAASJ,EAAgBgB,CAAa,CACzC,CACF,CKhGA,OAAS,WAAAE,OAAe,QAGjB,SAASC,IAAoB,CAClC,IAAMC,EAAMC,EAAmB,EAC/B,OAAOC,GACL,KAAO,CACL,OAAQF,EAAI,OACZ,oBAAqBA,EAAI,mBAC3B,GACA,CAACA,EAAI,OAAQA,EAAI,mBAAmB,CACtC,CACF,CCZA,OAAS,eAAAG,GAAa,WAAAC,OAAe,QAQ9B,SAASC,IAAe,CAE7B,IAAMC,EADMC,EAAmB,EACb,OACZC,EAASC,GAAQ,IAChBH,EACE,CAAC,GAAGA,EAAM,MAAM,EADJ,CAAC,EAEnB,CAACA,CAAK,CAAC,EACJI,EAAYC,GACZC,GACGN,EACEO,GAAmBP,EAAM,KAAMM,CAAM,EADzB,CAAC,EAGtB,CAACN,CAAK,CACR,EACMQ,EAAsBH,GACzBI,GACQC,EAAyBV,EAAOS,CAAM,EAE/C,CAACT,CAAK,CACR,EACA,OAAOG,GACL,KAAO,CAAE,MAAAH,EAAO,OAAAE,EAAQ,UAAAE,EAAW,oBAAAI,CAAoB,GACvD,CAACR,EAAOE,EAAQE,EAAWI,CAAmB,CAChD,CACF,CChCA,OAAS,eAAAG,GAAa,WAAAC,GAAS,UAAAC,OAAc,QCA7C,OAAS,eAAAC,GAAa,aAAAC,GAAW,UAAAC,GAAQ,YAAAC,OAAgB,QACzD,UAAYC,OAAa,UCDlB,SAASC,IAA2B,CACzC,OAAO,IAAI,IAAI,mBAAoB,YAAY,GAAG,EAAE,IACtD,CDmBO,SAASC,IAAgB,CAC9B,GAAM,CAACC,EAAaC,CAAc,EAAIC,GAA+C,IAAI,EACnFC,EAAYC,GAAsB,IAAI,EAE5C,OAAAC,GAAU,IAAM,CACd,IAAMC,EAAS,IAAI,OAAOC,GAAiB,EAAG,CAAE,KAAM,QAAS,CAAC,EAChEJ,EAAU,QAAUG,EACpB,IAAME,EAAgB,QAAoBF,CAAM,EAChD,sBAAe,IAAML,EAAeO,CAAK,CAAC,EACnC,IAAM,CACXF,EAAO,UAAU,EACjBH,EAAU,QAAU,IACtB,CACF,EAAG,CAAC,CAAC,EAwBE,CAAE,QAtBOM,GACd,MACEC,EACAC,EACAC,EACAC,EACAC,EACAC,IACmB,CACnB,GAAI,CAACf,EAAa,MAAM,IAAI,MAAM,uBAAuB,EACzD,OAAOA,EAAY,QACjBU,EACAC,EACAC,EACAC,EACAC,EACAC,GAAW,CAAC,CACd,CACF,EACA,CAACf,CAAW,CACd,EAEkB,QAAS,CAAC,CAACA,CAAY,CAC3C,CExDO,SAASgB,GACdC,EACAC,EACAC,EAC+B,CAC/B,OAAOC,GAA2BH,EAAM,KAAMC,EAAMC,CAAQ,CAC9D,CAEO,SAASC,GACdC,EACAH,EACAC,EACuB,CACvB,IAAMG,EAAaD,EAAK,OAClBE,EACJJ,GAAY,EAAI,EAAI,KAAK,IAAI,EAAG,KAAK,KAAKG,EAAaH,CAAQ,CAAC,EAC5DK,EAAW,KAAK,IAAI,EAAG,KAAK,IAAIN,EAAMK,CAAU,CAAC,EACjDE,GAASD,EAAW,GAAKL,EACzBO,EAAM,KAAK,IAAID,EAAQN,EAAUG,CAAU,EAC3CK,EAAQN,EAAK,MAAMI,EAAOC,CAAG,EACnC,MAAO,CACL,KAAMF,EACN,SAAAL,EACA,WAAAG,EACA,WAAAC,EACA,KAAMI,CACR,CACF,CHbO,SAASC,EAAeC,EAAiC,CAAC,EAAG,CAClE,GAAM,CACJ,OAAQC,EACR,UAAAC,EACA,OAAAC,EACA,UAAAC,EACA,kBAAAC,EACA,WAAAC,CACF,EAAIC,EAAmB,EACjB,CAAE,QAAAC,EAAS,QAAAC,CAAQ,EAAIC,GAAc,EACrCC,EAAU,CAACL,EACX,CAAE,KAAAM,EAAO,EAAG,SAAAC,EAAW,GAAI,WAAAC,CAAW,EAAId,EAC1Ce,EAAcC,GAA6C,IAAI,EAE/DC,EAAWC,GAAQ,IAClBjB,EAGEkB,GAAmBlB,EAAOW,EAAMC,CAAQ,EAFtC,CAAE,KAAM,EAAG,SAAAA,EAAU,WAAY,EAAG,WAAY,EAAG,KAAM,CAAC,CAAE,EAGpE,CAACZ,EAAOW,EAAMC,CAAQ,CAAC,EAEpBO,EAAaH,EAAS,WAEtBI,EAAYC,GACfC,GAA2B,CAC1B,GAAI,CAACtB,GAAS,CAACE,GAAUG,EAAY,OAAO,QAAQ,QAAQ,EAC5D,IAAMkB,EACJC,EAAcxB,EAAOsB,EAAO,QAAQ,GACpCG,GAAaD,EAAcxB,EAAOsB,EAAO,QAAQ,EAAIA,EAAO,OAAO,GAAG,MACxE,OAAOf,EAAQP,EAAOE,EAAQoB,EAAO,SAAUA,EAAO,QAASA,EAAO,KAAK,EAAE,KAC1EI,GAAa,CACZzB,EAAUyB,CAAQ,EAClB,eAAe,IAAM,CACnB,IAAMC,EAAwB,CAC5B,KAAM,YACN,SAAUL,EAAO,SACjB,QAASA,EAAO,QAChB,MAAOA,EAAO,MACd,cAAAC,EACA,UAAW,KAAK,IAAI,CACtB,EACAnB,EAAkBuB,CAAK,CACzB,CAAC,CACH,CACF,CACF,EACA,CAAC3B,EAAOE,EAAQG,EAAYE,EAASN,EAAWG,CAAiB,CACnE,EAEMwB,EAAWP,GACdC,GAAiD,CAChD,GAAIT,GAAc,MAAQA,EAAa,EAAG,CACpCC,EAAY,SAAS,aAAaA,EAAY,OAAO,EACzDA,EAAY,QAAU,WAAW,IAAM,CACrCA,EAAY,QAAU,KACtBM,EAAUE,CAAM,CAClB,EAAGT,CAAU,EACb,MACF,CACA,OAAOO,EAAUE,CAAM,CACzB,EACA,CAACT,EAAYO,CAAS,CACxB,EAEMS,EAAYR,GACfS,GAA2B,CAC1B,GAAI,CAAC9B,GAASK,EAAY,OAC1B,IAAMqB,EAAWG,GAAe7B,EAAO8B,CAAQ,EAC/C7B,EAAUyB,CAAQ,EAClB,eAAe,IAAM,CACnB,IAAMC,EAAwB,CAC5B,KAAM,aACN,SAAAG,EACA,UAAW,KAAK,IAAI,CACtB,EACA1B,EAAkBuB,CAAK,CACzB,CAAC,CACH,EACA,CAAC3B,EAAOK,EAAYJ,EAAWG,CAAiB,CAClD,EAEM2B,EAAkBd,GAAQ,IAAMe,EAAsB7B,CAAS,EAAG,CAACA,CAAS,CAAC,EAEnF,OAAOc,GACL,KAAO,CACL,MAAAjB,EACA,SAAA4B,EACA,UAAAC,EACA,SAAAb,EACA,WAAAG,EACA,QAAAX,EACA,QAAAE,EACA,UAAAP,EACA,gBAAA4B,CACF,GACA,CAAC/B,EAAO4B,EAAUC,EAAWb,EAAUG,EAAYX,EAASE,EAASP,EAAW4B,CAAe,CACjG,CACF,CIlHA,OAAS,eAAAE,EAAa,WAAAC,EAAS,YAAAC,OAAgB,QCM/C,SAASC,GAAeC,EAAeC,EAA2B,CAGhE,OADED,EAAM,SAASC,CAAS,GAAKD,EAAM,SAAS,GAAG,GAAKA,EAAM,SAAS;AAAA,CAAI,GAAKA,EAAM,SAAS,IAAI,EAE1F,IAAMA,EAAM,QAAQ,KAAM,IAAI,EAAI,IADhBA,CAE3B,CAEA,SAASE,GAAkBF,EAAgBG,EAA8B,CACvE,OAAIH,GAAU,KAAoC,GAC9CA,aAAiB,KAAaG,EAAcH,EAAM,eAAe,EAAIA,EAAM,YAAY,EACpF,OAAOA,CAAK,CACrB,CAEO,SAASI,GACdC,EACAC,EACAC,EAAyB,CAAC,EAClB,CACR,GAAM,CACJ,eAAAC,EAAiB,GACjB,aAAAC,EAAe,IACf,qBAAAC,EAAuB,EACzB,EAAIH,EACEI,EACJL,GAAe,KAAO,OAAO,KAAKA,EAAY,MAAM,EAAI,CAAC,EACrDM,EACJD,EAAW,OAAS,EAChBA,EACCN,EAAM,KAAK,CAAC,GAAG,MAAM,IAAKQ,GAAMA,EAAE,GAAG,GAAKR,EAAM,QAAQ,MAAM,EAE/DS,EAAkB,CAAC,EACrBN,GAAkBI,EAAe,OAAS,GAC5CE,EAAM,KAAKF,EAAe,IAAKG,GAAMhB,GAAegB,EAAGN,CAAY,CAAC,EAAE,KAAKA,CAAY,CAAC,EAE1F,QAAWO,KAAOX,EAAM,KAAM,CAC5B,IAAMY,EAASL,EAAe,IAAKM,GAAQ,CAEzC,IAAMC,EADOH,EAAI,MAAM,KAAMH,GAAMA,EAAE,MAAQK,CAAG,GAC9B,OAAS,GAC3B,OAAOnB,GAAeG,GAAkBiB,EAAKT,CAAoB,EAAGD,CAAY,CAClF,CAAC,EACDK,EAAM,KAAKG,EAAO,KAAKR,CAAY,CAAC,CACtC,CAEA,MAAO,SADMK,EAAM,KAAK;AAAA,CAAM,CAEhC,CC9CA,SAASM,GAAgBC,EAAgBC,EAA+B,CACtE,OAAID,GAAU,KAAoC,KAC9CA,aAAiB,KAAaC,EAAcD,EAAM,eAAe,EAAIA,EAAM,YAAY,EACpFA,CACT,CAEO,SAASE,GACdC,EACAC,EACAC,EAAyB,CAAC,EAClB,CACR,GAAM,CAAE,qBAAAC,EAAuB,EAAM,EAAID,EACnCE,EAAOJ,EAAM,KAAK,IAAKK,GAAQ,CACnC,IAAMC,EAA+B,CAAC,EACtC,QAAWC,KAAQF,EAAI,MACrBC,EAAIC,EAAK,GAAG,EAAIX,GAAgBW,EAAK,MAAOJ,CAAoB,EAElE,OAAOG,CACT,CAAC,EACD,OAAO,KAAK,UAAUF,EAAM,KAAM,CAAC,CACrC,CFbO,SAASI,GAAaC,EAA+B,CAAC,EAAqC,CAChG,GAAM,CAAE,KAAMC,EAAc,EAAG,gBAAAC,EAAkB,GAAI,WAAAC,EAAa,KAAM,EAAIH,EACtE,CAACI,EAAMC,CAAO,EAAIC,GAASL,CAAW,EACtCM,EAAWL,EACX,CAAE,MAAAM,EAAO,SAAAC,EAAU,UAAAC,EAAW,UAAAC,EAAW,gBAAAC,CAAgB,EAAIC,EAAe,CAAC,CAAC,EAC9EC,EAAMC,EAAmB,EAEzBC,EAAiBC,EAAQ,IAAOT,EAAQU,EAAkBV,CAAK,EAAI,CAAC,EAAI,CAACA,CAAK,CAAC,EAC/EW,EAAaF,EACjB,IAAOd,IAAe,cAAgBa,EAAkBR,GAAO,MAAQ,CAAC,EACxE,CAACL,EAAYa,EAAgBR,CAAK,CACpC,EACMY,EAAYD,EAAW,OAEvBE,EAAqBC,EACzB,CAACC,EAAYC,IAGJC,GAA2BN,EAFvBI,GAAKnB,EACJoB,GAAMjB,CACmC,EAEvD,CAACH,EAAMG,EAAUY,CAAU,CAC7B,EACMO,EAAgBT,EACpB,IAAMI,EAAmBjB,EAAMG,CAAQ,EAAE,KACzC,CAACc,EAAoBjB,EAAMG,CAAQ,CACrC,EACMoB,EAAUL,EACd,CAAClB,EAAcwB,IAAkB,CAE/B,IAAMC,GAASzB,EAAO,GAAKwB,EAC3B,OAAOT,EAAW,MAAMU,EAAOA,EAAQD,CAAK,CAC9C,EACA,CAACT,CAAU,CACb,EACMW,EAASb,EACb,IAAOT,EAAQuB,EAAcvB,CAAK,EAAI,CAAE,UAAW,EAAG,eAAgB,EAAG,YAAa,CAAE,EACxF,CAACA,CAAK,CACR,EAEMwB,EAAcV,EACjBW,GACK,CAACzB,GAAS,CAACM,EAAI,OAAe,GAC3BoB,GAAW1B,EAAOM,EAAI,OAAQmB,GAAQ,CAAC,CAAC,EAEjD,CAACzB,EAAOM,EAAI,MAAM,CACpB,EACMqB,EAAeb,EAClBW,GACMzB,EACE4B,GAAY5B,EAAOM,EAAI,QAAU,KAAMmB,GAAQ,CAAC,CAAC,EADrC,KAGrB,CAACzB,EAAOM,EAAI,MAAM,CACpB,EAEMuB,EAAcf,EAClB,MAAOW,GAA4D,CACjE,IAAMK,EAAUN,EAAYC,CAAI,EAChC,GAAI,CAACK,EAAS,OACd,IAAMC,EAAO,IAAI,KAAK,CAACD,CAAO,EAAG,CAAE,KAAM,wBAAyB,CAAC,EAC7DE,EAAM,IAAI,gBAAgBD,CAAI,EAC9BE,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,KAAOD,EACTC,EAAE,UAAYR,GAAM,UAAY,UAAY,OAC5CQ,EAAE,MAAM,EACR,IAAI,gBAAgBD,CAAG,CACzB,EACA,CAACR,CAAW,CACd,EACMU,EAAepB,EACnB,MAAOW,GAA6D,CAClE,IAAMK,EAAUH,EAAaF,CAAI,EAC3BM,EAAO,IAAI,KAAK,CAACD,CAAO,EAAG,CAAE,KAAM,kBAAmB,CAAC,EACvDE,EAAM,IAAI,gBAAgBD,CAAI,EAC9BE,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,KAAOD,EACTC,EAAE,UAAYR,GAAM,UAAY,UAAY,QAC5CQ,EAAE,MAAM,EACR,IAAI,gBAAgBD,CAAG,CACzB,EACA,CAACL,CAAY,CACf,EAEA,OAAOlB,EACL,KAAO,CACL,MAAAT,EACA,mBAAAa,EACA,cAAAK,EACA,KAAAtB,EACA,QAAAC,EACA,SAAAE,EACA,UAAAa,EACA,QAAAO,EACA,eAAAX,EACA,OAAAc,EACA,SAAArB,EACA,UAAAC,EACA,UAAAC,EACA,gBAAAC,EACA,YAAAoB,EACA,aAAAG,EACA,YAAAE,EACA,aAAAK,EACA,sBAAuB5B,EAAI,sBAC3B,eAAgBA,EAAI,eACpB,oBAAqBA,EAAI,mBAC3B,GACA,CACEN,EACAa,EACAK,EACAtB,EACAG,EACAa,EACAO,EACAX,EACAc,EACArB,EACAC,EACAC,EACAC,EACAoB,EACAG,EACAE,EACAK,EACA5B,EAAI,sBACJA,EAAI,eACJA,EAAI,mBACN,CACF,CACF,CG5IA,OAAS,eAAA6B,GAAa,aAAAC,OAAiB,QAKhC,SAASC,IAAyB,CAEvC,IAAMC,EADMC,EAAmB,EACZ,oBAEbC,EAAsBC,GACzBC,GAAuD,CACtD,IAAMC,EAAWC,GAAa,CAC5BF,EAAUE,EAA0C,MAAM,CAC5D,EACA,OAAAN,EAAO,iBAAiBO,EAAyBF,CAAO,EACjD,IAAM,CACXL,EAAO,oBAAoBO,EAAyBF,CAAO,CAC7D,CACF,EACA,CAACL,CAAM,CACT,EAEA,MAAO,CAAE,oBAAqBA,EAAQ,oBAAAE,CAAoB,CAC5D,CAEO,SAASM,GACdJ,EACA,CACA,GAAM,CAAE,oBAAAF,CAAoB,EAAIH,GAAuB,EACvDU,GAAU,IACDP,EAAoBE,CAAQ,EAClC,CAACF,EAAqBE,CAAQ,CAAC,CACpC","names":["useEffect","useMemo","useRef","useState","PERSIST_STORE_NAME","DEFAULT_PERSIST_KEY","createContext","ImporterContext","initialState","useCallback","useMemo","formatMs","ms","buildPipelineMetrics","timings","rowCount","overheadMs","totalMs","isSlow","efficiency","percentages","overhead","totalWithOverhead","formatChangeLogAsText","entries","lines","e","prev","IMPORTER_PROGRESS_EVENT","IMPORTER_ABORTED_EVENT","useCallback","useImporterStateSetters","deps","setState","setLayoutState","setEngineState","setFile","file","prev","setRawData","rawData","setDocumentHash","documentHash","setStatus","status","setResult","result","setConvertedSheet","convertedSheet","setSanitizedSheet","sanitizedSheet","setConvertResultData","dataOrUpdater","setMetrics","metrics","setSubmitDone","submitDone","setLayout","next","setEngine","INITIAL_PHASE_TIMINGS","useImporterActions","deps","setState","setLayoutState","setEngineState","progressEventTarget","validatorRegistry","sanitizerRegistry","transformRegistry","activeWorkerRef","phaseTimingsRef","stateSetters","useImporterStateSetters","dispatchProgress","useCallback","detail","IMPORTER_PROGRESS_EVENT","setActiveWorker","worker","abort","prev","IMPORTER_ABORTED_EVENT","setPhaseTiming","phase","ms","finalizeMetrics","rowCount","timings","metrics","buildPipelineMetrics","addChangeLogEntry","entry","processFile","file","registerValidator","name","fn","options","registerSanitizer","registerTransform","useMemo","useCallback","useEffect","useRef","useState","openDb","resolve","reject","req","PERSIST_STORE_NAME","savePersistedState","key","state","db","tx","store","record","loadPersistedState","row","savedAt","_k","clearPersistedState","DEBOUNCE_MS","usePersistSession","persist","persistKey","rawData","result","setRawData","setResult","layoutVersion","recoverableSession","setRecoverableSession","useState","debounceRef","useRef","useEffect","loadPersistedState","state","payload","savePersistedState","recoverSession","useCallback","clearPersistedState","useCallback","useEffect","useCallback","useEffect","useRef","useState","Comlink","getParserWorkerUrl","useParserWorker","setActiveWorker","dispatchProgress","useImporterContext","workerProxy","setWorkerProxy","useState","workerRef","useRef","useEffect","worker","getParserWorkerUrl","proxy","load","useCallback","blob","options","parseAll","onProgress","progressProxy","firstSheetFromResult","result","names","useImportSheet","ctx","useImporterContext","load","parseAll","isReady","useParserWorker","useEffect","file","status","engine","sheet","useCallback","t0","detail","t1","jsx","jsxs","ImporterOrchestrator","useImportSheet","ImporterProvider","children","layoutProp","engineProp","persist","persistKey","DEFAULT_PERSIST_KEY","onSubmit","submitKeyMap","state","setState","useState","initialState","layout","setLayoutState","engine","setEngineState","progressEventTarget","useMemo","validatorRegistry","Registry","sanitizerRegistry","transformRegistry","activeWorkerRef","useRef","phaseTimingsRef","stateSetters","useImporterStateSetters","persistSession","usePersistSession","actions","useImporterActions","useEffect","worker","value","ImporterContext","useContext","useImporterContext","context","useContext","ImporterContext","useCallback","useEffect","useMemo","getRowsWithErrors","sheet","row","hasValidationErrors","sheet","getViewCounts","totalRows","rowsWithErrors","getRowsWithErrors","totalErrors","sum","row","c","cell","getCellValue","row","key","c","sheetRowsToObjects","rows","mapRow","sheetToObjectsWithKeyMap","sheet","keyMap","obj","sheetKey","outputKey","rowsToLayoutObjects","sheet","row","acc","c","useImporter","options","ctx","useImporterContext","layoutOption","engineOption","useEffect","canSubmit","useMemo","hasValidationErrors","submit","useCallback","data","sheetToObjectsWithKeyMap","useCallback","useMemo","buildConvertedSheet","rawSheet","_sheetLayout","columnOrder","fieldToHeader","headers","headerIndex","h","i","rows","row","cells","fieldName","fileHeader","value","idx","normalize","s","levenshteinDistance","a","b","prev","_","i","curr","j","cost","getSimilarity","s1","s2","longer","shorter","distance","DEFAULT_FUZZY_THRESHOLD","mapHeaders","rawHeaders","expectedKeys","options","threshold","keyScores","key","header","score","x","y","assignedKeys","assignedHeaders","keyToHeader","k","defaultNormalize","header","caseSensitive","trimmed","matchHeadersToLayout","rawSheet","sheetLayout","headerToFieldMap","options","normalizer","h","layoutFieldNames","fileHeaders","normalizedToFileHeader","fieldToHeader","usedFileHeaders","fileHeader","fieldName","key","unmatchedFields","f","availableHeaders","threshold","fuzzyResults","mapHeaders","matchedHeader","mismatches","required","runConvert","rawSheet","sheetLayout","options","existing","layoutFieldNames","columnOrder","headerToFieldMap","fieldToHeader","mismatches","matchHeadersToLayout","allRequiredMatched","f","buildConvertedSheet","layoutError","useConvert","ctx","useImporterContext","rawData","layout","convertedSheet","convertResultData","setConvertedSheet","setConvertResultData","convert","useCallback","options","result","runConvert","applyMappingImpl","reorderColumns","fieldNames","prev","renameColumn","fileHeader","layoutFieldName","convertResult","useMemo","useMemo","useImporterStatus","ctx","useImporterContext","useMemo","useCallback","useMemo","useSheetData","sheet","useImporterContext","errors","useMemo","toObjects","useCallback","mapRow","sheetRowsToObjects","toObjectsWithKeyMap","keyMap","sheetToObjectsWithKeyMap","useCallback","useMemo","useRef","useCallback","useEffect","useRef","useState","Comlink","getEditWorkerUrl","useEditWorker","workerProxy","setWorkerProxy","useState","workerRef","useRef","useEffect","worker","getEditWorkerUrl","proxy","useCallback","sheet","sheetLayout","rowIndex","cellKey","value","options","getPaginatedResult","sheet","page","pageSize","getPaginatedResultFromRows","rows","totalCount","totalPages","safePage","start","end","slice","useSheetEditor","options","sheet","setResult","layout","changeLog","addChangeLogEntry","submitDone","useImporterContext","runEdit","isReady","useEditWorker","canEdit","page","pageSize","debounceMs","debounceRef","useRef","pageData","useMemo","getPaginatedResult","totalPages","applyEdit","useCallback","params","previousValue","getRowByIndex","getCellByKey","newSheet","entry","editCell","removeRow","rowIndex","changeLogAsText","formatChangeLogAsText","useCallback","useMemo","useState","escapeCsvValue","value","separator","cellValueToString","formatDates","sheetToCSV","sheet","sheetLayout","options","includeHeaders","csvSeparator","formatDatesForExport","fieldOrder","effectiveOrder","c","lines","h","row","values","key","raw","cellValueToJson","value","formatDates","sheetToJSON","sheet","_sheetLayout","options","formatDatesForExport","rows","row","obj","cell","useSheetView","options","initialPage","defaultPageSize","filterMode","page","setPage","useState","pageSize","sheet","editCell","removeRow","changeLog","changeLogAsText","useSheetEditor","ctx","useImporterContext","rowsWithErrors","useMemo","getRowsWithErrors","sourceRows","totalRows","getPaginatedResult","useCallback","p","ps","getPaginatedResultFromRows","paginatedRows","getRows","limit","start","counts","getViewCounts","exportToCSV","opts","sheetToCSV","exportToJSON","sheetToJSON","downloadCSV","content","blob","url","a","downloadJSON","useCallback","useEffect","useImporterEventTarget","target","useImporterContext","subscribeToProgress","useCallback","callback","handler","e","IMPORTER_PROGRESS_EVENT","useImporterProgressSubscription","useEffect"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cristianmpx/react-import-sheet-headless",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Headless component for React Import Sheet",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -23,7 +23,11 @@
23
23
  "lint": "eslint .",
24
24
  "publish": "npm run test && npm run build && npm publish --access public",
25
25
  "prepare": "husky",
26
- "commit": "cz"
26
+ "commit": "cz",
27
+ "verify": "node scripts/verify-package.js",
28
+ "diagnose": "node scripts/diagnose-installation.js",
29
+ "prebuild": "node scripts/verify-package.js || true",
30
+ "postbuild": "node scripts/verify-package.js"
27
31
  },
28
32
  "config": {
29
33
  "commitizen": {
@@ -64,10 +68,23 @@
64
68
  "react",
65
69
  "import",
66
70
  "sheet",
67
- "headless"
71
+ "headless",
72
+ "csv",
73
+ "excel",
74
+ "xlsx",
75
+ "validation",
76
+ "web-workers"
68
77
  ],
69
78
  "author": "Cristian Marin",
70
79
  "license": "MIT",
80
+ "repository": {
81
+ "type": "git",
82
+ "url": "https://github.com/cristianm-developer/react-import-sheet-headless.git"
83
+ },
84
+ "bugs": {
85
+ "url": "https://github.com/cristianm-developer/react-import-sheet-headless/issues"
86
+ },
87
+ "homepage": "https://github.com/cristianm-developer/react-import-sheet-headless#readme",
71
88
  "lint-staged": {
72
89
  "src/**/*.{ts,tsx,js,jsx}": [
73
90
  "eslint --fix",