spectraview 1.8.1 → 1.8.2

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/CHANGELOG.md CHANGED
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
+ ## [1.8.2] — 2026-02-26
9
+
10
+ ### Added
11
+
12
+ - ESLint 9 flat config with TypeScript, React, and React Hooks rules
13
+ - Test coverage reporting in CI with PR comments and dynamic badge
14
+ - Tests for StackedView (8), useExport (9), useResizeObserver (8) — 25 new tests
15
+ - Coverage badge in README
16
+
17
+ ### Fixed
18
+
19
+ - `Tooltip.tsx`: React rules-of-hooks violation (early return before useMemo)
20
+ - `spc.ts`: `let` → `const` for single-assignment variable
21
+ - README: `pip install spectrakit` → `pip install pyspectrakit`
22
+
8
23
  ## [1.8.1] — 2026-02-26
9
24
 
10
25
  ### Added
package/README.md CHANGED
@@ -7,6 +7,7 @@ Interactive React component for vibrational spectroscopy (IR, Raman, NIR).
7
7
  [![bundle size](https://img.shields.io/bundlephobia/minzip/spectraview)](https://bundlephobia.com/package/spectraview)
8
8
  [![license](https://img.shields.io/npm/l/spectraview)](https://github.com/ktubhyam/spectraview/blob/main/LICENSE)
9
9
  [![CI](https://img.shields.io/github/actions/workflow/status/ktubhyam/spectraview/ci.yml?branch=main)](https://github.com/ktubhyam/spectraview/actions)
10
+ [![coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/ktubhyam/spectraview/coverage-badges/coverage.json)](https://github.com/ktubhyam/spectraview/actions/workflows/ci.yml)
10
11
  [![Storybook](https://img.shields.io/badge/storybook-deployed-ff4785)](https://ktubhyam.github.io/spectraview/)
11
12
 
12
13
  ## Features
@@ -297,7 +298,7 @@ SpectraView pairs with [SpectraKit](https://github.com/ktubhyam/spectrakit), a P
297
298
  - **SpectraView** — View spectra: interactive visualization in the browser
298
299
 
299
300
  ```
300
- pip install spectrakit # Process in Python
301
+ pip install pyspectrakit # Process in Python
301
302
  npm install spectraview # View in the browser
302
303
  ```
303
304
 
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- "use strict";var st=Object.defineProperty;var Tr=Object.getOwnPropertyDescriptor;var Ar=Object.getOwnPropertyNames;var Er=Object.prototype.hasOwnProperty;var Lr=(e,t)=>{for(var r in t)st(e,r,{get:t[r],enumerable:!0})},Pr=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Ar(t))!Er.call(e,n)&&n!==r&&st(e,n,{get:()=>t[n],enumerable:!(o=Tr(t,n))||o.enumerable});return e};var Fr=e=>Pr(st({},"__esModule",{value:!0}),e);var hn={};Lr(hn,{AnnotationLayer:()=>Ee,AxisLayer:()=>se,Crosshair:()=>Ae,DARK_THEME:()=>mt,DataTable:()=>Zt,DropZone:()=>Fe,ExportMenu:()=>or,KEYBOARD_SHORTCUTS:()=>zt,LIGHT_THEME:()=>ut,LINE_DASH_PATTERNS:()=>gt,Legend:()=>fe,Minimap:()=>Bt,PeakMarkers:()=>Re,RegionSelector:()=>Te,SPECTRUM_COLORS:()=>Ce,SpectraView:()=>Vt,SpectrumCanvas:()=>ae,StackedView:()=>Ue,Toolbar:()=>Pe,Tooltip:()=>Ht,addSpectra:()=>ur,baselineRubberBand:()=>je,binarySearchClosest:()=>pe,computeXExtent:()=>ve,computeYExtent:()=>ne,correlationCoefficient:()=>pr,createXScale:()=>ke,createYScale:()=>oe,derivative1st:()=>qe,derivative2nd:()=>er,detectPeaks:()=>ze,differenceSpectrum:()=>cr,downloadString:()=>lr,downloadSvg:()=>Xe,generateChartDescription:()=>Oe,generateSvg:()=>_e,getSpectrumColor:()=>L,getThemeColors:()=>O,interpolateToGrid:()=>dr,lttbDownsample:()=>Me,multiSpectraToCsv:()=>ar,normalizeArea:()=>Ge,normalizeMinMax:()=>Ye,normalizeSNV:()=>Ke,parseCsv:()=>Ve,parseCsvMulti:()=>Yt,parseJcamp:()=>Ze,parseJson:()=>Be,parseSpc:()=>br,prefersReducedMotion:()=>Ot,residualSpectrum:()=>fr,scaleSpectrum:()=>mr,smoothSavitzkyGolay:()=>Je,snapToNearestSpectrum:()=>Le,spectrumToCsv:()=>ir,spectrumToJson:()=>sr,useExport:()=>Qt,useHistory:()=>nr,useKeyboardNavigation:()=>Ie,useNormalization:()=>rr,usePeakPicking:()=>Xt,useRegionSelect:()=>$e,useResizeObserver:()=>Ne,useSpectrumData:()=>qt,useZoomPan:()=>we});module.exports=Fr(hn);var T=require("react");var lt=require("d3-scale"),ct=require("d3-array"),Dr=.05;function ve(e){let t=1/0,r=-1/0;for(let o of e){if(o.visible===!1)continue;let[n,a]=(0,ct.extent)(o.x);n<t&&(t=n),a>r&&(r=a)}return isFinite(t)?[t,r]:[0,1]}function ne(e){let t=1/0,r=-1/0;for(let a of e){if(a.visible===!1)continue;let[s,i]=(0,ct.extent)(a.y);s<t&&(t=s),i>r&&(r=i)}if(!isFinite(t))return[0,1];let n=(r-t)*Dr;return[t-n,r+n]}function ke(e,t,r,o){let n=t-r.left-r.right,a=o?[e[1],e[0]]:e;return(0,lt.scaleLinear)().domain(a).range([0,n])}function oe(e,t,r){let o=t-r.top-r.bottom;return(0,lt.scaleLinear)().domain(e).range([o,0])}var Ce=["#2563eb","#dc2626","#16a34a","#9333ea","#ea580c","#0891b2","#be185d","#854d0e","#4f46e5","#65a30d"],ut={background:"#ffffff",axisColor:"#374151",gridColor:"#e5e7eb",tickColor:"#6b7280",labelColor:"#111827",crosshairColor:"#9ca3af",regionFill:"rgba(37, 99, 235, 0.1)",regionStroke:"rgba(37, 99, 235, 0.4)",tooltipBg:"#ffffff",tooltipBorder:"#d1d5db",tooltipText:"#111827"},mt={background:"#111827",axisColor:"#d1d5db",gridColor:"#374151",tickColor:"#9ca3af",labelColor:"#f9fafb",crosshairColor:"#6b7280",regionFill:"rgba(96, 165, 250, 0.15)",regionStroke:"rgba(96, 165, 250, 0.5)",tooltipBg:"#1f2937",tooltipBorder:"#4b5563",tooltipText:"#f9fafb"};function L(e){return Ce[e%Ce.length]}function O(e){return e==="dark"?mt:ut}var P=require("react"),ie=require("d3-zoom"),G=require("d3-selection"),vn=require("d3-transition"),Tt=1.5;function we(e){let{plotWidth:t,plotHeight:r,xScale:o,yScale:n,scaleExtent:a=[1,50],enabled:s=!0,onViewChange:i}=e,c=(0,P.useRef)(null),l=(0,P.useRef)(null),m=(0,P.useRef)(i);m.current=i;let p=(0,P.useRef)(a);p.current=a;let[f,u]=(0,P.useState)(ie.zoomIdentity),d=(0,P.useMemo)(()=>f.rescaleX(o.copy()),[f,o]),h=(0,P.useMemo)(()=>f.rescaleY(n.copy()),[f,n]);(0,P.useEffect)(()=>{let S=c.current;if(!S||!s)return;let v=(0,ie.zoom)().scaleExtent(p.current).extent([[0,0],[t,r]]).translateExtent([[-1/0,-1/0],[1/0,1/0]]).on("zoom",y=>{let k=y.transform;if(u(k),m.current){let C=k.rescaleX(o.copy()),w=k.rescaleY(n.copy());m.current(C.domain(),w.domain())}});return l.current=v,(0,G.select)(S).call(v),(0,G.select)(S).on("dblclick.zoom",()=>{(0,G.select)(S).transition().duration(300).call(v.transform,ie.zoomIdentity)}),()=>{(0,G.select)(S).on(".zoom",null)}},[t,r,s,o,n]);let g=(0,P.useCallback)(()=>{!c.current||!l.current||(0,G.select)(c.current).transition().duration(300).call(l.current.transform,ie.zoomIdentity)},[]),b=(0,P.useCallback)(()=>{!c.current||!l.current||(0,G.select)(c.current).transition().duration(200).call(l.current.scaleBy,Tt)},[]),x=(0,P.useCallback)(()=>{!c.current||!l.current||(0,G.select)(c.current).transition().duration(200).call(l.current.scaleBy,1/Tt)},[]);return{zoomRef:c,state:{transform:f,isZoomed:f.k!==1||f.x!==0||f.y!==0},zoomedXScale:d,zoomedYScale:h,resetZoom:g,zoomIn:b,zoomOut:x}}var z=require("react");function Me(e,t,r,o,n,a,s){let i=o-r;if(i<=s){let f=[];for(let u=r;u<o;u++)f.push({px:n(e[u]),py:a(t[u]),index:u});return f}let c=[];c.push({px:n(e[r]),py:a(t[r]),index:r});let l=s-2,m=(i-2)/l,p=r;for(let f=0;f<l;f++){let u=r+1+Math.floor(f*m),d=r+1+Math.min(Math.floor((f+1)*m),i-2),h=d,g=r+1+Math.min(Math.floor((f+2)*m),i-2),b,x;if(f===l-1)b=n(e[o-1]),x=a(t[o-1]);else{b=0,x=0;let C=g-h;for(let w=h;w<g;w++)b+=n(e[w]),x+=a(t[w]);C>0&&(b/=C,x/=C)}let S=n(e[p]),v=a(t[p]),y=-1,k=u;for(let C=u;C<d;C++){let w=n(e[C]),R=a(t[C]),E=Math.abs((S-b)*(R-v)-(S-w)*(x-v));E>y&&(y=E,k=C)}c.push({px:n(e[k]),py:a(t[k]),index:k}),p=k}return c.push({px:n(e[o-1]),py:a(t[o-1]),index:o-1}),c}var Ur=1.5,$r={solid:[],dashed:[8,4],dotted:[2,2],"dash-dot":[8,4,2,4]},Nr=2e3;function Ir(e,t,r){e.clearRect(0,0,t,r)}function Or(e,t,r,o,n,a,s){let{highlighted:i=!1,opacity:c=1}=s??{},l=Math.min(t.x.length,t.y.length);if(l<2)return;let m=t.color??L(r),p=t.lineWidth??Ur,f=i?p+1:p,u=$r[t.lineStyle??"solid"]??[],[d,h]=o.domain(),g=Math.min(d,h),b=Math.max(d,h),x=0,S=l;for(let y=0;y<l;y++)if(t.x[y]>=g||y<l-1&&t.x[y+1]>=g){x=Math.max(0,y-1);break}for(let y=l-1;y>=0;y--)if(t.x[y]<=b||y>0&&t.x[y-1]<=b){S=Math.min(l,y+2);break}let v=S-x;if(e.save(),e.beginPath(),e.strokeStyle=m,e.lineWidth=f,e.globalAlpha=c,e.lineJoin="round",e.setLineDash(u),v>Nr){let y=Math.max(Math.ceil(a*2),200),k=Me(t.x,t.y,x,S,o,n,y);if(k.length>0){e.moveTo(k[0].px,k[0].py);for(let C=1;C<k.length;C++)e.lineTo(k[C].px,k[C].py)}}else{let y=!1;for(let k=x;k<S;k++){let C=o(t.x[k]),w=n(t.y[k]);y?e.lineTo(C,w):(e.moveTo(C,w),y=!0)}}e.stroke(),e.restore()}function At(e,t,r,o,n,a,s){Ir(e,n,a),t.forEach((i,c)=>{i.visible!==!1&&Or(e,i,c,r,o,n,{highlighted:i.id===s,opacity:s&&i.id!==s?.3:1})})}var Et=require("react/jsx-runtime"),ae=(0,z.forwardRef)(function({spectra:t,xScale:r,yScale:o,width:n,height:a,highlightedId:s},i){let c=(0,z.useRef)(null),l=(0,z.useRef)(1);return(0,z.useImperativeHandle)(i,()=>c.current,[]),(0,z.useEffect)(()=>{let m=c.current;if(!m)return;let p=window.devicePixelRatio||1;l.current=p,m.width=n*p,m.height=a*p},[n,a]),(0,z.useEffect)(()=>{let m=c.current;if(!m)return;let p=m.getContext("2d");if(!p)return;let f=l.current;p.setTransform(f,0,0,f,0,0),At(p,t,r,o,n,a,s)},[t,r,o,n,a,s]),(0,Et.jsx)("canvas",{ref:c,style:{width:n,height:a,position:"absolute",top:0,left:0,pointerEvents:"none"}})});var A=require("react/jsx-runtime");function Lt(e,t){let[r,o]=e.domain(),n=Math.min(r,o),s=(Math.max(r,o)-n)/(t-1);return Array.from({length:t},(i,c)=>n+c*s)}function Pt(e){return Math.abs(e)>=1e3?Math.round(e).toString():Math.abs(e)>=1?e.toFixed(1):Math.abs(e)>=.01?e.toFixed(3):e.toExponential(1)}function se({xScale:e,yScale:t,width:r,height:o,xLabel:n,yLabel:a,showGrid:s=!0,colors:i}){let c=Lt(e,8),l=Lt(t,6);return(0,A.jsxs)("g",{children:[s&&(0,A.jsxs)("g",{children:[c.map(m=>(0,A.jsx)("line",{x1:e(m),x2:e(m),y1:0,y2:o,stroke:i.gridColor,strokeWidth:.5},`xgrid-${m}`)),l.map(m=>(0,A.jsx)("line",{x1:0,x2:r,y1:t(m),y2:t(m),stroke:i.gridColor,strokeWidth:.5},`ygrid-${m}`))]}),(0,A.jsxs)("g",{transform:`translate(0, ${o})`,children:[(0,A.jsx)("line",{x1:0,x2:r,y1:0,y2:0,stroke:i.axisColor}),c.map(m=>(0,A.jsxs)("g",{transform:`translate(${e(m)}, 0)`,children:[(0,A.jsx)("line",{y1:0,y2:6,stroke:i.axisColor}),(0,A.jsx)("text",{y:20,textAnchor:"middle",fill:i.tickColor,fontSize:11,fontFamily:"system-ui, sans-serif",children:Pt(m)})]},`xtick-${m}`)),n&&(0,A.jsx)("text",{x:r/2,y:42,textAnchor:"middle",fill:i.labelColor,fontSize:13,fontFamily:"system-ui, sans-serif",children:n})]}),(0,A.jsxs)("g",{children:[(0,A.jsx)("line",{x1:0,x2:0,y1:0,y2:o,stroke:i.axisColor}),l.map(m=>(0,A.jsxs)("g",{transform:`translate(0, ${t(m)})`,children:[(0,A.jsx)("line",{x1:-6,x2:0,stroke:i.axisColor}),(0,A.jsx)("text",{x:-10,textAnchor:"end",dominantBaseline:"middle",fill:i.tickColor,fontSize:11,fontFamily:"system-ui, sans-serif",children:Pt(m)})]},`ytick-${m}`)),a&&(0,A.jsx)("text",{transform:`translate(-50, ${o/2}) rotate(-90)`,textAnchor:"middle",fill:i.labelColor,fontSize:13,fontFamily:"system-ui, sans-serif",children:a})]})]})}var le=require("react/jsx-runtime");function Re({peaks:e,xScale:t,yScale:r,colors:o,onPeakClick:n}){let[a,s]=t.domain(),i=Math.min(a,s),c=Math.max(a,s),l=e.filter(m=>m.x>=i&&m.x<=c);return(0,le.jsx)("g",{className:"spectraview-peaks",children:l.map((m,p)=>{let f=t(m.x),u=r(m.y);return(0,le.jsxs)("g",{transform:`translate(${f}, ${u})`,style:{cursor:n?"pointer":"default"},onClick:()=>n?.(m),children:[(0,le.jsx)("polygon",{points:`0,-5 -5,${-5*2.5} 5,${-5*2.5}`,fill:o.labelColor,opacity:.8}),m.label&&(0,le.jsx)("text",{y:-5*2.5-14,textAnchor:"middle",fill:o.labelColor,fontSize:10,fontFamily:"system-ui, sans-serif",fontWeight:500,children:m.label})]},`peak-${m.x}-${p}`)})})}var ce=require("react/jsx-runtime");function Te({regions:e,xScale:t,height:r,colors:o}){return(0,ce.jsx)("g",{className:"spectraview-regions",children:e.map((n,a)=>{let s=t(n.xStart),i=t(n.xEnd),c=Math.min(s,i),l=Math.abs(i-s);return(0,ce.jsxs)("g",{children:[(0,ce.jsx)("rect",{x:c,y:0,width:l,height:r,fill:n.color??o.regionFill,stroke:o.regionStroke,strokeWidth:1}),n.label&&(0,ce.jsx)("text",{x:c+l/2,y:12,textAnchor:"middle",fill:o.labelColor,fontSize:10,fontFamily:"system-ui, sans-serif",children:n.label})]},`region-${a}`)})})}var H=require("react/jsx-runtime");function Ae({position:e,width:t,height:r,colors:o,snapPoint:n}){return e?(0,H.jsxs)("g",{className:"spectraview-crosshair",pointerEvents:"none",children:[(0,H.jsx)("line",{x1:e.px,x2:e.px,y1:0,y2:r,stroke:o.crosshairColor,strokeWidth:1,strokeDasharray:"4 4"}),(0,H.jsx)("line",{x1:0,x2:t,y1:e.py,y2:e.py,stroke:o.crosshairColor,strokeWidth:1,strokeDasharray:"4 4"}),n&&(0,H.jsx)("circle",{cx:n.px,cy:n.py,r:4,fill:n.color??o.crosshairColor,stroke:o.background,strokeWidth:1.5}),(0,H.jsxs)("g",{transform:`translate(${Math.min(e.px+10,t-100)}, ${Math.max(e.py-10,20)})`,children:[(0,H.jsx)("rect",{x:0,y:-14,width:90,height:18,rx:3,fill:o.tooltipBg,stroke:o.tooltipBorder,strokeWidth:.5,opacity:.9}),(0,H.jsxs)("text",{x:5,y:0,fill:o.tooltipText,fontSize:10,fontFamily:"monospace",children:[Ft(n?.dataX??e.dataX),","," ",Ft(n?.dataY??e.dataY)]})]})]}):null}function Ft(e){return Math.abs(e)>=100?Math.round(e).toString():Math.abs(e)>=1?e.toFixed(1):e.toFixed(4)}var K=require("react/jsx-runtime");function Ee({annotations:e,xScale:t,yScale:r,colors:o}){return e.length===0?null:(0,K.jsx)("g",{className:"spectraview-annotations",pointerEvents:"none",children:e.map(n=>{let a=t(n.x),s=r(n.y),[i,c]=n.offset??[0,-20],l=a+i,m=s+c,p=n.fontSize??11,f=n.color??o.tickColor,u=n.showAnchorLine!==!1;return(0,K.jsxs)("g",{children:[u&&(0,K.jsx)("line",{x1:a,y1:s,x2:l,y2:m,stroke:f,strokeWidth:.75,strokeDasharray:"3 2",opacity:.6}),(0,K.jsx)("circle",{cx:a,cy:s,r:2.5,fill:f,opacity:.8}),(0,K.jsx)("text",{x:l,y:m,fill:o.background,fontSize:p,fontFamily:"system-ui, sans-serif",textAnchor:"middle",dominantBaseline:"auto",stroke:o.background,strokeWidth:3,strokeLinejoin:"round",children:n.text}),(0,K.jsx)("text",{x:l,y:m,fill:f,fontSize:p,fontFamily:"system-ui, sans-serif",textAnchor:"middle",dominantBaseline:"auto",children:n.text})]},n.id)})})}function pe(e,t,r){if(r===0)return-1;if(r===1)return 0;let o=e[r-1]>=e[0],n=0,a=r-1;for(;n<a-1;){let c=n+a>>>1,l=e[c];o?l<=t?n=c:a=c:l>=t?n=c:a=c}let s=Math.abs(e[n]-t),i=Math.abs(e[a]-t);return s<=i?n:a}function Le(e,t,r,o,n){let a=null;for(let s of e){if(s.visible===!1)continue;let i=Math.min(s.x.length,s.y.length);if(i<2)continue;let c=pe(s.x,t,i);if(c<0)continue;let l=s.x[c],m=s.y[c],p=Math.abs(o(l)-o(t)),f=Math.abs(n(m)-r),u=Math.sqrt(p*p+f*f);(!a||u<a.distance)&&(a={spectrumId:s.id,index:c,x:l,y:m,distance:u})}return a}var Dt=require("react"),ue=require("react/jsx-runtime"),pt=e=>({display:"inline-flex",alignItems:"center",justifyContent:"center",width:28,height:28,border:`1px solid ${e==="dark"?"#4b5563":"#d1d5db"}`,borderRadius:4,background:e==="dark"?"#1f2937":"#ffffff",color:e==="dark"?"#d1d5db":"#374151",fontSize:14,cursor:"pointer",padding:0,lineHeight:1}),zr=e=>({display:"flex",gap:4,padding:"4px 0",borderBottom:`1px solid ${e==="dark"?"#374151":"#e5e7eb"}`}),Pe=(0,Dt.memo)(function({onZoomIn:t,onZoomOut:r,onReset:o,isZoomed:n,theme:a}){return(0,ue.jsxs)("div",{style:zr(a),className:"spectraview-toolbar",children:[(0,ue.jsx)("button",{type:"button",style:pt(a),onClick:t,title:"Zoom in","aria-label":"Zoom in",children:"+"}),(0,ue.jsx)("button",{type:"button",style:pt(a),onClick:r,title:"Zoom out","aria-label":"Zoom out",children:"\u2212"}),(0,ue.jsx)("button",{type:"button",style:{...pt(a),opacity:n?1:.4},onClick:o,disabled:!n,title:"Reset zoom","aria-label":"Reset zoom",children:"\u21BA"})]})});var Ut=require("react");var me=require("react/jsx-runtime"),Vr=(e,t)=>({display:"flex",flexDirection:t==="left"||t==="right"?"column":"row",flexWrap:"wrap",gap:6,padding:"4px 8px",fontSize:12,fontFamily:"system-ui, sans-serif",borderTop:t==="bottom"?`1px solid ${e==="dark"?"#374151":"#e5e7eb"}`:void 0,borderBottom:t==="top"?`1px solid ${e==="dark"?"#374151":"#e5e7eb"}`:void 0,borderLeft:t==="right"?`1px solid ${e==="dark"?"#374151":"#e5e7eb"}`:void 0,borderRight:t==="left"?`1px solid ${e==="dark"?"#374151":"#e5e7eb"}`:void 0}),Br=(e,t,r)=>({display:"inline-flex",alignItems:"center",gap:4,cursor:"pointer",opacity:t?.4:1,fontWeight:r?600:400,color:e==="dark"?"#e5e7eb":"#374151",userSelect:"none",padding:"2px 4px",borderRadius:3,background:r?e==="dark"?"rgba(255,255,255,0.08)":"rgba(0,0,0,0.04)":"transparent",transition:"background 0.15s, opacity 0.15s"}),Hr=(e,t)=>({width:12,height:3,borderRadius:1,background:e,opacity:t?.4:1,flexShrink:0}),fe=(0,Ut.memo)(function({spectra:t,theme:r,position:o,onToggleVisibility:n,onHighlight:a,highlightedId:s}){return t.length<=1?null:(0,me.jsx)("div",{className:"spectraview-legend",style:Vr(r,o),role:"list","aria-label":"Spectrum legend",children:t.map((i,c)=>{let l=i.color??L(c),m=i.visible===!1,p=s===i.id;return(0,me.jsxs)("div",{role:"listitem",style:Br(r,m,p),onClick:()=>n?.(i.id),onMouseEnter:()=>a?.(i.id),onMouseLeave:()=>a?.(null),title:m?`Show ${i.label}`:`Hide ${i.label}`,children:[(0,me.jsx)("span",{style:Hr(l,m)}),(0,me.jsx)("span",{style:{textDecoration:m?"line-through":"none",maxWidth:120,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:i.label})]},i.id)})})});var te=require("react"),De=require("react/jsx-runtime");function Fe({enabled:e,theme:t,width:r,height:o,onDrop:n,children:a}){let[s,i]=(0,te.useState)(!1),c={current:0},l=(0,te.useCallback)(u=>{e&&(u.preventDefault(),c.current++,i(!0))},[e]),m=(0,te.useCallback)(u=>{e&&(u.preventDefault(),c.current--,c.current<=0&&(c.current=0,i(!1)))},[e]),p=(0,te.useCallback)(u=>{e&&(u.preventDefault(),u.dataTransfer.dropEffect="copy")},[e]),f=(0,te.useCallback)(u=>{if(!e)return;u.preventDefault(),c.current=0,i(!1);let d=Array.from(u.dataTransfer.files);d.length>0&&n?.(d)},[e,n]);return(0,De.jsxs)("div",{style:{position:"relative",width:r,height:o},onDragEnter:l,onDragLeave:m,onDragOver:p,onDrop:f,children:[a,s&&(0,De.jsx)("div",{"data-testid":"dropzone-overlay",style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",background:t==="dark"?"rgba(30, 58, 138, 0.6)":"rgba(59, 130, 246, 0.15)",border:`2px dashed ${t==="dark"?"#60a5fa":"#3b82f6"}`,borderRadius:4,zIndex:100,pointerEvents:"none",fontSize:14,fontFamily:"system-ui, sans-serif",color:t==="dark"?"#93c5fd":"#1d4ed8",fontWeight:500},children:"Drop spectrum files here"})]})}var Nt=require("react");var Z=require("react/jsx-runtime"),$t=8;function Ue({spectra:e,xScale:t,plotWidth:r,plotHeight:o,margin:n,theme:a,showGrid:s,xLabel:i,yLabel:c}){let l=e.filter(d=>d.visible!==!1),m=(0,Nt.useMemo)(()=>O(a),[a]),p=l.length,f=(p-1)*$t,u=Math.max(40,Math.floor((o-f)/Math.max(p,1)));return(0,Z.jsx)("g",{className:"spectraview-stacked",children:l.map((d,h)=>{let g=h*(u+$t),b=ne([d]),x=oe(b,u+n.top+n.bottom,{...n,top:0,bottom:0}),S=d.color??L(h),v={...d,color:S};return(0,Z.jsxs)("g",{transform:`translate(0, ${g})`,children:[(0,Z.jsx)("rect",{x:0,y:0,width:r,height:u,fill:"transparent",stroke:m.gridColor,strokeWidth:.5,rx:2}),(0,Z.jsx)(se,{xScale:t,yScale:x,width:r,height:u,xLabel:h===p-1?i:"",yLabel:c,showGrid:s,colors:m}),(0,Z.jsx)("text",{x:4,y:14,fill:S,fontSize:11,fontFamily:"system-ui, sans-serif",fontWeight:500,children:d.label}),(0,Z.jsx)("foreignObject",{x:0,y:0,width:r,height:u,children:(0,Z.jsx)(ae,{spectra:[v],xScale:t,yScale:x,width:r,height:u})})]},d.id)})})}var J=require("react");function $e(e){let{enabled:t,xScale:r,onRegionSelect:o}=e,[n,a]=(0,J.useState)(null),s=(0,J.useRef)(null),i=(0,J.useCallback)(m=>{if(!t||!m.shiftKey)return;m.preventDefault();let p=m.currentTarget.getBoundingClientRect(),f=m.clientX-p.left,u=r.invert(f);s.current=u,a({xStart:u,xEnd:u})},[t,r]),c=(0,J.useCallback)(m=>{if(s.current===null)return;let p=m.currentTarget.getBoundingClientRect(),f=m.clientX-p.left,u=r.invert(f),d=s.current;a({xStart:Math.min(d,u),xEnd:Math.max(d,u)})},[r]),l=(0,J.useCallback)(()=>{if(s.current===null||!n)return;Math.abs(n.xEnd-n.xStart)>0&&o?.(n),s.current=null,a(null)},[n,o]);return{pendingRegion:n,handleMouseDown:i,handleMouseMove:c,handleMouseUp:l}}var _=require("react");function Ne(){let[e,t]=(0,_.useState)(null),r=(0,_.useRef)(null),o=(0,_.useRef)(null),n=(0,_.useCallback)(a=>{if(r.current&&(r.current.disconnect(),r.current=null),o.current=a,!a)return;let s=new ResizeObserver(l=>{let m=l[0];if(!m)return;let{width:p,height:f}=m.contentRect;t({width:Math.round(p),height:Math.round(f)})});s.observe(a),r.current=s;let{width:i,height:c}=a.getBoundingClientRect();t({width:Math.round(i),height:Math.round(c)})},[]);return(0,_.useEffect)(()=>()=>{r.current?.disconnect()},[]),{ref:n,size:e}}var It=require("react");function Ie(e){let{onZoomIn:t,onZoomOut:r,onReset:o,enabled:n=!0}=e;return(0,It.useCallback)(s=>{if(n)switch(s.key){case"+":case"=":s.preventDefault(),t();break;case"-":s.preventDefault(),r();break;case"Escape":s.preventDefault(),o();break}},[n,t,r,o])}function Ot(){return typeof window>"u"?!1:window.matchMedia("(prefers-reduced-motion: reduce)").matches}function Oe(e,t,r){return e===0?"Empty spectrum viewer":`Interactive spectrum viewer showing ${e} ${e===1?"spectrum":"spectra"}. X-axis: ${t}. Y-axis: ${r}. Use arrow keys to pan, +/- to zoom, Escape to reset.`}var zt={PAN_LEFT:"ArrowLeft",PAN_RIGHT:"ArrowRight",PAN_UP:"ArrowUp",PAN_DOWN:"ArrowDown",ZOOM_IN:"+",ZOOM_IN_ALT:"=",ZOOM_OUT:"-",RESET:"Escape",NEXT_PEAK:"Tab",PREV_PEAK:"Shift+Tab"};var M=require("react/jsx-runtime"),Zr={top:20,right:20,bottom:50,left:65},_r=800,Xr=400;function Wr(e){return{width:e.width??_r,height:e.height??Xr,reverseX:e.reverseX??!1,showGrid:e.showGrid??!0,showCrosshair:e.showCrosshair??!0,showToolbar:e.showToolbar??!0,showLegend:e.showLegend??!0,legendPosition:e.legendPosition??"bottom",displayMode:e.displayMode??"overlay",margin:{...Zr,...e.margin},theme:e.theme??"light",responsive:e.responsive??!1,enableDragDrop:e.enableDragDrop??!1,enableRegionSelect:e.enableRegionSelect??!1}}function jr(e,t,r){let o=e[0];return{xLabel:t??o?.xUnit??"x",yLabel:r??o?.yUnit??"y"}}function Vt(e){let{spectra:t,peaks:r=[],regions:o=[],annotations:n=[],onPeakClick:a,onViewChange:s,onCrosshairMove:i,onToggleVisibility:c,onFileDrop:l,onRegionSelect:m,canvasRef:p,snapCrosshair:f=!0}=e,{ref:u,size:d}=Ne(),g=`spectraview-clip-${(0,T.useId)().replace(/:/g,"")}`,b=(0,T.useMemo)(()=>Wr(e),[e.width,e.height,e.reverseX,e.showGrid,e.showCrosshair,e.showToolbar,e.showLegend,e.legendPosition,e.displayMode,e.margin,e.theme,e.responsive,e.enableDragDrop,e.enableRegionSelect]),x=b.responsive&&d?d.width:b.width,{height:S,margin:v,reverseX:y,theme:k}=b,C=x-v.left-v.right,w=S-v.top-v.bottom,R=(0,T.useMemo)(()=>O(k),[k]),E=(0,T.useMemo)(()=>jr(t,e.xLabel,e.yLabel),[t,e.xLabel,e.yLabel]),U=(0,T.useMemo)(()=>ve(t),[t]),$=(0,T.useMemo)(()=>ne(t),[t]),tt=(0,T.useMemo)(()=>ke(U,x,v,y),[U,x,v,y]),Q=(0,T.useMemo)(()=>oe($,S,v),[$,S,v]),ee=(0,T.useRef)(s);ee.current=s;let gr=(0,T.useMemo)(()=>(Y,ye)=>{ee.current?.({xDomain:Y,yDomain:ye})},[]),{zoomRef:ht,state:hr,zoomedXScale:D,zoomedYScale:j,resetZoom:xt,zoomIn:yt,zoomOut:St}=we({plotWidth:C,plotHeight:w,xScale:tt,yScale:Q,onViewChange:s?gr:void 0}),{pendingRegion:he,handleMouseDown:xr,handleMouseMove:yr,handleMouseUp:Sr}=$e({enabled:b.enableRegionSelect,xScale:D,onRegionSelect:m}),[rt,vt]=(0,T.useState)(null),[vr,kt]=(0,T.useState)(null),[kr,nt]=(0,T.useState)(null),xe=(0,T.useRef)(i);xe.current=i;let Ct=(0,T.useCallback)(Y=>{if(!b.showCrosshair)return;let ye=Y.currentTarget.getBoundingClientRect(),Mt=Y.clientX-ye.left,it=Y.clientY-ye.top,Se=D.invert(Mt),at=j.invert(it);if(kt({px:Mt,py:it,dataX:Se,dataY:at}),f&&t.length>0){let B=Le(t,Se,it,D,j);if(B&&B.distance<50){let Rt=t.findIndex(Rr=>Rr.id===B.spectrumId);nt({px:D(B.x),py:j(B.y),dataX:B.x,dataY:B.y,color:t[Rt]?.color??L(Rt)}),xe.current?.(B.x,B.y)}else nt(null),xe.current?.(Se,at)}else xe.current?.(Se,at)},[D,j,b.showCrosshair,f,t]),wt=(0,T.useCallback)(()=>{kt(null),nt(null)},[]),Cr=Ie({onZoomIn:yt,onZoomOut:St,onReset:xt}),wr=(0,T.useMemo)(()=>Oe(t.length,E.xLabel,E.yLabel),[t.length,E.xLabel,E.yLabel]),Mr=b.displayMode==="stacked";if(t.length===0)return(0,M.jsx)("div",{ref:b.responsive?u:void 0,style:{width:b.responsive?"100%":x,height:S,display:"flex",alignItems:"center",justifyContent:"center",border:`1px dashed ${R.gridColor}`,borderRadius:8,color:R.tickColor,fontFamily:"system-ui, sans-serif",fontSize:14},className:e.className,children:"No spectra loaded"});let ot=b.showToolbar?37:0;return(0,M.jsxs)("div",{ref:b.responsive?u:void 0,style:{width:b.responsive?"100%":x,background:R.background,borderRadius:4,overflow:"hidden"},className:e.className,role:"img","aria-label":wr,tabIndex:0,onKeyDown:Cr,children:[b.showToolbar&&(0,M.jsx)(Pe,{onZoomIn:yt,onZoomOut:St,onReset:xt,isZoomed:hr.isZoomed,theme:k}),b.showLegend&&b.legendPosition==="top"&&(0,M.jsx)(fe,{spectra:t,theme:k,position:"top",onToggleVisibility:c,onHighlight:vt,highlightedId:rt}),(0,M.jsx)(Fe,{enabled:b.enableDragDrop,theme:k,width:x,height:S-ot,onDrop:l,children:Mr?(0,M.jsx)("svg",{width:x,height:S-ot,style:{position:"absolute",top:0,left:0},children:(0,M.jsxs)("g",{transform:`translate(${v.left}, ${v.top})`,children:[(0,M.jsx)(Ue,{spectra:t,xScale:D,plotWidth:C,plotHeight:w,margin:v,theme:k,showGrid:b.showGrid,xLabel:E.xLabel,yLabel:E.yLabel}),(0,M.jsx)("rect",{ref:ht,x:0,y:0,width:C,height:w,fill:"transparent",style:{cursor:"grab"},onMouseMove:Ct,onMouseLeave:wt})]})}):(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)("div",{style:{position:"absolute",top:v.top,left:v.left,width:C,height:w,overflow:"hidden"},children:(0,M.jsx)(ae,{ref:p,spectra:t,xScale:D,yScale:j,width:C,height:w,highlightedId:rt??void 0})}),(0,M.jsx)("svg",{width:x,height:S-ot,style:{position:"absolute",top:0,left:0},children:(0,M.jsxs)("g",{transform:`translate(${v.left}, ${v.top})`,children:[(0,M.jsx)(se,{xScale:D,yScale:j,width:C,height:w,xLabel:E.xLabel,yLabel:E.yLabel,showGrid:b.showGrid,colors:R}),(0,M.jsx)("defs",{children:(0,M.jsx)("clipPath",{id:g,children:(0,M.jsx)("rect",{x:0,y:0,width:C,height:w})})}),(0,M.jsxs)("g",{clipPath:`url(#${g})`,children:[o.length>0&&(0,M.jsx)(Te,{regions:o,xScale:D,height:w,colors:R}),r.length>0&&(0,M.jsx)(Re,{peaks:r,xScale:D,yScale:j,colors:R,onPeakClick:a})]}),n.length>0&&(0,M.jsx)(Ee,{annotations:n,xScale:D,yScale:j,colors:R}),b.showCrosshair&&(0,M.jsx)(Ae,{position:vr,width:C,height:w,colors:R,snapPoint:kr}),he&&(0,M.jsx)("rect",{x:D(he.xStart),y:0,width:Math.abs(D(he.xEnd)-D(he.xStart)),height:w,fill:R.regionFill,stroke:R.regionStroke,strokeWidth:1,pointerEvents:"none"}),(0,M.jsx)("rect",{ref:ht,x:0,y:0,width:C,height:w,fill:"transparent",style:{cursor:b.showCrosshair?"crosshair":"grab"},onMouseDown:xr,onMouseMove:Y=>{Ct(Y),yr(Y)},onMouseUp:Sr,onMouseLeave:wt})]})})]})}),b.showLegend&&b.legendPosition==="bottom"&&(0,M.jsx)(fe,{spectra:t,theme:k,position:"bottom",onToggleVisibility:c,onHighlight:vt,highlightedId:rt})]})}var V=require("react"),ft=require("d3-scale");var q=require("react/jsx-runtime"),Bt=(0,V.memo)(function({spectra:t,xExtent:r,yExtent:o,visibleXDomain:n,width:a=200,height:s=50,theme:i="light",isZoomed:c=!1}){let l=(0,V.useRef)(null),m=(0,V.useMemo)(()=>O(i),[i]),p=(0,V.useMemo)(()=>(0,ft.scaleLinear)().domain(r).range([0,a]),[r,a]),f=(0,V.useMemo)(()=>(0,ft.scaleLinear)().domain(o).range([s-2,2]),[o,s]);(0,V.useEffect)(()=>{let g=l.current?.getContext("2d");if(g){g.clearRect(0,0,a,s);for(let b=0;b<t.length;b++){let x=t[b];if(x.visible===!1)continue;let S=Math.min(x.x.length,x.y.length);if(S<2)continue;let v=x.color??L(b);g.beginPath(),g.strokeStyle=v,g.lineWidth=1,g.globalAlpha=.7;let y=Math.max(1,Math.floor(S/a)),k=!1;for(let C=0;C<S;C+=y){let w=p(x.x[C]),R=f(x.y[C]);k?g.lineTo(w,R):(g.moveTo(w,R),k=!0)}g.stroke()}}},[t,p,f,a,s]);let u=p(Math.min(n[0],n[1])),d=p(Math.max(n[0],n[1])),h=Math.max(d-u,2);return(0,q.jsxs)("div",{className:"spectraview-minimap",style:{position:"relative",width:a,height:s,border:`1px solid ${m.gridColor}`,borderRadius:3,overflow:"hidden",background:m.background},children:[(0,q.jsx)("canvas",{ref:l,width:a,height:s,style:{position:"absolute",top:0,left:0}}),c&&(0,q.jsxs)("svg",{width:a,height:s,style:{position:"absolute",top:0,left:0},children:[(0,q.jsx)("rect",{x:0,y:0,width:u,height:s,fill:m.background,opacity:.6}),(0,q.jsx)("rect",{x:u+h,y:0,width:a-u-h,height:s,fill:m.background,opacity:.6}),(0,q.jsx)("rect",{x:u,y:0,width:h,height:s,fill:"none",stroke:i==="dark"?"#60a5fa":"#3b82f6",strokeWidth:1.5,rx:1})]})]})});var de=require("react");var X=require("react/jsx-runtime");function dt(e,t){switch(t){case"fixed2":return e.toFixed(2);case"fixed4":return e.toFixed(4);case"scientific":return e.toExponential(2);default:return Math.abs(e)>=100?Math.round(e).toString():Math.abs(e)>=1?e.toFixed(2):Math.abs(e)>=.01?e.toFixed(4):e.toExponential(2)}}var Ht=(0,de.memo)(function({data:t,spectra:r,peaks:o=[],plotWidth:n,plotHeight:a,colors:s,numberFormat:i="auto"}){if(!t)return null;let c=(0,de.useMemo)(()=>t?r.filter(b=>b.visible!==!1).map((b,x)=>{let S=Math.min(b.x.length,b.y.length);if(S<1)return null;let v=pe(b.x,t.dataX,S);return v<0?null:{label:b.label,color:b.color??L(x),value:b.y[v],x:b.x[v]}}).filter(Boolean):[],[t?.dataX,r]),l=(0,de.useMemo)(()=>{if(!t||o.length===0)return null;let b=null,x=1/0;for(let S of o){let v=Math.abs(S.x-t.dataX);v<x&&(x=v,b=S)}return b},[t?.dataX,o]),m=16,p=18,f=l?m:0,u=p+c.length*m+f+8,d=160,h=t.px+15,g=t.py-u/2;return h+d>n&&(h=t.px-d-15),g<0&&(g=4),g+u>a&&(g=a-u-4),(0,X.jsxs)("g",{className:"spectraview-tooltip",transform:`translate(${h}, ${g})`,pointerEvents:"none",children:[(0,X.jsx)("rect",{x:0,y:0,width:d,height:u,rx:4,fill:s.tooltipBg,stroke:s.tooltipBorder,strokeWidth:.5,opacity:.95}),(0,X.jsxs)("text",{x:8,y:14,fill:s.tooltipText,fontSize:10,fontFamily:"monospace",fontWeight:600,children:["x = ",dt(t.dataX,i)]}),c.map((b,x)=>(0,X.jsxs)("g",{transform:`translate(0, ${p+x*m})`,children:[(0,X.jsx)("circle",{cx:12,cy:8,r:3,fill:b.color}),(0,X.jsxs)("text",{x:20,y:11,fill:s.tooltipText,fontSize:9,fontFamily:"monospace",children:[b.label.slice(0,10),": ",dt(b.value,i)]})]},b.label)),l&&(0,X.jsxs)("text",{x:8,y:p+c.length*m+12,fill:s.labelColor,fontSize:9,fontFamily:"monospace",fontStyle:"italic",children:["Peak: ",l.label??dt(l.x,i)]})]})});var re=require("react");var F=require("react/jsx-runtime"),Zt=(0,re.memo)(function({spectrum:t,theme:r="light",maxRows:o=200,height:n=300,highlightRange:a}){let s=(0,re.useMemo)(()=>O(r),[r]),[i,c]=(0,re.useState)(!1),l=Math.min(t.x.length,t.y.length),m=(0,re.useMemo)(()=>{let g=Array.from({length:l},(b,x)=>x);return i&&g.reverse(),g.slice(0,o)},[l,i,o]),p=g=>{if(!a)return!1;let b=Math.min(a[0],a[1]),x=Math.max(a[0],a[1]);return g>=b&&g<=x},f=g=>Math.abs(g)>=100?g.toFixed(2):Math.abs(g)>=.01?g.toFixed(4):g.toExponential(3),u=r==="dark"?"#1f2937":"#f3f4f6",d=r==="dark"?"#374151":"#e5e7eb",h=r==="dark"?"rgba(59,130,246,0.15)":"rgba(59,130,246,0.08)";return(0,F.jsxs)("div",{className:"spectraview-datatable",style:{height:n,overflow:"auto",border:`1px solid ${d}`,borderRadius:4,fontFamily:"monospace",fontSize:12,color:s.tickColor,background:s.background},children:[(0,F.jsxs)("table",{style:{width:"100%",borderCollapse:"collapse"},children:[(0,F.jsx)("thead",{children:(0,F.jsxs)("tr",{style:{position:"sticky",top:0,background:u,borderBottom:`1px solid ${d}`},children:[(0,F.jsx)("th",{style:{padding:"6px 8px",textAlign:"right"},children:"#"}),(0,F.jsxs)("th",{style:{padding:"6px 8px",textAlign:"right",cursor:"pointer",userSelect:"none"},onClick:()=>c(g=>!g),title:"Click to reverse sort",children:[t.xUnit??"x"," ",i?"\u2191":"\u2193"]}),(0,F.jsx)("th",{style:{padding:"6px 8px",textAlign:"right"},children:t.yUnit??"y"})]})}),(0,F.jsx)("tbody",{children:m.map(g=>{let b=t.x[g],x=t.y[g];return(0,F.jsxs)("tr",{style:{background:p(b)?h:"transparent",borderBottom:`1px solid ${d}`},children:[(0,F.jsx)("td",{style:{padding:"3px 8px",textAlign:"right",opacity:.5},children:g}),(0,F.jsx)("td",{style:{padding:"3px 8px",textAlign:"right"},children:f(b)}),(0,F.jsx)("td",{style:{padding:"3px 8px",textAlign:"right"},children:f(x)})]},g)})})]}),l>o&&(0,F.jsxs)("div",{style:{padding:"6px 8px",textAlign:"center",fontSize:11,opacity:.6,borderTop:`1px solid ${d}`},children:["Showing ",o," of ",l," points"]})]})});var _t=require("react");function ze(e,t,r={}){let{prominence:o=.01,minDistance:n=5,maxPeaks:a}=r;if(e.length<3||t.length<3)return[];let s=1/0,i=-1/0;for(let u=0;u<t.length;u++)t[u]<s&&(s=t[u]),t[u]>i&&(i=t[u]);let c=i-s;if(c===0)return[];let l=o*c,m=[];for(let u=1;u<t.length-1;u++)if(t[u]>t[u-1]&&t[u]>t[u+1]){let d=Yr(t,u),h=Gr(t,u),g=t[u]-Math.max(d,h);g>=l&&m.push({index:u,prom:g})}m.sort((u,d)=>d.prom-u.prom);let p=[];for(let u of m)p.some(h=>Math.abs(h.index-u.index)<n)||p.push(u);return(a?p.slice(0,a):p).map(u=>({x:e[u.index],y:t[u.index],label:Kr(e[u.index])})).sort((u,d)=>u.x-d.x)}function Yr(e,t){let r=e[t];for(let o=t-1;o>=0&&!(e[o]>e[t]);o--)e[o]<r&&(r=e[o]);return r}function Gr(e,t){let r=e[t];for(let o=t+1;o<e.length&&!(e[o]>e[t]);o++)e[o]<r&&(r=e[o]);return r}function Kr(e){return Math.round(e).toString()}function Xt(e,t={}){let{enabled:r=!0,spectrumIds:o,prominence:n,minDistance:a,maxPeaks:s}=t;return(0,_t.useMemo)(()=>{if(!r)return[];let i=o?e.filter(l=>o.includes(l.id)):e,c=[];for(let l of i){if(l.visible===!1)continue;let m=ze(l.x,l.y,{prominence:n,minDistance:a,maxPeaks:s});for(let p of m)c.push({...p,spectrumId:l.id})}return c},[e,r,o,n,a,s])}var I=require("react");var Wt=0,Jr=[" ",",",";"," "];function jt(e){let t=e.trim().split(/\r?\n/).slice(0,5),r=",",o=0;for(let n of Jr){let a=t.map(i=>i.split(n).length-1),s=Math.min(...a);s>0&&s>=o&&(a.every(c=>c===a[0])||s>o)&&(o=s,r=n)}return r}function Ve(e,t={}){let{xColumn:r=0,yColumn:o=1,hasHeader:n=!0,label:a="CSV Spectrum"}=t,s=t.delimiter??jt(e),i=e.trim().split(/\r?\n/);if(i.length<2)throw new Error("CSV file must contain at least 2 lines");let c=a,l=0;if(n){let f=i[0].split(s).map(u=>u.trim());!t.label&&f[o]&&(c=f[o]),l=1}let m=[],p=[];for(let f=l;f<i.length;f++){let u=i[f].trim();if(u===""||u.startsWith("#"))continue;let d=u.split(s),h=parseFloat(d[r]),g=parseFloat(d[o]);!isNaN(h)&&!isNaN(g)&&(m.push(h),p.push(g))}if(m.length===0)throw new Error("No valid numeric data found in CSV");return{id:`csv-${++Wt}`,label:c,x:new Float64Array(m),y:new Float64Array(p)}}function Yt(e,t={}){let{hasHeader:r=!0,label:o}=t,n=t.delimiter??jt(e),a=e.trim().split(/\r?\n/);if(a.length<2)throw new Error("CSV file must contain at least 2 lines");let i=a[r?1:0].split(n).length;if(i<2)throw new Error("CSV must have at least 2 columns (x + y)");let c,l=0;r&&(c=a[0].split(n).map(u=>u.trim()),l=1);let m=[],p=Array.from({length:i-1},()=>[]);for(let u=l;u<a.length;u++){let d=a[u].trim();if(d===""||d.startsWith("#"))continue;let h=d.split(n),g=parseFloat(h[0]);if(!isNaN(g)){m.push(g);for(let b=1;b<i;b++){let x=parseFloat(h[b]);p[b-1].push(isNaN(x)?0:x)}}}let f=new Float64Array(m);return p.map((u,d)=>({id:`csv-${++Wt}`,label:o??c?.[d+1]??`Spectrum ${d+1}`,x:f,y:new Float64Array(u)}))}var qr=0;function Be(e){let t;try{t=JSON.parse(e)}catch{throw new Error("Invalid JSON: failed to parse input")}if(Array.isArray(t))return t.map((r,o)=>bt(r,o));if(typeof t=="object"&&t!==null){let r=t;return Array.isArray(r.spectra)?r.spectra.map((o,n)=>bt(o,n)):[bt(t,0)]}throw new Error("Invalid JSON structure: expected an object or array")}function bt(e,t){let r=e.x??e.wavenumbers??e.wavelengths;if(!r||!Array.isArray(r))throw new Error(`Spectrum ${t}: missing x-axis data (expected "x", "wavenumbers", or "wavelengths")`);let o=e.y??e.intensities??e.absorbance;if(!o||!Array.isArray(o))throw new Error(`Spectrum ${t}: missing y-axis data (expected "y", "intensities", or "absorbance")`);if(r.length!==o.length)throw new Error(`Spectrum ${t}: x and y arrays must have the same length (got ${r.length} and ${o.length})`);let n=e.label??e.title??e.name??`Spectrum ${t+1}`;return{id:`json-${++qr}`,label:n,x:new Float64Array(r),y:new Float64Array(o),xUnit:e.xUnit,yUnit:e.yUnit,type:e.type,meta:e.meta}}var Kt=0,He=null,Gt=!1;async function Qr(){if(Gt)return He;Gt=!0;try{He=await import("jcampconverter")}catch{He=null}return He}function Jt(e){let t=(e["DATA TYPE"]??e.DATATYPE??"").toLowerCase();return t.includes("infrared")||t.includes("ir")?"IR":t.includes("raman")?"Raman":t.includes("nir")||t.includes("near")?"NIR":t.includes("uv")||t.includes("vis")?"UV-Vis":t.includes("fluor")?"fluorescence":"other"}async function Ze(e){let t=await Qr();return t?en(e,t):[tn(e)]}function en(e,t){return t.convert(e,{keepRecordsRegExp:/.*/}).flatten.map((o,n)=>{let a=o.spectra?.[0]?.data?.[0];if(!a)throw new Error(`JCAMP block ${n}: no spectral data found`);return{id:`jcamp-${++Kt}`,label:o.info?.TITLE??`Spectrum ${n+1}`,x:new Float64Array(a.x),y:new Float64Array(a.y),xUnit:o.info?.XUNITS??"cm\u207B\xB9",yUnit:o.info?.YUNITS??"Absorbance",type:Jt(o.info),meta:o.info}})}function tn(e){let t=e.split(/\r?\n/),r={},o=[],n=[],a=!1;for(let s of t){let i=s.trim();if(i.startsWith("##")){let c=i.match(/^##(.+?)=\s*(.*)$/);if(c){let l=c[1].trim().toUpperCase(),m=c[2].trim();if(l==="XYDATA"||l==="XYPOINTS"){a=!0;continue}if(l==="END"){a=!1;continue}r[l]=m}continue}if(a&&i!==""){let c=i.split(/[\s,]+/).map(Number);if(c.length>=2&&!c.some(isNaN)){let l=c[0],m=parseFloat(r.FIRSTX??"0"),p=parseFloat(r.LASTX??"0"),f=parseInt(r.NPOINTS??"0",10);if(f>0&&c.length===2)o.push(c[0]),n.push(c[1]);else if(c.length>1){let u=f>1?(p-m)/(f-1):0;for(let d=1;d<c.length;d++)o.push(l+(d-1)*u),n.push(c[d])}}}}if(o.length===0)throw new Error("Failed to parse JCAMP-DX: no data found. Install jcampconverter for full format support.");return{id:`jcamp-${++Kt}`,label:r.TITLE??"JCAMP Spectrum",x:new Float64Array(o),y:new Float64Array(n),xUnit:r.XUNITS??"cm\u207B\xB9",yUnit:r.YUNITS??"Absorbance",type:Jt(r),meta:r}}function rn(e){switch(e.toLowerCase().split(".").pop()){case"dx":case"jdx":case"jcamp":return"jcamp";case"csv":case"tsv":case"txt":return"csv";case"json":return"json";default:return null}}function qt(e=[]){let[t,r]=(0,I.useState)(e),[o,n]=(0,I.useState)(!1),[a,s]=(0,I.useState)(null),i=(0,I.useCallback)(async(u,d)=>{n(!0),s(null);try{let h;switch(d){case"jcamp":h=await Ze(u);break;case"csv":h=[Ve(u)];break;case"json":h=Be(u);break}r(g=>[...g,...h])}catch(h){let g=h instanceof Error?h.message:"Failed to parse file";s(g)}finally{n(!1)}},[]),c=(0,I.useCallback)(async u=>{let d=rn(u.name);if(!d){s(`Unsupported file format: ${u.name}`);return}let h=await u.text();await i(h,d)},[i]),l=(0,I.useCallback)(u=>{r(d=>[...d,u])},[]),m=(0,I.useCallback)(u=>{r(d=>d.filter(h=>h.id!==u))},[]),p=(0,I.useCallback)(u=>{r(d=>d.map(h=>h.id===u?{...h,visible:h.visible===!1}:h))},[]),f=(0,I.useCallback)(()=>{r([]),s(null)},[]);return{spectra:t,loading:o,error:a,loadFile:c,loadText:i,addSpectrum:l,removeSpectrum:m,toggleVisibility:p,clear:f}}var be=require("react");var gt={solid:"",dashed:"8 4",dotted:"2 2","dash-dot":"8 4 2 4"};function _e(e,t,r,o){let{width:n,height:a,background:s="#ffffff",title:i}=o,c=e.filter(l=>l.visible!==!1).map((l,m)=>{let p=l.color??L(m),f=l.lineStyle??"solid",u=l.lineWidth??1.5,d=gt[f]??"",h=Math.min(l.x.length,l.y.length);if(h<2)return"";let g=[];for(let b=0;b<h;b++){let x=t(l.x[b]).toFixed(2),S=r(l.y[b]).toFixed(2);g.push(`${b===0?"M":"L"}${x},${S}`)}return`<path d="${g.join(" ")}" fill="none" stroke="${p}" stroke-width="${u}"${d?` stroke-dasharray="${d}"`:""}/>
2
+ "use strict";var st=Object.defineProperty;var Tr=Object.getOwnPropertyDescriptor;var Ar=Object.getOwnPropertyNames;var Er=Object.prototype.hasOwnProperty;var Lr=(e,t)=>{for(var r in t)st(e,r,{get:t[r],enumerable:!0})},Pr=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Ar(t))!Er.call(e,n)&&n!==r&&st(e,n,{get:()=>t[n],enumerable:!(o=Tr(t,n))||o.enumerable});return e};var Fr=e=>Pr(st({},"__esModule",{value:!0}),e);var hn={};Lr(hn,{AnnotationLayer:()=>Ee,AxisLayer:()=>se,Crosshair:()=>Ae,DARK_THEME:()=>mt,DataTable:()=>Zt,DropZone:()=>Fe,ExportMenu:()=>or,KEYBOARD_SHORTCUTS:()=>zt,LIGHT_THEME:()=>ut,LINE_DASH_PATTERNS:()=>gt,Legend:()=>fe,Minimap:()=>Bt,PeakMarkers:()=>Re,RegionSelector:()=>Te,SPECTRUM_COLORS:()=>Ce,SpectraView:()=>Vt,SpectrumCanvas:()=>ae,StackedView:()=>Ue,Toolbar:()=>Pe,Tooltip:()=>Ht,addSpectra:()=>ur,baselineRubberBand:()=>je,binarySearchClosest:()=>pe,computeXExtent:()=>ve,computeYExtent:()=>ne,correlationCoefficient:()=>pr,createXScale:()=>ke,createYScale:()=>oe,derivative1st:()=>qe,derivative2nd:()=>er,detectPeaks:()=>ze,differenceSpectrum:()=>cr,downloadString:()=>lr,downloadSvg:()=>Xe,generateChartDescription:()=>Oe,generateSvg:()=>_e,getSpectrumColor:()=>L,getThemeColors:()=>I,interpolateToGrid:()=>dr,lttbDownsample:()=>Me,multiSpectraToCsv:()=>ar,normalizeArea:()=>Ge,normalizeMinMax:()=>Ye,normalizeSNV:()=>Ke,parseCsv:()=>Ve,parseCsvMulti:()=>Yt,parseJcamp:()=>Ze,parseJson:()=>Be,parseSpc:()=>br,prefersReducedMotion:()=>Ot,residualSpectrum:()=>fr,scaleSpectrum:()=>mr,smoothSavitzkyGolay:()=>Je,snapToNearestSpectrum:()=>Le,spectrumToCsv:()=>ir,spectrumToJson:()=>sr,useExport:()=>Qt,useHistory:()=>nr,useKeyboardNavigation:()=>Ie,useNormalization:()=>rr,usePeakPicking:()=>Xt,useRegionSelect:()=>$e,useResizeObserver:()=>Ne,useSpectrumData:()=>qt,useZoomPan:()=>we});module.exports=Fr(hn);var A=require("react");var lt=require("d3-scale"),ct=require("d3-array"),Dr=.05;function ve(e){let t=1/0,r=-1/0;for(let o of e){if(o.visible===!1)continue;let[n,a]=(0,ct.extent)(o.x);n<t&&(t=n),a>r&&(r=a)}return isFinite(t)?[t,r]:[0,1]}function ne(e){let t=1/0,r=-1/0;for(let a of e){if(a.visible===!1)continue;let[s,i]=(0,ct.extent)(a.y);s<t&&(t=s),i>r&&(r=i)}if(!isFinite(t))return[0,1];let n=(r-t)*Dr;return[t-n,r+n]}function ke(e,t,r,o){let n=t-r.left-r.right,a=o?[e[1],e[0]]:e;return(0,lt.scaleLinear)().domain(a).range([0,n])}function oe(e,t,r){let o=t-r.top-r.bottom;return(0,lt.scaleLinear)().domain(e).range([o,0])}var Ce=["#2563eb","#dc2626","#16a34a","#9333ea","#ea580c","#0891b2","#be185d","#854d0e","#4f46e5","#65a30d"],ut={background:"#ffffff",axisColor:"#374151",gridColor:"#e5e7eb",tickColor:"#6b7280",labelColor:"#111827",crosshairColor:"#9ca3af",regionFill:"rgba(37, 99, 235, 0.1)",regionStroke:"rgba(37, 99, 235, 0.4)",tooltipBg:"#ffffff",tooltipBorder:"#d1d5db",tooltipText:"#111827"},mt={background:"#111827",axisColor:"#d1d5db",gridColor:"#374151",tickColor:"#9ca3af",labelColor:"#f9fafb",crosshairColor:"#6b7280",regionFill:"rgba(96, 165, 250, 0.15)",regionStroke:"rgba(96, 165, 250, 0.5)",tooltipBg:"#1f2937",tooltipBorder:"#4b5563",tooltipText:"#f9fafb"};function L(e){return Ce[e%Ce.length]}function I(e){return e==="dark"?mt:ut}var P=require("react"),ie=require("d3-zoom"),Y=require("d3-selection"),vn=require("d3-transition"),Tt=1.5;function we(e){let{plotWidth:t,plotHeight:r,xScale:o,yScale:n,scaleExtent:a=[1,50],enabled:s=!0,onViewChange:i}=e,c=(0,P.useRef)(null),l=(0,P.useRef)(null),m=(0,P.useRef)(i);m.current=i;let p=(0,P.useRef)(a);p.current=a;let[f,u]=(0,P.useState)(ie.zoomIdentity),d=(0,P.useMemo)(()=>f.rescaleX(o.copy()),[f,o]),h=(0,P.useMemo)(()=>f.rescaleY(n.copy()),[f,n]);(0,P.useEffect)(()=>{let S=c.current;if(!S||!s)return;let v=(0,ie.zoom)().scaleExtent(p.current).extent([[0,0],[t,r]]).translateExtent([[-1/0,-1/0],[1/0,1/0]]).on("zoom",y=>{let k=y.transform;if(u(k),m.current){let C=k.rescaleX(o.copy()),w=k.rescaleY(n.copy());m.current(C.domain(),w.domain())}});return l.current=v,(0,Y.select)(S).call(v),(0,Y.select)(S).on("dblclick.zoom",()=>{(0,Y.select)(S).transition().duration(300).call(v.transform,ie.zoomIdentity)}),()=>{(0,Y.select)(S).on(".zoom",null)}},[t,r,s,o,n]);let g=(0,P.useCallback)(()=>{!c.current||!l.current||(0,Y.select)(c.current).transition().duration(300).call(l.current.transform,ie.zoomIdentity)},[]),b=(0,P.useCallback)(()=>{!c.current||!l.current||(0,Y.select)(c.current).transition().duration(200).call(l.current.scaleBy,Tt)},[]),x=(0,P.useCallback)(()=>{!c.current||!l.current||(0,Y.select)(c.current).transition().duration(200).call(l.current.scaleBy,1/Tt)},[]);return{zoomRef:c,state:{transform:f,isZoomed:f.k!==1||f.x!==0||f.y!==0},zoomedXScale:d,zoomedYScale:h,resetZoom:g,zoomIn:b,zoomOut:x}}var O=require("react");function Me(e,t,r,o,n,a,s){let i=o-r;if(i<=s){let f=[];for(let u=r;u<o;u++)f.push({px:n(e[u]),py:a(t[u]),index:u});return f}let c=[];c.push({px:n(e[r]),py:a(t[r]),index:r});let l=s-2,m=(i-2)/l,p=r;for(let f=0;f<l;f++){let u=r+1+Math.floor(f*m),d=r+1+Math.min(Math.floor((f+1)*m),i-2),h=d,g=r+1+Math.min(Math.floor((f+2)*m),i-2),b,x;if(f===l-1)b=n(e[o-1]),x=a(t[o-1]);else{b=0,x=0;let C=g-h;for(let w=h;w<g;w++)b+=n(e[w]),x+=a(t[w]);C>0&&(b/=C,x/=C)}let S=n(e[p]),v=a(t[p]),y=-1,k=u;for(let C=u;C<d;C++){let w=n(e[C]),R=a(t[C]),T=Math.abs((S-b)*(R-v)-(S-w)*(x-v));T>y&&(y=T,k=C)}c.push({px:n(e[k]),py:a(t[k]),index:k}),p=k}return c.push({px:n(e[o-1]),py:a(t[o-1]),index:o-1}),c}var Ur=1.5,$r={solid:[],dashed:[8,4],dotted:[2,2],"dash-dot":[8,4,2,4]},Nr=2e3;function Ir(e,t,r){e.clearRect(0,0,t,r)}function Or(e,t,r,o,n,a,s){let{highlighted:i=!1,opacity:c=1}=s??{},l=Math.min(t.x.length,t.y.length);if(l<2)return;let m=t.color??L(r),p=t.lineWidth??Ur,f=i?p+1:p,u=$r[t.lineStyle??"solid"]??[],[d,h]=o.domain(),g=Math.min(d,h),b=Math.max(d,h),x=0,S=l;for(let y=0;y<l;y++)if(t.x[y]>=g||y<l-1&&t.x[y+1]>=g){x=Math.max(0,y-1);break}for(let y=l-1;y>=0;y--)if(t.x[y]<=b||y>0&&t.x[y-1]<=b){S=Math.min(l,y+2);break}let v=S-x;if(e.save(),e.beginPath(),e.strokeStyle=m,e.lineWidth=f,e.globalAlpha=c,e.lineJoin="round",e.setLineDash(u),v>Nr){let y=Math.max(Math.ceil(a*2),200),k=Me(t.x,t.y,x,S,o,n,y);if(k.length>0){e.moveTo(k[0].px,k[0].py);for(let C=1;C<k.length;C++)e.lineTo(k[C].px,k[C].py)}}else{let y=!1;for(let k=x;k<S;k++){let C=o(t.x[k]),w=n(t.y[k]);y?e.lineTo(C,w):(e.moveTo(C,w),y=!0)}}e.stroke(),e.restore()}function At(e,t,r,o,n,a,s){Ir(e,n,a),t.forEach((i,c)=>{i.visible!==!1&&Or(e,i,c,r,o,n,{highlighted:i.id===s,opacity:s&&i.id!==s?.3:1})})}var Et=require("react/jsx-runtime"),ae=(0,O.forwardRef)(function({spectra:t,xScale:r,yScale:o,width:n,height:a,highlightedId:s},i){let c=(0,O.useRef)(null),l=(0,O.useRef)(1);return(0,O.useImperativeHandle)(i,()=>c.current,[]),(0,O.useEffect)(()=>{let m=c.current;if(!m)return;let p=window.devicePixelRatio||1;l.current=p,m.width=n*p,m.height=a*p},[n,a]),(0,O.useEffect)(()=>{let m=c.current;if(!m)return;let p=m.getContext("2d");if(!p)return;let f=l.current;p.setTransform(f,0,0,f,0,0),At(p,t,r,o,n,a,s)},[t,r,o,n,a,s]),(0,Et.jsx)("canvas",{ref:c,style:{width:n,height:a,position:"absolute",top:0,left:0,pointerEvents:"none"}})});var E=require("react/jsx-runtime");function Lt(e,t){let[r,o]=e.domain(),n=Math.min(r,o),s=(Math.max(r,o)-n)/(t-1);return Array.from({length:t},(i,c)=>n+c*s)}function Pt(e){return Math.abs(e)>=1e3?Math.round(e).toString():Math.abs(e)>=1?e.toFixed(1):Math.abs(e)>=.01?e.toFixed(3):e.toExponential(1)}function se({xScale:e,yScale:t,width:r,height:o,xLabel:n,yLabel:a,showGrid:s=!0,colors:i}){let c=Lt(e,8),l=Lt(t,6);return(0,E.jsxs)("g",{children:[s&&(0,E.jsxs)("g",{children:[c.map(m=>(0,E.jsx)("line",{x1:e(m),x2:e(m),y1:0,y2:o,stroke:i.gridColor,strokeWidth:.5},`xgrid-${m}`)),l.map(m=>(0,E.jsx)("line",{x1:0,x2:r,y1:t(m),y2:t(m),stroke:i.gridColor,strokeWidth:.5},`ygrid-${m}`))]}),(0,E.jsxs)("g",{transform:`translate(0, ${o})`,children:[(0,E.jsx)("line",{x1:0,x2:r,y1:0,y2:0,stroke:i.axisColor}),c.map(m=>(0,E.jsxs)("g",{transform:`translate(${e(m)}, 0)`,children:[(0,E.jsx)("line",{y1:0,y2:6,stroke:i.axisColor}),(0,E.jsx)("text",{y:20,textAnchor:"middle",fill:i.tickColor,fontSize:11,fontFamily:"system-ui, sans-serif",children:Pt(m)})]},`xtick-${m}`)),n&&(0,E.jsx)("text",{x:r/2,y:42,textAnchor:"middle",fill:i.labelColor,fontSize:13,fontFamily:"system-ui, sans-serif",children:n})]}),(0,E.jsxs)("g",{children:[(0,E.jsx)("line",{x1:0,x2:0,y1:0,y2:o,stroke:i.axisColor}),l.map(m=>(0,E.jsxs)("g",{transform:`translate(0, ${t(m)})`,children:[(0,E.jsx)("line",{x1:-6,x2:0,stroke:i.axisColor}),(0,E.jsx)("text",{x:-10,textAnchor:"end",dominantBaseline:"middle",fill:i.tickColor,fontSize:11,fontFamily:"system-ui, sans-serif",children:Pt(m)})]},`ytick-${m}`)),a&&(0,E.jsx)("text",{transform:`translate(-50, ${o/2}) rotate(-90)`,textAnchor:"middle",fill:i.labelColor,fontSize:13,fontFamily:"system-ui, sans-serif",children:a})]})]})}var le=require("react/jsx-runtime");function Re({peaks:e,xScale:t,yScale:r,colors:o,onPeakClick:n}){let[a,s]=t.domain(),i=Math.min(a,s),c=Math.max(a,s),l=e.filter(m=>m.x>=i&&m.x<=c);return(0,le.jsx)("g",{className:"spectraview-peaks",children:l.map((m,p)=>{let f=t(m.x),u=r(m.y);return(0,le.jsxs)("g",{transform:`translate(${f}, ${u})`,style:{cursor:n?"pointer":"default"},onClick:()=>n?.(m),children:[(0,le.jsx)("polygon",{points:`0,-5 -5,${-5*2.5} 5,${-5*2.5}`,fill:o.labelColor,opacity:.8}),m.label&&(0,le.jsx)("text",{y:-5*2.5-14,textAnchor:"middle",fill:o.labelColor,fontSize:10,fontFamily:"system-ui, sans-serif",fontWeight:500,children:m.label})]},`peak-${m.x}-${p}`)})})}var ce=require("react/jsx-runtime");function Te({regions:e,xScale:t,height:r,colors:o}){return(0,ce.jsx)("g",{className:"spectraview-regions",children:e.map((n,a)=>{let s=t(n.xStart),i=t(n.xEnd),c=Math.min(s,i),l=Math.abs(i-s);return(0,ce.jsxs)("g",{children:[(0,ce.jsx)("rect",{x:c,y:0,width:l,height:r,fill:n.color??o.regionFill,stroke:o.regionStroke,strokeWidth:1}),n.label&&(0,ce.jsx)("text",{x:c+l/2,y:12,textAnchor:"middle",fill:o.labelColor,fontSize:10,fontFamily:"system-ui, sans-serif",children:n.label})]},`region-${a}`)})})}var B=require("react/jsx-runtime");function Ae({position:e,width:t,height:r,colors:o,snapPoint:n}){return e?(0,B.jsxs)("g",{className:"spectraview-crosshair",pointerEvents:"none",children:[(0,B.jsx)("line",{x1:e.px,x2:e.px,y1:0,y2:r,stroke:o.crosshairColor,strokeWidth:1,strokeDasharray:"4 4"}),(0,B.jsx)("line",{x1:0,x2:t,y1:e.py,y2:e.py,stroke:o.crosshairColor,strokeWidth:1,strokeDasharray:"4 4"}),n&&(0,B.jsx)("circle",{cx:n.px,cy:n.py,r:4,fill:n.color??o.crosshairColor,stroke:o.background,strokeWidth:1.5}),(0,B.jsxs)("g",{transform:`translate(${Math.min(e.px+10,t-100)}, ${Math.max(e.py-10,20)})`,children:[(0,B.jsx)("rect",{x:0,y:-14,width:90,height:18,rx:3,fill:o.tooltipBg,stroke:o.tooltipBorder,strokeWidth:.5,opacity:.9}),(0,B.jsxs)("text",{x:5,y:0,fill:o.tooltipText,fontSize:10,fontFamily:"monospace",children:[Ft(n?.dataX??e.dataX),","," ",Ft(n?.dataY??e.dataY)]})]})]}):null}function Ft(e){return Math.abs(e)>=100?Math.round(e).toString():Math.abs(e)>=1?e.toFixed(1):e.toFixed(4)}var G=require("react/jsx-runtime");function Ee({annotations:e,xScale:t,yScale:r,colors:o}){return e.length===0?null:(0,G.jsx)("g",{className:"spectraview-annotations",pointerEvents:"none",children:e.map(n=>{let a=t(n.x),s=r(n.y),[i,c]=n.offset??[0,-20],l=a+i,m=s+c,p=n.fontSize??11,f=n.color??o.tickColor,u=n.showAnchorLine!==!1;return(0,G.jsxs)("g",{children:[u&&(0,G.jsx)("line",{x1:a,y1:s,x2:l,y2:m,stroke:f,strokeWidth:.75,strokeDasharray:"3 2",opacity:.6}),(0,G.jsx)("circle",{cx:a,cy:s,r:2.5,fill:f,opacity:.8}),(0,G.jsx)("text",{x:l,y:m,fill:o.background,fontSize:p,fontFamily:"system-ui, sans-serif",textAnchor:"middle",dominantBaseline:"auto",stroke:o.background,strokeWidth:3,strokeLinejoin:"round",children:n.text}),(0,G.jsx)("text",{x:l,y:m,fill:f,fontSize:p,fontFamily:"system-ui, sans-serif",textAnchor:"middle",dominantBaseline:"auto",children:n.text})]},n.id)})})}function pe(e,t,r){if(r===0)return-1;if(r===1)return 0;let o=e[r-1]>=e[0],n=0,a=r-1;for(;n<a-1;){let c=n+a>>>1,l=e[c];o?l<=t?n=c:a=c:l>=t?n=c:a=c}let s=Math.abs(e[n]-t),i=Math.abs(e[a]-t);return s<=i?n:a}function Le(e,t,r,o,n){let a=null;for(let s of e){if(s.visible===!1)continue;let i=Math.min(s.x.length,s.y.length);if(i<2)continue;let c=pe(s.x,t,i);if(c<0)continue;let l=s.x[c],m=s.y[c],p=Math.abs(o(l)-o(t)),f=Math.abs(n(m)-r),u=Math.sqrt(p*p+f*f);(!a||u<a.distance)&&(a={spectrumId:s.id,index:c,x:l,y:m,distance:u})}return a}var Dt=require("react"),ue=require("react/jsx-runtime"),pt=e=>({display:"inline-flex",alignItems:"center",justifyContent:"center",width:28,height:28,border:`1px solid ${e==="dark"?"#4b5563":"#d1d5db"}`,borderRadius:4,background:e==="dark"?"#1f2937":"#ffffff",color:e==="dark"?"#d1d5db":"#374151",fontSize:14,cursor:"pointer",padding:0,lineHeight:1}),zr=e=>({display:"flex",gap:4,padding:"4px 0",borderBottom:`1px solid ${e==="dark"?"#374151":"#e5e7eb"}`}),Pe=(0,Dt.memo)(function({onZoomIn:t,onZoomOut:r,onReset:o,isZoomed:n,theme:a}){return(0,ue.jsxs)("div",{style:zr(a),className:"spectraview-toolbar",children:[(0,ue.jsx)("button",{type:"button",style:pt(a),onClick:t,title:"Zoom in","aria-label":"Zoom in",children:"+"}),(0,ue.jsx)("button",{type:"button",style:pt(a),onClick:r,title:"Zoom out","aria-label":"Zoom out",children:"\u2212"}),(0,ue.jsx)("button",{type:"button",style:{...pt(a),opacity:n?1:.4},onClick:o,disabled:!n,title:"Reset zoom","aria-label":"Reset zoom",children:"\u21BA"})]})});var Ut=require("react");var me=require("react/jsx-runtime"),Vr=(e,t)=>({display:"flex",flexDirection:t==="left"||t==="right"?"column":"row",flexWrap:"wrap",gap:6,padding:"4px 8px",fontSize:12,fontFamily:"system-ui, sans-serif",borderTop:t==="bottom"?`1px solid ${e==="dark"?"#374151":"#e5e7eb"}`:void 0,borderBottom:t==="top"?`1px solid ${e==="dark"?"#374151":"#e5e7eb"}`:void 0,borderLeft:t==="right"?`1px solid ${e==="dark"?"#374151":"#e5e7eb"}`:void 0,borderRight:t==="left"?`1px solid ${e==="dark"?"#374151":"#e5e7eb"}`:void 0}),Br=(e,t,r)=>({display:"inline-flex",alignItems:"center",gap:4,cursor:"pointer",opacity:t?.4:1,fontWeight:r?600:400,color:e==="dark"?"#e5e7eb":"#374151",userSelect:"none",padding:"2px 4px",borderRadius:3,background:r?e==="dark"?"rgba(255,255,255,0.08)":"rgba(0,0,0,0.04)":"transparent",transition:"background 0.15s, opacity 0.15s"}),Hr=(e,t)=>({width:12,height:3,borderRadius:1,background:e,opacity:t?.4:1,flexShrink:0}),fe=(0,Ut.memo)(function({spectra:t,theme:r,position:o,onToggleVisibility:n,onHighlight:a,highlightedId:s}){return t.length<=1?null:(0,me.jsx)("div",{className:"spectraview-legend",style:Vr(r,o),role:"list","aria-label":"Spectrum legend",children:t.map((i,c)=>{let l=i.color??L(c),m=i.visible===!1,p=s===i.id;return(0,me.jsxs)("div",{role:"listitem",style:Br(r,m,p),onClick:()=>n?.(i.id),onMouseEnter:()=>a?.(i.id),onMouseLeave:()=>a?.(null),title:m?`Show ${i.label}`:`Hide ${i.label}`,children:[(0,me.jsx)("span",{style:Hr(l,m)}),(0,me.jsx)("span",{style:{textDecoration:m?"line-through":"none",maxWidth:120,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:i.label})]},i.id)})})});var ee=require("react"),De=require("react/jsx-runtime");function Fe({enabled:e,theme:t,width:r,height:o,onDrop:n,children:a}){let[s,i]=(0,ee.useState)(!1),c={current:0},l=(0,ee.useCallback)(u=>{e&&(u.preventDefault(),c.current++,i(!0))},[e]),m=(0,ee.useCallback)(u=>{e&&(u.preventDefault(),c.current--,c.current<=0&&(c.current=0,i(!1)))},[e]),p=(0,ee.useCallback)(u=>{e&&(u.preventDefault(),u.dataTransfer.dropEffect="copy")},[e]),f=(0,ee.useCallback)(u=>{if(!e)return;u.preventDefault(),c.current=0,i(!1);let d=Array.from(u.dataTransfer.files);d.length>0&&n?.(d)},[e,n]);return(0,De.jsxs)("div",{style:{position:"relative",width:r,height:o},onDragEnter:l,onDragLeave:m,onDragOver:p,onDrop:f,children:[a,s&&(0,De.jsx)("div",{"data-testid":"dropzone-overlay",style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",background:t==="dark"?"rgba(30, 58, 138, 0.6)":"rgba(59, 130, 246, 0.15)",border:`2px dashed ${t==="dark"?"#60a5fa":"#3b82f6"}`,borderRadius:4,zIndex:100,pointerEvents:"none",fontSize:14,fontFamily:"system-ui, sans-serif",color:t==="dark"?"#93c5fd":"#1d4ed8",fontWeight:500},children:"Drop spectrum files here"})]})}var Nt=require("react");var H=require("react/jsx-runtime"),$t=8;function Ue({spectra:e,xScale:t,plotWidth:r,plotHeight:o,margin:n,theme:a,showGrid:s,xLabel:i,yLabel:c}){let l=e.filter(d=>d.visible!==!1),m=(0,Nt.useMemo)(()=>I(a),[a]),p=l.length,f=(p-1)*$t,u=Math.max(40,Math.floor((o-f)/Math.max(p,1)));return(0,H.jsx)("g",{className:"spectraview-stacked",children:l.map((d,h)=>{let g=h*(u+$t),b=ne([d]),x=oe(b,u+n.top+n.bottom,{...n,top:0,bottom:0}),S=d.color??L(h),v={...d,color:S};return(0,H.jsxs)("g",{transform:`translate(0, ${g})`,children:[(0,H.jsx)("rect",{x:0,y:0,width:r,height:u,fill:"transparent",stroke:m.gridColor,strokeWidth:.5,rx:2}),(0,H.jsx)(se,{xScale:t,yScale:x,width:r,height:u,xLabel:h===p-1?i:"",yLabel:c,showGrid:s,colors:m}),(0,H.jsx)("text",{x:4,y:14,fill:S,fontSize:11,fontFamily:"system-ui, sans-serif",fontWeight:500,children:d.label}),(0,H.jsx)("foreignObject",{x:0,y:0,width:r,height:u,children:(0,H.jsx)(ae,{spectra:[v],xScale:t,yScale:x,width:r,height:u})})]},d.id)})})}var K=require("react");function $e(e){let{enabled:t,xScale:r,onRegionSelect:o}=e,[n,a]=(0,K.useState)(null),s=(0,K.useRef)(null),i=(0,K.useCallback)(m=>{if(!t||!m.shiftKey)return;m.preventDefault();let p=m.currentTarget.getBoundingClientRect(),f=m.clientX-p.left,u=r.invert(f);s.current=u,a({xStart:u,xEnd:u})},[t,r]),c=(0,K.useCallback)(m=>{if(s.current===null)return;let p=m.currentTarget.getBoundingClientRect(),f=m.clientX-p.left,u=r.invert(f),d=s.current;a({xStart:Math.min(d,u),xEnd:Math.max(d,u)})},[r]),l=(0,K.useCallback)(()=>{if(s.current===null||!n)return;Math.abs(n.xEnd-n.xStart)>0&&o?.(n),s.current=null,a(null)},[n,o]);return{pendingRegion:n,handleMouseDown:i,handleMouseMove:c,handleMouseUp:l}}var Z=require("react");function Ne(){let[e,t]=(0,Z.useState)(null),r=(0,Z.useRef)(null),o=(0,Z.useRef)(null),n=(0,Z.useCallback)(a=>{if(r.current&&(r.current.disconnect(),r.current=null),o.current=a,!a)return;let s=new ResizeObserver(l=>{let m=l[0];if(!m)return;let{width:p,height:f}=m.contentRect;t({width:Math.round(p),height:Math.round(f)})});s.observe(a),r.current=s;let{width:i,height:c}=a.getBoundingClientRect();t({width:Math.round(i),height:Math.round(c)})},[]);return(0,Z.useEffect)(()=>()=>{r.current?.disconnect()},[]),{ref:n,size:e}}var It=require("react");function Ie(e){let{onZoomIn:t,onZoomOut:r,onReset:o,enabled:n=!0}=e;return(0,It.useCallback)(s=>{if(n)switch(s.key){case"+":case"=":s.preventDefault(),t();break;case"-":s.preventDefault(),r();break;case"Escape":s.preventDefault(),o();break}},[n,t,r,o])}function Ot(){return typeof window>"u"?!1:window.matchMedia("(prefers-reduced-motion: reduce)").matches}function Oe(e,t,r){return e===0?"Empty spectrum viewer":`Interactive spectrum viewer showing ${e} ${e===1?"spectrum":"spectra"}. X-axis: ${t}. Y-axis: ${r}. Use arrow keys to pan, +/- to zoom, Escape to reset.`}var zt={PAN_LEFT:"ArrowLeft",PAN_RIGHT:"ArrowRight",PAN_UP:"ArrowUp",PAN_DOWN:"ArrowDown",ZOOM_IN:"+",ZOOM_IN_ALT:"=",ZOOM_OUT:"-",RESET:"Escape",NEXT_PEAK:"Tab",PREV_PEAK:"Shift+Tab"};var M=require("react/jsx-runtime"),Zr={top:20,right:20,bottom:50,left:65},_r=800,Xr=400;function Wr(e){return{width:e.width??_r,height:e.height??Xr,reverseX:e.reverseX??!1,showGrid:e.showGrid??!0,showCrosshair:e.showCrosshair??!0,showToolbar:e.showToolbar??!0,showLegend:e.showLegend??!0,legendPosition:e.legendPosition??"bottom",displayMode:e.displayMode??"overlay",margin:{...Zr,...e.margin},theme:e.theme??"light",responsive:e.responsive??!1,enableDragDrop:e.enableDragDrop??!1,enableRegionSelect:e.enableRegionSelect??!1}}function jr(e,t,r){let o=e[0];return{xLabel:t??o?.xUnit??"x",yLabel:r??o?.yUnit??"y"}}function Vt(e){let{spectra:t,peaks:r=[],regions:o=[],annotations:n=[],onPeakClick:a,onViewChange:s,onCrosshairMove:i,onToggleVisibility:c,onFileDrop:l,onRegionSelect:m,canvasRef:p,snapCrosshair:f=!0}=e,{ref:u,size:d}=Ne(),g=`spectraview-clip-${(0,A.useId)().replace(/:/g,"")}`,b=(0,A.useMemo)(()=>Wr(e),[e.width,e.height,e.reverseX,e.showGrid,e.showCrosshair,e.showToolbar,e.showLegend,e.legendPosition,e.displayMode,e.margin,e.theme,e.responsive,e.enableDragDrop,e.enableRegionSelect]),x=b.responsive&&d?d.width:b.width,{height:S,margin:v,reverseX:y,theme:k}=b,C=x-v.left-v.right,w=S-v.top-v.bottom,R=(0,A.useMemo)(()=>I(k),[k]),T=(0,A.useMemo)(()=>jr(t,e.xLabel,e.yLabel),[t,e.xLabel,e.yLabel]),re=(0,A.useMemo)(()=>ve(t),[t]),U=(0,A.useMemo)(()=>ne(t),[t]),tt=(0,A.useMemo)(()=>ke(re,x,v,y),[re,x,v,y]),q=(0,A.useMemo)(()=>oe(U,S,v),[U,S,v]),Q=(0,A.useRef)(s);Q.current=s;let gr=(0,A.useMemo)(()=>(j,ye)=>{Q.current?.({xDomain:j,yDomain:ye})},[]),{zoomRef:ht,state:hr,zoomedXScale:D,zoomedYScale:W,resetZoom:xt,zoomIn:yt,zoomOut:St}=we({plotWidth:C,plotHeight:w,xScale:tt,yScale:q,onViewChange:s?gr:void 0}),{pendingRegion:he,handleMouseDown:xr,handleMouseMove:yr,handleMouseUp:Sr}=$e({enabled:b.enableRegionSelect,xScale:D,onRegionSelect:m}),[rt,vt]=(0,A.useState)(null),[vr,kt]=(0,A.useState)(null),[kr,nt]=(0,A.useState)(null),xe=(0,A.useRef)(i);xe.current=i;let Ct=(0,A.useCallback)(j=>{if(!b.showCrosshair)return;let ye=j.currentTarget.getBoundingClientRect(),Mt=j.clientX-ye.left,it=j.clientY-ye.top,Se=D.invert(Mt),at=W.invert(it);if(kt({px:Mt,py:it,dataX:Se,dataY:at}),f&&t.length>0){let V=Le(t,Se,it,D,W);if(V&&V.distance<50){let Rt=t.findIndex(Rr=>Rr.id===V.spectrumId);nt({px:D(V.x),py:W(V.y),dataX:V.x,dataY:V.y,color:t[Rt]?.color??L(Rt)}),xe.current?.(V.x,V.y)}else nt(null),xe.current?.(Se,at)}else xe.current?.(Se,at)},[D,W,b.showCrosshair,f,t]),wt=(0,A.useCallback)(()=>{kt(null),nt(null)},[]),Cr=Ie({onZoomIn:yt,onZoomOut:St,onReset:xt}),wr=(0,A.useMemo)(()=>Oe(t.length,T.xLabel,T.yLabel),[t.length,T.xLabel,T.yLabel]),Mr=b.displayMode==="stacked";if(t.length===0)return(0,M.jsx)("div",{ref:b.responsive?u:void 0,style:{width:b.responsive?"100%":x,height:S,display:"flex",alignItems:"center",justifyContent:"center",border:`1px dashed ${R.gridColor}`,borderRadius:8,color:R.tickColor,fontFamily:"system-ui, sans-serif",fontSize:14},className:e.className,children:"No spectra loaded"});let ot=b.showToolbar?37:0;return(0,M.jsxs)("div",{ref:b.responsive?u:void 0,style:{width:b.responsive?"100%":x,background:R.background,borderRadius:4,overflow:"hidden"},className:e.className,role:"img","aria-label":wr,tabIndex:0,onKeyDown:Cr,children:[b.showToolbar&&(0,M.jsx)(Pe,{onZoomIn:yt,onZoomOut:St,onReset:xt,isZoomed:hr.isZoomed,theme:k}),b.showLegend&&b.legendPosition==="top"&&(0,M.jsx)(fe,{spectra:t,theme:k,position:"top",onToggleVisibility:c,onHighlight:vt,highlightedId:rt}),(0,M.jsx)(Fe,{enabled:b.enableDragDrop,theme:k,width:x,height:S-ot,onDrop:l,children:Mr?(0,M.jsx)("svg",{width:x,height:S-ot,style:{position:"absolute",top:0,left:0},children:(0,M.jsxs)("g",{transform:`translate(${v.left}, ${v.top})`,children:[(0,M.jsx)(Ue,{spectra:t,xScale:D,plotWidth:C,plotHeight:w,margin:v,theme:k,showGrid:b.showGrid,xLabel:T.xLabel,yLabel:T.yLabel}),(0,M.jsx)("rect",{ref:ht,x:0,y:0,width:C,height:w,fill:"transparent",style:{cursor:"grab"},onMouseMove:Ct,onMouseLeave:wt})]})}):(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)("div",{style:{position:"absolute",top:v.top,left:v.left,width:C,height:w,overflow:"hidden"},children:(0,M.jsx)(ae,{ref:p,spectra:t,xScale:D,yScale:W,width:C,height:w,highlightedId:rt??void 0})}),(0,M.jsx)("svg",{width:x,height:S-ot,style:{position:"absolute",top:0,left:0},children:(0,M.jsxs)("g",{transform:`translate(${v.left}, ${v.top})`,children:[(0,M.jsx)(se,{xScale:D,yScale:W,width:C,height:w,xLabel:T.xLabel,yLabel:T.yLabel,showGrid:b.showGrid,colors:R}),(0,M.jsx)("defs",{children:(0,M.jsx)("clipPath",{id:g,children:(0,M.jsx)("rect",{x:0,y:0,width:C,height:w})})}),(0,M.jsxs)("g",{clipPath:`url(#${g})`,children:[o.length>0&&(0,M.jsx)(Te,{regions:o,xScale:D,height:w,colors:R}),r.length>0&&(0,M.jsx)(Re,{peaks:r,xScale:D,yScale:W,colors:R,onPeakClick:a})]}),n.length>0&&(0,M.jsx)(Ee,{annotations:n,xScale:D,yScale:W,colors:R}),b.showCrosshair&&(0,M.jsx)(Ae,{position:vr,width:C,height:w,colors:R,snapPoint:kr}),he&&(0,M.jsx)("rect",{x:D(he.xStart),y:0,width:Math.abs(D(he.xEnd)-D(he.xStart)),height:w,fill:R.regionFill,stroke:R.regionStroke,strokeWidth:1,pointerEvents:"none"}),(0,M.jsx)("rect",{ref:ht,x:0,y:0,width:C,height:w,fill:"transparent",style:{cursor:b.showCrosshair?"crosshair":"grab"},onMouseDown:xr,onMouseMove:j=>{Ct(j),yr(j)},onMouseUp:Sr,onMouseLeave:wt})]})})]})}),b.showLegend&&b.legendPosition==="bottom"&&(0,M.jsx)(fe,{spectra:t,theme:k,position:"bottom",onToggleVisibility:c,onHighlight:vt,highlightedId:rt})]})}var z=require("react"),ft=require("d3-scale");var J=require("react/jsx-runtime"),Bt=(0,z.memo)(function({spectra:t,xExtent:r,yExtent:o,visibleXDomain:n,width:a=200,height:s=50,theme:i="light",isZoomed:c=!1}){let l=(0,z.useRef)(null),m=(0,z.useMemo)(()=>I(i),[i]),p=(0,z.useMemo)(()=>(0,ft.scaleLinear)().domain(r).range([0,a]),[r,a]),f=(0,z.useMemo)(()=>(0,ft.scaleLinear)().domain(o).range([s-2,2]),[o,s]);(0,z.useEffect)(()=>{let g=l.current?.getContext("2d");if(g){g.clearRect(0,0,a,s);for(let b=0;b<t.length;b++){let x=t[b];if(x.visible===!1)continue;let S=Math.min(x.x.length,x.y.length);if(S<2)continue;let v=x.color??L(b);g.beginPath(),g.strokeStyle=v,g.lineWidth=1,g.globalAlpha=.7;let y=Math.max(1,Math.floor(S/a)),k=!1;for(let C=0;C<S;C+=y){let w=p(x.x[C]),R=f(x.y[C]);k?g.lineTo(w,R):(g.moveTo(w,R),k=!0)}g.stroke()}}},[t,p,f,a,s]);let u=p(Math.min(n[0],n[1])),d=p(Math.max(n[0],n[1])),h=Math.max(d-u,2);return(0,J.jsxs)("div",{className:"spectraview-minimap",style:{position:"relative",width:a,height:s,border:`1px solid ${m.gridColor}`,borderRadius:3,overflow:"hidden",background:m.background},children:[(0,J.jsx)("canvas",{ref:l,width:a,height:s,style:{position:"absolute",top:0,left:0}}),c&&(0,J.jsxs)("svg",{width:a,height:s,style:{position:"absolute",top:0,left:0},children:[(0,J.jsx)("rect",{x:0,y:0,width:u,height:s,fill:m.background,opacity:.6}),(0,J.jsx)("rect",{x:u+h,y:0,width:a-u-h,height:s,fill:m.background,opacity:.6}),(0,J.jsx)("rect",{x:u,y:0,width:h,height:s,fill:"none",stroke:i==="dark"?"#60a5fa":"#3b82f6",strokeWidth:1.5,rx:1})]})]})});var de=require("react");var _=require("react/jsx-runtime");function dt(e,t){switch(t){case"fixed2":return e.toFixed(2);case"fixed4":return e.toFixed(4);case"scientific":return e.toExponential(2);default:return Math.abs(e)>=100?Math.round(e).toString():Math.abs(e)>=1?e.toFixed(2):Math.abs(e)>=.01?e.toFixed(4):e.toExponential(2)}}var Ht=(0,de.memo)(function({data:t,spectra:r,peaks:o=[],plotWidth:n,plotHeight:a,colors:s,numberFormat:i="auto"}){let c=(0,de.useMemo)(()=>t?r.filter(b=>b.visible!==!1).map((b,x)=>{let S=Math.min(b.x.length,b.y.length);if(S<1)return null;let v=pe(b.x,t.dataX,S);return v<0?null:{label:b.label,color:b.color??L(x),value:b.y[v],x:b.x[v]}}).filter(Boolean):[],[t,r]),l=(0,de.useMemo)(()=>{if(!t||o.length===0)return null;let b=null,x=1/0;for(let S of o){let v=Math.abs(S.x-t.dataX);v<x&&(x=v,b=S)}return b},[t,o]);if(!t)return null;let m=16,p=18,f=l?m:0,u=p+c.length*m+f+8,d=160,h=t.px+15,g=t.py-u/2;return h+d>n&&(h=t.px-d-15),g<0&&(g=4),g+u>a&&(g=a-u-4),(0,_.jsxs)("g",{className:"spectraview-tooltip",transform:`translate(${h}, ${g})`,pointerEvents:"none",children:[(0,_.jsx)("rect",{x:0,y:0,width:d,height:u,rx:4,fill:s.tooltipBg,stroke:s.tooltipBorder,strokeWidth:.5,opacity:.95}),(0,_.jsxs)("text",{x:8,y:14,fill:s.tooltipText,fontSize:10,fontFamily:"monospace",fontWeight:600,children:["x = ",dt(t.dataX,i)]}),c.map((b,x)=>(0,_.jsxs)("g",{transform:`translate(0, ${p+x*m})`,children:[(0,_.jsx)("circle",{cx:12,cy:8,r:3,fill:b.color}),(0,_.jsxs)("text",{x:20,y:11,fill:s.tooltipText,fontSize:9,fontFamily:"monospace",children:[b.label.slice(0,10),": ",dt(b.value,i)]})]},b.label)),l&&(0,_.jsxs)("text",{x:8,y:p+c.length*m+12,fill:s.labelColor,fontSize:9,fontFamily:"monospace",fontStyle:"italic",children:["Peak: ",l.label??dt(l.x,i)]})]})});var te=require("react");var F=require("react/jsx-runtime"),Zt=(0,te.memo)(function({spectrum:t,theme:r="light",maxRows:o=200,height:n=300,highlightRange:a}){let s=(0,te.useMemo)(()=>I(r),[r]),[i,c]=(0,te.useState)(!1),l=Math.min(t.x.length,t.y.length),m=(0,te.useMemo)(()=>{let g=Array.from({length:l},(b,x)=>x);return i&&g.reverse(),g.slice(0,o)},[l,i,o]),p=g=>{if(!a)return!1;let b=Math.min(a[0],a[1]),x=Math.max(a[0],a[1]);return g>=b&&g<=x},f=g=>Math.abs(g)>=100?g.toFixed(2):Math.abs(g)>=.01?g.toFixed(4):g.toExponential(3),u=r==="dark"?"#1f2937":"#f3f4f6",d=r==="dark"?"#374151":"#e5e7eb",h=r==="dark"?"rgba(59,130,246,0.15)":"rgba(59,130,246,0.08)";return(0,F.jsxs)("div",{className:"spectraview-datatable",style:{height:n,overflow:"auto",border:`1px solid ${d}`,borderRadius:4,fontFamily:"monospace",fontSize:12,color:s.tickColor,background:s.background},children:[(0,F.jsxs)("table",{style:{width:"100%",borderCollapse:"collapse"},children:[(0,F.jsx)("thead",{children:(0,F.jsxs)("tr",{style:{position:"sticky",top:0,background:u,borderBottom:`1px solid ${d}`},children:[(0,F.jsx)("th",{style:{padding:"6px 8px",textAlign:"right"},children:"#"}),(0,F.jsxs)("th",{style:{padding:"6px 8px",textAlign:"right",cursor:"pointer",userSelect:"none"},onClick:()=>c(g=>!g),title:"Click to reverse sort",children:[t.xUnit??"x"," ",i?"\u2191":"\u2193"]}),(0,F.jsx)("th",{style:{padding:"6px 8px",textAlign:"right"},children:t.yUnit??"y"})]})}),(0,F.jsx)("tbody",{children:m.map(g=>{let b=t.x[g],x=t.y[g];return(0,F.jsxs)("tr",{style:{background:p(b)?h:"transparent",borderBottom:`1px solid ${d}`},children:[(0,F.jsx)("td",{style:{padding:"3px 8px",textAlign:"right",opacity:.5},children:g}),(0,F.jsx)("td",{style:{padding:"3px 8px",textAlign:"right"},children:f(b)}),(0,F.jsx)("td",{style:{padding:"3px 8px",textAlign:"right"},children:f(x)})]},g)})})]}),l>o&&(0,F.jsxs)("div",{style:{padding:"6px 8px",textAlign:"center",fontSize:11,opacity:.6,borderTop:`1px solid ${d}`},children:["Showing ",o," of ",l," points"]})]})});var _t=require("react");function ze(e,t,r={}){let{prominence:o=.01,minDistance:n=5,maxPeaks:a}=r;if(e.length<3||t.length<3)return[];let s=1/0,i=-1/0;for(let u=0;u<t.length;u++)t[u]<s&&(s=t[u]),t[u]>i&&(i=t[u]);let c=i-s;if(c===0)return[];let l=o*c,m=[];for(let u=1;u<t.length-1;u++)if(t[u]>t[u-1]&&t[u]>t[u+1]){let d=Yr(t,u),h=Gr(t,u),g=t[u]-Math.max(d,h);g>=l&&m.push({index:u,prom:g})}m.sort((u,d)=>d.prom-u.prom);let p=[];for(let u of m)p.some(h=>Math.abs(h.index-u.index)<n)||p.push(u);return(a?p.slice(0,a):p).map(u=>({x:e[u.index],y:t[u.index],label:Kr(e[u.index])})).sort((u,d)=>u.x-d.x)}function Yr(e,t){let r=e[t];for(let o=t-1;o>=0&&!(e[o]>e[t]);o--)e[o]<r&&(r=e[o]);return r}function Gr(e,t){let r=e[t];for(let o=t+1;o<e.length&&!(e[o]>e[t]);o++)e[o]<r&&(r=e[o]);return r}function Kr(e){return Math.round(e).toString()}function Xt(e,t={}){let{enabled:r=!0,spectrumIds:o,prominence:n,minDistance:a,maxPeaks:s}=t;return(0,_t.useMemo)(()=>{if(!r)return[];let i=o?e.filter(l=>o.includes(l.id)):e,c=[];for(let l of i){if(l.visible===!1)continue;let m=ze(l.x,l.y,{prominence:n,minDistance:a,maxPeaks:s});for(let p of m)c.push({...p,spectrumId:l.id})}return c},[e,r,o,n,a,s])}var N=require("react");var Wt=0,Jr=[" ",",",";"," "];function jt(e){let t=e.trim().split(/\r?\n/).slice(0,5),r=",",o=0;for(let n of Jr){let a=t.map(i=>i.split(n).length-1),s=Math.min(...a);s>0&&s>=o&&(a.every(c=>c===a[0])||s>o)&&(o=s,r=n)}return r}function Ve(e,t={}){let{xColumn:r=0,yColumn:o=1,hasHeader:n=!0,label:a="CSV Spectrum"}=t,s=t.delimiter??jt(e),i=e.trim().split(/\r?\n/);if(i.length<2)throw new Error("CSV file must contain at least 2 lines");let c=a,l=0;if(n){let f=i[0].split(s).map(u=>u.trim());!t.label&&f[o]&&(c=f[o]),l=1}let m=[],p=[];for(let f=l;f<i.length;f++){let u=i[f].trim();if(u===""||u.startsWith("#"))continue;let d=u.split(s),h=parseFloat(d[r]),g=parseFloat(d[o]);!isNaN(h)&&!isNaN(g)&&(m.push(h),p.push(g))}if(m.length===0)throw new Error("No valid numeric data found in CSV");return{id:`csv-${++Wt}`,label:c,x:new Float64Array(m),y:new Float64Array(p)}}function Yt(e,t={}){let{hasHeader:r=!0,label:o}=t,n=t.delimiter??jt(e),a=e.trim().split(/\r?\n/);if(a.length<2)throw new Error("CSV file must contain at least 2 lines");let i=a[r?1:0].split(n).length;if(i<2)throw new Error("CSV must have at least 2 columns (x + y)");let c,l=0;r&&(c=a[0].split(n).map(u=>u.trim()),l=1);let m=[],p=Array.from({length:i-1},()=>[]);for(let u=l;u<a.length;u++){let d=a[u].trim();if(d===""||d.startsWith("#"))continue;let h=d.split(n),g=parseFloat(h[0]);if(!isNaN(g)){m.push(g);for(let b=1;b<i;b++){let x=parseFloat(h[b]);p[b-1].push(isNaN(x)?0:x)}}}let f=new Float64Array(m);return p.map((u,d)=>({id:`csv-${++Wt}`,label:o??c?.[d+1]??`Spectrum ${d+1}`,x:f,y:new Float64Array(u)}))}var qr=0;function Be(e){let t;try{t=JSON.parse(e)}catch{throw new Error("Invalid JSON: failed to parse input")}if(Array.isArray(t))return t.map((r,o)=>bt(r,o));if(typeof t=="object"&&t!==null){let r=t;return Array.isArray(r.spectra)?r.spectra.map((o,n)=>bt(o,n)):[bt(t,0)]}throw new Error("Invalid JSON structure: expected an object or array")}function bt(e,t){let r=e.x??e.wavenumbers??e.wavelengths;if(!r||!Array.isArray(r))throw new Error(`Spectrum ${t}: missing x-axis data (expected "x", "wavenumbers", or "wavelengths")`);let o=e.y??e.intensities??e.absorbance;if(!o||!Array.isArray(o))throw new Error(`Spectrum ${t}: missing y-axis data (expected "y", "intensities", or "absorbance")`);if(r.length!==o.length)throw new Error(`Spectrum ${t}: x and y arrays must have the same length (got ${r.length} and ${o.length})`);let n=e.label??e.title??e.name??`Spectrum ${t+1}`;return{id:`json-${++qr}`,label:n,x:new Float64Array(r),y:new Float64Array(o),xUnit:e.xUnit,yUnit:e.yUnit,type:e.type,meta:e.meta}}var Kt=0,He=null,Gt=!1;async function Qr(){if(Gt)return He;Gt=!0;try{He=await import("jcampconverter")}catch{He=null}return He}function Jt(e){let t=(e["DATA TYPE"]??e.DATATYPE??"").toLowerCase();return t.includes("infrared")||t.includes("ir")?"IR":t.includes("raman")?"Raman":t.includes("nir")||t.includes("near")?"NIR":t.includes("uv")||t.includes("vis")?"UV-Vis":t.includes("fluor")?"fluorescence":"other"}async function Ze(e){let t=await Qr();return t?en(e,t):[tn(e)]}function en(e,t){return t.convert(e,{keepRecordsRegExp:/.*/}).flatten.map((o,n)=>{let a=o.spectra?.[0]?.data?.[0];if(!a)throw new Error(`JCAMP block ${n}: no spectral data found`);return{id:`jcamp-${++Kt}`,label:o.info?.TITLE??`Spectrum ${n+1}`,x:new Float64Array(a.x),y:new Float64Array(a.y),xUnit:o.info?.XUNITS??"cm\u207B\xB9",yUnit:o.info?.YUNITS??"Absorbance",type:Jt(o.info),meta:o.info}})}function tn(e){let t=e.split(/\r?\n/),r={},o=[],n=[],a=!1;for(let s of t){let i=s.trim();if(i.startsWith("##")){let c=i.match(/^##(.+?)=\s*(.*)$/);if(c){let l=c[1].trim().toUpperCase(),m=c[2].trim();if(l==="XYDATA"||l==="XYPOINTS"){a=!0;continue}if(l==="END"){a=!1;continue}r[l]=m}continue}if(a&&i!==""){let c=i.split(/[\s,]+/).map(Number);if(c.length>=2&&!c.some(isNaN)){let l=c[0],m=parseFloat(r.FIRSTX??"0"),p=parseFloat(r.LASTX??"0"),f=parseInt(r.NPOINTS??"0",10);if(f>0&&c.length===2)o.push(c[0]),n.push(c[1]);else if(c.length>1){let u=f>1?(p-m)/(f-1):0;for(let d=1;d<c.length;d++)o.push(l+(d-1)*u),n.push(c[d])}}}}if(o.length===0)throw new Error("Failed to parse JCAMP-DX: no data found. Install jcampconverter for full format support.");return{id:`jcamp-${++Kt}`,label:r.TITLE??"JCAMP Spectrum",x:new Float64Array(o),y:new Float64Array(n),xUnit:r.XUNITS??"cm\u207B\xB9",yUnit:r.YUNITS??"Absorbance",type:Jt(r),meta:r}}function rn(e){switch(e.toLowerCase().split(".").pop()){case"dx":case"jdx":case"jcamp":return"jcamp";case"csv":case"tsv":case"txt":return"csv";case"json":return"json";default:return null}}function qt(e=[]){let[t,r]=(0,N.useState)(e),[o,n]=(0,N.useState)(!1),[a,s]=(0,N.useState)(null),i=(0,N.useCallback)(async(u,d)=>{n(!0),s(null);try{let h;switch(d){case"jcamp":h=await Ze(u);break;case"csv":h=[Ve(u)];break;case"json":h=Be(u);break}r(g=>[...g,...h])}catch(h){let g=h instanceof Error?h.message:"Failed to parse file";s(g)}finally{n(!1)}},[]),c=(0,N.useCallback)(async u=>{let d=rn(u.name);if(!d){s(`Unsupported file format: ${u.name}`);return}let h=await u.text();await i(h,d)},[i]),l=(0,N.useCallback)(u=>{r(d=>[...d,u])},[]),m=(0,N.useCallback)(u=>{r(d=>d.filter(h=>h.id!==u))},[]),p=(0,N.useCallback)(u=>{r(d=>d.map(h=>h.id===u?{...h,visible:h.visible===!1}:h))},[]),f=(0,N.useCallback)(()=>{r([]),s(null)},[]);return{spectra:t,loading:o,error:a,loadFile:c,loadText:i,addSpectrum:l,removeSpectrum:m,toggleVisibility:p,clear:f}}var be=require("react");var gt={solid:"",dashed:"8 4",dotted:"2 2","dash-dot":"8 4 2 4"};function _e(e,t,r,o){let{width:n,height:a,background:s="#ffffff",title:i}=o,c=e.filter(l=>l.visible!==!1).map((l,m)=>{let p=l.color??L(m),f=l.lineStyle??"solid",u=l.lineWidth??1.5,d=gt[f]??"",h=Math.min(l.x.length,l.y.length);if(h<2)return"";let g=[];for(let b=0;b<h;b++){let x=t(l.x[b]).toFixed(2),S=r(l.y[b]).toFixed(2);g.push(`${b===0?"M":"L"}${x},${S}`)}return`<path d="${g.join(" ")}" fill="none" stroke="${p}" stroke-width="${u}"${d?` stroke-dasharray="${d}"`:""}/>
3
3
  <!-- ${l.label} -->`}).filter(Boolean).join(`
4
4
  `);return`<?xml version="1.0" encoding="UTF-8"?>
5
5
  <svg xmlns="http://www.w3.org/2000/svg" width="${n}" height="${a}" viewBox="0 0 ${n} ${a}">
@@ -12,7 +12,7 @@
12
12
  `,l=Array.from(i.x).map((p,f)=>`${p},${i.y[f]}`),m=c+l.join(`
13
13
  `);We(new Blob([m],{type:"text/csv"}),a)}else{let i=Math.max(...s.map(p=>p.x.length)),c=s.map(p=>`${p.label}_x,${p.label}_y`).join(","),l=[];for(let p=0;p<i;p++){let f=s.map(u=>p<u.x.length?`${u.x[p]},${u.y[p]}`:",");l.push(f.join(","))}let m=c+`
14
14
  `+l.join(`
15
- `);We(new Blob([m],{type:"text/csv"}),a)}},[]),r=(0,be.useCallback)((n,a="spectra.json")=>{let i=n.filter(l=>l.visible!==!1).map(l=>({label:l.label,x:Array.from(l.x),y:Array.from(l.y),xUnit:l.xUnit,yUnit:l.yUnit,type:l.type})),c=JSON.stringify(i,null,2);We(new Blob([c],{type:"application/json"}),a)},[]),o=(0,be.useCallback)((n,a,s,i,c,l="spectrum.svg")=>{let m=_e(n,a,s,{width:i,height:c});Xe(m,l)},[]);return{exportPng:e,exportSvg:o,exportCsv:t,exportJson:r}}var tr=require("react");function je(e){let t=e.length;if(t<3)return new Float64Array(e);let r=[0];for(let s=1;s<t;s++){for(;r.length>=2;){let i=r.length-1,c=r[i-1],l=r[i];if((s-c)*(e[l]-e[c])-(l-c)*(e[s]-e[c])>=0)r.pop();else break}r.push(s)}let o=new Float64Array(t),n=0;for(let s=0;s<t;s++){for(;n<r.length-1&&r[n+1]<=s;)n++;if(n>=r.length-1)o[s]=e[r[r.length-1]];else{let i=r[n],c=r[n+1],l=(s-i)/(c-i);o[s]=e[i]*(1-l)+e[c]*l}}let a=new Float64Array(t);for(let s=0;s<t;s++)a[s]=e[s]-o[s];return a}function Ye(e){let t=e.length,r=new Float64Array(t),o=1/0,n=-1/0;for(let s=0;s<t;s++){let i=e[s];i<o&&(o=i),i>n&&(n=i)}let a=n-o;if(a===0)return r;for(let s=0;s<t;s++)r[s]=(e[s]-o)/a;return r}function Ge(e,t){let r=Math.min(e.length,t.length);if(r<2)return new Float64Array(t);let o=0;for(let a=1;a<r;a++)o+=Math.abs(e[a]-e[a-1])*(Math.abs(t[a])+Math.abs(t[a-1]))*.5;if(o===0)return new Float64Array(t);let n=new Float64Array(r);for(let a=0;a<r;a++)n[a]=t[a]/o;return n}function Ke(e){let t=e.length;if(t===0)return new Float64Array(0);let r=0;for(let i=0;i<t;i++)r+=e[i];let o=r/t,n=0;for(let i=0;i<t;i++){let c=e[i]-o;n+=c*c}let a=Math.sqrt(n/t);if(a===0)return new Float64Array(t);let s=new Float64Array(t);for(let i=0;i<t;i++)s[i]=(e[i]-o)/a;return s}function Je(e,t=5){let r=e.length;if(r<t||t<3)return new Float64Array(e);let o=t%2===0?t+1:t,n=(o-1)/2,a=nn(o),s=new Float64Array(r);for(let i=0;i<n;i++)s[i]=e[i],s[r-1-i]=e[r-1-i];for(let i=n;i<r-n;i++){let c=0;for(let l=-n;l<=n;l++)c+=a[l+n]*e[i+l];s[i]=c}return s}function nn(e){let t={5:[-3,12,17,12,-3].map(r=>r/35),7:[-2,3,6,7,6,3,-2].map(r=>r/21),9:[-21,14,39,54,59,54,39,14,-21].map(r=>r/231),11:[-36,9,44,69,84,89,84,69,44,9,-36].map(r=>r/429)};return t[e]?t[e]:Array(e).fill(1/e)}function qe(e,t){let r=Math.min(e.length,t.length);if(r<2)return new Float64Array(r);let o=new Float64Array(r);o[0]=(t[1]-t[0])/(e[1]-e[0]);for(let n=1;n<r-1;n++)o[n]=(t[n+1]-t[n-1])/(e[n+1]-e[n-1]);return o[r-1]=(t[r-1]-t[r-2])/(e[r-1]-e[r-2]),o}function er(e,t){let r=Math.min(e.length,t.length);if(r<3)return new Float64Array(r);let o=new Float64Array(r);for(let n=1;n<r-1;n++){let a=e[n]-e[n-1],s=e[n+1]-e[n],i=(a+s)/2;o[n]=(t[n+1]-2*t[n]+t[n-1])/(i*i)}return o[0]=o[1],o[r-1]=o[r-2],o}var on={none:"Raw","min-max":"Min-Max",area:"Area Normalized",snv:"SNV",baseline:"Baseline Corrected",smooth:"Smoothed",derivative:"1st Derivative"};function an(e,t,r){if(t==="none")return e;let o;switch(t){case"min-max":o=Ye(e.y);break;case"area":o=Ge(e.x,e.y);break;case"snv":o=Ke(e.y);break;case"baseline":o=je(e.y);break;case"smooth":o=Je(e.y,r);break;case"derivative":o=qe(e.x,e.y);break;default:return e}return{...e,y:o}}function rr({spectra:e,mode:t,smoothWindow:r=7}){return{spectra:(0,tr.useMemo)(()=>e.map(n=>an(n,t,r)),[e,t,r]),modeLabel:on[t]}}var N=require("react");function nr({initialState:e,maxDepth:t=50}){let[r,o]=(0,N.useState)(e),n=(0,N.useRef)([]),a=(0,N.useRef)([]),[s,i]=(0,N.useState)(0),[c,l]=(0,N.useState)(0),m=(0,N.useCallback)(d=>{o(h=>(n.current.push(h),n.current.length>t&&n.current.shift(),i(n.current.length),a.current=[],l(0),d))},[t]),p=(0,N.useCallback)(()=>{let d=n.current.pop();return d===void 0?!1:(o(h=>(a.current.push(h),l(a.current.length),i(n.current.length),d)),!0)},[]),f=(0,N.useCallback)(()=>{let d=a.current.pop();return d===void 0?!1:(o(h=>(n.current.push(h),i(n.current.length),l(a.current.length),d)),!0)},[]),u=(0,N.useCallback)(()=>{o(e),n.current=[],a.current=[],i(0),l(0)},[e]);return{state:r,push:m,undo:p,redo:f,reset:u,canUndo:s>0,canRedo:c>0,undoCount:s,redoCount:c}}var et=require("react"),W=require("react/jsx-runtime"),sn=e=>({display:"inline-flex",alignItems:"center",justifyContent:"center",height:28,padding:"0 8px",border:`1px solid ${e==="dark"?"#4b5563":"#d1d5db"}`,borderRadius:4,background:e==="dark"?"#1f2937":"#ffffff",color:e==="dark"?"#d1d5db":"#374151",fontSize:12,cursor:"pointer",lineHeight:1,position:"relative"}),ln=e=>({position:"absolute",top:30,left:0,background:e==="dark"?"#1f2937":"#ffffff",border:`1px solid ${e==="dark"?"#4b5563":"#d1d5db"}`,borderRadius:4,boxShadow:"0 2px 8px rgba(0,0,0,0.15)",zIndex:200,minWidth:100,overflow:"hidden"}),Qe=e=>({display:"block",width:"100%",padding:"6px 12px",border:"none",background:"transparent",color:e==="dark"?"#d1d5db":"#374151",fontSize:12,textAlign:"left",cursor:"pointer"});function or({theme:e,onExportPng:t,onExportSvg:r,onExportCsv:o,onExportJson:n}){let[a,s]=(0,et.useState)(!1),i=(0,et.useCallback)(c=>{s(!1),c?.()},[]);return(0,W.jsxs)("div",{style:{position:"relative",display:"inline-block"},children:[(0,W.jsx)("button",{type:"button",style:sn(e),onClick:()=>s(!a),"aria-label":"Export","aria-expanded":a,"aria-haspopup":"true",children:"Export"}),a&&(0,W.jsxs)("div",{style:ln(e),role:"menu",children:[t&&(0,W.jsx)("button",{type:"button",role:"menuitem",style:Qe(e),onClick:()=>i(t),children:"PNG Image"}),r&&(0,W.jsx)("button",{type:"button",role:"menuitem",style:Qe(e),onClick:()=>i(r),children:"SVG Vector"}),o&&(0,W.jsx)("button",{type:"button",role:"menuitem",style:Qe(e),onClick:()=>i(o),children:"CSV Data"}),n&&(0,W.jsx)("button",{type:"button",role:"menuitem",style:Qe(e),onClick:()=>i(n),children:"JSON Data"})]})]})}function ir(e,t={}){let{delimiter:r=",",includeHeader:o=!0,xRange:n,precision:a=6}=t,s=Math.min(e.x.length,e.y.length),i=[];if(o){let c=e.xUnit??"x",l=e.yUnit??"y";i.push(`${c}${r}${l}`)}for(let c=0;c<s;c++){let l=e.x[c];if(n){let p=Math.min(n[0],n[1]),f=Math.max(n[0],n[1]);if(l<p||l>f)continue}let m=e.y[c];i.push(`${l.toFixed(a)}${r}${m.toFixed(a)}`)}return i.join(`
15
+ `);We(new Blob([m],{type:"text/csv"}),a)}},[]),r=(0,be.useCallback)((n,a="spectra.json")=>{let i=n.filter(l=>l.visible!==!1).map(l=>({label:l.label,x:Array.from(l.x),y:Array.from(l.y),xUnit:l.xUnit,yUnit:l.yUnit,type:l.type})),c=JSON.stringify(i,null,2);We(new Blob([c],{type:"application/json"}),a)},[]),o=(0,be.useCallback)((n,a,s,i,c,l="spectrum.svg")=>{let m=_e(n,a,s,{width:i,height:c});Xe(m,l)},[]);return{exportPng:e,exportSvg:o,exportCsv:t,exportJson:r}}var tr=require("react");function je(e){let t=e.length;if(t<3)return new Float64Array(e);let r=[0];for(let s=1;s<t;s++){for(;r.length>=2;){let i=r.length-1,c=r[i-1],l=r[i];if((s-c)*(e[l]-e[c])-(l-c)*(e[s]-e[c])>=0)r.pop();else break}r.push(s)}let o=new Float64Array(t),n=0;for(let s=0;s<t;s++){for(;n<r.length-1&&r[n+1]<=s;)n++;if(n>=r.length-1)o[s]=e[r[r.length-1]];else{let i=r[n],c=r[n+1],l=(s-i)/(c-i);o[s]=e[i]*(1-l)+e[c]*l}}let a=new Float64Array(t);for(let s=0;s<t;s++)a[s]=e[s]-o[s];return a}function Ye(e){let t=e.length,r=new Float64Array(t),o=1/0,n=-1/0;for(let s=0;s<t;s++){let i=e[s];i<o&&(o=i),i>n&&(n=i)}let a=n-o;if(a===0)return r;for(let s=0;s<t;s++)r[s]=(e[s]-o)/a;return r}function Ge(e,t){let r=Math.min(e.length,t.length);if(r<2)return new Float64Array(t);let o=0;for(let a=1;a<r;a++)o+=Math.abs(e[a]-e[a-1])*(Math.abs(t[a])+Math.abs(t[a-1]))*.5;if(o===0)return new Float64Array(t);let n=new Float64Array(r);for(let a=0;a<r;a++)n[a]=t[a]/o;return n}function Ke(e){let t=e.length;if(t===0)return new Float64Array(0);let r=0;for(let i=0;i<t;i++)r+=e[i];let o=r/t,n=0;for(let i=0;i<t;i++){let c=e[i]-o;n+=c*c}let a=Math.sqrt(n/t);if(a===0)return new Float64Array(t);let s=new Float64Array(t);for(let i=0;i<t;i++)s[i]=(e[i]-o)/a;return s}function Je(e,t=5){let r=e.length;if(r<t||t<3)return new Float64Array(e);let o=t%2===0?t+1:t,n=(o-1)/2,a=nn(o),s=new Float64Array(r);for(let i=0;i<n;i++)s[i]=e[i],s[r-1-i]=e[r-1-i];for(let i=n;i<r-n;i++){let c=0;for(let l=-n;l<=n;l++)c+=a[l+n]*e[i+l];s[i]=c}return s}function nn(e){let t={5:[-3,12,17,12,-3].map(r=>r/35),7:[-2,3,6,7,6,3,-2].map(r=>r/21),9:[-21,14,39,54,59,54,39,14,-21].map(r=>r/231),11:[-36,9,44,69,84,89,84,69,44,9,-36].map(r=>r/429)};return t[e]?t[e]:Array(e).fill(1/e)}function qe(e,t){let r=Math.min(e.length,t.length);if(r<2)return new Float64Array(r);let o=new Float64Array(r);o[0]=(t[1]-t[0])/(e[1]-e[0]);for(let n=1;n<r-1;n++)o[n]=(t[n+1]-t[n-1])/(e[n+1]-e[n-1]);return o[r-1]=(t[r-1]-t[r-2])/(e[r-1]-e[r-2]),o}function er(e,t){let r=Math.min(e.length,t.length);if(r<3)return new Float64Array(r);let o=new Float64Array(r);for(let n=1;n<r-1;n++){let a=e[n]-e[n-1],s=e[n+1]-e[n],i=(a+s)/2;o[n]=(t[n+1]-2*t[n]+t[n-1])/(i*i)}return o[0]=o[1],o[r-1]=o[r-2],o}var on={none:"Raw","min-max":"Min-Max",area:"Area Normalized",snv:"SNV",baseline:"Baseline Corrected",smooth:"Smoothed",derivative:"1st Derivative"};function an(e,t,r){if(t==="none")return e;let o;switch(t){case"min-max":o=Ye(e.y);break;case"area":o=Ge(e.x,e.y);break;case"snv":o=Ke(e.y);break;case"baseline":o=je(e.y);break;case"smooth":o=Je(e.y,r);break;case"derivative":o=qe(e.x,e.y);break;default:return e}return{...e,y:o}}function rr({spectra:e,mode:t,smoothWindow:r=7}){return{spectra:(0,tr.useMemo)(()=>e.map(n=>an(n,t,r)),[e,t,r]),modeLabel:on[t]}}var $=require("react");function nr({initialState:e,maxDepth:t=50}){let[r,o]=(0,$.useState)(e),n=(0,$.useRef)([]),a=(0,$.useRef)([]),[s,i]=(0,$.useState)(0),[c,l]=(0,$.useState)(0),m=(0,$.useCallback)(d=>{o(h=>(n.current.push(h),n.current.length>t&&n.current.shift(),i(n.current.length),a.current=[],l(0),d))},[t]),p=(0,$.useCallback)(()=>{let d=n.current.pop();return d===void 0?!1:(o(h=>(a.current.push(h),l(a.current.length),i(n.current.length),d)),!0)},[]),f=(0,$.useCallback)(()=>{let d=a.current.pop();return d===void 0?!1:(o(h=>(n.current.push(h),i(n.current.length),l(a.current.length),d)),!0)},[]),u=(0,$.useCallback)(()=>{o(e),n.current=[],a.current=[],i(0),l(0)},[e]);return{state:r,push:m,undo:p,redo:f,reset:u,canUndo:s>0,canRedo:c>0,undoCount:s,redoCount:c}}var et=require("react"),X=require("react/jsx-runtime"),sn=e=>({display:"inline-flex",alignItems:"center",justifyContent:"center",height:28,padding:"0 8px",border:`1px solid ${e==="dark"?"#4b5563":"#d1d5db"}`,borderRadius:4,background:e==="dark"?"#1f2937":"#ffffff",color:e==="dark"?"#d1d5db":"#374151",fontSize:12,cursor:"pointer",lineHeight:1,position:"relative"}),ln=e=>({position:"absolute",top:30,left:0,background:e==="dark"?"#1f2937":"#ffffff",border:`1px solid ${e==="dark"?"#4b5563":"#d1d5db"}`,borderRadius:4,boxShadow:"0 2px 8px rgba(0,0,0,0.15)",zIndex:200,minWidth:100,overflow:"hidden"}),Qe=e=>({display:"block",width:"100%",padding:"6px 12px",border:"none",background:"transparent",color:e==="dark"?"#d1d5db":"#374151",fontSize:12,textAlign:"left",cursor:"pointer"});function or({theme:e,onExportPng:t,onExportSvg:r,onExportCsv:o,onExportJson:n}){let[a,s]=(0,et.useState)(!1),i=(0,et.useCallback)(c=>{s(!1),c?.()},[]);return(0,X.jsxs)("div",{style:{position:"relative",display:"inline-block"},children:[(0,X.jsx)("button",{type:"button",style:sn(e),onClick:()=>s(!a),"aria-label":"Export","aria-expanded":a,"aria-haspopup":"true",children:"Export"}),a&&(0,X.jsxs)("div",{style:ln(e),role:"menu",children:[t&&(0,X.jsx)("button",{type:"button",role:"menuitem",style:Qe(e),onClick:()=>i(t),children:"PNG Image"}),r&&(0,X.jsx)("button",{type:"button",role:"menuitem",style:Qe(e),onClick:()=>i(r),children:"SVG Vector"}),o&&(0,X.jsx)("button",{type:"button",role:"menuitem",style:Qe(e),onClick:()=>i(o),children:"CSV Data"}),n&&(0,X.jsx)("button",{type:"button",role:"menuitem",style:Qe(e),onClick:()=>i(n),children:"JSON Data"})]})]})}function ir(e,t={}){let{delimiter:r=",",includeHeader:o=!0,xRange:n,precision:a=6}=t,s=Math.min(e.x.length,e.y.length),i=[];if(o){let c=e.xUnit??"x",l=e.yUnit??"y";i.push(`${c}${r}${l}`)}for(let c=0;c<s;c++){let l=e.x[c];if(n){let p=Math.min(n[0],n[1]),f=Math.max(n[0],n[1]);if(l<p||l>f)continue}let m=e.y[c];i.push(`${l.toFixed(a)}${r}${m.toFixed(a)}`)}return i.join(`
16
16
  `)}function ar(e,t={}){let{delimiter:r=",",includeHeader:o=!0,xRange:n,precision:a=6}=t;if(e.length===0)return"";let s=e[0],i=Math.min(...e.map(l=>Math.min(l.x.length,l.y.length))),c=[];if(o){let l=[s.xUnit??"x",...e.map(m=>m.label)];c.push(l.join(r))}for(let l=0;l<i;l++){let m=s.x[l];if(n){let f=Math.min(n[0],n[1]),u=Math.max(n[0],n[1]);if(m<f||m>u)continue}let p=[m.toFixed(a),...e.map(f=>f.y[l].toFixed(a))];c.push(p.join(r))}return c.join(`
17
- `)}function sr(e,t={}){let{xRange:r,precision:o=6}=t,n=Math.min(e.x.length,e.y.length),a=[],s=[];for(let i=0;i<n;i++){let c=e.x[i];if(r){let l=Math.min(r[0],r[1]),m=Math.max(r[0],r[1]);if(c<l||c>m)continue}a.push(parseFloat(c.toFixed(o))),s.push(parseFloat(e.y[i].toFixed(o)))}return JSON.stringify({id:e.id,label:e.label,xUnit:e.xUnit,yUnit:e.yUnit,type:e.type,x:a,y:s},null,2)}function lr(e,t,r="text/plain"){let o=new Blob([e],{type:r}),n=URL.createObjectURL(o),a=document.createElement("a");a.href=n,a.download=t,a.click(),URL.revokeObjectURL(n)}var ge=0;function cr(e,t){let r=Math.min(e.y.length,t.y.length),o=new Float64Array(r);for(let n=0;n<r;n++)o[n]=e.y[n]-t.y[n];return{id:`diff-${++ge}`,label:`${e.label} \u2212 ${t.label}`,x:e.x.length<=t.x.length?new Float64Array(e.x):new Float64Array(t.x),y:o,xUnit:e.xUnit,yUnit:e.yUnit,color:"#ef4444",type:e.type}}function ur(e,t){let r=Math.min(e.y.length,t.y.length),o=new Float64Array(r);for(let n=0;n<r;n++)o[n]=e.y[n]+t.y[n];return{id:`add-${++ge}`,label:`${e.label} + ${t.label}`,x:e.x.length<=t.x.length?new Float64Array(e.x):new Float64Array(t.x),y:o,xUnit:e.xUnit,yUnit:e.yUnit,type:e.type}}function mr(e,t){let r=e.y.length,o=new Float64Array(r);for(let n=0;n<r;n++)o[n]=e.y[n]*t;return{id:`scaled-${++ge}`,label:`${e.label} \xD7 ${t}`,x:new Float64Array(e.x),y:o,xUnit:e.xUnit,yUnit:e.yUnit,color:e.color,type:e.type}}function pr(e,t){let r=Math.min(e.y.length,t.y.length);if(r===0)return 0;let o=0,n=0;for(let p=0;p<r;p++)o+=e.y[p],n+=t.y[p];let a=o/r,s=n/r,i=0,c=0,l=0;for(let p=0;p<r;p++){let f=e.y[p]-a,u=t.y[p]-s;i+=f*u,c+=f*f,l+=u*u}let m=Math.sqrt(c*l);return m===0?0:i/m}function fr(e,t){let r=Math.min(e.y.length,t.y.length),o=new Float64Array(r);for(let n=0;n<r;n++)o[n]=Math.abs(e.y[n]-t.y[n]);return{id:`residual-${++ge}`,label:`|${e.label} \u2212 ${t.label}|`,x:e.x.length<=t.x.length?new Float64Array(e.x):new Float64Array(t.x),y:o,xUnit:e.xUnit,yUnit:e.yUnit,color:"#f97316",lineStyle:"dashed",type:e.type}}function dr(e,t){let r=Math.min(e.x.length,e.y.length),o=t.length,n=new Float64Array(o);if(r<2)return{...e,x:new Float64Array(t),y:n};let a=e.x[r-1]>e.x[0];for(let s=0;s<o;s++){let i=t[s],c=0,l=r-1;for(;c<l-1;){let d=c+l>>>1;a?e.x[d]<=i?c=d:l=d:e.x[d]>=i?c=d:l=d}let m=e.x[c],p=e.x[l],f=e.y[c],u=e.y[l];if(m===p)n[s]=f;else{let d=(i-m)/(p-m);n[s]=f+d*(u-f)}}return{...e,id:`interp-${++ge}`,x:new Float64Array(t),y:n}}var cn=0,un=1,mn=4,pn=128,fn={0:"Arbitrary",1:"cm\u207B\xB9",2:"\xB5m",3:"nm",4:"s",5:"min",6:"Hz",7:"kHz",8:"MHz",9:"m/z",10:"Da",11:"ppm",12:"days",13:"years",14:"Raman shift (cm\u207B\xB9)",15:"eV",16:"Text label",255:"Double interferogram"},dn={0:"Arbitrary",1:"Interferogram",2:"Absorbance",3:"Kubelka-Munk",4:"Counts",5:"V",6:"\xB0",7:"mA",8:"mm",9:"mV",10:"log(1/R)",11:"%",12:"Intensity",13:"Relative intensity",14:"Energy",16:"dB",19:"\xB0C",20:"\xB0F",21:"K",22:"Index of refraction [n]",23:"Extinction coeff. [k]",24:"Real",25:"Imaginary",26:"Complex",128:"Transmittance",129:"Reflectance",130:"Arbitrary (Valley to peak)",131:"Emission"};function bn(e,t){return e===1?"IR":e===14?"Raman":e===3&&(t===2||t===128)?"UV-Vis":e===2?"NIR":t===131?"fluorescence":"other"}function br(e){let t=new DataView(e);if(e.byteLength<512)throw new Error("Invalid SPC file: too small for SPC header");let o=t.getUint8(0),n=t.getUint8(1);if(n!==75&&n!==77)throw new Error(`Unsupported SPC version: 0x${n.toString(16)}. Expected 0x4B or 0x4D.`);let a=t.getUint8(2),s=t.getUint8(3),i=t.getUint32(4,!0),c=t.getFloat64(8,!0),l=t.getFloat64(16,!0),m=t.getUint32(24,!0),p=fn[a]??"Arbitrary",f=dn[s]??"Arbitrary",u=new Uint8Array(e,30,130),d=gn(u),h=(o&mn)!==0,g=(o&pn)!==0,b=(o&un)!==0,x=bn(a,s),S=null;if(!g&&i>0){S=new Float64Array(i);let w=i>1?(l-c)/(i-1):0;for(let R=0;R<i;R++)S[R]=c+R*w}let v=[],y=512,k=null;if(g&&!h){k=new Float64Array(i);for(let w=0;w<i;w++)k[w]=t.getFloat32(y,!0),y+=4}let C=h?m:1;for(let w=0;w<C;w++){let R,E,U=i;if(h){if(y+32>e.byteLength)break;let $=t.getFloat32(y+4,!0),tt=t.getFloat32(y+8,!0);if(U=t.getUint32(y+12,!0)||i,y+=32,g){R=new Float64Array(U);for(let Q=0;Q<U&&!(y+4>e.byteLength);Q++)R[Q]=t.getFloat32(y,!0),y+=4}else if(S)R=S;else{R=new Float64Array(U);let Q=U>1?(tt-$)/(U-1):0;for(let ee=0;ee<U;ee++)R[ee]=$+ee*Q}}else R=k??S??new Float64Array(0);if(E=new Float64Array(U),b)for(let $=0;$<U&&!(y+2>e.byteLength);$++)E[$]=t.getInt16(y,!0),y+=2;else for(let $=0;$<U&&!(y+4>e.byteLength);$++)E[$]=t.getFloat32(y,!0),y+=4;v.push({id:`spc-${++cn}`,label:d||`SPC Spectrum ${w+1}`,x:R,y:E,xUnit:p,yUnit:f,type:x,meta:{format:"SPC",version:n===75?"new":"old",xType:a.toString(),yType:s.toString()}})}if(v.length===0)throw new Error("Invalid SPC file: no spectra found");return v}function gn(e){let t=e.indexOf(0),r=t>=0?e.slice(0,t):e;return new TextDecoder("ascii").decode(r).trim()}0&&(module.exports={AnnotationLayer,AxisLayer,Crosshair,DARK_THEME,DataTable,DropZone,ExportMenu,KEYBOARD_SHORTCUTS,LIGHT_THEME,LINE_DASH_PATTERNS,Legend,Minimap,PeakMarkers,RegionSelector,SPECTRUM_COLORS,SpectraView,SpectrumCanvas,StackedView,Toolbar,Tooltip,addSpectra,baselineRubberBand,binarySearchClosest,computeXExtent,computeYExtent,correlationCoefficient,createXScale,createYScale,derivative1st,derivative2nd,detectPeaks,differenceSpectrum,downloadString,downloadSvg,generateChartDescription,generateSvg,getSpectrumColor,getThemeColors,interpolateToGrid,lttbDownsample,multiSpectraToCsv,normalizeArea,normalizeMinMax,normalizeSNV,parseCsv,parseCsvMulti,parseJcamp,parseJson,parseSpc,prefersReducedMotion,residualSpectrum,scaleSpectrum,smoothSavitzkyGolay,snapToNearestSpectrum,spectrumToCsv,spectrumToJson,useExport,useHistory,useKeyboardNavigation,useNormalization,usePeakPicking,useRegionSelect,useResizeObserver,useSpectrumData,useZoomPan});
17
+ `)}function sr(e,t={}){let{xRange:r,precision:o=6}=t,n=Math.min(e.x.length,e.y.length),a=[],s=[];for(let i=0;i<n;i++){let c=e.x[i];if(r){let l=Math.min(r[0],r[1]),m=Math.max(r[0],r[1]);if(c<l||c>m)continue}a.push(parseFloat(c.toFixed(o))),s.push(parseFloat(e.y[i].toFixed(o)))}return JSON.stringify({id:e.id,label:e.label,xUnit:e.xUnit,yUnit:e.yUnit,type:e.type,x:a,y:s},null,2)}function lr(e,t,r="text/plain"){let o=new Blob([e],{type:r}),n=URL.createObjectURL(o),a=document.createElement("a");a.href=n,a.download=t,a.click(),URL.revokeObjectURL(n)}var ge=0;function cr(e,t){let r=Math.min(e.y.length,t.y.length),o=new Float64Array(r);for(let n=0;n<r;n++)o[n]=e.y[n]-t.y[n];return{id:`diff-${++ge}`,label:`${e.label} \u2212 ${t.label}`,x:e.x.length<=t.x.length?new Float64Array(e.x):new Float64Array(t.x),y:o,xUnit:e.xUnit,yUnit:e.yUnit,color:"#ef4444",type:e.type}}function ur(e,t){let r=Math.min(e.y.length,t.y.length),o=new Float64Array(r);for(let n=0;n<r;n++)o[n]=e.y[n]+t.y[n];return{id:`add-${++ge}`,label:`${e.label} + ${t.label}`,x:e.x.length<=t.x.length?new Float64Array(e.x):new Float64Array(t.x),y:o,xUnit:e.xUnit,yUnit:e.yUnit,type:e.type}}function mr(e,t){let r=e.y.length,o=new Float64Array(r);for(let n=0;n<r;n++)o[n]=e.y[n]*t;return{id:`scaled-${++ge}`,label:`${e.label} \xD7 ${t}`,x:new Float64Array(e.x),y:o,xUnit:e.xUnit,yUnit:e.yUnit,color:e.color,type:e.type}}function pr(e,t){let r=Math.min(e.y.length,t.y.length);if(r===0)return 0;let o=0,n=0;for(let p=0;p<r;p++)o+=e.y[p],n+=t.y[p];let a=o/r,s=n/r,i=0,c=0,l=0;for(let p=0;p<r;p++){let f=e.y[p]-a,u=t.y[p]-s;i+=f*u,c+=f*f,l+=u*u}let m=Math.sqrt(c*l);return m===0?0:i/m}function fr(e,t){let r=Math.min(e.y.length,t.y.length),o=new Float64Array(r);for(let n=0;n<r;n++)o[n]=Math.abs(e.y[n]-t.y[n]);return{id:`residual-${++ge}`,label:`|${e.label} \u2212 ${t.label}|`,x:e.x.length<=t.x.length?new Float64Array(e.x):new Float64Array(t.x),y:o,xUnit:e.xUnit,yUnit:e.yUnit,color:"#f97316",lineStyle:"dashed",type:e.type}}function dr(e,t){let r=Math.min(e.x.length,e.y.length),o=t.length,n=new Float64Array(o);if(r<2)return{...e,x:new Float64Array(t),y:n};let a=e.x[r-1]>e.x[0];for(let s=0;s<o;s++){let i=t[s],c=0,l=r-1;for(;c<l-1;){let d=c+l>>>1;a?e.x[d]<=i?c=d:l=d:e.x[d]>=i?c=d:l=d}let m=e.x[c],p=e.x[l],f=e.y[c],u=e.y[l];if(m===p)n[s]=f;else{let d=(i-m)/(p-m);n[s]=f+d*(u-f)}}return{...e,id:`interp-${++ge}`,x:new Float64Array(t),y:n}}var cn=0,un=1,mn=4,pn=128,fn={0:"Arbitrary",1:"cm\u207B\xB9",2:"\xB5m",3:"nm",4:"s",5:"min",6:"Hz",7:"kHz",8:"MHz",9:"m/z",10:"Da",11:"ppm",12:"days",13:"years",14:"Raman shift (cm\u207B\xB9)",15:"eV",16:"Text label",255:"Double interferogram"},dn={0:"Arbitrary",1:"Interferogram",2:"Absorbance",3:"Kubelka-Munk",4:"Counts",5:"V",6:"\xB0",7:"mA",8:"mm",9:"mV",10:"log(1/R)",11:"%",12:"Intensity",13:"Relative intensity",14:"Energy",16:"dB",19:"\xB0C",20:"\xB0F",21:"K",22:"Index of refraction [n]",23:"Extinction coeff. [k]",24:"Real",25:"Imaginary",26:"Complex",128:"Transmittance",129:"Reflectance",130:"Arbitrary (Valley to peak)",131:"Emission"};function bn(e,t){return e===1?"IR":e===14?"Raman":e===3&&(t===2||t===128)?"UV-Vis":e===2?"NIR":t===131?"fluorescence":"other"}function br(e){let t=new DataView(e);if(e.byteLength<512)throw new Error("Invalid SPC file: too small for SPC header");let o=t.getUint8(0),n=t.getUint8(1);if(n!==75&&n!==77)throw new Error(`Unsupported SPC version: 0x${n.toString(16)}. Expected 0x4B or 0x4D.`);let a=t.getUint8(2),s=t.getUint8(3),i=t.getUint32(4,!0),c=t.getFloat64(8,!0),l=t.getFloat64(16,!0),m=t.getUint32(24,!0),p=fn[a]??"Arbitrary",f=dn[s]??"Arbitrary",u=new Uint8Array(e,30,130),d=gn(u),h=(o&mn)!==0,g=(o&pn)!==0,b=(o&un)!==0,x=bn(a,s),S=null;if(!g&&i>0){S=new Float64Array(i);let w=i>1?(l-c)/(i-1):0;for(let R=0;R<i;R++)S[R]=c+R*w}let v=[],y=512,k=null;if(g&&!h){k=new Float64Array(i);for(let w=0;w<i;w++)k[w]=t.getFloat32(y,!0),y+=4}let C=h?m:1;for(let w=0;w<C;w++){let R,T=i;if(h){if(y+32>e.byteLength)break;let U=t.getFloat32(y+4,!0),tt=t.getFloat32(y+8,!0);if(T=t.getUint32(y+12,!0)||i,y+=32,g){R=new Float64Array(T);for(let q=0;q<T&&!(y+4>e.byteLength);q++)R[q]=t.getFloat32(y,!0),y+=4}else if(S)R=S;else{R=new Float64Array(T);let q=T>1?(tt-U)/(T-1):0;for(let Q=0;Q<T;Q++)R[Q]=U+Q*q}}else R=k??S??new Float64Array(0);let re=new Float64Array(T);if(b)for(let U=0;U<T&&!(y+2>e.byteLength);U++)re[U]=t.getInt16(y,!0),y+=2;else for(let U=0;U<T&&!(y+4>e.byteLength);U++)re[U]=t.getFloat32(y,!0),y+=4;v.push({id:`spc-${++cn}`,label:d||`SPC Spectrum ${w+1}`,x:R,y:re,xUnit:p,yUnit:f,type:x,meta:{format:"SPC",version:n===75?"new":"old",xType:a.toString(),yType:s.toString()}})}if(v.length===0)throw new Error("Invalid SPC file: no spectra found");return v}function gn(e){let t=e.indexOf(0),r=t>=0?e.slice(0,t):e;return new TextDecoder("ascii").decode(r).trim()}0&&(module.exports={AnnotationLayer,AxisLayer,Crosshair,DARK_THEME,DataTable,DropZone,ExportMenu,KEYBOARD_SHORTCUTS,LIGHT_THEME,LINE_DASH_PATTERNS,Legend,Minimap,PeakMarkers,RegionSelector,SPECTRUM_COLORS,SpectraView,SpectrumCanvas,StackedView,Toolbar,Tooltip,addSpectra,baselineRubberBand,binarySearchClosest,computeXExtent,computeYExtent,correlationCoefficient,createXScale,createYScale,derivative1st,derivative2nd,detectPeaks,differenceSpectrum,downloadString,downloadSvg,generateChartDescription,generateSvg,getSpectrumColor,getThemeColors,interpolateToGrid,lttbDownsample,multiSpectraToCsv,normalizeArea,normalizeMinMax,normalizeSNV,parseCsv,parseCsvMulti,parseJcamp,parseJson,parseSpc,prefersReducedMotion,residualSpectrum,scaleSpectrum,smoothSavitzkyGolay,snapToNearestSpectrum,spectrumToCsv,spectrumToJson,useExport,useHistory,useKeyboardNavigation,useNormalization,usePeakPicking,useRegionSelect,useResizeObserver,useSpectrumData,useZoomPan});
18
18
  //# sourceMappingURL=index.cjs.map