d3-charts-viz-library
Version:
A comprehensive D3-based chart library with customizable charts and graphs
1 lines • 128 kB
JavaScript
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("d3")):"function"==typeof define&&define.amd?define(["exports","d3"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).D3ChartLibrary={},t.d3)}(this,function(t,e){"use strict";function a(t){var e=Object.create(null);return t&&Object.keys(t).forEach(function(a){if("default"!==a){var i=Object.getOwnPropertyDescriptor(t,a);Object.defineProperty(e,a,i.get?i:{enumerable:!0,get:function(){return t[a]}})}}),e.default=t,Object.freeze(e)}var i=a(e);class r{constructor(t,e={}){this.container=t,this.options={width:800,height:400,margin:{top:20,right:30,bottom:40,left:40},backgroundColor:"#ffffff",...e},this.data=null,this.svg=null,this.chartGroup=null,this.init()}init(){i.select(this.container).selectAll("*").remove(),this.svg=i.select(this.container).append("svg").attr("width",this.options.width).attr("height",this.options.height).style("background-color",this.options.backgroundColor),this.chartGroup=this.svg.append("g").attr("transform",`translate(${this.options.margin.left}, ${this.options.margin.top})`),this.innerWidth=this.options.width-this.options.margin.left-this.options.margin.right,this.innerHeight=this.options.height-this.options.margin.top-this.options.margin.bottom}setData(t){return this.data=t,this}updateOptions(t){return this.options={...this.options,...t},this.init(),this}getDimensions(){return{width:this.innerWidth,height:this.innerHeight,margin:this.options.margin}}addTitle(t,e={}){const a={fontSize:"16px",fontWeight:"bold",textAnchor:"middle",fill:"#333",...e};return this.svg.append("text").attr("x",this.options.width/2).attr("y","16px"===a.fontSize?16:parseInt(a.fontSize)).style("font-size",a.fontSize).style("font-weight",a.fontWeight).style("text-anchor",a.textAnchor).style("fill",a.fill).text(t),this}addLegend(t,e={}){const a={x:this.options.width-100,y:30,itemHeight:20,fontSize:"12px",...e},i=this.svg.append("g").attr("class","legend").attr("transform",`translate(${a.x}, ${a.y})`).selectAll(".legend-item").data(t).enter().append("g").attr("class","legend-item").attr("transform",(t,e)=>`translate(0, ${e*a.itemHeight})`);return i.append("rect").attr("width",12).attr("height",12).attr("fill",t=>t.color),i.append("text").attr("x",16).attr("y",9).style("font-size",a.fontSize).style("alignment-baseline","middle").text(t=>t.label),this}addTooltip(){return this.tooltip=i.select("body").append("div").attr("class","d3-tooltip").style("position","absolute").style("visibility","hidden").style("background-color","rgba(0, 0, 0, 0.8)").style("color","white").style("padding","8px").style("border-radius","4px").style("font-size","12px").style("pointer-events","none").style("z-index","1000"),this}showTooltip(t,e){this.tooltip&&this.tooltip.style("visibility","visible").html(t).style("left",e.pageX+10+"px").style("top",e.pageY-10+"px")}hideTooltip(){this.tooltip&&this.tooltip.style("visibility","hidden")}render(){throw new Error("render() method must be implemented by subclasses")}destroy(){this.tooltip&&this.tooltip.remove(),i.select(this.container).selectAll("*").remove()}}class o extends r{constructor(t,e={}){super(t,{innerRadius:0,outerRadius:null,padAngle:.02,cornerRadius:0,colors:i.schemeCategory10,showLabels:!0,labelOffset:20,showPercentages:!0,...e}),this.addTooltip()}render(){if(!this.data||0===this.data.length)return console.warn("No data provided for PieChart"),this;this.chartGroup.selectAll("*").remove();const t=this.options.outerRadius||Math.min(this.innerWidth,this.innerHeight)/2-10,e=this.innerWidth/2,a=this.innerHeight/2,r=this.chartGroup.append("g").attr("transform",`translate(${e}, ${a})`),o=i.pie().value(t=>t.value).sort(null).padAngle(this.options.padAngle),s=i.arc().innerRadius(this.options.innerRadius).outerRadius(t).cornerRadius(this.options.cornerRadius),n=i.arc().innerRadius(t+this.options.labelOffset).outerRadius(t+this.options.labelOffset),l=i.scaleOrdinal(this.options.colors),h=r.selectAll(".slice").data(o(this.data)).enter().append("g").attr("class","slice"),c=h.append("path").attr("fill",(t,e)=>l(e)).attr("stroke","#fff").attr("stroke-width",2).style("cursor","pointer").each(function(t){this._current={startAngle:0,endAngle:0}});return c.transition().duration(1e3).attrTween("d",function(t){const e=i.interpolate(this._current,t);return this._current=e(0),function(t){return s(e(t))}}),this.addSliceInteractivity(c,s),this.options.showLabels&&this.addLabels(h,o(this.data),n),this}addSliceInteractivity(t,e){const a=this,r=i.arc().innerRadius(this.options.innerRadius).outerRadius(e.outerRadius()()+10).cornerRadius(this.options.cornerRadius);t.on("mouseover",function(t,e){i.select(this).transition().duration(200).attr("d",r);const o=((e.endAngle-e.startAngle)/(2*Math.PI)*100).toFixed(1),s=`${e.data.label}: ${e.data.value} (${o}%)`;a.showTooltip(s,t)}).on("mouseout",function(t,r){i.select(this).transition().duration(200).attr("d",e),a.hideTooltip()}).on("click",function(t,e){a.options.onClick&&a.options.onClick(e.data,t)})}addLabels(t,e,a){const i=t.append("text").attr("transform",t=>`translate(${a.centroid(t)})`).attr("text-anchor","middle").attr("alignment-baseline","middle").style("font-size","12px").style("fill","#333").style("opacity",0);i.text(t=>{if(this.options.showPercentages){const e=((t.endAngle-t.startAngle)/(2*Math.PI)*100).toFixed(1);return`${t.data.label} (${e}%)`}return t.data.label}),i.transition().delay(500).duration(500).style("opacity",1),this.addLabelLines(t,e,a)}addLabelLines(t,e,a){const r=i.arc().innerRadius(this.options.innerRadius).outerRadius(this.options.outerRadius||Math.min(this.innerWidth,this.innerHeight)/2-10),o=t.append("polyline").attr("fill","none").attr("stroke","#999").attr("stroke-width",1).style("opacity",0);o.attr("points",t=>{const e=a.centroid(t);return[r.centroid(t),e]}),o.transition().delay(500).duration(500).style("opacity",.7)}createDonut(t=.5){const e=this.options.outerRadius||Math.min(this.innerWidth,this.innerHeight)/2-10;return this.options.innerRadius=e*t,this.render()}updateData(t){return this.setData(t),this.render(),this}explodeSlice(t,e=20){const a=this.chartGroup.select(`.slice:nth-child(${t+1})`),r=i.pie().value(t=>t.value)(this.data),o=i.arc().innerRadius(this.options.innerRadius).outerRadius(this.options.outerRadius||Math.min(this.innerWidth,this.innerHeight)/2-10).centroid(r[t]),s=o[0]*e/100,n=o[1]*e/100;return a.transition().duration(300).attr("transform",`translate(${s}, ${n})`),this}resetSlices(){return this.chartGroup.selectAll(".slice").transition().duration(300).attr("transform","translate(0, 0)"),this}}const s={parseCSV:function(t,e,a,i=null){const r=t.trim().split("\n"),o=r[0].split(",").map(t=>t.trim()),s=o.indexOf(e),n=o.indexOf(a),l=i?o.indexOf(i):-1;if(-1===s||-1===n)throw new Error("Column not found in CSV data");return r.slice(1).map(t=>{const e=t.split(",").map(t=>t.trim()),a={x:isNaN(e[s])?e[s]:+e[s],y:isNaN(e[n])?e[n]:+e[n]};return-1!==l&&(a.label=e[l]),a})},generateSampleData:function(t="linear",e=50){const a=[];switch(t){case"linear":for(let t=0;t<e;t++)a.push({x:t,y:2*t+10*Math.random(),label:`Point ${t}`});break;case"sine":for(let t=0;t<e;t++){const i=t/e*4*Math.PI;a.push({x:i,y:50*Math.sin(i)+50,label:`Point ${t}`})}break;case"random":for(let t=0;t<e;t++)a.push({x:100*Math.random(),y:100*Math.random(),label:`Point ${t}`});break;case"categories":return["A","B","C","D","E"].map(t=>({label:t,value:Math.floor(100*Math.random())+10}))}return a},normalize:function(t,e="y",a=0,i=1){const r=t.map(t=>t[e]),o=Math.min(...r),s=Math.max(...r)-o;return t.map(t=>({...t,[e]:(t[e]-o)/s*(i-a)+a}))},groupBy:function(t,e){return t.reduce((t,a)=>{const i=a[e];return t[i]||(t[i]=[]),t[i].push(a),t},{})},movingAverage:function(t,e=5,a="y"){const i=[];for(let r=0;r<t.length;r++){const o=Math.max(0,r-Math.floor(e/2)),s=Math.min(t.length,r+Math.ceil(e/2)),n=t.slice(o,s),l=n.reduce((t,e)=>t+e[a],0)/n.length;i.push({...t[r],[a]:l})}return i}},n={generatePalette:function(t,e="category10"){const a={category10:["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf"],pastel:["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec","#f2f2f2"],dark:["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"]},i=a[e]||a.category10,r=[];for(let e=0;e<t;e++)r.push(i[e%i.length]);return r},interpolateColor:function(t,e,a){const i=this.hexToRgb(t),r=this.hexToRgb(e),o=Math.round(i.r+(r.r-i.r)*a),s=Math.round(i.g+(r.g-i.g)*a),n=Math.round(i.b+(r.b-i.b)*a);return this.rgbToHex(o,s,n)},hexToRgb:function(t){const e=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return e?{r:parseInt(e[1],16),g:parseInt(e[2],16),b:parseInt(e[3],16)}:null},rgbToHex:function(t,e,a){return"#"+((1<<24)+(t<<16)+(e<<8)+a).toString(16).slice(1)},darken:function(t,e=.2){const a=this.hexToRgb(t);if(!a)return t;const i=Math.max(0,Math.round(a.r*(1-e))),r=Math.max(0,Math.round(a.g*(1-e))),o=Math.max(0,Math.round(a.b*(1-e)));return this.rgbToHex(i,r,o)},lighten:function(t,e=.2){const a=this.hexToRgb(t);if(!a)return t;const i=Math.min(255,Math.round(a.r+(255-a.r)*e)),r=Math.min(255,Math.round(a.g+(255-a.g)*e)),o=Math.min(255,Math.round(a.b+(255-a.b)*e));return this.rgbToHex(i,r,o)}},l={easing:{linear:t=>t,easeInQuad:t=>t*t,easeOutQuad:t=>t*(2-t),easeInOutQuad:t=>t<.5?2*t*t:(4-2*t)*t-1,easeInCubic:t=>t*t*t,easeOutCubic:t=>--t*t*t+1,easeInOutCubic:t=>t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},animate:function(t,e,a,i,r="easeOutQuad"){const o=Date.now(),s=this.easing[r]||this.easing.linear;requestAnimationFrame(function r(){const n=Date.now()-o,l=Math.min(n/a,1),h=s(l);i(t+(e-t)*h,l),l<1&&requestAnimationFrame(r)})},stagger:function(t,e=100){return t.map((t,a)=>({...t,delay:a*e}))}},h={stats:function(t,e="y"){const a=t.map(t=>t[e]).filter(t=>!isNaN(t)),i=a.slice().sort((t,e)=>t-e),r=a.length;if(0===r)return null;const o=a.reduce((t,e)=>t+e,0),s=o/r,n=a.reduce((t,e)=>t+Math.pow(e-s,2),0)/r;return{count:r,min:Math.min(...a),max:Math.max(...a),sum:o,mean:s,median:r%2==0?(i[r/2-1]+i[r/2])/2:i[Math.floor(r/2)],mode:this.calculateMode(a),variance:n,standardDeviation:Math.sqrt(n),q1:this.percentile(i,.25),q3:this.percentile(i,.75)}},percentile:function(t,e){const a=e*(t.length-1),i=Math.floor(a),r=Math.ceil(a),o=a%1;return r>=t.length?t[t.length-1]:t[i]*(1-o)+t[r]*o},calculateMode:function(t){const e={};let a=0,i=null;return t.forEach(t=>{e[t]=(e[t]||0)+1,e[t]>a&&(a=e[t],i=t)}),i},lerp:function(t,e,a){return t+(e-t)*a},clamp:function(t,e,a){return Math.min(Math.max(t,e),a)},map:function(t,e,a,i,r){return(t-e)*(r-i)/(a-e)+i}},c={getDimensions:function(t){const e=t.getBoundingClientRect();return{width:e.width,height:e.height,top:e.top,left:e.left}},makeResponsive:function(t,e){const a=new ResizeObserver(e=>{for(let a of e){const{width:e,height:i}=a.contentRect;t.updateOptions({width:e,height:i}),t.render()}});return a.observe(e),a},exportAsImage:function(t,e="chart.png",a=2){const i=(new XMLSerializer).serializeToString(t),r=document.createElement("canvas"),o=r.getContext("2d"),s=new Image,n=new Blob([i],{type:"image/svg+xml;charset=utf-8"}),l=URL.createObjectURL(n);s.onload=function(){r.width=s.width*a,r.height=s.height*a,o.scale(a,a),o.drawImage(s,0,0),r.toBlob(t=>{const a=document.createElement("a");a.download=e,a.href=URL.createObjectURL(t),a.click(),URL.revokeObjectURL(l),URL.revokeObjectURL(a.href)})},s.src=l}};t.AnimatedBumpChart=class extends r{constructor(t,e={}){super(t,{width:800,height:500,margin:{top:40,right:120,bottom:60,left:80},animationDuration:1500,animationDelay:500,pointRadius:6,strokeWidth:2,principalRatio:.6,colors:["#3498db","#e74c3c","#f39c12"],showDistributionBars:!0,showPoints:!0,showTooltip:!0,curve:i.curveCatmullRom,...e}),this.addTooltip(),this.colorScale=i.scaleOrdinal(this.options.colors)}processData(t){if(!t?.economicSchedule)return[];return t.economicSchedule.slice(0,10).map((t,e)=>({year:e+1,principal:t.remainder*this.options.principalRatio,growth:t.remainder*(1-this.options.principalRatio),total:t.remainder,distribution:t.distribution||0,income:t.income||0}))}createGradients(){const t=this.svg.append("defs"),e=t.append("linearGradient").attr("id","principal-gradient").attr("gradientUnits","userSpaceOnUse").attr("x1",0).attr("y1",this.innerHeight).attr("x2",0).attr("y2",0);e.append("stop").attr("offset","0%").attr("stop-color",this.colorScale(0)).attr("stop-opacity",.8),e.append("stop").attr("offset","100%").attr("stop-color",this.colorScale(0)).attr("stop-opacity",.3);const a=t.append("linearGradient").attr("id","growth-gradient").attr("gradientUnits","userSpaceOnUse").attr("x1",0).attr("y1",this.innerHeight).attr("x2",0).attr("y2",0);a.append("stop").attr("offset","0%").attr("stop-color",this.colorScale(1)).attr("stop-opacity",.8),a.append("stop").attr("offset","100%").attr("stop-color",this.colorScale(1)).attr("stop-opacity",.3)}createScales(t){const e=i.max(t,t=>t.year)||10,a=i.max(t,t=>t.total)||1e6;this.xScale=i.scaleLinear().domain([1,e]).range([0,this.innerWidth]),this.yScale=i.scaleLinear().domain([0,a]).range([this.innerHeight,0])}createAreaGenerators(){this.principalArea=i.area().x(t=>this.xScale(t.year)).y0(this.innerHeight).y1(t=>this.yScale(t.principal)).curve(this.options.curve),this.growthArea=i.area().x(t=>this.xScale(t.year)).y0(t=>this.yScale(t.principal)).y1(t=>this.yScale(t.total)).curve(this.options.curve)}drawAreas(t){const e=this.chartGroup.append("path").datum(t).attr("class","principal-area").attr("fill","url(#principal-gradient)").attr("stroke",this.colorScale(0)).attr("stroke-width",this.options.strokeWidth).attr("d",this.principalArea).style("opacity",0),a=this.chartGroup.append("path").datum(t).attr("class","growth-area").attr("fill","url(#growth-gradient)").attr("stroke",this.colorScale(1)).attr("stroke-width",this.options.strokeWidth).attr("d",this.growthArea).style("opacity",0);return e.transition().duration(this.options.animationDuration).style("opacity",1),a.transition().delay(this.options.animationDelay).duration(this.options.animationDuration).style("opacity",1),{principalPath:e,growthPath:a}}drawPoints(t){if(!this.options.showPoints)return;const e=this.chartGroup.selectAll(".principal-point").data(t).enter().append("circle").attr("class","principal-point").attr("cx",t=>this.xScale(t.year)).attr("cy",t=>this.yScale(t.principal)).attr("r",0).attr("fill",this.colorScale(0)).attr("stroke","white").attr("stroke-width",2).style("filter","drop-shadow(0 2px 4px rgba(0,0,0,0.2))"),a=this.chartGroup.selectAll(".growth-point").data(t).enter().append("circle").attr("class","growth-point").attr("cx",t=>this.xScale(t.year)).attr("cy",t=>this.yScale(t.total)).attr("r",0).attr("fill",this.colorScale(1)).attr("stroke","white").attr("stroke-width",2).style("filter","drop-shadow(0 2px 4px rgba(0,0,0,0.2))");e.transition().delay((t,e)=>1e3+100*e).duration(300).attr("r",this.options.pointRadius),a.transition().delay((t,e)=>1500+100*e).duration(300).attr("r",this.options.pointRadius)}drawDistributionBars(t){if(!this.options.showDistributionBars)return;const e=i.max(t,t=>t.distribution)||5e4;this.chartGroup.selectAll(".distribution-bar").data(t).enter().append("rect").attr("class","distribution-bar").attr("x",t=>this.xScale(t.year)-8).attr("y",t=>this.yScale(t.total)-40).attr("width",16).attr("height",0).attr("fill",this.colorScale(2)).attr("rx",2).style("opacity",.7).transition().delay((t,e)=>2e3+100*e).duration(500).attr("height",t=>Math.max(2,t.distribution/e*30))}addInteractivity(t){this.options.showTooltip&&this.chartGroup.append("rect").attr("width",this.innerWidth).attr("height",this.innerHeight).attr("fill","transparent").style("cursor","crosshair").on("mousemove",e=>{const[a]=i.pointer(e),r=Math.round(this.xScale.invert(a)),o=t.find(t=>t.year===r);if(o){const t=`\n <div style="font-weight: bold; margin-bottom: 5px;">Year ${o.year}</div>\n <div>Principal: ${this.formatValue(o.principal)}</div>\n <div>Growth: ${this.formatValue(o.growth)}</div>\n <div>Distribution: ${this.formatValue(o.distribution)}</div>\n <div style="color: ${this.colorScale(0)}; font-weight: bold; margin-top: 5px;">\n Total: ${this.formatValue(o.total)}\n </div>\n `;this.showTooltip(t,e)}}).on("mouseout",()=>{this.hideTooltip()})}formatValue(t){return t>=1e6?`$${(t/1e6).toFixed(1)}M`:t>=1e3?`$${(t/1e3).toFixed(0)}K`:`$${t.toFixed(0)}`}drawAxes(){const t=i.axisBottom(this.xScale).tickFormat(t=>`Year ${t}`),e=i.axisLeft(this.yScale).tickFormat(t=>this.formatValue(t));this.chartGroup.append("g").attr("class","x-axis").attr("transform",`translate(0,${this.innerHeight})`).call(t).selectAll("text").attr("font-size","11px").attr("fill","#64748b"),this.chartGroup.append("g").attr("class","y-axis").call(e).selectAll("text").attr("font-size","11px").attr("fill","#64748b"),this.chartGroup.append("text").attr("transform",`translate(${this.innerWidth/2}, ${this.innerHeight+45})`).attr("text-anchor","middle").attr("font-size","12px").attr("font-weight","600").attr("fill","#1e293b").text("Time Period"),this.chartGroup.append("text").attr("transform","rotate(-90)").attr("y",-60).attr("x",-this.innerHeight/2).attr("text-anchor","middle").attr("font-size","12px").attr("font-weight","600").attr("fill","#1e293b").text("Value")}createLegend(){const t=this.svg.append("g").attr("transform",`translate(${this.options.width-100}, 60)`);[{label:"Principal",color:this.colorScale(0)},{label:"Growth",color:this.colorScale(1)},{label:"Distribution",color:this.colorScale(2)}].forEach((e,a)=>{const i=t.append("g").attr("transform",`translate(0, ${25*a})`);i.append("rect").attr("width",15).attr("height",15).attr("fill",e.color).attr("rx",3),i.append("text").attr("x",20).attr("y",12).attr("font-size","11px").attr("fill","#1e293b").text(e.label)})}render(){if(!this.data)return this;this.chartGroup.selectAll("*").remove(),this.svg.selectAll("defs").remove();const t=this.processData(this.data);return 0===t.length||(this.createGradients(),this.createScales(t),this.createAreaGenerators(),this.drawAreas(t),this.drawPoints(t),this.drawDistributionBars(t),this.drawAxes(),this.createLegend(),this.addInteractivity(t)),this}update(t){return this.setData(t),this.render()}},t.AnimationUtils=l,t.AreaChart=class extends r{constructor(t,e={}){super(t,{areaColor:"rgba(52, 152, 219, 0.6)",lineColor:"#3498db",lineWidth:2,curve:i.curveLinear,showLine:!0,showPoints:!1,pointRadius:3,...e}),this.addTooltip()}render(){if(!this.data||0===this.data.length)return console.warn("No data provided for AreaChart"),this;this.chartGroup.selectAll("*").remove();const t=i.scaleLinear().domain(i.extent(this.data,t=>t.x)).range([0,this.innerWidth]),e=i.scaleLinear().domain([0,i.max(this.data,t=>t.y)]).range([this.innerHeight,0]),a=i.area().x(e=>t(e.x)).y0(this.innerHeight).y1(t=>e(t.y)).curve(this.options.curve),r=i.line().x(e=>t(e.x)).y(t=>e(t.y)).curve(this.options.curve),o=i.axisBottom(t),s=i.axisLeft(e);this.chartGroup.append("g").attr("class","x-axis").attr("transform",`translate(0, ${this.innerHeight})`).call(o),this.chartGroup.append("g").attr("class","y-axis").call(s);const n=this.chartGroup.append("path").datum(this.data).attr("class","area").attr("fill",this.options.areaColor).attr("d",a);if(this.animateArea(n),this.options.showLine){const t=this.chartGroup.append("path").datum(this.data).attr("class","line").attr("fill","none").attr("stroke",this.options.lineColor).attr("stroke-width",this.options.lineWidth).attr("d",r);this.animateLine(t)}return this.options.showPoints&&this.addPoints(t,e),this.addInteractionOverlay(t,e),this}animateArea(t){const e=t.node().getTotalLength();t.attr("stroke-dasharray",e+" "+e).attr("stroke-dashoffset",e).attr("stroke",this.options.areaColor).attr("stroke-width",1).transition().duration(1500).attr("stroke-dashoffset",0).on("end",function(){i.select(this).attr("stroke","none")})}animateLine(t){const e=t.node().getTotalLength();t.attr("stroke-dasharray",e+" "+e).attr("stroke-dashoffset",e).transition().duration(1500).attr("stroke-dashoffset",0)}addPoints(t,e){const a=this,r=this.chartGroup.selectAll(".point").data(this.data).enter().append("circle").attr("class","point").attr("cx",e=>t(e.x)).attr("cy",t=>e(t.y)).attr("r",0).attr("fill",this.options.lineColor).style("cursor","pointer");r.transition().delay((t,e)=>50*e).duration(300).attr("r",this.options.pointRadius),r.on("mouseover",function(t,e){i.select(this).transition().duration(150).attr("r",1.5*a.options.pointRadius),a.showTooltip(`(${e.x}, ${e.y})`,t)}).on("mouseout",function(){i.select(this).transition().duration(150).attr("r",a.options.pointRadius),a.hideTooltip()})}addInteractionOverlay(t,e){const a=this,r=i.bisector(t=>t.x).left,o=this.chartGroup.append("rect").attr("class","overlay").attr("width",this.innerWidth).attr("height",this.innerHeight).attr("fill","none").attr("pointer-events","all").style("cursor","crosshair"),s=this.chartGroup.append("g").attr("class","focus").style("display","none");s.append("circle").attr("r",4).attr("fill",this.options.lineColor).attr("stroke","#fff").attr("stroke-width",2),s.append("line").attr("class","x-hover-line").attr("stroke","#999").attr("stroke-width",1).attr("stroke-dasharray","3,3"),s.append("line").attr("class","y-hover-line").attr("stroke","#999").attr("stroke-width",1).attr("stroke-dasharray","3,3"),o.on("mouseover",()=>s.style("display",null)).on("mouseout",()=>{s.style("display","none"),a.hideTooltip()}).on("mousemove",function(o){const[n]=i.pointer(o,this),l=t.invert(n),h=r(a.data,l,1);if(h>=a.data.length)return;const c=a.data[h-1],d=a.data[h],p=l-c.x>d.x-l?d:c;s.attr("transform",`translate(${t(p.x)}, ${e(p.y)})`),s.select(".x-hover-line").attr("y1",-e(p.y)).attr("y2",a.innerHeight-e(p.y)),s.select(".y-hover-line").attr("x1",-t(p.x)).attr("x2",a.innerWidth-t(p.x)),a.showTooltip(`(${p.x}, ${p.y})`,o)})}renderStacked(t){if(!t||0===t.length)return console.warn("No series data provided for stacked AreaChart"),this;this.chartGroup.selectAll("*").remove();const e=t.map(t=>t.name),a=this.prepareStackData(t),r=i.stack().keys(e).order(i.stackOrderNone).offset(i.stackOffsetNone)(a),o=i.scaleLinear().domain(i.extent(a,t=>t.x)).range([0,this.innerWidth]),s=i.scaleLinear().domain([0,i.max(r,t=>i.max(t,t=>t[1]))]).range([this.innerHeight,0]),n=i.scaleOrdinal(i.schemeCategory10),l=i.area().x(t=>o(t.data.x)).y0(t=>s(t[0])).y1(t=>s(t[1])).curve(this.options.curve),h=i.axisBottom(o),c=i.axisLeft(s);this.chartGroup.append("g").attr("class","x-axis").attr("transform",`translate(0, ${this.innerHeight})`).call(h),this.chartGroup.append("g").attr("class","y-axis").call(c),this.chartGroup.selectAll(".area").data(r).enter().append("path").attr("class","area").attr("fill",(t,e)=>n(e)).attr("d",l).style("opacity",.8);const d=e.map((t,e)=>({label:t,color:n(e)}));return this.addLegend(d),this}prepareStackData(t){return[...new Set(t.flatMap(t=>t.data.map(t=>t.x)))].sort((t,e)=>t-e).map(e=>{const a={x:e};return t.forEach(t=>{const i=t.data.find(t=>t.x===e);a[t.name]=i?i.y:0}),a})}updateData(t){return this.setData(t),this.render(),this}},t.BarChart=class extends r{constructor(t,e={}){super(t,{barPadding:.1,barColor:"#3498db",hoverColor:"#2980b9",showValues:!1,orientation:"vertical",...e}),this.addTooltip()}render(){return this.data&&0!==this.data.length?(this.chartGroup.selectAll("*").remove(),"vertical"===this.options.orientation?this.renderVerticalBars():this.renderHorizontalBars(),this):(console.warn("No data provided for BarChart"),this)}renderVerticalBars(){const t=i.scaleBand().domain(this.data.map(t=>t.label)).range([0,this.innerWidth]).padding(this.options.barPadding),e=i.scaleLinear().domain([0,i.max(this.data,t=>t.value)]).range([this.innerHeight,0]),a=i.axisBottom(t),r=i.axisLeft(e);this.chartGroup.append("g").attr("class","x-axis").attr("transform",`translate(0, ${this.innerHeight})`).call(a),this.chartGroup.append("g").attr("class","y-axis").call(r);const o=this.chartGroup.selectAll(".bar").data(this.data).enter().append("rect").attr("class","bar").attr("x",e=>t(e.label)).attr("width",t.bandwidth()).attr("y",this.innerHeight).attr("height",0).attr("fill",this.options.barColor).style("cursor","pointer");o.transition().duration(800).attr("y",t=>e(t.value)).attr("height",t=>this.innerHeight-e(t.value)),this.addBarInteractivity(o),this.options.showValues&&this.addValueLabels(t,e)}renderHorizontalBars(){const t=i.scaleBand().domain(this.data.map(t=>t.label)).range([0,this.innerHeight]).padding(this.options.barPadding),e=i.scaleLinear().domain([0,i.max(this.data,t=>t.value)]).range([0,this.innerWidth]),a=i.axisBottom(e),r=i.axisLeft(t);this.chartGroup.append("g").attr("class","x-axis").attr("transform",`translate(0, ${this.innerHeight})`).call(a),this.chartGroup.append("g").attr("class","y-axis").call(r);const o=this.chartGroup.selectAll(".bar").data(this.data).enter().append("rect").attr("class","bar").attr("y",e=>t(e.label)).attr("height",t.bandwidth()).attr("x",0).attr("width",0).attr("fill",this.options.barColor).style("cursor","pointer");o.transition().duration(800).attr("width",t=>e(t.value)),this.addBarInteractivity(o)}addBarInteractivity(t){const e=this;t.on("mouseover",function(t,a){i.select(this).attr("fill",e.options.hoverColor),e.showTooltip(`${a.label}: ${a.value}`,t)}).on("mouseout",function(){i.select(this).attr("fill",e.options.barColor),e.hideTooltip()}).on("click",function(t,a){e.options.onClick&&e.options.onClick(a,t)})}addValueLabels(t,e){"vertical"===this.options.orientation?this.chartGroup.selectAll(".value-label").data(this.data).enter().append("text").attr("class","value-label").attr("x",e=>t(e.label)+t.bandwidth()/2).attr("y",t=>e(t.value)-5).attr("text-anchor","middle").style("font-size","12px").style("fill","#333").text(t=>t.value):this.chartGroup.selectAll(".value-label").data(this.data).enter().append("text").attr("class","value-label").attr("x",e=>t(e.value)+5).attr("y",t=>e(t.label)+e.bandwidth()/2).attr("text-anchor","start").attr("alignment-baseline","middle").style("font-size","12px").style("fill","#333").text(t=>t.value)}updateData(t){return this.setData(t),this.render(),this}},t.BaseChart=r,t.CalendarHeatmapChart=class extends r{constructor(t,e={}){super(t,{width:900,height:200,margin:{top:20,right:20,bottom:20,left:50},colorScheme:"green",showTooltip:!0,showLegend:!0,cellSize:12,cellPadding:2,showMonthLabels:!0,showWeekdayLabels:!0,showYearLabel:!0,animated:!0,year:(new Date).getFullYear(),...e}),this.colorSchemes={green:{colors:["#ebedf0","#9be9a8","#40c463","#30a14e","#216e39"],name:"GitHub Green"},blue:{colors:["#f0f9ff","#7dd3fc","#38bdf8","#0ea5e9","#0284c7"],name:"Ocean Blue"},purple:{colors:["#faf5ff","#c4b5fd","#a78bfa","#8b5cf6","#7c3aed"],name:"Royal Purple"},orange:{colors:["#fff7ed","#fed7aa","#fdba74","#fb923c","#f97316"],name:"Sunset Orange"}},this.timeWeek=i.timeWeek,this.timeDay=i.timeDay,this.timeFormat=i.timeFormat,this.timeParse=i.timeParse,this.options.showTooltip&&this.addTooltip()}init(){super.init(),this.colorSchemes||(this.colorSchemes={green:{colors:["#ebedf0","#9be9a8","#40c463","#30a14e","#216e39"],name:"GitHub Green"},blue:{colors:["#f0f9ff","#7dd3fc","#38bdf8","#0ea5e9","#0284c7"],name:"Ocean Blue"},purple:{colors:["#faf5ff","#c4b5fd","#a78bfa","#8b5cf6","#7c3aed"],name:"Royal Purple"},orange:{colors:["#fff7ed","#fed7aa","#fdba74","#fb923c","#f97316"],name:"Sunset Orange"}}),this.year=this.options.year,this.cellSize=this.options.cellSize,this.cellPadding=this.options.cellPadding,this.yearStart=new Date(this.year,0,1),this.yearEnd=new Date(this.year,11,31);const t=i.timeWeek.count(this.yearStart,this.yearEnd)+1;this.chartWidth=t*(this.cellSize+this.cellPadding),this.chartHeight=7*(this.cellSize+this.cellPadding),this.options.width<this.chartWidth+this.options.margin.left+this.options.margin.right&&(this.options.width=this.chartWidth+this.options.margin.left+this.options.margin.right,this.svg.attr("width",this.options.width)),this.options.height<this.chartHeight+this.options.margin.top+this.options.margin.bottom+60&&(this.options.height=this.chartHeight+this.options.margin.top+this.options.margin.bottom+60,this.svg.attr("height",this.options.height)),this.setupScales(),this.options.showWeekdayLabels&&this.addWeekdayLabels(),this.options.showMonthLabels&&this.addMonthLabels(),this.options.showYearLabel&&this.addYearLabel(),this.options.showLegend&&this.addLegend()}setupScales(){const t=this.colorSchemes[this.options.colorScheme];this.colorScale=i.scaleQuantile().range(t.colors),this.xScale=t=>i.timeWeek.count(this.yearStart,t)*(this.cellSize+this.cellPadding),this.yScale=t=>t.getDay()*(this.cellSize+this.cellPadding)}addWeekdayLabels(){this.chartGroup.selectAll(".weekday-label").data(["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]).enter().append("text").attr("class","weekday-label").attr("x",-10).attr("y",(t,e)=>e*(this.cellSize+this.cellPadding)+this.cellSize/2).attr("text-anchor","end").attr("dominant-baseline","middle").style("font-size","10px").style("fill","#666").style("font-family","monospace").text(t=>t)}addMonthLabels(){this.chartGroup.selectAll(".month-label").data(i.timeMonths(this.yearStart,new Date(this.year+1,0,1))).enter().append("text").attr("class","month-label").attr("x",t=>this.xScale(t)).attr("y",-10).style("font-size","10px").style("fill","#666").style("font-family","monospace").text(t=>i.timeFormat("%b")(t))}addYearLabel(){this.svg.append("text").attr("class","year-label").attr("x",this.options.margin.left).attr("y",this.options.height-10).style("font-size","12px").style("font-weight","bold").style("fill","#333").text(this.year)}addLegend(){const t=this.svg.append("g").attr("class","legend").attr("transform",`translate(${this.options.width-200}, ${this.options.height-30})`);t.append("text").attr("x",0).attr("y",-5).style("font-size","10px").style("fill","#666").text("Less"),t.append("text").attr("x",80).attr("y",-5).style("font-size","10px").style("fill","#666").text("More");const e=this.colorSchemes[this.options.colorScheme];t.selectAll(".legend-cell").data(e.colors).enter().append("rect").attr("class","legend-cell").attr("x",(t,e)=>12*e).attr("y",0).attr("width",10).attr("height",10).attr("fill",t=>t).attr("stroke","#ccc").attr("stroke-width",.5)}render(){if(!this.data)return console.warn("No data provided to CalendarHeatmapChart"),this;this.dataMap=new Map;let t=0;this.data.forEach(e=>{const a="string"==typeof e.date?new Date(e.date):e.date,r=i.timeFormat("%Y-%m-%d")(a);this.dataMap.set(r,e.value||0),t=Math.max(t,e.value||0)}),this.colorScale.domain([0,t]);const e=i.timeDays(this.yearStart,new Date(this.year+1,0,1)),a=this.chartGroup.selectAll(".day-cell").data(e,t=>i.timeFormat("%Y-%m-%d")(t));a.exit().remove();const r=a.enter().append("rect").attr("class","day-cell").attr("width",this.cellSize).attr("height",this.cellSize).attr("rx",2).attr("ry",2).attr("stroke","#ccc").attr("stroke-width",.5),o=r.merge(a).attr("x",t=>this.xScale(t)).attr("y",t=>this.yScale(t)).attr("fill",t=>{const e=i.timeFormat("%Y-%m-%d")(t),a=this.dataMap.get(e)||0;return this.colorScale(a)});return this.options.showTooltip&&o.on("mouseover",(t,e)=>{const a=i.timeFormat("%Y-%m-%d")(e),r=this.dataMap.get(a)||0,o=i.timeFormat("%B %d, %Y")(e);this.showTooltip(`<strong>${o}</strong><br/>Value: ${r}`,t),i.select(t.target).attr("stroke","#333").attr("stroke-width",2)}).on("mouseout",t=>{this.hideTooltip(),i.select(t.target).attr("stroke","#ccc").attr("stroke-width",.5)}),this.options.animated&&r.style("opacity",0).transition().duration(50).delay((t,e)=>2*e).style("opacity",1),this}updateYear(t){return this.options.year=t,this.init(),this.render(),this}updateColorScheme(t){return this.options.colorScheme=t,this.setupScales(),this.render(),this}updateData(t){return this.setData(t),this.render(),this}getDataForDate(t){const e=i.timeFormat("%Y-%m-%d")(t);return this.dataMap.get(e)||0}setDataForDate(t,e){const a=i.timeFormat("%Y-%m-%d")(t);this.dataMap.set(a,e);const r=this.data.findIndex(t=>{const e="string"==typeof t.date?new Date(t.date):t.date;return i.timeFormat("%Y-%m-%d")(e)===a});return r>=0?this.data[r].value=e:this.data.push({date:new Date(t),value:e}),this.render(),this}},t.ChordDiagramChart=class extends r{constructor(t,e={}){super(t,{width:600,height:600,margin:{top:60,right:60,bottom:60,left:60},outerRadius:null,innerRadius:null,padAngle:.05,animationDuration:1200,groupAnimationDelay:200,chordAnimationDelay:1e3,primaryColor:"#10b981",secondaryColor:"#3b82f6",accentColor:"#8b5cf6",warningColor:"#f59e0b",mutedColor:"#6b7280",showTooltip:!0,showCenterInfo:!0,title:"Trust Relationships",...e}),this.chordData=[],this.matrix=[],this.labels=["Charitable\nDeduction","Income\nStream","Annual\nDistributions","Trust\nRemainder"],this.colors=[this.options.primaryColor,this.options.secondaryColor,this.options.accentColor,this.options.warningColor],this.id=Math.random().toString(36).substr(2,9)}processData(t){if(!t)return console.warn("ChordDiagramChart: No data provided"),{matrix:[],labels:this.labels};let e=t;t.data&&(e=t.data);const a=e.economicSchedule?.[0]?.remainder||e.economicSchedule?.[0]?.beginningPrincipal||1e6,i=e.economicSchedule?.reduce((t,e)=>t+(e.distribution||0),0)||.05*a,r=e.charitDeduction||e.charitableDeduction||.3*a,o=e.economicSchedule?.[e.economicSchedule.length-1]?.remainder||.7*a;return{matrix:[[0,.3*r,.2*i,.1*o],[.3*r,0,.4*i,.3*o],[.2*i,.4*i,0,.2*o],[.1*o,.3*o,.2*o,0]],labels:this.labels,totalFlow:i+r,totalTrust:a,charitableDeduction:r,totalDistribution:i,remainderValue:o}}createGradients(){const t=this.svg.select("defs").empty()?this.svg.append("defs"):this.svg.select("defs");this.colors.forEach((e,a)=>{const i=t.append("radialGradient").attr("id",`chord-gradient-${this.id}-${a}`).attr("cx","50%").attr("cy","50%").attr("r","50%");i.append("stop").attr("offset","0%").attr("stop-color",n.lighten(e,.2)).attr("stop-opacity",1),i.append("stop").attr("offset","100%").attr("stop-color",e).attr("stop-opacity",.8)});const e=t.append("filter").attr("id",`chord-glow-${this.id}`).attr("x","-50%").attr("y","-50%").attr("width","200%").attr("height","200%");e.append("feGaussianBlur").attr("stdDeviation","2").attr("result","coloredBlur");const a=e.append("feMerge");a.append("feMergeNode").attr("in","coloredBlur"),a.append("feMergeNode").attr("in","SourceGraphic")}renderGroups(t){const e=i.arc().innerRadius(this.innerRadius).outerRadius(this.outerRadius),a=this.chartGroup.selectAll(".chord-group").data(t.groups).enter().append("g").attr("class","chord-group");return a.append("path").attr("fill",(t,e)=>`url(#chord-gradient-${this.id}-${e})`).attr("stroke",(t,e)=>this.colors[e]).attr("stroke-width",2).attr("d",e).style("opacity",0).style("filter",`url(#chord-glow-${this.id})`).transition().delay((t,e)=>e*this.options.groupAnimationDelay).duration(800).style("opacity",.8),a.append("text").attr("transform",t=>{const e=(t.startAngle+t.endAngle)/2,a=this.outerRadius+20;return`translate(${Math.cos(e-Math.PI/2)*a},${Math.sin(e-Math.PI/2)*a})`}).attr("text-anchor",t=>(t.startAngle+t.endAngle)/2>Math.PI?"end":"start").attr("font-size","11px").attr("font-weight","bold").attr("fill","#1e293b").style("opacity",0).text((t,e)=>this.processedData.labels[e]).transition().delay((t,e)=>e*this.options.groupAnimationDelay+400).duration(600).style("opacity",1),a}renderChords(t){const e=i.ribbon().radius(this.innerRadius),a=this.chartGroup.selectAll(".chord-path").data(t).enter().append("path").attr("class","chord-path").attr("fill",t=>this.colors[t.source.index]).attr("stroke",t=>this.colors[t.source.index]).attr("stroke-width",1).attr("opacity",.6).attr("d",e).style("opacity",0).style("filter","drop-shadow(0 2px 4px rgba(0,0,0,0.2))");return a.transition().delay(this.options.chordAnimationDelay).duration(this.options.animationDuration).style("opacity",.6),a}addInteractions(t,e){if(!this.options.showTooltip)return;const a=this;t.on("mouseover",function(t,i){const r=i.index;e.style("opacity",t=>t.source.index===r||t.target.index===r?.8:.1),a.showTooltip(t,i)}).on("mouseout",function(){e.style("opacity",.6),a.hideTooltip()})}showTooltip(t,e){const a=this.chartGroup.append("g").attr("class","chord-tooltip"),i=e.value,r=this.formatCurrency(i),o=this.getTextBBox(r,"11px");a.append("rect").attr("x",-o.width/2-5).attr("y",-o.height/2-2).attr("width",o.width+10).attr("height",o.height+4).attr("fill","rgba(0,0,0,0.8)").attr("rx",4),a.append("text").attr("text-anchor","middle").attr("dy","0.35em").attr("fill","white").attr("font-size","11px").text(r)}hideTooltip(){this.chartGroup.selectAll(".chord-tooltip").remove()}renderCenterInfo(){if(!this.options.showCenterInfo)return;const t=this.chartGroup.append("g").attr("class","center-info");t.append("text").attr("text-anchor","middle").attr("dy","-0.5em").attr("font-size","14px").attr("font-weight","bold").attr("fill","#1e293b").text(this.options.title),t.append("text").attr("text-anchor","middle").attr("dy","1em").attr("font-size","10px").attr("fill",this.options.mutedColor).text("Component Interactions");this.chartGroup.append("g").attr("class","summary-info").attr("transform",`translate(0, ${this.outerRadius+60})`).append("text").attr("text-anchor","middle").attr("font-size","12px").attr("font-weight","600").attr("fill",this.options.primaryColor).text(`Total Flow: ${this.formatCurrency(this.processedData.totalFlow)}`)}formatCurrency(t){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:0,maximumFractionDigits:0}).format(t)}getTextBBox(t,e){const a=this.svg.append("text").attr("font-size",e).text(t).style("opacity",0),i=a.node().getBBox();return a.remove(),i}clear(){this.svg&&this.svg.selectAll(".chord-diagram-chart").remove()}render(){if(!this.data)return console.warn("ChordDiagramChart: No data to render"),this;if(this.clear(),this.processedData=this.processData(this.data),!this.processedData.matrix||0===this.processedData.matrix.length)return console.warn("ChordDiagramChart: No valid matrix data found"),this;this.outerRadius=this.options.outerRadius||.4*Math.min(this.innerWidth,this.innerHeight),this.innerRadius=this.options.innerRadius||this.outerRadius-30,this.chartGroup=this.svg.append("g").attr("class","chord-diagram-chart").attr("transform",`translate(${this.options.margin.left+this.innerWidth/2}, ${this.options.margin.top+this.innerHeight/2})`),this.createGradients();const t=i.chord().padAngle(this.options.padAngle).sortSubgroups(i.descending)(this.processedData.matrix),e=this.renderGroups(t),a=this.renderChords(t);return this.addInteractions(e,a),this.renderCenterInfo(),this}updateData(t){return this.setData(t),this.render(),this}static fromEconomicData(t){return t&&t.economicSchedule?{data:t}:(console.warn("ChordDiagramChart: Invalid economic data format"),{})}},t.ColorUtils=n,t.DOMUtils=c,t.DataUtils=s,t.DonutChart=class extends o{constructor(t,e={}){super(t,{innerRadius:.5,showCenterText:!0,centerText:"",centerTextSize:"24px",centerTextColor:"#333",...e})}render(){if(!this.data||0===this.data.length)return console.warn("No data provided for DonutChart"),this;const t=this.options.outerRadius||Math.min(this.innerWidth,this.innerHeight)/2-10;return"number"==typeof this.options.innerRadius&&this.options.innerRadius<1&&(this.options.innerRadius=t*this.options.innerRadius),super.render(),this.options.showCenterText&&this.addCenterText(),this}addCenterText(){this.innerWidth,this.innerHeight;const t=this.chartGroup.select("g").append("g").attr("class","center-text"),e=this.options.centerText||this.calculateTotal();t.append("text").attr("class","center-main-text").attr("text-anchor","middle").attr("alignment-baseline","middle").style("font-size",this.options.centerTextSize).style("font-weight","bold").style("fill",this.options.centerTextColor).text(e),this.options.centerSubtext&&t.append("text").attr("class","center-sub-text").attr("text-anchor","middle").attr("alignment-baseline","middle").attr("dy","1.5em").style("font-size","14px").style("fill","#666").text(this.options.centerSubtext)}calculateTotal(){return i.sum(this.data,t=>t.value)}updateCenterText(t,e=null){const a=this.chartGroup.select(".center-text");if(!a.empty()&&(a.select(".center-main-text").text(t),null!==e)){let t=a.select(".center-sub-text");t.empty()&&(t=a.append("text").attr("class","center-sub-text").attr("text-anchor","middle").attr("alignment-baseline","middle").attr("dy","1.5em").style("font-size","14px").style("fill","#666")),t.text(e)}return this}renderProgress(t,e,a={}){const i={progressColor:"#3498db",remainingColor:"#ecf0f1",showPercentage:!0,...a},r=t/e*100,o=e-t,s=[{label:"Progress",value:t,color:i.progressColor},{label:"Remaining",value:o,color:i.remainingColor}];return this.setData(s),this.options.colors=[i.progressColor,i.remainingColor],this.options.showLabels=!1,this.render(),i.showPercentage&&this.updateCenterText(`${r.toFixed(1)}%`,"Complete"),this}animateProgress(t,e,a=2e3,i={}){const r={progressColor:"#3498db",remainingColor:"#ecf0f1",...i};this.renderProgress(0,e,r);const o=this,s=Date.now();return requestAnimationFrame(function i(){const n=Date.now()-s,l=Math.min(n/a,1),h=t*l;o.renderProgress(h,e,r),l<1&&requestAnimationFrame(i)}),this}addDonutInteractivity(){const t=this;return this.chartGroup.selectAll(".slice path").on("mouseover",function(e,a){i.select(this).transition().duration(200).style("opacity",.8);const r=((a.endAngle-a.startAngle)/(2*Math.PI)*100).toFixed(1);t.updateCenterText(a.data.value,`${a.data.label} (${r}%)`);const o=`${a.data.label}: ${a.data.value} (${r}%)`;t.showTooltip(o,e)}).on("mouseout",function(e,a){i.select(this).transition().duration(200).style("opacity",1);const r=t.options.centerText||t.calculateTotal();t.updateCenterText(r,t.options.centerSubtext),t.hideTooltip()}),this}renderMultiLevel(t,e){this.chartGroup.selectAll("*").remove();const a=this.innerWidth/2,i=this.innerHeight/2,r=Math.min(this.innerWidth,this.innerHeight)/2-10,o=this.chartGroup.append("g").attr("transform",`translate(${a}, ${i})`);return this.renderDonutLevel(o,t,.3*r,.6*r,"inner"),this.renderDonutLevel(o,e,.7*r,r,"outer"),this}renderDonutLevel(t,e,a,r,o){const s=i.pie().value(t=>t.value).sort(null),n=i.arc().innerRadius(a).outerRadius(r),l=i.scaleOrdinal(i.schemeCategory10);return t.selectAll(`.${o}-slice`).data(s(e)).enter().append("g").attr("class",`${o}-slice`).append("path").attr("fill",(t,e)=>l(e)).attr("stroke","#fff").attr("stroke-width",2).attr("d",n).each(function(t){this._current={startAngle:0,endAngle:0}}).transition().duration(1e3).attrTween("d",function(t){const e=i.interpolate(this._current,t);return this._current=e(0),function(t){return n(e(t))}}),this}},t.FlowContainersChart=class extends r{constructor(t,e={}){super(t,{width:800,height:600,margin:{top:60,right:40,bottom:60,left:40},containerWidth:120,containerHeight:200,containerSpacing:180,animationDuration:1e3,animationDelay:100,maxDollarSymbols:12,particleCount:10,sparkleCount:20,colors:["#10b981","#8b5cf6","#f59e0b","#ef4444","#06b6d4"],showSparkles:!0,showParticles:!0,showYearLabels:!0,autoPlay:!1,...e}),this.addTooltip(),this.colorScale=i.scaleOrdinal(this.options.colors),this.isAnimating=!1,this.currentYear=0,this.showTotals=!1,this.containers=[{key:"primaryValue",label:"Primary",icon:"💰",color:this.colorScale(0)},{key:"secondaryValue",label:"Secondary",icon:"📈",color:this.colorScale(1)},{key:"tertiaryValue",label:"Tertiary",icon:"💵",color:this.colorScale(2)},{key:"distributionValue",label:"Distribution",icon:"📤",color:this.colorScale(3)},{key:"remainderValue",label:"Remainder",icon:"💎",color:this.colorScale(4)}]}processData(t){if(t?.containers)return t.containers.slice(0,10).map((t,e)=>({year:t.year||e+1,primaryValue:Math.abs(.4*t.amount)||0,secondaryValue:Math.abs(.3*t.amount)||0,tertiaryValue:Math.abs(.2*t.amount)||0,distributionValue:Math.abs(.1*t.amount)||0,remainderValue:Math.abs(.05*t.amount)||0,totalValue:Math.abs(t.amount)||0,fillPercentage:t.fillPercentage||.5,label:t.label||`Year ${t.year||e+1}`}));if(t?.economicSchedule){return t.economicSchedule.slice(0,10).map((t,e)=>({year:e+1,primaryValue:Math.abs(.4*t.remainder)||0,secondaryValue:Math.abs(.3*t.remainder)||0,tertiaryValue:Math.abs(.2*t.remainder)||0,distributionValue:Math.abs(t.distribution)||0,remainderValue:Math.abs(.1*t.remainder)||0,totalValue:Math.abs(t.remainder)||0,fillPercentage:.5,label:`Year ${e+1}`}))}return[]}createDefsAndFilters(){const t=this.svg.append("defs");this.containers.forEach(e=>{const a=t.append("linearGradient").attr("id",`gradient-${e.key}`).attr("x1","0%").attr("y1","0%").attr("x2","0%").attr("y2","100%");a.append("stop").attr("offset","0%").attr("stop-color",i.color(e.color)?.brighter(.5)?.toString()||e.color).attr("stop-opacity",.9),a.append("stop").attr("offset","100%").attr("stop-color",e.color).attr("stop-opacity",.7)});const e=t.append("filter").attr("id","glow").attr("x","-50%").attr("y","-50%").attr("width","200%").attr("height","200%");e.append("feGaussianBlur").attr("stdDeviation","3").attr("result","coloredBlur");const a=e.append("feMerge");return a.append("feMergeNode").attr("in","coloredBlur"),a.append("feMergeNode").attr("in","SourceGraphic"),t}createSparkles(t){if(!this.options.showSparkles)return;const e=t.append("g").attr("class","sparkles"),{width:a,height:r}=this.options;for(let t=0;t<this.options.sparkleCount;t++)e.append("circle").attr("cx",Math.random()*a).attr("cy",Math.random()*r).attr("r",3*Math.random()+1).attr("fill","#fbbf24").attr("opacity",.5*Math.random()+.2).attr("filter","url(#glow)").transition().duration(2e3+3e3*Math.random()).ease(i.easeSinInOut).attr("cy",Math.random()*r).attr("opacity",.3*Math.random()+.1).on("end",function t(){i.select(this).transition().duration(2e3+3e3*Math.random()).ease(i.easeSinInOut).attr("cy",Math.random()*r).attr("opacity",.5*Math.random()+.2).on("end",t)})}createContainers(t,e){const a=(this.options.width-(this.containers.length*this.options.containerSpacing-(this.options.containerSpacing-this.options.containerWidth)))/2,i=this.containers.map(t=>e.reduce((e,a)=>e+Math.abs(a[t.key]||0),0)),r=t.selectAll(".container-group").data(this.containers).enter().append("g").attr("class","container-group").attr("transform",(t,e)=>`translate(${a+e*this.options.containerSpacing}, 200)`);return r.append("path").attr("class","container-outline").attr("d",()=>{const t=.8*this.options.containerWidth,e=this.options.containerWidth,a=this.options.containerHeight;return`M ${(this.options.containerWidth-t)/2} 0 L ${(this.options.containerWidth+t)/2} 0 L ${e} ${a} L 0 ${a} Z`}).attr("fill","none").attr("stroke",t=>t.color).attr("stroke-width",3).attr("stroke-opacity",.6).attr("rx",5),r.append("text").attr("class","container-label").attr("x",this.options.containerWidth/2).attr("y",-15).attr("text-anchor","middle").attr("font-size","14px").attr("font-weight","bold").attr("fill",t=>t.color).text(t=>`${t.icon} ${t.label}`),r.append("text").attr("class","value-display").attr("x",this.options.containerWidth/2).attr("y",this.options.containerHeight+25).attr("text-anchor","middle").attr("font-size","12px").attr("font-weight","bold").attr("fill","#374151").text("$0"),r.append("g").attr("class","dollar-container"),r.append("g").attr("class","year-lines"),r.append("g").attr("class","dollar-particles"),r.append("rect").attr("class","amount-bg").attr("x",-10).attr("y",this.options.containerHeight+10).attr("width",this.options.containerWidth+20).attr("height",30).attr("rx",15).attr("fill",t=>t.color).attr("opacity",.2).attr("filter","url(#glow)"),r.append("line").attr("class","fill-level-indicator").attr("x1",-5).attr("x2",this.options.containerWidth+5).attr("y1",this.options.containerHeight).attr("y2",this.options.containerHeight).attr("stroke",t=>t.color).attr("stroke-width",3).attr("stroke-dasharray","8,4").attr("opacity",0).attr("filter","url(#glow)"),this.initializeFillElements(r),{containerGroups:r,maxValues:i}}initializeFillElements(t){t.each((e,a)=>{const r=i.select(t.nodes()[a]),o=this.containers[a];r.append("rect").attr("class","fill-background").attr("x",8).attr("width",this.options.containerWidth-16).attr("y",this.options.containerHeight).attr("height",0).attr("fill",o.color).attr("opacity",.15).attr("rx",5),r.append("ellipse").attr("class","liquid-surface").attr("cx",this.options.containerWidth/2).attr("cy",this.options.containerHeight).attr("rx",(this.options.containerWidth-16)/2).attr("ry",3).attr("fill",o.color).attr("opacity",0).attr("filter","url(#glow)");for(let t=0;t<3;t++)r.append("circle").attr("class",`bubble-${t}`).attr("cx",this.options.containerWidth/2+40*(Math.random()-.5)).attr("cy",this.options.containerHeight).attr("r",1).attr("fill",o.color).attr("opacity",0).attr("filter","url(#glow)")})}animateYear(t,e,a,r,o){if(t>=e.length)return this.showTotals=!0,this.isAnimating=!1,void this._showTotalValuesInternal(e,a,r);const s=e[t];this.containers.forEach((o,n)=>{if(!o||!o.key)return;const l=e.slice(0,t+1).reduce((t,e)=>t+Math.abs(e&&e[o.key]||0),0),h=r&&r[n]?r[n]:1,c=h>0?l/h*this.options.containerHeight*.8:0,d=Math.abs(s&&s[o.key]||0),p=Math.min(Math.floor(c/15),this.options.maxDollarSymbols),u=i.select(a.nodes()[n]);u.empty()||(this.updateContainerFill(u,o,c,d,t),this.createDollarSymbols(u,o,p,d),this.createFlowingParticles(u,o,d,c,p),this.updateValueDisplay(u,l))}),this.updateYearIndicator(o,s.year);const n=this.containers.reduce((t,e)=>t+Math.abs(s[e.key]||0),0)>0?this.options.animationDuration+1e3:500;i.timeout(()=>{this.isAnimating&&this.animateYear(t+1,e,a,r,o)},n)}updateContainerFill(t,e,a,r,o){const s=t.select(".year-lines");s.append("line").attr("x1",10).attr("x2",this.options.containerWidth-10).attr("y1",this.options.containerHeight-a).attr("y2",this.options.containerHeight-a).attr("stroke",e.color).attr("stroke-width",2).attr("opacity",0).transition().duration(500).attr("opacity",r>0?.4:0),this.options.showYearLabels&&s.append("text").attr("x",this.options.containerWidth+15).attr("y",this.options.containerHeight-a+5).attr("font-siz