chartifypdf 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +193 -10
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/types/chart.types.d.ts +2 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsxs as t,jsx as e}from"react/jsx-runtime";import n,{useState as o,useLayoutEffect as i,useMemo as r,useRef as l,useCallback as a,useEffect as c,useId as s}from"react";const d=["#4e79a7","#f28e2b","#e15759","#76b7b2","#59a14f","#edc948","#b07aa1","#ff9da7","#9c755f","#bab0ac"];function h(t,e,n){const[r,l]=o({width:e??0,height:n??0}),a=void 0!==e&&void 0!==n;return i(()=>{if(a)return void l({width:e,height:n});const o=t.current;if(!o)return;const i=()=>{const t=o.getBoundingClientRect();l({width:t.width,height:t.height})};i();const r=new ResizeObserver(()=>{i()});return r.observe(o),()=>r.disconnect()},[t,a,e,n]),r}function f(t,e,n){return Math.min(Math.max(t,e),n)}function u(t,e,n){return t+(e-t)*n}function m(t,e){const n=Math.floor(Math.log10(t)),o=t/Math.pow(10,n);let i;return i=e?o<1.5?1:o<3?2:o<7?5:10:o<=1?1:o<=2?2:o<=5?5:10,i*Math.pow(10,n)}function g(t,e,n){if(t===e){const n=0===t?1:.1*Math.abs(t);t-=n,e+=n}const o=m(e-t,!1),i=m(o/(n-1),!0);return{niceMin:Math.floor(t/i)*i,niceMax:Math.ceil(e/i)*i,tickStep:i}}function y(t,e,n,o){return i=>{if(e===t)return(n+o)/2;const r=function(t,e,n){return t===e?0:(n-t)/(e-t)}(t,e,i);return u(n,o,r)}}function p(t,e,n){const o=[];for(let i=t;i<=e+.5*n;i+=n)o.push(parseFloat(i.toPrecision(12)));return o}function x(t,e,n){return r(()=>{let o=1/0,i=-1/0,r=1/0,l=-1/0;for(const e of t)for(const t of e.data)t.x<o&&(o=t.x),t.x>i&&(i=t.x),t.y<r&&(r=t.y),t.y>l&&(l=t.y);isFinite(o)||(o=0,i=1,r=0,l=1),void 0!==e?.min&&(o=e.min),void 0!==e?.max&&(i=e.max),void 0!==n?.min&&(r=n.min),void 0!==n?.max&&(l=n.max);const a=e?.tickCount??6,c=n?.tickCount??6,s=g(o,i,a),d=g(r,l,c);return{fullXDomain:[s.niceMin,s.niceMax],fullYDomain:[d.niceMin,d.niceMax]}},[t,e,n])}function b(t,e,n,o,i,l,a){return r(()=>{let r=1/0,c=-1/0,s=1/0,d=-1/0;for(const e of t)for(const t of e.data)t.x<r&&(r=t.x),t.x>c&&(c=t.x),t.y<s&&(s=t.y),t.y>d&&(d=t.y);isFinite(r)||(r=0,c=1,s=0,d=1),void 0!==o?.min&&(r=o.min),void 0!==o?.max&&(c=o.max),void 0!==i?.min&&(s=i.min),void 0!==i?.max&&(d=i.max);const h=o?.tickCount??6,f=i?.tickCount??6;let u,m,x,b;if(l)u=l[0],m=l[1];else{const t=g(r,c,h);u=t.niceMin,m=t.niceMax}if(a)x=a[0],b=a[1];else{const t=g(s,d,f);x=t.niceMin,b=t.niceMax}const k=g(u,m,h),v=g(x,b,f),w=y(u,m,0,e),M=y(x,b,n,0);let C=k.tickStep,$=k.niceMin,S=k.niceMax;o?.integerTicks&&(C=Math.max(1,Math.ceil(C)),$=Math.ceil(u),S=Math.floor(m));let L=v.tickStep,P=v.niceMin,T=v.niceMax;i?.integerTicks&&(L=Math.max(1,Math.ceil(L)),P=Math.ceil(x),T=Math.floor(b));return{xScale:w,yScale:M,xTicks:p($,S,C).filter(t=>t>=u&&t<=m).filter(t=>!o?.integerTicks||Number.isInteger(t)),yTicks:p(P,T,L).filter(t=>t>=x&&t<=b).filter(t=>!i?.integerTicks||Number.isInteger(t)),xDomain:[u,m],yDomain:[x,b]}},[t,e,n,o,i,l,a])}function k(t,e,n,i,r){const c=t?.enabled??!1,s=t?.maxScale??10,d=t?.step??.5,h=t?.enableWheel??!0,m=t?.enablePan??!0,g=t?.requireCtrlKey??!0,[y,p]=o(e),[x,b]=o(n),[k,v]=o(!1),[w,M]=o(!1),C=l({x:0,y:0,xDomain:e,yDomain:n}),$=l(null),S=l({x:e,y:n});e[0]===S.current.x[0]&&e[1]===S.current.x[1]&&n[0]===S.current.y[0]&&n[1]===S.current.y[1]||(S.current={x:e,y:n},p(e),b(n));const L=e[1]-e[0],P=y[1]-y[0],T=L>0&&P>0?L/P:1,W=a((t,e)=>{const n=t[1]-t[0];if(n>=e[1]-e[0])return e;let o=t[0],i=t[1];return o<e[0]&&(o=e[0],i=o+n),i>e[1]&&(i=e[1],o=i-n),[o,i]},[]),D=a(()=>{$.current&&clearTimeout($.current),M(!0),$.current=setTimeout(()=>M(!1),2e3)},[]),R=a((t,o,i)=>{if(!c)return;const r=o??.5,l=i??.5;p(n=>{const o=(n[1]-n[0])/t,i=L/s,l=Math.max(o,i),a=Math.min(l,L),c=u(n[0],n[1],r)-a*r;return W([c,c+a],e)}),b(e=>{const o=e[1]-e[0],i=n[1]-n[0],r=o/t,a=i/s,c=Math.max(r,a),d=Math.min(c,i),h=u(e[0],e[1],l)-d*l;return W([h,h+d],n)})},[c,e,n,L,s,W]),z=a(()=>{R(1+d)},[d,R]),A=a(()=>{R(1/(1+d))},[d,R]),N=a(()=>{p(e),b(n)},[e,n]),X=a((t,o)=>{if(!c)return;p(n=>{const o=(n[1]-n[0])/2,i=L/s,r=Math.max(o,i),l=Math.min(r,L),a=t-l/2;return W([a,a+l],e)}),b(t=>{const e=t[1]-t[0],i=n[1]-n[0],r=e/2,l=i/s,a=Math.max(r,l),c=Math.min(a,i),d=o-c/2;return W([d,d+c],n)})},[c,e,n,L,s,W]),Y=a(t=>{if(!c||!h)return;if(g&&!t.ctrlKey&&!t.metaKey)return void D();t.preventDefault();const e=t.currentTarget.getBoundingClientRect(),n=t.clientX-e.left,o=t.clientY-e.top,i=f(n/(e.width||1),0,1),r=f(o/(e.height||1),0,1),l=t.deltaY<0?1+d:1/(1+d);R(l,i,r)},[c,h,g,d,D,R]),E=a(t=>{!c||!m||T<=1||0===t.button&&(v(!0),C.current={x:t.clientX,y:t.clientY,xDomain:y,yDomain:x})},[c,m,T,y,x]),F=a(t=>{if(!k)return;const o=t.clientX-C.current.x,l=t.clientY-C.current.y,a=C.current.xDomain,c=C.current.yDomain,s=a[1]-a[0],d=c[1]-c[0],h=-o/i*s,f=l/r*d,u=[a[0]+h,a[1]+h],m=[c[0]+f,c[1]+f];p(W(u,e)),b(W(m,n))},[k,i,r,e,n,W]),I=a(()=>{v(!1)},[]);return{viewXDomain:y,viewYDomain:x,scale:T,isPanning:k,showZoomHint:w,zoomIn:z,zoomOut:A,resetZoom:N,zoomToPoint:X,handleWheel:Y,handlePanStart:E,handlePanMove:F,handlePanEnd:I}}function v(t,e,n){if(0===t.length)return null;let o=0,i=t.length-1;for(;o<i;){const r=Math.floor((o+i)/2);n(t[r].x)<e?o=r+1:i=r}let r=t[o],l=Math.abs(n(r.x)-e);if(o>0){const i=Math.abs(n(t[o-1].x)-e);i<l&&(l=i,r=t[o-1])}return r}function w(t,e,n,i,r,l,c,s){const[d,h]=o(!1),[f,u]=o(0),[m,g]=o(0),[y,p]=o(null),[x,b]=o(null),[k,w]=o(null);return{tooltipVisible:d,tooltipX:f,tooltipY:m,activePoint:y,activeSeries:x,activeSeriesId:k,handleMouseMove:a(o=>{const a=t.current;if(!a)return;const s=a.getBoundingClientRect(),d=o.clientX-s.left-r,f=o.clientY-s.top-l;if(d<0||d>c)return h(!1),void w(null);let m=0,y=1/0;for(const t of e){const e=v(t.data,d,n);if(!e)continue;const o=Math.abs(n(e.x)-d);o<y&&(y=o,m=e.x)}let x=null,k=null,M=1/0;for(const t of e){let e=null,n=1/0;for(const o of t.data){const t=Math.abs(o.x-m);t<n&&(n=t,e=o)}if(!e)continue;const o=i(e.y),r=Math.abs(o-f);r<M&&(M=r,x=e,k=t)}x&&k&&(u(n(x.x)),g(i(x.y)),p(x),b(k),w(k.id),h(!0))},[t,e,n,i,r,l,c]),handleMouseLeave:a(()=>{h(!1),p(null),b(null),w(null)},[])}}const M=t=>Math.abs(t)>=1e6?`${(t/1e6).toFixed(1)}M`:Math.abs(t)>=1e3?`${(t/1e3).toFixed(1)}K`:Number.isInteger(t)?t.toString():t.toFixed(1),C=n.memo(({xTicks:n,yTicks:o,xScale:i,yScale:r,plotWidth:l,plotHeight:a,xAxisConfig:c,yAxisConfig:s,style:d})=>{const h=d?.axisColor??"#333",f=d?.tickColor??"#666",u=d?.fontFamily??"sans-serif",m=d?.fontSize??11,g=c?.tickFormat??M,y=s?.tickFormat??M;return t("g",{className:"chartifypdf-axes",children:[e("line",{x1:0,y1:a,x2:l,y2:a,stroke:h,strokeWidth:1}),n.map(n=>{const o=i(n);return t("g",{children:[e("line",{x1:o,y1:a,x2:o,y2:a+6,stroke:h,strokeWidth:1}),e("text",{x:o,y:a+18,textAnchor:"middle",fill:f,fontFamily:u,fontSize:m,children:g(n)})]},`x-tick-${n}`)}),c?.label&&e("text",{x:l/2,y:a+38,textAnchor:"middle",fill:h,fontFamily:u,fontSize:m+1,fontWeight:"bold",children:c.label}),e("line",{x1:0,y1:0,x2:0,y2:a,stroke:h,strokeWidth:1}),o.map(n=>{const o=r(n);return t("g",{children:[e("line",{x1:-6,y1:o,x2:0,y2:o,stroke:h,strokeWidth:1}),e("text",{x:-10,y:o,textAnchor:"end",dominantBaseline:"middle",fill:f,fontFamily:u,fontSize:m,children:y(n)})]},`y-tick-${n}`)}),s?.label&&e("text",{x:0,y:0,textAnchor:"middle",fill:h,fontFamily:u,fontSize:m+1,fontWeight:"bold",transform:`translate(-40, ${a/2}) rotate(-90)`,children:s.label})]})});C.displayName="Axes";const $=n.memo(({xTicks:n,yTicks:o,xScale:i,yScale:r,plotWidth:l,plotHeight:a,showXGrid:c,showYGrid:s,xGridColor:d="#e0e0e0",yGridColor:h="#e0e0e0"})=>t("g",{className:"chartifypdf-grid",children:[s&&o.map(t=>{const n=r(t);return e("line",{x1:0,y1:n,x2:l,y2:n,stroke:h,strokeDasharray:"4 4",strokeOpacity:.5},`y-grid-${t}`)}),c&&n.map(t=>{const n=i(t);return e("line",{x1:n,y1:0,x2:n,y2:a,stroke:d,strokeDasharray:"4 4",strokeOpacity:.5},`x-grid-${t}`)})]}));function S(t){if(0===t.length)return"";const[e,...n]=t;return`M${e.x},${e.y}`+n.map(t=>`L${t.x},${t.y}`).join("")}function L(t,e){switch(e){case"monotone":return function(t){const e=t.length;if(e<2)return S(t);if(2===e)return S(t);const n=[],o=[],i=[];for(let r=0;r<e-1;r++)n.push(t[r+1].x-t[r].x),o.push(t[r+1].y-t[r].y),i.push(0===n[r]?0:o[r]/n[r]);const r=new Array(e);r[0]=i[0],r[e-1]=i[e-2];for(let t=1;t<e-1;t++)i[t-1]*i[t]<=0?r[t]=0:r[t]=2/(1/i[t-1]+1/i[t]);for(let t=0;t<e-1;t++)if(0===i[t])r[t]=0,r[t+1]=0;else{const e=r[t]/i[t],n=r[t+1]/i[t],o=e*e+n*n;if(o>9){const l=3/Math.sqrt(o);r[t]=l*e*i[t],r[t+1]=l*n*i[t]}}let l=`M${t[0].x},${t[0].y}`;for(let o=0;o<e-1;o++){const e=n[o]/3;l+=`C${t[o].x+e},${t[o].y+r[o]*e},${t[o+1].x-e},${t[o+1].y-r[o+1]*e},${t[o+1].x},${t[o+1].y}`}return l}(t);case"natural":return function(t){const e=t.length;if(e<2)return S(t);if(2===e)return S(t);function n(t){const e=t.length-1,n=new Array(e),o=new Array(e),i=new Array(e);n[0]=0,o[0]=2,i[0]=t[0]+2*t[1];for(let r=1;r<e-1;r++)n[r]=1,o[r]=4,i[r]=4*t[r]+2*t[r+1];n[e-1]=2,o[e-1]=7,i[e-1]=8*t[e-1]+t[e];for(let t=1;t<e;t++){const e=n[t]/o[t-1];o[t]-=e,i[t]-=e*i[t-1]}const r=new Array(e);r[e-1]=i[e-1]/o[e-1];for(let t=e-2;t>=0;t--)r[t]=(i[t]-r[t+1])/o[t];const l=new Array(e);for(let n=0;n<e-1;n++)l[n]=2*t[n+1]-r[n+1];l[e-1]=(t[e]+r[e-1])/2;const a=[];for(let t=0;t<e;t++)a.push({cp1:r[t],cp2:l[t]});return a}const o=t.map(t=>t.x),i=t.map(t=>t.y),r=n(o),l=n(i);let a=`M${t[0].x},${t[0].y}`;for(let n=0;n<e-1;n++)a+=`C${r[n].cp1},${l[n].cp1},${r[n].cp2},${l[n].cp2},${t[n+1].x},${t[n+1].y}`;return a}(t);default:return S(t)}}$.displayName="GridLines";const P=n.memo(({series:n,xScale:i,yScale:r,color:a,animation:s,onPointClick:d,curveType:h,highlightOpacity:f})=>{const u=l(null),[m,g]=o(0),[y,p]=o(!s?.enabled),x=n.strokeWidth??2,b=n.showDots??!1,k=n.dotRadius??3.5,v=n.curveType??h??"linear",w=f??1,M=n.data.map(t=>({x:i(t.x),y:r(t.y)})),C="linear"===v?S(M):L(M,v);c(()=>{if(s?.enabled&&u.current){const t=u.current.getTotalLength();g(t),p(!1);const e=setTimeout(()=>{p(!0)},s.duration??800);return()=>clearTimeout(e)}},[C,s?.enabled,s?.duration]);const $=s?.enabled&&m>0?{strokeDasharray:m,strokeDashoffset:y?0:m,transition:`stroke-dashoffset ${s.duration??800}ms ${s.easing??"ease-in-out"}`}:{};return t("g",{className:"chartifypdf-line-path",style:{opacity:w,transition:"opacity 150ms ease"},children:[e("path",{ref:u,d:C,fill:"none",stroke:a,strokeWidth:x,strokeDasharray:n.strokeDasharray,strokeLinecap:"round",strokeLinejoin:"round",style:$}),b&&n.data.map((t,o)=>e("circle",{cx:i(t.x),cy:r(t.y),r:k,fill:a,stroke:"#fff",strokeWidth:1.5,style:{cursor:d?"pointer":"default"},onClick:d?()=>d(t,n):void 0},`dot-${n.id}-${o}`))]})});P.displayName="LinePath";const T=n.memo(({visible:n,x:o,y:i,point:r,series:l,plotHeight:a,plotWidth:c,config:s,seriesColor:d})=>{if(!n||!r||!l)return null;const h=s?.backgroundColor??"rgba(0, 0, 0, 0.8)",f=s?.textColor??"#fff";let u;if(s?.renderCustom)u=s.renderCustom(r,l);else{u=s?.formatter?s.formatter(r,l):`${l.name}: (${r.x}, ${r.y})`}let m=o+12,g=i-40-8;return m+140>c&&(m=o-140-12),g<0&&(g=i+12),t("g",{className:"chartifypdf-tooltip",pointerEvents:"none",children:[e("line",{x1:o,y1:0,x2:o,y2:a,stroke:"#999",strokeWidth:1,strokeDasharray:"4 4",opacity:.6}),e("circle",{cx:o,cy:i,r:5,fill:d,stroke:"#fff",strokeWidth:2}),e("foreignObject",{x:m,y:g,width:140,height:60,overflow:"visible",children:e("div",{style:{backgroundColor:h,color:f,padding:"6px 10px",borderRadius:"4px",fontSize:"12px",fontFamily:"sans-serif",whiteSpace:"nowrap",lineHeight:1.4,boxShadow:"0 2px 6px rgba(0,0,0,0.2)"},children:u})})]})});T.displayName="Tooltip";const W=n.memo(({config:n,svgWidth:o,svgHeight:i,margin:r,scale:l,onZoomIn:a,onZoomOut:c,onReset:s})=>{if(!n?.enabled||!1===n.showControls)return null;const d=n.controlsPosition??"top-right",h=24;let f,u;switch(d){case"top-left":f=r.left+8,u=r.top+8;break;case"bottom-left":f=r.left+8,u=i-r.bottom-24-8;break;case"bottom-right":f=o-r.right-80-8,u=i-r.bottom-24-8;break;default:f=o-r.right-80-8,u=r.top+8}return e("g",{className:"chartifypdf-zoom-controls",transform:`translate(${f}, ${u})`,children:(l>1?[{label:"+",onClick:a},{label:"−",onClick:c},{label:"↺",onClick:s}]:[{label:"+",onClick:a},{label:"−",onClick:c}]).map((n,o)=>t("g",{transform:`translate(${28*o}, 0)`,onClick:n.onClick,style:{cursor:"pointer"},children:[e("rect",{width:h,height:h,rx:4,fill:"rgba(255,255,255,0.9)",stroke:"#ccc",strokeWidth:1}),e("text",{x:12,y:12,textAnchor:"middle",dominantBaseline:"central",fontSize:14,fontFamily:"sans-serif",fill:"#333",fontWeight:"bold",children:n.label})]},n.label))})});function D({x:t,y:n,color:o}){return e("polygon",{points:`${t},${n} ${t-5},${n-10} ${t+5},${n-10}`,fill:o})}function R({x:t,y:n,color:o}){return e("polygon",{points:`${t},${n-6} ${t+5},${n} ${t},${n+6} ${t-5},${n}`,fill:o})}function z({x:t,y:n,color:o}){const i=[];for(let e=0;e<5;e++){const o=(72*e-90)*(Math.PI/180),r=(72*e+36-90)*(Math.PI/180);i.push(`${t+6*Math.cos(o)},${n+6*Math.sin(o)}`),i.push(`${t+3*Math.cos(r)},${n+3*Math.sin(r)}`)}return e("polygon",{points:i.join(" "),fill:o})}W.displayName="ZoomControls";const A=n.memo(({peaks:n,data:o,xScale:i,yScale:r})=>e("g",{className:"chartifypdf-peak-markers",children:n.map((n,l)=>{const a=function(t,e){let n=-1/0,o=-1;for(let i=0;i<t.length;i++){const r=t[i];let l=r.data[0],a=1/0;for(const t of r.data){const n=Math.abs(t.x-e);n<a&&(a=n,l=t)}l&&l.y>n&&(n=l.y,o=i)}return-1===o?null:{y:n,seriesIndex:o}}(o,n.x);if(!a)return null;const c=i(n.x),s=r(a.y),d=n.color??"#ef4444",h=n.icon??"arrow",f=n.label,u=s-14;return t("g",{children:[e("line",{x1:c,y1:s,x2:c,y2:u+6,stroke:d,strokeWidth:1,strokeDasharray:"3 2",opacity:.6}),"arrow"===h&&e(D,{x:c,y:u,color:d}),"diamond"===h&&e(R,{x:c,y:u,color:d}),"star"===h&&e(z,{x:c,y:u,color:d}),f&&e("text",{x:c,y:u-8,textAnchor:"middle",fill:d,fontSize:11,fontWeight:600,children:f})]},`peak-${l}`)})}));A.displayName="PeakMarkers";const N=({visible:n,x:o,y:i,nearestX:r,data:a,config:s,getSeriesColor:d,onClose:h})=>{const f=l(null);if(c(()=>{if(!n)return;const t=t=>{f.current&&!f.current.contains(t.target)&&h()},e=t=>{"Escape"===t.key&&h()},o=setTimeout(()=>{document.addEventListener("mousedown",t),document.addEventListener("keydown",e)},0);return()=>{clearTimeout(o),document.removeEventListener("mousedown",t),document.removeEventListener("keydown",e)}},[n,h]),!n)return null;const u=s?.backgroundColor??"#ffffff",m=s?.textColor??"#1f2937",g=s?.borderColor??"#e5e7eb",y=a.map((t,e)=>{const n=function(t,e){if(0===t.data.length)return null;let n=t.data[0],o=Math.abs(n.x-e);for(const i of t.data){const t=Math.abs(i.x-e);t<o&&(o=t,n=i)}return n.y}(t,r);return{name:t.name,color:t.color??d(e),x:r,y:n}});return t("div",{ref:f,style:{position:"fixed",left:o,top:i,zIndex:9999,backgroundColor:u,color:m,border:`1px solid ${g}`,borderRadius:6,boxShadow:"0 4px 12px rgba(0,0,0,0.15)",padding:"8px 0",minWidth:200,fontSize:12,fontFamily:"system-ui, -apple-system, sans-serif"},children:[t("div",{style:{padding:"4px 12px 8px",fontWeight:600,fontSize:11,color:m,opacity:.6,borderBottom:`1px solid ${g}`,marginBottom:4},children:["Data at X = ","number"==typeof r?r.toLocaleString():r]}),t("table",{style:{width:"100%",borderCollapse:"collapse"},children:[e("thead",{children:t("tr",{children:[e("th",{style:{textAlign:"left",padding:"4px 12px",fontWeight:600,opacity:.7},children:"Series"}),e("th",{style:{textAlign:"right",padding:"4px 12px",fontWeight:600,opacity:.7},children:"Y"})]})}),e("tbody",{children:y.map((n,o)=>t("tr",{style:{borderTop:o>0?`1px solid ${g}`:void 0},children:[t("td",{style:{padding:"4px 12px",display:"flex",alignItems:"center",gap:6},children:[e("span",{style:{display:"inline-block",width:8,height:8,borderRadius:"50%",backgroundColor:n.color,flexShrink:0}}),n.name]}),e("td",{style:{padding:"4px 12px",textAlign:"right",fontVariantNumeric:"tabular-nums"},children:null!==n.y?n.y.toLocaleString():"—"})]},o))})]})]})};function X(t){const e=t.cloneNode(!0),n=t.getBoundingClientRect();e.setAttribute("width",String(n.width)),e.setAttribute("height",String(n.height)),e.setAttribute("xmlns","http://www.w3.org/2000/svg"),e.setAttribute("xmlns:xlink","http://www.w3.org/1999/xlink");const o=t.querySelectorAll("*"),i=e.querySelectorAll("*");for(let t=0;t<o.length;t++){const e=o[t],n=i[t];if(!n.style)continue;const r=window.getComputedStyle(e),l=["fill","stroke","stroke-width","stroke-dasharray","opacity","font-family","font-size","font-weight","text-anchor","dominant-baseline","visibility","display"];for(const t of l){const e=r.getPropertyValue(t);e&&n.style.setProperty(t,e)}}return e}function Y(t,e){const n=URL.createObjectURL(t),o=document.createElement("a");o.href=n,o.download=e,document.body.appendChild(o),o.click(),document.body.removeChild(o),URL.revokeObjectURL(n)}async function E(t,e=2){const n=t.getBoundingClientRect(),o=n.width*e,i=n.height*e,r=document.createElement("canvas");r.width=o,r.height=i;const l=r.getContext("2d");if(!l)throw new Error("Cannot get canvas 2d context");l.scale(e,e);const a=function(t){const e=X(t),n=(new XMLSerializer).serializeToString(e),o=new Blob([n],{type:"image/svg+xml;charset=utf-8"});return URL.createObjectURL(o)}(t);return new Promise((t,e)=>{const o=new Image;o.onload=()=>{l.fillStyle="#ffffff",l.fillRect(0,0,n.width,n.height),l.drawImage(o,0,0,n.width,n.height),URL.revokeObjectURL(a),t(r)},o.onerror=()=>{URL.revokeObjectURL(a),e(new Error("Failed to load SVG as image"))},o.src=a})}async function F(t,e="chart"){const n=X(t),o=(new XMLSerializer).serializeToString(n);Y(new Blob([o],{type:"image/svg+xml;charset=utf-8"}),`${e}.svg`)}async function I(t,e="chart"){const n=await E(t);Y(await new Promise((t,e)=>{n.toBlob(n=>n?t(n):e(new Error("Canvas toBlob failed")),"image/png")}),`${e}.png`)}async function B(t,e="chart"){const n=(await E(t)).toDataURL("image/png"),o=t.getBoundingClientRect(),i=window.open("","_blank");if(!i)throw new Error("Popup blocked. Please allow popups to export PDF.");i.document.write(`\n <!DOCTYPE html>\n <html>\n <head>\n <title>${e}</title>\n <style>\n @page { size: landscape; margin: 10mm; }\n body { margin: 0; display: flex; justify-content: center; align-items: center; min-height: 100vh; }\n img { max-width: 100%; height: auto; }\n </style>\n </head>\n <body>\n <img src="${n}" width="${o.width}" height="${o.height}" />\n <script>\n window.onload = function() {\n setTimeout(function() { window.print(); window.close(); }, 300);\n };\n <\/script>\n </body>\n </html>\n `),i.document.close()}async function O(t,e="pdf",n="chart"){switch(e){case"svg":return F(t,n);case"png":return I(t,n);case"pdf":return B(t,n)}}N.displayName="ContextMenu";const H=n.memo(({config:n,svgRef:o,svgWidth:i,svgHeight:r,margin:l})=>{if(!n?.enabled)return null;let c,s;switch(n.buttonPosition??"top-right"){case"top-left":c=l.left+8,s=l.top+8+24+8;break;case"bottom-left":c=l.left+8,s=r-l.bottom-24-8;break;case"bottom-right":c=i-l.right-28-8,s=r-l.bottom-24-8;break;default:c=i-l.right-28-8,s=l.top+8+24+8}const d=a(()=>{const t=o.current;if(!t)return;O(t,n?.format??"pdf",n?.fileName??"chart")},[o,n?.format,n?.fileName]);return t("g",{className:"chartifypdf-export-button",transform:`translate(${c}, ${s})`,onClick:d,style:{cursor:"pointer"},children:[e("rect",{width:28,height:24,rx:4,fill:"rgba(255,255,255,0.9)",stroke:"#ccc",strokeWidth:1}),e("g",{transform:"translate(7, 4)",children:e("path",{d:"M7,2 L7,10 L4,7 M7,10 L10,7 M3,13 L11,13",fill:"none",stroke:"#333",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round"})})]})});H.displayName="ExportButton";const j={top:20,right:20,bottom:50,left:60},U=({data:n,width:i,height:r,margin:f,xAxis:u,yAxis:m,tooltip:g,zoom:y,style:p,animation:v,colorPalette:M,className:S,onPointClick:L,ariaLabel:D,curveType:R,peaks:z,contextMenu:X,export:Y})=>{const E=l(null),F=l(null),I=s(),B={...j,...f},O=h(E,i,r??400),{width:U,height:Z}=O,G=Math.max(0,U-B.left-B.right),K=Math.max(0,Z-B.top-B.bottom),{fullXDomain:V,fullYDomain:q}=x(n,u,m),_=k(y,V,q,G,K),J=y?.enabled??!1,Q=y?.enableClickZoom??!1,{xScale:tt,yScale:et,xTicks:nt,yTicks:ot}=b(n,G,K,u,m,J?_.viewXDomain:void 0,J?_.viewYDomain:void 0),it=!1!==g?.enabled,rt=w(F,n,tt,et,B.left,B.top,G),lt=rt.activeSeriesId,at=rt.tooltipVisible&&null!==lt,ct=t=>at?t===lt?1:.2:1,st=y?.requireCtrlKey??!0,dt=y?.enableWheel??!0;c(()=>{const t=F.current;if(!t||!J||!dt)return;const e=t=>{st?(t.ctrlKey||t.metaKey)&&t.preventDefault():t.preventDefault()};return t.addEventListener("wheel",e,{passive:!1}),()=>t.removeEventListener("wheel",e)},[J,dt,st]);const ht=a(t=>{if(!J||!Q)return;if(_.isPanning)return;const e=F.current;if(!e)return;const o=e.getBoundingClientRect(),i=t.clientX-o.left-B.left,r=t.clientY-o.top-B.top;if(i<0||i>G||r<0||r>K)return;let l=0,a=0,c=1/0;for(const t of n)for(const e of t.data){const t=tt(e.x),n=et(e.y),o=Math.hypot(t-i,n-r);o<c&&(c=o,l=e.x,a=e.y)}_.zoomToPoint(l,a)},[J,Q,_,n,tt,et,B.left,B.top,G,K]),ft=a(()=>{J&&Q&&_.resetZoom()},[J,Q,_]),[ut,mt]=o({visible:!1,clientX:0,clientY:0,nearestX:0}),gt=a(t=>{if(!X?.enabled)return;t.preventDefault();const e=F.current;if(!e)return;const o=e.getBoundingClientRect(),i=t.clientX-o.left-B.left;if(i<0||i>G)return;let r=0,l=1/0;for(const t of n)for(const e of t.data){const t=tt(e.x),n=Math.abs(t-i);n<l&&(l=n,r=e.x)}mt({visible:!0,clientX:t.clientX,clientY:t.clientY,nearestX:r})},[X?.enabled,n,tt,B.left,G]),yt=a(()=>{mt(t=>({...t,visible:!1}))},[]),pt=u?.gridLines??!1,xt=m?.gridLines??!0,bt=t=>function(t,e){const n=e??d;return n[t%n.length]}(t,M);return 0===U||0===Z?e("div",{ref:E,className:S,style:{width:i??"100%",height:r??400,backgroundColor:p?.backgroundColor}}):t("div",{ref:E,className:S,style:{width:i??"100%",height:r??400,backgroundColor:p?.backgroundColor,position:"relative"},children:[t("svg",{ref:F,width:U,height:Z,role:"img","aria-label":D??"Line chart",onMouseMove:it&&!_.isPanning?rt.handleMouseMove:void 0,onMouseLeave:it?rt.handleMouseLeave:void 0,onWheel:J?_.handleWheel:void 0,onMouseDown:J?_.handlePanStart:void 0,onMouseUp:J?_.handlePanEnd:void 0,onClick:ht,onDoubleClick:ft,onContextMenu:gt,style:{userSelect:_.isPanning?"none":void 0,cursor:_.isPanning?"grabbing":J&&_.scale>1?"grab":void 0},children:[e("defs",{children:e("clipPath",{id:I,children:e("rect",{width:G,height:K})})}),t("g",{transform:`translate(${B.left}, ${B.top})`,children:[e(C,{xTicks:nt,yTicks:ot,xScale:tt,yScale:et,plotWidth:G,plotHeight:K,xAxisConfig:u,yAxisConfig:m,style:p}),e($,{xTicks:nt,yTicks:ot,xScale:tt,yScale:et,plotWidth:G,plotHeight:K,showXGrid:pt,showYGrid:xt,xGridColor:u?.gridLineColor,yGridColor:m?.gridLineColor}),t("g",{clipPath:`url(#${I})`,children:[J?e("g",{onMouseMove:_.handlePanMove,children:n.map((t,n)=>e(P,{series:t,xScale:tt,yScale:et,color:t.color??bt(n),animation:v,onPointClick:L,curveType:R,highlightOpacity:ct(t.id)},t.id))}):n.map((t,n)=>e(P,{series:t,xScale:tt,yScale:et,color:t.color??bt(n),animation:v,onPointClick:L,curveType:R,highlightOpacity:ct(t.id)},t.id)),z&&z.length>0&&e(A,{peaks:z,data:n,xScale:tt,yScale:et,colorPalette:M})]}),it&&e(T,{visible:rt.tooltipVisible,x:rt.tooltipX,y:rt.tooltipY,point:rt.activePoint,series:rt.activeSeries,plotHeight:K,plotWidth:G,config:g,seriesColor:rt.activeSeries?.color??bt(n.findIndex(t=>t.id===rt.activeSeries?.id))})]}),e(W,{config:y,svgWidth:U,svgHeight:Z,margin:B,scale:_.scale,onZoomIn:_.zoomIn,onZoomOut:_.zoomOut,onReset:_.resetZoom}),e(H,{config:Y,svgRef:F,svgWidth:U,svgHeight:Z,margin:B})]}),_.showZoomHint&&e("div",{style:{position:"absolute",top:"50%",left:"50%",transform:"translate(-50%, -50%)",background:"rgba(0, 0, 0, 0.7)",color:"#fff",padding:"8px 16px",borderRadius:6,fontSize:13,fontFamily:"system-ui, -apple-system, sans-serif",pointerEvents:"none",whiteSpace:"nowrap",zIndex:10},children:"Hold Ctrl + scroll to zoom"}),X?.enabled&&e(N,{visible:ut.visible,x:ut.clientX,y:ut.clientY,nearestX:ut.nearestX,data:n,config:X,getSeriesColor:bt,onClose:yt})]})};U.displayName="LineChart";export{U as LineChart,O as exportChart,B as exportChartAsPdf,I as exportChartAsPng,F as exportChartAsSvg,h as useChartDimensions,x as useDataDomain,b as useScales,w as useTooltip,k as useZoom};
|
|
1
|
+
import{jsxs as t,jsx as e}from"react/jsx-runtime";import n,{useState as o,useLayoutEffect as i,useMemo as r,useRef as l,useCallback as a,useEffect as s,useId as c}from"react";const d=["#4e79a7","#f28e2b","#e15759","#76b7b2","#59a14f","#edc948","#b07aa1","#ff9da7","#9c755f","#bab0ac"];function h(t,e,n){const[r,l]=o({width:e??0,height:n??0}),a=void 0!==e&&void 0!==n;return i(()=>{if(a)return void l({width:e,height:n});const o=t.current;if(!o)return;const i=()=>{const t=o.getBoundingClientRect();l({width:t.width,height:t.height})};i();const r=new ResizeObserver(()=>{i()});return r.observe(o),()=>r.disconnect()},[t,a,e,n]),r}function f(t,e,n){return Math.min(Math.max(t,e),n)}function u(t,e,n){return t+(e-t)*n}function m(t,e){const n=Math.floor(Math.log10(t)),o=t/Math.pow(10,n);let i;return i=e?o<1.5?1:o<3?2:o<7?5:10:o<=1?1:o<=2?2:o<=5?5:10,i*Math.pow(10,n)}function y(t,e,n){if(t===e){const n=0===t?1:.1*Math.abs(t);t-=n,e+=n}const o=m(e-t,!1),i=m(o/(n-1),!0);return{niceMin:Math.floor(t/i)*i,niceMax:Math.ceil(e/i)*i,tickStep:i}}function g(t,e,n,o){return i=>{if(e===t)return(n+o)/2;const r=function(t,e,n){return t===e?0:(n-t)/(e-t)}(t,e,i);return u(n,o,r)}}function p(t,e,n){const o=[];for(let i=t;i<=e+.5*n;i+=n)o.push(parseFloat(i.toPrecision(12)));return o}function x(t,e,n){return r(()=>{let o=1/0,i=-1/0,r=1/0,l=-1/0;for(const e of t)for(const t of e.data)t.x<o&&(o=t.x),t.x>i&&(i=t.x),t.y<r&&(r=t.y),t.y>l&&(l=t.y);isFinite(o)||(o=0,i=1,r=0,l=1),void 0!==e?.min&&(o=e.min),void 0!==e?.max&&(i=e.max),void 0!==n?.min&&(r=n.min),void 0!==n?.max&&(l=n.max);const a=e?.tickCount??6,s=n?.tickCount??6,c=y(o,i,a),d=y(r,l,s);return{fullXDomain:[c.niceMin,c.niceMax],fullYDomain:[d.niceMin,d.niceMax]}},[t,e,n])}function b(t,e,n,o,i,l,a){return r(()=>{let r=1/0,s=-1/0,c=1/0,d=-1/0;for(const e of t)for(const t of e.data)t.x<r&&(r=t.x),t.x>s&&(s=t.x),t.y<c&&(c=t.y),t.y>d&&(d=t.y);isFinite(r)||(r=0,s=1,c=0,d=1),void 0!==o?.min&&(r=o.min),void 0!==o?.max&&(s=o.max),void 0!==i?.min&&(c=i.min),void 0!==i?.max&&(d=i.max);const h=o?.tickCount??6,f=i?.tickCount??6;let u,m,x,b;if(l)u=l[0],m=l[1];else{const t=y(r,s,h);u=t.niceMin,m=t.niceMax}if(a)x=a[0],b=a[1];else{const t=y(c,d,f);x=t.niceMin,b=t.niceMax}const k=y(u,m,h),v=y(x,b,f),w=g(u,m,0,e),M=g(x,b,n,0);let C=k.tickStep,$=k.niceMin,S=k.niceMax;o?.integerTicks&&(C=Math.max(1,Math.ceil(C)),$=Math.ceil(u),S=Math.floor(m));let L=v.tickStep,P=v.niceMin,T=v.niceMax;i?.integerTicks&&(L=Math.max(1,Math.ceil(L)),P=Math.ceil(x),T=Math.floor(b));return{xScale:w,yScale:M,xTicks:p($,S,C).filter(t=>t>=u&&t<=m).filter(t=>!o?.integerTicks||Number.isInteger(t)),yTicks:p(P,T,L).filter(t=>t>=x&&t<=b).filter(t=>!i?.integerTicks||Number.isInteger(t)),xDomain:[u,m],yDomain:[x,b]}},[t,e,n,o,i,l,a])}function k(t,e,n,i,r){const s=t?.enabled??!1,c=t?.maxScale??10,d=t?.step??.5,h=t?.enableWheel??!0,m=t?.enablePan??!0,y=t?.requireModifierKey??!0,g=t?.modifierKey??"shift",[p,x]=o(e),[b,k]=o(n),[v,w]=o(!1),[M,C]=o(!1),$=l({x:0,y:0,xDomain:e,yDomain:n}),S=l(null),L=l({x:e,y:n});e[0]===L.current.x[0]&&e[1]===L.current.x[1]&&n[0]===L.current.y[0]&&n[1]===L.current.y[1]||(L.current={x:e,y:n},x(e),k(n));const P=e[1]-e[0],T=p[1]-p[0],W=P>0&&T>0?P/T:1,D=a((t,e)=>{const n=t[1]-t[0];if(n>=e[1]-e[0])return e;let o=t[0],i=t[1];return o<e[0]&&(o=e[0],i=o+n),i>e[1]&&(i=e[1],o=i-n),[o,i]},[]),R=a(()=>{S.current&&clearTimeout(S.current),C(!0),S.current=setTimeout(()=>C(!1),2e3)},[]),z=a((t,o,i)=>{if(!s)return;const r=o??.5,l=i??.5;x(n=>{const o=(n[1]-n[0])/t,i=P/c,l=Math.max(o,i),a=Math.min(l,P),s=u(n[0],n[1],r)-a*r;return D([s,s+a],e)}),k(e=>{const o=e[1]-e[0],i=n[1]-n[0],r=o/t,a=i/c,s=Math.max(r,a),d=Math.min(s,i),h=u(e[0],e[1],l)-d*l;return D([h,h+d],n)})},[s,e,n,P,c,D]),A=a(()=>{z(1+d)},[d,z]),N=a(()=>{z(1/(1+d))},[d,z]),X=a(()=>{x(e),k(n)},[e,n]),Y=a((t,o)=>{if(!s)return;x(n=>{const o=(n[1]-n[0])/2,i=P/c,r=Math.max(o,i),l=Math.min(r,P),a=t-l/2;return D([a,a+l],e)}),k(t=>{const e=t[1]-t[0],i=n[1]-n[0],r=e/2,l=i/c,a=Math.max(r,l),s=Math.min(a,i),d=o-s/2;return D([d,d+s],n)})},[s,e,n,P,c,D]),E=a(t=>{if(!s||!h)return;if(y){if(!("shift"===g?t.shiftKey:"ctrl"===g?t.ctrlKey||t.metaKey:"alt"===g&&t.altKey))return void R()}t.preventDefault();const e=t.currentTarget.getBoundingClientRect(),n=t.clientX-e.left,o=t.clientY-e.top,i=f(n/(e.width||1),0,1),r=f(o/(e.height||1),0,1),l=t.deltaY<0?1+d:1/(1+d);z(l,i,r)},[s,h,y,g,d,R,z]),F=a(t=>{!s||!m||W<=1||0===t.button&&(w(!0),$.current={x:t.clientX,y:t.clientY,xDomain:p,yDomain:b})},[s,m,W,p,b]),I=a(t=>{if(!v)return;const o=t.clientX-$.current.x,l=t.clientY-$.current.y,a=$.current.xDomain,s=$.current.yDomain,c=a[1]-a[0],d=s[1]-s[0],h=-o/i*c,f=l/r*d,u=[a[0]+h,a[1]+h],m=[s[0]+f,s[1]+f];x(D(u,e)),k(D(m,n))},[v,i,r,e,n,D]),B=a(()=>{w(!1)},[]);return{viewXDomain:p,viewYDomain:b,scale:W,isPanning:v,showZoomHint:M,zoomIn:A,zoomOut:N,resetZoom:X,zoomToPoint:Y,handleWheel:E,handlePanStart:F,handlePanMove:I,handlePanEnd:B}}function v(t,e,n){if(0===t.length)return null;let o=0,i=t.length-1;for(;o<i;){const r=Math.floor((o+i)/2);n(t[r].x)<e?o=r+1:i=r}let r=t[o],l=Math.abs(n(r.x)-e);if(o>0){const i=Math.abs(n(t[o-1].x)-e);i<l&&(l=i,r=t[o-1])}return r}function w(t,e,n,i,r,l,s,c){const[d,h]=o(!1),[f,u]=o(0),[m,y]=o(0),[g,p]=o(null),[x,b]=o(null),[k,w]=o(null);return{tooltipVisible:d,tooltipX:f,tooltipY:m,activePoint:g,activeSeries:x,activeSeriesId:k,handleMouseMove:a(o=>{const a=t.current;if(!a)return;const c=a.getBoundingClientRect(),d=o.clientX-c.left-r,f=o.clientY-c.top-l;if(d<0||d>s)return h(!1),void w(null);let m=0,g=1/0;for(const t of e){const e=v(t.data,d,n);if(!e)continue;const o=Math.abs(n(e.x)-d);o<g&&(g=o,m=e.x)}let x=null,k=null,M=1/0;for(const t of e){let e=null,n=1/0;for(const o of t.data){const t=Math.abs(o.x-m);t<n&&(n=t,e=o)}if(!e)continue;const o=i(e.y),r=Math.abs(o-f);r<M&&(M=r,x=e,k=t)}x&&k&&(u(n(x.x)),y(i(x.y)),p(x),b(k),w(k.id),h(!0))},[t,e,n,i,r,l,s]),handleMouseLeave:a(()=>{h(!1),p(null),b(null),w(null)},[])}}const M=t=>Math.abs(t)>=1e6?`${(t/1e6).toFixed(1)}M`:Math.abs(t)>=1e3?`${(t/1e3).toFixed(1)}K`:Number.isInteger(t)?t.toString():t.toFixed(1),C=n.memo(({xTicks:n,yTicks:o,xScale:i,yScale:r,plotWidth:l,plotHeight:a,xAxisConfig:s,yAxisConfig:c,style:d})=>{const h=d?.axisColor??"#333",f=d?.tickColor??"#666",u=d?.fontFamily??"sans-serif",m=d?.fontSize??11,y=s?.tickFormat??M,g=c?.tickFormat??M;return t("g",{className:"chartifypdf-axes",children:[e("line",{x1:0,y1:a,x2:l,y2:a,stroke:h,strokeWidth:1}),n.map(n=>{const o=i(n);return t("g",{children:[e("line",{x1:o,y1:a,x2:o,y2:a+6,stroke:h,strokeWidth:1}),e("text",{x:o,y:a+18,textAnchor:"middle",fill:f,fontFamily:u,fontSize:m,children:y(n)})]},`x-tick-${n}`)}),s?.label&&e("text",{x:l/2,y:a+38,textAnchor:"middle",fill:h,fontFamily:u,fontSize:m+1,fontWeight:"bold",children:s.label}),e("line",{x1:0,y1:0,x2:0,y2:a,stroke:h,strokeWidth:1}),o.map(n=>{const o=r(n);return t("g",{children:[e("line",{x1:-6,y1:o,x2:0,y2:o,stroke:h,strokeWidth:1}),e("text",{x:-10,y:o,textAnchor:"end",dominantBaseline:"middle",fill:f,fontFamily:u,fontSize:m,children:g(n)})]},`y-tick-${n}`)}),c?.label&&e("text",{x:0,y:0,textAnchor:"middle",fill:h,fontFamily:u,fontSize:m+1,fontWeight:"bold",transform:`translate(-40, ${a/2}) rotate(-90)`,children:c.label})]})});C.displayName="Axes";const $=n.memo(({xTicks:n,yTicks:o,xScale:i,yScale:r,plotWidth:l,plotHeight:a,showXGrid:s,showYGrid:c,xGridColor:d="#e0e0e0",yGridColor:h="#e0e0e0"})=>t("g",{className:"chartifypdf-grid",children:[c&&o.map(t=>{const n=r(t);return e("line",{x1:0,y1:n,x2:l,y2:n,stroke:h,strokeDasharray:"4 4",strokeOpacity:.5},`y-grid-${t}`)}),s&&n.map(t=>{const n=i(t);return e("line",{x1:n,y1:0,x2:n,y2:a,stroke:d,strokeDasharray:"4 4",strokeOpacity:.5},`x-grid-${t}`)})]}));function S(t){if(0===t.length)return"";const[e,...n]=t;return`M${e.x},${e.y}`+n.map(t=>`L${t.x},${t.y}`).join("")}function L(t,e){switch(e){case"monotone":return function(t){const e=t.length;if(e<2)return S(t);if(2===e)return S(t);const n=[],o=[],i=[];for(let r=0;r<e-1;r++)n.push(t[r+1].x-t[r].x),o.push(t[r+1].y-t[r].y),i.push(0===n[r]?0:o[r]/n[r]);const r=new Array(e);r[0]=i[0],r[e-1]=i[e-2];for(let t=1;t<e-1;t++)i[t-1]*i[t]<=0?r[t]=0:r[t]=2/(1/i[t-1]+1/i[t]);for(let t=0;t<e-1;t++)if(0===i[t])r[t]=0,r[t+1]=0;else{const e=r[t]/i[t],n=r[t+1]/i[t],o=e*e+n*n;if(o>9){const l=3/Math.sqrt(o);r[t]=l*e*i[t],r[t+1]=l*n*i[t]}}let l=`M${t[0].x},${t[0].y}`;for(let o=0;o<e-1;o++){const e=n[o]/3;l+=`C${t[o].x+e},${t[o].y+r[o]*e},${t[o+1].x-e},${t[o+1].y-r[o+1]*e},${t[o+1].x},${t[o+1].y}`}return l}(t);case"natural":return function(t){const e=t.length;if(e<2)return S(t);if(2===e)return S(t);function n(t){const e=t.length-1,n=new Array(e),o=new Array(e),i=new Array(e);n[0]=0,o[0]=2,i[0]=t[0]+2*t[1];for(let r=1;r<e-1;r++)n[r]=1,o[r]=4,i[r]=4*t[r]+2*t[r+1];n[e-1]=2,o[e-1]=7,i[e-1]=8*t[e-1]+t[e];for(let t=1;t<e;t++){const e=n[t]/o[t-1];o[t]-=e,i[t]-=e*i[t-1]}const r=new Array(e);r[e-1]=i[e-1]/o[e-1];for(let t=e-2;t>=0;t--)r[t]=(i[t]-r[t+1])/o[t];const l=new Array(e);for(let n=0;n<e-1;n++)l[n]=2*t[n+1]-r[n+1];l[e-1]=(t[e]+r[e-1])/2;const a=[];for(let t=0;t<e;t++)a.push({cp1:r[t],cp2:l[t]});return a}const o=t.map(t=>t.x),i=t.map(t=>t.y),r=n(o),l=n(i);let a=`M${t[0].x},${t[0].y}`;for(let n=0;n<e-1;n++)a+=`C${r[n].cp1},${l[n].cp1},${r[n].cp2},${l[n].cp2},${t[n+1].x},${t[n+1].y}`;return a}(t);default:return S(t)}}$.displayName="GridLines";const P=n.memo(({series:n,xScale:i,yScale:r,color:a,animation:c,onPointClick:d,curveType:h,highlightOpacity:f})=>{const u=l(null),[m,y]=o(0),[g,p]=o(!c?.enabled),x=n.strokeWidth??2,b=n.showDots??!1,k=n.dotRadius??3.5,v=n.curveType??h??"linear",w=f??1,M=n.data.map(t=>({x:i(t.x),y:r(t.y)})),C="linear"===v?S(M):L(M,v);s(()=>{if(c?.enabled&&u.current){const t=u.current.getTotalLength();y(t),p(!1);const e=setTimeout(()=>{p(!0)},c.duration??800);return()=>clearTimeout(e)}},[C,c?.enabled,c?.duration]);const $=c?.enabled&&m>0?{strokeDasharray:m,strokeDashoffset:g?0:m,transition:`stroke-dashoffset ${c.duration??800}ms ${c.easing??"ease-in-out"}`}:{};return t("g",{className:"chartifypdf-line-path",style:{opacity:w,transition:"opacity 150ms ease"},children:[e("path",{ref:u,d:C,fill:"none",stroke:a,strokeWidth:x,strokeDasharray:n.strokeDasharray,strokeLinecap:"round",strokeLinejoin:"round",style:$}),b&&n.data.map((t,o)=>e("circle",{cx:i(t.x),cy:r(t.y),r:k,fill:a,stroke:"#fff",strokeWidth:1.5,style:{cursor:d?"pointer":"default"},onClick:d?()=>d(t,n):void 0},`dot-${n.id}-${o}`))]})});P.displayName="LinePath";const T=n.memo(({visible:n,x:o,y:i,point:r,series:l,plotHeight:a,plotWidth:s,config:c,seriesColor:d})=>{if(!n||!r||!l)return null;const h=c?.backgroundColor??"rgba(0, 0, 0, 0.8)",f=c?.textColor??"#fff";let u;if(c?.renderCustom)u=c.renderCustom(r,l);else{u=c?.formatter?c.formatter(r,l):`${l.name}: (${r.x}, ${r.y})`}let m=o+12,y=i-40-8;return m+140>s&&(m=o-140-12),y<0&&(y=i+12),t("g",{className:"chartifypdf-tooltip",pointerEvents:"none",children:[e("line",{x1:o,y1:0,x2:o,y2:a,stroke:"#999",strokeWidth:1,strokeDasharray:"4 4",opacity:.6}),e("circle",{cx:o,cy:i,r:5,fill:d,stroke:"#fff",strokeWidth:2}),e("foreignObject",{x:m,y:y,width:140,height:60,overflow:"visible",children:e("div",{style:{backgroundColor:h,color:f,padding:"6px 10px",borderRadius:"4px",fontSize:"12px",fontFamily:"sans-serif",whiteSpace:"nowrap",lineHeight:1.4,boxShadow:"0 2px 6px rgba(0,0,0,0.2)"},children:u})})]})});T.displayName="Tooltip";const W=n.memo(({config:n,svgWidth:o,svgHeight:i,margin:r,scale:l,onZoomIn:a,onZoomOut:s,onReset:c})=>{if(!n?.enabled||!1===n.showControls)return null;const d=n.controlsPosition??"top-right",h=24;let f,u;switch(d){case"top-left":f=r.left+8,u=r.top+8;break;case"bottom-left":f=r.left+8,u=i-r.bottom-24-8;break;case"bottom-right":f=o-r.right-80-8,u=i-r.bottom-24-8;break;default:f=o-r.right-80-8,u=r.top+8}return e("g",{className:"chartifypdf-zoom-controls",transform:`translate(${f}, ${u})`,children:(l>1?[{label:"+",onClick:a},{label:"−",onClick:s},{label:"↺",onClick:c}]:[{label:"+",onClick:a},{label:"−",onClick:s}]).map((n,o)=>t("g",{transform:`translate(${28*o}, 0)`,onClick:n.onClick,style:{cursor:"pointer"},children:[e("rect",{width:h,height:h,rx:4,fill:"rgba(255,255,255,0.9)",stroke:"#ccc",strokeWidth:1}),e("text",{x:12,y:12,textAnchor:"middle",dominantBaseline:"central",fontSize:14,fontFamily:"sans-serif",fill:"#333",fontWeight:"bold",children:n.label})]},n.label))})});function D({x:t,y:n,color:o}){return e("polygon",{points:`${t},${n} ${t-5},${n-10} ${t+5},${n-10}`,fill:o})}function R({x:t,y:n,color:o}){return e("polygon",{points:`${t},${n-6} ${t+5},${n} ${t},${n+6} ${t-5},${n}`,fill:o})}function z({x:t,y:n,color:o}){const i=[];for(let e=0;e<5;e++){const o=(72*e-90)*(Math.PI/180),r=(72*e+36-90)*(Math.PI/180);i.push(`${t+6*Math.cos(o)},${n+6*Math.sin(o)}`),i.push(`${t+3*Math.cos(r)},${n+3*Math.sin(r)}`)}return e("polygon",{points:i.join(" "),fill:o})}W.displayName="ZoomControls";const A=n.memo(({peaks:n,data:o,xScale:i,yScale:r})=>e("g",{className:"chartifypdf-peak-markers",children:n.map((n,l)=>{const a=function(t,e){let n=-1/0,o=-1;for(let i=0;i<t.length;i++){const r=t[i];let l=r.data[0],a=1/0;for(const t of r.data){const n=Math.abs(t.x-e);n<a&&(a=n,l=t)}l&&l.y>n&&(n=l.y,o=i)}return-1===o?null:{y:n,seriesIndex:o}}(o,n.x);if(!a)return null;const s=i(n.x),c=r(a.y),d=n.color??"#ef4444",h=n.icon??"arrow",f=n.label,u=c-14;return t("g",{children:[e("line",{x1:s,y1:c,x2:s,y2:u+6,stroke:d,strokeWidth:1,strokeDasharray:"3 2",opacity:.6}),"arrow"===h&&e(D,{x:s,y:u,color:d}),"diamond"===h&&e(R,{x:s,y:u,color:d}),"star"===h&&e(z,{x:s,y:u,color:d}),f&&e("text",{x:s,y:u-8,textAnchor:"middle",fill:d,fontSize:11,fontWeight:600,children:f})]},`peak-${l}`)})}));A.displayName="PeakMarkers";const N=({visible:n,x:o,y:i,nearestX:r,data:a,config:c,getSeriesColor:d,onClose:h})=>{const f=l(null);if(s(()=>{if(!n)return;const t=t=>{f.current&&!f.current.contains(t.target)&&h()},e=t=>{"Escape"===t.key&&h()},o=setTimeout(()=>{document.addEventListener("mousedown",t),document.addEventListener("keydown",e)},0);return()=>{clearTimeout(o),document.removeEventListener("mousedown",t),document.removeEventListener("keydown",e)}},[n,h]),!n)return null;const u=c?.backgroundColor??"#ffffff",m=c?.textColor??"#1f2937",y=c?.borderColor??"#e5e7eb",g=a.map((t,e)=>{const n=function(t,e){if(0===t.data.length)return null;let n=t.data[0],o=Math.abs(n.x-e);for(const i of t.data){const t=Math.abs(i.x-e);t<o&&(o=t,n=i)}return n.y}(t,r);return{name:t.name,color:t.color??d(e),x:r,y:n}});return t("div",{ref:f,style:{position:"fixed",left:o,top:i,zIndex:9999,backgroundColor:u,color:m,border:`1px solid ${y}`,borderRadius:6,boxShadow:"0 4px 12px rgba(0,0,0,0.15)",padding:"8px 0",minWidth:200,fontSize:12,fontFamily:"system-ui, -apple-system, sans-serif"},children:[t("div",{style:{padding:"4px 12px 8px",fontWeight:600,fontSize:11,color:m,opacity:.6,borderBottom:`1px solid ${y}`,marginBottom:4},children:["Data at X = ","number"==typeof r?r.toLocaleString():r]}),t("table",{style:{width:"100%",borderCollapse:"collapse"},children:[e("thead",{children:t("tr",{children:[e("th",{style:{textAlign:"left",padding:"4px 12px",fontWeight:600,opacity:.7},children:"Series"}),e("th",{style:{textAlign:"right",padding:"4px 12px",fontWeight:600,opacity:.7},children:"Y"})]})}),e("tbody",{children:g.map((n,o)=>t("tr",{style:{borderTop:o>0?`1px solid ${y}`:void 0},children:[t("td",{style:{padding:"4px 12px",display:"flex",alignItems:"center",gap:6},children:[e("span",{style:{display:"inline-block",width:8,height:8,borderRadius:"50%",backgroundColor:n.color,flexShrink:0}}),n.name]}),e("td",{style:{padding:"4px 12px",textAlign:"right",fontVariantNumeric:"tabular-nums"},children:null!==n.y?n.y.toLocaleString():"—"})]},o))})]})]})};function X(t){const e=t.cloneNode(!0),n=t.getBoundingClientRect();e.setAttribute("width",String(n.width)),e.setAttribute("height",String(n.height)),e.setAttribute("xmlns","http://www.w3.org/2000/svg"),e.setAttribute("xmlns:xlink","http://www.w3.org/1999/xlink");const o=t.querySelectorAll("*"),i=e.querySelectorAll("*");for(let t=0;t<o.length;t++){const e=o[t],n=i[t];if(!n.style)continue;const r=window.getComputedStyle(e),l=["fill","stroke","stroke-width","stroke-dasharray","opacity","font-family","font-size","font-weight","text-anchor","dominant-baseline","visibility","display"];for(const t of l){const e=r.getPropertyValue(t);e&&n.style.setProperty(t,e)}}return e}function Y(t,e){const n=URL.createObjectURL(t),o=document.createElement("a");o.href=n,o.download=e,document.body.appendChild(o),o.click(),document.body.removeChild(o),URL.revokeObjectURL(n)}async function E(t,e=2){const n=t.getBoundingClientRect(),o=n.width*e,i=n.height*e,r=document.createElement("canvas");r.width=o,r.height=i;const l=r.getContext("2d");if(!l)throw new Error("Cannot get canvas 2d context");l.scale(e,e);const a=function(t){const e=X(t),n=(new XMLSerializer).serializeToString(e),o=new Blob([n],{type:"image/svg+xml;charset=utf-8"});return URL.createObjectURL(o)}(t);return new Promise((t,e)=>{const o=new Image;o.onload=()=>{l.fillStyle="#ffffff",l.fillRect(0,0,n.width,n.height),l.drawImage(o,0,0,n.width,n.height),URL.revokeObjectURL(a),t(r)},o.onerror=()=>{URL.revokeObjectURL(a),e(new Error("Failed to load SVG as image"))},o.src=a})}async function F(t,e="chart"){const n=X(t),o=(new XMLSerializer).serializeToString(n);Y(new Blob([o],{type:"image/svg+xml;charset=utf-8"}),`${e}.svg`)}async function I(t,e="chart"){const n=await E(t);Y(await new Promise((t,e)=>{n.toBlob(n=>n?t(n):e(new Error("Canvas toBlob failed")),"image/png")}),`${e}.png`)}async function B(t,e="chart"){const n=(await E(t)).toDataURL("image/png"),o=t.getBoundingClientRect(),i=window.open("","_blank");if(!i)throw new Error("Popup blocked. Please allow popups to export PDF.");i.document.write(`\n <!DOCTYPE html>\n <html>\n <head>\n <title>${e}</title>\n <style>\n @page { size: landscape; margin: 10mm; }\n body { margin: 0; display: flex; justify-content: center; align-items: center; min-height: 100vh; }\n img { max-width: 100%; height: auto; }\n </style>\n </head>\n <body>\n <img src="${n}" width="${o.width}" height="${o.height}" />\n <script>\n window.onload = function() {\n setTimeout(function() { window.print(); window.close(); }, 300);\n };\n <\/script>\n </body>\n </html>\n `),i.document.close()}async function O(t,e="pdf",n="chart"){switch(e){case"svg":return F(t,n);case"png":return I(t,n);case"pdf":return B(t,n)}}N.displayName="ContextMenu";const H=n.memo(({config:n,svgRef:o,svgWidth:i,svgHeight:r,margin:l})=>{if(!n?.enabled)return null;let s,c;switch(n.buttonPosition??"top-right"){case"top-left":s=l.left+8,c=l.top+8+24+8;break;case"bottom-left":s=l.left+8,c=r-l.bottom-24-8;break;case"bottom-right":s=i-l.right-28-8,c=r-l.bottom-24-8;break;default:s=i-l.right-28-8,c=l.top+8+24+8}const d=a(()=>{const t=o.current;if(!t)return;O(t,n?.format??"pdf",n?.fileName??"chart")},[o,n?.format,n?.fileName]);return t("g",{className:"chartifypdf-export-button",transform:`translate(${s}, ${c})`,onClick:d,style:{cursor:"pointer"},children:[e("rect",{width:28,height:24,rx:4,fill:"rgba(255,255,255,0.9)",stroke:"#ccc",strokeWidth:1}),e("g",{transform:"translate(7, 4)",children:e("path",{d:"M7,2 L7,10 L4,7 M7,10 L10,7 M3,13 L11,13",fill:"none",stroke:"#333",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round"})})]})});H.displayName="ExportButton";const K={top:20,right:20,bottom:50,left:60},j=({data:n,width:i,height:r,margin:f,xAxis:u,yAxis:m,tooltip:y,zoom:g,style:p,animation:v,colorPalette:M,className:S,onPointClick:L,ariaLabel:D,curveType:R,peaks:z,contextMenu:X,export:Y})=>{const E=l(null),F=l(null),I=c(),B={...K,...f},O=h(E,i,r??400),{width:j,height:U}=O,Z=Math.max(0,j-B.left-B.right),G=Math.max(0,U-B.top-B.bottom),{fullXDomain:V,fullYDomain:q}=x(n,u,m),_=k(g,V,q,Z,G),J=g?.enabled??!1,Q=g?.enableClickZoom??!1,{xScale:tt,yScale:et,xTicks:nt,yTicks:ot}=b(n,Z,G,u,m,J?_.viewXDomain:void 0,J?_.viewYDomain:void 0),it=!1!==y?.enabled,rt=w(F,n,tt,et,B.left,B.top,Z),lt=rt.activeSeriesId,at=rt.tooltipVisible&&null!==lt,st=t=>at?t===lt?1:.2:1,ct=g?.requireModifierKey??!0,dt=g?.modifierKey??"shift",ht=g?.enableWheel??!0;s(()=>{const t=F.current;if(!t||!J||!ht)return;const e=t=>{if(ct){("shift"===dt?t.shiftKey:"ctrl"===dt?t.ctrlKey||t.metaKey:"alt"===dt&&t.altKey)&&t.preventDefault()}else t.preventDefault()};return t.addEventListener("wheel",e,{passive:!1}),()=>t.removeEventListener("wheel",e)},[J,ht,ct,dt]);const ft=a(t=>{if(!J||!Q)return;if(_.isPanning)return;const e=F.current;if(!e)return;const o=e.getBoundingClientRect(),i=t.clientX-o.left-B.left,r=t.clientY-o.top-B.top;if(i<0||i>Z||r<0||r>G)return;let l=0,a=0,s=1/0;for(const t of n)for(const e of t.data){const t=tt(e.x),n=et(e.y),o=Math.hypot(t-i,n-r);o<s&&(s=o,l=e.x,a=e.y)}_.zoomToPoint(l,a)},[J,Q,_,n,tt,et,B.left,B.top,Z,G]),ut=a(()=>{J&&Q&&_.resetZoom()},[J,Q,_]),[mt,yt]=o({visible:!1,clientX:0,clientY:0,nearestX:0}),gt=a(t=>{if(!X?.enabled)return;t.preventDefault();const e=F.current;if(!e)return;const o=e.getBoundingClientRect(),i=t.clientX-o.left-B.left;if(i<0||i>Z)return;let r=0,l=1/0;for(const t of n)for(const e of t.data){const t=tt(e.x),n=Math.abs(t-i);n<l&&(l=n,r=e.x)}yt({visible:!0,clientX:t.clientX,clientY:t.clientY,nearestX:r})},[X?.enabled,n,tt,B.left,Z]),pt=a(()=>{yt(t=>({...t,visible:!1}))},[]),xt=u?.gridLines??!1,bt=m?.gridLines??!0,kt=t=>function(t,e){const n=e??d;return n[t%n.length]}(t,M);return 0===j||0===U?e("div",{ref:E,className:S,style:{width:i??"100%",height:r??400,backgroundColor:p?.backgroundColor}}):t("div",{ref:E,className:S,style:{width:i??"100%",height:r??400,backgroundColor:p?.backgroundColor,position:"relative"},children:[t("svg",{ref:F,width:j,height:U,role:"img","aria-label":D??"Line chart",onMouseMove:it&&!_.isPanning?rt.handleMouseMove:void 0,onMouseLeave:it?rt.handleMouseLeave:void 0,onWheel:J?_.handleWheel:void 0,onMouseDown:J?_.handlePanStart:void 0,onMouseUp:J?_.handlePanEnd:void 0,onClick:ft,onDoubleClick:ut,onContextMenu:gt,style:{userSelect:_.isPanning?"none":void 0,cursor:_.isPanning?"grabbing":J&&_.scale>1?"grab":void 0},children:[e("defs",{children:e("clipPath",{id:I,children:e("rect",{width:Z,height:G})})}),t("g",{transform:`translate(${B.left}, ${B.top})`,children:[e(C,{xTicks:nt,yTicks:ot,xScale:tt,yScale:et,plotWidth:Z,plotHeight:G,xAxisConfig:u,yAxisConfig:m,style:p}),e($,{xTicks:nt,yTicks:ot,xScale:tt,yScale:et,plotWidth:Z,plotHeight:G,showXGrid:xt,showYGrid:bt,xGridColor:u?.gridLineColor,yGridColor:m?.gridLineColor}),t("g",{clipPath:`url(#${I})`,children:[J?e("g",{onMouseMove:_.handlePanMove,children:n.map((t,n)=>e(P,{series:t,xScale:tt,yScale:et,color:t.color??kt(n),animation:v,onPointClick:L,curveType:R,highlightOpacity:st(t.id)},t.id))}):n.map((t,n)=>e(P,{series:t,xScale:tt,yScale:et,color:t.color??kt(n),animation:v,onPointClick:L,curveType:R,highlightOpacity:st(t.id)},t.id)),z&&z.length>0&&e(A,{peaks:z,data:n,xScale:tt,yScale:et,colorPalette:M})]}),it&&e(T,{visible:rt.tooltipVisible,x:rt.tooltipX,y:rt.tooltipY,point:rt.activePoint,series:rt.activeSeries,plotHeight:G,plotWidth:Z,config:y,seriesColor:rt.activeSeries?.color??kt(n.findIndex(t=>t.id===rt.activeSeries?.id))})]}),e(W,{config:g,svgWidth:j,svgHeight:U,margin:B,scale:_.scale,onZoomIn:_.zoomIn,onZoomOut:_.zoomOut,onReset:_.resetZoom}),e(H,{config:Y,svgRef:F,svgWidth:j,svgHeight:U,margin:B})]}),_.showZoomHint&&e("div",{style:{position:"absolute",top:"50%",left:"50%",transform:"translate(-50%, -50%)",background:"rgba(0, 0, 0, 0.7)",color:"#fff",padding:"8px 16px",borderRadius:6,fontSize:13,fontFamily:"system-ui, -apple-system, sans-serif",pointerEvents:"none",whiteSpace:"nowrap",zIndex:10},children:`Hold ${"shift"===dt?"Shift":"ctrl"===dt?"Ctrl":"Alt"} + scroll to zoom`}),X?.enabled&&e(N,{visible:mt.visible,x:mt.clientX,y:mt.clientY,nearestX:mt.nearestX,data:n,config:X,getSeriesColor:kt,onClose:pt})]})};j.displayName="LineChart";export{j as LineChart,O as exportChart,B as exportChartAsPdf,I as exportChartAsPng,F as exportChartAsSvg,h as useChartDimensions,x as useDataDomain,b as useScales,w as useTooltip,k as useZoom};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|