chordia-ui 3.6.6 → 3.6.8

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.
@@ -1,3 +1,3 @@
1
- "use strict";const t=require("react/jsx-runtime"),E=require("react"),e=require("recharts"),a=["#5E88B0","#9B7AA8","#C98A5A","#7BA89D","#D17B6B","#6B7C93","#9B8E6F","#8A9BAF","#B8976A","#A8C76B"],_={fill:"var(--text-muted, #666)",fontSize:12},j={stroke:"var(--border, #e0e0e0)"},M="var(--border, #e0e0e0)",R={contentStyle:{backgroundColor:"var(--paper-elevated, #fff)",border:"1px solid var(--border, #e0e0e0)",borderRadius:"var(--radius-sm, 4px)",boxShadow:"0 2px 8px rgba(0, 0, 0, 0.1)",color:"var(--text-ink, #1e2125)"},labelStyle:{color:"var(--text-strong, #1e2125)"}},N={color:"var(--text-ink, #1e2125)",fontSize:"12px"},q=(l,c)=>{if(!l)return!1;const d=l.toLowerCase();return c.filter(s=>String(s).toLowerCase().includes(d)).length<c.length*.5},V=async(l,c)=>{const d=l.querySelector("svg");if(!d)return;const i=d.cloneNode(!0),s=d.clientWidth||600,x=d.clientHeight||300;i.setAttribute("width",s),i.setAttribute("height",x),i.setAttribute("xmlns","http://www.w3.org/2000/svg");const S=document.createElement("style");S.textContent='text { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }',i.insertBefore(S,i.firstChild);const k=new XMLSerializer().serializeToString(i),u=new Blob([k],{type:"image/svg+xml;charset=utf-8"}),h=URL.createObjectURL(u),m=new Image;m.onload=()=>{const g=document.createElement("canvas"),b=2;g.width=s*b,g.height=x*b;const y=g.getContext("2d");y.fillStyle="#ffffff",y.fillRect(0,0,g.width,g.height),y.scale(b,b),y.drawImage(m,0,0,s,x),URL.revokeObjectURL(h);const B=document.createElement("a");B.download=`${(c||"chart").replace(/[^a-z0-9]+/gi,"_")}.png`,B.href=g.toDataURL("image/png"),B.click()},m.src=h},H=(l,c)=>{const d=["",...l.map(x=>x.name)].join(","),i=c.map(x=>{const S=l.map(k=>{const u=k.data.find(h=>h.x===x);return u?u.y:""});return[x,...S].join(",")}),s=[d,...i].join(`
2
- `);navigator.clipboard.writeText(s)},$=({onDownload:l,onCopy:c,copied:d})=>t.jsxs("div",{style:{display:"flex",gap:6,justifyContent:"flex-end",marginBottom:8,opacity:.7,transition:"opacity 0.15s"},children:[t.jsx("button",{onClick:c,title:"Copy data as CSV",style:{background:"none",border:"1px solid var(--border, #e0e0e0)",borderRadius:"var(--radius-sm, 4px)",padding:"3px 8px",fontSize:11,color:"var(--text-muted, #666)",cursor:"pointer",display:"flex",alignItems:"center",gap:4},children:d?"✓ Copied":"📋 CSV"}),t.jsx("button",{onClick:l,title:"Download as PNG",style:{background:"none",border:"1px solid var(--border, #e0e0e0)",borderRadius:"var(--radius-sm, 4px)",padding:"3px 8px",fontSize:11,color:"var(--text-muted, #666)",cursor:"pointer",display:"flex",alignItems:"center",gap:4},children:"📥 PNG"})]}),J=({chartType:l,title:c,xLabel:d,yLabel:i,series:s})=>{const x=E.useRef(null),[S,k]=E.useState(!1);if(!s||s.length===0)return null;const u=[...new Set(s.flatMap(n=>n.data.map(r=>r.x)))],h=u.map(n=>{const r={x:n};return s.forEach(p=>{const o=p.data.find(f=>f.x===n);r[p.name]=o?o.y:null}),r}),m=s.map(n=>n.name),g=m.length===1,b=q(d,u),y=b?20:5,D=Math.max(...u.map(n=>String(n).length))>12||u.length>8,G={background:"var(--paper-elevated, #fff)",border:"1px solid var(--border, #e0e0e0)",borderRadius:"var(--radius-md, 8px)",padding:"16px",marginBottom:"16px"},O={color:"var(--text-strong, #1e2125)",fontSize:"14px",fontWeight:"600",marginBottom:"12px"},P={dataKey:"x",tick:D?{fill:"var(--text-muted, #666)",fontSize:11,angle:-35,textAnchor:"end"}:_,axisLine:j,tickLine:j,...b?{label:{value:d,position:"insideBottom",offset:-10,style:{textAnchor:"middle",fill:"var(--text-muted, #666)"}}}:{}},X={tick:_,axisLine:j,tickLine:j,...i?{label:{value:i,angle:-90,position:"insideLeft",style:{textAnchor:"middle",fill:"var(--text-muted, #666)"}}}:{}},U=()=>{switch(l){case"bar":return t.jsx(e.ResponsiveContainer,{width:"100%",height:300,children:t.jsxs(e.BarChart,{data:h,margin:{top:5,right:30,left:20,bottom:D?40:y},children:[t.jsx(e.CartesianGrid,{strokeDasharray:"3 3",stroke:M}),t.jsx(e.XAxis,{...P}),t.jsx(e.YAxis,{...X}),t.jsx(e.Tooltip,{...R}),!g&&t.jsx(e.Legend,{wrapperStyle:N}),m.map((n,r)=>t.jsx(e.Bar,{dataKey:n,fill:a[r%a.length],radius:[2,2,0,0],children:g&&h.map((p,o)=>t.jsx(e.Cell,{fill:a[o%a.length]},o))},n))]})});case"horizontal_bar":return t.jsx(e.ResponsiveContainer,{width:"100%",height:Math.max(300,h.length*40),children:t.jsxs(e.BarChart,{data:h,layout:"vertical",margin:{top:5,right:30,left:100,bottom:5},children:[t.jsx(e.CartesianGrid,{strokeDasharray:"3 3",stroke:M}),t.jsx(e.XAxis,{type:"number",tick:_,axisLine:j,tickLine:j,...i?{label:{value:i,position:"insideBottom",offset:-5,style:{textAnchor:"middle",fill:"var(--text-muted, #666)"}}}:{}}),t.jsx(e.YAxis,{type:"category",dataKey:"x",tick:{fill:"var(--text-muted, #666)",fontSize:11},width:90,axisLine:j,tickLine:j}),t.jsx(e.Tooltip,{...R}),!g&&t.jsx(e.Legend,{wrapperStyle:N}),m.map((n,r)=>t.jsx(e.Bar,{dataKey:n,fill:a[r%a.length],radius:[0,2,2,0],children:g&&h.map((p,o)=>t.jsx(e.Cell,{fill:a[o%a.length]},o))},n))]})});case"line":return t.jsx(e.ResponsiveContainer,{width:"100%",height:300,children:t.jsxs(e.LineChart,{data:h,margin:{top:5,right:30,left:20,bottom:D?40:y},children:[t.jsx(e.CartesianGrid,{strokeDasharray:"3 3",stroke:M}),t.jsx(e.XAxis,{...P}),t.jsx(e.YAxis,{...X}),t.jsx(e.Tooltip,{...R}),t.jsx(e.Legend,{wrapperStyle:N}),m.map((n,r)=>t.jsx(e.Line,{type:"monotone",dataKey:n,stroke:a[r%a.length],strokeWidth:2,dot:{r:4,fill:a[r%a.length]},activeDot:{r:6,fill:a[r%a.length]}},n))]})});case"area":return t.jsx(e.ResponsiveContainer,{width:"100%",height:300,children:t.jsxs(e.AreaChart,{data:h,margin:{top:5,right:30,left:20,bottom:D?40:y},children:[t.jsx(e.CartesianGrid,{strokeDasharray:"3 3",stroke:M}),t.jsx(e.XAxis,{...P}),t.jsx(e.YAxis,{...X}),t.jsx(e.Tooltip,{...R}),t.jsx(e.Legend,{wrapperStyle:N}),m.map((n,r)=>t.jsx(e.Area,{type:"monotone",dataKey:n,stroke:a[r%a.length],strokeWidth:2,fill:a[r%a.length],fillOpacity:.15},n))]})});case"pie":{const n=s[0].data.map((o,f)=>({name:o.x,value:o.y,fill:a[f%a.length]})),r=Math.PI/180,p=({cx:o,cy:f,midAngle:C,innerRadius:A,outerRadius:K,percent:w,name:L})=>{const z=K+20,I=o+z*Math.cos(-C*r),T=f+z*Math.sin(-C*r);return w<.04?null:t.jsxs("text",{x:I,y:T,fill:"var(--text-ink, #1e2125)",fontSize:11,textAnchor:I>o?"start":"end",dominantBaseline:"central",children:[L," (",(w*100).toFixed(0),"%)"]})};return t.jsx(e.ResponsiveContainer,{width:"100%",height:320,children:t.jsxs(e.PieChart,{children:[t.jsx(e.Pie,{data:n,cx:"50%",cy:"50%",outerRadius:100,dataKey:"value",label:p,labelLine:{stroke:"var(--text-muted, #666)"},children:n.map((o,f)=>t.jsx(e.Cell,{fill:o.fill},f))}),t.jsx(e.Tooltip,{...R})]})})}case"metric":{const n=s[0],r=n.data[0],p=n.data.length>1?n.data[1]:null,o=r.y,f=r.x||"",C=p!==null,A=C?o-p.y:0,K=C&&p.y!==0?A/Math.abs(p.y)*100:0,w=A>0,L=A<0,z=w?"#7BA89D":L?"#D17B6B":"var(--text-muted, #666)",I=w?"↑":L?"↓":"→",T=v=>Number.isInteger(v)&&Math.abs(v)>=1e3?v.toLocaleString():typeof v=="number"?v%1===0?v.toString():v.toFixed(v<10?2:1):String(v);return t.jsxs("div",{style:{display:"flex",alignItems:"baseline",gap:12,padding:"8px 0"},children:[t.jsx("div",{style:{fontSize:"36px",fontWeight:700,lineHeight:1,color:"var(--text-strong, #1e2125)",fontVariantNumeric:"tabular-nums"},children:T(o)}),f&&t.jsx("div",{style:{fontSize:"14px",color:"var(--text-muted, #666)",fontWeight:500},children:f}),C&&t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:4,fontSize:"13px",fontWeight:600,color:z,background:w?"rgba(123,168,157,0.12)":L?"rgba(209,123,107,0.12)":"rgba(128,128,128,0.08)",padding:"3px 8px",borderRadius:"var(--radius-sm, 4px)"},children:[t.jsx("span",{children:I}),t.jsxs("span",{children:[T(Math.abs(A))," (",Math.abs(K).toFixed(1),"%)"]})]}),C&&t.jsxs("div",{style:{fontSize:"11px",color:"var(--text-faint, #999)"},children:["vs ",p.x||"previous"]})]})}default:return t.jsxs("div",{style:{color:"var(--text-muted)",fontSize:12,padding:8},children:["Unsupported chart type: ",l]})}},W=E.useCallback(()=>{x.current&&V(x.current,c)},[c]),F=E.useCallback(()=>{H(s,u),k(!0),setTimeout(()=>k(!1),2e3)},[s,u]),Y=l!=="metric";return t.jsxs("div",{style:G,children:[c&&t.jsx("div",{style:O,children:c}),Y&&t.jsx($,{onDownload:W,onCopy:F,copied:S}),t.jsx("div",{ref:x,children:U()})]})};exports.ChartRenderer=J;
1
+ "use strict";const t=require("react/jsx-runtime"),E=require("react"),e=require("recharts"),a=["#5E88B0","#9B7AA8","#C98A5A","#7BA89D","#D17B6B","#6B7C93","#9B8E6F","#8A9BAF","#B8976A","#A8C76B"],_={fill:"var(--text-muted, #666)",fontSize:12},j={stroke:"var(--border, #e0e0e0)"},M="var(--border, #e0e0e0)",R={contentStyle:{backgroundColor:"var(--paper-elevated, #fff)",border:"1px solid var(--border, #e0e0e0)",borderRadius:"var(--radius-sm, 4px)",boxShadow:"0 2px 8px rgba(0, 0, 0, 0.1)",color:"var(--text-ink, #1e2125)"},labelStyle:{color:"var(--text-strong, #1e2125)"}},N={color:"var(--text-ink, #1e2125)",fontSize:"12px"},q=(l,c)=>{if(!l)return!1;const d=l.toLowerCase();return c.filter(o=>String(o).toLowerCase().includes(d)).length<c.length*.5},V=async(l,c)=>{const d=l.querySelector("svg");if(!d)return;const i=d.cloneNode(!0),o=d.clientWidth||600,x=d.clientHeight||300;i.setAttribute("width",o),i.setAttribute("height",x),i.setAttribute("xmlns","http://www.w3.org/2000/svg");const C=document.createElement("style");C.textContent='text { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }',i.insertBefore(C,i.firstChild);const S=new XMLSerializer().serializeToString(i),u=new Blob([S],{type:"image/svg+xml;charset=utf-8"}),h=URL.createObjectURL(u),m=new Image;m.onload=()=>{const g=document.createElement("canvas"),b=2;g.width=o*b,g.height=x*b;const y=g.getContext("2d");y.fillStyle="#ffffff",y.fillRect(0,0,g.width,g.height),y.scale(b,b),y.drawImage(m,0,0,o,x),URL.revokeObjectURL(h);const B=document.createElement("a");B.download=`${(c||"chart").replace(/[^a-z0-9]+/gi,"_")}.png`,B.href=g.toDataURL("image/png"),B.click()},m.src=h},H=(l,c)=>{const d=["",...l.map(x=>x.name)].join(","),i=c.map(x=>{const C=l.map(S=>{const u=S.data.find(h=>h.x===x);return u?u.y:""});return[x,...C].join(",")}),o=[d,...i].join(`
2
+ `);navigator.clipboard.writeText(o)},$=({onDownload:l,onCopy:c,copied:d})=>t.jsxs("div",{style:{display:"flex",gap:6,justifyContent:"flex-end",marginBottom:8,opacity:.7,transition:"opacity 0.15s"},children:[t.jsx("button",{onClick:c,title:"Copy data as CSV",style:{background:"none",border:"1px solid var(--border, #e0e0e0)",borderRadius:"var(--radius-sm, 4px)",padding:"3px 8px",fontSize:11,color:"var(--text-muted, #666)",cursor:"pointer",display:"flex",alignItems:"center",gap:4},children:d?"✓ Copied":"📋 CSV"}),t.jsx("button",{onClick:l,title:"Download as PNG",style:{background:"none",border:"1px solid var(--border, #e0e0e0)",borderRadius:"var(--radius-sm, 4px)",padding:"3px 8px",fontSize:11,color:"var(--text-muted, #666)",cursor:"pointer",display:"flex",alignItems:"center",gap:4},children:"📥 PNG"})]}),J=({chartType:l,title:c,xLabel:d,yLabel:i,series:o})=>{const x=E.useRef(null),[C,S]=E.useState(!1);if(!o||o.length===0)return null;const u=[...new Set(o.flatMap(n=>n.data.map(r=>r.x)))],h=u.map(n=>{const r={x:n};return o.forEach(p=>{const s=p.data.find(f=>f.x===n);r[p.name]=s?s.y:null}),r}),m=o.map(n=>n.name),g=m.length===1,b=q(d,u),y=b?20:5,D=Math.max(...u.map(n=>String(n).length))>12||u.length>8,G={background:"var(--paper-elevated, #fff)",border:"1px solid var(--border, #e0e0e0)",borderRadius:"var(--radius-md, 8px)",padding:"16px",marginBottom:"16px"},O={color:"var(--text-strong, #1e2125)",fontSize:"14px",fontWeight:"600",marginBottom:"12px"},P={dataKey:"x",tick:D?{fill:"var(--text-muted, #666)",fontSize:11,angle:-35,textAnchor:"end"}:_,axisLine:j,tickLine:j,...b?{label:{value:d,position:"insideBottom",offset:-10,style:{textAnchor:"middle",fill:"var(--text-muted, #666)"}}}:{}},X={tick:_,axisLine:j,tickLine:j,...i?{label:{value:i,angle:-90,position:"insideLeft",style:{textAnchor:"middle",fill:"var(--text-muted, #666)"}}}:{}},U=()=>{switch(l){case"bar":return t.jsx(e.ResponsiveContainer,{width:"100%",height:300,children:t.jsxs(e.BarChart,{data:h,margin:{top:5,right:30,left:20,bottom:D?40:y},children:[t.jsx(e.CartesianGrid,{strokeDasharray:"3 3",stroke:M}),t.jsx(e.XAxis,{...P}),t.jsx(e.YAxis,{...X}),t.jsx(e.Tooltip,{...R}),!g&&t.jsx(e.Legend,{wrapperStyle:N}),m.map((n,r)=>t.jsx(e.Bar,{dataKey:n,fill:a[r%a.length],radius:[2,2,0,0],isAnimationActive:!1,children:g&&h.map((p,s)=>t.jsx(e.Cell,{fill:a[s%a.length]},s))},n))]})});case"horizontal_bar":return t.jsx(e.ResponsiveContainer,{width:"100%",height:Math.max(300,h.length*40),children:t.jsxs(e.BarChart,{data:h,layout:"vertical",margin:{top:5,right:30,left:100,bottom:5},children:[t.jsx(e.CartesianGrid,{strokeDasharray:"3 3",stroke:M}),t.jsx(e.XAxis,{type:"number",tick:_,axisLine:j,tickLine:j,...i?{label:{value:i,position:"insideBottom",offset:-5,style:{textAnchor:"middle",fill:"var(--text-muted, #666)"}}}:{}}),t.jsx(e.YAxis,{type:"category",dataKey:"x",tick:{fill:"var(--text-muted, #666)",fontSize:11},width:90,axisLine:j,tickLine:j}),t.jsx(e.Tooltip,{...R}),!g&&t.jsx(e.Legend,{wrapperStyle:N}),m.map((n,r)=>t.jsx(e.Bar,{dataKey:n,fill:a[r%a.length],radius:[0,2,2,0],isAnimationActive:!1,children:g&&h.map((p,s)=>t.jsx(e.Cell,{fill:a[s%a.length]},s))},n))]})});case"line":return t.jsx(e.ResponsiveContainer,{width:"100%",height:300,children:t.jsxs(e.LineChart,{data:h,margin:{top:5,right:30,left:20,bottom:D?40:y},children:[t.jsx(e.CartesianGrid,{strokeDasharray:"3 3",stroke:M}),t.jsx(e.XAxis,{...P}),t.jsx(e.YAxis,{...X}),t.jsx(e.Tooltip,{...R}),t.jsx(e.Legend,{wrapperStyle:N}),m.map((n,r)=>t.jsx(e.Line,{type:"monotone",dataKey:n,stroke:a[r%a.length],strokeWidth:2,dot:{r:4,fill:a[r%a.length]},activeDot:{r:6,fill:a[r%a.length]},isAnimationActive:!1},n))]})});case"area":return t.jsx(e.ResponsiveContainer,{width:"100%",height:300,children:t.jsxs(e.AreaChart,{data:h,margin:{top:5,right:30,left:20,bottom:D?40:y},children:[t.jsx(e.CartesianGrid,{strokeDasharray:"3 3",stroke:M}),t.jsx(e.XAxis,{...P}),t.jsx(e.YAxis,{...X}),t.jsx(e.Tooltip,{...R}),t.jsx(e.Legend,{wrapperStyle:N}),m.map((n,r)=>t.jsx(e.Area,{type:"monotone",dataKey:n,stroke:a[r%a.length],strokeWidth:2,fill:a[r%a.length],fillOpacity:.15,isAnimationActive:!1},n))]})});case"pie":{const n=o[0].data.map((s,f)=>({name:s.x,value:s.y,fill:a[f%a.length]})),r=Math.PI/180,p=({cx:s,cy:f,midAngle:A,innerRadius:w,outerRadius:K,percent:k,name:L})=>{const z=K+20,I=s+z*Math.cos(-A*r),T=f+z*Math.sin(-A*r);return k<.04?null:t.jsxs("text",{x:I,y:T,fill:"var(--text-ink, #1e2125)",fontSize:11,textAnchor:I>s?"start":"end",dominantBaseline:"central",children:[L," (",(k*100).toFixed(0),"%)"]})};return t.jsx(e.ResponsiveContainer,{width:"100%",height:320,children:t.jsxs(e.PieChart,{children:[t.jsx(e.Pie,{data:n,cx:"50%",cy:"50%",outerRadius:100,dataKey:"value",label:p,labelLine:{stroke:"var(--text-muted, #666)"},isAnimationActive:!1,children:n.map((s,f)=>t.jsx(e.Cell,{fill:s.fill},f))}),t.jsx(e.Tooltip,{...R})]})})}case"metric":{const n=o[0],r=n.data[0],p=n.data.length>1?n.data[1]:null,s=r.y,f=r.x||"",A=p!==null,w=A?s-p.y:0,K=A&&p.y!==0?w/Math.abs(p.y)*100:0,k=w>0,L=w<0,z=k?"#7BA89D":L?"#D17B6B":"var(--text-muted, #666)",I=k?"↑":L?"↓":"→",T=v=>Number.isInteger(v)&&Math.abs(v)>=1e3?v.toLocaleString():typeof v=="number"?v%1===0?v.toString():v.toFixed(v<10?2:1):String(v);return t.jsxs("div",{style:{display:"flex",alignItems:"baseline",gap:12,padding:"8px 0"},children:[t.jsx("div",{style:{fontSize:"36px",fontWeight:700,lineHeight:1,color:"var(--text-strong, #1e2125)",fontVariantNumeric:"tabular-nums"},children:T(s)}),f&&t.jsx("div",{style:{fontSize:"14px",color:"var(--text-muted, #666)",fontWeight:500},children:f}),A&&t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:4,fontSize:"13px",fontWeight:600,color:z,background:k?"rgba(123,168,157,0.12)":L?"rgba(209,123,107,0.12)":"rgba(128,128,128,0.08)",padding:"3px 8px",borderRadius:"var(--radius-sm, 4px)"},children:[t.jsx("span",{children:I}),t.jsxs("span",{children:[T(Math.abs(w))," (",Math.abs(K).toFixed(1),"%)"]})]}),A&&t.jsxs("div",{style:{fontSize:"11px",color:"var(--text-faint, #999)"},children:["vs ",p.x||"previous"]})]})}default:return t.jsxs("div",{style:{color:"var(--text-muted)",fontSize:12,padding:8},children:["Unsupported chart type: ",l]})}},W=E.useCallback(()=>{x.current&&V(x.current,c)},[c]),F=E.useCallback(()=>{H(o,u),S(!0),setTimeout(()=>S(!1),2e3)},[o,u]),Y=l!=="metric";return t.jsxs("div",{style:G,children:[c&&t.jsx("div",{style:O,children:c}),Y&&t.jsx($,{onDownload:W,onCopy:F,copied:C}),t.jsx("div",{ref:x,children:U()})]})};exports.ChartRenderer=J;
3
3
  //# sourceMappingURL=ChartRenderer.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChartRenderer.cjs.js","sources":["../src/components/chat/ChartRenderer.jsx"],"sourcesContent":["\"use client\";\nimport React, { useRef, useCallback } from 'react';\nimport {\n ResponsiveContainer, BarChart, Bar, Cell, LineChart, Line,\n XAxis, YAxis, CartesianGrid, Tooltip, Legend,\n PieChart, Pie, AreaChart, Area,\n} from 'recharts';\n\n// Chordia design system rail colors — ordered for max visual distinction\nconst COLORS = [\n '#5E88B0', // rail-discovery / rail-blue\n '#9B7AA8', // rail-purple / rail-tone\n '#C98A5A', // rail-compliance / rail-orange\n '#7BA89D', // rail-signal-upsell (teal-green)\n '#D17B6B', // rail-coral / rail-signal-churn\n '#6B7C93', // rail-slate / rail-outcome\n '#9B8E6F', // rail-olive / rail-signal-satisfaction\n '#8A9BAF', // rail-quality\n '#B8976A', // rail-teal (warm gold)\n '#A8C76B', // green accent (complementary)\n];\n\n// Shared axis/tooltip/legend styling\nconst AXIS_TICK = { fill: 'var(--text-muted, #666)', fontSize: 12 };\nconst AXIS_LINE = { stroke: 'var(--border, #e0e0e0)' };\nconst GRID_STROKE = 'var(--border, #e0e0e0)';\nconst TOOLTIP_STYLE = {\n contentStyle: {\n backgroundColor: 'var(--paper-elevated, #fff)',\n border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-sm, 4px)',\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',\n color: 'var(--text-ink, #1e2125)',\n },\n labelStyle: { color: 'var(--text-strong, #1e2125)' },\n};\nconst LEGEND_STYLE = { color: 'var(--text-ink, #1e2125)', fontSize: '12px' };\n\n// Smart label: skip x_label if tick values already contain the label text\nconst shouldShowAxisLabel = (label, tickValues) => {\n if (!label) return false;\n const lower = label.toLowerCase();\n // If most ticks contain the label word, it's redundant\n const matches = tickValues.filter(v => String(v).toLowerCase().includes(lower));\n return matches.length < tickValues.length * 0.5;\n};\n\n// --- Export utilities ---\nconst downloadPng = async (containerEl, title) => {\n const svg = containerEl.querySelector('svg');\n if (!svg) return;\n const clone = svg.cloneNode(true);\n // Ensure dimensions\n const w = svg.clientWidth || 600;\n const h = svg.clientHeight || 300;\n clone.setAttribute('width', w);\n clone.setAttribute('height', h);\n clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg');\n // Inline computed styles for export fidelity\n const styleEl = document.createElement('style');\n styleEl.textContent = `text { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif; }`;\n clone.insertBefore(styleEl, clone.firstChild);\n const xml = new XMLSerializer().serializeToString(clone);\n const blob = new Blob([xml], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const img = new Image();\n img.onload = () => {\n const canvas = document.createElement('canvas');\n const scale = 2; // retina\n canvas.width = w * scale;\n canvas.height = h * scale;\n const ctx = canvas.getContext('2d');\n ctx.fillStyle = '#ffffff';\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.scale(scale, scale);\n ctx.drawImage(img, 0, 0, w, h);\n URL.revokeObjectURL(url);\n const link = document.createElement('a');\n link.download = `${(title || 'chart').replace(/[^a-z0-9]+/gi, '_')}.png`;\n link.href = canvas.toDataURL('image/png');\n link.click();\n };\n img.src = url;\n};\n\nconst copyAsCsv = (series, allXValues) => {\n const header = ['', ...series.map(s => s.name)].join(',');\n const rows = allXValues.map(x => {\n const vals = series.map(s => {\n const match = s.data.find(d => d.x === x);\n return match ? match.y : '';\n });\n return [x, ...vals].join(',');\n });\n const csv = [header, ...rows].join('\\n');\n navigator.clipboard.writeText(csv);\n};\n\nconst ActionBar = ({ onDownload, onCopy, copied }) => (\n <div style={{\n display: 'flex', gap: 6, justifyContent: 'flex-end',\n marginBottom: 8, opacity: 0.7, transition: 'opacity 0.15s',\n }}>\n <button onClick={onCopy} title=\"Copy data as CSV\" style={{\n background: 'none', border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-sm, 4px)', padding: '3px 8px',\n fontSize: 11, color: 'var(--text-muted, #666)', cursor: 'pointer',\n display: 'flex', alignItems: 'center', gap: 4,\n }}>\n {copied ? '✓ Copied' : '📋 CSV'}\n </button>\n <button onClick={onDownload} title=\"Download as PNG\" style={{\n background: 'none', border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-sm, 4px)', padding: '3px 8px',\n fontSize: 11, color: 'var(--text-muted, #666)', cursor: 'pointer',\n display: 'flex', alignItems: 'center', gap: 4,\n }}>\n 📥 PNG\n </button>\n </div>\n);\n\nconst ChartRenderer = ({ chartType, title, xLabel, yLabel, series }) => {\n const chartRef = useRef(null);\n const [copied, setCopied] = React.useState(false);\n\n if (!series || series.length === 0) return null;\n\n // Transform: merge all series into [{x, series1: val, series2: val}, ...]\n const allXValues = [...new Set(series.flatMap(s => s.data.map(d => d.x)))];\n const chartData = allXValues.map(x => {\n const point = { x };\n series.forEach(s => {\n const match = s.data.find(d => d.x === x);\n point[s.name] = match ? match.y : null;\n });\n return point;\n });\n\n const seriesNames = series.map(s => s.name);\n const isSingleSeries = seriesNames.length === 1;\n\n // Determine if axis labels are redundant\n const showXLabel = shouldShowAxisLabel(xLabel, allXValues);\n const bottomMargin = showXLabel ? 20 : 5;\n\n // Check if x-axis labels are long (rotate them)\n const maxTickLen = Math.max(...allXValues.map(v => String(v).length));\n const rotateXTicks = maxTickLen > 12 || allXValues.length > 8;\n\n const containerStyle = {\n background: 'var(--paper-elevated, #fff)',\n border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-md, 8px)',\n padding: '16px',\n marginBottom: '16px',\n };\n\n const titleStyle = {\n color: 'var(--text-strong, #1e2125)',\n fontSize: '14px',\n fontWeight: '600',\n marginBottom: '12px',\n };\n\n const xAxisProps = {\n dataKey: 'x',\n tick: rotateXTicks\n ? { fill: 'var(--text-muted, #666)', fontSize: 11, angle: -35, textAnchor: 'end' }\n : AXIS_TICK,\n axisLine: AXIS_LINE,\n tickLine: AXIS_LINE,\n ...(showXLabel ? {\n label: { value: xLabel, position: 'insideBottom', offset: -10, style: { textAnchor: 'middle', fill: 'var(--text-muted, #666)' } }\n } : {}),\n };\n\n const yAxisProps = {\n tick: AXIS_TICK,\n axisLine: AXIS_LINE,\n tickLine: AXIS_LINE,\n ...(yLabel ? {\n label: { value: yLabel, angle: -90, position: 'insideLeft', style: { textAnchor: 'middle', fill: 'var(--text-muted, #666)' } }\n } : {}),\n };\n\n const renderChart = () => {\n switch (chartType) {\n case 'bar':\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <BarChart data={chartData} margin={{ top: 5, right: 30, left: 20, bottom: rotateXTicks ? 40 : bottomMargin }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis {...xAxisProps} />\n <YAxis {...yAxisProps} />\n <Tooltip {...TOOLTIP_STYLE} />\n {!isSingleSeries && <Legend wrapperStyle={LEGEND_STYLE} />}\n {seriesNames.map((name, i) => (\n <Bar key={name} dataKey={name} fill={COLORS[i % COLORS.length]} radius={[2, 2, 0, 0]}>\n {isSingleSeries && chartData.map((_, idx) => (\n <Cell key={idx} fill={COLORS[idx % COLORS.length]} />\n ))}\n </Bar>\n ))}\n </BarChart>\n </ResponsiveContainer>\n );\n\n case 'horizontal_bar': {\n // Horizontal bar: swap X/Y, use YAxis for categories\n return (\n <ResponsiveContainer width=\"100%\" height={Math.max(300, chartData.length * 40)}>\n <BarChart data={chartData} layout=\"vertical\" margin={{ top: 5, right: 30, left: 100, bottom: 5 }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis type=\"number\" tick={AXIS_TICK} axisLine={AXIS_LINE} tickLine={AXIS_LINE}\n {...(yLabel ? { label: { value: yLabel, position: 'insideBottom', offset: -5, style: { textAnchor: 'middle', fill: 'var(--text-muted, #666)' } } } : {})}\n />\n <YAxis type=\"category\" dataKey=\"x\" tick={{ fill: 'var(--text-muted, #666)', fontSize: 11 }} width={90} axisLine={AXIS_LINE} tickLine={AXIS_LINE} />\n <Tooltip {...TOOLTIP_STYLE} />\n {!isSingleSeries && <Legend wrapperStyle={LEGEND_STYLE} />}\n {seriesNames.map((name, i) => (\n <Bar key={name} dataKey={name} fill={COLORS[i % COLORS.length]} radius={[0, 2, 2, 0]}>\n {isSingleSeries && chartData.map((_, idx) => (\n <Cell key={idx} fill={COLORS[idx % COLORS.length]} />\n ))}\n </Bar>\n ))}\n </BarChart>\n </ResponsiveContainer>\n );\n }\n\n case 'line':\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <LineChart data={chartData} margin={{ top: 5, right: 30, left: 20, bottom: rotateXTicks ? 40 : bottomMargin }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis {...xAxisProps} />\n <YAxis {...yAxisProps} />\n <Tooltip {...TOOLTIP_STYLE} />\n <Legend wrapperStyle={LEGEND_STYLE} />\n {seriesNames.map((name, i) => (\n <Line key={name} type=\"monotone\" dataKey={name}\n stroke={COLORS[i % COLORS.length]} strokeWidth={2}\n dot={{ r: 4, fill: COLORS[i % COLORS.length] }}\n activeDot={{ r: 6, fill: COLORS[i % COLORS.length] }}\n />\n ))}\n </LineChart>\n </ResponsiveContainer>\n );\n\n case 'area':\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <AreaChart data={chartData} margin={{ top: 5, right: 30, left: 20, bottom: rotateXTicks ? 40 : bottomMargin }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis {...xAxisProps} />\n <YAxis {...yAxisProps} />\n <Tooltip {...TOOLTIP_STYLE} />\n <Legend wrapperStyle={LEGEND_STYLE} />\n {seriesNames.map((name, i) => (\n <Area key={name} type=\"monotone\" dataKey={name}\n stroke={COLORS[i % COLORS.length]} strokeWidth={2}\n fill={COLORS[i % COLORS.length]} fillOpacity={0.15}\n />\n ))}\n </AreaChart>\n </ResponsiveContainer>\n );\n\n case 'pie': {\n // Pie uses first series only\n const pieData = series[0].data.map((d, i) => ({\n name: d.x,\n value: d.y,\n fill: COLORS[i % COLORS.length],\n }));\n const RADIAN = Math.PI / 180;\n const renderLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, percent, name }) => {\n const radius = outerRadius + 20;\n const x = cx + radius * Math.cos(-midAngle * RADIAN);\n const y = cy + radius * Math.sin(-midAngle * RADIAN);\n if (percent < 0.04) return null;\n return (\n <text x={x} y={y} fill=\"var(--text-ink, #1e2125)\" fontSize={11}\n textAnchor={x > cx ? 'start' : 'end'} dominantBaseline=\"central\">\n {name} ({(percent * 100).toFixed(0)}%)\n </text>\n );\n };\n return (\n <ResponsiveContainer width=\"100%\" height={320}>\n <PieChart>\n <Pie data={pieData} cx=\"50%\" cy=\"50%\" outerRadius={100}\n dataKey=\"value\" label={renderLabel} labelLine={{ stroke: 'var(--text-muted, #666)' }}>\n {pieData.map((entry, i) => (\n <Cell key={i} fill={entry.fill} />\n ))}\n </Pie>\n <Tooltip {...TOOLTIP_STYLE} />\n </PieChart>\n </ResponsiveContainer>\n );\n }\n\n case 'metric': {\n const s = series[0];\n const current = s.data[0];\n const previous = s.data.length > 1 ? s.data[1] : null;\n const value = current.y;\n const unit = current.x || '';\n const hasTrend = previous !== null;\n const change = hasTrend ? value - previous.y : 0;\n const pctChange = hasTrend && previous.y !== 0 ? ((change / Math.abs(previous.y)) * 100) : 0;\n const isPositive = change > 0;\n const isNegative = change < 0;\n const trendColor = isPositive ? '#7BA89D' : isNegative ? '#D17B6B' : 'var(--text-muted, #666)';\n const trendArrow = isPositive ? '↑' : isNegative ? '↓' : '→';\n\n // Format large numbers nicely\n const fmt = (n) => {\n if (Number.isInteger(n) && Math.abs(n) >= 1000) return n.toLocaleString();\n if (typeof n === 'number') return n % 1 === 0 ? n.toString() : n.toFixed(n < 10 ? 2 : 1);\n return String(n);\n };\n\n return (\n <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, padding: '8px 0' }}>\n <div style={{\n fontSize: '36px', fontWeight: 700, lineHeight: 1,\n color: 'var(--text-strong, #1e2125)',\n fontVariantNumeric: 'tabular-nums',\n }}>\n {fmt(value)}\n </div>\n {unit && (\n <div style={{ fontSize: '14px', color: 'var(--text-muted, #666)', fontWeight: 500 }}>\n {unit}\n </div>\n )}\n {hasTrend && (\n <div style={{\n display: 'flex', alignItems: 'center', gap: 4,\n fontSize: '13px', fontWeight: 600, color: trendColor,\n background: isPositive ? 'rgba(123,168,157,0.12)' : isNegative ? 'rgba(209,123,107,0.12)' : 'rgba(128,128,128,0.08)',\n padding: '3px 8px', borderRadius: 'var(--radius-sm, 4px)',\n }}>\n <span>{trendArrow}</span>\n <span>{fmt(Math.abs(change))} ({Math.abs(pctChange).toFixed(1)}%)</span>\n </div>\n )}\n {hasTrend && (\n <div style={{ fontSize: '11px', color: 'var(--text-faint, #999)' }}>\n vs {previous.x || 'previous'}\n </div>\n )}\n </div>\n );\n }\n\n default:\n return <div style={{ color: 'var(--text-muted)', fontSize: 12, padding: 8 }}>Unsupported chart type: {chartType}</div>;\n }\n };\n\n const handleDownload = useCallback(() => {\n if (chartRef.current) downloadPng(chartRef.current, title);\n }, [title]);\n\n const handleCopy = useCallback(() => {\n copyAsCsv(series, allXValues);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }, [series, allXValues]);\n\n const showActions = chartType !== 'metric';\n\n return (\n <div style={containerStyle}>\n {title && <div style={titleStyle}>{title}</div>}\n {showActions && <ActionBar onDownload={handleDownload} onCopy={handleCopy} copied={copied} />}\n <div ref={chartRef}>\n {renderChart()}\n </div>\n </div>\n );\n};\n\nexport default ChartRenderer;\n"],"names":["COLORS","AXIS_TICK","AXIS_LINE","GRID_STROKE","TOOLTIP_STYLE","LEGEND_STYLE","shouldShowAxisLabel","label","tickValues","lower","v","downloadPng","containerEl","title","svg","clone","w","h","styleEl","xml","blob","url","img","canvas","scale","ctx","link","copyAsCsv","series","allXValues","header","s","rows","vals","match","d","csv","ActionBar","onDownload","onCopy","copied","jsxs","jsx","ChartRenderer","chartType","xLabel","yLabel","chartRef","useRef","setCopied","React","chartData","x","point","seriesNames","isSingleSeries","showXLabel","bottomMargin","rotateXTicks","containerStyle","titleStyle","xAxisProps","yAxisProps","renderChart","ResponsiveContainer","BarChart","CartesianGrid","XAxis","YAxis","Tooltip","Legend","name","i","Bar","_","idx","Cell","LineChart","Line","AreaChart","Area","pieData","RADIAN","renderLabel","cx","cy","midAngle","innerRadius","outerRadius","percent","radius","y","PieChart","Pie","entry","current","previous","value","unit","hasTrend","change","pctChange","isPositive","isNegative","trendColor","trendArrow","fmt","n","handleDownload","useCallback","handleCopy","showActions"],"mappings":"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"}
1
+ {"version":3,"file":"ChartRenderer.cjs.js","sources":["../src/components/chat/ChartRenderer.jsx"],"sourcesContent":["\"use client\";\nimport React, { useRef, useCallback } from 'react';\nimport {\n ResponsiveContainer, BarChart, Bar, Cell, LineChart, Line,\n XAxis, YAxis, CartesianGrid, Tooltip, Legend,\n PieChart, Pie, AreaChart, Area,\n} from 'recharts';\n\n// Chordia design system rail colors — ordered for max visual distinction\nconst COLORS = [\n '#5E88B0', // rail-discovery / rail-blue\n '#9B7AA8', // rail-purple / rail-tone\n '#C98A5A', // rail-compliance / rail-orange\n '#7BA89D', // rail-signal-upsell (teal-green)\n '#D17B6B', // rail-coral / rail-signal-churn\n '#6B7C93', // rail-slate / rail-outcome\n '#9B8E6F', // rail-olive / rail-signal-satisfaction\n '#8A9BAF', // rail-quality\n '#B8976A', // rail-teal (warm gold)\n '#A8C76B', // green accent (complementary)\n];\n\n// Shared axis/tooltip/legend styling\nconst AXIS_TICK = { fill: 'var(--text-muted, #666)', fontSize: 12 };\nconst AXIS_LINE = { stroke: 'var(--border, #e0e0e0)' };\nconst GRID_STROKE = 'var(--border, #e0e0e0)';\nconst TOOLTIP_STYLE = {\n contentStyle: {\n backgroundColor: 'var(--paper-elevated, #fff)',\n border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-sm, 4px)',\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',\n color: 'var(--text-ink, #1e2125)',\n },\n labelStyle: { color: 'var(--text-strong, #1e2125)' },\n};\nconst LEGEND_STYLE = { color: 'var(--text-ink, #1e2125)', fontSize: '12px' };\n\n// Smart label: skip x_label if tick values already contain the label text\nconst shouldShowAxisLabel = (label, tickValues) => {\n if (!label) return false;\n const lower = label.toLowerCase();\n // If most ticks contain the label word, it's redundant\n const matches = tickValues.filter(v => String(v).toLowerCase().includes(lower));\n return matches.length < tickValues.length * 0.5;\n};\n\n// --- Export utilities ---\nconst downloadPng = async (containerEl, title) => {\n const svg = containerEl.querySelector('svg');\n if (!svg) return;\n const clone = svg.cloneNode(true);\n // Ensure dimensions\n const w = svg.clientWidth || 600;\n const h = svg.clientHeight || 300;\n clone.setAttribute('width', w);\n clone.setAttribute('height', h);\n clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg');\n // Inline computed styles for export fidelity\n const styleEl = document.createElement('style');\n styleEl.textContent = `text { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif; }`;\n clone.insertBefore(styleEl, clone.firstChild);\n const xml = new XMLSerializer().serializeToString(clone);\n const blob = new Blob([xml], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const img = new Image();\n img.onload = () => {\n const canvas = document.createElement('canvas');\n const scale = 2; // retina\n canvas.width = w * scale;\n canvas.height = h * scale;\n const ctx = canvas.getContext('2d');\n ctx.fillStyle = '#ffffff';\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.scale(scale, scale);\n ctx.drawImage(img, 0, 0, w, h);\n URL.revokeObjectURL(url);\n const link = document.createElement('a');\n link.download = `${(title || 'chart').replace(/[^a-z0-9]+/gi, '_')}.png`;\n link.href = canvas.toDataURL('image/png');\n link.click();\n };\n img.src = url;\n};\n\nconst copyAsCsv = (series, allXValues) => {\n const header = ['', ...series.map(s => s.name)].join(',');\n const rows = allXValues.map(x => {\n const vals = series.map(s => {\n const match = s.data.find(d => d.x === x);\n return match ? match.y : '';\n });\n return [x, ...vals].join(',');\n });\n const csv = [header, ...rows].join('\\n');\n navigator.clipboard.writeText(csv);\n};\n\nconst ActionBar = ({ onDownload, onCopy, copied }) => (\n <div style={{\n display: 'flex', gap: 6, justifyContent: 'flex-end',\n marginBottom: 8, opacity: 0.7, transition: 'opacity 0.15s',\n }}>\n <button onClick={onCopy} title=\"Copy data as CSV\" style={{\n background: 'none', border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-sm, 4px)', padding: '3px 8px',\n fontSize: 11, color: 'var(--text-muted, #666)', cursor: 'pointer',\n display: 'flex', alignItems: 'center', gap: 4,\n }}>\n {copied ? '✓ Copied' : '📋 CSV'}\n </button>\n <button onClick={onDownload} title=\"Download as PNG\" style={{\n background: 'none', border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-sm, 4px)', padding: '3px 8px',\n fontSize: 11, color: 'var(--text-muted, #666)', cursor: 'pointer',\n display: 'flex', alignItems: 'center', gap: 4,\n }}>\n 📥 PNG\n </button>\n </div>\n);\n\nconst ChartRenderer = ({ chartType, title, xLabel, yLabel, series }) => {\n const chartRef = useRef(null);\n const [copied, setCopied] = React.useState(false);\n\n if (!series || series.length === 0) return null;\n\n // Transform: merge all series into [{x, series1: val, series2: val}, ...]\n const allXValues = [...new Set(series.flatMap(s => s.data.map(d => d.x)))];\n const chartData = allXValues.map(x => {\n const point = { x };\n series.forEach(s => {\n const match = s.data.find(d => d.x === x);\n point[s.name] = match ? match.y : null;\n });\n return point;\n });\n\n const seriesNames = series.map(s => s.name);\n const isSingleSeries = seriesNames.length === 1;\n\n // Determine if axis labels are redundant\n const showXLabel = shouldShowAxisLabel(xLabel, allXValues);\n const bottomMargin = showXLabel ? 20 : 5;\n\n // Check if x-axis labels are long (rotate them)\n const maxTickLen = Math.max(...allXValues.map(v => String(v).length));\n const rotateXTicks = maxTickLen > 12 || allXValues.length > 8;\n\n const containerStyle = {\n background: 'var(--paper-elevated, #fff)',\n border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-md, 8px)',\n padding: '16px',\n marginBottom: '16px',\n };\n\n const titleStyle = {\n color: 'var(--text-strong, #1e2125)',\n fontSize: '14px',\n fontWeight: '600',\n marginBottom: '12px',\n };\n\n const xAxisProps = {\n dataKey: 'x',\n tick: rotateXTicks\n ? { fill: 'var(--text-muted, #666)', fontSize: 11, angle: -35, textAnchor: 'end' }\n : AXIS_TICK,\n axisLine: AXIS_LINE,\n tickLine: AXIS_LINE,\n ...(showXLabel ? {\n label: { value: xLabel, position: 'insideBottom', offset: -10, style: { textAnchor: 'middle', fill: 'var(--text-muted, #666)' } }\n } : {}),\n };\n\n const yAxisProps = {\n tick: AXIS_TICK,\n axisLine: AXIS_LINE,\n tickLine: AXIS_LINE,\n ...(yLabel ? {\n label: { value: yLabel, angle: -90, position: 'insideLeft', style: { textAnchor: 'middle', fill: 'var(--text-muted, #666)' } }\n } : {}),\n };\n\n const renderChart = () => {\n switch (chartType) {\n case 'bar':\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <BarChart data={chartData} margin={{ top: 5, right: 30, left: 20, bottom: rotateXTicks ? 40 : bottomMargin }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis {...xAxisProps} />\n <YAxis {...yAxisProps} />\n <Tooltip {...TOOLTIP_STYLE} />\n {!isSingleSeries && <Legend wrapperStyle={LEGEND_STYLE} />}\n {seriesNames.map((name, i) => (\n <Bar key={name} dataKey={name} fill={COLORS[i % COLORS.length]} radius={[2, 2, 0, 0]} isAnimationActive={false}>\n {isSingleSeries && chartData.map((_, idx) => (\n <Cell key={idx} fill={COLORS[idx % COLORS.length]} />\n ))}\n </Bar>\n ))}\n </BarChart>\n </ResponsiveContainer>\n );\n\n case 'horizontal_bar': {\n // Horizontal bar: swap X/Y, use YAxis for categories\n return (\n <ResponsiveContainer width=\"100%\" height={Math.max(300, chartData.length * 40)}>\n <BarChart data={chartData} layout=\"vertical\" margin={{ top: 5, right: 30, left: 100, bottom: 5 }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis type=\"number\" tick={AXIS_TICK} axisLine={AXIS_LINE} tickLine={AXIS_LINE}\n {...(yLabel ? { label: { value: yLabel, position: 'insideBottom', offset: -5, style: { textAnchor: 'middle', fill: 'var(--text-muted, #666)' } } } : {})}\n />\n <YAxis type=\"category\" dataKey=\"x\" tick={{ fill: 'var(--text-muted, #666)', fontSize: 11 }} width={90} axisLine={AXIS_LINE} tickLine={AXIS_LINE} />\n <Tooltip {...TOOLTIP_STYLE} />\n {!isSingleSeries && <Legend wrapperStyle={LEGEND_STYLE} />}\n {seriesNames.map((name, i) => (\n <Bar key={name} dataKey={name} fill={COLORS[i % COLORS.length]} radius={[0, 2, 2, 0]} isAnimationActive={false}>\n {isSingleSeries && chartData.map((_, idx) => (\n <Cell key={idx} fill={COLORS[idx % COLORS.length]} />\n ))}\n </Bar>\n ))}\n </BarChart>\n </ResponsiveContainer>\n );\n }\n\n case 'line':\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <LineChart data={chartData} margin={{ top: 5, right: 30, left: 20, bottom: rotateXTicks ? 40 : bottomMargin }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis {...xAxisProps} />\n <YAxis {...yAxisProps} />\n <Tooltip {...TOOLTIP_STYLE} />\n <Legend wrapperStyle={LEGEND_STYLE} />\n {seriesNames.map((name, i) => (\n <Line key={name} type=\"monotone\" dataKey={name}\n stroke={COLORS[i % COLORS.length]} strokeWidth={2}\n dot={{ r: 4, fill: COLORS[i % COLORS.length] }}\n activeDot={{ r: 6, fill: COLORS[i % COLORS.length] }}\n isAnimationActive={false}\n />\n ))}\n </LineChart>\n </ResponsiveContainer>\n );\n\n case 'area':\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <AreaChart data={chartData} margin={{ top: 5, right: 30, left: 20, bottom: rotateXTicks ? 40 : bottomMargin }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis {...xAxisProps} />\n <YAxis {...yAxisProps} />\n <Tooltip {...TOOLTIP_STYLE} />\n <Legend wrapperStyle={LEGEND_STYLE} />\n {seriesNames.map((name, i) => (\n <Area key={name} type=\"monotone\" dataKey={name}\n stroke={COLORS[i % COLORS.length]} strokeWidth={2}\n fill={COLORS[i % COLORS.length]} fillOpacity={0.15}\n isAnimationActive={false}\n />\n ))}\n </AreaChart>\n </ResponsiveContainer>\n );\n\n case 'pie': {\n // Pie uses first series only\n const pieData = series[0].data.map((d, i) => ({\n name: d.x,\n value: d.y,\n fill: COLORS[i % COLORS.length],\n }));\n const RADIAN = Math.PI / 180;\n const renderLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, percent, name }) => {\n const radius = outerRadius + 20;\n const x = cx + radius * Math.cos(-midAngle * RADIAN);\n const y = cy + radius * Math.sin(-midAngle * RADIAN);\n if (percent < 0.04) return null;\n return (\n <text x={x} y={y} fill=\"var(--text-ink, #1e2125)\" fontSize={11}\n textAnchor={x > cx ? 'start' : 'end'} dominantBaseline=\"central\">\n {name} ({(percent * 100).toFixed(0)}%)\n </text>\n );\n };\n return (\n <ResponsiveContainer width=\"100%\" height={320}>\n <PieChart>\n <Pie data={pieData} cx=\"50%\" cy=\"50%\" outerRadius={100}\n dataKey=\"value\" label={renderLabel} labelLine={{ stroke: 'var(--text-muted, #666)' }}\n isAnimationActive={false}>\n {pieData.map((entry, i) => (\n <Cell key={i} fill={entry.fill} />\n ))}\n </Pie>\n <Tooltip {...TOOLTIP_STYLE} />\n </PieChart>\n </ResponsiveContainer>\n );\n }\n\n case 'metric': {\n const s = series[0];\n const current = s.data[0];\n const previous = s.data.length > 1 ? s.data[1] : null;\n const value = current.y;\n const unit = current.x || '';\n const hasTrend = previous !== null;\n const change = hasTrend ? value - previous.y : 0;\n const pctChange = hasTrend && previous.y !== 0 ? ((change / Math.abs(previous.y)) * 100) : 0;\n const isPositive = change > 0;\n const isNegative = change < 0;\n const trendColor = isPositive ? '#7BA89D' : isNegative ? '#D17B6B' : 'var(--text-muted, #666)';\n const trendArrow = isPositive ? '↑' : isNegative ? '↓' : '→';\n\n // Format large numbers nicely\n const fmt = (n) => {\n if (Number.isInteger(n) && Math.abs(n) >= 1000) return n.toLocaleString();\n if (typeof n === 'number') return n % 1 === 0 ? n.toString() : n.toFixed(n < 10 ? 2 : 1);\n return String(n);\n };\n\n return (\n <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, padding: '8px 0' }}>\n <div style={{\n fontSize: '36px', fontWeight: 700, lineHeight: 1,\n color: 'var(--text-strong, #1e2125)',\n fontVariantNumeric: 'tabular-nums',\n }}>\n {fmt(value)}\n </div>\n {unit && (\n <div style={{ fontSize: '14px', color: 'var(--text-muted, #666)', fontWeight: 500 }}>\n {unit}\n </div>\n )}\n {hasTrend && (\n <div style={{\n display: 'flex', alignItems: 'center', gap: 4,\n fontSize: '13px', fontWeight: 600, color: trendColor,\n background: isPositive ? 'rgba(123,168,157,0.12)' : isNegative ? 'rgba(209,123,107,0.12)' : 'rgba(128,128,128,0.08)',\n padding: '3px 8px', borderRadius: 'var(--radius-sm, 4px)',\n }}>\n <span>{trendArrow}</span>\n <span>{fmt(Math.abs(change))} ({Math.abs(pctChange).toFixed(1)}%)</span>\n </div>\n )}\n {hasTrend && (\n <div style={{ fontSize: '11px', color: 'var(--text-faint, #999)' }}>\n vs {previous.x || 'previous'}\n </div>\n )}\n </div>\n );\n }\n\n default:\n return <div style={{ color: 'var(--text-muted)', fontSize: 12, padding: 8 }}>Unsupported chart type: {chartType}</div>;\n }\n };\n\n const handleDownload = useCallback(() => {\n if (chartRef.current) downloadPng(chartRef.current, title);\n }, [title]);\n\n const handleCopy = useCallback(() => {\n copyAsCsv(series, allXValues);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }, [series, allXValues]);\n\n const showActions = chartType !== 'metric';\n\n return (\n <div style={containerStyle}>\n {title && <div style={titleStyle}>{title}</div>}\n {showActions && <ActionBar onDownload={handleDownload} onCopy={handleCopy} copied={copied} />}\n <div ref={chartRef}>\n {renderChart()}\n </div>\n </div>\n );\n};\n\nexport default ChartRenderer;\n"],"names":["COLORS","AXIS_TICK","AXIS_LINE","GRID_STROKE","TOOLTIP_STYLE","LEGEND_STYLE","shouldShowAxisLabel","label","tickValues","lower","v","downloadPng","containerEl","title","svg","clone","w","h","styleEl","xml","blob","url","img","canvas","scale","ctx","link","copyAsCsv","series","allXValues","header","s","rows","vals","match","d","csv","ActionBar","onDownload","onCopy","copied","jsxs","jsx","ChartRenderer","chartType","xLabel","yLabel","chartRef","useRef","setCopied","React","chartData","x","point","seriesNames","isSingleSeries","showXLabel","bottomMargin","rotateXTicks","containerStyle","titleStyle","xAxisProps","yAxisProps","renderChart","ResponsiveContainer","BarChart","CartesianGrid","XAxis","YAxis","Tooltip","Legend","name","i","Bar","_","idx","Cell","LineChart","Line","AreaChart","Area","pieData","RADIAN","renderLabel","cx","cy","midAngle","innerRadius","outerRadius","percent","radius","y","PieChart","Pie","entry","current","previous","value","unit","hasTrend","change","pctChange","isPositive","isNegative","trendColor","trendArrow","fmt","n","handleDownload","useCallback","handleCopy","showActions"],"mappings":"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"}
@@ -42,24 +42,24 @@ const r = [
42
42
  return;
43
43
  const i = c.cloneNode(!0), o = c.clientWidth || 600, h = c.clientHeight || 300;
44
44
  i.setAttribute("width", o), i.setAttribute("height", h), i.setAttribute("xmlns", "http://www.w3.org/2000/svg");
45
- const k = document.createElement("style");
46
- k.textContent = 'text { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }', i.insertBefore(k, i.firstChild);
47
- const C = new XMLSerializer().serializeToString(i), u = new Blob([C], { type: "image/svg+xml;charset=utf-8" }), p = URL.createObjectURL(u), x = new Image();
45
+ const w = document.createElement("style");
46
+ w.textContent = 'text { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }', i.insertBefore(w, i.firstChild);
47
+ const k = new XMLSerializer().serializeToString(i), f = new Blob([k], { type: "image/svg+xml;charset=utf-8" }), p = URL.createObjectURL(f), x = new Image();
48
48
  x.onload = () => {
49
- const g = document.createElement("canvas"), S = 2;
50
- g.width = o * S, g.height = h * S;
51
- const y = g.getContext("2d");
52
- y.fillStyle = "#ffffff", y.fillRect(0, 0, g.width, g.height), y.scale(S, S), y.drawImage(x, 0, 0, o, h), URL.revokeObjectURL(p);
49
+ const m = document.createElement("canvas"), S = 2;
50
+ m.width = o * S, m.height = h * S;
51
+ const y = m.getContext("2d");
52
+ y.fillStyle = "#ffffff", y.fillRect(0, 0, m.width, m.height), y.scale(S, S), y.drawImage(x, 0, 0, o, h), URL.revokeObjectURL(p);
53
53
  const I = document.createElement("a");
54
- I.download = `${(s || "chart").replace(/[^a-z0-9]+/gi, "_")}.png`, I.href = g.toDataURL("image/png"), I.click();
54
+ I.download = `${(s || "chart").replace(/[^a-z0-9]+/gi, "_")}.png`, I.href = m.toDataURL("image/png"), I.click();
55
55
  }, x.src = p;
56
56
  }, ht = (l, s) => {
57
57
  const c = ["", ...l.map((h) => h.name)].join(","), i = s.map((h) => {
58
- const k = l.map((C) => {
59
- const u = C.data.find((p) => p.x === h);
60
- return u ? u.y : "";
58
+ const w = l.map((k) => {
59
+ const f = k.data.find((p) => p.x === h);
60
+ return f ? f.y : "";
61
61
  });
62
- return [h, ...k].join(",");
62
+ return [h, ...w].join(",");
63
63
  }), o = [c, ...i].join(`
64
64
  `);
65
65
  navigator.clipboard.writeText(o);
@@ -96,16 +96,16 @@ const r = [
96
96
  gap: 4
97
97
  }, children: "📥 PNG" })
98
98
  ] }), xt = ({ chartType: l, title: s, xLabel: c, yLabel: i, series: o }) => {
99
- const h = nt(null), [k, C] = et.useState(!1);
99
+ const h = nt(null), [w, k] = et.useState(!1);
100
100
  if (!o || o.length === 0)
101
101
  return null;
102
- const u = [...new Set(o.flatMap((e) => e.data.map((n) => n.x)))], p = u.map((e) => {
102
+ const f = [...new Set(o.flatMap((e) => e.data.map((n) => n.x)))], p = f.map((e) => {
103
103
  const n = { x: e };
104
- return o.forEach((f) => {
105
- const a = f.data.find((m) => m.x === e);
106
- n[f.name] = a ? a.y : null;
104
+ return o.forEach((u) => {
105
+ const a = u.data.find((g) => g.x === e);
106
+ n[u.name] = a ? a.y : null;
107
107
  }), n;
108
- }), x = o.map((e) => e.name), g = x.length === 1, S = ct(c, u), y = S ? 20 : 5, E = Math.max(...u.map((e) => String(e).length)) > 12 || u.length > 8, $ = {
108
+ }), x = o.map((e) => e.name), m = x.length === 1, S = ct(c, f), y = S ? 20 : 5, E = Math.max(...f.map((e) => String(e).length)) > 12 || f.length > 8, $ = {
109
109
  background: "var(--paper-elevated, #fff)",
110
110
  border: "1px solid var(--border, #e0e0e0)",
111
111
  borderRadius: "var(--radius-md, 8px)",
@@ -139,8 +139,8 @@ const r = [
139
139
  /* @__PURE__ */ t(P, { ...W }),
140
140
  /* @__PURE__ */ t(K, { ...X }),
141
141
  /* @__PURE__ */ t(D, { ...z }),
142
- !g && /* @__PURE__ */ t(j, { wrapperStyle: U }),
143
- x.map((e, n) => /* @__PURE__ */ t(q, { dataKey: e, fill: r[n % r.length], radius: [2, 2, 0, 0], children: g && p.map((f, a) => /* @__PURE__ */ t(G, { fill: r[a % r.length] }, a)) }, e))
142
+ !m && /* @__PURE__ */ t(j, { wrapperStyle: U }),
143
+ x.map((e, n) => /* @__PURE__ */ t(q, { dataKey: e, fill: r[n % r.length], radius: [2, 2, 0, 0], isAnimationActive: !1, children: m && p.map((u, a) => /* @__PURE__ */ t(G, { fill: r[a % r.length] }, a)) }, e))
144
144
  ] }) });
145
145
  case "horizontal_bar":
146
146
  return /* @__PURE__ */ t(R, { width: "100%", height: Math.max(300, p.length * 40), children: /* @__PURE__ */ d(H, { data: p, layout: "vertical", margin: { top: 5, right: 30, left: 100, bottom: 5 }, children: [
@@ -157,8 +157,8 @@ const r = [
157
157
  ),
158
158
  /* @__PURE__ */ t(K, { type: "category", dataKey: "x", tick: { fill: "var(--text-muted, #666)", fontSize: 11 }, width: 90, axisLine: b, tickLine: b }),
159
159
  /* @__PURE__ */ t(D, { ...z }),
160
- !g && /* @__PURE__ */ t(j, { wrapperStyle: U }),
161
- x.map((e, n) => /* @__PURE__ */ t(q, { dataKey: e, fill: r[n % r.length], radius: [0, 2, 2, 0], children: g && p.map((f, a) => /* @__PURE__ */ t(G, { fill: r[a % r.length] }, a)) }, e))
160
+ !m && /* @__PURE__ */ t(j, { wrapperStyle: U }),
161
+ x.map((e, n) => /* @__PURE__ */ t(q, { dataKey: e, fill: r[n % r.length], radius: [0, 2, 2, 0], isAnimationActive: !1, children: m && p.map((u, a) => /* @__PURE__ */ t(G, { fill: r[a % r.length] }, a)) }, e))
162
162
  ] }) });
163
163
  case "line":
164
164
  return /* @__PURE__ */ t(R, { width: "100%", height: 300, children: /* @__PURE__ */ d(lt, { data: p, margin: { top: 5, right: 30, left: 20, bottom: E ? 40 : y }, children: [
@@ -175,7 +175,8 @@ const r = [
175
175
  stroke: r[n % r.length],
176
176
  strokeWidth: 2,
177
177
  dot: { r: 4, fill: r[n % r.length] },
178
- activeDot: { r: 6, fill: r[n % r.length] }
178
+ activeDot: { r: 6, fill: r[n % r.length] },
179
+ isAnimationActive: !1
179
180
  },
180
181
  e
181
182
  ))
@@ -195,16 +196,17 @@ const r = [
195
196
  stroke: r[n % r.length],
196
197
  strokeWidth: 2,
197
198
  fill: r[n % r.length],
198
- fillOpacity: 0.15
199
+ fillOpacity: 0.15,
200
+ isAnimationActive: !1
199
201
  },
200
202
  e
201
203
  ))
202
204
  ] }) });
203
205
  case "pie": {
204
- const e = o[0].data.map((a, m) => ({
206
+ const e = o[0].data.map((a, g) => ({
205
207
  name: a.x,
206
208
  value: a.y,
207
- fill: r[m % r.length]
209
+ fill: r[g % r.length]
208
210
  })), n = Math.PI / 180;
209
211
  return /* @__PURE__ */ t(R, { width: "100%", height: 320, children: /* @__PURE__ */ d(rt, { children: [
210
212
  /* @__PURE__ */ t(
@@ -215,9 +217,9 @@ const r = [
215
217
  cy: "50%",
216
218
  outerRadius: 100,
217
219
  dataKey: "value",
218
- label: ({ cx: a, cy: m, midAngle: w, innerRadius: L, outerRadius: F, percent: A, name: B }) => {
219
- const M = F + 20, T = a + M * Math.cos(-w * n), _ = m + M * Math.sin(-w * n);
220
- return A < 0.04 ? null : /* @__PURE__ */ d(
220
+ label: ({ cx: a, cy: g, midAngle: A, innerRadius: L, outerRadius: F, percent: C, name: B }) => {
221
+ const M = F + 20, T = a + M * Math.cos(-A * n), _ = g + M * Math.sin(-A * n);
222
+ return C < 0.04 ? null : /* @__PURE__ */ d(
221
223
  "text",
222
224
  {
223
225
  x: T,
@@ -229,21 +231,22 @@ const r = [
229
231
  children: [
230
232
  B,
231
233
  " (",
232
- (A * 100).toFixed(0),
234
+ (C * 100).toFixed(0),
233
235
  "%)"
234
236
  ]
235
237
  }
236
238
  );
237
239
  },
238
240
  labelLine: { stroke: "var(--text-muted, #666)" },
239
- children: e.map((a, m) => /* @__PURE__ */ t(G, { fill: a.fill }, m))
241
+ isAnimationActive: !1,
242
+ children: e.map((a, g) => /* @__PURE__ */ t(G, { fill: a.fill }, g))
240
243
  }
241
244
  ),
242
245
  /* @__PURE__ */ t(D, { ...z })
243
246
  ] }) });
244
247
  }
245
248
  case "metric": {
246
- const e = o[0], n = e.data[0], f = e.data.length > 1 ? e.data[1] : null, a = n.y, m = n.x || "", w = f !== null, L = w ? a - f.y : 0, F = w && f.y !== 0 ? L / Math.abs(f.y) * 100 : 0, A = L > 0, B = L < 0, M = A ? "#7BA89D" : B ? "#D17B6B" : "var(--text-muted, #666)", T = A ? "↑" : B ? "↓" : "→", _ = (v) => Number.isInteger(v) && Math.abs(v) >= 1e3 ? v.toLocaleString() : typeof v == "number" ? v % 1 === 0 ? v.toString() : v.toFixed(v < 10 ? 2 : 1) : String(v);
249
+ const e = o[0], n = e.data[0], u = e.data.length > 1 ? e.data[1] : null, a = n.y, g = n.x || "", A = u !== null, L = A ? a - u.y : 0, F = A && u.y !== 0 ? L / Math.abs(u.y) * 100 : 0, C = L > 0, B = L < 0, M = C ? "#7BA89D" : B ? "#D17B6B" : "var(--text-muted, #666)", T = C ? "↑" : B ? "↓" : "→", _ = (v) => Number.isInteger(v) && Math.abs(v) >= 1e3 ? v.toLocaleString() : typeof v == "number" ? v % 1 === 0 ? v.toString() : v.toFixed(v < 10 ? 2 : 1) : String(v);
247
250
  return /* @__PURE__ */ d("div", { style: { display: "flex", alignItems: "baseline", gap: 12, padding: "8px 0" }, children: [
248
251
  /* @__PURE__ */ t("div", { style: {
249
252
  fontSize: "36px",
@@ -252,15 +255,15 @@ const r = [
252
255
  color: "var(--text-strong, #1e2125)",
253
256
  fontVariantNumeric: "tabular-nums"
254
257
  }, children: _(a) }),
255
- m && /* @__PURE__ */ t("div", { style: { fontSize: "14px", color: "var(--text-muted, #666)", fontWeight: 500 }, children: m }),
256
- w && /* @__PURE__ */ d("div", { style: {
258
+ g && /* @__PURE__ */ t("div", { style: { fontSize: "14px", color: "var(--text-muted, #666)", fontWeight: 500 }, children: g }),
259
+ A && /* @__PURE__ */ d("div", { style: {
257
260
  display: "flex",
258
261
  alignItems: "center",
259
262
  gap: 4,
260
263
  fontSize: "13px",
261
264
  fontWeight: 600,
262
265
  color: M,
263
- background: A ? "rgba(123,168,157,0.12)" : B ? "rgba(209,123,107,0.12)" : "rgba(128,128,128,0.08)",
266
+ background: C ? "rgba(123,168,157,0.12)" : B ? "rgba(209,123,107,0.12)" : "rgba(128,128,128,0.08)",
264
267
  padding: "3px 8px",
265
268
  borderRadius: "var(--radius-sm, 4px)"
266
269
  }, children: [
@@ -272,9 +275,9 @@ const r = [
272
275
  "%)"
273
276
  ] })
274
277
  ] }),
275
- w && /* @__PURE__ */ d("div", { style: { fontSize: "11px", color: "var(--text-faint, #999)" }, children: [
278
+ A && /* @__PURE__ */ d("div", { style: { fontSize: "11px", color: "var(--text-faint, #999)" }, children: [
276
279
  "vs ",
277
- f.x || "previous"
280
+ u.x || "previous"
278
281
  ] })
279
282
  ] });
280
283
  }
@@ -287,11 +290,11 @@ const r = [
287
290
  }, Z = Y(() => {
288
291
  h.current && dt(h.current, s);
289
292
  }, [s]), tt = Y(() => {
290
- ht(o, u), C(!0), setTimeout(() => C(!1), 2e3);
291
- }, [o, u]);
293
+ ht(o, f), k(!0), setTimeout(() => k(!1), 2e3);
294
+ }, [o, f]);
292
295
  return /* @__PURE__ */ d("div", { style: $, children: [
293
296
  s && /* @__PURE__ */ t("div", { style: J, children: s }),
294
- l !== "metric" && /* @__PURE__ */ t(pt, { onDownload: Z, onCopy: tt, copied: k }),
297
+ l !== "metric" && /* @__PURE__ */ t(pt, { onDownload: Z, onCopy: tt, copied: w }),
295
298
  /* @__PURE__ */ t("div", { ref: h, children: Q() })
296
299
  ] });
297
300
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ChartRenderer.es.js","sources":["../src/components/chat/ChartRenderer.jsx"],"sourcesContent":["\"use client\";\nimport React, { useRef, useCallback } from 'react';\nimport {\n ResponsiveContainer, BarChart, Bar, Cell, LineChart, Line,\n XAxis, YAxis, CartesianGrid, Tooltip, Legend,\n PieChart, Pie, AreaChart, Area,\n} from 'recharts';\n\n// Chordia design system rail colors — ordered for max visual distinction\nconst COLORS = [\n '#5E88B0', // rail-discovery / rail-blue\n '#9B7AA8', // rail-purple / rail-tone\n '#C98A5A', // rail-compliance / rail-orange\n '#7BA89D', // rail-signal-upsell (teal-green)\n '#D17B6B', // rail-coral / rail-signal-churn\n '#6B7C93', // rail-slate / rail-outcome\n '#9B8E6F', // rail-olive / rail-signal-satisfaction\n '#8A9BAF', // rail-quality\n '#B8976A', // rail-teal (warm gold)\n '#A8C76B', // green accent (complementary)\n];\n\n// Shared axis/tooltip/legend styling\nconst AXIS_TICK = { fill: 'var(--text-muted, #666)', fontSize: 12 };\nconst AXIS_LINE = { stroke: 'var(--border, #e0e0e0)' };\nconst GRID_STROKE = 'var(--border, #e0e0e0)';\nconst TOOLTIP_STYLE = {\n contentStyle: {\n backgroundColor: 'var(--paper-elevated, #fff)',\n border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-sm, 4px)',\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',\n color: 'var(--text-ink, #1e2125)',\n },\n labelStyle: { color: 'var(--text-strong, #1e2125)' },\n};\nconst LEGEND_STYLE = { color: 'var(--text-ink, #1e2125)', fontSize: '12px' };\n\n// Smart label: skip x_label if tick values already contain the label text\nconst shouldShowAxisLabel = (label, tickValues) => {\n if (!label) return false;\n const lower = label.toLowerCase();\n // If most ticks contain the label word, it's redundant\n const matches = tickValues.filter(v => String(v).toLowerCase().includes(lower));\n return matches.length < tickValues.length * 0.5;\n};\n\n// --- Export utilities ---\nconst downloadPng = async (containerEl, title) => {\n const svg = containerEl.querySelector('svg');\n if (!svg) return;\n const clone = svg.cloneNode(true);\n // Ensure dimensions\n const w = svg.clientWidth || 600;\n const h = svg.clientHeight || 300;\n clone.setAttribute('width', w);\n clone.setAttribute('height', h);\n clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg');\n // Inline computed styles for export fidelity\n const styleEl = document.createElement('style');\n styleEl.textContent = `text { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif; }`;\n clone.insertBefore(styleEl, clone.firstChild);\n const xml = new XMLSerializer().serializeToString(clone);\n const blob = new Blob([xml], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const img = new Image();\n img.onload = () => {\n const canvas = document.createElement('canvas');\n const scale = 2; // retina\n canvas.width = w * scale;\n canvas.height = h * scale;\n const ctx = canvas.getContext('2d');\n ctx.fillStyle = '#ffffff';\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.scale(scale, scale);\n ctx.drawImage(img, 0, 0, w, h);\n URL.revokeObjectURL(url);\n const link = document.createElement('a');\n link.download = `${(title || 'chart').replace(/[^a-z0-9]+/gi, '_')}.png`;\n link.href = canvas.toDataURL('image/png');\n link.click();\n };\n img.src = url;\n};\n\nconst copyAsCsv = (series, allXValues) => {\n const header = ['', ...series.map(s => s.name)].join(',');\n const rows = allXValues.map(x => {\n const vals = series.map(s => {\n const match = s.data.find(d => d.x === x);\n return match ? match.y : '';\n });\n return [x, ...vals].join(',');\n });\n const csv = [header, ...rows].join('\\n');\n navigator.clipboard.writeText(csv);\n};\n\nconst ActionBar = ({ onDownload, onCopy, copied }) => (\n <div style={{\n display: 'flex', gap: 6, justifyContent: 'flex-end',\n marginBottom: 8, opacity: 0.7, transition: 'opacity 0.15s',\n }}>\n <button onClick={onCopy} title=\"Copy data as CSV\" style={{\n background: 'none', border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-sm, 4px)', padding: '3px 8px',\n fontSize: 11, color: 'var(--text-muted, #666)', cursor: 'pointer',\n display: 'flex', alignItems: 'center', gap: 4,\n }}>\n {copied ? '✓ Copied' : '📋 CSV'}\n </button>\n <button onClick={onDownload} title=\"Download as PNG\" style={{\n background: 'none', border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-sm, 4px)', padding: '3px 8px',\n fontSize: 11, color: 'var(--text-muted, #666)', cursor: 'pointer',\n display: 'flex', alignItems: 'center', gap: 4,\n }}>\n 📥 PNG\n </button>\n </div>\n);\n\nconst ChartRenderer = ({ chartType, title, xLabel, yLabel, series }) => {\n const chartRef = useRef(null);\n const [copied, setCopied] = React.useState(false);\n\n if (!series || series.length === 0) return null;\n\n // Transform: merge all series into [{x, series1: val, series2: val}, ...]\n const allXValues = [...new Set(series.flatMap(s => s.data.map(d => d.x)))];\n const chartData = allXValues.map(x => {\n const point = { x };\n series.forEach(s => {\n const match = s.data.find(d => d.x === x);\n point[s.name] = match ? match.y : null;\n });\n return point;\n });\n\n const seriesNames = series.map(s => s.name);\n const isSingleSeries = seriesNames.length === 1;\n\n // Determine if axis labels are redundant\n const showXLabel = shouldShowAxisLabel(xLabel, allXValues);\n const bottomMargin = showXLabel ? 20 : 5;\n\n // Check if x-axis labels are long (rotate them)\n const maxTickLen = Math.max(...allXValues.map(v => String(v).length));\n const rotateXTicks = maxTickLen > 12 || allXValues.length > 8;\n\n const containerStyle = {\n background: 'var(--paper-elevated, #fff)',\n border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-md, 8px)',\n padding: '16px',\n marginBottom: '16px',\n };\n\n const titleStyle = {\n color: 'var(--text-strong, #1e2125)',\n fontSize: '14px',\n fontWeight: '600',\n marginBottom: '12px',\n };\n\n const xAxisProps = {\n dataKey: 'x',\n tick: rotateXTicks\n ? { fill: 'var(--text-muted, #666)', fontSize: 11, angle: -35, textAnchor: 'end' }\n : AXIS_TICK,\n axisLine: AXIS_LINE,\n tickLine: AXIS_LINE,\n ...(showXLabel ? {\n label: { value: xLabel, position: 'insideBottom', offset: -10, style: { textAnchor: 'middle', fill: 'var(--text-muted, #666)' } }\n } : {}),\n };\n\n const yAxisProps = {\n tick: AXIS_TICK,\n axisLine: AXIS_LINE,\n tickLine: AXIS_LINE,\n ...(yLabel ? {\n label: { value: yLabel, angle: -90, position: 'insideLeft', style: { textAnchor: 'middle', fill: 'var(--text-muted, #666)' } }\n } : {}),\n };\n\n const renderChart = () => {\n switch (chartType) {\n case 'bar':\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <BarChart data={chartData} margin={{ top: 5, right: 30, left: 20, bottom: rotateXTicks ? 40 : bottomMargin }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis {...xAxisProps} />\n <YAxis {...yAxisProps} />\n <Tooltip {...TOOLTIP_STYLE} />\n {!isSingleSeries && <Legend wrapperStyle={LEGEND_STYLE} />}\n {seriesNames.map((name, i) => (\n <Bar key={name} dataKey={name} fill={COLORS[i % COLORS.length]} radius={[2, 2, 0, 0]}>\n {isSingleSeries && chartData.map((_, idx) => (\n <Cell key={idx} fill={COLORS[idx % COLORS.length]} />\n ))}\n </Bar>\n ))}\n </BarChart>\n </ResponsiveContainer>\n );\n\n case 'horizontal_bar': {\n // Horizontal bar: swap X/Y, use YAxis for categories\n return (\n <ResponsiveContainer width=\"100%\" height={Math.max(300, chartData.length * 40)}>\n <BarChart data={chartData} layout=\"vertical\" margin={{ top: 5, right: 30, left: 100, bottom: 5 }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis type=\"number\" tick={AXIS_TICK} axisLine={AXIS_LINE} tickLine={AXIS_LINE}\n {...(yLabel ? { label: { value: yLabel, position: 'insideBottom', offset: -5, style: { textAnchor: 'middle', fill: 'var(--text-muted, #666)' } } } : {})}\n />\n <YAxis type=\"category\" dataKey=\"x\" tick={{ fill: 'var(--text-muted, #666)', fontSize: 11 }} width={90} axisLine={AXIS_LINE} tickLine={AXIS_LINE} />\n <Tooltip {...TOOLTIP_STYLE} />\n {!isSingleSeries && <Legend wrapperStyle={LEGEND_STYLE} />}\n {seriesNames.map((name, i) => (\n <Bar key={name} dataKey={name} fill={COLORS[i % COLORS.length]} radius={[0, 2, 2, 0]}>\n {isSingleSeries && chartData.map((_, idx) => (\n <Cell key={idx} fill={COLORS[idx % COLORS.length]} />\n ))}\n </Bar>\n ))}\n </BarChart>\n </ResponsiveContainer>\n );\n }\n\n case 'line':\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <LineChart data={chartData} margin={{ top: 5, right: 30, left: 20, bottom: rotateXTicks ? 40 : bottomMargin }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis {...xAxisProps} />\n <YAxis {...yAxisProps} />\n <Tooltip {...TOOLTIP_STYLE} />\n <Legend wrapperStyle={LEGEND_STYLE} />\n {seriesNames.map((name, i) => (\n <Line key={name} type=\"monotone\" dataKey={name}\n stroke={COLORS[i % COLORS.length]} strokeWidth={2}\n dot={{ r: 4, fill: COLORS[i % COLORS.length] }}\n activeDot={{ r: 6, fill: COLORS[i % COLORS.length] }}\n />\n ))}\n </LineChart>\n </ResponsiveContainer>\n );\n\n case 'area':\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <AreaChart data={chartData} margin={{ top: 5, right: 30, left: 20, bottom: rotateXTicks ? 40 : bottomMargin }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis {...xAxisProps} />\n <YAxis {...yAxisProps} />\n <Tooltip {...TOOLTIP_STYLE} />\n <Legend wrapperStyle={LEGEND_STYLE} />\n {seriesNames.map((name, i) => (\n <Area key={name} type=\"monotone\" dataKey={name}\n stroke={COLORS[i % COLORS.length]} strokeWidth={2}\n fill={COLORS[i % COLORS.length]} fillOpacity={0.15}\n />\n ))}\n </AreaChart>\n </ResponsiveContainer>\n );\n\n case 'pie': {\n // Pie uses first series only\n const pieData = series[0].data.map((d, i) => ({\n name: d.x,\n value: d.y,\n fill: COLORS[i % COLORS.length],\n }));\n const RADIAN = Math.PI / 180;\n const renderLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, percent, name }) => {\n const radius = outerRadius + 20;\n const x = cx + radius * Math.cos(-midAngle * RADIAN);\n const y = cy + radius * Math.sin(-midAngle * RADIAN);\n if (percent < 0.04) return null;\n return (\n <text x={x} y={y} fill=\"var(--text-ink, #1e2125)\" fontSize={11}\n textAnchor={x > cx ? 'start' : 'end'} dominantBaseline=\"central\">\n {name} ({(percent * 100).toFixed(0)}%)\n </text>\n );\n };\n return (\n <ResponsiveContainer width=\"100%\" height={320}>\n <PieChart>\n <Pie data={pieData} cx=\"50%\" cy=\"50%\" outerRadius={100}\n dataKey=\"value\" label={renderLabel} labelLine={{ stroke: 'var(--text-muted, #666)' }}>\n {pieData.map((entry, i) => (\n <Cell key={i} fill={entry.fill} />\n ))}\n </Pie>\n <Tooltip {...TOOLTIP_STYLE} />\n </PieChart>\n </ResponsiveContainer>\n );\n }\n\n case 'metric': {\n const s = series[0];\n const current = s.data[0];\n const previous = s.data.length > 1 ? s.data[1] : null;\n const value = current.y;\n const unit = current.x || '';\n const hasTrend = previous !== null;\n const change = hasTrend ? value - previous.y : 0;\n const pctChange = hasTrend && previous.y !== 0 ? ((change / Math.abs(previous.y)) * 100) : 0;\n const isPositive = change > 0;\n const isNegative = change < 0;\n const trendColor = isPositive ? '#7BA89D' : isNegative ? '#D17B6B' : 'var(--text-muted, #666)';\n const trendArrow = isPositive ? '↑' : isNegative ? '↓' : '→';\n\n // Format large numbers nicely\n const fmt = (n) => {\n if (Number.isInteger(n) && Math.abs(n) >= 1000) return n.toLocaleString();\n if (typeof n === 'number') return n % 1 === 0 ? n.toString() : n.toFixed(n < 10 ? 2 : 1);\n return String(n);\n };\n\n return (\n <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, padding: '8px 0' }}>\n <div style={{\n fontSize: '36px', fontWeight: 700, lineHeight: 1,\n color: 'var(--text-strong, #1e2125)',\n fontVariantNumeric: 'tabular-nums',\n }}>\n {fmt(value)}\n </div>\n {unit && (\n <div style={{ fontSize: '14px', color: 'var(--text-muted, #666)', fontWeight: 500 }}>\n {unit}\n </div>\n )}\n {hasTrend && (\n <div style={{\n display: 'flex', alignItems: 'center', gap: 4,\n fontSize: '13px', fontWeight: 600, color: trendColor,\n background: isPositive ? 'rgba(123,168,157,0.12)' : isNegative ? 'rgba(209,123,107,0.12)' : 'rgba(128,128,128,0.08)',\n padding: '3px 8px', borderRadius: 'var(--radius-sm, 4px)',\n }}>\n <span>{trendArrow}</span>\n <span>{fmt(Math.abs(change))} ({Math.abs(pctChange).toFixed(1)}%)</span>\n </div>\n )}\n {hasTrend && (\n <div style={{ fontSize: '11px', color: 'var(--text-faint, #999)' }}>\n vs {previous.x || 'previous'}\n </div>\n )}\n </div>\n );\n }\n\n default:\n return <div style={{ color: 'var(--text-muted)', fontSize: 12, padding: 8 }}>Unsupported chart type: {chartType}</div>;\n }\n };\n\n const handleDownload = useCallback(() => {\n if (chartRef.current) downloadPng(chartRef.current, title);\n }, [title]);\n\n const handleCopy = useCallback(() => {\n copyAsCsv(series, allXValues);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }, [series, allXValues]);\n\n const showActions = chartType !== 'metric';\n\n return (\n <div style={containerStyle}>\n {title && <div style={titleStyle}>{title}</div>}\n {showActions && <ActionBar onDownload={handleDownload} onCopy={handleCopy} copied={copied} />}\n <div ref={chartRef}>\n {renderChart()}\n </div>\n </div>\n );\n};\n\nexport default ChartRenderer;\n"],"names":["COLORS","AXIS_TICK","AXIS_LINE","GRID_STROKE","TOOLTIP_STYLE","LEGEND_STYLE","shouldShowAxisLabel","label","tickValues","lower","v","downloadPng","containerEl","title","svg","clone","w","styleEl","xml","blob","url","img","canvas","scale","ctx","link","copyAsCsv","series","allXValues","header","s","rows","x","vals","match","d","csv","ActionBar","onDownload","onCopy","copied","jsxs","jsx","ChartRenderer","chartType","xLabel","yLabel","chartRef","useRef","setCopied","React","chartData","point","seriesNames","isSingleSeries","showXLabel","bottomMargin","rotateXTicks","containerStyle","titleStyle","xAxisProps","yAxisProps","renderChart","ResponsiveContainer","BarChart","CartesianGrid","XAxis","YAxis","Tooltip","Legend","name","i","Bar","_","idx","Cell","LineChart","Line","AreaChart","Area","pieData","RADIAN","PieChart","Pie","cx","cy","midAngle","innerRadius","outerRadius","percent","radius","y","entry","current","previous","value","unit","hasTrend","change","pctChange","isPositive","isNegative","trendColor","trendArrow","fmt","n","handleDownload","useCallback","handleCopy"],"mappings":";;;AASA,MAAMA,IAAS;AAAA,EACb;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF,GAGMC,IAAY,EAAE,MAAM,2BAA2B,UAAU,GAAG,GAC5DC,IAAY,EAAE,QAAQ,4BACtBC,IAAc,0BACdC,IAAgB;AAAA,EACpB,cAAc;AAAA,IACZ,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,WAAW;AAAA,IACX,OAAO;AAAA,EACT;AAAA,EACA,YAAY,EAAE,OAAO,8BAA8B;AACrD,GACMC,IAAe,EAAE,OAAO,4BAA4B,UAAU,OAAO,GAGrEC,KAAsB,CAACC,GAAOC,MAAe;AACjD,MAAI,CAACD;AAAc,WAAA;AACb,QAAAE,IAAQF,EAAM;AAGb,SADSC,EAAW,OAAO,CAAKE,MAAA,OAAOA,CAAC,EAAE,YAAY,EAAE,SAASD,CAAK,CAAC,EAC/D,SAASD,EAAW,SAAS;AAC9C,GAGMG,KAAc,OAAOC,GAAaC,MAAU;AAC1C,QAAAC,IAAMF,EAAY,cAAc,KAAK;AAC3C,MAAI,CAACE;AAAK;AACJ,QAAAC,IAAQD,EAAI,UAAU,EAAI,GAE1BE,IAAIF,EAAI,eAAe,KACvB,IAAIA,EAAI,gBAAgB;AACxB,EAAAC,EAAA,aAAa,SAASC,CAAC,GACvBD,EAAA,aAAa,UAAU,CAAC,GACxBA,EAAA,aAAa,SAAS,4BAA4B;AAElD,QAAAE,IAAU,SAAS,cAAc,OAAO;AAC9C,EAAAA,EAAQ,cAAc,4FAChBF,EAAA,aAAaE,GAASF,EAAM,UAAU;AAC5C,QAAMG,IAAM,IAAI,cAAc,EAAE,kBAAkBH,CAAK,GACjDI,IAAO,IAAI,KAAK,CAACD,CAAG,GAAG,EAAE,MAAM,8BAAA,CAA+B,GAC9DE,IAAM,IAAI,gBAAgBD,CAAI,GAC9BE,IAAM,IAAI;AAChB,EAAAA,EAAI,SAAS,MAAM;AACX,UAAAC,IAAS,SAAS,cAAc,QAAQ,GACxCC,IAAQ;AACd,IAAAD,EAAO,QAAQN,IAAIO,GACnBD,EAAO,SAAS,IAAIC;AACd,UAAAC,IAAMF,EAAO,WAAW,IAAI;AAClC,IAAAE,EAAI,YAAY,WAChBA,EAAI,SAAS,GAAG,GAAGF,EAAO,OAAOA,EAAO,MAAM,GAC1CE,EAAA,MAAMD,GAAOA,CAAK,GACtBC,EAAI,UAAUH,GAAK,GAAG,GAAGL,GAAG,CAAC,GAC7B,IAAI,gBAAgBI,CAAG;AACjB,UAAAK,IAAO,SAAS,cAAc,GAAG;AACvC,IAAAA,EAAK,WAAW,IAAIZ,KAAS,SAAS,QAAQ,gBAAgB,GAAG,CAAC,QAC7DY,EAAA,OAAOH,EAAO,UAAU,WAAW,GACxCG,EAAK,MAAM;AAAA,EAAA,GAEbJ,EAAI,MAAMD;AACZ,GAEMM,KAAY,CAACC,GAAQC,MAAe;AACxC,QAAMC,IAAS,CAAC,IAAI,GAAGF,EAAO,IAAI,CAAKG,MAAAA,EAAE,IAAI,CAAC,EAAE,KAAK,GAAG,GAClDC,IAAOH,EAAW,IAAI,CAAKI,MAAA;AACzB,UAAAC,IAAON,EAAO,IAAI,CAAKG,MAAA;AAC3B,YAAMI,IAAQJ,EAAE,KAAK,KAAK,CAAKK,MAAAA,EAAE,MAAMH,CAAC;AACjC,aAAAE,IAAQA,EAAM,IAAI;AAAA,IAAA,CAC1B;AACD,WAAO,CAACF,GAAG,GAAGC,CAAI,EAAE,KAAK,GAAG;AAAA,EAAA,CAC7B,GACKG,IAAM,CAACP,GAAQ,GAAGE,CAAI,EAAE,KAAK;AAAA,CAAI;AAC7B,YAAA,UAAU,UAAUK,CAAG;AACnC,GAEMC,KAAY,CAAC,EAAE,YAAAC,GAAY,QAAAC,GAAQ,QAAAC,EAAO,MAC7C,gBAAAC,EAAA,OAAA,EAAI,OAAO;AAAA,EACV,SAAS;AAAA,EAAQ,KAAK;AAAA,EAAG,gBAAgB;AAAA,EACzC,cAAc;AAAA,EAAG,SAAS;AAAA,EAAK,YAAY;AAC7C,GACE,UAAA;AAAA,EAAA,gBAAAC,EAAC,UAAO,EAAA,SAASH,GAAQ,OAAM,oBAAmB,OAAO;AAAA,IACvD,YAAY;AAAA,IAAQ,QAAQ;AAAA,IAC5B,cAAc;AAAA,IAAyB,SAAS;AAAA,IAChD,UAAU;AAAA,IAAI,OAAO;AAAA,IAA2B,QAAQ;AAAA,IACxD,SAAS;AAAA,IAAQ,YAAY;AAAA,IAAU,KAAK;AAAA,EAC9C,GACG,UAASC,IAAA,aAAa,SACzB,CAAA;AAAA,oBACC,UAAO,EAAA,SAASF,GAAY,OAAM,mBAAkB,OAAO;AAAA,IAC1D,YAAY;AAAA,IAAQ,QAAQ;AAAA,IAC5B,cAAc;AAAA,IAAyB,SAAS;AAAA,IAChD,UAAU;AAAA,IAAI,OAAO;AAAA,IAA2B,QAAQ;AAAA,IACxD,SAAS;AAAA,IAAQ,YAAY;AAAA,IAAU,KAAK;AAAA,EAAA,GAC3C,UAEH,UAAA;AAAA,EACF,CAAA,GAGIK,KAAgB,CAAC,EAAE,WAAAC,GAAW,OAAA/B,GAAO,QAAAgC,GAAQ,QAAAC,GAAQ,QAAAnB,QAAa;AAChE,QAAAoB,IAAWC,GAAO,IAAI,GACtB,CAACR,GAAQS,CAAS,IAAIC,GAAM,SAAS,EAAK;AAE5C,MAAA,CAACvB,KAAUA,EAAO,WAAW;AAAU,WAAA;AAG3C,QAAMC,IAAa,CAAC,GAAG,IAAI,IAAID,EAAO,QAAQ,CAAAG,MAAKA,EAAE,KAAK,IAAI,CAAKK,MAAAA,EAAE,CAAC,CAAC,CAAC,CAAC,GACnEgB,IAAYvB,EAAW,IAAI,CAAKI,MAAA;AAC9B,UAAAoB,IAAQ,EAAE,GAAApB;AAChB,WAAAL,EAAO,QAAQ,CAAKG,MAAA;AAClB,YAAMI,IAAQJ,EAAE,KAAK,KAAK,CAAKK,MAAAA,EAAE,MAAMH,CAAC;AACxC,MAAAoB,EAAMtB,EAAE,IAAI,IAAII,IAAQA,EAAM,IAAI;AAAA,IAAA,CACnC,GACMkB;AAAA,EAAA,CACR,GAEKC,IAAc1B,EAAO,IAAI,CAAAG,MAAKA,EAAE,IAAI,GACpCwB,IAAiBD,EAAY,WAAW,GAGxCE,IAAajD,GAAoBuC,GAAQjB,CAAU,GACnD4B,IAAeD,IAAa,KAAK,GAIjCE,IADa,KAAK,IAAI,GAAG7B,EAAW,IAAI,CAAAlB,MAAK,OAAOA,CAAC,EAAE,MAAM,CAAC,IAClC,MAAMkB,EAAW,SAAS,GAEtD8B,IAAiB;AAAA,IACrB,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,SAAS;AAAA,IACT,cAAc;AAAA,EAAA,GAGVC,IAAa;AAAA,IACjB,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA,EAAA,GAGVC,IAAa;AAAA,IACjB,SAAS;AAAA,IACT,MAAMH,IACF,EAAE,MAAM,2BAA2B,UAAU,IAAI,OAAO,KAAK,YAAY,MACzE,IAAAxD;AAAA,IACJ,UAAUC;AAAA,IACV,UAAUA;AAAA,IACV,GAAIqD,IAAa;AAAA,MACf,OAAO,EAAE,OAAOV,GAAQ,UAAU,gBAAgB,QAAQ,KAAK,OAAO,EAAE,YAAY,UAAU,MAAM,4BAA4B;AAAA,IAAA,IAC9H,CAAC;AAAA,EAAA,GAGDgB,IAAa;AAAA,IACjB,MAAM5D;AAAA,IACN,UAAUC;AAAA,IACV,UAAUA;AAAA,IACV,GAAI4C,IAAS;AAAA,MACX,OAAO,EAAE,OAAOA,GAAQ,OAAO,KAAK,UAAU,cAAc,OAAO,EAAE,YAAY,UAAU,MAAM,4BAA4B;AAAA,IAAA,IAC3H,CAAC;AAAA,EAAA,GAGDgB,IAAc,MAAM;AACxB,YAAQlB,GAAW;AAAA,MACjB,KAAK;AAED,eAAA,gBAAAF,EAACqB,KAAoB,OAAM,QAAO,QAAQ,KACxC,UAAA,gBAAAtB,EAACuB,GAAS,EAAA,MAAMb,GAAW,QAAQ,EAAE,KAAK,GAAG,OAAO,IAAI,MAAM,IAAI,QAAQM,IAAe,KAAKD,EAAA,GAC5F,UAAA;AAAA,UAAA,gBAAAd,EAACuB,GAAc,EAAA,iBAAgB,OAAM,QAAQ9D,GAAa;AAAA,UAC1D,gBAAAuC,EAACwB,GAAO,EAAA,GAAGN,GAAY;AAAA,UACvB,gBAAAlB,EAACyB,GAAO,EAAA,GAAGN,GAAY;AAAA,UACvB,gBAAAnB,EAAC0B,GAAS,EAAA,GAAGhE,GAAe;AAAA,UAC3B,CAACkD,KAAmB,gBAAAZ,EAAA2B,GAAA,EAAO,cAAchE,EAAc,CAAA;AAAA,UACvDgD,EAAY,IAAI,CAACiB,GAAMC,MACtB,gBAAA7B,EAAC8B,KAAe,SAASF,GAAM,MAAMtE,EAAOuE,IAAIvE,EAAO,MAAM,GAAG,QAAQ,CAAC,GAAG,GAAG,GAAG,CAAC,GAChF,eAAkBmD,EAAU,IAAI,CAACsB,GAAGC,wBAClCC,GAAe,EAAA,MAAM3E,EAAO0E,IAAM1E,EAAO,MAAM,EAAA,GAArC0E,CAAwC,CACpD,KAHOJ,CAIV,CACD;AAAA,QAAA,EACH,CAAA,EACF,CAAA;AAAA,MAGJ,KAAK;AAEH,eACG,gBAAA5B,EAAAqB,GAAA,EAAoB,OAAM,QAAO,QAAQ,KAAK,IAAI,KAAKZ,EAAU,SAAS,EAAE,GAC3E,UAAC,gBAAAV,EAAAuB,GAAA,EAAS,MAAMb,GAAW,QAAO,YAAW,QAAQ,EAAE,KAAK,GAAG,OAAO,IAAI,MAAM,KAAK,QAAQ,EAC3F,GAAA,UAAA;AAAA,UAAA,gBAAAT,EAACuB,GAAc,EAAA,iBAAgB,OAAM,QAAQ9D,GAAa;AAAA,UAC1D,gBAAAuC;AAAA,YAACwB;AAAA,YAAA;AAAA,cAAM,MAAK;AAAA,cAAS,MAAMjE;AAAA,cAAW,UAAUC;AAAA,cAAW,UAAUA;AAAA,cAClE,GAAI4C,IAAS,EAAE,OAAO,EAAE,OAAOA,GAAQ,UAAU,gBAAgB,QAAQ,IAAI,OAAO,EAAE,YAAY,UAAU,MAAM,4BAA4B,EAAA,IAAM,CAAC;AAAA,YAAA;AAAA,UACxJ;AAAA,4BACCqB,GAAM,EAAA,MAAK,YAAW,SAAQ,KAAI,MAAM,EAAE,MAAM,2BAA2B,UAAU,GAAM,GAAA,OAAO,IAAI,UAAUjE,GAAW,UAAUA,GAAW;AAAA,UACjJ,gBAAAwC,EAAC0B,GAAS,EAAA,GAAGhE,GAAe;AAAA,UAC3B,CAACkD,KAAmB,gBAAAZ,EAAA2B,GAAA,EAAO,cAAchE,EAAc,CAAA;AAAA,UACvDgD,EAAY,IAAI,CAACiB,GAAMC,MACtB,gBAAA7B,EAAC8B,KAAe,SAASF,GAAM,MAAMtE,EAAOuE,IAAIvE,EAAO,MAAM,GAAG,QAAQ,CAAC,GAAG,GAAG,GAAG,CAAC,GAChF,eAAkBmD,EAAU,IAAI,CAACsB,GAAGC,wBAClCC,GAAe,EAAA,MAAM3E,EAAO0E,IAAM1E,EAAO,MAAM,EAAA,GAArC0E,CAAwC,CACpD,KAHOJ,CAIV,CACD;AAAA,QAAA,EACH,CAAA,EACF,CAAA;AAAA,MAIJ,KAAK;AAED,eAAA,gBAAA5B,EAACqB,KAAoB,OAAM,QAAO,QAAQ,KACxC,UAAA,gBAAAtB,EAACmC,IAAU,EAAA,MAAMzB,GAAW,QAAQ,EAAE,KAAK,GAAG,OAAO,IAAI,MAAM,IAAI,QAAQM,IAAe,KAAKD,EAAA,GAC7F,UAAA;AAAA,UAAA,gBAAAd,EAACuB,GAAc,EAAA,iBAAgB,OAAM,QAAQ9D,GAAa;AAAA,UAC1D,gBAAAuC,EAACwB,GAAO,EAAA,GAAGN,GAAY;AAAA,UACvB,gBAAAlB,EAACyB,GAAO,EAAA,GAAGN,GAAY;AAAA,UACvB,gBAAAnB,EAAC0B,GAAS,EAAA,GAAGhE,GAAe;AAAA,UAC5B,gBAAAsC,EAAC2B,GAAO,EAAA,cAAchE,EAAc,CAAA;AAAA,UACnCgD,EAAY,IAAI,CAACiB,GAAMC,MACtB,gBAAA7B;AAAA,YAACmC;AAAA,YAAA;AAAA,cAAgB,MAAK;AAAA,cAAW,SAASP;AAAA,cACxC,QAAQtE,EAAOuE,IAAIvE,EAAO,MAAM;AAAA,cAAG,aAAa;AAAA,cAChD,KAAK,EAAE,GAAG,GAAG,MAAMA,EAAOuE,IAAIvE,EAAO,MAAM,EAAE;AAAA,cAC7C,WAAW,EAAE,GAAG,GAAG,MAAMA,EAAOuE,IAAIvE,EAAO,MAAM,EAAE;AAAA,YAAA;AAAA,YAH1CsE;AAAA,UAAA,CAKZ;AAAA,QAAA,EACH,CAAA,EACF,CAAA;AAAA,MAGJ,KAAK;AAED,eAAA,gBAAA5B,EAACqB,KAAoB,OAAM,QAAO,QAAQ,KACxC,UAAA,gBAAAtB,EAACqC,IAAU,EAAA,MAAM3B,GAAW,QAAQ,EAAE,KAAK,GAAG,OAAO,IAAI,MAAM,IAAI,QAAQM,IAAe,KAAKD,EAAA,GAC7F,UAAA;AAAA,UAAA,gBAAAd,EAACuB,GAAc,EAAA,iBAAgB,OAAM,QAAQ9D,GAAa;AAAA,UAC1D,gBAAAuC,EAACwB,GAAO,EAAA,GAAGN,GAAY;AAAA,UACvB,gBAAAlB,EAACyB,GAAO,EAAA,GAAGN,GAAY;AAAA,UACvB,gBAAAnB,EAAC0B,GAAS,EAAA,GAAGhE,GAAe;AAAA,UAC5B,gBAAAsC,EAAC2B,GAAO,EAAA,cAAchE,EAAc,CAAA;AAAA,UACnCgD,EAAY,IAAI,CAACiB,GAAMC,MACtB,gBAAA7B;AAAA,YAACqC;AAAA,YAAA;AAAA,cAAgB,MAAK;AAAA,cAAW,SAAST;AAAA,cACxC,QAAQtE,EAAOuE,IAAIvE,EAAO,MAAM;AAAA,cAAG,aAAa;AAAA,cAChD,MAAMA,EAAOuE,IAAIvE,EAAO,MAAM;AAAA,cAAG,aAAa;AAAA,YAAA;AAAA,YAFrCsE;AAAA,UAAA,CAIZ;AAAA,QAAA,EACH,CAAA,EACF,CAAA;AAAA,MAGJ,KAAK,OAAO;AAEJ,cAAAU,IAAUrD,EAAO,CAAC,EAAE,KAAK,IAAI,CAACQ,GAAGoC,OAAO;AAAA,UAC5C,MAAMpC,EAAE;AAAA,UACR,OAAOA,EAAE;AAAA,UACT,MAAMnC,EAAOuE,IAAIvE,EAAO,MAAM;AAAA,QAC9B,EAAA,GACIiF,IAAS,KAAK,KAAK;AAazB,iCACGlB,GAAoB,EAAA,OAAM,QAAO,QAAQ,KACxC,4BAACmB,IACC,EAAA,UAAA;AAAA,UAAA,gBAAAxC;AAAA,YAACyC;AAAA,YAAA;AAAA,cAAI,MAAMH;AAAA,cAAS,IAAG;AAAA,cAAM,IAAG;AAAA,cAAM,aAAa;AAAA,cACjD,SAAQ;AAAA,cAAQ,OAhBJ,CAAC,EAAE,IAAAI,GAAI,IAAAC,GAAI,UAAAC,GAAU,aAAAC,GAAa,aAAAC,GAAa,SAAAC,GAAS,MAAAnB,QAAW;AACrF,sBAAMoB,IAASF,IAAc,IACvBxD,IAAIoD,IAAKM,IAAS,KAAK,IAAI,CAACJ,IAAWL,CAAM,GAC7CU,IAAIN,IAAKK,IAAS,KAAK,IAAI,CAACJ,IAAWL,CAAM;AACnD,uBAAIQ,IAAU,OAAa,OAEzB,gBAAAhD;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBAAK,GAAAT;AAAA,oBAAM,GAAA2D;AAAA,oBAAM,MAAK;AAAA,oBAA2B,UAAU;AAAA,oBAC1D,YAAY3D,IAAIoD,IAAK,UAAU;AAAA,oBAAO,kBAAiB;AAAA,oBACtD,UAAA;AAAA,sBAAAd;AAAA,sBAAK;AAAA,uBAAImB,IAAU,KAAK,QAAQ,CAAC;AAAA,sBAAE;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACtC;AAAA,cAOwC,WAAW,EAAE,QAAQ,0BAA0B;AAAA,cAClF,UAAAT,EAAQ,IAAI,CAACY,GAAOrB,MAClB,gBAAA7B,EAAAiC,GAAA,EAAa,MAAMiB,EAAM,KAAf,GAAArB,CAAqB,CACjC;AAAA,YAAA;AAAA,UACH;AAAA,UACA,gBAAA7B,EAAC0B,GAAS,EAAA,GAAGhE,GAAe;AAAA,QAAA,EAC9B,CAAA,EACF,CAAA;AAAA,MAEJ;AAAA,MAEA,KAAK,UAAU;AACP,cAAA0B,IAAIH,EAAO,CAAC,GACZkE,IAAU/D,EAAE,KAAK,CAAC,GAClBgE,IAAWhE,EAAE,KAAK,SAAS,IAAIA,EAAE,KAAK,CAAC,IAAI,MAC3CiE,IAAQF,EAAQ,GAChBG,IAAOH,EAAQ,KAAK,IACpBI,IAAWH,MAAa,MACxBI,IAASD,IAAWF,IAAQD,EAAS,IAAI,GACzCK,IAAYF,KAAYH,EAAS,MAAM,IAAMI,IAAS,KAAK,IAAIJ,EAAS,CAAC,IAAK,MAAO,GACrFM,IAAaF,IAAS,GACtBG,IAAaH,IAAS,GACtBI,IAAaF,IAAa,YAAYC,IAAa,YAAY,2BAC/DE,IAAaH,IAAa,MAAMC,IAAa,MAAM,KAGnDG,IAAM,CAACC,MACP,OAAO,UAAUA,CAAC,KAAK,KAAK,IAAIA,CAAC,KAAK,MAAaA,EAAE,mBACrD,OAAOA,KAAM,WAAiBA,IAAI,MAAM,IAAIA,EAAE,SAAa,IAAAA,EAAE,QAAQA,IAAI,KAAK,IAAI,CAAC,IAChF,OAAOA,CAAC;AAGjB,eACG,gBAAAhE,EAAA,OAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,YAAY,KAAK,IAAI,SAAS,QAAA,GACvE,UAAA;AAAA,UAAA,gBAAAC,EAAC,SAAI,OAAO;AAAA,YACV,UAAU;AAAA,YAAQ,YAAY;AAAA,YAAK,YAAY;AAAA,YAC/C,OAAO;AAAA,YACP,oBAAoB;AAAA,UACtB,GACG,UAAI8D,EAAAT,CAAK,GACZ;AAAA,UACCC,KACC,gBAAAtD,EAAC,OAAI,EAAA,OAAO,EAAE,UAAU,QAAQ,OAAO,2BAA2B,YAAY,IAAI,GAC/E,UACHsD,EAAA,CAAA;AAAA,UAEDC,KACE,gBAAAxD,EAAA,OAAA,EAAI,OAAO;AAAA,YACV,SAAS;AAAA,YAAQ,YAAY;AAAA,YAAU,KAAK;AAAA,YAC5C,UAAU;AAAA,YAAQ,YAAY;AAAA,YAAK,OAAO6D;AAAA,YAC1C,YAAYF,IAAa,2BAA2BC,IAAa,2BAA2B;AAAA,YAC5F,SAAS;AAAA,YAAW,cAAc;AAAA,UAElC,GAAA,UAAA;AAAA,YAAA,gBAAA3D,EAAC,UAAM,UAAW6D,EAAA,CAAA;AAAA,8BACjB,QAAM,EAAA,UAAA;AAAA,cAAIC,EAAA,KAAK,IAAIN,CAAM,CAAC;AAAA,cAAE;AAAA,cAAG,KAAK,IAAIC,CAAS,EAAE,QAAQ,CAAC;AAAA,cAAE;AAAA,YAAA,GAAE;AAAA,UAAA,GACnE;AAAA,UAEDF,uBACE,OAAI,EAAA,OAAO,EAAE,UAAU,QAAQ,OAAO,0BAA6B,GAAA,UAAA;AAAA,YAAA;AAAA,YAC9DH,EAAS,KAAK;AAAA,UAAA,GACpB;AAAA,QAEJ,EAAA,CAAA;AAAA,MAEJ;AAAA,MAEA;AACS,eAAA,gBAAArD,EAAC,OAAI,EAAA,OAAO,EAAE,OAAO,qBAAqB,UAAU,IAAI,SAAS,EAAA,GAAK,UAAA;AAAA,UAAA;AAAA,UAAyBG;AAAA,QAAU,EAAA,CAAA;AAAA,IACpH;AAAA,EAAA,GAGI8D,IAAiBC,EAAY,MAAM;AACvC,IAAI5D,EAAS,WAAqBpC,GAAAoC,EAAS,SAASlC,CAAK;AAAA,EAAA,GACxD,CAACA,CAAK,CAAC,GAEJ+F,KAAaD,EAAY,MAAM;AACnC,IAAAjF,GAAUC,GAAQC,CAAU,GAC5BqB,EAAU,EAAI,GACd,WAAW,MAAMA,EAAU,EAAK,GAAG,GAAI;AAAA,EAAA,GACtC,CAACtB,GAAQC,CAAU,CAAC;AAKrB,SAAA,gBAAAa,EAAC,OAAI,EAAA,OAAOiB,GACT,UAAA;AAAA,IAAA7C,KAAU,gBAAA6B,EAAA,OAAA,EAAI,OAAOiB,GAAa,UAAM9C,GAAA;AAAA,IAJzB+B,MAAc,YAKb,gBAAAF,EAAAL,IAAA,EAAU,YAAYqE,GAAgB,QAAQE,IAAY,QAAApE,GAAgB;AAAA,IAC1F,gBAAAE,EAAA,OAAA,EAAI,KAAKK,GACP,eACH;AAAA,EACF,EAAA,CAAA;AAEJ;"}
1
+ {"version":3,"file":"ChartRenderer.es.js","sources":["../src/components/chat/ChartRenderer.jsx"],"sourcesContent":["\"use client\";\nimport React, { useRef, useCallback } from 'react';\nimport {\n ResponsiveContainer, BarChart, Bar, Cell, LineChart, Line,\n XAxis, YAxis, CartesianGrid, Tooltip, Legend,\n PieChart, Pie, AreaChart, Area,\n} from 'recharts';\n\n// Chordia design system rail colors — ordered for max visual distinction\nconst COLORS = [\n '#5E88B0', // rail-discovery / rail-blue\n '#9B7AA8', // rail-purple / rail-tone\n '#C98A5A', // rail-compliance / rail-orange\n '#7BA89D', // rail-signal-upsell (teal-green)\n '#D17B6B', // rail-coral / rail-signal-churn\n '#6B7C93', // rail-slate / rail-outcome\n '#9B8E6F', // rail-olive / rail-signal-satisfaction\n '#8A9BAF', // rail-quality\n '#B8976A', // rail-teal (warm gold)\n '#A8C76B', // green accent (complementary)\n];\n\n// Shared axis/tooltip/legend styling\nconst AXIS_TICK = { fill: 'var(--text-muted, #666)', fontSize: 12 };\nconst AXIS_LINE = { stroke: 'var(--border, #e0e0e0)' };\nconst GRID_STROKE = 'var(--border, #e0e0e0)';\nconst TOOLTIP_STYLE = {\n contentStyle: {\n backgroundColor: 'var(--paper-elevated, #fff)',\n border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-sm, 4px)',\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',\n color: 'var(--text-ink, #1e2125)',\n },\n labelStyle: { color: 'var(--text-strong, #1e2125)' },\n};\nconst LEGEND_STYLE = { color: 'var(--text-ink, #1e2125)', fontSize: '12px' };\n\n// Smart label: skip x_label if tick values already contain the label text\nconst shouldShowAxisLabel = (label, tickValues) => {\n if (!label) return false;\n const lower = label.toLowerCase();\n // If most ticks contain the label word, it's redundant\n const matches = tickValues.filter(v => String(v).toLowerCase().includes(lower));\n return matches.length < tickValues.length * 0.5;\n};\n\n// --- Export utilities ---\nconst downloadPng = async (containerEl, title) => {\n const svg = containerEl.querySelector('svg');\n if (!svg) return;\n const clone = svg.cloneNode(true);\n // Ensure dimensions\n const w = svg.clientWidth || 600;\n const h = svg.clientHeight || 300;\n clone.setAttribute('width', w);\n clone.setAttribute('height', h);\n clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg');\n // Inline computed styles for export fidelity\n const styleEl = document.createElement('style');\n styleEl.textContent = `text { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif; }`;\n clone.insertBefore(styleEl, clone.firstChild);\n const xml = new XMLSerializer().serializeToString(clone);\n const blob = new Blob([xml], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const img = new Image();\n img.onload = () => {\n const canvas = document.createElement('canvas');\n const scale = 2; // retina\n canvas.width = w * scale;\n canvas.height = h * scale;\n const ctx = canvas.getContext('2d');\n ctx.fillStyle = '#ffffff';\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.scale(scale, scale);\n ctx.drawImage(img, 0, 0, w, h);\n URL.revokeObjectURL(url);\n const link = document.createElement('a');\n link.download = `${(title || 'chart').replace(/[^a-z0-9]+/gi, '_')}.png`;\n link.href = canvas.toDataURL('image/png');\n link.click();\n };\n img.src = url;\n};\n\nconst copyAsCsv = (series, allXValues) => {\n const header = ['', ...series.map(s => s.name)].join(',');\n const rows = allXValues.map(x => {\n const vals = series.map(s => {\n const match = s.data.find(d => d.x === x);\n return match ? match.y : '';\n });\n return [x, ...vals].join(',');\n });\n const csv = [header, ...rows].join('\\n');\n navigator.clipboard.writeText(csv);\n};\n\nconst ActionBar = ({ onDownload, onCopy, copied }) => (\n <div style={{\n display: 'flex', gap: 6, justifyContent: 'flex-end',\n marginBottom: 8, opacity: 0.7, transition: 'opacity 0.15s',\n }}>\n <button onClick={onCopy} title=\"Copy data as CSV\" style={{\n background: 'none', border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-sm, 4px)', padding: '3px 8px',\n fontSize: 11, color: 'var(--text-muted, #666)', cursor: 'pointer',\n display: 'flex', alignItems: 'center', gap: 4,\n }}>\n {copied ? '✓ Copied' : '📋 CSV'}\n </button>\n <button onClick={onDownload} title=\"Download as PNG\" style={{\n background: 'none', border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-sm, 4px)', padding: '3px 8px',\n fontSize: 11, color: 'var(--text-muted, #666)', cursor: 'pointer',\n display: 'flex', alignItems: 'center', gap: 4,\n }}>\n 📥 PNG\n </button>\n </div>\n);\n\nconst ChartRenderer = ({ chartType, title, xLabel, yLabel, series }) => {\n const chartRef = useRef(null);\n const [copied, setCopied] = React.useState(false);\n\n if (!series || series.length === 0) return null;\n\n // Transform: merge all series into [{x, series1: val, series2: val}, ...]\n const allXValues = [...new Set(series.flatMap(s => s.data.map(d => d.x)))];\n const chartData = allXValues.map(x => {\n const point = { x };\n series.forEach(s => {\n const match = s.data.find(d => d.x === x);\n point[s.name] = match ? match.y : null;\n });\n return point;\n });\n\n const seriesNames = series.map(s => s.name);\n const isSingleSeries = seriesNames.length === 1;\n\n // Determine if axis labels are redundant\n const showXLabel = shouldShowAxisLabel(xLabel, allXValues);\n const bottomMargin = showXLabel ? 20 : 5;\n\n // Check if x-axis labels are long (rotate them)\n const maxTickLen = Math.max(...allXValues.map(v => String(v).length));\n const rotateXTicks = maxTickLen > 12 || allXValues.length > 8;\n\n const containerStyle = {\n background: 'var(--paper-elevated, #fff)',\n border: '1px solid var(--border, #e0e0e0)',\n borderRadius: 'var(--radius-md, 8px)',\n padding: '16px',\n marginBottom: '16px',\n };\n\n const titleStyle = {\n color: 'var(--text-strong, #1e2125)',\n fontSize: '14px',\n fontWeight: '600',\n marginBottom: '12px',\n };\n\n const xAxisProps = {\n dataKey: 'x',\n tick: rotateXTicks\n ? { fill: 'var(--text-muted, #666)', fontSize: 11, angle: -35, textAnchor: 'end' }\n : AXIS_TICK,\n axisLine: AXIS_LINE,\n tickLine: AXIS_LINE,\n ...(showXLabel ? {\n label: { value: xLabel, position: 'insideBottom', offset: -10, style: { textAnchor: 'middle', fill: 'var(--text-muted, #666)' } }\n } : {}),\n };\n\n const yAxisProps = {\n tick: AXIS_TICK,\n axisLine: AXIS_LINE,\n tickLine: AXIS_LINE,\n ...(yLabel ? {\n label: { value: yLabel, angle: -90, position: 'insideLeft', style: { textAnchor: 'middle', fill: 'var(--text-muted, #666)' } }\n } : {}),\n };\n\n const renderChart = () => {\n switch (chartType) {\n case 'bar':\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <BarChart data={chartData} margin={{ top: 5, right: 30, left: 20, bottom: rotateXTicks ? 40 : bottomMargin }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis {...xAxisProps} />\n <YAxis {...yAxisProps} />\n <Tooltip {...TOOLTIP_STYLE} />\n {!isSingleSeries && <Legend wrapperStyle={LEGEND_STYLE} />}\n {seriesNames.map((name, i) => (\n <Bar key={name} dataKey={name} fill={COLORS[i % COLORS.length]} radius={[2, 2, 0, 0]} isAnimationActive={false}>\n {isSingleSeries && chartData.map((_, idx) => (\n <Cell key={idx} fill={COLORS[idx % COLORS.length]} />\n ))}\n </Bar>\n ))}\n </BarChart>\n </ResponsiveContainer>\n );\n\n case 'horizontal_bar': {\n // Horizontal bar: swap X/Y, use YAxis for categories\n return (\n <ResponsiveContainer width=\"100%\" height={Math.max(300, chartData.length * 40)}>\n <BarChart data={chartData} layout=\"vertical\" margin={{ top: 5, right: 30, left: 100, bottom: 5 }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis type=\"number\" tick={AXIS_TICK} axisLine={AXIS_LINE} tickLine={AXIS_LINE}\n {...(yLabel ? { label: { value: yLabel, position: 'insideBottom', offset: -5, style: { textAnchor: 'middle', fill: 'var(--text-muted, #666)' } } } : {})}\n />\n <YAxis type=\"category\" dataKey=\"x\" tick={{ fill: 'var(--text-muted, #666)', fontSize: 11 }} width={90} axisLine={AXIS_LINE} tickLine={AXIS_LINE} />\n <Tooltip {...TOOLTIP_STYLE} />\n {!isSingleSeries && <Legend wrapperStyle={LEGEND_STYLE} />}\n {seriesNames.map((name, i) => (\n <Bar key={name} dataKey={name} fill={COLORS[i % COLORS.length]} radius={[0, 2, 2, 0]} isAnimationActive={false}>\n {isSingleSeries && chartData.map((_, idx) => (\n <Cell key={idx} fill={COLORS[idx % COLORS.length]} />\n ))}\n </Bar>\n ))}\n </BarChart>\n </ResponsiveContainer>\n );\n }\n\n case 'line':\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <LineChart data={chartData} margin={{ top: 5, right: 30, left: 20, bottom: rotateXTicks ? 40 : bottomMargin }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis {...xAxisProps} />\n <YAxis {...yAxisProps} />\n <Tooltip {...TOOLTIP_STYLE} />\n <Legend wrapperStyle={LEGEND_STYLE} />\n {seriesNames.map((name, i) => (\n <Line key={name} type=\"monotone\" dataKey={name}\n stroke={COLORS[i % COLORS.length]} strokeWidth={2}\n dot={{ r: 4, fill: COLORS[i % COLORS.length] }}\n activeDot={{ r: 6, fill: COLORS[i % COLORS.length] }}\n isAnimationActive={false}\n />\n ))}\n </LineChart>\n </ResponsiveContainer>\n );\n\n case 'area':\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <AreaChart data={chartData} margin={{ top: 5, right: 30, left: 20, bottom: rotateXTicks ? 40 : bottomMargin }}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis {...xAxisProps} />\n <YAxis {...yAxisProps} />\n <Tooltip {...TOOLTIP_STYLE} />\n <Legend wrapperStyle={LEGEND_STYLE} />\n {seriesNames.map((name, i) => (\n <Area key={name} type=\"monotone\" dataKey={name}\n stroke={COLORS[i % COLORS.length]} strokeWidth={2}\n fill={COLORS[i % COLORS.length]} fillOpacity={0.15}\n isAnimationActive={false}\n />\n ))}\n </AreaChart>\n </ResponsiveContainer>\n );\n\n case 'pie': {\n // Pie uses first series only\n const pieData = series[0].data.map((d, i) => ({\n name: d.x,\n value: d.y,\n fill: COLORS[i % COLORS.length],\n }));\n const RADIAN = Math.PI / 180;\n const renderLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, percent, name }) => {\n const radius = outerRadius + 20;\n const x = cx + radius * Math.cos(-midAngle * RADIAN);\n const y = cy + radius * Math.sin(-midAngle * RADIAN);\n if (percent < 0.04) return null;\n return (\n <text x={x} y={y} fill=\"var(--text-ink, #1e2125)\" fontSize={11}\n textAnchor={x > cx ? 'start' : 'end'} dominantBaseline=\"central\">\n {name} ({(percent * 100).toFixed(0)}%)\n </text>\n );\n };\n return (\n <ResponsiveContainer width=\"100%\" height={320}>\n <PieChart>\n <Pie data={pieData} cx=\"50%\" cy=\"50%\" outerRadius={100}\n dataKey=\"value\" label={renderLabel} labelLine={{ stroke: 'var(--text-muted, #666)' }}\n isAnimationActive={false}>\n {pieData.map((entry, i) => (\n <Cell key={i} fill={entry.fill} />\n ))}\n </Pie>\n <Tooltip {...TOOLTIP_STYLE} />\n </PieChart>\n </ResponsiveContainer>\n );\n }\n\n case 'metric': {\n const s = series[0];\n const current = s.data[0];\n const previous = s.data.length > 1 ? s.data[1] : null;\n const value = current.y;\n const unit = current.x || '';\n const hasTrend = previous !== null;\n const change = hasTrend ? value - previous.y : 0;\n const pctChange = hasTrend && previous.y !== 0 ? ((change / Math.abs(previous.y)) * 100) : 0;\n const isPositive = change > 0;\n const isNegative = change < 0;\n const trendColor = isPositive ? '#7BA89D' : isNegative ? '#D17B6B' : 'var(--text-muted, #666)';\n const trendArrow = isPositive ? '↑' : isNegative ? '↓' : '→';\n\n // Format large numbers nicely\n const fmt = (n) => {\n if (Number.isInteger(n) && Math.abs(n) >= 1000) return n.toLocaleString();\n if (typeof n === 'number') return n % 1 === 0 ? n.toString() : n.toFixed(n < 10 ? 2 : 1);\n return String(n);\n };\n\n return (\n <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, padding: '8px 0' }}>\n <div style={{\n fontSize: '36px', fontWeight: 700, lineHeight: 1,\n color: 'var(--text-strong, #1e2125)',\n fontVariantNumeric: 'tabular-nums',\n }}>\n {fmt(value)}\n </div>\n {unit && (\n <div style={{ fontSize: '14px', color: 'var(--text-muted, #666)', fontWeight: 500 }}>\n {unit}\n </div>\n )}\n {hasTrend && (\n <div style={{\n display: 'flex', alignItems: 'center', gap: 4,\n fontSize: '13px', fontWeight: 600, color: trendColor,\n background: isPositive ? 'rgba(123,168,157,0.12)' : isNegative ? 'rgba(209,123,107,0.12)' : 'rgba(128,128,128,0.08)',\n padding: '3px 8px', borderRadius: 'var(--radius-sm, 4px)',\n }}>\n <span>{trendArrow}</span>\n <span>{fmt(Math.abs(change))} ({Math.abs(pctChange).toFixed(1)}%)</span>\n </div>\n )}\n {hasTrend && (\n <div style={{ fontSize: '11px', color: 'var(--text-faint, #999)' }}>\n vs {previous.x || 'previous'}\n </div>\n )}\n </div>\n );\n }\n\n default:\n return <div style={{ color: 'var(--text-muted)', fontSize: 12, padding: 8 }}>Unsupported chart type: {chartType}</div>;\n }\n };\n\n const handleDownload = useCallback(() => {\n if (chartRef.current) downloadPng(chartRef.current, title);\n }, [title]);\n\n const handleCopy = useCallback(() => {\n copyAsCsv(series, allXValues);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }, [series, allXValues]);\n\n const showActions = chartType !== 'metric';\n\n return (\n <div style={containerStyle}>\n {title && <div style={titleStyle}>{title}</div>}\n {showActions && <ActionBar onDownload={handleDownload} onCopy={handleCopy} copied={copied} />}\n <div ref={chartRef}>\n {renderChart()}\n </div>\n </div>\n );\n};\n\nexport default ChartRenderer;\n"],"names":["COLORS","AXIS_TICK","AXIS_LINE","GRID_STROKE","TOOLTIP_STYLE","LEGEND_STYLE","shouldShowAxisLabel","label","tickValues","lower","v","downloadPng","containerEl","title","svg","clone","w","styleEl","xml","blob","url","img","canvas","scale","ctx","link","copyAsCsv","series","allXValues","header","s","rows","x","vals","match","d","csv","ActionBar","onDownload","onCopy","copied","jsxs","jsx","ChartRenderer","chartType","xLabel","yLabel","chartRef","useRef","setCopied","React","chartData","point","seriesNames","isSingleSeries","showXLabel","bottomMargin","rotateXTicks","containerStyle","titleStyle","xAxisProps","yAxisProps","renderChart","ResponsiveContainer","BarChart","CartesianGrid","XAxis","YAxis","Tooltip","Legend","name","i","Bar","_","idx","Cell","LineChart","Line","AreaChart","Area","pieData","RADIAN","PieChart","Pie","cx","cy","midAngle","innerRadius","outerRadius","percent","radius","y","entry","current","previous","value","unit","hasTrend","change","pctChange","isPositive","isNegative","trendColor","trendArrow","fmt","n","handleDownload","useCallback","handleCopy"],"mappings":"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"}