bubble-chart-js 1.0.3 → 1.0.4

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 (46) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +35 -20
  3. package/assets/bubble-chart.png +0 -0
  4. package/commands.jsonc +13 -0
  5. package/dist/bubbleChart.cjs.js +1 -0
  6. package/dist/bubbleChart.esm.js +1 -0
  7. package/dist/bubbleChart.umd.js +1 -0
  8. package/dist/canvas.d.ts +2 -1
  9. package/dist/constants/app-constants.d.ts +3 -0
  10. package/dist/constants/physics.d.ts +3 -3
  11. package/dist/features/text-wrapper.d.ts +1 -0
  12. package/dist/features/tooltip.d.ts +4 -3
  13. package/dist/index.d.ts +1 -1
  14. package/dist/models/internal/{dataItemInfo.d.ts → data-item-info.d.ts} +1 -1
  15. package/dist/models/public/config/bubble-appearance.d.ts +32 -0
  16. package/dist/models/public/config/font-options.d.ts +46 -0
  17. package/dist/models/public/config/interaction-options.d.ts +5 -0
  18. package/dist/models/public/config/tooltip-config.d.ts +4 -0
  19. package/dist/models/public/config/tooltip-options.d.ts +170 -0
  20. package/dist/models/public/configuration.d.ts +25 -10
  21. package/dist/models/public/data-item.d.ts +8 -0
  22. package/dist/services/{renderService.d.ts → render-service.d.ts} +1 -1
  23. package/dist/utils/helper.d.ts +1 -1
  24. package/index.html +77 -0
  25. package/package.json +5 -3
  26. package/webpack.config.js +49 -14
  27. package/bubble-chart-js-1.0.0-old.tgz +0 -0
  28. package/dist/features/textWrapper.d.ts +0 -1
  29. package/dist/index.js +0 -187
  30. package/dist/models/public/dataItem.d.ts +0 -4
  31. package/src/canvas.ts +0 -33
  32. package/src/constants/physics.ts +0 -10
  33. package/src/core/renderer.ts +0 -110
  34. package/src/declaration.d.ts +0 -1
  35. package/src/features/textWrapper.ts +0 -168
  36. package/src/features/tooltip.ts +0 -95
  37. package/src/index.ts +0 -14
  38. package/src/models/internal/dataItemInfo.ts +0 -8
  39. package/src/models/public/configuration.ts +0 -16
  40. package/src/models/public/dataItem.ts +0 -4
  41. package/src/services/chartService.ts +0 -24
  42. package/src/services/renderService.ts +0 -262
  43. package/src/utils/config.ts +0 -33
  44. package/src/utils/helper.ts +0 -3
  45. package/src/utils/validation.ts +0 -18
  46. /package/dist/services/{chartService.d.ts → chart-service.d.ts} +0 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+
6
+
5
7
  ## [Unreleased] - Initial Commit
6
8
 
7
9
  ### 🚀 Added
package/README.md CHANGED
@@ -30,6 +30,12 @@ Social Media Metrics – Visualize engagement levels across platforms.
30
30
 
31
31
  Scientific Research – Show relationships in grouped experimental data.
32
32
 
33
+ ### 🎨 Example Output
34
+
35
+ Here’s an example of the bubble chart generated using this package:
36
+
37
+ ![Stacked Bubble Chart Example](./assets/bubble-chart.png)
38
+
33
39
  ## Installation
34
40
 
35
41
  You can install `bubbleChartJs` via npm:
@@ -45,29 +51,38 @@ npm install bubble-chart-js
45
51
  ```js
46
52
  import BubbleChart from "bubblechartjs";
47
53
 
48
- const config = {
49
- canvasContainerId: "bubbleChartCanvas",
50
- data: [
51
- { label: "A", value: 100 },
52
- { label: "B", value: 80 },
53
- { label: "C", value: 60 },
54
- ],
55
- colorMap: {
56
- A: "#ff5733",
57
- B: "#33ff57",
58
- C: "#3357ff",
59
- },
60
- defaultBubbleColor: "#cccccc",
54
+ const tooltipOptions = {
55
+ fontStyle: "italic",
56
+ fontWeight: 800,
57
+ textAlign: "center",
58
+ textDecoration: "underline",
59
+ textTransform: "uppercase",
60
+ fontColor: "#FFF",
61
+ };
62
+
63
+ const data = [
64
+ { label: "Biryani Battles", value: 89, bubbleColor: "#ff5733" },
65
+ { label: "Chai vs. Coffee", value: 70, bubbleColor: "#c70039" },
66
+ { label: "Bollywood Blockbusters", value: 90, bubbleColor: "#900c3f" },
67
+ { label: "IPL Fever", value: 85, bubbleColor: "#ffc300" },
68
+ { label: "Himalayan Treks", value: 65, bubbleColor: "#4caf50" },
69
+ { label: "Diwali Firecrackers", value: 95, bubbleColor: "#ff8c00" },
70
+ { label: "Street Food Craze", value: 75, bubbleColor: "#e91e63" },
71
+ { label: "Fastest Century Records", value: 88, bubbleColor: "#3f51b5" },
72
+ { label: "Royal Enfield Craze", value: 60, bubbleColor: "#795548" },
73
+ { label: "Digital Payment Boom", value: 93, bubbleColor: "#00bcd4" },
74
+ ];
75
+
76
+ const chartoptions = {
77
+ canvasContainerId: "bubbleChart",
78
+ data: data,
61
79
  fontSize: 14,
62
- fontFamily: "Arial",
63
- fontColor: "#000000",
64
- minRadius: 10,
65
80
  maxLines: 2,
66
- textWrap: true,
67
- isResizeCanvasOnWindowSizeChange: true,
81
+ tooltipOptions: tooltipOptions,
68
82
  };
69
83
 
70
- initializeChart(config);
84
+ // Initialize chart
85
+ initializeChart(chartoptions);
71
86
  ```
72
87
 
73
88
  ## Configuration Options
@@ -106,4 +121,4 @@ Contributions, issues, and feature requests are welcome!
106
121
 
107
122
  ---
108
123
 
109
- Made with ❤️ by Pragadeeshwaran
124
+ Made with ❤️ by Pragadeesh
Binary file
package/commands.jsonc ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "Project Build": "npm run build",
3
+ "Project Publish": "npm publish",
4
+ "Project Bundle": "npm pack",
5
+ "Project Link": "npm link",
6
+
7
+ //npm modules commands: In Client Code
8
+ "Remove node_modules and package-lock": "Remove-Item -Recurse -Force node_modules, package-lock.json",
9
+ "NPM unlink" : "npm unlink bubble-chart-js",
10
+ //"bubble-chart-js": "file:D:/NPM/bubbleChartJS",
11
+ // "bubble-chart-js": "^1.0.3",
12
+ "NPM link" : "npm link bubble-chart-js"
13
+ }
@@ -0,0 +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,{initializeChart:()=>d});let n="default";class o{}o.TRANSPARENT="transparent";const i={forceStrength:.008,iterations:1e3,damping:.65,boundaryForce:.02,centerForce:.12,centerAttraction:.8,centerDamping:.3,centerRadiusBuffer:35};function a(t,e=14,n=400){const o=n>=700?1.25:n>=500?1.1:1;return Math.min(e*o,t/2)}function r(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 i=document.getElementById(t.canvasContainerId);if(!i)return console.error(`Canvas container with ID '${t.canvasContainerId}' not found.`),null;const a=document.createElement("canvas");return a.width=i.offsetWidth,a.height=i.offsetHeight,console.log(t.canvasBackgroundColor),Object.assign(a.style,{border:(null===(e=t.canvasBorderColor)||void 0===e?void 0:e.trim())?`1px solid #${t.canvasBorderColor}`:o.TRANSPARENT,background:(null===(n=t.canvasBackgroundColor)||void 0===n?void 0:n.trim())?`#${t.canvasBackgroundColor}`:o.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"),i.appendChild(a),a}(t);if(!e)return;const r=e.getContext("2d");if(!r)return void console.error("Invalid context");const l=function(t,e,n){const o=Math.min((e.width-10)/2,(e.height-10)/2),a=window.devicePixelRatio||1,r=e.getBoundingClientRect();e.width=r.width*a,e.height=r.height*a,e.style.width=r.width+"px",e.style.height=r.height+"px",n.scale(a,a);const l=r.width/2,d=r.height/2,s=[...t.data].sort(((t,e)=>e.value-t.value)).map((t=>Object.assign(Object.assign({},t),{radius:0,x:0,y:0,fixed:!1}))),u=s[0].value,c=Math.min(1*o,100),h=Math.max(.3*c,30);s.forEach((t=>{const n=t.value/u;t.radius=h+n*(c-h),t.radius=Math.min(t.radius,(e.width-10)/2,(e.height-10)/2)})),s.forEach(((t,n)=>{if(0===n)t.x=l,t.y=d,t.fixed=!0;else{const o=s[0].radius+t.radius+3,i=Math.PI*(3-Math.sqrt(5)),a=e.width-5-t.radius,r=e.height-5-t.radius;t.x=Math.min(a,Math.max(5+t.radius,l+Math.cos(i*n)*o)),t.y=Math.min(r,Math.max(5+t.radius,d+Math.sin(i*n)*o)),t.fixed=!1}}));for(let t=0;t<i.iterations;t++)s.forEach(((t,n)=>{if(0===n){const e=l-t.x,n=d-t.y;return void(Math.hypot(e,n)>2&&(t.x+=e*i.centerDamping,t.y+=n*i.centerDamping))}let o=0,a=0;const r=t.radius+5;t.x<r?o+=(r-t.x)*i.boundaryForce:t.x>e.width-r&&(o+=(e.width-r-t.x)*i.boundaryForce),s.forEach((e=>{if(t===e)return;const n=t.x-e.x,r=t.y-e.y,s=Math.hypot(n,r),c=t.radius+e.radius;if(s<1.5*c){const t=i.forceStrength*(c/Math.max(s,.1));o+=n/s*t,a+=r/s*t}const h=l-t.x,f=d-t.y,v=Math.hypot(h,f),m=t.value/u*.02;t.x+=h/v*m,t.y+=f/v*m}));const c=l-t.x,h=d-t.y,f=Math.hypot(c,h),v=s[0].radius+t.radius+i.centerRadiusBuffer,m=(i.centerForce,Math.pow(t.value/u,.3),i.centerAttraction*(1-t.value/u)*(1-Math.min(1,f/v)));t.x+=c*m,t.y+=h*m,t.x+=o*(1-i.damping),t.y+=a*(1-i.damping)})),s.forEach(((t,e)=>{s.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),d=o.radius+i.radius+2;if(l<d){const t=d-l,e=Math.atan2(r,a);i.x+=Math.cos(e)*t*.7,i.y+=Math.sin(e)*t*.7}return}const a=t.x-n.x,r=t.y-n.y,l=Math.hypot(a,r),d=t.radius+n.radius-5;if(l<d){const e=(d-l)*(.3+5*i.forceStrength),o=Math.atan2(r,a),s=n.radius/(t.radius+n.radius);t.fixed||(t.x+=Math.cos(o)*e*s,t.y+=Math.sin(o)*e*s),n.fixed||(n.x-=Math.cos(o)*e*(1-s),n.y-=Math.sin(o)*e*(1-s))}}))}));return s.forEach((t=>{const n=Math.max(5+t.radius,Math.min(e.width-5-t.radius,t.x)),o=Math.max(5+t.radius,Math.min(e.height-5-t.radius,t.y));(!t.fixed||Math.hypot(t.x-n,t.y-o)>2)&&(t.x=n,t.y=o)})),s}(t,e,r);function d(){e&&r?(r.clearRect(0,0,e.width,e.height),l.forEach((e=>{const{x:n,y:o,radius:i,bubbleColor:l,borderColor:d,borderThickness:s,opacity:u,fontColor:c,fontFamily:h,fontSize:f,fontStyle:v,fontWeight:m,textAlign:g,textTransform:y,textBaseline:p}=function(t,e){var n,o,i,r,l,d,s,u,c,h,f;return{x:t.x,y:t.y,radius:Math.max(t.radius,e.minRadius),bubbleColor:null!==(n=t.bubbleColor)&&void 0!==n?n:e.defaultBubbleColor,borderColor:null!==(o=t.borderColor)&&void 0!==o?o:"black",borderThickness:null!==(i=t.borderThickness)&&void 0!==i?i:.25,opacity:null!==(r=t.opacity)&&void 0!==r?r:1,fontFamily:null!==(l=t.fontFamily)&&void 0!==l?l:e.defaultFontFamily,fontStyle:null!==(d=t.fontStyle)&&void 0!==d?d:"normal",fontWeight:null!==(s=t.fontWeight)&&void 0!==s?s:400,textAlign:null!==(u=t.textAlign)&&void 0!==u?u:"center",textTransform:null!==(c=t.textTransform)&&void 0!==c?c:"none",fontColor:null!==(h=t.fontColor)&&void 0!==h?h:e.defaultFontColor,textBaseline:null!==(f=t.textBaseline)&&void 0!==f?f:"middle",fontSize:a(t.radius,e.fontSize,t.fontWeight)}}(e,t);r.beginPath(),r.arc(n,o,i,0,2*Math.PI),r.fillStyle=l,r.fill(),r.strokeStyle=d,r.lineWidth=s,r.stroke(),r.fillStyle=c,r.font=`${v} ${m} ${f}px ${h}`,r.textAlign=g,r.textBaseline=p;let x=e.label||"";if("uppercase"===y?x=x.toUpperCase():"lowercase"===y?x=x.toLowerCase():"capitalize"===y&&(x=x.replace(/\b\w/g,(t=>t.toUpperCase()))),t.textWrap){const a=1.5*i-10,l=1.2*f,d=function(t,e,n,o,i,a,r=14,l=5,d=5,s=1.2){const u=1.5*(i-d),c=r*s,h=Math.max(1,Math.floor(u/c)),f="auto"===o||void 0===o?h:Math.min(o,h);n=Math.max(0,n-l);const v=e.split(" ");let m="";const g=[];let y=!1;for(const e of v){const o=m?`${m} ${e}`:e;if(t.measureText(o).width<=n?m=o:(m.trim()&&g.push(m),m=e),g.length>=f){y=!0;break}}if(m&&g.length<f&&g.push(m),y&&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}(r,e.label,a,t.maxLines,i),s=o-(d.length-1)*l/2;d.forEach(((t,e)=>r.fillText(t,n,s+e*l)))}else r.fillText(e.label,n,o)}))):console.warn("canvas or ctx is not valid")}function s(){const n=document.getElementById(t.canvasContainerId);n&&e&&(e.width=n.offsetWidth,e.height=n.offsetHeight,d())}if(t.isResizeCanvasOnWindowSizeChange&&(s(),window.addEventListener("resize",s)),d(),t.showToolTip){const o=function(t){var e,n,o,i,a,r,l,d,s,u,c,h,f,v,m,g,y,p;const x=null===(n=null===(e=t.data[0].toolTipConfig)||void 0===e?void 0:e.tooltipFormattedData)||void 0===n?void 0:n.trim();if(x){const e=document.createElement("div");e.innerHTML=x.trim();const n=t.canvasContainerId?document.getElementById(t.canvasContainerId):null,o=e.firstElementChild;return(n||document.body).appendChild(o),o}const b=document.createElement("div");b.id="tooltip",b.style.display="none";const C=null!==(o=null==t?void 0:t.tooltipOptions)&&void 0!==o?o:{},M=(t,e)=>"number"==typeof t?`${t}px`:null!=t?t:e;return Object.assign(b.style,{position:"absolute",padding:M(C.padding,"8px"),margin:M(C.margin,"0"),background:null!==(i=C.backgroundColor)&&void 0!==i?i:"rgba(0, 0, 0, 0.85)",color:null!==(a=C.fontColor)&&void 0!==a?a:"white",borderRadius:"4px",pointerEvents:null!==(r=C.pointerEvents)&&void 0!==r?r:"none",fontFamily:null!==(l=C.fontFamily)&&void 0!==l?l:"Arial, sans-serif",fontSize:M(C.fontSize,"14px"),fontWeight:String(null!==(d=C.fontWeight)&&void 0!==d?d:"400"),fontStyle:null!==(s=C.fontStyle)&&void 0!==s?s:"normal",textAlign:null!==(u=C.textAlign)&&void 0!==u?u:"left",textDecoration:null!==(c=C.textDecoration)&&void 0!==c?c:"none",textTransform:null!==(h=C.textTransform)&&void 0!==h?h:"none",letterSpacing:M(C.letterSpacing,"normal"),border:(()=>{var t;if(!C.borderStyle)return"none";const e=M(C.borderWidth,"1px"),n=null!==(t=C.borderColor)&&void 0!==t?t:"transparent";return`${e} ${C.borderStyle} ${n}`})(),boxShadow:null!==(f=C.boxShadow)&&void 0!==f?f:"none",opacity:String(null!==(v=C.opacity)&&void 0!==v?v:1),maxWidth:M(C.maxWidth,"200px"),minWidth:M(C.minWidth,"auto"),maxHeight:M(C.maxHeight,"none"),minHeight:M(C.minHeight,"auto"),zIndex:String(null!==(m=C.zIndex)&&void 0!==m?m:1e3),transition:null!==(g=C.transition)&&void 0!==g?g:"opacity 0.2s",transform:null!==(y=C.transform)&&void 0!==y?y:"none",backdropFilter:null!==(p=C.backdropFilter)&&void 0!==p?p:"none"}),((t.canvasContainerId?document.getElementById(t.canvasContainerId):null)||document.body).appendChild(b),b}(t);let i=null;e.addEventListener("mousemove",(a=>{i||(i=requestAnimationFrame((()=>{(function(t,e,o,i,a){const{mouseX:r,mouseY:l}=function(t,e){const n=e.getBoundingClientRect();return{mouseX:t.clientX-n.left,mouseY:t.clientY-n.top}}(t,o),d=function(t,e,n){return n.find((n=>Math.hypot(t-n.x,e-n.y)<n.radius))||null}(r,l,e);(null==a?void 0:a.cursorType)&&(n=null==a?void 0:a.cursorType),d?function(t,e,o,i){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),i.style.left=`${t.pageX+15}px`,i.style.top=t.pageY-30+"px",i.style.zIndex="9999")}(t,d,o,i):(o.style.cursor="default",i.style.display="none")})(a,l,e,o,t),i=null})))}))}}const l={defaultBubbleColor:"#3498DB",defaultFontColor:"#ffffff",minRadius:10,maxLines:"auto",textWrap:!0,isResizeCanvasOnWindowSizeChange:!0,fontSize:14,defaultFontFamily:"Arial",showToolTip:!0};function d(t={}){var e,n;if(!t.data||0===t.data.length)return void console.warn("initializeChart: No valid data provided. Chart initialization aborted.");var o;r((o=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({},l),o)))}window.initializeChart=d,module.exports=e})();
@@ -0,0 +1 @@
1
+ var t={d:(n,e)=>{for(var o in e)t.o(e,o)&&!t.o(n,o)&&Object.defineProperty(n,o,{enumerable:!0,get:e[o]})},o:(t,n)=>Object.prototype.hasOwnProperty.call(t,n)},n={};t.d(n,{$:()=>d});let e="default";class o{}o.TRANSPARENT="transparent";const i={forceStrength:.008,iterations:1e3,damping:.65,boundaryForce:.02,centerForce:.12,centerAttraction:.8,centerDamping:.3,centerRadiusBuffer:35};function a(t,n=14,e=400){const o=e>=700?1.25:e>=500?1.1:1;return Math.min(n*o,t/2)}function r(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 n=function(t){var n,e;const i=document.getElementById(t.canvasContainerId);if(!i)return console.error(`Canvas container with ID '${t.canvasContainerId}' not found.`),null;const a=document.createElement("canvas");return a.width=i.offsetWidth,a.height=i.offsetHeight,console.log(t.canvasBackgroundColor),Object.assign(a.style,{border:(null===(n=t.canvasBorderColor)||void 0===n?void 0:n.trim())?`1px solid #${t.canvasBorderColor}`:o.TRANSPARENT,background:(null===(e=t.canvasBackgroundColor)||void 0===e?void 0:e.trim())?`#${t.canvasBackgroundColor}`:o.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"),i.appendChild(a),a}(t);if(!n)return;const r=n.getContext("2d");if(!r)return void console.error("Invalid context");const l=function(t,n,e){const o=Math.min((n.width-10)/2,(n.height-10)/2),a=window.devicePixelRatio||1,r=n.getBoundingClientRect();n.width=r.width*a,n.height=r.height*a,n.style.width=r.width+"px",n.style.height=r.height+"px",e.scale(a,a);const l=r.width/2,d=r.height/2,s=[...t.data].sort(((t,n)=>n.value-t.value)).map((t=>Object.assign(Object.assign({},t),{radius:0,x:0,y:0,fixed:!1}))),u=s[0].value,c=Math.min(1*o,100),h=Math.max(.3*c,30);s.forEach((t=>{const e=t.value/u;t.radius=h+e*(c-h),t.radius=Math.min(t.radius,(n.width-10)/2,(n.height-10)/2)})),s.forEach(((t,e)=>{if(0===e)t.x=l,t.y=d,t.fixed=!0;else{const o=s[0].radius+t.radius+3,i=Math.PI*(3-Math.sqrt(5)),a=n.width-5-t.radius,r=n.height-5-t.radius;t.x=Math.min(a,Math.max(5+t.radius,l+Math.cos(i*e)*o)),t.y=Math.min(r,Math.max(5+t.radius,d+Math.sin(i*e)*o)),t.fixed=!1}}));for(let t=0;t<i.iterations;t++)s.forEach(((t,e)=>{if(0===e){const n=l-t.x,e=d-t.y;return void(Math.hypot(n,e)>2&&(t.x+=n*i.centerDamping,t.y+=e*i.centerDamping))}let o=0,a=0;const r=t.radius+5;t.x<r?o+=(r-t.x)*i.boundaryForce:t.x>n.width-r&&(o+=(n.width-r-t.x)*i.boundaryForce),s.forEach((n=>{if(t===n)return;const e=t.x-n.x,r=t.y-n.y,s=Math.hypot(e,r),c=t.radius+n.radius;if(s<1.5*c){const t=i.forceStrength*(c/Math.max(s,.1));o+=e/s*t,a+=r/s*t}const h=l-t.x,f=d-t.y,v=Math.hypot(h,f),m=t.value/u*.02;t.x+=h/v*m,t.y+=f/v*m}));const c=l-t.x,h=d-t.y,f=Math.hypot(c,h),v=s[0].radius+t.radius+i.centerRadiusBuffer,m=(i.centerForce,Math.pow(t.value/u,.3),i.centerAttraction*(1-t.value/u)*(1-Math.min(1,f/v)));t.x+=c*m,t.y+=h*m,t.x+=o*(1-i.damping),t.y+=a*(1-i.damping)})),s.forEach(((t,n)=>{s.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),d=o.radius+i.radius+2;if(l<d){const t=d-l,n=Math.atan2(r,a);i.x+=Math.cos(n)*t*.7,i.y+=Math.sin(n)*t*.7}return}const a=t.x-e.x,r=t.y-e.y,l=Math.hypot(a,r),d=t.radius+e.radius-5;if(l<d){const n=(d-l)*(.3+5*i.forceStrength),o=Math.atan2(r,a),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 s.forEach((t=>{const e=Math.max(5+t.radius,Math.min(n.width-5-t.radius,t.x)),o=Math.max(5+t.radius,Math.min(n.height-5-t.radius,t.y));(!t.fixed||Math.hypot(t.x-e,t.y-o)>2)&&(t.x=e,t.y=o)})),s}(t,n,r);function d(){n&&r?(r.clearRect(0,0,n.width,n.height),l.forEach((n=>{const{x:e,y:o,radius:i,bubbleColor:l,borderColor:d,borderThickness:s,opacity:u,fontColor:c,fontFamily:h,fontSize:f,fontStyle:v,fontWeight:m,textAlign:g,textTransform:p,textBaseline:y}=function(t,n){var e,o,i,r,l,d,s,u,c,h,f;return{x:t.x,y:t.y,radius:Math.max(t.radius,n.minRadius),bubbleColor:null!==(e=t.bubbleColor)&&void 0!==e?e:n.defaultBubbleColor,borderColor:null!==(o=t.borderColor)&&void 0!==o?o:"black",borderThickness:null!==(i=t.borderThickness)&&void 0!==i?i:.25,opacity:null!==(r=t.opacity)&&void 0!==r?r:1,fontFamily:null!==(l=t.fontFamily)&&void 0!==l?l:n.defaultFontFamily,fontStyle:null!==(d=t.fontStyle)&&void 0!==d?d:"normal",fontWeight:null!==(s=t.fontWeight)&&void 0!==s?s:400,textAlign:null!==(u=t.textAlign)&&void 0!==u?u:"center",textTransform:null!==(c=t.textTransform)&&void 0!==c?c:"none",fontColor:null!==(h=t.fontColor)&&void 0!==h?h:n.defaultFontColor,textBaseline:null!==(f=t.textBaseline)&&void 0!==f?f:"middle",fontSize:a(t.radius,n.fontSize,t.fontWeight)}}(n,t);r.beginPath(),r.arc(e,o,i,0,2*Math.PI),r.fillStyle=l,r.fill(),r.strokeStyle=d,r.lineWidth=s,r.stroke(),r.fillStyle=c,r.font=`${v} ${m} ${f}px ${h}`,r.textAlign=g,r.textBaseline=y;let x=n.label||"";if("uppercase"===p?x=x.toUpperCase():"lowercase"===p?x=x.toLowerCase():"capitalize"===p&&(x=x.replace(/\b\w/g,(t=>t.toUpperCase()))),t.textWrap){const a=1.5*i-10,l=1.2*f,d=function(t,n,e,o,i,a,r=14,l=5,d=5,s=1.2){const u=1.5*(i-d),c=r*s,h=Math.max(1,Math.floor(u/c)),f="auto"===o||void 0===o?h:Math.min(o,h);e=Math.max(0,e-l);const v=n.split(" ");let m="";const g=[];let p=!1;for(const n of v){const o=m?`${m} ${n}`:n;if(t.measureText(o).width<=e?m=o:(m.trim()&&g.push(m),m=n),g.length>=f){p=!0;break}}if(m&&g.length<f&&g.push(m),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}(r,n.label,a,t.maxLines,i),s=o-(d.length-1)*l/2;d.forEach(((t,n)=>r.fillText(t,e,s+n*l)))}else r.fillText(n.label,e,o)}))):console.warn("canvas or ctx is not valid")}function s(){const e=document.getElementById(t.canvasContainerId);e&&n&&(n.width=e.offsetWidth,n.height=e.offsetHeight,d())}if(t.isResizeCanvasOnWindowSizeChange&&(s(),window.addEventListener("resize",s)),d(),t.showToolTip){const o=function(t){var n,e,o,i,a,r,l,d,s,u,c,h,f,v,m,g,p,y;const x=null===(e=null===(n=t.data[0].toolTipConfig)||void 0===n?void 0:n.tooltipFormattedData)||void 0===e?void 0:e.trim();if(x){const n=document.createElement("div");n.innerHTML=x.trim();const e=t.canvasContainerId?document.getElementById(t.canvasContainerId):null,o=n.firstElementChild;return(e||document.body).appendChild(o),o}const b=document.createElement("div");b.id="tooltip",b.style.display="none";const C=null!==(o=null==t?void 0:t.tooltipOptions)&&void 0!==o?o:{},M=(t,n)=>"number"==typeof t?`${t}px`:null!=t?t:n;return Object.assign(b.style,{position:"absolute",padding:M(C.padding,"8px"),margin:M(C.margin,"0"),background:null!==(i=C.backgroundColor)&&void 0!==i?i:"rgba(0, 0, 0, 0.85)",color:null!==(a=C.fontColor)&&void 0!==a?a:"white",borderRadius:"4px",pointerEvents:null!==(r=C.pointerEvents)&&void 0!==r?r:"none",fontFamily:null!==(l=C.fontFamily)&&void 0!==l?l:"Arial, sans-serif",fontSize:M(C.fontSize,"14px"),fontWeight:String(null!==(d=C.fontWeight)&&void 0!==d?d:"400"),fontStyle:null!==(s=C.fontStyle)&&void 0!==s?s:"normal",textAlign:null!==(u=C.textAlign)&&void 0!==u?u:"left",textDecoration:null!==(c=C.textDecoration)&&void 0!==c?c:"none",textTransform:null!==(h=C.textTransform)&&void 0!==h?h:"none",letterSpacing:M(C.letterSpacing,"normal"),border:(()=>{var t;if(!C.borderStyle)return"none";const n=M(C.borderWidth,"1px"),e=null!==(t=C.borderColor)&&void 0!==t?t:"transparent";return`${n} ${C.borderStyle} ${e}`})(),boxShadow:null!==(f=C.boxShadow)&&void 0!==f?f:"none",opacity:String(null!==(v=C.opacity)&&void 0!==v?v:1),maxWidth:M(C.maxWidth,"200px"),minWidth:M(C.minWidth,"auto"),maxHeight:M(C.maxHeight,"none"),minHeight:M(C.minHeight,"auto"),zIndex:String(null!==(m=C.zIndex)&&void 0!==m?m:1e3),transition:null!==(g=C.transition)&&void 0!==g?g:"opacity 0.2s",transform:null!==(p=C.transform)&&void 0!==p?p:"none",backdropFilter:null!==(y=C.backdropFilter)&&void 0!==y?y:"none"}),((t.canvasContainerId?document.getElementById(t.canvasContainerId):null)||document.body).appendChild(b),b}(t);let i=null;n.addEventListener("mousemove",(a=>{i||(i=requestAnimationFrame((()=>{(function(t,n,o,i,a){const{mouseX:r,mouseY:l}=function(t,n){const e=n.getBoundingClientRect();return{mouseX:t.clientX-e.left,mouseY:t.clientY-e.top}}(t,o),d=function(t,n,e){return e.find((e=>Math.hypot(t-e.x,n-e.y)<e.radius))||null}(r,l,n);(null==a?void 0:a.cursorType)&&(e=null==a?void 0:a.cursorType),d?function(t,n,o,i){n&&n.value&&o&&i&&(o.style.cursor=e,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>`}(n),i.style.left=`${t.pageX+15}px`,i.style.top=t.pageY-30+"px",i.style.zIndex="9999")}(t,d,o,i):(o.style.cursor="default",i.style.display="none")})(a,l,n,o,t),i=null})))}))}}const l={defaultBubbleColor:"#3498DB",defaultFontColor:"#ffffff",minRadius:10,maxLines:"auto",textWrap:!0,isResizeCanvasOnWindowSizeChange:!0,fontSize:14,defaultFontFamily:"Arial",showToolTip:!0};function d(t={}){var n,e;if(!t.data||0===t.data.length)return void console.warn("initializeChart: No valid data provided. Chart initialization aborted.");var o;r((o=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),o)))}window.initializeChart=d;var s=n.$;export{s as initializeChart};
@@ -0,0 +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,{initializeChart:()=>d});let n="default";class o{}o.TRANSPARENT="transparent";const i={forceStrength:.008,iterations:1e3,damping:.65,boundaryForce:.02,centerForce:.12,centerAttraction:.8,centerDamping:.3,centerRadiusBuffer:35};function a(t,e=14,n=400){const o=n>=700?1.25:n>=500?1.1:1;return Math.min(e*o,t/2)}function r(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 i=document.getElementById(t.canvasContainerId);if(!i)return console.error(`Canvas container with ID '${t.canvasContainerId}' not found.`),null;const a=document.createElement("canvas");return a.width=i.offsetWidth,a.height=i.offsetHeight,console.log(t.canvasBackgroundColor),Object.assign(a.style,{border:(null===(e=t.canvasBorderColor)||void 0===e?void 0:e.trim())?`1px solid #${t.canvasBorderColor}`:o.TRANSPARENT,background:(null===(n=t.canvasBackgroundColor)||void 0===n?void 0:n.trim())?`#${t.canvasBackgroundColor}`:o.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"),i.appendChild(a),a}(t);if(!e)return;const r=e.getContext("2d");if(!r)return void console.error("Invalid context");const l=function(t,e,n){const o=Math.min((e.width-10)/2,(e.height-10)/2),a=window.devicePixelRatio||1,r=e.getBoundingClientRect();e.width=r.width*a,e.height=r.height*a,e.style.width=r.width+"px",e.style.height=r.height+"px",n.scale(a,a);const l=r.width/2,d=r.height/2,s=[...t.data].sort(((t,e)=>e.value-t.value)).map((t=>Object.assign(Object.assign({},t),{radius:0,x:0,y:0,fixed:!1}))),u=s[0].value,c=Math.min(1*o,100),h=Math.max(.3*c,30);s.forEach((t=>{const n=t.value/u;t.radius=h+n*(c-h),t.radius=Math.min(t.radius,(e.width-10)/2,(e.height-10)/2)})),s.forEach(((t,n)=>{if(0===n)t.x=l,t.y=d,t.fixed=!0;else{const o=s[0].radius+t.radius+3,i=Math.PI*(3-Math.sqrt(5)),a=e.width-5-t.radius,r=e.height-5-t.radius;t.x=Math.min(a,Math.max(5+t.radius,l+Math.cos(i*n)*o)),t.y=Math.min(r,Math.max(5+t.radius,d+Math.sin(i*n)*o)),t.fixed=!1}}));for(let t=0;t<i.iterations;t++)s.forEach(((t,n)=>{if(0===n){const e=l-t.x,n=d-t.y;return void(Math.hypot(e,n)>2&&(t.x+=e*i.centerDamping,t.y+=n*i.centerDamping))}let o=0,a=0;const r=t.radius+5;t.x<r?o+=(r-t.x)*i.boundaryForce:t.x>e.width-r&&(o+=(e.width-r-t.x)*i.boundaryForce),s.forEach((e=>{if(t===e)return;const n=t.x-e.x,r=t.y-e.y,s=Math.hypot(n,r),c=t.radius+e.radius;if(s<1.5*c){const t=i.forceStrength*(c/Math.max(s,.1));o+=n/s*t,a+=r/s*t}const h=l-t.x,f=d-t.y,v=Math.hypot(h,f),m=t.value/u*.02;t.x+=h/v*m,t.y+=f/v*m}));const c=l-t.x,h=d-t.y,f=Math.hypot(c,h),v=s[0].radius+t.radius+i.centerRadiusBuffer,m=(i.centerForce,Math.pow(t.value/u,.3),i.centerAttraction*(1-t.value/u)*(1-Math.min(1,f/v)));t.x+=c*m,t.y+=h*m,t.x+=o*(1-i.damping),t.y+=a*(1-i.damping)})),s.forEach(((t,e)=>{s.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),d=o.radius+i.radius+2;if(l<d){const t=d-l,e=Math.atan2(r,a);i.x+=Math.cos(e)*t*.7,i.y+=Math.sin(e)*t*.7}return}const a=t.x-n.x,r=t.y-n.y,l=Math.hypot(a,r),d=t.radius+n.radius-5;if(l<d){const e=(d-l)*(.3+5*i.forceStrength),o=Math.atan2(r,a),s=n.radius/(t.radius+n.radius);t.fixed||(t.x+=Math.cos(o)*e*s,t.y+=Math.sin(o)*e*s),n.fixed||(n.x-=Math.cos(o)*e*(1-s),n.y-=Math.sin(o)*e*(1-s))}}))}));return s.forEach((t=>{const n=Math.max(5+t.radius,Math.min(e.width-5-t.radius,t.x)),o=Math.max(5+t.radius,Math.min(e.height-5-t.radius,t.y));(!t.fixed||Math.hypot(t.x-n,t.y-o)>2)&&(t.x=n,t.y=o)})),s}(t,e,r);function d(){e&&r?(r.clearRect(0,0,e.width,e.height),l.forEach((e=>{const{x:n,y:o,radius:i,bubbleColor:l,borderColor:d,borderThickness:s,opacity:u,fontColor:c,fontFamily:h,fontSize:f,fontStyle:v,fontWeight:m,textAlign:p,textTransform:y,textBaseline:g}=function(t,e){var n,o,i,r,l,d,s,u,c,h,f;return{x:t.x,y:t.y,radius:Math.max(t.radius,e.minRadius),bubbleColor:null!==(n=t.bubbleColor)&&void 0!==n?n:e.defaultBubbleColor,borderColor:null!==(o=t.borderColor)&&void 0!==o?o:"black",borderThickness:null!==(i=t.borderThickness)&&void 0!==i?i:.25,opacity:null!==(r=t.opacity)&&void 0!==r?r:1,fontFamily:null!==(l=t.fontFamily)&&void 0!==l?l:e.defaultFontFamily,fontStyle:null!==(d=t.fontStyle)&&void 0!==d?d:"normal",fontWeight:null!==(s=t.fontWeight)&&void 0!==s?s:400,textAlign:null!==(u=t.textAlign)&&void 0!==u?u:"center",textTransform:null!==(c=t.textTransform)&&void 0!==c?c:"none",fontColor:null!==(h=t.fontColor)&&void 0!==h?h:e.defaultFontColor,textBaseline:null!==(f=t.textBaseline)&&void 0!==f?f:"middle",fontSize:a(t.radius,e.fontSize,t.fontWeight)}}(e,t);r.beginPath(),r.arc(n,o,i,0,2*Math.PI),r.fillStyle=l,r.fill(),r.strokeStyle=d,r.lineWidth=s,r.stroke(),r.fillStyle=c,r.font=`${v} ${m} ${f}px ${h}`,r.textAlign=p,r.textBaseline=g;let x=e.label||"";if("uppercase"===y?x=x.toUpperCase():"lowercase"===y?x=x.toLowerCase():"capitalize"===y&&(x=x.replace(/\b\w/g,(t=>t.toUpperCase()))),t.textWrap){const a=1.5*i-10,l=1.2*f,d=function(t,e,n,o,i,a,r=14,l=5,d=5,s=1.2){const u=1.5*(i-d),c=r*s,h=Math.max(1,Math.floor(u/c)),f="auto"===o||void 0===o?h:Math.min(o,h);n=Math.max(0,n-l);const v=e.split(" ");let m="";const p=[];let y=!1;for(const e of v){const o=m?`${m} ${e}`:e;if(t.measureText(o).width<=n?m=o:(m.trim()&&p.push(m),m=e),p.length>=f){y=!0;break}}if(m&&p.length<f&&p.push(m),y&&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}(r,e.label,a,t.maxLines,i),s=o-(d.length-1)*l/2;d.forEach(((t,e)=>r.fillText(t,n,s+e*l)))}else r.fillText(e.label,n,o)}))):console.warn("canvas or ctx is not valid")}function s(){const n=document.getElementById(t.canvasContainerId);n&&e&&(e.width=n.offsetWidth,e.height=n.offsetHeight,d())}if(t.isResizeCanvasOnWindowSizeChange&&(s(),window.addEventListener("resize",s)),d(),t.showToolTip){const o=function(t){var e,n,o,i,a,r,l,d,s,u,c,h,f,v,m,p,y,g;const x=null===(n=null===(e=t.data[0].toolTipConfig)||void 0===e?void 0:e.tooltipFormattedData)||void 0===n?void 0:n.trim();if(x){const e=document.createElement("div");e.innerHTML=x.trim();const n=t.canvasContainerId?document.getElementById(t.canvasContainerId):null,o=e.firstElementChild;return(n||document.body).appendChild(o),o}const b=document.createElement("div");b.id="tooltip",b.style.display="none";const C=null!==(o=null==t?void 0:t.tooltipOptions)&&void 0!==o?o:{},M=(t,e)=>"number"==typeof t?`${t}px`:null!=t?t:e;return Object.assign(b.style,{position:"absolute",padding:M(C.padding,"8px"),margin:M(C.margin,"0"),background:null!==(i=C.backgroundColor)&&void 0!==i?i:"rgba(0, 0, 0, 0.85)",color:null!==(a=C.fontColor)&&void 0!==a?a:"white",borderRadius:"4px",pointerEvents:null!==(r=C.pointerEvents)&&void 0!==r?r:"none",fontFamily:null!==(l=C.fontFamily)&&void 0!==l?l:"Arial, sans-serif",fontSize:M(C.fontSize,"14px"),fontWeight:String(null!==(d=C.fontWeight)&&void 0!==d?d:"400"),fontStyle:null!==(s=C.fontStyle)&&void 0!==s?s:"normal",textAlign:null!==(u=C.textAlign)&&void 0!==u?u:"left",textDecoration:null!==(c=C.textDecoration)&&void 0!==c?c:"none",textTransform:null!==(h=C.textTransform)&&void 0!==h?h:"none",letterSpacing:M(C.letterSpacing,"normal"),border:(()=>{var t;if(!C.borderStyle)return"none";const e=M(C.borderWidth,"1px"),n=null!==(t=C.borderColor)&&void 0!==t?t:"transparent";return`${e} ${C.borderStyle} ${n}`})(),boxShadow:null!==(f=C.boxShadow)&&void 0!==f?f:"none",opacity:String(null!==(v=C.opacity)&&void 0!==v?v:1),maxWidth:M(C.maxWidth,"200px"),minWidth:M(C.minWidth,"auto"),maxHeight:M(C.maxHeight,"none"),minHeight:M(C.minHeight,"auto"),zIndex:String(null!==(m=C.zIndex)&&void 0!==m?m:1e3),transition:null!==(p=C.transition)&&void 0!==p?p:"opacity 0.2s",transform:null!==(y=C.transform)&&void 0!==y?y:"none",backdropFilter:null!==(g=C.backdropFilter)&&void 0!==g?g:"none"}),((t.canvasContainerId?document.getElementById(t.canvasContainerId):null)||document.body).appendChild(b),b}(t);let i=null;e.addEventListener("mousemove",(a=>{i||(i=requestAnimationFrame((()=>{(function(t,e,o,i,a){const{mouseX:r,mouseY:l}=function(t,e){const n=e.getBoundingClientRect();return{mouseX:t.clientX-n.left,mouseY:t.clientY-n.top}}(t,o),d=function(t,e,n){return n.find((n=>Math.hypot(t-n.x,e-n.y)<n.radius))||null}(r,l,e);(null==a?void 0:a.cursorType)&&(n=null==a?void 0:a.cursorType),d?function(t,e,o,i){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),i.style.left=`${t.pageX+15}px`,i.style.top=t.pageY-30+"px",i.style.zIndex="9999")}(t,d,o,i):(o.style.cursor="default",i.style.display="none")})(a,l,e,o,t),i=null})))}))}}const l={defaultBubbleColor:"#3498DB",defaultFontColor:"#ffffff",minRadius:10,maxLines:"auto",textWrap:!0,isResizeCanvasOnWindowSizeChange:!0,fontSize:14,defaultFontFamily:"Arial",showToolTip:!0};function d(t={}){var e,n;if(!t.data||0===t.data.length)return void console.warn("initializeChart: No valid data provided. Chart initialization aborted.");var o;r((o=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({},l),o)))}return window.initializeChart=d,e})()));
package/dist/canvas.d.ts CHANGED
@@ -1,4 +1,5 @@
1
+ import { Configuration } from "./models/public/configuration";
1
2
  /**
2
3
  * Creates and initializes the canvas inside the specified container.
3
4
  */
4
- export declare function createCanvas(containerId: string): HTMLCanvasElement | null;
5
+ export declare function createCanvas(config: Configuration): HTMLCanvasElement | null;
@@ -0,0 +1,3 @@
1
+ export declare class AppConstants {
2
+ static readonly TRANSPARENT = "transparent";
3
+ }
@@ -1,10 +1,10 @@
1
1
  export declare const PHYSICS: {
2
- readonly forceStrength: 0.015;
2
+ readonly forceStrength: 0.008;
3
3
  readonly iterations: 1000;
4
- readonly damping: 0.55;
4
+ readonly damping: 0.65;
5
5
  readonly boundaryForce: 0.02;
6
6
  readonly centerForce: 0.12;
7
- readonly centerAttraction: 0.6;
7
+ readonly centerAttraction: 0.8;
8
8
  readonly centerDamping: 0.3;
9
9
  readonly centerRadiusBuffer: 35;
10
10
  };
@@ -0,0 +1 @@
1
+ export declare function getWrappedLines(ctx: CanvasRenderingContext2D, text: string, maxLineWidth: number, maxAllowedLines: number | "auto" | undefined, radius: number, maxCharsPerWord?: number | undefined, fontSize?: number, horizontalPadding?: number, verticalPadding?: number, lineHeightFactor?: number): string[];
@@ -1,3 +1,4 @@
1
- import { DataItemInfo } from "../models/internal/dataItemInfo";
2
- export declare function createTooltipElement(canvasContainerId: string): HTMLDivElement;
3
- export declare function handleMouseMove(event: MouseEvent, data: DataItemInfo[], canvas: HTMLCanvasElement, tooltip: HTMLDivElement): void;
1
+ import { DataItemInfo } from "../models/internal/data-item-info";
2
+ import { Configuration } from "../models/public/configuration";
3
+ export declare function createTooltipElement(config: Configuration): HTMLDivElement;
4
+ export declare function handleMouseMove(event: MouseEvent, data: DataItemInfo[], canvas: HTMLCanvasElement, tooltip: HTMLDivElement, config: Configuration): void;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { initializeChart } from "./services/chartService";
1
+ import { initializeChart } from "./services/chart-service";
2
2
  export { initializeChart };
3
3
  declare global {
4
4
  interface Window {
@@ -1,4 +1,4 @@
1
- import { DataItem } from "../public/dataItem";
1
+ import { DataItem } from "../public/data-item";
2
2
  export interface DataItemInfo extends DataItem {
3
3
  radius: number;
4
4
  x: number;
@@ -0,0 +1,32 @@
1
+ export interface BubbleAppearance {
2
+ bubbleColor?: string;
3
+ borderThickness?: number;
4
+ borderColor?: string;
5
+ opacity?: number;
6
+ }
7
+ /**
8
+ * Defines the appearance properties for a bubble.
9
+ */
10
+ export interface BubbleAppearance {
11
+ /**
12
+ * Bubble background color
13
+ * @default "#3498DB"
14
+ */
15
+ bubbleColor?: string;
16
+ /**
17
+ * Border thickness (in pixels)
18
+ * @default 0.25
19
+ */
20
+ borderThickness?: number;
21
+ /**
22
+ * Border color
23
+ * @default "black"
24
+ */
25
+ borderColor?: string;
26
+ /**
27
+ * Opacity level (0: transparent, 1: fully visible)
28
+ * @validValues 0 - 1
29
+ * @default 1
30
+ */
31
+ opacity?: number;
32
+ }
@@ -0,0 +1,46 @@
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
+ }
@@ -0,0 +1,5 @@
1
+ export interface InteractionOptions {
2
+ showToolTip?: boolean;
3
+ isResizeCanvasOnWindowSizeChange?: boolean;
4
+ cursorType?: "default" | "pointer" | "grab" | "crosshair" | "move" | "not-allowed" | "help";
5
+ }
@@ -0,0 +1,4 @@
1
+ export declare class ToolTipConfig {
2
+ tooltipText?: string;
3
+ tooltipFormattedData?: string;
4
+ }
@@ -0,0 +1,170 @@
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,15 +1,30 @@
1
- import { DataItem } from "./dataItem";
2
- export interface Configuration {
3
- canvasContainerId: string;
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 {
4
5
  data: DataItem[];
5
- colorMap: Record<string, string>;
6
- defaultBubbleColor: string;
7
- fontSize: number;
8
- fontFamily: string;
9
- fontColor: string;
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;
10
21
  minRadius: number;
11
- maxLines: number;
22
+ maxLines: number | "auto";
12
23
  textWrap: boolean;
24
+ defaultBubbleColor: string;
25
+ fontSize: number;
26
+ defaultFontColor: string;
27
+ defaultFontFamily: string;
13
28
  isResizeCanvasOnWindowSizeChange: boolean;
14
- showToolTip: boolean;
29
+ tooltipOptions?: TooltipOptions;
15
30
  }
@@ -0,0 +1,8 @@
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,3 +1,3 @@
1
- import { DataItemInfo } from "../models/internal/dataItemInfo";
1
+ import { DataItemInfo } from "../models/internal/data-item-info";
2
2
  import { Configuration } from "../models/public/configuration";
3
3
  export declare function getChartData(config: Configuration, canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D): DataItemInfo[];
@@ -1 +1 @@
1
- export declare function getFontSize(radius: number, defaultFontSize?: number): number;
1
+ export declare function getFontSize(radius: number, fontSize?: number, fontWeight?: number): number;
package/index.html ADDED
@@ -0,0 +1,77 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Bubble JS</title>
8
+
9
+ <!-- <script type="module" src="./dist/index.js"></script> -->
10
+ <script src="./dist/bubbleChart.umd.js" defer></script>
11
+
12
+ </head>
13
+
14
+ <body>
15
+ <div id="bubbleChart" style="width: 667px; height: 632px;"></div>
16
+ <script>
17
+ document.addEventListener("DOMContentLoaded", function () {
18
+ if (typeof initializeChart === "function") {
19
+
20
+ // Sample data
21
+ // const data = [
22
+ // { label: 'Activation of supply for Electricity and Water', value: 45000, bubbleColor: "#024831", fontColor: '#FFFFFF', fontWeight: 600 },
23
+ // { label: 'Reconnection', value: 28500, bubbleColor: "#03714d", fontColor: '#FFF', fontWeight: 600 },
24
+ // { label: 'Refund Request', value: 22500, bubbleColor: "#03714d", fontColor: '#000', fontWeight: 400 },
25
+ // { label: 'Request for Information Update', value: 28500, bubbleColor: "#049e6b", fontColor: '#000', fontWeight: 400 },
26
+ // { label: 'Supply Issues', value: 25500, bubbleColor: "#31b086", fontColor: '#000', fontWeight: 400 },
27
+ // { label: 'Smart Services', value: 26500, bubbleColor: "#03875c", fontColor: '#000', fontWeight: 400 },
28
+ // ];
29
+
30
+ const toolTipConfig = {
31
+ tooltipText: 'Sample Tooltip',
32
+ tooltipFormattedData: `<div style="position: absolute; display: block; border-style: solid; z-index: 99999999; will-change: transform; transition: opacity 0.2s cubic-bezier(0.23, 1, 0.32, 1), visibility 0.2s cubic-bezier(0.23, 1, 0.32, 1), transform 0.4s cubic-bezier(0.23, 1, 0.32, 1); background-color: rgb(30, 30, 47); border-width: 1px; border-radius: 8px; color: rgb(237, 237, 237); font: 12px / 18px Arial, sans-serif; padding: 10px 12px; top: 0px; left: 0px; transform: translate3d(4px, 4px, 0px); border-color: transparent; overflow: visible; white-space: normal; box-shadow: rgba(0, 0, 0, 0.25) 0px 4px 10px; pointer-events: none;">
33
+ Sample Tooltip
34
+ </div>
35
+ `
36
+ }
37
+
38
+ const tooltipOptions = {
39
+ fontStyle: 'italic',
40
+ fontWeight: 800,
41
+ textAlign: 'center',
42
+ textDecoration: 'underline',
43
+ textTransform: "uppercase",
44
+ fontColor: '#FFF'
45
+ }
46
+
47
+ const data = [
48
+ { label: "Biryani Battles", "value": 89, bubbleColor: "#ff5733" },
49
+ { label: "Chai vs. Coffee", "value": 70, bubbleColor: "#c70039" },
50
+ { label: "Bollywood Blockbusters", "value": 90, bubbleColor: "#900c3f" },
51
+ { label: "IPL Fever", "value": 85, bubbleColor: "#ffc300" },
52
+ { label: "Himalayan Treks", "value": 65, bubbleColor: "#4caf50" },
53
+ { label: "Diwali Firecrackers", "value": 95, bubbleColor: "#ff8c00" },
54
+ { label: "Street Food Craze", "value": 75, bubbleColor: "#e91e63" },
55
+ { label: "Fastest Century Records", "value": 88, bubbleColor: "#3f51b5" },
56
+ { label: "Royal Enfield Craze", "value": 60, bubbleColor: "#795548" },
57
+ { label: "Digital Payment Boom", "value": 93, bubbleColor: "#00bcd4" }
58
+ ];
59
+
60
+ const chartoptions = {
61
+ canvasContainerId: 'bubbleChart',
62
+ data: data,
63
+ fontSize: 14,
64
+ maxLines: 2,
65
+ tooltipOptions: tooltipOptions,
66
+ }
67
+
68
+ // Initialize chart
69
+ initializeChart(chartoptions);
70
+ } else {
71
+ console.error("initializeChart is not defined");
72
+ }
73
+ });
74
+ </script>
75
+ </body>
76
+
77
+ </html>