bubble-chart-js 1.0.19 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/bubbleChart.cjs.js +1 -1
  2. package/dist/bubbleChart.esm.js +1 -1
  3. package/dist/bubbleChart.umd.js +1 -1
  4. package/examples/test.html +194 -0
  5. package/package.json +6 -3
  6. package/scripts/generate-fixtures.ts +45 -0
  7. package/spec/config-defaults.json +16 -0
  8. package/spec/fixtures/3-bubbles.input.json +10 -0
  9. package/spec/fixtures/equal-values.input.json +11 -0
  10. package/spec/fixtures/many-bubbles.input.json +17 -0
  11. package/spec/fixtures/single-bubble.input.json +8 -0
  12. package/spec/physics.json +11 -0
  13. package/dist/canvas.d.ts +0 -5
  14. package/dist/constants/app-constants.d.ts +0 -3
  15. package/dist/constants/physics.d.ts +0 -10
  16. package/dist/core/renderer.d.ts +0 -2
  17. package/dist/features/text-wrapper.d.ts +0 -2
  18. package/dist/features/tooltip.d.ts +0 -6
  19. package/dist/index.d.ts +0 -8
  20. package/dist/models/internal/data-item-info.d.ts +0 -7
  21. package/dist/models/public/bubble-chart.d.ts +0 -6
  22. package/dist/models/public/config/bubble-appearance.d.ts +0 -26
  23. package/dist/models/public/config/font-options.d.ts +0 -46
  24. package/dist/models/public/config/interaction-options.d.ts +0 -6
  25. package/dist/models/public/config/tooltip-config.d.ts +0 -4
  26. package/dist/models/public/config/tooltip-options.d.ts +0 -170
  27. package/dist/models/public/configuration.d.ts +0 -30
  28. package/dist/models/public/data-item.d.ts +0 -8
  29. package/dist/services/chart-service.d.ts +0 -5
  30. package/dist/services/render-service.d.ts +0 -3
  31. package/dist/utils/config.d.ts +0 -12
  32. package/dist/utils/helper.d.ts +0 -2
  33. package/dist/utils/validation.d.ts +0 -5
@@ -1 +1 @@
1
- (()=>{"use strict";var t={d:(e,n)=>{for(var o in n)t.o(n,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:n[o]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{BubbleChart:()=>h,initializeChart:()=>c});let n="default";function o(t,e){if(!e)return console.error("Invalid containerId."),null;const n=document.getElementById(e);if(!n)return console.error("Container not found."),null;const o=n.parentElement;return o?o.querySelector("#bubbleChartTooltip")||(o.prepend(t),t):(console.error("Parent container not found."),null)}function i(t,e){const n=e.getBoundingClientRect();return{mouseX:t.clientX-n.left,mouseY:t.clientY-n.top}}function a(t,e,n){return n.find(n=>Math.hypot(t-n.x,e-n.y)<n.radius)||null}class r{}r.TRANSPARENT="transparent";const l={forceStrength:.008,iterations:1e3,damping:.65,boundaryForce:.02,centerForce:.12,centerAttraction:.8,centerDamping:.3,centerRadiusBuffer:35};function s(t,e=14,n=400,o=6){const i=n>=700?1.25:n>=500?1.1:1,a=Math.min(t/o,t/1.2);let r=Math.min(e*i,a,.8*t);return r=Math.max(r,Math.max(8,t/6)),Math.round(r)}function d(t){if(!function(t){return t?!(!Array.isArray(t.data)||0===t.data.length)||(console.error("Invalid or empty data array"),!1):(console.error("Invalid config object"),!1)}(t))return;let e=function(t){var e,n;const o=document.getElementById(t.canvasContainerId);if(!o)return console.error(`Canvas container with ID '${t.canvasContainerId}' not found.`),null;if(o.querySelector("canvas"))return console.error("A canvas already exists inside the container."),null;const i=document.createElement("canvas");return Object.assign(i.style,{border:(null===(e=t.canvasBorderColor)||void 0===e?void 0:e.trim())?`1px solid #${t.canvasBorderColor}`:r.TRANSPARENT,background:(null===(n=t.canvasBackgroundColor)||void 0===n?void 0:n.trim())?`#${t.canvasBackgroundColor}`:r.TRANSPARENT,width:"100%",height:"100%",display:"block",imageRendering:"crisp-edges",aspectRatio:"1 / 1"}),i.style.setProperty("image-rendering","-moz-crisp-edges"),i.style.setProperty("image-rendering","-webkit-optimize-contrast"),i.style.setProperty("-ms-interpolation-mode","nearest-neighbor"),o.appendChild(i),i}(t);if(!e)return;const d=e.getContext("2d");if(!d)return void console.error("Invalid context");const{width:u,height:c}=m(e,d),h=function(t,e,n){const o=Math.min((e-10)/2,(n-10)/2),i=e/2,a=n/2,r=[...t.data].sort((t,e)=>e.value-t.value).map(t=>Object.assign(Object.assign({},t),{radius:0,x:0,y:0,fixed:!1})),s=r[0].value,d=Math.min(.5*o,.2*Math.min(e,n)),u=Math.max(.3*d,.05*Math.min(e,n));r.forEach(t=>{const o=t.value/s;t.radius=u+o*(d-u),t.radius=Math.min(t.radius,(e-10)/2,(n-10)/2)}),r.forEach((t,o)=>{if(0===o)t.x=i,t.y=a,t.fixed=!0;else{const l=r[0].radius+t.radius+3,s=Math.PI*(3-Math.sqrt(5)),d=e-5-t.radius,u=n-5-t.radius;t.x=Math.min(d,Math.max(5+t.radius,i+Math.cos(s*o)*l)),t.y=Math.min(u,Math.max(5+t.radius,a+Math.sin(s*o)*l)),t.fixed=!1}});for(let t=0;t<l.iterations;t++)r.forEach((t,n)=>{if(0===n){const e=i-t.x,n=a-t.y;return void(Math.hypot(e,n)>2&&(t.x+=e*l.centerDamping,t.y+=n*l.centerDamping))}let o=0,d=0;const u=t.radius+5;t.x<u?o+=(u-t.x)*l.boundaryForce:t.x>e-u&&(o+=(e-u-t.x)*l.boundaryForce),r.forEach(e=>{if(t===e)return;const n=t.x-e.x,r=t.y-e.y,u=Math.hypot(n,r),c=t.radius+e.radius;if(u<1.5*c){const t=l.forceStrength*(c/Math.max(u,.1));o+=n/u*t,d+=r/u*t}const h=i-t.x,f=a-t.y,m=Math.hypot(h,f),y=t.value/s*.02;t.x+=h/m*y,t.y+=f/m*y});const c=i-t.x,h=a-t.y,f=Math.hypot(c,h),m=r[0].radius+t.radius+l.centerRadiusBuffer,y=(l.centerForce,Math.pow(t.value/s,.3),l.centerAttraction*(1-t.value/s)*(1-Math.min(1,f/m)));t.x+=c*y,t.y+=h*y,t.x+=o*(1-l.damping),t.y+=d*(1-l.damping)}),r.forEach((t,e)=>{r.forEach((n,o)=>{if(e>=o)return;if(0===e||0===o){const o=0===e?t:n,i=0===e?n:t,a=i.x-o.x,r=i.y-o.y,l=Math.hypot(a,r),s=o.radius+i.radius+2;if(l<s){const t=s-l,e=Math.atan2(r,a);i.x+=Math.cos(e)*t*.7,i.y+=Math.sin(e)*t*.7}return}const i=t.x-n.x,a=t.y-n.y,r=Math.hypot(i,a),s=t.radius+n.radius-5;if(r<s){const e=(s-r)*(.3+5*l.forceStrength),o=Math.atan2(a,i),d=n.radius/(t.radius+n.radius);t.fixed||(t.x+=Math.cos(o)*e*d,t.y+=Math.sin(o)*e*d),n.fixed||(n.x-=Math.cos(o)*e*(1-d),n.y-=Math.sin(o)*e*(1-d))}})});return r.forEach(t=>{const o=Math.max(5+t.radius,Math.min(e-5-t.radius,t.x)),i=Math.max(5+t.radius,Math.min(n-5-t.radius,t.y));(!t.fixed||Math.hypot(t.x-o,t.y-i)>2)&&(t.x=o,t.y=i)}),r}(t,u,c);function f(){e&&d?(m(e,d),d.clearRect(0,0,e.width,e.height),h.forEach(e=>{const{x:n,y:o,radius:i,bubbleColor:a,borderColor:r,borderThickness:l,opacity:u,fontColor:c,fontFamily:h,fontSize:f,fontStyle:m,fontWeight:y,textAlign:v,textTransform:g,textBaseline:p}=function(t,e){var n,o,i,a,r,l,d,u,c,h,f,m;return{x:t.x,y:t.y,radius:Math.max(t.radius||0,e.minRadius||10),bubbleColor:null!==(o=null!==(n=t.bubbleColor)&&void 0!==n?n:e.defaultBubbleColor)&&void 0!==o?o:"#3498db",borderColor:null!==(i=t.borderColor)&&void 0!==i?i:"black",borderThickness:Math.max(null!==(a=t.borderThickness)&&void 0!==a?a:.25,0),opacity:void 0!==t.opacity?Math.max(0,Math.min(1,t.opacity)):1,fontStyle:t.fontStyle||"normal",fontWeight:"number"==typeof t.fontWeight&&t.fontWeight>=100&&t.fontWeight<=900?t.fontWeight:400,textAlign:null!==(r=t.textAlign)&&void 0!==r?r:"center",textTransform:null!==(l=t.textTransform)&&void 0!==l?l:"none",fontColor:null!==(u=null!==(d=t.fontColor)&&void 0!==d?d:e.defaultFontColor)&&void 0!==u?u:"#000",textBaseline:null!==(c=t.textBaseline)&&void 0!==c?c:"middle",fontSize:Math.max(s(t.radius||e.minRadius||10,null!==(h=e.fontSize)&&void 0!==h?h:14,null!==(f=t.fontWeight)&&void 0!==f?f:400),8),fontFamily:t.fontFamily&&"string"==typeof t.fontFamily&&"Arial"!==t.fontFamily?`${t.fontFamily}, Arial, sans-serif`:`${null!==(m=e.defaultFontFamily)&&void 0!==m?m:"Arial"}, sans-serif`}}(e,t);d.beginPath(),d.arc(n,o,i,0,2*Math.PI),d.fillStyle=a,d.fill(),d.strokeStyle=r,d.lineWidth=l,d.stroke();const x=`${m} ${y} ${f}px ${h}`;d.fillStyle=c,d.font=x,d.imageSmoothingEnabled=!0,d.imageSmoothingQuality="high",d.textAlign=v,d.textBaseline=p;let b=e.label||"";if("uppercase"===g?b=b.toUpperCase():"lowercase"===g?b=b.toLowerCase():"capitalize"===g&&(b=b.replace(/\b\w/g,t=>t.toUpperCase())),t.textWrap){const a=1.5*i-10,r=1.4*f,l=function(t,e,n,o,i,a=14,r=400,l="normal",s="Arial",d=0,u=5,c=1.2){const h=1.5*(i-u),f=a*c,m=Math.max(1,Math.floor(h/f)),y="auto"===o||void 0===o?m:Math.min(o,m);n=Math.max(0,n-2*d);const v=e.split(" ");let g="";const p=[];let x=!1,b=!1;t.font=`${r||""} ${l||""} ${a}px ${s}`,t.imageSmoothingEnabled=!0,t.imageSmoothingQuality="high";for(const e of v){const o=g?`${g} ${e}`:e;if(t.measureText(o).width<=n)g=o;else if(g.trim()&&p.push(g),g=e,t.measureText(g).width>n){let e=g;for(;t.measureText(e+"...").width>n&&e.length>0;)e=e.slice(0,-1);p.push(e+"..."),b=!0;break}if(p.length>=y){x=!0;break}}if(g&&p.length<y&&!b&&p.push(g),x&&p.length>0){let e=p[p.length-1];for(;t.measureText(e+"...").width>n&&e.length>0;)e=e.slice(0,-1);p[p.length-1]=e+"..."}return p}(d,e.label,a,t.maxLines,i,f,y,m,h),s=o-(l.length-1)*r/2;l.forEach((t,e)=>{const o=Math.round(n),i=Math.round(s+e*r);d.fillText(t,o,i)})}else d.fillText(e.label,Math.round(n),Math.round(o))})):console.warn("canvas or ctx is not valid")}function m(t,e){const n=window.devicePixelRatio||1,o=t.getBoundingClientRect();return t.width=o.width*n,t.height=o.height*n,t.style.width=`${o.width}px`,t.style.height=`${o.height}px`,e.setTransform(1,0,0,1,0,0),e.scale(n,n),{width:o.width,height:o.height,dpr:n}}function y(){const n=document.getElementById(t.canvasContainerId);n&&e&&(e.width=n.offsetWidth,e.height=n.offsetHeight,e.getContext("2d"),f())}let v;t.isResizeCanvasOnWindowSizeChange&&(y(),window.addEventListener("resize",y)),f(),t.showToolTip&&(v=function(t){var e,n,i,a,r,l,s,d,u,c,h,f,m,y,v,g,p,x;const b=null===(n=null===(e=t.data[0].toolTipConfig)||void 0===e?void 0:e.tooltipFormattedData)||void 0===n?void 0:n.trim();if(b){const e=document.createElement("div");e.innerHTML=b.trim();const n=e.firstElementChild;return n.style.display="none",n.style.visibility="hidden",n.style.opacity="0",n.style.position="absolute",o(n,t.canvasContainerId)}const M=document.createElement("div");M.id="bubbleChartTooltip",M.style.display="none";const C=null!==(i=null==t?void 0:t.tooltipOptions)&&void 0!==i?i:{},S=(t,e)=>"number"==typeof t?`${t}px`:null!=t?t:e;return Object.assign(M.style,{position:"absolute",padding:S(C.padding,"8px"),margin:S(C.margin,"0"),background:null!==(a=C.backgroundColor)&&void 0!==a?a:"rgba(0, 0, 0, 0.85)",color:null!==(r=C.fontColor)&&void 0!==r?r:"white",borderRadius:"4px",pointerEvents:null!==(l=C.pointerEvents)&&void 0!==l?l:"none",fontFamily:null!==(s=C.fontFamily)&&void 0!==s?s:"Arial, sans-serif",fontSize:S(C.fontSize,"14px"),fontWeight:String(null!==(d=C.fontWeight)&&void 0!==d?d:"400"),fontStyle:null!==(u=C.fontStyle)&&void 0!==u?u:"normal",textAlign:null!==(c=C.textAlign)&&void 0!==c?c:"left",textDecoration:null!==(h=C.textDecoration)&&void 0!==h?h:"none",textTransform:null!==(f=C.textTransform)&&void 0!==f?f:"none",letterSpacing:S(C.letterSpacing,"normal"),border:(()=>{var t;if(!C.borderStyle)return"none";const e=S(C.borderWidth,"1px"),n=null!==(t=C.borderColor)&&void 0!==t?t:"transparent";return`${e} ${C.borderStyle} ${n}`})(),boxShadow:null!==(m=C.boxShadow)&&void 0!==m?m:"none",maxWidth:S(C.maxWidth,"200px"),minWidth:S(C.minWidth,"auto"),maxHeight:S(C.maxHeight,"none"),minHeight:S(C.minHeight,"auto"),zIndex:String(null!==(y=C.zIndex)&&void 0!==y?y:1e3),transition:null!==(v=C.transition)&&void 0!==v?v:"opacity 0.2s",transform:null!==(g=C.transform)&&void 0!==g?g:"none",backdropFilter:null!==(p=C.backdropFilter)&&void 0!==p?p:"none",opacity:String(null!==(x=C.opacity)&&void 0!==x?x:1),display:"none",visibility:"hidden"}),o(M,t.canvasContainerId),M}(t));let g=null;if(e.addEventListener("mousemove",o=>{g||(g=requestAnimationFrame(()=>{(function(t,e,o,r,l){const{mouseX:s,mouseY:d}=i(t,o),u=a(s,d,e);n=(null==l?void 0:l.cursorType)||"pointer",o.style.cursor="default",r&&(u?function(t,e,o,i){if(e&&e.value&&o&&i){o.style.cursor=n,i.style.display="block",i.innerHTML=function(t){var e,n,o;if(!t)return"";const i=null===(n=null===(e=t.toolTipConfig)||void 0===e?void 0:e.tooltipText)||void 0===n?void 0:n.trim();if(i)return`<div>${i}</div>`;const a=null===(o=t.label)||void 0===o?void 0:o.trim();return a?`<div>${a}<br>Value: ${t.value}</div>`:`<div>${t.value}</div>`}(e);const a=o.getBoundingClientRect();i.style.left=t.clientX-a.left+15+"px",i.style.top=t.clientY-a.top+15+"px",i.style.zIndex="999999",i.style.visibility="visible",i.style.opacity="1",i.style.position="absolute"}}(t,u,o,r):(o.style.cursor="default",r.style.display="none",r.style.visibility="hidden",r.style.opacity="0"))})(o,h,e,v,t),g=null}))}),t.onBubbleClick){let n=null;e.addEventListener("click",o=>{n||(n=requestAnimationFrame(()=>{!function(t,e,n,o){const{mouseX:r,mouseY:l}=i(t,n),s=a(r,l,e);null!=s&&o.onBubbleClick&&o.onBubbleClick(s,t)}(o,h,e,t),n=null}))})}}const u={defaultBubbleColor:"#3498DB",defaultFontColor:"#ffffff",minRadius:10,maxLines:"auto",textWrap:!0,isResizeCanvasOnWindowSizeChange:!0,fontSize:14,defaultFontFamily:"Arial",showToolTip:!0};function c(t={}){var e,n;if(!t)return void console.error("Configuration is not valid. Chart initialization aborted.");if(!t.data||0===t.data.length)return void console.error("No valid data provided. Chart initialization aborted.");const o=(i=Object.assign({canvasContainerId:null!==(e=t.canvasContainerId)&&void 0!==e?e:"chart-container",data:null!==(n=t.data)&&void 0!==n?n:[]},t),Object.assign(Object.assign({},u),i));var i;return d(o),o}class h{constructor(t){const e=c(t);e&&(this.configuration=e)}render(){this.configuration&&d(this.configuration)}}window.initializeChart=c,module.exports=e})();
1
+ (()=>{"use strict";var t={d:(e,n)=>{for(var i in n)t.o(n,i)&&!t.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:n[i]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{BubbleChart:()=>m,initializeChart:()=>v});const n={defaultBubbleColor:"#3498DB",defaultFontColor:"#ffffff",minRadius:10,maxLines:"auto",textWrap:!0,isResizeCanvasOnWindowSizeChange:!0,fontSize:14,defaultFontFamily:"Arial",showToolTip:!0},i=JSON.parse('{"FC":0.008,"rX":1000,"d6":0.65,"WH":0.02,"ND":0.12,"$l":0.8,"cg":0.3,"e0":35}');function o(t,e){t.forEach((n,i)=>{t.forEach((t,o)=>{if(i>=o)return;if(0===i||0===o){const e=0===i?n:t,o=0===i?t:n,a=o.x-e.x,r=o.y-e.y,l=Math.hypot(a,r),s=e.radius+o.radius+2;if(l<s){const t=s-l,e=Math.atan2(r,a);o.x+=Math.cos(e)*t*.7,o.y+=Math.sin(e)*t*.7}return}const a=n.x-t.x,r=n.y-t.y,l=Math.hypot(a,r),s=n.radius+t.radius-5;if(l<s){const i=(s-l)*(.3+5*e.forceStrength),o=Math.atan2(r,a),d=n.radius+t.radius,c=d>0?t.radius/d:.5;n.fixed||(n.x+=Math.cos(o)*i*c,n.y+=Math.sin(o)*i*c),t.fixed||(t.x-=Math.cos(o)*i*(1-c),t.y-=Math.sin(o)*i*(1-c))}})})}function a(t,e=14,n=400,i=6){const o=n>=700?1.25:n>=500?1.1:1,a=Math.min(t/i,t/1.2);let r=Math.min(e*o,a,.8*t);return r=Math.max(r,Math.max(8,t/6)),Math.round(r)}class r{constructor(t){this.canvas=t;const e=t.getContext("2d");if(!e)throw new Error("Failed to get 2D rendering context from canvas");this.ctx=e}getContext(){return this.ctx}getCanvas(){return this.canvas}setup(){const t=window.devicePixelRatio||1,e=this.canvas.getBoundingClientRect();return this.canvas.width=e.width*t,this.canvas.height=e.height*t,this.canvas.style.width=`${e.width}px`,this.canvas.style.height=`${e.height}px`,this.ctx.setTransform(1,0,0,1,0,0),this.ctx.scale(t,t),{width:e.width,height:e.height}}getSize(){const t=this.canvas.getBoundingClientRect();return{width:t.width,height:t.height}}clear(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height)}drawCircle(t,e,n,i,o,a,r){this.ctx.beginPath(),this.ctx.arc(t,e,n,0,2*Math.PI),this.ctx.fillStyle=i,this.ctx.fill(),a>0&&(this.ctx.strokeStyle=o,this.ctx.lineWidth=a,this.ctx.stroke())}drawText(t,e,n,i){const o=`${i.fontStyle} ${i.fontWeight} ${i.fontSize}px ${i.fontFamily}`;this.ctx.fillStyle=i.fontColor,this.ctx.font=o,this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.ctx.textAlign=i.textAlign,this.ctx.textBaseline=i.textBaseline,this.ctx.fillText(t,Math.round(e),Math.round(n))}destroy(){const t=this.canvas.parentElement;t&&t.removeChild(this.canvas)}}class l{constructor(t){this.ctx=t}measureWidth(t,e,n,i,o){return this.ctx.font=`${i} ${n} ${e}px ${o}`,this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.ctx.measureText(t).width}}function s(t,e){const n=`bubbleChartTooltip-${e}`;return document.body.querySelector(`#${n}`)||(t.id=n,document.body.appendChild(t),t)}function d(t,e){const n=e.getBoundingClientRect(),i=window.devicePixelRatio||1;return{mouseX:(t.clientX-n.left)*i,mouseY:(t.clientY-n.top)*i}}function c(t,e,n){return n.find(n=>Math.hypot(t-n.x,e-n.y)<n.radius)||null}function u(t){let e=null;return{handle:n=>{e||(e=requestAnimationFrame(()=>{t(n),e=null}))},cancel:()=>{e&&(cancelAnimationFrame(e),e=null)}}}class h{}function f(t){if(!function(t){return t?!(!Array.isArray(t.data)||0===t.data.length)||(console.error("Invalid or empty data array"),!1):(console.error("Invalid config object"),!1)}(t))return;const e=function(t){var e,n;const i=document.getElementById(t.canvasContainerId);if(!i)return console.error(`Canvas container with ID '${t.canvasContainerId}' not found.`),null;if(i.querySelector("canvas"))return console.error("A canvas already exists inside the container."),null;const o=document.createElement("canvas");return Object.assign(o.style,{border:(null===(e=t.canvasBorderColor)||void 0===e?void 0:e.trim())?`1px solid #${t.canvasBorderColor}`:h.TRANSPARENT,background:(null===(n=t.canvasBackgroundColor)||void 0===n?void 0:n.trim())?`#${t.canvasBackgroundColor}`:h.TRANSPARENT,width:"100%",height:"100%",display:"block",imageRendering:"crisp-edges",aspectRatio:"1 / 1"}),o.style.setProperty("image-rendering","-moz-crisp-edges"),o.style.setProperty("image-rendering","-webkit-optimize-contrast"),o.style.setProperty("-ms-interpolation-mode","nearest-neighbor"),i.appendChild(o),o}(t);if(!e)return;const n=new r(e),m=new l(n.getContext()),{width:v,height:y}=n.setup();let x=function(t,e,n,a){const r=Object.assign({forceStrength:i.FC,iterations:i.rX,damping:i.d6,boundaryForce:i.WH,centerForce:i.ND,centerAttraction:i.$l,centerDamping:i.cg,centerRadiusBuffer:i.e0},a),l=Math.min((e-10)/2,(n-10)/2),s=e/2,d=n/2,c=[...t].sort((t,e)=>e.value-t.value).map(t=>Object.assign(Object.assign({},t),{radius:0,x:0,y:0,fixed:!1}));if(0===c.length)return c;const u=c[0].value,h=Math.min(.5*l,.2*Math.min(e,n)),f=Math.max(.3*h,.05*Math.min(e,n));return c.forEach(t=>{const i=u>0?t.value/u:1;t.radius=f+i*(h-f),t.radius=Math.max(0,Math.min(t.radius,(e-10)/2,(n-10)/2))}),c.forEach((t,i)=>{if(0===i)t.x=s,t.y=d,t.fixed=!0;else{const o=c[0].radius+t.radius+3,a=Math.PI*(3-Math.sqrt(5)),r=e-5-t.radius,l=n-5-t.radius;t.x=Math.min(r,Math.max(5+t.radius,s+Math.cos(a*i)*o)),t.y=Math.min(l,Math.max(5+t.radius,d+Math.sin(a*i)*o)),t.fixed=!1}}),function(t,e,n,i,a,r,l){for(let i=0;i<e.iterations;i++)t.forEach((i,o)=>{if(0===o){const t=a-i.x,n=r-i.y;return void(Math.hypot(t,n)>2&&(i.x+=t*e.centerDamping,i.y+=n*e.centerDamping))}let s=0,d=0;const c=i.radius+5;i.x<c?s+=(c-i.x)*e.boundaryForce:i.x>n-c&&(s+=(n-c-i.x)*e.boundaryForce),t.forEach(t=>{if(i===t)return;const n=i.x-t.x,o=i.y-t.y,c=Math.hypot(n,o),u=i.radius+t.radius;if(c<1.5*u){const t=e.forceStrength*(u/Math.max(c,.1));s+=n/c*t,d+=o/c*t}const h=a-i.x,f=r-i.y,m=Math.hypot(h,f),v=i.value/l*.02;i.x+=h/m*v,i.y+=f/m*v});const u=a-i.x,h=r-i.y,f=Math.hypot(u,h),m=t[0].radius+i.radius+e.centerRadiusBuffer,v=e.centerAttraction*(1-i.value/l)*(1-Math.min(1,f/m));i.x+=u*v,i.y+=h*v,i.x+=s*(1-e.damping),i.y+=d*(1-e.damping)}),o(t,e)}(c,r,e,0,s,d,u),function(t,e,n){t.forEach(t=>{const i=Math.max(5+t.radius,Math.min(e-5-t.radius,t.x)),o=Math.max(5+t.radius,Math.min(n-5-t.radius,t.y));(!t.fixed||Math.hypot(t.x-i,t.y-o)>2)&&(t.x=i,t.y=o)})}(c,e,n),c}(t.data,v,y);function g(){n.setup(),n.clear(),x.forEach(e=>{const i=function(t,e,n){var i,o,r,l,s,d,c,u,h,f,m;let v=null!==(i=n.defaultBubbleColor)&&void 0!==i?i:"#3498db";if(t.bubbleColor)v=t.bubbleColor;else if(n.colorPalette&&n.colorPalette.length>0){const i=e.findIndex(e=>e.label===t.label&&e.value===t.value),o=i>=0?i:0;v=n.colorPalette[o%n.colorPalette.length]}const y=Math.max(t.radius||0,n.minRadius||10);return{bubbleColor:v,borderColor:null!==(o=t.borderColor)&&void 0!==o?o:"black",borderThickness:Math.max(null!==(r=t.borderThickness)&&void 0!==r?r:.25,0),opacity:void 0!==t.opacity?Math.max(0,Math.min(1,t.opacity)):1,fontStyle:t.fontStyle||"normal",fontWeight:"number"==typeof t.fontWeight&&t.fontWeight>=100&&t.fontWeight<=900?t.fontWeight:400,textAlign:null!==(l=t.textAlign)&&void 0!==l?l:"center",textTransform:null!==(s=t.textTransform)&&void 0!==s?s:"none",fontColor:null!==(c=null!==(d=t.fontColor)&&void 0!==d?d:n.defaultFontColor)&&void 0!==c?c:"#000",textBaseline:null!==(u=t.textBaseline)&&void 0!==u?u:"middle",fontSize:Math.max(a(y,null!==(h=n.fontSize)&&void 0!==h?h:14,null!==(f=t.fontWeight)&&void 0!==f?f:400),8),fontFamily:t.fontFamily&&"string"==typeof t.fontFamily&&"Arial"!==t.fontFamily?`${t.fontFamily}, Arial, sans-serif`:`${null!==(m=n.defaultFontFamily)&&void 0!==m?m:"Arial"}, sans-serif`}}(e,x,t);n.drawCircle(e.x,e.y,Math.max(e.radius||0,t.minRadius||10),i.bubbleColor,i.borderColor,i.borderThickness,i.opacity);let o=e.label||"";"uppercase"===i.textTransform?o=o.toUpperCase():"lowercase"===i.textTransform?o=o.toLowerCase():"capitalize"===i.textTransform&&(o=o.replace(/\b\w/g,t=>t.toUpperCase()));const r=Math.max(e.radius||0,t.minRadius||10),l={fontSize:i.fontSize,fontFamily:i.fontFamily,fontWeight:i.fontWeight,fontStyle:i.fontStyle,fontColor:i.fontColor,textAlign:i.textAlign,textBaseline:i.textBaseline};if(t.textWrap){const o=1.5*r-10,a=1.4*i.fontSize,s=function(t,e,n,i,o,a=14,r=400,l="normal",s="Arial",d=0,c=5,u=1.2){const h=1.5*(o-c),f=a*u,m=Math.max(1,Math.floor(h/f)),v="auto"===i||void 0===i?m:Math.min(i,m);n=Math.max(0,n-2*d);const y=e.split(" ");let x="";const g=[];let p=!1,b=!1;const C=e=>t.measureWidth(e,a,r,l,s);for(const t of y){const e=x?`${x} ${t}`:t;if(C(e)<=n)x=e;else if(x.trim()&&g.push(x),x=t,C(x)>n){let t=x;for(;C(t+"...")>n&&t.length>0;)t=t.slice(0,-1);g.push(t+"..."),b=!0;break}if(g.length>=v){p=!0;break}}if(x&&g.length<v&&!b&&g.push(x),p&&g.length>0){let t=g[g.length-1];for(;C(t+"...")>n&&t.length>0;)t=t.slice(0,-1);g[g.length-1]=t+"..."}return g}(m,e.label,o,t.maxLines,r,i.fontSize,i.fontWeight,i.fontStyle,i.fontFamily),d=e.y-(s.length-1)*a/2;s.forEach((t,i)=>{n.drawText(t,e.x,d+i*a,l)})}else n.drawText(o,e.x,e.y,l)})}let p=null;if(t.isResizeCanvasOnWindowSizeChange){const e=document.getElementById(t.canvasContainerId);e&&(p=function(t,e){let n=null,i=null;const o=()=>{i||(i=requestAnimationFrame(()=>{e(),i=null}))};return"undefined"!=typeof ResizeObserver?(n=new ResizeObserver(o),n.observe(t)):(o(),window.addEventListener("resize",o)),{destroy:()=>{n&&(n.disconnect(),n=null),window.removeEventListener("resize",o),i&&(cancelAnimationFrame(i),i=null)}}}(e,()=>{const t=n.getCanvas();e&&t&&(t.width=e.offsetWidth,t.height=e.offsetHeight,g())}))}g();let b=null;t.showToolTip&&(b=function(t){var e,n,i,o,a,r,l,d,c,u,h,f,m,v,y,x,g,p,b;const C=null===(i=null===(n=null===(e=t.data[0])||void 0===e?void 0:e.toolTipConfig)||void 0===n?void 0:n.tooltipFormattedData)||void 0===i?void 0:i.trim();if(C){const e=document.createElement("div");e.innerHTML=C.trim();const n=e.firstElementChild;return n.style.display="none",n.style.visibility="hidden",n.style.opacity="0",n.style.position="absolute",s(n,t.canvasContainerId)}const M=document.createElement("div");M.style.display="none";const w=null!==(o=null==t?void 0:t.tooltipOptions)&&void 0!==o?o:{},S=(t,e)=>"number"==typeof t?`${t}px`:null!=t?t:e;return Object.assign(M.style,{position:"absolute",padding:S(w.padding,"8px"),margin:S(w.margin,"0"),background:null!==(a=w.backgroundColor)&&void 0!==a?a:"rgba(0, 0, 0, 0.85)",color:null!==(r=w.fontColor)&&void 0!==r?r:"white",borderRadius:"4px",pointerEvents:null!==(l=w.pointerEvents)&&void 0!==l?l:"none",fontFamily:null!==(d=w.fontFamily)&&void 0!==d?d:"Arial, sans-serif",fontSize:S(w.fontSize,"14px"),fontWeight:String(null!==(c=w.fontWeight)&&void 0!==c?c:"400"),fontStyle:null!==(u=w.fontStyle)&&void 0!==u?u:"normal",textAlign:null!==(h=w.textAlign)&&void 0!==h?h:"left",textDecoration:null!==(f=w.textDecoration)&&void 0!==f?f:"none",textTransform:null!==(m=w.textTransform)&&void 0!==m?m:"none",letterSpacing:S(w.letterSpacing,"normal"),border:(()=>{var t;if(!w.borderStyle)return"none";const e=S(w.borderWidth,"1px"),n=null!==(t=w.borderColor)&&void 0!==t?t:"transparent";return`${e} ${w.borderStyle} ${n}`})(),boxShadow:null!==(v=w.boxShadow)&&void 0!==v?v:"none",maxWidth:S(w.maxWidth,"200px"),minWidth:S(w.minWidth,"auto"),maxHeight:S(w.maxHeight,"none"),minHeight:S(w.minHeight,"auto"),zIndex:String(null!==(y=w.zIndex)&&void 0!==y?y:1e3),transition:null!==(x=w.transition)&&void 0!==x?x:"opacity 0.2s",transform:null!==(g=w.transform)&&void 0!==g?g:"none",backdropFilter:null!==(p=w.backdropFilter)&&void 0!==p?p:"none",opacity:String(null!==(b=w.opacity)&&void 0!==b?b:1),display:"none",visibility:"hidden"}),s(M,t.canvasContainerId),M}(t));const C=n.getCanvas(),M=u(e=>{const{mouseX:n,mouseY:i}=d(e,C),o=c(n,i,x);if(o){const n=(null==t?void 0:t.cursorType)||"pointer";if(C.style.cursor=n,b){const n=function(t,e){var n,i,o;if(!t)return"";if(e.tooltipOptions&&"function"==typeof e.tooltipOptions.formatter)return e.tooltipOptions.formatter(t);const a=null===(i=null===(n=t.toolTipConfig)||void 0===n?void 0:n.tooltipText)||void 0===i?void 0:i.trim();if(a)return`<div>${a}</div>`;const r=null===(o=t.label)||void 0===o?void 0:o.trim();return r?`<div>${r}<br>Value: ${t.value}</div>`:`<div>${t.value}</div>`}(o,t);!function(t,e,n,i){e&&n&&(e.style.display="block",e.innerHTML=i,e.style.left=`${t.pageX+15}px`,e.style.top=`${t.pageY+15}px`,e.style.zIndex="999999",e.style.visibility="visible",e.style.opacity="1",e.style.position="absolute")}(e,b,C,n)}}else C.style.cursor="default",function(t){t&&(t.style.display="none",t.style.visibility="hidden",t.style.opacity="0")}(b)});C.addEventListener("mousemove",M.handle);const w=u(e=>{const{mouseX:n,mouseY:i}=d(e,C),o=c(n,i,x);o&&t.onBubbleClick&&t.onBubbleClick(o,e)});t.onBubbleClick&&C.addEventListener("click",w.handle);const S=()=>{null==p||p.destroy(),M.cancel(),w.cancel(),C.removeEventListener("mousemove",M.handle),C.removeEventListener("click",w.handle),n.destroy(),(null==b?void 0:b.parentElement)&&b.parentElement.removeChild(b),b=null};return{destroy:S,update:e=>(S(),t.data=e,f(t))}}h.TRANSPARENT="transparent";class m{constructor(t){const e=function(t={}){var e,i;if(!t)return void console.error("Configuration is not valid. Chart initialization aborted.");if(!t.data||0===t.data.length)return void console.error("No valid data provided. Chart initialization aborted.");const o=(a=Object.assign({canvasContainerId:null!==(e=t.canvasContainerId)&&void 0!==e?e:"chart-container",data:null!==(i=t.data)&&void 0!==i?i:[]},t),Object.assign(Object.assign({},n),a));var a;const r=f(o);return r?{config:o,instance:r}:void 0}(t);e&&(this.configuration=e.config,this.instance=e.instance)}destroy(){this.instance&&this.instance.destroy()}update(t){this.instance&&(this.instance=this.instance.update(t))}}function v(t){return new m(t)}"undefined"!=typeof window&&(window.initializeChart=v,window.BubbleChart=m),module.exports=e})();
@@ -1 +1 @@
1
- let t="default";function n(t,n){if(!n)return console.error("Invalid containerId."),null;const e=document.getElementById(n);if(!e)return console.error("Container not found."),null;const o=e.parentElement;return o?o.querySelector("#bubbleChartTooltip")||(o.prepend(t),t):(console.error("Parent container not found."),null)}function e(t,n){const e=n.getBoundingClientRect();return{mouseX:t.clientX-e.left,mouseY:t.clientY-e.top}}function o(t,n,e){return e.find(e=>Math.hypot(t-e.x,n-e.y)<e.radius)||null}class i{}i.TRANSPARENT="transparent";function a(t,n=14,e=400,o=6){const i=e>=700?1.25:e>=500?1.1:1,a=Math.min(t/o,t/1.2);let r=Math.min(n*i,a,.8*t);return r=Math.max(r,Math.max(8,t/6)),Math.round(r)}function r(r){if(!function(t){return t?!(!Array.isArray(t.data)||0===t.data.length)||(console.error("Invalid or empty data array"),!1):(console.error("Invalid config object"),!1)}(r))return;let l=function(t){var n,e;const o=document.getElementById(t.canvasContainerId);if(!o)return console.error(`Canvas container with ID '${t.canvasContainerId}' not found.`),null;if(o.querySelector("canvas"))return console.error("A canvas already exists inside the container."),null;const a=document.createElement("canvas");return Object.assign(a.style,{border:(null===(n=t.canvasBorderColor)||void 0===n?void 0:n.trim())?`1px solid #${t.canvasBorderColor}`:i.TRANSPARENT,background:(null===(e=t.canvasBackgroundColor)||void 0===e?void 0:e.trim())?`#${t.canvasBackgroundColor}`:i.TRANSPARENT,width:"100%",height:"100%",display:"block",imageRendering:"crisp-edges",aspectRatio:"1 / 1"}),a.style.setProperty("image-rendering","-moz-crisp-edges"),a.style.setProperty("image-rendering","-webkit-optimize-contrast"),a.style.setProperty("-ms-interpolation-mode","nearest-neighbor"),o.appendChild(a),a}(r);if(!l)return;const s=l.getContext("2d");if(!s)return void console.error("Invalid context");const{width:d,height:u}=f(l,s),c=function(t,n,e){const o=Math.min((n-10)/2,(e-10)/2),i=n/2,a=e/2,r=[...t.data].sort((t,n)=>n.value-t.value).map(t=>Object.assign(Object.assign({},t),{radius:0,x:0,y:0,fixed:!1})),l=r[0].value,s=Math.min(.5*o,.2*Math.min(n,e)),d=Math.max(.3*s,.05*Math.min(n,e));r.forEach(t=>{const o=t.value/l;t.radius=d+o*(s-d),t.radius=Math.min(t.radius,(n-10)/2,(e-10)/2)}),r.forEach((t,o)=>{if(0===o)t.x=i,t.y=a,t.fixed=!0;else{const l=r[0].radius+t.radius+3,s=Math.PI*(3-Math.sqrt(5)),d=n-5-t.radius,u=e-5-t.radius;t.x=Math.min(d,Math.max(5+t.radius,i+Math.cos(s*o)*l)),t.y=Math.min(u,Math.max(5+t.radius,a+Math.sin(s*o)*l)),t.fixed=!1}});for(let t=0;t<1e3;t++)r.forEach((t,e)=>{if(0===e){const n=i-t.x,e=a-t.y;return void(Math.hypot(n,e)>2&&(t.x+=.3*n,t.y+=.3*e))}let o=0,s=0;const d=t.radius+5;t.x<d?o+=.02*(d-t.x):t.x>n-d&&(o+=.02*(n-d-t.x)),r.forEach(n=>{if(t===n)return;const e=t.x-n.x,r=t.y-n.y,d=Math.hypot(e,r),u=t.radius+n.radius;if(d<1.5*u){const t=u/Math.max(d,.1)*.008;o+=e/d*t,s+=r/d*t}const c=i-t.x,h=a-t.y,f=Math.hypot(c,h),m=t.value/l*.02;t.x+=c/f*m,t.y+=h/f*m});const u=i-t.x,c=a-t.y,h=Math.hypot(u,c),f=r[0].radius+t.radius+35,m=(Math.pow(t.value/l,.3),.8*(1-t.value/l)*(1-Math.min(1,h/f)));t.x+=u*m,t.y+=c*m,t.x+=.35*o,t.y+=.35*s}),r.forEach((t,n)=>{r.forEach((e,o)=>{if(n>=o)return;if(0===n||0===o){const o=0===n?t:e,i=0===n?e:t,a=i.x-o.x,r=i.y-o.y,l=Math.hypot(a,r),s=o.radius+i.radius+2;if(l<s){const t=s-l,n=Math.atan2(r,a);i.x+=Math.cos(n)*t*.7,i.y+=Math.sin(n)*t*.7}return}const i=t.x-e.x,a=t.y-e.y,r=Math.hypot(i,a),l=t.radius+e.radius-5;if(r<l){const n=(l-r)*(.3+.04),o=Math.atan2(a,i),s=e.radius/(t.radius+e.radius);t.fixed||(t.x+=Math.cos(o)*n*s,t.y+=Math.sin(o)*n*s),e.fixed||(e.x-=Math.cos(o)*n*(1-s),e.y-=Math.sin(o)*n*(1-s))}})});return r.forEach(t=>{const o=Math.max(5+t.radius,Math.min(n-5-t.radius,t.x)),i=Math.max(5+t.radius,Math.min(e-5-t.radius,t.y));(!t.fixed||Math.hypot(t.x-o,t.y-i)>2)&&(t.x=o,t.y=i)}),r}(r,d,u);function h(){l&&s?(f(l,s),s.clearRect(0,0,l.width,l.height),c.forEach(t=>{const{x:n,y:e,radius:o,bubbleColor:i,borderColor:l,borderThickness:d,opacity:u,fontColor:c,fontFamily:h,fontSize:f,fontStyle:m,fontWeight:y,textAlign:v,textTransform:x,textBaseline:g}=function(t,n){var e,o,i,r,l,s,d,u,c,h,f,m;return{x:t.x,y:t.y,radius:Math.max(t.radius||0,n.minRadius||10),bubbleColor:null!==(o=null!==(e=t.bubbleColor)&&void 0!==e?e:n.defaultBubbleColor)&&void 0!==o?o:"#3498db",borderColor:null!==(i=t.borderColor)&&void 0!==i?i:"black",borderThickness:Math.max(null!==(r=t.borderThickness)&&void 0!==r?r:.25,0),opacity:void 0!==t.opacity?Math.max(0,Math.min(1,t.opacity)):1,fontStyle:t.fontStyle||"normal",fontWeight:"number"==typeof t.fontWeight&&t.fontWeight>=100&&t.fontWeight<=900?t.fontWeight:400,textAlign:null!==(l=t.textAlign)&&void 0!==l?l:"center",textTransform:null!==(s=t.textTransform)&&void 0!==s?s:"none",fontColor:null!==(u=null!==(d=t.fontColor)&&void 0!==d?d:n.defaultFontColor)&&void 0!==u?u:"#000",textBaseline:null!==(c=t.textBaseline)&&void 0!==c?c:"middle",fontSize:Math.max(a(t.radius||n.minRadius||10,null!==(h=n.fontSize)&&void 0!==h?h:14,null!==(f=t.fontWeight)&&void 0!==f?f:400),8),fontFamily:t.fontFamily&&"string"==typeof t.fontFamily&&"Arial"!==t.fontFamily?`${t.fontFamily}, Arial, sans-serif`:`${null!==(m=n.defaultFontFamily)&&void 0!==m?m:"Arial"}, sans-serif`}}(t,r);s.beginPath(),s.arc(n,e,o,0,2*Math.PI),s.fillStyle=i,s.fill(),s.strokeStyle=l,s.lineWidth=d,s.stroke();const p=`${m} ${y} ${f}px ${h}`;s.fillStyle=c,s.font=p,s.imageSmoothingEnabled=!0,s.imageSmoothingQuality="high",s.textAlign=v,s.textBaseline=g;let b=t.label||"";if("uppercase"===x?b=b.toUpperCase():"lowercase"===x?b=b.toLowerCase():"capitalize"===x&&(b=b.replace(/\b\w/g,t=>t.toUpperCase())),r.textWrap){const i=1.5*o-10,a=1.4*f,l=function(t,n,e,o,i,a=14,r=400,l="normal",s="Arial",d=0,u=5,c=1.2){const h=1.5*(i-u),f=a*c,m=Math.max(1,Math.floor(h/f)),y="auto"===o||void 0===o?m:Math.min(o,m);e=Math.max(0,e-2*d);const v=n.split(" ");let x="";const g=[];let p=!1,b=!1;t.font=`${r||""} ${l||""} ${a}px ${s}`,t.imageSmoothingEnabled=!0,t.imageSmoothingQuality="high";for(const n of v){const o=x?`${x} ${n}`:n;if(t.measureText(o).width<=e)x=o;else if(x.trim()&&g.push(x),x=n,t.measureText(x).width>e){let n=x;for(;t.measureText(n+"...").width>e&&n.length>0;)n=n.slice(0,-1);g.push(n+"..."),b=!0;break}if(g.length>=y){p=!0;break}}if(x&&g.length<y&&!b&&g.push(x),p&&g.length>0){let n=g[g.length-1];for(;t.measureText(n+"...").width>e&&n.length>0;)n=n.slice(0,-1);g[g.length-1]=n+"..."}return g}(s,t.label,i,r.maxLines,o,f,y,m,h),d=e-(l.length-1)*a/2;l.forEach((t,e)=>{const o=Math.round(n),i=Math.round(d+e*a);s.fillText(t,o,i)})}else s.fillText(t.label,Math.round(n),Math.round(e))})):console.warn("canvas or ctx is not valid")}function f(t,n){const e=window.devicePixelRatio||1,o=t.getBoundingClientRect();return t.width=o.width*e,t.height=o.height*e,t.style.width=`${o.width}px`,t.style.height=`${o.height}px`,n.setTransform(1,0,0,1,0,0),n.scale(e,e),{width:o.width,height:o.height,dpr:e}}function m(){const t=document.getElementById(r.canvasContainerId);t&&l&&(l.width=t.offsetWidth,l.height=t.offsetHeight,l.getContext("2d"),h())}let y;r.isResizeCanvasOnWindowSizeChange&&(m(),window.addEventListener("resize",m)),h(),r.showToolTip&&(y=function(t){var e,o,i,a,r,l,s,d,u,c,h,f,m,y,v,x,g,p;const b=null===(o=null===(e=t.data[0].toolTipConfig)||void 0===e?void 0:e.tooltipFormattedData)||void 0===o?void 0:o.trim();if(b){const e=document.createElement("div");e.innerHTML=b.trim();const o=e.firstElementChild;return o.style.display="none",o.style.visibility="hidden",o.style.opacity="0",o.style.position="absolute",n(o,t.canvasContainerId)}const M=document.createElement("div");M.id="bubbleChartTooltip",M.style.display="none";const C=null!==(i=null==t?void 0:t.tooltipOptions)&&void 0!==i?i:{},w=(t,n)=>"number"==typeof t?`${t}px`:null!=t?t:n;return Object.assign(M.style,{position:"absolute",padding:w(C.padding,"8px"),margin:w(C.margin,"0"),background:null!==(a=C.backgroundColor)&&void 0!==a?a:"rgba(0, 0, 0, 0.85)",color:null!==(r=C.fontColor)&&void 0!==r?r:"white",borderRadius:"4px",pointerEvents:null!==(l=C.pointerEvents)&&void 0!==l?l:"none",fontFamily:null!==(s=C.fontFamily)&&void 0!==s?s:"Arial, sans-serif",fontSize:w(C.fontSize,"14px"),fontWeight:String(null!==(d=C.fontWeight)&&void 0!==d?d:"400"),fontStyle:null!==(u=C.fontStyle)&&void 0!==u?u:"normal",textAlign:null!==(c=C.textAlign)&&void 0!==c?c:"left",textDecoration:null!==(h=C.textDecoration)&&void 0!==h?h:"none",textTransform:null!==(f=C.textTransform)&&void 0!==f?f:"none",letterSpacing:w(C.letterSpacing,"normal"),border:(()=>{var t;if(!C.borderStyle)return"none";const n=w(C.borderWidth,"1px"),e=null!==(t=C.borderColor)&&void 0!==t?t:"transparent";return`${n} ${C.borderStyle} ${e}`})(),boxShadow:null!==(m=C.boxShadow)&&void 0!==m?m:"none",maxWidth:w(C.maxWidth,"200px"),minWidth:w(C.minWidth,"auto"),maxHeight:w(C.maxHeight,"none"),minHeight:w(C.minHeight,"auto"),zIndex:String(null!==(y=C.zIndex)&&void 0!==y?y:1e3),transition:null!==(v=C.transition)&&void 0!==v?v:"opacity 0.2s",transform:null!==(x=C.transform)&&void 0!==x?x:"none",backdropFilter:null!==(g=C.backdropFilter)&&void 0!==g?g:"none",opacity:String(null!==(p=C.opacity)&&void 0!==p?p:1),display:"none",visibility:"hidden"}),n(M,t.canvasContainerId),M}(r));let v=null;if(l.addEventListener("mousemove",n=>{v||(v=requestAnimationFrame(()=>{(function(n,i,a,r,l){const{mouseX:s,mouseY:d}=e(n,a),u=o(s,d,i);t=(null==l?void 0:l.cursorType)||"pointer",a.style.cursor="default",r&&(u?function(n,e,o,i){if(e&&e.value&&o&&i){o.style.cursor=t,i.style.display="block",i.innerHTML=function(t){var n,e,o;if(!t)return"";const i=null===(e=null===(n=t.toolTipConfig)||void 0===n?void 0:n.tooltipText)||void 0===e?void 0:e.trim();if(i)return`<div>${i}</div>`;const a=null===(o=t.label)||void 0===o?void 0:o.trim();return a?`<div>${a}<br>Value: ${t.value}</div>`:`<div>${t.value}</div>`}(e);const a=o.getBoundingClientRect();i.style.left=n.clientX-a.left+15+"px",i.style.top=n.clientY-a.top+15+"px",i.style.zIndex="999999",i.style.visibility="visible",i.style.opacity="1",i.style.position="absolute"}}(n,u,a,r):(a.style.cursor="default",r.style.display="none",r.style.visibility="hidden",r.style.opacity="0"))})(n,c,l,y,r),v=null}))}),r.onBubbleClick){let t=null;l.addEventListener("click",n=>{t||(t=requestAnimationFrame(()=>{!function(t,n,i,a){const{mouseX:r,mouseY:l}=e(t,i),s=o(r,l,n);null!=s&&a.onBubbleClick&&a.onBubbleClick(s,t)}(n,c,l,r),t=null}))})}}const l={defaultBubbleColor:"#3498DB",defaultFontColor:"#ffffff",minRadius:10,maxLines:"auto",textWrap:!0,isResizeCanvasOnWindowSizeChange:!0,fontSize:14,defaultFontFamily:"Arial",showToolTip:!0};function s(t={}){var n,e;if(!t)return void console.error("Configuration is not valid. Chart initialization aborted.");if(!t.data||0===t.data.length)return void console.error("No valid data provided. Chart initialization aborted.");const o=(i=Object.assign({canvasContainerId:null!==(n=t.canvasContainerId)&&void 0!==n?n:"chart-container",data:null!==(e=t.data)&&void 0!==e?e:[]},t),Object.assign(Object.assign({},l),i));var i;return r(o),o}class d{constructor(t){const n=s(t);n&&(this.configuration=n)}render(){this.configuration&&r(this.configuration)}}window.initializeChart=s;export{d as BubbleChart,s as initializeChart};
1
+ const t={defaultBubbleColor:"#3498DB",defaultFontColor:"#ffffff",minRadius:10,maxLines:"auto",textWrap:!0,isResizeCanvasOnWindowSizeChange:!0,fontSize:14,defaultFontFamily:"Arial",showToolTip:!0},e=JSON.parse('{"FC":0.008,"rX":1000,"d6":0.65,"WH":0.02,"ND":0.12,"$l":0.8,"cg":0.3,"e0":35}');function n(t,e){t.forEach((n,i)=>{t.forEach((t,o)=>{if(i>=o)return;if(0===i||0===o){const e=0===i?n:t,o=0===i?t:n,a=o.x-e.x,r=o.y-e.y,l=Math.hypot(a,r),s=e.radius+o.radius+2;if(l<s){const t=s-l,e=Math.atan2(r,a);o.x+=Math.cos(e)*t*.7,o.y+=Math.sin(e)*t*.7}return}const a=n.x-t.x,r=n.y-t.y,l=Math.hypot(a,r),s=n.radius+t.radius-5;if(l<s){const i=(s-l)*(.3+5*e.forceStrength),o=Math.atan2(r,a),d=n.radius+t.radius,c=d>0?t.radius/d:.5;n.fixed||(n.x+=Math.cos(o)*i*c,n.y+=Math.sin(o)*i*c),t.fixed||(t.x-=Math.cos(o)*i*(1-c),t.y-=Math.sin(o)*i*(1-c))}})})}function i(t,e=14,n=400,i=6){const o=n>=700?1.25:n>=500?1.1:1,a=Math.min(t/i,t/1.2);let r=Math.min(e*o,a,.8*t);return r=Math.max(r,Math.max(8,t/6)),Math.round(r)}class o{constructor(t){this.canvas=t;const e=t.getContext("2d");if(!e)throw new Error("Failed to get 2D rendering context from canvas");this.ctx=e}getContext(){return this.ctx}getCanvas(){return this.canvas}setup(){const t=window.devicePixelRatio||1,e=this.canvas.getBoundingClientRect();return this.canvas.width=e.width*t,this.canvas.height=e.height*t,this.canvas.style.width=`${e.width}px`,this.canvas.style.height=`${e.height}px`,this.ctx.setTransform(1,0,0,1,0,0),this.ctx.scale(t,t),{width:e.width,height:e.height}}getSize(){const t=this.canvas.getBoundingClientRect();return{width:t.width,height:t.height}}clear(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height)}drawCircle(t,e,n,i,o,a,r){this.ctx.beginPath(),this.ctx.arc(t,e,n,0,2*Math.PI),this.ctx.fillStyle=i,this.ctx.fill(),a>0&&(this.ctx.strokeStyle=o,this.ctx.lineWidth=a,this.ctx.stroke())}drawText(t,e,n,i){const o=`${i.fontStyle} ${i.fontWeight} ${i.fontSize}px ${i.fontFamily}`;this.ctx.fillStyle=i.fontColor,this.ctx.font=o,this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.ctx.textAlign=i.textAlign,this.ctx.textBaseline=i.textBaseline,this.ctx.fillText(t,Math.round(e),Math.round(n))}destroy(){const t=this.canvas.parentElement;t&&t.removeChild(this.canvas)}}class a{constructor(t){this.ctx=t}measureWidth(t,e,n,i,o){return this.ctx.font=`${i} ${n} ${e}px ${o}`,this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.ctx.measureText(t).width}}function r(t,e){const n=`bubbleChartTooltip-${e}`;return document.body.querySelector(`#${n}`)||(t.id=n,document.body.appendChild(t),t)}function l(t,e){const n=e.getBoundingClientRect(),i=window.devicePixelRatio||1;return{mouseX:(t.clientX-n.left)*i,mouseY:(t.clientY-n.top)*i}}function s(t,e,n){return n.find(n=>Math.hypot(t-n.x,e-n.y)<n.radius)||null}function d(t){let e=null;return{handle:n=>{e||(e=requestAnimationFrame(()=>{t(n),e=null}))},cancel:()=>{e&&(cancelAnimationFrame(e),e=null)}}}class c{}function u(t){if(!function(t){return t?!(!Array.isArray(t.data)||0===t.data.length)||(console.error("Invalid or empty data array"),!1):(console.error("Invalid config object"),!1)}(t))return;const h=function(t){var e,n;const i=document.getElementById(t.canvasContainerId);if(!i)return console.error(`Canvas container with ID '${t.canvasContainerId}' not found.`),null;if(i.querySelector("canvas"))return console.error("A canvas already exists inside the container."),null;const o=document.createElement("canvas");return Object.assign(o.style,{border:(null===(e=t.canvasBorderColor)||void 0===e?void 0:e.trim())?`1px solid #${t.canvasBorderColor}`:c.TRANSPARENT,background:(null===(n=t.canvasBackgroundColor)||void 0===n?void 0:n.trim())?`#${t.canvasBackgroundColor}`:c.TRANSPARENT,width:"100%",height:"100%",display:"block",imageRendering:"crisp-edges",aspectRatio:"1 / 1"}),o.style.setProperty("image-rendering","-moz-crisp-edges"),o.style.setProperty("image-rendering","-webkit-optimize-contrast"),o.style.setProperty("-ms-interpolation-mode","nearest-neighbor"),i.appendChild(o),o}(t);if(!h)return;const f=new o(h),m=new a(f.getContext()),{width:v,height:x}=f.setup();let y=function(t,i,o,a){const r=Object.assign({forceStrength:e.FC,iterations:e.rX,damping:e.d6,boundaryForce:e.WH,centerForce:e.ND,centerAttraction:e.$l,centerDamping:e.cg,centerRadiusBuffer:e.e0},a),l=Math.min((i-10)/2,(o-10)/2),s=i/2,d=o/2,c=[...t].sort((t,e)=>e.value-t.value).map(t=>Object.assign(Object.assign({},t),{radius:0,x:0,y:0,fixed:!1}));if(0===c.length)return c;const u=c[0].value,h=Math.min(.5*l,.2*Math.min(i,o)),f=Math.max(.3*h,.05*Math.min(i,o));return c.forEach(t=>{const e=u>0?t.value/u:1;t.radius=f+e*(h-f),t.radius=Math.max(0,Math.min(t.radius,(i-10)/2,(o-10)/2))}),c.forEach((t,e)=>{if(0===e)t.x=s,t.y=d,t.fixed=!0;else{const n=c[0].radius+t.radius+3,a=Math.PI*(3-Math.sqrt(5)),r=i-5-t.radius,l=o-5-t.radius;t.x=Math.min(r,Math.max(5+t.radius,s+Math.cos(a*e)*n)),t.y=Math.min(l,Math.max(5+t.radius,d+Math.sin(a*e)*n)),t.fixed=!1}}),function(t,e,i,o,a,r,l){for(let o=0;o<e.iterations;o++)t.forEach((n,o)=>{if(0===o){const t=a-n.x,i=r-n.y;return void(Math.hypot(t,i)>2&&(n.x+=t*e.centerDamping,n.y+=i*e.centerDamping))}let s=0,d=0;const c=n.radius+5;n.x<c?s+=(c-n.x)*e.boundaryForce:n.x>i-c&&(s+=(i-c-n.x)*e.boundaryForce),t.forEach(t=>{if(n===t)return;const i=n.x-t.x,o=n.y-t.y,c=Math.hypot(i,o),u=n.radius+t.radius;if(c<1.5*u){const t=e.forceStrength*(u/Math.max(c,.1));s+=i/c*t,d+=o/c*t}const h=a-n.x,f=r-n.y,m=Math.hypot(h,f),v=n.value/l*.02;n.x+=h/m*v,n.y+=f/m*v});const u=a-n.x,h=r-n.y,f=Math.hypot(u,h),m=t[0].radius+n.radius+e.centerRadiusBuffer,v=e.centerAttraction*(1-n.value/l)*(1-Math.min(1,f/m));n.x+=u*v,n.y+=h*v,n.x+=s*(1-e.damping),n.y+=d*(1-e.damping)}),n(t,e)}(c,r,i,0,s,d,u),function(t,e,n){t.forEach(t=>{const i=Math.max(5+t.radius,Math.min(e-5-t.radius,t.x)),o=Math.max(5+t.radius,Math.min(n-5-t.radius,t.y));(!t.fixed||Math.hypot(t.x-i,t.y-o)>2)&&(t.x=i,t.y=o)})}(c,i,o),c}(t.data,v,x);function g(){f.setup(),f.clear(),y.forEach(e=>{const n=function(t,e,n){var o,a,r,l,s,d,c,u,h,f,m;let v=null!==(o=n.defaultBubbleColor)&&void 0!==o?o:"#3498db";if(t.bubbleColor)v=t.bubbleColor;else if(n.colorPalette&&n.colorPalette.length>0){const i=e.findIndex(e=>e.label===t.label&&e.value===t.value),o=i>=0?i:0;v=n.colorPalette[o%n.colorPalette.length]}const x=Math.max(t.radius||0,n.minRadius||10);return{bubbleColor:v,borderColor:null!==(a=t.borderColor)&&void 0!==a?a:"black",borderThickness:Math.max(null!==(r=t.borderThickness)&&void 0!==r?r:.25,0),opacity:void 0!==t.opacity?Math.max(0,Math.min(1,t.opacity)):1,fontStyle:t.fontStyle||"normal",fontWeight:"number"==typeof t.fontWeight&&t.fontWeight>=100&&t.fontWeight<=900?t.fontWeight:400,textAlign:null!==(l=t.textAlign)&&void 0!==l?l:"center",textTransform:null!==(s=t.textTransform)&&void 0!==s?s:"none",fontColor:null!==(c=null!==(d=t.fontColor)&&void 0!==d?d:n.defaultFontColor)&&void 0!==c?c:"#000",textBaseline:null!==(u=t.textBaseline)&&void 0!==u?u:"middle",fontSize:Math.max(i(x,null!==(h=n.fontSize)&&void 0!==h?h:14,null!==(f=t.fontWeight)&&void 0!==f?f:400),8),fontFamily:t.fontFamily&&"string"==typeof t.fontFamily&&"Arial"!==t.fontFamily?`${t.fontFamily}, Arial, sans-serif`:`${null!==(m=n.defaultFontFamily)&&void 0!==m?m:"Arial"}, sans-serif`}}(e,y,t);f.drawCircle(e.x,e.y,Math.max(e.radius||0,t.minRadius||10),n.bubbleColor,n.borderColor,n.borderThickness,n.opacity);let o=e.label||"";"uppercase"===n.textTransform?o=o.toUpperCase():"lowercase"===n.textTransform?o=o.toLowerCase():"capitalize"===n.textTransform&&(o=o.replace(/\b\w/g,t=>t.toUpperCase()));const a=Math.max(e.radius||0,t.minRadius||10),r={fontSize:n.fontSize,fontFamily:n.fontFamily,fontWeight:n.fontWeight,fontStyle:n.fontStyle,fontColor:n.fontColor,textAlign:n.textAlign,textBaseline:n.textBaseline};if(t.textWrap){const i=1.5*a-10,o=1.4*n.fontSize,l=function(t,e,n,i,o,a=14,r=400,l="normal",s="Arial",d=0,c=5,u=1.2){const h=1.5*(o-c),f=a*u,m=Math.max(1,Math.floor(h/f)),v="auto"===i||void 0===i?m:Math.min(i,m);n=Math.max(0,n-2*d);const x=e.split(" ");let y="";const g=[];let p=!1,b=!1;const C=e=>t.measureWidth(e,a,r,l,s);for(const t of x){const e=y?`${y} ${t}`:t;if(C(e)<=n)y=e;else if(y.trim()&&g.push(y),y=t,C(y)>n){let t=y;for(;C(t+"...")>n&&t.length>0;)t=t.slice(0,-1);g.push(t+"..."),b=!0;break}if(g.length>=v){p=!0;break}}if(y&&g.length<v&&!b&&g.push(y),p&&g.length>0){let t=g[g.length-1];for(;C(t+"...")>n&&t.length>0;)t=t.slice(0,-1);g[g.length-1]=t+"..."}return g}(m,e.label,i,t.maxLines,a,n.fontSize,n.fontWeight,n.fontStyle,n.fontFamily),s=e.y-(l.length-1)*o/2;l.forEach((t,n)=>{f.drawText(t,e.x,s+n*o,r)})}else f.drawText(o,e.x,e.y,r)})}let p=null;if(t.isResizeCanvasOnWindowSizeChange){const e=document.getElementById(t.canvasContainerId);e&&(p=function(t,e){let n=null,i=null;const o=()=>{i||(i=requestAnimationFrame(()=>{e(),i=null}))};return"undefined"!=typeof ResizeObserver?(n=new ResizeObserver(o),n.observe(t)):(o(),window.addEventListener("resize",o)),{destroy:()=>{n&&(n.disconnect(),n=null),window.removeEventListener("resize",o),i&&(cancelAnimationFrame(i),i=null)}}}(e,()=>{const t=f.getCanvas();e&&t&&(t.width=e.offsetWidth,t.height=e.offsetHeight,g())}))}g();let b=null;t.showToolTip&&(b=function(t){var e,n,i,o,a,l,s,d,c,u,h,f,m,v,x,y,g,p,b;const C=null===(i=null===(n=null===(e=t.data[0])||void 0===e?void 0:e.toolTipConfig)||void 0===n?void 0:n.tooltipFormattedData)||void 0===i?void 0:i.trim();if(C){const e=document.createElement("div");e.innerHTML=C.trim();const n=e.firstElementChild;return n.style.display="none",n.style.visibility="hidden",n.style.opacity="0",n.style.position="absolute",r(n,t.canvasContainerId)}const M=document.createElement("div");M.style.display="none";const w=null!==(o=null==t?void 0:t.tooltipOptions)&&void 0!==o?o:{},S=(t,e)=>"number"==typeof t?`${t}px`:null!=t?t:e;return Object.assign(M.style,{position:"absolute",padding:S(w.padding,"8px"),margin:S(w.margin,"0"),background:null!==(a=w.backgroundColor)&&void 0!==a?a:"rgba(0, 0, 0, 0.85)",color:null!==(l=w.fontColor)&&void 0!==l?l:"white",borderRadius:"4px",pointerEvents:null!==(s=w.pointerEvents)&&void 0!==s?s:"none",fontFamily:null!==(d=w.fontFamily)&&void 0!==d?d:"Arial, sans-serif",fontSize:S(w.fontSize,"14px"),fontWeight:String(null!==(c=w.fontWeight)&&void 0!==c?c:"400"),fontStyle:null!==(u=w.fontStyle)&&void 0!==u?u:"normal",textAlign:null!==(h=w.textAlign)&&void 0!==h?h:"left",textDecoration:null!==(f=w.textDecoration)&&void 0!==f?f:"none",textTransform:null!==(m=w.textTransform)&&void 0!==m?m:"none",letterSpacing:S(w.letterSpacing,"normal"),border:(()=>{var t;if(!w.borderStyle)return"none";const e=S(w.borderWidth,"1px"),n=null!==(t=w.borderColor)&&void 0!==t?t:"transparent";return`${e} ${w.borderStyle} ${n}`})(),boxShadow:null!==(v=w.boxShadow)&&void 0!==v?v:"none",maxWidth:S(w.maxWidth,"200px"),minWidth:S(w.minWidth,"auto"),maxHeight:S(w.maxHeight,"none"),minHeight:S(w.minHeight,"auto"),zIndex:String(null!==(x=w.zIndex)&&void 0!==x?x:1e3),transition:null!==(y=w.transition)&&void 0!==y?y:"opacity 0.2s",transform:null!==(g=w.transform)&&void 0!==g?g:"none",backdropFilter:null!==(p=w.backdropFilter)&&void 0!==p?p:"none",opacity:String(null!==(b=w.opacity)&&void 0!==b?b:1),display:"none",visibility:"hidden"}),r(M,t.canvasContainerId),M}(t));const C=f.getCanvas(),M=d(e=>{const{mouseX:n,mouseY:i}=l(e,C),o=s(n,i,y);if(o){const n=(null==t?void 0:t.cursorType)||"pointer";if(C.style.cursor=n,b){const n=function(t,e){var n,i,o;if(!t)return"";if(e.tooltipOptions&&"function"==typeof e.tooltipOptions.formatter)return e.tooltipOptions.formatter(t);const a=null===(i=null===(n=t.toolTipConfig)||void 0===n?void 0:n.tooltipText)||void 0===i?void 0:i.trim();if(a)return`<div>${a}</div>`;const r=null===(o=t.label)||void 0===o?void 0:o.trim();return r?`<div>${r}<br>Value: ${t.value}</div>`:`<div>${t.value}</div>`}(o,t);!function(t,e,n,i){e&&n&&(e.style.display="block",e.innerHTML=i,e.style.left=`${t.pageX+15}px`,e.style.top=`${t.pageY+15}px`,e.style.zIndex="999999",e.style.visibility="visible",e.style.opacity="1",e.style.position="absolute")}(e,b,C,n)}}else C.style.cursor="default",function(t){t&&(t.style.display="none",t.style.visibility="hidden",t.style.opacity="0")}(b)});C.addEventListener("mousemove",M.handle);const w=d(e=>{const{mouseX:n,mouseY:i}=l(e,C),o=s(n,i,y);o&&t.onBubbleClick&&t.onBubbleClick(o,e)});t.onBubbleClick&&C.addEventListener("click",w.handle);const S=()=>{null==p||p.destroy(),M.cancel(),w.cancel(),C.removeEventListener("mousemove",M.handle),C.removeEventListener("click",w.handle),f.destroy(),(null==b?void 0:b.parentElement)&&b.parentElement.removeChild(b),b=null};return{destroy:S,update:e=>(S(),t.data=e,u(t))}}c.TRANSPARENT="transparent";class h{constructor(e){const n=function(e={}){var n,i;if(!e)return void console.error("Configuration is not valid. Chart initialization aborted.");if(!e.data||0===e.data.length)return void console.error("No valid data provided. Chart initialization aborted.");const o=(a=Object.assign({canvasContainerId:null!==(n=e.canvasContainerId)&&void 0!==n?n:"chart-container",data:null!==(i=e.data)&&void 0!==i?i:[]},e),Object.assign(Object.assign({},t),a));var a;const r=u(o);return r?{config:o,instance:r}:void 0}(e);n&&(this.configuration=n.config,this.instance=n.instance)}destroy(){this.instance&&this.instance.destroy()}update(t){this.instance&&(this.instance=this.instance.update(t))}}function f(t){return new h(t)}"undefined"!=typeof window&&(window.initializeChart=f,window.BubbleChart=h);export{h as BubbleChart,f as initializeChart};
@@ -1 +1 @@
1
- !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("BubbleChart",[],e):"object"==typeof exports?exports.BubbleChart=e():t.BubbleChart=e()}(this,()=>(()=>{"use strict";var t={d:(e,n)=>{for(var o in n)t.o(n,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:n[o]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{BubbleChart:()=>h,initializeChart:()=>c});let n="default";function o(t,e){if(!e)return console.error("Invalid containerId."),null;const n=document.getElementById(e);if(!n)return console.error("Container not found."),null;const o=n.parentElement;return o?o.querySelector("#bubbleChartTooltip")||(o.prepend(t),t):(console.error("Parent container not found."),null)}function i(t,e){const n=e.getBoundingClientRect();return{mouseX:t.clientX-n.left,mouseY:t.clientY-n.top}}function r(t,e,n){return n.find(n=>Math.hypot(t-n.x,e-n.y)<n.radius)||null}class a{}a.TRANSPARENT="transparent";const l={forceStrength:.008,iterations:1e3,damping:.65,boundaryForce:.02,centerForce:.12,centerAttraction:.8,centerDamping:.3,centerRadiusBuffer:35};function s(t,e=14,n=400,o=6){const i=n>=700?1.25:n>=500?1.1:1,r=Math.min(t/o,t/1.2);let a=Math.min(e*i,r,.8*t);return a=Math.max(a,Math.max(8,t/6)),Math.round(a)}function d(t){if(!function(t){return t?!(!Array.isArray(t.data)||0===t.data.length)||(console.error("Invalid or empty data array"),!1):(console.error("Invalid config object"),!1)}(t))return;let e=function(t){var e,n;const o=document.getElementById(t.canvasContainerId);if(!o)return console.error(`Canvas container with ID '${t.canvasContainerId}' not found.`),null;if(o.querySelector("canvas"))return console.error("A canvas already exists inside the container."),null;const i=document.createElement("canvas");return Object.assign(i.style,{border:(null===(e=t.canvasBorderColor)||void 0===e?void 0:e.trim())?`1px solid #${t.canvasBorderColor}`:a.TRANSPARENT,background:(null===(n=t.canvasBackgroundColor)||void 0===n?void 0:n.trim())?`#${t.canvasBackgroundColor}`:a.TRANSPARENT,width:"100%",height:"100%",display:"block",imageRendering:"crisp-edges",aspectRatio:"1 / 1"}),i.style.setProperty("image-rendering","-moz-crisp-edges"),i.style.setProperty("image-rendering","-webkit-optimize-contrast"),i.style.setProperty("-ms-interpolation-mode","nearest-neighbor"),o.appendChild(i),i}(t);if(!e)return;const d=e.getContext("2d");if(!d)return void console.error("Invalid context");const{width:u,height:c}=m(e,d),h=function(t,e,n){const o=Math.min((e-10)/2,(n-10)/2),i=e/2,r=n/2,a=[...t.data].sort((t,e)=>e.value-t.value).map(t=>Object.assign(Object.assign({},t),{radius:0,x:0,y:0,fixed:!1})),s=a[0].value,d=Math.min(.5*o,.2*Math.min(e,n)),u=Math.max(.3*d,.05*Math.min(e,n));a.forEach(t=>{const o=t.value/s;t.radius=u+o*(d-u),t.radius=Math.min(t.radius,(e-10)/2,(n-10)/2)}),a.forEach((t,o)=>{if(0===o)t.x=i,t.y=r,t.fixed=!0;else{const l=a[0].radius+t.radius+3,s=Math.PI*(3-Math.sqrt(5)),d=e-5-t.radius,u=n-5-t.radius;t.x=Math.min(d,Math.max(5+t.radius,i+Math.cos(s*o)*l)),t.y=Math.min(u,Math.max(5+t.radius,r+Math.sin(s*o)*l)),t.fixed=!1}});for(let t=0;t<l.iterations;t++)a.forEach((t,n)=>{if(0===n){const e=i-t.x,n=r-t.y;return void(Math.hypot(e,n)>2&&(t.x+=e*l.centerDamping,t.y+=n*l.centerDamping))}let o=0,d=0;const u=t.radius+5;t.x<u?o+=(u-t.x)*l.boundaryForce:t.x>e-u&&(o+=(e-u-t.x)*l.boundaryForce),a.forEach(e=>{if(t===e)return;const n=t.x-e.x,a=t.y-e.y,u=Math.hypot(n,a),c=t.radius+e.radius;if(u<1.5*c){const t=l.forceStrength*(c/Math.max(u,.1));o+=n/u*t,d+=a/u*t}const h=i-t.x,f=r-t.y,m=Math.hypot(h,f),y=t.value/s*.02;t.x+=h/m*y,t.y+=f/m*y});const c=i-t.x,h=r-t.y,f=Math.hypot(c,h),m=a[0].radius+t.radius+l.centerRadiusBuffer,y=(l.centerForce,Math.pow(t.value/s,.3),l.centerAttraction*(1-t.value/s)*(1-Math.min(1,f/m)));t.x+=c*y,t.y+=h*y,t.x+=o*(1-l.damping),t.y+=d*(1-l.damping)}),a.forEach((t,e)=>{a.forEach((n,o)=>{if(e>=o)return;if(0===e||0===o){const o=0===e?t:n,i=0===e?n:t,r=i.x-o.x,a=i.y-o.y,l=Math.hypot(r,a),s=o.radius+i.radius+2;if(l<s){const t=s-l,e=Math.atan2(a,r);i.x+=Math.cos(e)*t*.7,i.y+=Math.sin(e)*t*.7}return}const i=t.x-n.x,r=t.y-n.y,a=Math.hypot(i,r),s=t.radius+n.radius-5;if(a<s){const e=(s-a)*(.3+5*l.forceStrength),o=Math.atan2(r,i),d=n.radius/(t.radius+n.radius);t.fixed||(t.x+=Math.cos(o)*e*d,t.y+=Math.sin(o)*e*d),n.fixed||(n.x-=Math.cos(o)*e*(1-d),n.y-=Math.sin(o)*e*(1-d))}})});return a.forEach(t=>{const o=Math.max(5+t.radius,Math.min(e-5-t.radius,t.x)),i=Math.max(5+t.radius,Math.min(n-5-t.radius,t.y));(!t.fixed||Math.hypot(t.x-o,t.y-i)>2)&&(t.x=o,t.y=i)}),a}(t,u,c);function f(){e&&d?(m(e,d),d.clearRect(0,0,e.width,e.height),h.forEach(e=>{const{x:n,y:o,radius:i,bubbleColor:r,borderColor:a,borderThickness:l,opacity:u,fontColor:c,fontFamily:h,fontSize:f,fontStyle:m,fontWeight:y,textAlign:p,textTransform:v,textBaseline:g}=function(t,e){var n,o,i,r,a,l,d,u,c,h,f,m;return{x:t.x,y:t.y,radius:Math.max(t.radius||0,e.minRadius||10),bubbleColor:null!==(o=null!==(n=t.bubbleColor)&&void 0!==n?n:e.defaultBubbleColor)&&void 0!==o?o:"#3498db",borderColor:null!==(i=t.borderColor)&&void 0!==i?i:"black",borderThickness:Math.max(null!==(r=t.borderThickness)&&void 0!==r?r:.25,0),opacity:void 0!==t.opacity?Math.max(0,Math.min(1,t.opacity)):1,fontStyle:t.fontStyle||"normal",fontWeight:"number"==typeof t.fontWeight&&t.fontWeight>=100&&t.fontWeight<=900?t.fontWeight:400,textAlign:null!==(a=t.textAlign)&&void 0!==a?a:"center",textTransform:null!==(l=t.textTransform)&&void 0!==l?l:"none",fontColor:null!==(u=null!==(d=t.fontColor)&&void 0!==d?d:e.defaultFontColor)&&void 0!==u?u:"#000",textBaseline:null!==(c=t.textBaseline)&&void 0!==c?c:"middle",fontSize:Math.max(s(t.radius||e.minRadius||10,null!==(h=e.fontSize)&&void 0!==h?h:14,null!==(f=t.fontWeight)&&void 0!==f?f:400),8),fontFamily:t.fontFamily&&"string"==typeof t.fontFamily&&"Arial"!==t.fontFamily?`${t.fontFamily}, Arial, sans-serif`:`${null!==(m=e.defaultFontFamily)&&void 0!==m?m:"Arial"}, sans-serif`}}(e,t);d.beginPath(),d.arc(n,o,i,0,2*Math.PI),d.fillStyle=r,d.fill(),d.strokeStyle=a,d.lineWidth=l,d.stroke();const x=`${m} ${y} ${f}px ${h}`;d.fillStyle=c,d.font=x,d.imageSmoothingEnabled=!0,d.imageSmoothingQuality="high",d.textAlign=p,d.textBaseline=g;let b=e.label||"";if("uppercase"===v?b=b.toUpperCase():"lowercase"===v?b=b.toLowerCase():"capitalize"===v&&(b=b.replace(/\b\w/g,t=>t.toUpperCase())),t.textWrap){const r=1.5*i-10,a=1.4*f,l=function(t,e,n,o,i,r=14,a=400,l="normal",s="Arial",d=0,u=5,c=1.2){const h=1.5*(i-u),f=r*c,m=Math.max(1,Math.floor(h/f)),y="auto"===o||void 0===o?m:Math.min(o,m);n=Math.max(0,n-2*d);const p=e.split(" ");let v="";const g=[];let x=!1,b=!1;t.font=`${a||""} ${l||""} ${r}px ${s}`,t.imageSmoothingEnabled=!0,t.imageSmoothingQuality="high";for(const e of p){const o=v?`${v} ${e}`:e;if(t.measureText(o).width<=n)v=o;else if(v.trim()&&g.push(v),v=e,t.measureText(v).width>n){let e=v;for(;t.measureText(e+"...").width>n&&e.length>0;)e=e.slice(0,-1);g.push(e+"..."),b=!0;break}if(g.length>=y){x=!0;break}}if(v&&g.length<y&&!b&&g.push(v),x&&g.length>0){let e=g[g.length-1];for(;t.measureText(e+"...").width>n&&e.length>0;)e=e.slice(0,-1);g[g.length-1]=e+"..."}return g}(d,e.label,r,t.maxLines,i,f,y,m,h),s=o-(l.length-1)*a/2;l.forEach((t,e)=>{const o=Math.round(n),i=Math.round(s+e*a);d.fillText(t,o,i)})}else d.fillText(e.label,Math.round(n),Math.round(o))})):console.warn("canvas or ctx is not valid")}function m(t,e){const n=window.devicePixelRatio||1,o=t.getBoundingClientRect();return t.width=o.width*n,t.height=o.height*n,t.style.width=`${o.width}px`,t.style.height=`${o.height}px`,e.setTransform(1,0,0,1,0,0),e.scale(n,n),{width:o.width,height:o.height,dpr:n}}function y(){const n=document.getElementById(t.canvasContainerId);n&&e&&(e.width=n.offsetWidth,e.height=n.offsetHeight,e.getContext("2d"),f())}let p;t.isResizeCanvasOnWindowSizeChange&&(y(),window.addEventListener("resize",y)),f(),t.showToolTip&&(p=function(t){var e,n,i,r,a,l,s,d,u,c,h,f,m,y,p,v,g,x;const b=null===(n=null===(e=t.data[0].toolTipConfig)||void 0===e?void 0:e.tooltipFormattedData)||void 0===n?void 0:n.trim();if(b){const e=document.createElement("div");e.innerHTML=b.trim();const n=e.firstElementChild;return n.style.display="none",n.style.visibility="hidden",n.style.opacity="0",n.style.position="absolute",o(n,t.canvasContainerId)}const M=document.createElement("div");M.id="bubbleChartTooltip",M.style.display="none";const C=null!==(i=null==t?void 0:t.tooltipOptions)&&void 0!==i?i:{},S=(t,e)=>"number"==typeof t?`${t}px`:null!=t?t:e;return Object.assign(M.style,{position:"absolute",padding:S(C.padding,"8px"),margin:S(C.margin,"0"),background:null!==(r=C.backgroundColor)&&void 0!==r?r:"rgba(0, 0, 0, 0.85)",color:null!==(a=C.fontColor)&&void 0!==a?a:"white",borderRadius:"4px",pointerEvents:null!==(l=C.pointerEvents)&&void 0!==l?l:"none",fontFamily:null!==(s=C.fontFamily)&&void 0!==s?s:"Arial, sans-serif",fontSize:S(C.fontSize,"14px"),fontWeight:String(null!==(d=C.fontWeight)&&void 0!==d?d:"400"),fontStyle:null!==(u=C.fontStyle)&&void 0!==u?u:"normal",textAlign:null!==(c=C.textAlign)&&void 0!==c?c:"left",textDecoration:null!==(h=C.textDecoration)&&void 0!==h?h:"none",textTransform:null!==(f=C.textTransform)&&void 0!==f?f:"none",letterSpacing:S(C.letterSpacing,"normal"),border:(()=>{var t;if(!C.borderStyle)return"none";const e=S(C.borderWidth,"1px"),n=null!==(t=C.borderColor)&&void 0!==t?t:"transparent";return`${e} ${C.borderStyle} ${n}`})(),boxShadow:null!==(m=C.boxShadow)&&void 0!==m?m:"none",maxWidth:S(C.maxWidth,"200px"),minWidth:S(C.minWidth,"auto"),maxHeight:S(C.maxHeight,"none"),minHeight:S(C.minHeight,"auto"),zIndex:String(null!==(y=C.zIndex)&&void 0!==y?y:1e3),transition:null!==(p=C.transition)&&void 0!==p?p:"opacity 0.2s",transform:null!==(v=C.transform)&&void 0!==v?v:"none",backdropFilter:null!==(g=C.backdropFilter)&&void 0!==g?g:"none",opacity:String(null!==(x=C.opacity)&&void 0!==x?x:1),display:"none",visibility:"hidden"}),o(M,t.canvasContainerId),M}(t));let v=null;if(e.addEventListener("mousemove",o=>{v||(v=requestAnimationFrame(()=>{(function(t,e,o,a,l){const{mouseX:s,mouseY:d}=i(t,o),u=r(s,d,e);n=(null==l?void 0:l.cursorType)||"pointer",o.style.cursor="default",a&&(u?function(t,e,o,i){if(e&&e.value&&o&&i){o.style.cursor=n,i.style.display="block",i.innerHTML=function(t){var e,n,o;if(!t)return"";const i=null===(n=null===(e=t.toolTipConfig)||void 0===e?void 0:e.tooltipText)||void 0===n?void 0:n.trim();if(i)return`<div>${i}</div>`;const r=null===(o=t.label)||void 0===o?void 0:o.trim();return r?`<div>${r}<br>Value: ${t.value}</div>`:`<div>${t.value}</div>`}(e);const r=o.getBoundingClientRect();i.style.left=t.clientX-r.left+15+"px",i.style.top=t.clientY-r.top+15+"px",i.style.zIndex="999999",i.style.visibility="visible",i.style.opacity="1",i.style.position="absolute"}}(t,u,o,a):(o.style.cursor="default",a.style.display="none",a.style.visibility="hidden",a.style.opacity="0"))})(o,h,e,p,t),v=null}))}),t.onBubbleClick){let n=null;e.addEventListener("click",o=>{n||(n=requestAnimationFrame(()=>{!function(t,e,n,o){const{mouseX:a,mouseY:l}=i(t,n),s=r(a,l,e);null!=s&&o.onBubbleClick&&o.onBubbleClick(s,t)}(o,h,e,t),n=null}))})}}const u={defaultBubbleColor:"#3498DB",defaultFontColor:"#ffffff",minRadius:10,maxLines:"auto",textWrap:!0,isResizeCanvasOnWindowSizeChange:!0,fontSize:14,defaultFontFamily:"Arial",showToolTip:!0};function c(t={}){var e,n;if(!t)return void console.error("Configuration is not valid. Chart initialization aborted.");if(!t.data||0===t.data.length)return void console.error("No valid data provided. Chart initialization aborted.");const o=(i=Object.assign({canvasContainerId:null!==(e=t.canvasContainerId)&&void 0!==e?e:"chart-container",data:null!==(n=t.data)&&void 0!==n?n:[]},t),Object.assign(Object.assign({},u),i));var i;return d(o),o}class h{constructor(t){const e=c(t);e&&(this.configuration=e)}render(){this.configuration&&d(this.configuration)}}return window.initializeChart=c,e})());
1
+ !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("BubbleChart",[],e):"object"==typeof exports?exports.BubbleChart=e():t.BubbleChart=e()}(this,()=>(()=>{"use strict";var t={d:(e,n)=>{for(var i in n)t.o(n,i)&&!t.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:n[i]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{BubbleChart:()=>m,initializeChart:()=>y});const n={defaultBubbleColor:"#3498DB",defaultFontColor:"#ffffff",minRadius:10,maxLines:"auto",textWrap:!0,isResizeCanvasOnWindowSizeChange:!0,fontSize:14,defaultFontFamily:"Arial",showToolTip:!0},i=JSON.parse('{"FC":0.008,"rX":1000,"d6":0.65,"WH":0.02,"ND":0.12,"$l":0.8,"cg":0.3,"e0":35}');function o(t,e){t.forEach((n,i)=>{t.forEach((t,o)=>{if(i>=o)return;if(0===i||0===o){const e=0===i?n:t,o=0===i?t:n,a=o.x-e.x,r=o.y-e.y,l=Math.hypot(a,r),s=e.radius+o.radius+2;if(l<s){const t=s-l,e=Math.atan2(r,a);o.x+=Math.cos(e)*t*.7,o.y+=Math.sin(e)*t*.7}return}const a=n.x-t.x,r=n.y-t.y,l=Math.hypot(a,r),s=n.radius+t.radius-5;if(l<s){const i=(s-l)*(.3+5*e.forceStrength),o=Math.atan2(r,a),d=n.radius+t.radius,c=d>0?t.radius/d:.5;n.fixed||(n.x+=Math.cos(o)*i*c,n.y+=Math.sin(o)*i*c),t.fixed||(t.x-=Math.cos(o)*i*(1-c),t.y-=Math.sin(o)*i*(1-c))}})})}function a(t,e=14,n=400,i=6){const o=n>=700?1.25:n>=500?1.1:1,a=Math.min(t/i,t/1.2);let r=Math.min(e*o,a,.8*t);return r=Math.max(r,Math.max(8,t/6)),Math.round(r)}class r{constructor(t){this.canvas=t;const e=t.getContext("2d");if(!e)throw new Error("Failed to get 2D rendering context from canvas");this.ctx=e}getContext(){return this.ctx}getCanvas(){return this.canvas}setup(){const t=window.devicePixelRatio||1,e=this.canvas.getBoundingClientRect();return this.canvas.width=e.width*t,this.canvas.height=e.height*t,this.canvas.style.width=`${e.width}px`,this.canvas.style.height=`${e.height}px`,this.ctx.setTransform(1,0,0,1,0,0),this.ctx.scale(t,t),{width:e.width,height:e.height}}getSize(){const t=this.canvas.getBoundingClientRect();return{width:t.width,height:t.height}}clear(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height)}drawCircle(t,e,n,i,o,a,r){this.ctx.beginPath(),this.ctx.arc(t,e,n,0,2*Math.PI),this.ctx.fillStyle=i,this.ctx.fill(),a>0&&(this.ctx.strokeStyle=o,this.ctx.lineWidth=a,this.ctx.stroke())}drawText(t,e,n,i){const o=`${i.fontStyle} ${i.fontWeight} ${i.fontSize}px ${i.fontFamily}`;this.ctx.fillStyle=i.fontColor,this.ctx.font=o,this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.ctx.textAlign=i.textAlign,this.ctx.textBaseline=i.textBaseline,this.ctx.fillText(t,Math.round(e),Math.round(n))}destroy(){const t=this.canvas.parentElement;t&&t.removeChild(this.canvas)}}class l{constructor(t){this.ctx=t}measureWidth(t,e,n,i,o){return this.ctx.font=`${i} ${n} ${e}px ${o}`,this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.ctx.measureText(t).width}}function s(t,e){const n=`bubbleChartTooltip-${e}`;return document.body.querySelector(`#${n}`)||(t.id=n,document.body.appendChild(t),t)}function d(t,e){const n=e.getBoundingClientRect(),i=window.devicePixelRatio||1;return{mouseX:(t.clientX-n.left)*i,mouseY:(t.clientY-n.top)*i}}function c(t,e,n){return n.find(n=>Math.hypot(t-n.x,e-n.y)<n.radius)||null}function u(t){let e=null;return{handle:n=>{e||(e=requestAnimationFrame(()=>{t(n),e=null}))},cancel:()=>{e&&(cancelAnimationFrame(e),e=null)}}}class h{}function f(t){if(!function(t){return t?!(!Array.isArray(t.data)||0===t.data.length)||(console.error("Invalid or empty data array"),!1):(console.error("Invalid config object"),!1)}(t))return;const e=function(t){var e,n;const i=document.getElementById(t.canvasContainerId);if(!i)return console.error(`Canvas container with ID '${t.canvasContainerId}' not found.`),null;if(i.querySelector("canvas"))return console.error("A canvas already exists inside the container."),null;const o=document.createElement("canvas");return Object.assign(o.style,{border:(null===(e=t.canvasBorderColor)||void 0===e?void 0:e.trim())?`1px solid #${t.canvasBorderColor}`:h.TRANSPARENT,background:(null===(n=t.canvasBackgroundColor)||void 0===n?void 0:n.trim())?`#${t.canvasBackgroundColor}`:h.TRANSPARENT,width:"100%",height:"100%",display:"block",imageRendering:"crisp-edges",aspectRatio:"1 / 1"}),o.style.setProperty("image-rendering","-moz-crisp-edges"),o.style.setProperty("image-rendering","-webkit-optimize-contrast"),o.style.setProperty("-ms-interpolation-mode","nearest-neighbor"),i.appendChild(o),o}(t);if(!e)return;const n=new r(e),m=new l(n.getContext()),{width:y,height:v}=n.setup();let x=function(t,e,n,a){const r=Object.assign({forceStrength:i.FC,iterations:i.rX,damping:i.d6,boundaryForce:i.WH,centerForce:i.ND,centerAttraction:i.$l,centerDamping:i.cg,centerRadiusBuffer:i.e0},a),l=Math.min((e-10)/2,(n-10)/2),s=e/2,d=n/2,c=[...t].sort((t,e)=>e.value-t.value).map(t=>Object.assign(Object.assign({},t),{radius:0,x:0,y:0,fixed:!1}));if(0===c.length)return c;const u=c[0].value,h=Math.min(.5*l,.2*Math.min(e,n)),f=Math.max(.3*h,.05*Math.min(e,n));return c.forEach(t=>{const i=u>0?t.value/u:1;t.radius=f+i*(h-f),t.radius=Math.max(0,Math.min(t.radius,(e-10)/2,(n-10)/2))}),c.forEach((t,i)=>{if(0===i)t.x=s,t.y=d,t.fixed=!0;else{const o=c[0].radius+t.radius+3,a=Math.PI*(3-Math.sqrt(5)),r=e-5-t.radius,l=n-5-t.radius;t.x=Math.min(r,Math.max(5+t.radius,s+Math.cos(a*i)*o)),t.y=Math.min(l,Math.max(5+t.radius,d+Math.sin(a*i)*o)),t.fixed=!1}}),function(t,e,n,i,a,r,l){for(let i=0;i<e.iterations;i++)t.forEach((i,o)=>{if(0===o){const t=a-i.x,n=r-i.y;return void(Math.hypot(t,n)>2&&(i.x+=t*e.centerDamping,i.y+=n*e.centerDamping))}let s=0,d=0;const c=i.radius+5;i.x<c?s+=(c-i.x)*e.boundaryForce:i.x>n-c&&(s+=(n-c-i.x)*e.boundaryForce),t.forEach(t=>{if(i===t)return;const n=i.x-t.x,o=i.y-t.y,c=Math.hypot(n,o),u=i.radius+t.radius;if(c<1.5*u){const t=e.forceStrength*(u/Math.max(c,.1));s+=n/c*t,d+=o/c*t}const h=a-i.x,f=r-i.y,m=Math.hypot(h,f),y=i.value/l*.02;i.x+=h/m*y,i.y+=f/m*y});const u=a-i.x,h=r-i.y,f=Math.hypot(u,h),m=t[0].radius+i.radius+e.centerRadiusBuffer,y=e.centerAttraction*(1-i.value/l)*(1-Math.min(1,f/m));i.x+=u*y,i.y+=h*y,i.x+=s*(1-e.damping),i.y+=d*(1-e.damping)}),o(t,e)}(c,r,e,0,s,d,u),function(t,e,n){t.forEach(t=>{const i=Math.max(5+t.radius,Math.min(e-5-t.radius,t.x)),o=Math.max(5+t.radius,Math.min(n-5-t.radius,t.y));(!t.fixed||Math.hypot(t.x-i,t.y-o)>2)&&(t.x=i,t.y=o)})}(c,e,n),c}(t.data,y,v);function g(){n.setup(),n.clear(),x.forEach(e=>{const i=function(t,e,n){var i,o,r,l,s,d,c,u,h,f,m;let y=null!==(i=n.defaultBubbleColor)&&void 0!==i?i:"#3498db";if(t.bubbleColor)y=t.bubbleColor;else if(n.colorPalette&&n.colorPalette.length>0){const i=e.findIndex(e=>e.label===t.label&&e.value===t.value),o=i>=0?i:0;y=n.colorPalette[o%n.colorPalette.length]}const v=Math.max(t.radius||0,n.minRadius||10);return{bubbleColor:y,borderColor:null!==(o=t.borderColor)&&void 0!==o?o:"black",borderThickness:Math.max(null!==(r=t.borderThickness)&&void 0!==r?r:.25,0),opacity:void 0!==t.opacity?Math.max(0,Math.min(1,t.opacity)):1,fontStyle:t.fontStyle||"normal",fontWeight:"number"==typeof t.fontWeight&&t.fontWeight>=100&&t.fontWeight<=900?t.fontWeight:400,textAlign:null!==(l=t.textAlign)&&void 0!==l?l:"center",textTransform:null!==(s=t.textTransform)&&void 0!==s?s:"none",fontColor:null!==(c=null!==(d=t.fontColor)&&void 0!==d?d:n.defaultFontColor)&&void 0!==c?c:"#000",textBaseline:null!==(u=t.textBaseline)&&void 0!==u?u:"middle",fontSize:Math.max(a(v,null!==(h=n.fontSize)&&void 0!==h?h:14,null!==(f=t.fontWeight)&&void 0!==f?f:400),8),fontFamily:t.fontFamily&&"string"==typeof t.fontFamily&&"Arial"!==t.fontFamily?`${t.fontFamily}, Arial, sans-serif`:`${null!==(m=n.defaultFontFamily)&&void 0!==m?m:"Arial"}, sans-serif`}}(e,x,t);n.drawCircle(e.x,e.y,Math.max(e.radius||0,t.minRadius||10),i.bubbleColor,i.borderColor,i.borderThickness,i.opacity);let o=e.label||"";"uppercase"===i.textTransform?o=o.toUpperCase():"lowercase"===i.textTransform?o=o.toLowerCase():"capitalize"===i.textTransform&&(o=o.replace(/\b\w/g,t=>t.toUpperCase()));const r=Math.max(e.radius||0,t.minRadius||10),l={fontSize:i.fontSize,fontFamily:i.fontFamily,fontWeight:i.fontWeight,fontStyle:i.fontStyle,fontColor:i.fontColor,textAlign:i.textAlign,textBaseline:i.textBaseline};if(t.textWrap){const o=1.5*r-10,a=1.4*i.fontSize,s=function(t,e,n,i,o,a=14,r=400,l="normal",s="Arial",d=0,c=5,u=1.2){const h=1.5*(o-c),f=a*u,m=Math.max(1,Math.floor(h/f)),y="auto"===i||void 0===i?m:Math.min(i,m);n=Math.max(0,n-2*d);const v=e.split(" ");let x="";const g=[];let p=!1,b=!1;const C=e=>t.measureWidth(e,a,r,l,s);for(const t of v){const e=x?`${x} ${t}`:t;if(C(e)<=n)x=e;else if(x.trim()&&g.push(x),x=t,C(x)>n){let t=x;for(;C(t+"...")>n&&t.length>0;)t=t.slice(0,-1);g.push(t+"..."),b=!0;break}if(g.length>=y){p=!0;break}}if(x&&g.length<y&&!b&&g.push(x),p&&g.length>0){let t=g[g.length-1];for(;C(t+"...")>n&&t.length>0;)t=t.slice(0,-1);g[g.length-1]=t+"..."}return g}(m,e.label,o,t.maxLines,r,i.fontSize,i.fontWeight,i.fontStyle,i.fontFamily),d=e.y-(s.length-1)*a/2;s.forEach((t,i)=>{n.drawText(t,e.x,d+i*a,l)})}else n.drawText(o,e.x,e.y,l)})}let p=null;if(t.isResizeCanvasOnWindowSizeChange){const e=document.getElementById(t.canvasContainerId);e&&(p=function(t,e){let n=null,i=null;const o=()=>{i||(i=requestAnimationFrame(()=>{e(),i=null}))};return"undefined"!=typeof ResizeObserver?(n=new ResizeObserver(o),n.observe(t)):(o(),window.addEventListener("resize",o)),{destroy:()=>{n&&(n.disconnect(),n=null),window.removeEventListener("resize",o),i&&(cancelAnimationFrame(i),i=null)}}}(e,()=>{const t=n.getCanvas();e&&t&&(t.width=e.offsetWidth,t.height=e.offsetHeight,g())}))}g();let b=null;t.showToolTip&&(b=function(t){var e,n,i,o,a,r,l,d,c,u,h,f,m,y,v,x,g,p,b;const C=null===(i=null===(n=null===(e=t.data[0])||void 0===e?void 0:e.toolTipConfig)||void 0===n?void 0:n.tooltipFormattedData)||void 0===i?void 0:i.trim();if(C){const e=document.createElement("div");e.innerHTML=C.trim();const n=e.firstElementChild;return n.style.display="none",n.style.visibility="hidden",n.style.opacity="0",n.style.position="absolute",s(n,t.canvasContainerId)}const M=document.createElement("div");M.style.display="none";const w=null!==(o=null==t?void 0:t.tooltipOptions)&&void 0!==o?o:{},S=(t,e)=>"number"==typeof t?`${t}px`:null!=t?t:e;return Object.assign(M.style,{position:"absolute",padding:S(w.padding,"8px"),margin:S(w.margin,"0"),background:null!==(a=w.backgroundColor)&&void 0!==a?a:"rgba(0, 0, 0, 0.85)",color:null!==(r=w.fontColor)&&void 0!==r?r:"white",borderRadius:"4px",pointerEvents:null!==(l=w.pointerEvents)&&void 0!==l?l:"none",fontFamily:null!==(d=w.fontFamily)&&void 0!==d?d:"Arial, sans-serif",fontSize:S(w.fontSize,"14px"),fontWeight:String(null!==(c=w.fontWeight)&&void 0!==c?c:"400"),fontStyle:null!==(u=w.fontStyle)&&void 0!==u?u:"normal",textAlign:null!==(h=w.textAlign)&&void 0!==h?h:"left",textDecoration:null!==(f=w.textDecoration)&&void 0!==f?f:"none",textTransform:null!==(m=w.textTransform)&&void 0!==m?m:"none",letterSpacing:S(w.letterSpacing,"normal"),border:(()=>{var t;if(!w.borderStyle)return"none";const e=S(w.borderWidth,"1px"),n=null!==(t=w.borderColor)&&void 0!==t?t:"transparent";return`${e} ${w.borderStyle} ${n}`})(),boxShadow:null!==(y=w.boxShadow)&&void 0!==y?y:"none",maxWidth:S(w.maxWidth,"200px"),minWidth:S(w.minWidth,"auto"),maxHeight:S(w.maxHeight,"none"),minHeight:S(w.minHeight,"auto"),zIndex:String(null!==(v=w.zIndex)&&void 0!==v?v:1e3),transition:null!==(x=w.transition)&&void 0!==x?x:"opacity 0.2s",transform:null!==(g=w.transform)&&void 0!==g?g:"none",backdropFilter:null!==(p=w.backdropFilter)&&void 0!==p?p:"none",opacity:String(null!==(b=w.opacity)&&void 0!==b?b:1),display:"none",visibility:"hidden"}),s(M,t.canvasContainerId),M}(t));const C=n.getCanvas(),M=u(e=>{const{mouseX:n,mouseY:i}=d(e,C),o=c(n,i,x);if(o){const n=(null==t?void 0:t.cursorType)||"pointer";if(C.style.cursor=n,b){const n=function(t,e){var n,i,o;if(!t)return"";if(e.tooltipOptions&&"function"==typeof e.tooltipOptions.formatter)return e.tooltipOptions.formatter(t);const a=null===(i=null===(n=t.toolTipConfig)||void 0===n?void 0:n.tooltipText)||void 0===i?void 0:i.trim();if(a)return`<div>${a}</div>`;const r=null===(o=t.label)||void 0===o?void 0:o.trim();return r?`<div>${r}<br>Value: ${t.value}</div>`:`<div>${t.value}</div>`}(o,t);!function(t,e,n,i){e&&n&&(e.style.display="block",e.innerHTML=i,e.style.left=`${t.pageX+15}px`,e.style.top=`${t.pageY+15}px`,e.style.zIndex="999999",e.style.visibility="visible",e.style.opacity="1",e.style.position="absolute")}(e,b,C,n)}}else C.style.cursor="default",function(t){t&&(t.style.display="none",t.style.visibility="hidden",t.style.opacity="0")}(b)});C.addEventListener("mousemove",M.handle);const w=u(e=>{const{mouseX:n,mouseY:i}=d(e,C),o=c(n,i,x);o&&t.onBubbleClick&&t.onBubbleClick(o,e)});t.onBubbleClick&&C.addEventListener("click",w.handle);const S=()=>{null==p||p.destroy(),M.cancel(),w.cancel(),C.removeEventListener("mousemove",M.handle),C.removeEventListener("click",w.handle),n.destroy(),(null==b?void 0:b.parentElement)&&b.parentElement.removeChild(b),b=null};return{destroy:S,update:e=>(S(),t.data=e,f(t))}}h.TRANSPARENT="transparent";class m{constructor(t){const e=function(t={}){var e,i;if(!t)return void console.error("Configuration is not valid. Chart initialization aborted.");if(!t.data||0===t.data.length)return void console.error("No valid data provided. Chart initialization aborted.");const o=(a=Object.assign({canvasContainerId:null!==(e=t.canvasContainerId)&&void 0!==e?e:"chart-container",data:null!==(i=t.data)&&void 0!==i?i:[]},t),Object.assign(Object.assign({},n),a));var a;const r=f(o);return r?{config:o,instance:r}:void 0}(t);e&&(this.configuration=e.config,this.instance=e.instance)}destroy(){this.instance&&this.instance.destroy()}update(t){this.instance&&(this.instance=this.instance.update(t))}}function y(t){return new m(t)}return"undefined"!=typeof window&&(window.initializeChart=y,window.BubbleChart=m),e})());
@@ -0,0 +1,194 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>BubbleChartJS Test</title>
7
+ <style>
8
+ body {
9
+ font-family: Arial, sans-serif;
10
+ margin: 20px;
11
+ background-color: #f4f4f9;
12
+ }
13
+ .container {
14
+ display: flex;
15
+ flex-direction: column;
16
+ gap: 20px;
17
+ max-width: 800px;
18
+ margin: 0 auto;
19
+ }
20
+ .controls {
21
+ display: flex;
22
+ gap: 10px;
23
+ padding: 15px;
24
+ background: white;
25
+ border-radius: 8px;
26
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
27
+ }
28
+ button {
29
+ padding: 8px 16px;
30
+ cursor: pointer;
31
+ border: none;
32
+ border-radius: 4px;
33
+ background-color: #007bff;
34
+ color: white;
35
+ font-weight: bold;
36
+ }
37
+ button:hover {
38
+ background-color: #0056b3;
39
+ }
40
+ button.danger {
41
+ background-color: #dc3545;
42
+ }
43
+ button.danger:hover {
44
+ background-color: #a71d2a;
45
+ }
46
+ #chart-container {
47
+ width: 100%;
48
+ height: 400px;
49
+ background: white;
50
+ border-radius: 8px;
51
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
52
+ position: relative; /* important for tooltip */
53
+ }
54
+ #log {
55
+ padding: 15px;
56
+ background: #333;
57
+ color: #0f0;
58
+ font-family: monospace;
59
+ border-radius: 8px;
60
+ min-height: 100px;
61
+ }
62
+ </style>
63
+ </head>
64
+ <body>
65
+ <div class="container">
66
+ <h2>BubbleChartJS Testing Playground</h2>
67
+
68
+ <div class="controls">
69
+ <button id="btn-update">Update Data (Dynamic Update)</button>
70
+ <button id="btn-destroy" class="danger">Destroy Chart</button>
71
+ <button id="btn-recreate">Recreate Chart</button>
72
+ <button id="btn-resize">Change Container Size (Responsive)</button>
73
+ </div>
74
+
75
+ <div id="chart-container"></div>
76
+
77
+ <div id="log">Logs will appear here...<br></div>
78
+ </div>
79
+
80
+ <!-- Load the UMD bundle -->
81
+ <script src="../dist/bubbleChart.umd.js?v=2"></script>
82
+
83
+ <script>
84
+ const logEl = document.getElementById('log');
85
+ function log(msg) {
86
+ logEl.innerHTML += `> ${msg}<br>`;
87
+ logEl.scrollTop = logEl.scrollHeight;
88
+ }
89
+
90
+ let chartInstance = null;
91
+
92
+ const dataset1 = [
93
+ { label: "Sales", value: 50 },
94
+ { label: "Marketing", value: 30 },
95
+ { label: "Engineering", value: 80 },
96
+ { label: "HR", value: 20 },
97
+ { label: "Customer Support", value: 45 }
98
+ ];
99
+
100
+ const dataset2 = [
101
+ { label: "Alpha", value: 90 },
102
+ { label: "Beta", value: 60 },
103
+ { label: "Gamma", value: 40 }
104
+ ];
105
+
106
+ function createChart(data) {
107
+ if (chartInstance) {
108
+ log("Chart already exists. Destroy it first.");
109
+ return;
110
+ }
111
+
112
+ log("Initializing chart...");
113
+ chartInstance = window.initializeChart({
114
+ canvasContainerId: "chart-container",
115
+ data: data,
116
+ minRadius: 20,
117
+ maxLines: 3,
118
+ textWrap: true,
119
+ isResizeCanvasOnWindowSizeChange: true, // Responsive Resize
120
+ colorPalette: ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FFEEAD"], // Custom Color Palette
121
+ defaultFontColor: "#ffffff",
122
+ fontSize: 14,
123
+ showToolTip: true,
124
+ tooltipOptions: {
125
+ backgroundColor: "rgba(0, 0, 0, 0.9)",
126
+ fontColor: "#fff",
127
+ // GLOBAL TOOLTIP FORMATTER
128
+ formatter: (item) => {
129
+ return `<div style="text-align: center;">
130
+ <strong>🔥 Custom Formatter 🔥</strong><br>
131
+ <i>${item.label}</i><br>
132
+ <span style="color: #4ECDC4; font-size: 1.2em;">${item.value} units</span>
133
+ </div>`;
134
+ }
135
+ },
136
+ // BUBBLE CLICK EVENT
137
+ onBubbleClick: (bubble, event) => {
138
+ log(`Clicked on bubble: ${bubble.label} (Value: ${bubble.value})`);
139
+ }
140
+ });
141
+ log("Chart initialized.");
142
+
143
+ // Debugging the instance structure
144
+ log(`Instance Type: ${chartInstance.constructor ? chartInstance.constructor.name : 'Unknown'}`);
145
+ log(`Has update: ${!!chartInstance.update}`);
146
+ log(`Has destroy: ${!!chartInstance.destroy}`);
147
+ let props = [];
148
+ for (let k in chartInstance) { props.push(k); }
149
+ log(`Properties: ${props.join(', ')}`);
150
+ }
151
+
152
+ // 1. Initial Render
153
+ createChart(dataset1);
154
+
155
+ // 2. Dynamic Update binding
156
+ document.getElementById('btn-update').addEventListener('click', () => {
157
+ if (chartInstance && chartInstance.update) {
158
+ log("Updating chart with new dataset...");
159
+ chartInstance.update(dataset2);
160
+ } else {
161
+ log("Cannot update: Chart instance not found or doesn't support update().");
162
+ }
163
+ });
164
+
165
+ // 3. Destroy Method binding
166
+ document.getElementById('btn-destroy').addEventListener('click', () => {
167
+ if (chartInstance && chartInstance.destroy) {
168
+ log("Destroying chart...");
169
+ chartInstance.destroy();
170
+ chartInstance = null;
171
+ } else {
172
+ log("Cannot destroy: Chart instance not found or doesn't support destroy().");
173
+ }
174
+ });
175
+
176
+ // 4. Recreate binding
177
+ document.getElementById('btn-recreate').addEventListener('click', () => {
178
+ createChart(dataset1);
179
+ });
180
+
181
+ // 5. Responsive Resize binding
182
+ // Test ResizeObserver or Window Resize behavior
183
+ document.getElementById('btn-resize').addEventListener('click', () => {
184
+ const container = document.getElementById('chart-container');
185
+ const newWidth = container.style.width === '50%' ? '100%' : '50%';
186
+ container.style.width = newWidth;
187
+ log(`Resized container to ${newWidth}. Check if chart resizes correctly.`);
188
+ // Simulate window resize to trigger the window scale logic, since ResizeObserver is not implemented yet
189
+ window.dispatchEvent(new Event('resize'));
190
+ });
191
+
192
+ </script>
193
+ </body>
194
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bubble-chart-js",
3
- "version": "1.0.19",
3
+ "version": "1.1.0",
4
4
  "description": "bubbleChartJs is a lightweight, customizable JavaScript library for creating stacked bubble charts. It arranges bubbles based on their values, with the largest bubble positioned at the top and surrounding bubbles decreasing in size accordingly.",
5
5
  "main": "dist/bubbleChart.cjs.js",
6
6
  "module": "dist/bubbleChart.esm.js",
@@ -40,11 +40,14 @@
40
40
  "author": "Pragadeeshwaran Pasupathi <pragadeeshwaran.pasupathi@gmail.com>",
41
41
  "repository": {
42
42
  "type": "git",
43
- "url": "https://github.com/Praga-Dev/bubbleChartJS.git"
43
+ "url": "git+https://github.com/Praga-Dev/bubbleChartJS.git"
44
44
  },
45
45
  "license": "MIT",
46
46
  "keywords": [
47
+ "bubble",
48
+ "chart",
47
49
  "bubble chart",
50
+ "bubble chart js",
48
51
  "chartjs",
49
52
  "chart.js",
50
53
  "visualization",
@@ -58,4 +61,4 @@
58
61
  "data plotting",
59
62
  "bubble chartjs"
60
63
  ]
61
- }
64
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Conformance Test Fixture Generator
3
+ *
4
+ * Run with: npx ts-node --project tsconfig.json scripts/generate-fixtures.ts
5
+ *
6
+ * Reads all input fixtures from spec/fixtures/, runs them through the layout engine,
7
+ * and writes the expected output alongside each input file.
8
+ */
9
+
10
+ import * as fs from 'fs';
11
+ import * as path from 'path';
12
+ import { computeLayout } from '../src/core/layout-engine';
13
+
14
+ const fixturesDir = path.join(__dirname, '..', 'spec', 'fixtures');
15
+
16
+ const inputFiles = fs
17
+ .readdirSync(fixturesDir)
18
+ .filter((f) => f.endsWith('.input.json'));
19
+
20
+ for (const inputFile of inputFiles) {
21
+ const inputPath = path.join(fixturesDir, inputFile);
22
+ const input = JSON.parse(fs.readFileSync(inputPath, 'utf8'));
23
+
24
+ const result = computeLayout(input.data, input.width, input.height);
25
+
26
+ const expected = {
27
+ specVersion: input.specVersion || '1.0',
28
+ tolerance: 1.0,
29
+ nodes: result.map((node) => ({
30
+ label: node.label,
31
+ x: Math.round(node.x * 100) / 100,
32
+ y: Math.round(node.y * 100) / 100,
33
+ radius: Math.round(node.radius * 100) / 100,
34
+ fixed: node.fixed,
35
+ })),
36
+ };
37
+
38
+ const expectedFile = inputFile.replace('.input.json', '.expected.json');
39
+ const expectedPath = path.join(fixturesDir, expectedFile);
40
+
41
+ fs.writeFileSync(expectedPath, JSON.stringify(expected, null, 2) + '\n');
42
+ console.log(`Generated: ${expectedFile} (${expected.nodes.length} nodes)`);
43
+ }
44
+
45
+ console.log('Done! All expected fixtures generated.');
@@ -0,0 +1,16 @@
1
+ {
2
+ "specVersion": "1.0",
3
+ "defaultBubbleColor": "#3498DB",
4
+ "defaultFontColor": "#ffffff",
5
+ "minRadius": 10,
6
+ "maxLines": "auto",
7
+ "textWrap": true,
8
+ "fontSize": 14,
9
+ "defaultFontFamily": "Arial",
10
+ "showTooltip": true,
11
+ "enableResize": true,
12
+ "borderThickness": 0.25,
13
+ "borderColor": "#000000",
14
+ "opacity": 1.0,
15
+ "canvasPadding": 5
16
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "specVersion": "1.0",
3
+ "width": 800,
4
+ "height": 600,
5
+ "data": [
6
+ { "label": "Alpha", "value": 100 },
7
+ { "label": "Beta", "value": 50 },
8
+ { "label": "Gamma", "value": 25 }
9
+ ]
10
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "specVersion": "1.0",
3
+ "width": 800,
4
+ "height": 600,
5
+ "data": [
6
+ { "label": "A", "value": 50 },
7
+ { "label": "B", "value": 50 },
8
+ { "label": "C", "value": 50 },
9
+ { "label": "D", "value": 50 }
10
+ ]
11
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "specVersion": "1.0",
3
+ "width": 800,
4
+ "height": 600,
5
+ "data": [
6
+ { "label": "Item 1", "value": 100 },
7
+ { "label": "Item 2", "value": 90 },
8
+ { "label": "Item 3", "value": 80 },
9
+ { "label": "Item 4", "value": 70 },
10
+ { "label": "Item 5", "value": 60 },
11
+ { "label": "Item 6", "value": 50 },
12
+ { "label": "Item 7", "value": 40 },
13
+ { "label": "Item 8", "value": 30 },
14
+ { "label": "Item 9", "value": 20 },
15
+ { "label": "Item 10", "value": 10 }
16
+ ]
17
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "specVersion": "1.0",
3
+ "width": 800,
4
+ "height": 600,
5
+ "data": [
6
+ { "label": "Solo", "value": 100 }
7
+ ]
8
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "specVersion": "1.0",
3
+ "forceStrength": 0.008,
4
+ "iterations": 1000,
5
+ "damping": 0.65,
6
+ "boundaryForce": 0.02,
7
+ "centerForce": 0.12,
8
+ "centerAttraction": 0.8,
9
+ "centerDamping": 0.3,
10
+ "centerRadiusBuffer": 35
11
+ }
package/dist/canvas.d.ts DELETED
@@ -1,5 +0,0 @@
1
- import { Configuration } from "./models/public/configuration";
2
- /**
3
- * Creates and initializes the canvas inside the specified container.
4
- */
5
- export declare function createCanvas(config: Configuration): HTMLCanvasElement | null;
@@ -1,3 +0,0 @@
1
- export declare class AppConstants {
2
- static readonly TRANSPARENT = "transparent";
3
- }
@@ -1,10 +0,0 @@
1
- export declare const PHYSICS: {
2
- readonly forceStrength: 0.008;
3
- readonly iterations: 1000;
4
- readonly damping: 0.65;
5
- readonly boundaryForce: 0.02;
6
- readonly centerForce: 0.12;
7
- readonly centerAttraction: 0.8;
8
- readonly centerDamping: 0.3;
9
- readonly centerRadiusBuffer: 35;
10
- };
@@ -1,2 +0,0 @@
1
- import { Configuration } from "../models/public/configuration";
2
- export declare function renderChart(config: Configuration): void;
@@ -1,2 +0,0 @@
1
- export declare function getWrappedLines(ctx: CanvasRenderingContext2D, text: string, maxLineWidth: number, maxAllowedLines: number | "auto" | undefined, radius: number, fontSize?: number, // TODO : take all default values from constants
2
- fontWeight?: number, fontStyle?: "normal" | "italic" | "oblique", fontFamily?: string, horizontalPadding?: number, verticalPadding?: number, lineHeightFactor?: number, maxCharsPerWord?: number | undefined): string[];
@@ -1,6 +0,0 @@
1
- import { DataItemInfo } from "../models/internal/data-item-info";
2
- import { Configuration } from "../models/public/configuration";
3
- export declare function createTooltipElement(config: Configuration): HTMLDivElement | null;
4
- export declare function onBubbleClickEventHandler(// TODO : move to interactions.ts
5
- event: MouseEvent, data: DataItemInfo[], canvas: HTMLCanvasElement, config: Configuration): void;
6
- export declare function handleMouseMove(event: MouseEvent, data: DataItemInfo[], canvas: HTMLCanvasElement, tooltip: HTMLDivElement, config: Configuration): void;
package/dist/index.d.ts DELETED
@@ -1,8 +0,0 @@
1
- import { BubbleChart } from "./models/public/bubble-chart";
2
- import { initializeChart } from "./services/chart-service";
3
- export { initializeChart, BubbleChart };
4
- declare global {
5
- interface Window {
6
- initializeChart: typeof initializeChart;
7
- }
8
- }
@@ -1,7 +0,0 @@
1
- import { DataItem } from "../public/data-item";
2
- export interface DataItemInfo extends DataItem {
3
- radius: number;
4
- x: number;
5
- y: number;
6
- fixed: boolean;
7
- }
@@ -1,6 +0,0 @@
1
- import { Configuration } from "./configuration";
2
- export declare class BubbleChart {
3
- configuration: Configuration;
4
- constructor(config: Configuration);
5
- render(): void;
6
- }
@@ -1,26 +0,0 @@
1
- /**
2
- * Defines the appearance properties for a bubble.
3
- */
4
- export interface BubbleAppearance {
5
- /**
6
- * Bubble background color
7
- * @default "#3498DB"
8
- */
9
- bubbleColor?: string;
10
- /**
11
- * Border thickness (in pixels)
12
- * @default 0.25
13
- */
14
- borderThickness?: number;
15
- /**
16
- * Border color
17
- * @default "black"
18
- */
19
- borderColor?: string;
20
- /**
21
- * Opacity level (0: transparent, 1: fully visible)
22
- * @validValues 0 - 1
23
- * @default 1
24
- */
25
- opacity?: number;
26
- }
@@ -1,46 +0,0 @@
1
- /**
2
- * Defines the font-related styling options.
3
- */
4
- export interface FontOptions {
5
- /**
6
- * Custom font family
7
- * @example "Arial", "Verdana"
8
- * @default "Arial"
9
- */
10
- fontFamily?: string;
11
- /**
12
- * Font style
13
- * @validValues "normal" | "italic" | "oblique"
14
- * @default "normal"
15
- */
16
- fontStyle?: "normal" | "italic" | "oblique";
17
- /**
18
- * Font weight (numeric scale)
19
- * @validValues 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
20
- * @default 400
21
- */
22
- fontWeight?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
23
- /**
24
- * Text alignment
25
- * @validValues "center" | "end" | "left" | "right" | "start"
26
- * @default "center"
27
- */
28
- textAlign?: "center" | "end" | "left" | "right" | "start";
29
- /**
30
- * Text transformation style
31
- * @validValues "none" | "uppercase" | "lowercase" | "capitalize"
32
- * @default "none"
33
- */
34
- textTransform?: "none" | "uppercase" | "lowercase" | "capitalize";
35
- /**
36
- * Font color
37
- * @default "#000000"
38
- */
39
- fontColor?: string;
40
- /**
41
- * Text baseline position
42
- * @validValues "alphabetic" | "bottom" | "hanging" | "ideographic" | "middle" | "top"
43
- * @default "middle"
44
- */
45
- textBaseline?: "alphabetic" | "bottom" | "hanging" | "ideographic" | "middle" | "top";
46
- }
@@ -1,6 +0,0 @@
1
- export interface InteractionOptions {
2
- showToolTip?: boolean;
3
- isResizeCanvasOnWindowSizeChange?: boolean;
4
- cursorType?: "default" | "pointer" | "grab" | "crosshair" | "move" | "not-allowed" | "help";
5
- onBubbleClick?: (bubbleData: any, event: MouseEvent) => void;
6
- }
@@ -1,4 +0,0 @@
1
- export declare class ToolTipConfig {
2
- tooltipText?: string;
3
- tooltipFormattedData?: string;
4
- }
@@ -1,170 +0,0 @@
1
- export interface TooltipOptions {
2
- /**
3
- * CSS font-family property
4
- * @default "Arial, sans-serif"
5
- */
6
- fontFamily?: string;
7
- /**
8
- * Font style for tooltip text
9
- * @validValues "normal", "italic", "oblique"
10
- * @default "normal"
11
- */
12
- fontStyle?: "normal" | "italic" | "oblique";
13
- /**
14
- * Font weight (numeric scale)
15
- * @validValues 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
16
- * @default 400
17
- */
18
- fontWeight?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
19
- /**
20
- * Font size in pixels
21
- * @default 14
22
- */
23
- fontSize?: number;
24
- /**
25
- * Text alignment within tooltip
26
- * @validValues "left", "center", "right"
27
- * @default "left"
28
- */
29
- textAlign?: "left" | "center" | "right";
30
- /**
31
- * Text decoration style
32
- * @validValues "none", "underline", "line-through", "overline"
33
- * @default "none"
34
- */
35
- textDecoration?: "none" | "underline" | "line-through" | "overline";
36
- /**
37
- * Text transformation style
38
- * @validValues "none", "uppercase", "lowercase", "capitalize"
39
- * @default "none"
40
- */
41
- textTransform?: "none" | "uppercase" | "lowercase" | "capitalize";
42
- /**
43
- * Letter spacing in pixels (0 = normal)
44
- * @default undefined (normal spacing)
45
- */
46
- letterSpacing?: number;
47
- /**
48
- * Text color in CSS format
49
- * @default "white"
50
- */
51
- fontColor?: string;
52
- /**
53
- * Background color in CSS format
54
- * @default "rgba(0, 0, 0, 0.85)"
55
- */
56
- backgroundColor?: string;
57
- /**
58
- * Border color in CSS format
59
- * @default "transparent"
60
- */
61
- borderColor?: string;
62
- /**
63
- * Border style (requires borderWidth to be set)
64
- * @validValues "solid", "dashed", "dotted", "double", "none"
65
- * @default "none"
66
- */
67
- borderStyle?: "solid" | "dashed" | "dotted" | "double" | "none";
68
- /**
69
- * Border width (CSS value or number in pixels)
70
- * @example "2px", "0.5rem", 3
71
- */
72
- borderWidth?: string | number;
73
- /**
74
- * CSS padding value
75
- * @example "10px", "1em 2rem", "5% 10px"
76
- * @default "8px"
77
- */
78
- padding?: string | number;
79
- /**
80
- * CSS margin value
81
- * @example "10px auto", "2rem 1rem"
82
- * @default "0"
83
- */
84
- margin?: string | number;
85
- /**
86
- * CSS box-shadow property
87
- * @example "3px 3px 5px rgba(0,0,0,0.3)"
88
- * @default "none"
89
- */
90
- boxShadow?: string;
91
- /**
92
- * Opacity value (0 = fully transparent, 1 = fully opaque)
93
- * @minimum 0
94
- * @maximum 1
95
- * @default 1
96
- */
97
- opacity?: number;
98
- /**
99
- * Maximum width in pixels
100
- * @default 200
101
- */
102
- maxWidth?: number;
103
- /**
104
- * Minimum width in pixels
105
- * @default undefined (auto)
106
- */
107
- minWidth?: number;
108
- /**
109
- * Maximum height in pixels
110
- * @default undefined (none)
111
- */
112
- maxHeight?: number;
113
- /**
114
- * Minimum height in pixels
115
- * @default undefined (auto)
116
- */
117
- minHeight?: number;
118
- /**
119
- * Preferred position relative to target element
120
- * @validValues "top", "bottom", "left", "right"
121
- */
122
- position?: "top" | "bottom" | "left" | "right";
123
- /**
124
- * Horizontal offset in pixels
125
- * @default 0
126
- */
127
- offsetX?: number;
128
- /**
129
- * Vertical offset in pixels
130
- * @default 0
131
- */
132
- offsetY?: number;
133
- /**
134
- * CSS z-index property
135
- * @default 1000
136
- */
137
- zIndex?: number;
138
- /**
139
- * CSS pointer-events property
140
- * @validValues "auto", "none"
141
- * @default "none"
142
- */
143
- pointerEvents?: "auto" | "none";
144
- /**
145
- * Enable/disable animations
146
- * @default true
147
- */
148
- animation?: boolean;
149
- /**
150
- * Animation duration in milliseconds
151
- * @default 300
152
- */
153
- animationDuration?: number;
154
- /**
155
- * CSS backdrop-filter property
156
- * @example "blur(5px)"
157
- * @default "none"
158
- */
159
- backdropFilter?: string;
160
- /**
161
- * CSS transition property
162
- * @default "opacity 0.2s"
163
- */
164
- transition?: string;
165
- /**
166
- * CSS transform property
167
- * @default "none"
168
- */
169
- transform?: string;
170
- }
@@ -1,30 +0,0 @@
1
- import { InteractionOptions } from "./config/interaction-options";
2
- import { TooltipOptions } from "./config/tooltip-options";
3
- import { DataItem } from "./data-item";
4
- export interface Configuration extends InteractionOptions {
5
- data: DataItem[];
6
- canvasContainerId: string;
7
- /**
8
- * Background color of the canvas.
9
- *
10
- * @description Supports only HEX values (without `#`).
11
- * @default "transparent"
12
- */
13
- canvasBackgroundColor?: string;
14
- /**
15
- * Border color of the canvas.
16
- *
17
- * @description Supports only HEX values (without `#`).
18
- * @default "transparent"
19
- */
20
- canvasBorderColor?: string;
21
- minRadius: number;
22
- maxLines: number | "auto";
23
- textWrap: boolean;
24
- defaultBubbleColor: string;
25
- fontSize: number;
26
- defaultFontColor: string;
27
- defaultFontFamily: string;
28
- isResizeCanvasOnWindowSizeChange: boolean;
29
- tooltipOptions?: TooltipOptions;
30
- }
@@ -1,8 +0,0 @@
1
- import { BubbleAppearance } from "./config/bubble-appearance";
2
- import { FontOptions } from "./config/font-options";
3
- import { ToolTipConfig } from "./config/tooltip-config";
4
- export interface DataItem extends BubbleAppearance, FontOptions {
5
- label: string;
6
- value: number;
7
- toolTipConfig?: ToolTipConfig;
8
- }
@@ -1,5 +0,0 @@
1
- import { Configuration } from "../models/public/configuration";
2
- /**
3
- * Initializes the chart, but stops execution if no valid data is provided.
4
- */
5
- export declare function initializeChart(config?: Partial<Configuration>): Configuration | undefined;
@@ -1,3 +0,0 @@
1
- import { DataItemInfo } from "../models/internal/data-item-info";
2
- import { Configuration } from "../models/public/configuration";
3
- export declare function getChartData(config: Configuration, width: number, height: number): DataItemInfo[];
@@ -1,12 +0,0 @@
1
- import { Configuration } from "../models/public/configuration";
2
- /**
3
- * Default configuration object.
4
- */
5
- export declare const DEFAULT_CONFIG: Omit<Configuration, "canvasContainerId" | "data">;
6
- /**
7
- * Merges user config with defaults, ensuring `canvasContainerId` and `data` are required.
8
- */
9
- export declare function mergeConfig(customConfig: {
10
- canvasContainerId: string;
11
- data: Configuration["data"];
12
- } & Partial<Configuration>): Configuration;
@@ -1,2 +0,0 @@
1
- export declare function getFontSize(radius: number, fontSize?: number, fontWeight?: number, avgCharsPerLine?: number): number;
2
- export declare function isFontAvailable(font: string, fontSize?: string): boolean;
@@ -1,5 +0,0 @@
1
- import { Configuration } from "../models/public/configuration";
2
- /**
3
- * Validates configuration and ensures required properties exist.
4
- */
5
- export declare function validateConfig(config: Configuration): boolean;