@semcore/d3-chart 1.5.6 → 1.6.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 (58) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/lib/cjs/Area.js +6 -6
  3. package/lib/cjs/Axis.js +12 -12
  4. package/lib/cjs/Bar.js +5 -5
  5. package/lib/cjs/Bubble.js +272 -0
  6. package/lib/cjs/Bubble.js.map +1 -0
  7. package/lib/cjs/Donut.js +5 -5
  8. package/lib/cjs/Dots.js +5 -5
  9. package/lib/cjs/GroupBar.js +6 -6
  10. package/lib/cjs/HorizontalBar.js +5 -5
  11. package/lib/cjs/Hover.js +3 -3
  12. package/lib/cjs/Line.js +5 -5
  13. package/lib/cjs/ScatterPlot.js +220 -0
  14. package/lib/cjs/ScatterPlot.js.map +1 -0
  15. package/lib/cjs/StackBar.js +6 -6
  16. package/lib/cjs/StackedArea.js +7 -7
  17. package/lib/cjs/Tooltip.js +8 -8
  18. package/lib/cjs/Venn.js +4 -4
  19. package/lib/cjs/index.js +16 -0
  20. package/lib/cjs/index.js.map +1 -1
  21. package/lib/cjs/style/bubble.shadow.css +45 -0
  22. package/lib/cjs/style/scatterplot.shadow.css +27 -0
  23. package/lib/cjs/style/tooltip.shadow.css +2 -2
  24. package/lib/es6/Area.js +6 -6
  25. package/lib/es6/Axis.js +12 -12
  26. package/lib/es6/Bar.js +5 -5
  27. package/lib/es6/Bubble.js +255 -0
  28. package/lib/es6/Bubble.js.map +1 -0
  29. package/lib/es6/Donut.js +5 -5
  30. package/lib/es6/Dots.js +5 -5
  31. package/lib/es6/GroupBar.js +6 -6
  32. package/lib/es6/HorizontalBar.js +5 -5
  33. package/lib/es6/Hover.js +3 -3
  34. package/lib/es6/Line.js +5 -5
  35. package/lib/es6/ScatterPlot.js +205 -0
  36. package/lib/es6/ScatterPlot.js.map +1 -0
  37. package/lib/es6/StackBar.js +6 -6
  38. package/lib/es6/StackedArea.js +7 -7
  39. package/lib/es6/Tooltip.js +8 -8
  40. package/lib/es6/Venn.js +4 -4
  41. package/lib/es6/index.js +2 -0
  42. package/lib/es6/index.js.map +1 -1
  43. package/lib/es6/style/bubble.shadow.css +45 -0
  44. package/lib/es6/style/scatterplot.shadow.css +27 -0
  45. package/lib/es6/style/tooltip.shadow.css +2 -2
  46. package/lib/types/Bubble.d.ts +27 -0
  47. package/lib/types/ScatterPlot.d.ts +27 -0
  48. package/lib/types/index.d.ts +6 -0
  49. package/package.json +1 -1
  50. package/src/Bubble.js +189 -0
  51. package/src/ScatterPlot.js +130 -0
  52. package/src/index.js +2 -0
  53. package/src/style/bubble.shadow.css +45 -0
  54. package/src/style/scatterplot.shadow.css +27 -0
  55. package/src/style/tooltip.shadow.css +2 -2
  56. package/src/types/Bubble.d.ts +27 -0
  57. package/src/types/ScatterPlot.d.ts +27 -0
  58. package/src/types/index.d.ts +6 -0
@@ -27,15 +27,15 @@ var _ref = (
27
27
  /*__reshadow_css_start__*/
28
28
  __css__(
29
29
  /*__inner_css_start__*/
30
- ".___SBar_jj14u_gg_{fill:#50aef4;transition-property:height,width,y;transition-duration:var(--duration);transition-timing-function:ease-in-out}.___SBar_jj14u_gg_.__color_jj14u_gg_{fill:var(--color)}.___SBar_jj14u_gg_.__hide_jj14u_gg_{display:none}.___SBackground_jj14u_gg_{fill:#e4ecf1}"
30
+ ".___SBar_1q91m_gg_{fill:#50aef4;transition-property:height,width,y;transition-duration:var(--duration);transition-timing-function:ease-in-out}.___SBar_1q91m_gg_.__color_1q91m_gg_{fill:var(--color)}.___SBar_1q91m_gg_.__hide_1q91m_gg_{display:none}.___SBackground_1q91m_gg_{fill:#e4ecf1}"
31
31
  /*__inner_css_end__*/
32
- , "1iy4upi_gg_")
32
+ , "1uiyv3q_gg_")
33
33
  /*__reshadow_css_end__*/
34
34
  , {
35
- "__SBar": "___SBar_jj14u_gg_",
36
- "_color": "__color_jj14u_gg_",
37
- "_hide": "__hide_jj14u_gg_",
38
- "__SBackground": "___SBackground_jj14u_gg_"
35
+ "__SBar": "___SBar_1q91m_gg_",
36
+ "_color": "__color_1q91m_gg_",
37
+ "_hide": "__hide_1q91m_gg_",
38
+ "__SBackground": "___SBackground_1q91m_gg_"
39
39
  }),
40
40
  style = _extends({}, _ref);
41
41
 
@@ -26,16 +26,16 @@ var _ref = (
26
26
  /*__reshadow_css_start__*/
27
27
  __css__(
28
28
  /*__inner_css_start__*/
29
- ".___SArea_zz80o_gg_{fill:#50aef4;fill-opacity:.4}.___SArea_zz80o_gg_.__color_zz80o_gg_{fill:var(--color)}.___SAreaLine_zz80o_gg_{stroke:#50aef4;stroke-width:3;fill:transparent}.___SAreaLine_zz80o_gg_.__color_zz80o_gg_{stroke:var(--color)}.___SArea_zz80o_gg_,.___SAreaLine_zz80o_gg_{transition-property:d;transition-duration:var(--duration);transition-timing-function:ease-in-out}.___SNull_zz80o_gg_{fill:transparent;stroke:#bdc4c6;stroke-dasharray:4}.___SNull_zz80o_gg_.__hide_zz80o_gg_{display:none}"
29
+ ".___SArea_1pbv6_gg_{fill:#50aef4;fill-opacity:.4}.___SArea_1pbv6_gg_.__color_1pbv6_gg_{fill:var(--color)}.___SAreaLine_1pbv6_gg_{stroke:#50aef4;stroke-width:3;fill:transparent}.___SAreaLine_1pbv6_gg_.__color_1pbv6_gg_{stroke:var(--color)}.___SArea_1pbv6_gg_,.___SAreaLine_1pbv6_gg_{transition-property:d;transition-duration:var(--duration);transition-timing-function:ease-in-out}.___SNull_1pbv6_gg_{fill:transparent;stroke:#bdc4c6;stroke-dasharray:4}.___SNull_1pbv6_gg_.__hide_1pbv6_gg_{display:none}"
30
30
  /*__inner_css_end__*/
31
- , "1vghdzd_gg_")
31
+ , "2qdwr1_gg_")
32
32
  /*__reshadow_css_end__*/
33
33
  , {
34
- "__SArea": "___SArea_zz80o_gg_",
35
- "_color": "__color_zz80o_gg_",
36
- "__SAreaLine": "___SAreaLine_zz80o_gg_",
37
- "__SNull": "___SNull_zz80o_gg_",
38
- "_hide": "__hide_zz80o_gg_"
34
+ "__SArea": "___SArea_1pbv6_gg_",
35
+ "_color": "__color_1pbv6_gg_",
36
+ "__SAreaLine": "___SAreaLine_1pbv6_gg_",
37
+ "__SNull": "___SNull_1pbv6_gg_",
38
+ "_hide": "__hide_1pbv6_gg_"
39
39
  }),
40
40
  style = _extends({}, _ref);
41
41
 
@@ -33,17 +33,17 @@ var style = (
33
33
  /*__reshadow_css_start__*/
34
34
  _sstyled.insert(
35
35
  /*__inner_css_start__*/
36
- ".___STooltip_1rv9e_gg_{position:relative;background-color:#fff;border-radius:3px;border:1px solid #bdc4c6;box-sizing:border-box;box-shadow:0 2px 5px 0 rgba(0,0,0,.25),0 -2px 5px -2px rgba(0,0,0,.25);padding:12px}.___STitle_1rv9e_gg_{font-size:12px;line-height:1.5;color:#757575;margin-bottom:8px}.___SDotGroup_1rv9e_gg_{display:flex;align-items:center}.___SDot_1rv9e_gg_{width:8px;height:8px;border-radius:50%;margin-right:8px;background:#50aef4}.___SDot_1rv9e_gg_.__color_1rv9e_gg_{background:var(--color_1rmqsj5)}"
36
+ ".___STooltip_16ivl_gg_{font-size:12px;line-height:1.5;position:relative;background-color:#fff;border-radius:3px;border:1px solid #bdc4c6;box-sizing:border-box;box-shadow:0 2px 5px 0 rgba(0,0,0,.25),0 -2px 5px -2px rgba(0,0,0,.25);padding:12px}.___STitle_16ivl_gg_{color:#757575;margin-bottom:8px}.___SDotGroup_16ivl_gg_{display:flex;align-items:center}.___SDot_16ivl_gg_{width:8px;height:8px;border-radius:50%;margin-right:8px;background:#50aef4}.___SDot_16ivl_gg_.__color_16ivl_gg_{background:var(--color_drazch)}"
37
37
  /*__inner_css_end__*/
38
- , "1rmqsj5_gg_")
38
+ , "drazch_gg_")
39
39
  /*__reshadow_css_end__*/
40
40
  , {
41
- "__STooltip": "___STooltip_1rv9e_gg_",
42
- "__STitle": "___STitle_1rv9e_gg_",
43
- "__SDotGroup": "___SDotGroup_1rv9e_gg_",
44
- "__SDot": "___SDot_1rv9e_gg_",
45
- "_color": "__color_1rv9e_gg_",
46
- "--color": "--color_1rmqsj5"
41
+ "__STooltip": "___STooltip_16ivl_gg_",
42
+ "__STitle": "___STitle_16ivl_gg_",
43
+ "__SDotGroup": "___SDotGroup_16ivl_gg_",
44
+ "__SDot": "___SDot_16ivl_gg_",
45
+ "_color": "__color_16ivl_gg_",
46
+ "--color": "--color_drazch"
47
47
  });
48
48
 
49
49
  var TooltipRoot = /*#__PURE__*/function (_Component) {
package/lib/es6/Venn.js CHANGED
@@ -26,16 +26,16 @@ var style = (
26
26
  /*__reshadow_css_start__*/
27
27
  _sstyled.insert(
28
28
  /*__inner_css_start__*/
29
- ".___SCircle_c0tdq_gg_{fill:#3ab011;stroke:#fff;stroke-width:2px;fill-opacity:.5;transition-property:cx,cy;transition-duration:var(--duration_1j56sbj);transition-timing-function:ease-in-out}.___SCircle_c0tdq_gg_:hover{fill-opacity:.7}.___SCircle_c0tdq_gg_.__color_c0tdq_gg_{fill:var(--color_1j56sbj)}.___SIntersection_c0tdq_gg_{stroke:#fff;stroke-width:2px;fill-opacity:0}.___SIntersection_c0tdq_gg_:hover{fill-opacity:.1}"
29
+ ".___SCircle_1fulb_gg_{fill:#3ab011;stroke:#fff;stroke-width:2px;fill-opacity:.5;transition-property:cx,cy;transition-duration:var(--duration_1j56sbj);transition-timing-function:ease-in-out}.___SCircle_1fulb_gg_:hover{fill-opacity:.7}.___SCircle_1fulb_gg_.__color_1fulb_gg_{fill:var(--color_1j56sbj)}.___SIntersection_1fulb_gg_{stroke:#fff;stroke-width:2px;fill-opacity:0}.___SIntersection_1fulb_gg_:hover{fill-opacity:.1}"
30
30
  /*__inner_css_end__*/
31
31
  , "1j56sbj_gg_")
32
32
  /*__reshadow_css_end__*/
33
33
  , {
34
- "__SCircle": "___SCircle_c0tdq_gg_",
34
+ "__SCircle": "___SCircle_1fulb_gg_",
35
35
  "--duration": "--duration_1j56sbj",
36
- "_color": "__color_c0tdq_gg_",
36
+ "_color": "__color_1fulb_gg_",
37
37
  "--color": "--color_1j56sbj",
38
- "__SIntersection": "___SIntersection_c0tdq_gg_"
38
+ "__SIntersection": "___SIntersection_1fulb_gg_"
39
39
  });
40
40
 
41
41
  var VennRoot = /*#__PURE__*/function (_Component) {
package/lib/es6/index.js CHANGED
@@ -7,6 +7,8 @@ export { default as GroupBar } from './GroupBar';
7
7
  export { default as StackBar } from './StackBar';
8
8
  export { default as Area } from './Area';
9
9
  export { default as StackedArea } from './StackedArea';
10
+ export { default as ScatterPlot } from './ScatterPlot';
11
+ export { default as Bubble } from './Bubble';
10
12
  export { default as Donut } from './Donut';
11
13
  export { default as Venn } from './Venn';
12
14
  export { default as Tooltip } from './Tooltip';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.js"],"names":["default","Plot","XAxis","YAxis","Line","Bar","HorizontalBar","GroupBar","StackBar","Area","StackedArea","Donut","Venn","Tooltip","ResponsiveContainer","HoverLine","HoverRect","minMax","colors"],"mappings":"AAAA,SAASA,OAAO,IAAIC,IAApB,QAAgC,QAAhC;AAEA,SAASC,KAAT,EAAgBC,KAAhB,QAA6B,QAA7B;AAEA,SAASH,OAAO,IAAII,IAApB,QAAgC,QAAhC;AAEA,SAASJ,OAAO,IAAIK,GAApB,QAA+B,OAA/B;AACA,SAASL,OAAO,IAAIM,aAApB,QAAyC,iBAAzC;AACA,SAASN,OAAO,IAAIO,QAApB,QAAoC,YAApC;AACA,SAASP,OAAO,IAAIQ,QAApB,QAAoC,YAApC;AACA,SAASR,OAAO,IAAIS,IAApB,QAAgC,QAAhC;AACA,SAAST,OAAO,IAAIU,WAApB,QAAuC,eAAvC;AACA,SAASV,OAAO,IAAIW,KAApB,QAAiC,SAAjC;AACA,SAASX,OAAO,IAAIY,IAApB,QAAgC,QAAhC;AAEA,SAASZ,OAAO,IAAIa,OAApB,QAAmC,WAAnC;AAEA,SAASb,OAAO,IAAIc,mBAApB,QAA+C,uBAA/C;AAEA,SAASC,SAAT,EAAoBC,SAApB,QAAqC,SAArC;AAEA,SAASC,MAAT,QAAuB,SAAvB;AACA,SAASC,MAAT,QAAuB,SAAvB","sourcesContent":["export { default as Plot } from './Plot';\n\nexport { XAxis, YAxis } from './Axis';\n\nexport { default as Line } from './Line';\n\nexport { default as Bar } from './Bar';\nexport { default as HorizontalBar } from './HorizontalBar';\nexport { default as GroupBar } from './GroupBar';\nexport { default as StackBar } from './StackBar';\nexport { default as Area } from './Area';\nexport { default as StackedArea } from './StackedArea';\nexport { default as Donut } from './Donut';\nexport { default as Venn } from './Venn';\n\nexport { default as Tooltip } from './Tooltip';\n\nexport { default as ResponsiveContainer } from './ResponsiveContainer';\n\nexport { HoverLine, HoverRect } from './Hover';\n\nexport { minMax } from './utils';\nexport { colors } from './color';\n"],"file":"index.js"}
1
+ {"version":3,"sources":["../../src/index.js"],"names":["default","Plot","XAxis","YAxis","Line","Bar","HorizontalBar","GroupBar","StackBar","Area","StackedArea","ScatterPlot","Bubble","Donut","Venn","Tooltip","ResponsiveContainer","HoverLine","HoverRect","minMax","colors"],"mappings":"AAAA,SAASA,OAAO,IAAIC,IAApB,QAAgC,QAAhC;AAEA,SAASC,KAAT,EAAgBC,KAAhB,QAA6B,QAA7B;AAEA,SAASH,OAAO,IAAII,IAApB,QAAgC,QAAhC;AAEA,SAASJ,OAAO,IAAIK,GAApB,QAA+B,OAA/B;AACA,SAASL,OAAO,IAAIM,aAApB,QAAyC,iBAAzC;AACA,SAASN,OAAO,IAAIO,QAApB,QAAoC,YAApC;AACA,SAASP,OAAO,IAAIQ,QAApB,QAAoC,YAApC;AACA,SAASR,OAAO,IAAIS,IAApB,QAAgC,QAAhC;AACA,SAAST,OAAO,IAAIU,WAApB,QAAuC,eAAvC;AACA,SAASV,OAAO,IAAIW,WAApB,QAAuC,eAAvC;AACA,SAASX,OAAO,IAAIY,MAApB,QAAkC,UAAlC;AACA,SAASZ,OAAO,IAAIa,KAApB,QAAiC,SAAjC;AACA,SAASb,OAAO,IAAIc,IAApB,QAAgC,QAAhC;AAEA,SAASd,OAAO,IAAIe,OAApB,QAAmC,WAAnC;AAEA,SAASf,OAAO,IAAIgB,mBAApB,QAA+C,uBAA/C;AAEA,SAASC,SAAT,EAAoBC,SAApB,QAAqC,SAArC;AAEA,SAASC,MAAT,QAAuB,SAAvB;AACA,SAASC,MAAT,QAAuB,SAAvB","sourcesContent":["export { default as Plot } from './Plot';\n\nexport { XAxis, YAxis } from './Axis';\n\nexport { default as Line } from './Line';\n\nexport { default as Bar } from './Bar';\nexport { default as HorizontalBar } from './HorizontalBar';\nexport { default as GroupBar } from './GroupBar';\nexport { default as StackBar } from './StackBar';\nexport { default as Area } from './Area';\nexport { default as StackedArea } from './StackedArea';\nexport { default as ScatterPlot } from './ScatterPlot';\nexport { default as Bubble } from './Bubble';\nexport { default as Donut } from './Donut';\nexport { default as Venn } from './Venn';\n\nexport { default as Tooltip } from './Tooltip';\n\nexport { default as ResponsiveContainer } from './ResponsiveContainer';\n\nexport { HoverLine, HoverRect } from './Hover';\n\nexport { minMax } from './utils';\nexport { colors } from './color';\n"],"file":"index.js"}
@@ -0,0 +1,45 @@
1
+ @import '@semcore/utils/style/var.css';
2
+ @import '@semcore/d3-chart/src/style/var.css';
3
+
4
+ SBubble {
5
+ fill: #2bb3ff;
6
+ stroke: #fff;
7
+ stroke-width: 2px;
8
+ transition-property: cx, cy;
9
+ transition-duration: var(--duration);
10
+ transition-timing-function: ease-in-out;
11
+ opacity: 0.5;
12
+ &:hover {
13
+ opacity: 0.8;
14
+ }
15
+ }
16
+
17
+ SBubble[color] {
18
+ fill: var(--color);
19
+ }
20
+
21
+ SCenter {
22
+ text-anchor: middle;
23
+ font-size: 11px;
24
+ stroke: #2bb3ff;
25
+ }
26
+
27
+ SCenter[color] {
28
+ stroke: var(--color);
29
+ }
30
+
31
+ SLabel {
32
+ fill: #2bb3ff;
33
+ }
34
+
35
+ SLabel[position='right'] {
36
+ text-anchor: end;
37
+ }
38
+
39
+ SLabel[position='left'] {
40
+ text-anchor: start;
41
+ }
42
+
43
+ SLabel[color] {
44
+ fill: var(--color);
45
+ }
@@ -0,0 +1,27 @@
1
+ @import '@semcore/utils/style/var.css';
2
+ @import '@semcore/d3-chart/src/style/var.css';
3
+
4
+ SScatterPlot {
5
+ fill: #2bb3ff;
6
+ transition-property: cx, cy;
7
+ transition-duration: var(--duration);
8
+ transition-timing-function: ease-in-out;
9
+ opacity: 0.5;
10
+ &:hover {
11
+ opacity: 0.8;
12
+ }
13
+ }
14
+
15
+ SScatterPlot[color] {
16
+ fill: var(--color);
17
+ }
18
+
19
+ SValue {
20
+ text-anchor: middle;
21
+ font-size: 10px;
22
+ stroke: #008ff8;
23
+ }
24
+
25
+ SValue[color] {
26
+ stroke: var(--color);
27
+ }
@@ -2,6 +2,8 @@
2
2
  @import '@semcore/d3-chart/src/style/var.css';
3
3
 
4
4
  STooltip {
5
+ font-size: var(--fs-100);
6
+ line-height: var(--lh-100);
5
7
  position: relative;
6
8
  background-color: #fff;
7
9
  border-radius: 3px;
@@ -12,8 +14,6 @@ STooltip {
12
14
  }
13
15
 
14
16
  STitle {
15
- font-size: var(--fs-100);
16
- line-height: var(--lh-100);
17
17
  color: var(--gray60);
18
18
  margin-bottom: 8px;
19
19
  }
@@ -0,0 +1,27 @@
1
+ import { CProps, ReturnEl } from '@semcore/core';
2
+ import IContext from './context';
3
+
4
+ export interface IBubbleProps extends IContext {
5
+ /** Field from data for XAxis */
6
+ x: string;
7
+ /** Field from data for YAxis */
8
+ y: string;
9
+ /** Field from data for circle radius */
10
+ value: string;
11
+ /** Field from data for circle label */
12
+ label?: string;
13
+ /** Circle color */
14
+ color?: string;
15
+ /** Cross in the center of the bubble
16
+ * @default true
17
+ */
18
+ markedCross?: boolean;
19
+ /** Animation duration in ms
20
+ * @default 500
21
+ */
22
+ duration?: number;
23
+ }
24
+
25
+ declare const Bubble: <T>(props: CProps<IBubbleProps & T>) => ReturnEl;
26
+
27
+ export default Bubble;
@@ -0,0 +1,27 @@
1
+ import { CProps, ReturnEl } from '@semcore/core';
2
+ import IContext from './context';
3
+
4
+ export interface IScatterPlotProps extends IContext {
5
+ /** Field from data for XAxis */
6
+ x: string;
7
+ /** Field from data for YAxis */
8
+ y: string;
9
+ /** Field from data for circle value */
10
+ value?: string;
11
+ /** Circle color */
12
+ color?: string;
13
+ /** Circle value color */
14
+ valueColor?: string;
15
+ /** Animation duration in ms
16
+ * @default 500
17
+ */
18
+ duration?: number;
19
+ /** Radius of circles
20
+ * @default 5.5 or 12 with value
21
+ */
22
+ r?: number;
23
+ }
24
+
25
+ declare const ScatterPlot: <T>(props: CProps<IScatterPlotProps & T>) => ReturnEl;
26
+
27
+ export default ScatterPlot;
@@ -39,3 +39,9 @@ export * from './Donut';
39
39
 
40
40
  export { default as Tooltip } from './Tooltip';
41
41
  export * from './Tooltip';
42
+
43
+ export { default as ScatterPlot } from './ScatterPlot';
44
+ export * from './ScatterPlot';
45
+
46
+ export { default as Bubble } from './Bubble';
47
+ export * from './Bubble';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@semcore/d3-chart",
3
3
  "description": "SEMRush D3 Chart Component",
4
- "version": "1.5.6",
4
+ "version": "1.6.0",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/es6/index.js",
7
7
  "typings": "lib/types/index.d.ts",
package/src/Bubble.js ADDED
@@ -0,0 +1,189 @@
1
+ import React from 'react';
2
+ import { Component, sstyled } from '@semcore/core';
3
+ import canUseDOM from '@semcore/utils/lib/canUseDOM';
4
+ import { CONSTANT } from './utils';
5
+ import createElement from './createElement';
6
+ import uniqueIDEnhancement from '@semcore/utils/lib/uniqueID';
7
+ import { transition } from 'd3-transition';
8
+ import style from './style/bubble.shadow.css';
9
+ import ClipPath from './ClipPath';
10
+ import { scaleSqrt } from 'd3-scale';
11
+
12
+ const memoize = (func) => {
13
+ const results = {};
14
+ return (argsKey) => {
15
+ if (!results[argsKey]) {
16
+ results[argsKey] = func(argsKey);
17
+ }
18
+ return results[argsKey];
19
+ };
20
+ };
21
+
22
+ const measureText = memoize((text) => {
23
+ let span = document.createElement('span');
24
+ span.append(document.createTextNode(text));
25
+ span.style.display = 'inline-block';
26
+ document.body.append(span);
27
+ const textLength = span.offsetWidth;
28
+ span.remove();
29
+ return textLength;
30
+ });
31
+
32
+ class BubbleRoot extends Component {
33
+ static displayName = 'Bubble';
34
+ static style = style;
35
+ static enhance = [uniqueIDEnhancement()];
36
+
37
+ static defaultProps = {
38
+ offset: [0, 0],
39
+ duration: 500,
40
+ markedCross: true,
41
+ };
42
+
43
+ virtualElement = canUseDOM() ? document.createElement('div') : {};
44
+
45
+ generateGetBoundingClientRect(x = 0, y = 0) {
46
+ return () => ({ width: 0, height: 0, top: y, right: x, bottom: y, left: x });
47
+ }
48
+
49
+ bindHandlerTooltip = (visible, props) => ({ clientX: x, clientY: y }) => {
50
+ const { eventEmitter } = this.asProps;
51
+ this.virtualElement.getBoundingClientRect = this.generateGetBoundingClientRect(x, y);
52
+ this.virtualElement[CONSTANT.VIRTUAL_ELEMENT] = true;
53
+ eventEmitter.emit('onTooltipVisible', visible, props, this.virtualElement);
54
+ };
55
+
56
+ animationCircle() {
57
+ const { duration, uid, data, value } = this.asProps;
58
+ const z = scaleSqrt()
59
+ .domain([0, Math.max(...data.map((el) => el[value]))])
60
+ .range([5.5, 50.5]);
61
+
62
+ const selectRect = transition()
63
+ .selection()
64
+ .selectAll(`[id^=${uid}${uid}]`)
65
+ .attr('r', 0);
66
+
67
+ const selectRectNode = selectRect.node();
68
+ if (duration > 0 && selectRectNode) {
69
+ selectRect
70
+ .transition()
71
+ .duration(duration)
72
+ .attr('r', function(_, ind) {
73
+ return z(data[ind][value]);
74
+ });
75
+ }
76
+ }
77
+
78
+ componentDidUpdate() {
79
+ this.animationCircle();
80
+ }
81
+
82
+ componentDidMount() {
83
+ this.animationCircle();
84
+ }
85
+
86
+ renderCircle(d, i) {
87
+ const {
88
+ color,
89
+ scale,
90
+ x,
91
+ y,
92
+ offset,
93
+ styles,
94
+ uid,
95
+ duration,
96
+ value,
97
+ label,
98
+ markedCross,
99
+ size,
100
+ data,
101
+ } = this.asProps;
102
+ const [xScale, yScale] = scale;
103
+
104
+ const SBubble = this.Element;
105
+ const SCenter = 'text';
106
+ const SLabel = 'text';
107
+ const z = scaleSqrt()
108
+ .domain([0, Math.max(...data.map((el) => el[value]))])
109
+ .range([5.5, 50.5]);
110
+
111
+ const margin = Math.min(xScale.range()[0], xScale.range()[1]);
112
+
113
+ const labelPosition =
114
+ size[0] - 2 * margin - (xScale(d[x]) + offset[0] + z(d[value])) < measureText(d[label])
115
+ ? 'right'
116
+ : 'left';
117
+ const labelDistance = {
118
+ right: xScale(d[x]) + offset[0] - z(d[value]),
119
+ left: xScale(d[x]) + offset[0] + z(d[value]),
120
+ }[labelPosition];
121
+
122
+ return sstyled(styles)(
123
+ <g
124
+ key={`circle(#${i})`}
125
+ onMouseMove={this.bindHandlerTooltip(true, { xIndex: i })}
126
+ onMouseLeave={this.bindHandlerTooltip(false, { xIndex: i })}
127
+ >
128
+ {markedCross && (
129
+ <SCenter
130
+ x={xScale(d[x]) + offset[0]}
131
+ y={yScale(d[y]) + offset[1]}
132
+ dy=".3em"
133
+ clipPath={`url(#${uid})`}
134
+ color={d[color] ?? color}
135
+ >
136
+ &#43;
137
+ </SCenter>
138
+ )}
139
+ <SBubble
140
+ id={`${uid}${uid}`}
141
+ render="circle"
142
+ clipPath={`url(#${uid})`}
143
+ cx={xScale(d[x]) + offset[0]}
144
+ cy={yScale(d[y]) + offset[1]}
145
+ color={d[color]}
146
+ r={z(d[value])}
147
+ use:duration={`${duration}ms`}
148
+ />
149
+ {d[label] && (
150
+ <SLabel
151
+ x={labelDistance}
152
+ y={yScale(d[y]) + offset[1]}
153
+ dy=".3em"
154
+ clipPath={`url(#${uid})`}
155
+ position={labelPosition}
156
+ color={d[color]}
157
+ >
158
+ {d[label]}
159
+ </SLabel>
160
+ )}
161
+ </g>,
162
+ );
163
+ }
164
+
165
+ render() {
166
+ const { data, uid, size, scale } = this.asProps;
167
+ const [xScale, yScale] = scale;
168
+ const marginX = Math.min(xScale.range()[0], xScale.range()[1]);
169
+ const marginY = Math.min(yScale.range()[0], yScale.range()[1]);
170
+
171
+ return (
172
+ <>
173
+ {data.map(this.renderCircle.bind(this))}
174
+ {data.map(this.animationCircle.bind(this))}
175
+ <ClipPath
176
+ id={uid}
177
+ x={marginX}
178
+ y={marginY}
179
+ width={`${size[0] - 2 * marginX}px`}
180
+ height={`${size[1] - 2 * marginY}px`}
181
+ />
182
+ </>
183
+ );
184
+ }
185
+ }
186
+
187
+ const Bubble = createElement(BubbleRoot);
188
+
189
+ export default Bubble;
@@ -0,0 +1,130 @@
1
+ import React from 'react';
2
+ import { Component, sstyled } from '@semcore/core';
3
+ import canUseDOM from '@semcore/utils/lib/canUseDOM';
4
+ import { CONSTANT } from './utils';
5
+ import createElement from './createElement';
6
+ import uniqueIDEnhancement from '@semcore/utils/lib/uniqueID';
7
+ import { transition } from 'd3-transition';
8
+ import style from './style/scatterplot.shadow.css';
9
+ import ClipPath from './ClipPath';
10
+
11
+ class ScatterPlotRoot extends Component {
12
+ static displayName = 'ScatterPlot';
13
+ static style = style;
14
+ static enhance = [uniqueIDEnhancement()];
15
+
16
+ static defaultProps = {
17
+ offset: [0, 0],
18
+ duration: 500,
19
+ };
20
+
21
+ virtualElement = canUseDOM() ? document.createElement('div') : {};
22
+
23
+ generateGetBoundingClientRect(x = 0, y = 0) {
24
+ return () => ({ width: 0, height: 0, top: y, right: x, bottom: y, left: x });
25
+ }
26
+
27
+ bindHandlerTooltip = (visible, props) => ({ clientX: x, clientY: y }) => {
28
+ const { eventEmitter } = this.asProps;
29
+ this.virtualElement.getBoundingClientRect = this.generateGetBoundingClientRect(x, y);
30
+ this.virtualElement[CONSTANT.VIRTUAL_ELEMENT] = true;
31
+ eventEmitter.emit('onTooltipVisible', visible, props, this.virtualElement);
32
+ };
33
+
34
+ animationCircle() {
35
+ const { duration, uid, r, value } = this.asProps;
36
+ const radius = r ? r : value ? 12 : 5.5;
37
+ const selectRect = transition()
38
+ .selection()
39
+ .selectAll(`[id^=${uid}]`)
40
+ .attr('r', 0);
41
+ const selectRectNode = selectRect.node();
42
+
43
+ if (duration > 0 && selectRectNode) {
44
+ selectRect
45
+ .transition()
46
+ .duration(duration)
47
+ .attr('r', radius);
48
+ }
49
+ }
50
+
51
+ componentDidUpdate() {
52
+ this.animationCircle();
53
+ }
54
+
55
+ componentDidMount() {
56
+ this.animationCircle();
57
+ }
58
+
59
+ renderCircle(d, i) {
60
+ const {
61
+ color,
62
+ scale,
63
+ x,
64
+ y,
65
+ r,
66
+ offset,
67
+ styles,
68
+ uid,
69
+ duration,
70
+ value,
71
+ valueColor,
72
+ } = this.asProps;
73
+ const [xScale, yScale] = scale;
74
+ const SScatterPlot = this.Element;
75
+ const SValue = 'text';
76
+ return sstyled(styles)(
77
+ <g
78
+ key={`circle(#${i})`}
79
+ onMouseMove={this.bindHandlerTooltip(true, { xIndex: i })}
80
+ onMouseLeave={this.bindHandlerTooltip(false, { xIndex: i })}
81
+ >
82
+ <SScatterPlot
83
+ id={`${uid}${i}`}
84
+ render="circle"
85
+ clipPath={`url(#${uid})`}
86
+ cx={xScale(d[x]) + offset[0]}
87
+ cy={yScale(d[y]) + offset[1]}
88
+ color={d[color]}
89
+ r={r}
90
+ use:duration={`${duration}ms`}
91
+ />
92
+ {d[value] && (
93
+ <SValue
94
+ x={xScale(d[x]) + offset[0]}
95
+ y={yScale(d[y]) + offset[1]}
96
+ dy=".3em"
97
+ clipPath={`url(#${uid})`}
98
+ color={d[valueColor]}
99
+ >
100
+ {d[value]}
101
+ </SValue>
102
+ )}
103
+ </g>,
104
+ );
105
+ }
106
+
107
+ render() {
108
+ const { data, uid, size, scale } = this.asProps;
109
+ const [xScale, yScale] = scale;
110
+ const marginX = Math.min(xScale.range()[0], xScale.range()[1]);
111
+ const marginY = Math.min(yScale.range()[0], yScale.range()[1]);
112
+
113
+ return (
114
+ <>
115
+ {data.map(this.renderCircle.bind(this))}
116
+ <ClipPath
117
+ id={uid}
118
+ x={marginX}
119
+ y={marginY}
120
+ width={`${size[0] - 2 * marginX}px`}
121
+ height={`${size[1] - 2 * marginY}px`}
122
+ />
123
+ </>
124
+ );
125
+ }
126
+ }
127
+
128
+ const ScatterPlot = createElement(ScatterPlotRoot);
129
+
130
+ export default ScatterPlot;
package/src/index.js CHANGED
@@ -10,6 +10,8 @@ export { default as GroupBar } from './GroupBar';
10
10
  export { default as StackBar } from './StackBar';
11
11
  export { default as Area } from './Area';
12
12
  export { default as StackedArea } from './StackedArea';
13
+ export { default as ScatterPlot } from './ScatterPlot';
14
+ export { default as Bubble } from './Bubble';
13
15
  export { default as Donut } from './Donut';
14
16
  export { default as Venn } from './Venn';
15
17
 
@@ -0,0 +1,45 @@
1
+ @import '@semcore/utils/style/var.css';
2
+ @import '@semcore/d3-chart/src/style/var.css';
3
+
4
+ SBubble {
5
+ fill: #2bb3ff;
6
+ stroke: #fff;
7
+ stroke-width: 2px;
8
+ transition-property: cx, cy;
9
+ transition-duration: var(--duration);
10
+ transition-timing-function: ease-in-out;
11
+ opacity: 0.5;
12
+ &:hover {
13
+ opacity: 0.8;
14
+ }
15
+ }
16
+
17
+ SBubble[color] {
18
+ fill: var(--color);
19
+ }
20
+
21
+ SCenter {
22
+ text-anchor: middle;
23
+ font-size: 11px;
24
+ stroke: #2bb3ff;
25
+ }
26
+
27
+ SCenter[color] {
28
+ stroke: var(--color);
29
+ }
30
+
31
+ SLabel {
32
+ fill: #2bb3ff;
33
+ }
34
+
35
+ SLabel[position='right'] {
36
+ text-anchor: end;
37
+ }
38
+
39
+ SLabel[position='left'] {
40
+ text-anchor: start;
41
+ }
42
+
43
+ SLabel[color] {
44
+ fill: var(--color);
45
+ }