@gravity-ui/charts 0.8.0 → 0.10.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 (116) hide show
  1. package/README.md +0 -3
  2. package/dist/cjs/components/Axis/AxisX.d.ts +1 -0
  3. package/dist/cjs/components/Axis/AxisX.js +43 -6
  4. package/dist/cjs/components/Axis/AxisY.js +9 -5
  5. package/dist/cjs/components/Axis/styles.css +5 -5
  6. package/dist/cjs/components/ChartInner/index.js +5 -4
  7. package/dist/cjs/components/ChartInner/styles.css +4 -4
  8. package/dist/cjs/components/ChartInner/useChartInnerHandlers.d.ts +1 -0
  9. package/dist/cjs/components/ChartInner/useChartInnerHandlers.js +3 -4
  10. package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +3 -2
  11. package/dist/cjs/components/Legend/index.js +1 -1
  12. package/dist/cjs/components/Legend/styles.css +14 -14
  13. package/dist/cjs/components/Title/index.js +1 -1
  14. package/dist/cjs/components/Title/styles.css +1 -1
  15. package/dist/cjs/components/Tooltip/DefaultContent.js +18 -3
  16. package/dist/cjs/constants/defaults/series-options.js +12 -0
  17. package/dist/cjs/constants/index.d.ts +1 -0
  18. package/dist/cjs/constants/index.js +1 -0
  19. package/dist/cjs/hooks/useChartOptions/tooltip.js +2 -1
  20. package/dist/cjs/hooks/useChartOptions/types.d.ts +2 -1
  21. package/dist/cjs/hooks/useChartOptions/x-axis.js +9 -2
  22. package/dist/cjs/hooks/useSeries/constants.js +1 -1
  23. package/dist/cjs/hooks/useSeries/prepare-radar.d.ts +16 -0
  24. package/dist/cjs/hooks/useSeries/prepare-radar.js +63 -0
  25. package/dist/cjs/hooks/useSeries/prepareSeries.js +8 -0
  26. package/dist/cjs/hooks/useSeries/types.d.ts +35 -2
  27. package/dist/cjs/hooks/useShapes/area/index.js +1 -1
  28. package/dist/cjs/hooks/useShapes/index.d.ts +2 -1
  29. package/dist/cjs/hooks/useShapes/index.js +12 -0
  30. package/dist/cjs/hooks/useShapes/line/index.js +1 -1
  31. package/dist/cjs/hooks/useShapes/marker.d.ts +3 -2
  32. package/dist/cjs/hooks/useShapes/marker.js +1 -1
  33. package/dist/cjs/hooks/useShapes/pie/index.js +1 -1
  34. package/dist/cjs/hooks/useShapes/radar/index.d.ts +12 -0
  35. package/dist/cjs/hooks/useShapes/radar/index.js +136 -0
  36. package/dist/cjs/hooks/useShapes/radar/prepare-data.d.ts +9 -0
  37. package/dist/cjs/hooks/useShapes/radar/prepare-data.js +155 -0
  38. package/dist/cjs/hooks/useShapes/radar/types.d.ts +58 -0
  39. package/dist/cjs/hooks/useShapes/radar/types.js +1 -0
  40. package/dist/cjs/hooks/useShapes/scatter/index.js +1 -1
  41. package/dist/cjs/hooks/useShapes/styles.css +9 -5
  42. package/dist/cjs/hooks/useShapes/treemap/index.js +1 -1
  43. package/dist/cjs/hooks/useShapes/waterfall/index.js +1 -1
  44. package/dist/cjs/index.d.ts +1 -1
  45. package/dist/cjs/index.js +1 -0
  46. package/dist/cjs/types/chart/axis.d.ts +2 -2
  47. package/dist/cjs/types/chart/radar.d.ts +50 -0
  48. package/dist/cjs/types/chart/radar.js +1 -0
  49. package/dist/cjs/types/chart/series.d.ts +17 -2
  50. package/dist/cjs/types/chart/tooltip.d.ts +10 -1
  51. package/dist/cjs/types/index.d.ts +1 -0
  52. package/dist/cjs/types/index.js +1 -0
  53. package/dist/cjs/utils/chart/get-closest-data.js +39 -2
  54. package/dist/cjs/utils/chart/index.js +1 -1
  55. package/dist/cjs/utils/{d3-dispatcher.d.ts → dispatcher.d.ts} +1 -1
  56. package/dist/cjs/utils/{d3-dispatcher.js → dispatcher.js} +1 -1
  57. package/dist/cjs/utils/index.d.ts +1 -1
  58. package/dist/cjs/utils/index.js +1 -1
  59. package/dist/esm/components/Axis/AxisX.d.ts +1 -0
  60. package/dist/esm/components/Axis/AxisX.js +43 -6
  61. package/dist/esm/components/Axis/AxisY.js +9 -5
  62. package/dist/esm/components/Axis/styles.css +5 -5
  63. package/dist/esm/components/ChartInner/index.js +5 -4
  64. package/dist/esm/components/ChartInner/styles.css +4 -4
  65. package/dist/esm/components/ChartInner/useChartInnerHandlers.d.ts +1 -0
  66. package/dist/esm/components/ChartInner/useChartInnerHandlers.js +3 -4
  67. package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +3 -2
  68. package/dist/esm/components/Legend/index.js +1 -1
  69. package/dist/esm/components/Legend/styles.css +14 -14
  70. package/dist/esm/components/Title/index.js +1 -1
  71. package/dist/esm/components/Title/styles.css +1 -1
  72. package/dist/esm/components/Tooltip/DefaultContent.js +18 -3
  73. package/dist/esm/constants/defaults/series-options.js +12 -0
  74. package/dist/esm/constants/index.d.ts +1 -0
  75. package/dist/esm/constants/index.js +1 -0
  76. package/dist/esm/hooks/useChartOptions/tooltip.js +2 -1
  77. package/dist/esm/hooks/useChartOptions/types.d.ts +2 -1
  78. package/dist/esm/hooks/useChartOptions/x-axis.js +9 -2
  79. package/dist/esm/hooks/useSeries/constants.js +1 -1
  80. package/dist/esm/hooks/useSeries/prepare-radar.d.ts +16 -0
  81. package/dist/esm/hooks/useSeries/prepare-radar.js +63 -0
  82. package/dist/esm/hooks/useSeries/prepareSeries.js +8 -0
  83. package/dist/esm/hooks/useSeries/types.d.ts +35 -2
  84. package/dist/esm/hooks/useShapes/area/index.js +1 -1
  85. package/dist/esm/hooks/useShapes/index.d.ts +2 -1
  86. package/dist/esm/hooks/useShapes/index.js +12 -0
  87. package/dist/esm/hooks/useShapes/line/index.js +1 -1
  88. package/dist/esm/hooks/useShapes/marker.d.ts +3 -2
  89. package/dist/esm/hooks/useShapes/marker.js +1 -1
  90. package/dist/esm/hooks/useShapes/pie/index.js +1 -1
  91. package/dist/esm/hooks/useShapes/radar/index.d.ts +12 -0
  92. package/dist/esm/hooks/useShapes/radar/index.js +136 -0
  93. package/dist/esm/hooks/useShapes/radar/prepare-data.d.ts +9 -0
  94. package/dist/esm/hooks/useShapes/radar/prepare-data.js +155 -0
  95. package/dist/esm/hooks/useShapes/radar/types.d.ts +58 -0
  96. package/dist/esm/hooks/useShapes/radar/types.js +1 -0
  97. package/dist/esm/hooks/useShapes/scatter/index.js +1 -1
  98. package/dist/esm/hooks/useShapes/styles.css +9 -5
  99. package/dist/esm/hooks/useShapes/treemap/index.js +1 -1
  100. package/dist/esm/hooks/useShapes/waterfall/index.js +1 -1
  101. package/dist/esm/index.d.ts +1 -1
  102. package/dist/esm/index.js +1 -0
  103. package/dist/esm/types/chart/axis.d.ts +2 -2
  104. package/dist/esm/types/chart/radar.d.ts +50 -0
  105. package/dist/esm/types/chart/radar.js +1 -0
  106. package/dist/esm/types/chart/series.d.ts +17 -2
  107. package/dist/esm/types/chart/tooltip.d.ts +10 -1
  108. package/dist/esm/types/index.d.ts +1 -0
  109. package/dist/esm/types/index.js +1 -0
  110. package/dist/esm/utils/chart/get-closest-data.js +39 -2
  111. package/dist/esm/utils/chart/index.js +1 -1
  112. package/dist/esm/utils/{d3-dispatcher.d.ts → dispatcher.d.ts} +1 -1
  113. package/dist/esm/utils/{d3-dispatcher.js → dispatcher.js} +1 -1
  114. package/dist/esm/utils/index.d.ts +1 -1
  115. package/dist/esm/utils/index.js +1 -1
  116. package/package.json +11 -2
package/README.md CHANGED
@@ -1,8 +1,5 @@
1
1
  # Gravity Charts · [![npm package](https://img.shields.io/npm/v/@gravity-ui/charts)](https://www.npmjs.com/package/@gravity-ui/charts) [![CI](https://img.shields.io/github/actions/workflow/status/gravity-ui/charts/.github/workflows/ci.yml?label=CI&logo=github)](https://github.com/gravity-ui/charts/actions/workflows/ci.yml?query=branch:main) [![storybook](https://img.shields.io/badge/Storybook-deployed-ff4685)](https://preview.gravity-ui.com/charts/)
2
2
 
3
- > [!WARNING]
4
- > The library may have major changes in minor releases while it is on version `0.*.*`.
5
-
6
3
  ## Install
7
4
 
8
5
  ```shell
@@ -7,6 +7,7 @@ type Props = {
7
7
  height: number;
8
8
  scale: ChartScale;
9
9
  split: PreparedSplit;
10
+ plotRef?: React.MutableRefObject<SVGGElement | null>;
10
11
  };
11
12
  export declare function getTitlePosition(args: {
12
13
  axis: PreparedAxis;
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
- import { select } from 'd3';
3
- import { block, formatAxisTickLabel, getAxisTitleRows, getClosestPointsRange, getMaxTickCount, getScaleTicks, getTicksCount, handleOverflowingText, } from '../../utils';
2
+ import { line, select } from 'd3';
3
+ import { block, formatAxisTickLabel, getAxisTitleRows, getClosestPointsRange, getLineDashArray, getMaxTickCount, getScaleTicks, getTicksCount, handleOverflowingText, } from '../../utils';
4
4
  import { axisBottom } from '../../utils/chart/axis-generators';
5
5
  import './styles.css';
6
- const b = block('d3-axis');
6
+ const b = block('axis');
7
7
  function getLabelFormatter({ axis, scale }) {
8
8
  const ticks = getScaleTicks(scale);
9
9
  const tickStep = getClosestPointsRange(axis, ticks);
@@ -42,7 +42,7 @@ export function getTitlePosition(args) {
42
42
  return { x, y };
43
43
  }
44
44
  export const AxisX = React.memo(function AxisX(props) {
45
- const { axis, width, height: totalHeight, scale, split } = props;
45
+ const { axis, width, height: totalHeight, scale, split, plotRef } = props;
46
46
  const ref = React.useRef(null);
47
47
  React.useEffect(() => {
48
48
  if (!ref.current) {
@@ -57,8 +57,9 @@ export const AxisX = React.memo(function AxisX(props) {
57
57
  return [-top, -(top + height)];
58
58
  });
59
59
  }
60
+ const axisScale = scale;
60
61
  const xAxisGenerator = axisBottom({
61
- scale: scale,
62
+ scale: axisScale,
62
63
  ticks: {
63
64
  items: tickItems,
64
65
  labelFormat: getLabelFormatter({ axis, scale }),
@@ -103,6 +104,42 @@ export const AxisX = React.memo(function AxisX(props) {
103
104
  }
104
105
  });
105
106
  }
106
- }, [axis, width, totalHeight, scale, split]);
107
+ // add plot lines
108
+ if (plotRef && axis.plotLines.length > 0) {
109
+ const plotLineClassName = b('plotLine');
110
+ const plotLineContainer = select(plotRef.current);
111
+ plotLineContainer.selectAll(`.${plotLineClassName}-x`).remove();
112
+ const plotLinesSelection = plotLineContainer
113
+ .selectAll(`.${plotLineClassName}-x`)
114
+ .data(axis.plotLines)
115
+ .join('g')
116
+ .attr('class', `${plotLineClassName}-x`);
117
+ const lineGenerator = line();
118
+ plotLinesSelection
119
+ .append('path')
120
+ .attr('d', (plotLine) => {
121
+ const plotLineValue = Number(axisScale(plotLine.value));
122
+ const points = [
123
+ [plotLineValue, 0],
124
+ [plotLineValue, totalHeight],
125
+ ];
126
+ return lineGenerator(points);
127
+ })
128
+ .attr('stroke', (plotLine) => plotLine.color)
129
+ .attr('stroke-width', (plotLine) => plotLine.width)
130
+ .attr('stroke-dasharray', (plotLine) => getLineDashArray(plotLine.dashStyle, plotLine.width))
131
+ .attr('opacity', (plotLine) => plotLine.opacity);
132
+ // set layer placement
133
+ plotLinesSelection.each((plotLineData, i, nodes) => {
134
+ const plotLineSelection = select(nodes[i]);
135
+ if (plotLineData.layerPlacement === 'before') {
136
+ plotLineSelection.lower();
137
+ }
138
+ else {
139
+ plotLineSelection.raise();
140
+ }
141
+ });
142
+ }
143
+ }, [axis, width, totalHeight, scale, split, plotRef]);
107
144
  return React.createElement("g", { ref: ref });
108
145
  });
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { axisLeft, axisRight, line, select } from 'd3';
3
3
  import { block, calculateCos, calculateSin, formatAxisTickLabel, getAxisHeight, getAxisTitleRows, getClosestPointsRange, getLineDashArray, getScaleTicks, getTicksCount, handleOverflowingText, parseTransformStyle, setEllipsisForOverflowTexts, wrapText, } from '../../utils';
4
4
  import './styles.css';
5
- const b = block('d3-axis');
5
+ const b = block('axis');
6
6
  function transformLabel(args) {
7
7
  const { node, axis } = args;
8
8
  let topOffset = axis.labels.lineHeight / 2;
@@ -56,11 +56,14 @@ function getTitlePosition(args) {
56
56
  if (rowCount < 1) {
57
57
  return { x: 0, y: 0 };
58
58
  }
59
- const x = -(axis.title.height -
59
+ let x = axis.title.height -
60
60
  axis.title.height / rowCount +
61
61
  axis.title.margin +
62
62
  axis.labels.margin +
63
- axis.labels.width);
63
+ axis.labels.width;
64
+ if (axis.position === 'left') {
65
+ x = x * -1;
66
+ }
64
67
  let y;
65
68
  switch (axis.title.align) {
66
69
  case 'left': {
@@ -82,6 +85,7 @@ export const AxisY = (props) => {
82
85
  const { axes, width, height: totalHeight, scale, split, plotRef } = props;
83
86
  const height = getAxisHeight({ split, boundsHeight: totalHeight });
84
87
  const ref = React.useRef(null);
88
+ const lineGenerator = line();
85
89
  React.useEffect(() => {
86
90
  if (!ref.current) {
87
91
  return;
@@ -174,7 +178,7 @@ export const AxisY = (props) => {
174
178
  [0, plotLineValue],
175
179
  [width, plotLineValue],
176
180
  ];
177
- return line()(points);
181
+ return lineGenerator(points);
178
182
  })
179
183
  .attr('stroke', (plotLine) => plotLine.color)
180
184
  .attr('stroke-width', (plotLine) => plotLine.width)
@@ -199,7 +203,7 @@ export const AxisY = (props) => {
199
203
  [0, 0],
200
204
  [0, height],
201
205
  ];
202
- return line()(points);
206
+ return lineGenerator(points);
203
207
  })
204
208
  .style('stroke', (d) => d.lineColor || '');
205
209
  svgElement.selectAll('.tick').each((_d, index, nodes) => {
@@ -1,17 +1,17 @@
1
- .gcharts-d3-axis .domain {
1
+ .gcharts-axis .domain {
2
2
  stroke: var(--g-color-line-generic-active);
3
3
  }
4
- .gcharts-d3-axis .tick text {
4
+ .gcharts-axis .tick text {
5
5
  color: var(--g-color-text-secondary);
6
6
  alignment-baseline: after-edge;
7
7
  }
8
- .gcharts-d3-axis .tick line, .gcharts-d3-axis .tick path {
8
+ .gcharts-axis .tick line, .gcharts-axis .tick path {
9
9
  stroke: var(--g-color-line-generic);
10
10
  }
11
- .gcharts-d3-axis__title {
11
+ .gcharts-axis__title {
12
12
  alignment-baseline: after-edge;
13
13
  fill: var(--g-color-text-secondary);
14
14
  }
15
- .gcharts-d3-axis__title tspan {
15
+ .gcharts-axis__title tspan {
16
16
  alignment-baseline: after-edge;
17
17
  }
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { EventType, block, getD3Dispatcher } from '../../utils';
2
+ import { EventType, block, getDispatcher } from '../../utils';
3
3
  import { AxisX, AxisY } from '../Axis';
4
4
  import { Legend } from '../Legend';
5
5
  import { PlotTitle } from '../PlotTitle';
@@ -9,14 +9,14 @@ import { useChartInnerHandlers } from './useChartInnerHandlers';
9
9
  import { useChartInnerProps } from './useChartInnerProps';
10
10
  import { useChartInnerState } from './useChartInnerState';
11
11
  import './styles.css';
12
- const b = block('d3');
12
+ const b = block('chart');
13
13
  export const ChartInner = (props) => {
14
14
  var _a, _b, _c, _d;
15
15
  const { width, height, data } = props;
16
16
  const svgRef = React.useRef(null);
17
17
  const htmlLayerRef = React.useRef(null);
18
18
  const plotRef = React.useRef(null);
19
- const dispatcher = React.useMemo(() => getD3Dispatcher(), []);
19
+ const dispatcher = React.useMemo(() => getDispatcher(), []);
20
20
  const { boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, handleLegendItemClick, legendConfig, legendItems, preparedSeries, preparedSplit, preparedLegend, prevHeight, prevWidth, shapes, shapesData, title, tooltip, xAxis, xScale, yAxis, yScale, } = useChartInnerProps(Object.assign(Object.assign({}, props), { dispatcher, htmlLayout: htmlLayerRef.current }));
21
21
  const { tooltipPinned, togglePinTooltip, unpinTooltip } = useChartInnerState({
22
22
  dispatcher,
@@ -35,6 +35,7 @@ export const ChartInner = (props) => {
35
35
  unpinTooltip,
36
36
  xAxis,
37
37
  yAxis,
38
+ tooltipThrottle: tooltip.throttle,
38
39
  });
39
40
  const clickHandler = (_b = (_a = data.chart) === null || _a === void 0 ? void 0 : _a.events) === null || _b === void 0 ? void 0 : _b.click;
40
41
  const pointerMoveHandler = (_d = (_c = data.chart) === null || _c === void 0 ? void 0 : _c.events) === null || _d === void 0 ? void 0 : _d.pointermove;
@@ -68,7 +69,7 @@ export const ChartInner = (props) => {
68
69
  xScale && (yScale === null || yScale === void 0 ? void 0 : yScale.length) && (React.createElement(React.Fragment, null,
69
70
  React.createElement(AxisY, { axes: yAxis, width: boundsWidth, height: boundsHeight, scale: yScale, split: preparedSplit, plotRef: plotRef }),
70
71
  React.createElement("g", { transform: `translate(0, ${boundsHeight})` },
71
- React.createElement(AxisX, { axis: xAxis, width: boundsWidth, height: boundsHeight, scale: xScale, split: preparedSplit })))),
72
+ React.createElement(AxisX, { axis: xAxis, width: boundsWidth, height: boundsHeight, scale: xScale, split: preparedSplit, plotRef: plotRef })))),
72
73
  shapes),
73
74
  preparedLegend.enabled && (React.createElement(Legend, { chartSeries: preparedSeries, boundsWidth: boundsWidth, legend: preparedLegend, items: legendItems, config: legendConfig, onItemClick: handleLegendItemClick, onUpdate: unpinTooltip }))),
74
75
  React.createElement("div", { className: b('html-layer'), ref: htmlLayerRef, style: {
@@ -1,10 +1,10 @@
1
- .gcharts-d3 {
2
- --d3-data-labels: var(--g-color-text-secondary);
1
+ .gcharts-chart {
2
+ --gcharts-data-labels: var(--g-color-text-secondary);
3
3
  position: absolute;
4
4
  }
5
- .gcharts-d3__html-layer {
5
+ .gcharts-chart__html-layer {
6
6
  display: contents;
7
7
  }
8
- .gcharts-d3__html-layer > * {
8
+ .gcharts-chart__html-layer > * {
9
9
  transform: inherit;
10
10
  }
@@ -16,6 +16,7 @@ type Props = {
16
16
  unpinTooltip: ChartInnerState['unpinTooltip'];
17
17
  xAxis: PreparedAxis;
18
18
  yAxis: PreparedAxis[];
19
+ tooltipThrottle: number;
19
20
  };
20
21
  export declare function useChartInnerHandlers(props: Props): {
21
22
  handleChartClick: (event: React.MouseEvent<SVGSVGElement>) => void;
@@ -4,9 +4,8 @@ import throttle from 'lodash/throttle';
4
4
  import { IS_TOUCH_ENABLED } from '../../constants';
5
5
  import { EventType } from '../../utils';
6
6
  import { getClosestPoints } from '../../utils/chart/get-closest-data';
7
- const THROTTLE_DELAY = 50;
8
7
  export function useChartInnerHandlers(props) {
9
- const { boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, dispatcher, shapesData, svgContainer, togglePinTooltip, tooltipPinned, unpinTooltip, xAxis, yAxis, } = props;
8
+ const { boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, dispatcher, shapesData, svgContainer, togglePinTooltip, tooltipPinned, unpinTooltip, xAxis, yAxis, tooltipThrottle, } = props;
10
9
  const isOutsideBounds = React.useCallback((x, y) => {
11
10
  return x < 0 || x > boundsWidth || y < 0 || y > boundsHeight;
12
11
  }, [boundsHeight, boundsWidth]);
@@ -40,7 +39,7 @@ export function useChartInnerHandlers(props) {
40
39
  };
41
40
  const throttledHandleMouseMove = IS_TOUCH_ENABLED
42
41
  ? undefined
43
- : throttle(handleMouseMove, THROTTLE_DELAY);
42
+ : throttle(handleMouseMove, tooltipThrottle);
44
43
  const handleMouseLeave = (event) => {
45
44
  if (tooltipPinned) {
46
45
  return;
@@ -55,7 +54,7 @@ export function useChartInnerHandlers(props) {
55
54
  handleMove([pointerX, pointerY], event);
56
55
  };
57
56
  const throttledHandleTouchMove = IS_TOUCH_ENABLED
58
- ? throttle(handleTouchMove, THROTTLE_DELAY)
57
+ ? throttle(handleTouchMove, tooltipThrottle)
59
58
  : undefined;
60
59
  const handleChartClick = (event) => {
61
60
  const [pointerX, pointerY] = pointer(event, svgContainer);
@@ -29,11 +29,12 @@ export declare function useChartInnerProps(props: Props): {
29
29
  prevWidth: number | undefined;
30
30
  shapes: React.ReactElement<any, string | React.JSXElementConstructor<any>>[];
31
31
  shapesData: import("../../hooks").ShapeData[];
32
- title: (import("../../types").ChartTitle & {
32
+ title: (import("../..").ChartTitle & {
33
33
  height: number;
34
34
  }) | undefined;
35
- tooltip: import("../../types").ChartTooltip<any> & {
35
+ tooltip: import("../..").ChartTooltip<any> & {
36
36
  enabled: boolean;
37
+ throttle: number;
37
38
  };
38
39
  xAxis: import("../../hooks").PreparedAxis;
39
40
  xScale: import("../../hooks").ChartScale | undefined;
@@ -5,7 +5,7 @@ import { formatNumber } from '../../libs';
5
5
  import { block, createGradientRect, getContinuesColorFn, getLabelsSize, getLineDashArray, getSymbol, } from '../../utils';
6
6
  import { axisBottom } from '../../utils/chart/axis-generators';
7
7
  import './styles.css';
8
- const b = block('d3-legend');
8
+ const b = block('legend');
9
9
  const getLegendPosition = (args) => {
10
10
  const { align, offsetWidth = 0, width, contentWidth } = args;
11
11
  const top = 0;
@@ -1,47 +1,47 @@
1
- .gcharts-d3-legend {
1
+ .gcharts-legend {
2
2
  color: var(--g-color-text-secondary);
3
3
  }
4
- .gcharts-d3-legend__title {
4
+ .gcharts-legend__title {
5
5
  fill: var(--g-color-text-secondary);
6
6
  }
7
- .gcharts-d3-legend__item {
7
+ .gcharts-legend__item {
8
8
  cursor: pointer;
9
9
  user-select: none;
10
10
  }
11
- .gcharts-d3-legend__item-symbol_shape_rect.gcharts-d3-legend__item-symbol_unselected {
11
+ .gcharts-legend__item-symbol_shape_rect.gcharts-legend__item-symbol_unselected {
12
12
  fill: var(--g-color-text-hint);
13
13
  }
14
- .gcharts-d3-legend__item-symbol_shape_path.gcharts-d3-legend__item-symbol_unselected {
14
+ .gcharts-legend__item-symbol_shape_path.gcharts-legend__item-symbol_unselected {
15
15
  stroke: var(--g-color-text-hint);
16
16
  }
17
- .gcharts-d3-legend__item-symbol_shape_symbol.gcharts-d3-legend__item-symbol_unselected {
17
+ .gcharts-legend__item-symbol_shape_symbol.gcharts-legend__item-symbol_unselected {
18
18
  fill: var(--g-color-text-hint);
19
19
  }
20
- .gcharts-d3-legend__item-text {
20
+ .gcharts-legend__item-text {
21
21
  fill: var(--g-color-text-secondary);
22
22
  alignment-baseline: before-edge;
23
23
  }
24
- .gcharts-d3-legend__item-text_unselected {
24
+ .gcharts-legend__item-text_unselected {
25
25
  fill: var(--g-color-text-hint);
26
26
  }
27
- .gcharts-d3-legend__item-text:hover {
27
+ .gcharts-legend__item-text:hover {
28
28
  fill: var(--g-color-text-complementary);
29
29
  }
30
- .gcharts-d3-legend__pagination {
30
+ .gcharts-legend__pagination {
31
31
  user-select: none;
32
32
  fill: var(--g-color-text-primary);
33
33
  }
34
- .gcharts-d3-legend__pagination-counter, .gcharts-d3-legend__pagination-arrow {
34
+ .gcharts-legend__pagination-counter, .gcharts-legend__pagination-arrow {
35
35
  alignment-baseline: middle;
36
36
  }
37
- .gcharts-d3-legend__pagination-arrow {
37
+ .gcharts-legend__pagination-arrow {
38
38
  cursor: pointer;
39
39
  fill: var(--g-color-text-brand);
40
40
  }
41
- .gcharts-d3-legend__pagination-arrow_inactive {
41
+ .gcharts-legend__pagination-arrow_inactive {
42
42
  cursor: inherit;
43
43
  fill: var(--g-color-base-generic-accent-disabled);
44
44
  }
45
- .gcharts-d3-legend__pagination-arrow:hover:not(.gcharts-d3-legend__pagination-arrow_inactive) {
45
+ .gcharts-legend__pagination-arrow:hover:not(.gcharts-legend__pagination-arrow_inactive) {
46
46
  fill: var(--g-color-base-brand-hover);
47
47
  }
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { block } from '../../utils';
3
3
  import './styles.css';
4
- const b = block('d3-title');
4
+ const b = block('title');
5
5
  export const Title = (props) => {
6
6
  const { chartWidth, text, height, style } = props;
7
7
  return (React.createElement("text", { className: b(), dx: chartWidth / 2, dy: height / 2, dominantBaseline: "middle", textAnchor: "middle", style: Object.assign({ lineHeight: `${height}px` }, style) },
@@ -1,4 +1,4 @@
1
- .gcharts-d3-title {
1
+ .gcharts-title {
2
2
  font-size: var(--g-text-subheader-2-font-size);
3
3
  font-weight: var(--g-text-subheader-font-weight);
4
4
  fill: var(--g-color-text-primary);
@@ -28,14 +28,17 @@ const getRowData = (fieldName, data, axis) => {
28
28
  const getXRowData = (data, xAxis) => getRowData('x', data, xAxis);
29
29
  const getYRowData = (data, yAxis) => getRowData('y', data, yAxis);
30
30
  const getMeasureValue = (data, xAxis, yAxis) => {
31
- var _a, _b;
31
+ var _a, _b, _c, _d;
32
32
  if (data.every((item) => ['pie', 'treemap', 'waterfall', 'sankey'].includes(item.series.type))) {
33
33
  return null;
34
34
  }
35
+ if (data.some((item) => item.series.type === 'radar')) {
36
+ return (_b = (_a = data[0].category) === null || _a === void 0 ? void 0 : _a.key) !== null && _b !== void 0 ? _b : null;
37
+ }
35
38
  if (data.some((item) => item.series.type === 'bar-y')) {
36
- return getYRowData((_a = data[0]) === null || _a === void 0 ? void 0 : _a.data, yAxis);
39
+ return getYRowData((_c = data[0]) === null || _c === void 0 ? void 0 : _c.data, yAxis);
37
40
  }
38
- return getXRowData((_b = data[0]) === null || _b === void 0 ? void 0 : _b.data, xAxis);
41
+ return getXRowData((_d = data[0]) === null || _d === void 0 ? void 0 : _d.data, xAxis);
39
42
  };
40
43
  export const DefaultContent = ({ hovered, xAxis, yAxis }) => {
41
44
  const measureValue = getMeasureValue(hovered, xAxis, yAxis);
@@ -109,6 +112,18 @@ export const DefaultContent = ({ hovered, xAxis, yAxis }) => {
109
112
  ": ",
110
113
  value)));
111
114
  }
115
+ case 'radar': {
116
+ const radarSeries = series;
117
+ const seriesData = data;
118
+ const value = (React.createElement(React.Fragment, null,
119
+ React.createElement("span", null,
120
+ radarSeries.name || radarSeries.id,
121
+ "\u00A0"),
122
+ React.createElement("span", null, seriesData.value)));
123
+ return (React.createElement("div", { key: id, className: b('content-row') },
124
+ React.createElement("div", { className: b('color'), style: { backgroundColor: color } }),
125
+ React.createElement("div", null, closest ? React.createElement("b", null, value) : React.createElement("span", null, value))));
126
+ }
112
127
  default: {
113
128
  return null;
114
129
  }
@@ -89,6 +89,18 @@ export const seriesOptionsDefaults = {
89
89
  },
90
90
  },
91
91
  },
92
+ radar: {
93
+ states: {
94
+ hover: {
95
+ enabled: true,
96
+ brightness: 0.3,
97
+ },
98
+ inactive: {
99
+ enabled: true,
100
+ opacity: 0.5,
101
+ },
102
+ },
103
+ },
92
104
  waterfall: {
93
105
  barMaxWidth: 50,
94
106
  barPadding: 0.1,
@@ -10,6 +10,7 @@ export declare const SeriesType: {
10
10
  readonly Treemap: "treemap";
11
11
  readonly Waterfall: "waterfall";
12
12
  readonly Sankey: "sankey";
13
+ readonly Radar: "radar";
13
14
  };
14
15
  export declare enum DashStyle {
15
16
  Dash = "Dash",
@@ -10,6 +10,7 @@ export const SeriesType = {
10
10
  Treemap: 'treemap',
11
11
  Waterfall: 'waterfall',
12
12
  Sankey: 'sankey',
13
+ Radar: 'radar',
13
14
  };
14
15
  export var DashStyle;
15
16
  (function (DashStyle) {
@@ -1,5 +1,6 @@
1
1
  import get from 'lodash/get';
2
2
  export const getPreparedTooltip = (args) => {
3
+ var _a;
3
4
  const { tooltip } = args;
4
- return Object.assign(Object.assign({}, tooltip), { enabled: get(tooltip, 'enabled', true) });
5
+ return Object.assign(Object.assign({}, tooltip), { enabled: get(tooltip, 'enabled', true), throttle: (_a = tooltip === null || tooltip === void 0 ? void 0 : tooltip.throttle) !== null && _a !== void 0 ? _a : 0 });
5
6
  };
@@ -19,7 +19,7 @@ export type PreparedAxisPlotLine = {
19
19
  opacity: number;
20
20
  layerPlacement: AxisPlotLine['layerPlacement'];
21
21
  };
22
- export type PreparedAxis = Omit<ChartAxis, 'type' | 'labels'> & {
22
+ export type PreparedAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines'> & {
23
23
  type: ChartAxisType;
24
24
  labels: PreparedAxisLabels;
25
25
  title: {
@@ -48,6 +48,7 @@ export type PreparedTitle = ChartData['title'] & {
48
48
  };
49
49
  export type PreparedTooltip = ChartData['tooltip'] & {
50
50
  enabled: boolean;
51
+ throttle: number;
51
52
  };
52
53
  export type ChartOptions = {
53
54
  chart: PreparedChart;
@@ -1,5 +1,5 @@
1
1
  import get from 'lodash/get';
2
- import { DEFAULT_AXIS_LABEL_FONT_SIZE, axisLabelsDefaults, xAxisTitleDefaults, } from '../../constants';
2
+ import { DEFAULT_AXIS_LABEL_FONT_SIZE, DashStyle, axisLabelsDefaults, xAxisTitleDefaults, } from '../../constants';
3
3
  import { CHART_SERIES_WITH_VOLUME_ON_X_AXIS, calculateCos, formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsSize, getMaxTickCount, getTicksCount, getXAxisItems, hasOverlappingLabels, wrapText, } from '../../utils';
4
4
  import { createXScale } from '../useAxisScales';
5
5
  function getLabelSettings({ axis, series, width, autoRotation = true, }) {
@@ -102,7 +102,14 @@ export const getPreparedXAxis = ({ xAxis, series, width, }) => {
102
102
  },
103
103
  position: 'bottom',
104
104
  plotIndex: 0,
105
- plotLines: [],
105
+ plotLines: get(xAxis, 'plotLines', []).map((d) => ({
106
+ value: get(d, 'value', 0),
107
+ color: get(d, 'color', 'var(--g-color-base-brand)'),
108
+ width: get(d, 'width', 1),
109
+ dashStyle: get(d, 'dashStyle', DashStyle.Solid),
110
+ opacity: get(d, 'opacity', 1),
111
+ layerPlacement: get(d, 'layerPlacement', 'before'),
112
+ })),
106
113
  };
107
114
  const { height, rotation } = getLabelSettings({
108
115
  axis: preparedXAxis,
@@ -4,7 +4,7 @@ export const DEFAULT_DATALABELS_PADDING = 5;
4
4
  export const DEFAULT_DATALABELS_STYLE = {
5
5
  fontSize: '11px',
6
6
  fontWeight: 'bold',
7
- fontColor: 'var(--d3-data-labels)',
7
+ fontColor: 'var(--gcharts-data-labels)',
8
8
  };
9
9
  export const DEFAULT_HALO_OPTIONS = {
10
10
  enabled: true,
@@ -0,0 +1,16 @@
1
+ import type { ChartSeriesOptions, RadarSeries } from '../../types';
2
+ import type { PreparedLegend, PreparedRadarSeries } from './types';
3
+ type PrepareRadarSeriesArgs = {
4
+ series: RadarSeries[];
5
+ seriesOptions?: ChartSeriesOptions;
6
+ legend: PreparedLegend;
7
+ };
8
+ export declare const DEFAULT_MARKER: {
9
+ enabled: boolean;
10
+ radius: number;
11
+ symbol: `${import("../../constants").SymbolType}`;
12
+ borderColor: string;
13
+ borderWidth: number;
14
+ };
15
+ export declare function prepareRadarSeries(args: PrepareRadarSeriesArgs): PreparedRadarSeries[];
16
+ export {};
@@ -0,0 +1,63 @@
1
+ import { scaleOrdinal } from 'd3';
2
+ import get from 'lodash/get';
3
+ import merge from 'lodash/merge';
4
+ import { DEFAULT_PALETTE } from '../../constants';
5
+ import { getUniqId } from '../../utils';
6
+ import { DEFAULT_DATALABELS_PADDING, DEFAULT_DATALABELS_STYLE, DEFAULT_HALO_OPTIONS, DEFAULT_POINT_MARKER_OPTIONS, } from './constants';
7
+ import { prepareLegendSymbol } from './utils';
8
+ export const DEFAULT_MARKER = Object.assign(Object.assign({}, DEFAULT_POINT_MARKER_OPTIONS), { enabled: true, radius: 2 });
9
+ function prepareMarker(series, seriesOptions) {
10
+ var _a;
11
+ const seriesHoverState = get(seriesOptions, 'radar.states.hover');
12
+ const markerNormalState = Object.assign({}, DEFAULT_MARKER, (_a = seriesOptions === null || seriesOptions === void 0 ? void 0 : seriesOptions.radar) === null || _a === void 0 ? void 0 : _a.marker, series.marker);
13
+ const hoveredMarkerDefaultOptions = {
14
+ enabled: true,
15
+ radius: markerNormalState.radius + 1,
16
+ borderWidth: 1,
17
+ borderColor: '#ffffff',
18
+ halo: DEFAULT_HALO_OPTIONS,
19
+ };
20
+ return {
21
+ states: {
22
+ normal: markerNormalState,
23
+ hover: merge(hoveredMarkerDefaultOptions, seriesHoverState === null || seriesHoverState === void 0 ? void 0 : seriesHoverState.marker),
24
+ },
25
+ };
26
+ }
27
+ export function prepareRadarSeries(args) {
28
+ var _a, _b;
29
+ const { series: radarSeries, seriesOptions, legend } = args;
30
+ const colorScale = scaleOrdinal(radarSeries.map((s, index) => { var _a; return (_a = s.name) !== null && _a !== void 0 ? _a : `Series ${index + 1}`; }), DEFAULT_PALETTE);
31
+ const categories = (_b = (_a = radarSeries.find((s) => s.categories)) === null || _a === void 0 ? void 0 : _a.categories) !== null && _b !== void 0 ? _b : [];
32
+ return radarSeries.map((series, index) => {
33
+ var _a, _b, _c, _d, _e;
34
+ const name = (_a = series.name) !== null && _a !== void 0 ? _a : `Series ${index + 1}`;
35
+ const color = (_b = series.color) !== null && _b !== void 0 ? _b : colorScale(name);
36
+ const preparedSeries = {
37
+ type: 'radar',
38
+ data: series.data,
39
+ categories,
40
+ id: getUniqId(),
41
+ name,
42
+ color,
43
+ visible: typeof series.visible === 'boolean' ? series.visible : true,
44
+ legend: {
45
+ enabled: get(series, 'legend.enabled', legend.enabled),
46
+ symbol: prepareLegendSymbol(series),
47
+ },
48
+ borderColor: series.borderColor || color,
49
+ borderWidth: (_c = series.borderWidth) !== null && _c !== void 0 ? _c : 1,
50
+ fillOpacity: (_d = series.fillOpacity) !== null && _d !== void 0 ? _d : 0.25,
51
+ dataLabels: {
52
+ enabled: get(series, 'dataLabels.enabled', true),
53
+ style: Object.assign({}, DEFAULT_DATALABELS_STYLE, (_e = series.dataLabels) === null || _e === void 0 ? void 0 : _e.style),
54
+ padding: get(series, 'dataLabels.padding', DEFAULT_DATALABELS_PADDING),
55
+ allowOverlap: get(series, 'dataLabels.allowOverlap', false),
56
+ html: get(series, 'dataLabels.html', false),
57
+ },
58
+ cursor: get(series, 'cursor', null),
59
+ marker: prepareMarker(series, seriesOptions),
60
+ };
61
+ return preparedSeries;
62
+ });
63
+ }
@@ -4,6 +4,7 @@ import { prepareBarXSeries } from './prepare-bar-x';
4
4
  import { prepareBarYSeries } from './prepare-bar-y';
5
5
  import { prepareLineSeries } from './prepare-line';
6
6
  import { preparePieSeries } from './prepare-pie';
7
+ import { prepareRadarSeries } from './prepare-radar';
7
8
  import { prepareSankeySeries } from './prepare-sankey';
8
9
  import { prepareScatterSeries } from './prepare-scatter';
9
10
  import { prepareTreemap } from './prepare-treemap';
@@ -75,6 +76,13 @@ export function prepareSeries(args) {
75
76
  legend,
76
77
  });
77
78
  }
79
+ case 'radar': {
80
+ return prepareRadarSeries({
81
+ series: series,
82
+ seriesOptions,
83
+ legend,
84
+ });
85
+ }
78
86
  default: {
79
87
  throw new ChartError({
80
88
  message: `Series type "${type}" does not support data preparation for series that do not support the presence of axes`,