@gravity-ui/chartkit 3.4.2 → 3.5.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 (52) hide show
  1. package/build/components/ChartKit.js +2 -2
  2. package/build/components/Loader/Loader.js +2 -2
  3. package/build/plugins/d3/renderer/D3Widget.js +3 -3
  4. package/build/plugins/d3/renderer/components/AxisX.js +2 -2
  5. package/build/plugins/d3/renderer/components/AxisY.js +2 -2
  6. package/build/plugins/d3/renderer/components/Chart.d.ts +3 -1
  7. package/build/plugins/d3/renderer/components/Chart.js +11 -6
  8. package/build/plugins/d3/renderer/components/Legend.js +80 -61
  9. package/build/plugins/d3/renderer/components/Title.js +2 -2
  10. package/build/plugins/d3/renderer/components/Tooltip/DefaultContent.js +12 -0
  11. package/build/plugins/d3/renderer/components/Tooltip/index.js +2 -2
  12. package/build/plugins/d3/renderer/components/styles.css +4 -13
  13. package/build/plugins/d3/renderer/hooks/index.d.ts +1 -1
  14. package/build/plugins/d3/renderer/hooks/index.js +1 -1
  15. package/build/plugins/d3/renderer/hooks/{useScales → useAxisScales}/index.d.ts +6 -3
  16. package/build/plugins/d3/renderer/hooks/useAxisScales/index.js +122 -0
  17. package/build/plugins/d3/renderer/hooks/useChartOptions/chart.js +19 -12
  18. package/build/plugins/d3/renderer/hooks/useChartOptions/index.d.ts +3 -1
  19. package/build/plugins/d3/renderer/hooks/useLegend/index.js +35 -4
  20. package/build/plugins/d3/renderer/hooks/useSeries/index.js +48 -10
  21. package/build/plugins/d3/renderer/hooks/useShapes/bar-x.d.ts +4 -1
  22. package/build/plugins/d3/renderer/hooks/useShapes/bar-x.js +7 -4
  23. package/build/plugins/d3/renderer/hooks/useShapes/index.d.ts +8 -3
  24. package/build/plugins/d3/renderer/hooks/useShapes/index.js +46 -21
  25. package/build/plugins/d3/renderer/hooks/useShapes/pie.d.ts +13 -0
  26. package/build/plugins/d3/renderer/hooks/useShapes/pie.js +51 -0
  27. package/build/plugins/d3/renderer/hooks/useShapes/scatter.d.ts +3 -1
  28. package/build/plugins/d3/renderer/hooks/useShapes/scatter.js +5 -4
  29. package/build/plugins/d3/renderer/hooks/useShapes/styles.css +16 -0
  30. package/build/plugins/d3/renderer/utils/index.d.ts +7 -1
  31. package/build/plugins/d3/renderer/utils/index.js +7 -12
  32. package/build/plugins/d3/renderer/utils/math.d.ts +23 -0
  33. package/build/plugins/d3/renderer/utils/math.js +43 -0
  34. package/build/plugins/highcharts/renderer/components/HighchartsComponent.js +1 -1
  35. package/build/plugins/highcharts/renderer/components/HighchartsReact.d.ts +18 -0
  36. package/build/plugins/highcharts/renderer/components/HighchartsReact.js +46 -0
  37. package/build/plugins/highcharts/renderer/components/StyledSplitPane/StyledSplitPane.js +2 -2
  38. package/build/plugins/highcharts/renderer/components/withSplitPane/withSplitPane.js +2 -2
  39. package/build/plugins/highcharts/renderer/helpers/config/config.js +2 -2
  40. package/build/plugins/highcharts/renderer/helpers/config/options.js +2 -2
  41. package/build/plugins/index.d.ts +1 -0
  42. package/build/plugins/index.js +1 -0
  43. package/build/plugins/indicator/renderer/IndicatorItem.js +2 -2
  44. package/build/plugins/indicator/renderer/IndicatorWidget.js +2 -2
  45. package/build/types/widget-data/bar-x.d.ts +1 -1
  46. package/build/types/widget-data/base.d.ts +3 -0
  47. package/build/types/widget-data/pie.d.ts +18 -1
  48. package/build/types/widget-data/scatter.d.ts +1 -1
  49. package/build/utils/cn.d.ts +3 -0
  50. package/build/utils/cn.js +4 -0
  51. package/package.json +4 -6
  52. package/build/plugins/d3/renderer/hooks/useScales/index.js +0 -109
@@ -1,22 +1,60 @@
1
1
  import React from 'react';
2
- import clone from 'lodash/clone';
2
+ import cloneDeep from 'lodash/cloneDeep';
3
+ import get from 'lodash/get';
3
4
  import { scaleOrdinal } from 'd3';
4
5
  import { DEFAULT_PALETTE } from '../../constants';
5
- import { getSeriesNames } from '../../utils';
6
+ import { getSeriesNames, isAxisRelatedSeries } from '../../utils';
7
+ const prepareAxisRelatedSeries = (args) => {
8
+ const { activeLegendItems, colorScale, series } = args;
9
+ const preparedSeries = cloneDeep(series);
10
+ const legendEnabled = get(preparedSeries, 'legend.enabled', true);
11
+ const defaultVisible = get(preparedSeries, 'visible', true);
12
+ const name = 'name' in series && series.name ? series.name : '';
13
+ const color = 'color' in series && series.color ? series.color : colorScale(name);
14
+ preparedSeries.color = color;
15
+ preparedSeries.name = name;
16
+ preparedSeries.visible = legendEnabled ? activeLegendItems.includes(name) : defaultVisible;
17
+ return preparedSeries;
18
+ };
19
+ const preparePieSeries = (args) => {
20
+ const { activeLegendItems, series } = args;
21
+ const preparedSeries = cloneDeep(series);
22
+ const legendEnabled = get(preparedSeries, 'legend.enabled', true);
23
+ const dataNames = series.data.map((d) => d.name);
24
+ const colorScale = scaleOrdinal(dataNames, DEFAULT_PALETTE);
25
+ preparedSeries.data = preparedSeries.data.map((d) => {
26
+ const defaultVisible = get(d, 'visible', true);
27
+ d.color = d.color || colorScale(d.name);
28
+ d.visible = legendEnabled ? activeLegendItems.includes(d.name) : defaultVisible;
29
+ return d;
30
+ });
31
+ // Not axis related series manages their own data visibility inside their data
32
+ preparedSeries.visible = true;
33
+ return preparedSeries;
34
+ };
35
+ const prepareNotAxisRelatedSeries = (args) => {
36
+ const { activeLegendItems, series } = args;
37
+ switch (series.type) {
38
+ case 'pie': {
39
+ return preparePieSeries({ activeLegendItems, series });
40
+ }
41
+ default: {
42
+ throw new Error(`Series type ${series.type} does not support data preparation for series that do not support the presence of axes`);
43
+ }
44
+ }
45
+ };
6
46
  export const useSeries = (args) => {
7
47
  const { activeLegendItems, series } = args;
8
- // FIXME: handle case with one pie chart series
9
48
  const chartSeries = React.useMemo(() => {
10
49
  const seriesNames = getSeriesNames(series);
11
50
  const colorScale = scaleOrdinal(seriesNames, DEFAULT_PALETTE);
12
51
  return series.map((s) => {
13
- const preparedSeries = clone(s);
14
- const name = 'name' in s ? s.name : '';
15
- const color = 'color' in s && s.color ? s.color : colorScale(name);
16
- preparedSeries.color = color;
17
- preparedSeries.name = name;
18
- preparedSeries.visible = activeLegendItems.includes(name);
19
- return preparedSeries;
52
+ return isAxisRelatedSeries(s)
53
+ ? prepareAxisRelatedSeries({ activeLegendItems, colorScale, series: s })
54
+ : prepareNotAxisRelatedSeries({
55
+ activeLegendItems,
56
+ series: s,
57
+ });
20
58
  });
21
59
  }, [activeLegendItems, series]);
22
60
  return { chartSeries };
@@ -1,9 +1,11 @@
1
1
  import React from 'react';
2
2
  import { ChartOptions } from '../useChartOptions/types';
3
- import { ChartScale } from '../useScales';
3
+ import { ChartScale } from '../useAxisScales';
4
4
  import { OnSeriesMouseLeave, OnSeriesMouseMove } from '../useTooltip/types';
5
5
  import { BarXSeries } from '../../../../../types/widget-data';
6
6
  type Args = {
7
+ top: number;
8
+ left: number;
7
9
  series: BarXSeries[];
8
10
  xAxis: ChartOptions['xAxis'];
9
11
  xScale: ChartScale;
@@ -11,6 +13,7 @@ type Args = {
11
13
  yScale: ChartScale;
12
14
  onSeriesMouseMove?: OnSeriesMouseMove;
13
15
  onSeriesMouseLeave?: OnSeriesMouseLeave;
16
+ svgContainer: SVGSVGElement | null;
14
17
  };
15
18
  export declare function prepareBarXSeries(args: Args): React.ReactElement<any, string | React.JSXElementConstructor<any>>[];
16
19
  export {};
@@ -1,9 +1,10 @@
1
1
  import React from 'react';
2
- import block from 'bem-cn-lite';
2
+ import { block } from '../../../../../utils/cn';
3
+ import { pointer } from 'd3';
3
4
  const DEFAULT_BAR_RECT_WIDTH = 50;
4
5
  const DEFAULT_LINEAR_BAR_RECT_WIDTH = 20;
5
6
  const MIN_RECT_GAP = 1;
6
- const b = block('chartkit-d3-bar');
7
+ const b = block('d3-bar');
7
8
  const getRectProperties = (args) => {
8
9
  const { point, xAxis, xScale, yAxis, yScale, minPointDistance } = args;
9
10
  let cx;
@@ -47,7 +48,7 @@ function minDiff(arr) {
47
48
  return result;
48
49
  }
49
50
  export function prepareBarXSeries(args) {
50
- const { series, xAxis, xScale, yAxis, yScale, onSeriesMouseMove, onSeriesMouseLeave } = args;
51
+ const { top, left, series, xAxis, xScale, yAxis, yScale, onSeriesMouseMove, onSeriesMouseLeave, svgContainer, } = args;
51
52
  const seriesData = series.map(({ data }) => data).flat(2);
52
53
  const minPointDistance = minDiff(seriesData.map((item) => Number(item.x)));
53
54
  return series.reduce((result, item) => {
@@ -61,12 +62,14 @@ export function prepareBarXSeries(args) {
61
62
  yScale,
62
63
  minPointDistance,
63
64
  });
64
- result.push(React.createElement("rect", Object.assign({ key: `${i}-${randomKey}`, className: b('rect'), fill: item.color }, rectProps, { onMouseMove: function () {
65
+ result.push(React.createElement("rect", Object.assign({ key: `${i}-${randomKey}`, className: b('rect'), fill: item.color }, rectProps, { onMouseMove: function (e) {
66
+ const [x, y] = pointer(e, svgContainer);
65
67
  onSeriesMouseMove === null || onSeriesMouseMove === void 0 ? void 0 : onSeriesMouseMove({
66
68
  hovered: {
67
69
  data: point,
68
70
  series: item,
69
71
  },
72
+ pointerPosition: [x - left, y - top],
70
73
  });
71
74
  }, onMouseLeave: onSeriesMouseLeave })));
72
75
  });
@@ -1,17 +1,22 @@
1
1
  import React from 'react';
2
2
  import type { ChartOptions } from '../useChartOptions/types';
3
- import type { ChartScale } from '../useScales';
3
+ import type { ChartScale } from '../useAxisScales';
4
4
  import type { ChartSeries } from '../useSeries';
5
5
  import type { OnSeriesMouseMove, OnSeriesMouseLeave } from '../useTooltip/types';
6
+ import './styles.css';
6
7
  type Args = {
8
+ top: number;
9
+ left: number;
10
+ boundsWidth: number;
11
+ boundsHeight: number;
7
12
  series: ChartSeries[];
8
13
  xAxis: ChartOptions['xAxis'];
9
- xScale: ChartScale;
10
14
  yAxis: ChartOptions['yAxis'];
11
- yScale: ChartScale;
12
15
  svgContainer: SVGSVGElement | null;
13
16
  onSeriesMouseMove?: OnSeriesMouseMove;
14
17
  onSeriesMouseLeave?: OnSeriesMouseLeave;
18
+ xScale?: ChartScale;
19
+ yScale?: ChartScale;
15
20
  };
16
21
  export declare const useShapes: (args: Args) => {
17
22
  shapes: React.ReactElement<any, string | React.JSXElementConstructor<any>>[];
@@ -3,8 +3,10 @@ import { group } from 'd3';
3
3
  import { getOnlyVisibleSeries } from '../../utils';
4
4
  import { prepareBarXSeries } from './bar-x';
5
5
  import { prepareScatterSeries } from './scatter';
6
+ import { PieSeriesComponent } from './pie';
7
+ import './styles.css';
6
8
  export const useShapes = (args) => {
7
- const { series, xAxis, xScale, yAxis, yScale, svgContainer, onSeriesMouseMove, onSeriesMouseLeave, } = args;
9
+ const { top, left, boundsWidth, boundsHeight, series, xAxis, xScale, yAxis, yScale, svgContainer, onSeriesMouseMove, onSeriesMouseLeave, } = args;
8
10
  const shapes = React.useMemo(() => {
9
11
  const visibleSeries = getOnlyVisibleSeries(series);
10
12
  const groupedSeries = group(visibleSeries, (item) => item.type);
@@ -12,33 +14,56 @@ export const useShapes = (args) => {
12
14
  const [seriesType, chartSeries] = item;
13
15
  switch (seriesType) {
14
16
  case 'bar-x': {
15
- acc.push(...prepareBarXSeries({
16
- series: chartSeries,
17
- xAxis,
18
- xScale,
19
- yAxis,
20
- yScale,
21
- onSeriesMouseMove,
22
- onSeriesMouseLeave,
23
- }));
17
+ if (xScale && yScale) {
18
+ acc.push(...prepareBarXSeries({
19
+ top,
20
+ left,
21
+ series: chartSeries,
22
+ xAxis,
23
+ xScale,
24
+ yAxis,
25
+ yScale,
26
+ onSeriesMouseMove,
27
+ onSeriesMouseLeave,
28
+ svgContainer,
29
+ }));
30
+ }
24
31
  break;
25
32
  }
26
33
  case 'scatter': {
27
- acc.push(...prepareScatterSeries({
28
- series: chartSeries,
29
- xAxis,
30
- xScale,
31
- yAxis,
32
- yScale,
33
- onSeriesMouseMove,
34
- onSeriesMouseLeave,
35
- svgContainer,
36
- }));
34
+ if (xScale && yScale) {
35
+ acc.push(...prepareScatterSeries({
36
+ top,
37
+ left,
38
+ series: chartSeries,
39
+ xAxis,
40
+ xScale,
41
+ yAxis,
42
+ yScale,
43
+ onSeriesMouseMove,
44
+ onSeriesMouseLeave,
45
+ svgContainer,
46
+ }));
47
+ }
37
48
  break;
38
49
  }
50
+ case 'pie': {
51
+ acc.push(...chartSeries.map((cs, i) => (React.createElement(PieSeriesComponent, { key: `pie-${i}`, boundsWidth: boundsWidth, boundsHeight: boundsHeight, series: cs, onSeriesMouseMove: onSeriesMouseMove, onSeriesMouseLeave: onSeriesMouseLeave, svgContainer: svgContainer }))));
52
+ }
39
53
  }
40
54
  return acc;
41
55
  }, []);
42
- }, [series, xAxis, xScale, yAxis, yScale, svgContainer, onSeriesMouseMove, onSeriesMouseLeave]);
56
+ }, [
57
+ boundsWidth,
58
+ boundsHeight,
59
+ series,
60
+ xAxis,
61
+ xScale,
62
+ yAxis,
63
+ yScale,
64
+ svgContainer,
65
+ onSeriesMouseMove,
66
+ onSeriesMouseLeave,
67
+ ]);
43
68
  return { shapes };
44
69
  };
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import type { PieSeries } from '../../../../../types/widget-data';
3
+ import type { OnSeriesMouseLeave, OnSeriesMouseMove } from '../useTooltip/types';
4
+ type PreparePieSeriesArgs = {
5
+ boundsWidth: number;
6
+ boundsHeight: number;
7
+ series: PieSeries;
8
+ svgContainer: SVGSVGElement | null;
9
+ onSeriesMouseMove?: OnSeriesMouseMove;
10
+ onSeriesMouseLeave?: OnSeriesMouseLeave;
11
+ };
12
+ export declare function PieSeriesComponent(args: PreparePieSeriesArgs): React.JSX.Element;
13
+ export {};
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import { arc, pie, select } from 'd3';
3
+ import { block } from '../../../../../utils/cn';
4
+ import { calculateNumericProperty } from '../../utils';
5
+ const b = block('d3-pie');
6
+ const getCenter = (boundsWidth, boundsHeight, center) => {
7
+ var _a, _b;
8
+ const defaultX = boundsWidth * 0.5;
9
+ const defaultY = boundsHeight * 0.5;
10
+ if (!center) {
11
+ return [defaultX, defaultY];
12
+ }
13
+ const [x, y] = center;
14
+ const resultX = (_a = calculateNumericProperty({ value: x, base: boundsWidth })) !== null && _a !== void 0 ? _a : defaultX;
15
+ const resultY = (_b = calculateNumericProperty({ value: y, base: boundsHeight })) !== null && _b !== void 0 ? _b : defaultY;
16
+ return [resultX, resultY];
17
+ };
18
+ export function PieSeriesComponent(args) {
19
+ const { boundsWidth, boundsHeight, series, onSeriesMouseMove, onSeriesMouseLeave, svgContainer } = args;
20
+ const ref = React.useRef(null);
21
+ const [x, y] = getCenter(boundsWidth, boundsHeight, series.center);
22
+ React.useEffect(() => {
23
+ var _a, _b, _c, _d;
24
+ if (!ref.current) {
25
+ return;
26
+ }
27
+ const svgElement = select(ref.current);
28
+ const radiusRelatedToChart = Math.min(boundsWidth, boundsHeight) / 2;
29
+ const radius = (_a = calculateNumericProperty({ value: series.radius, base: radiusRelatedToChart })) !== null && _a !== void 0 ? _a : radiusRelatedToChart;
30
+ const innerRadius = (_b = calculateNumericProperty({ value: series.innerRadius, base: radius })) !== null && _b !== void 0 ? _b : 0;
31
+ const pieGenerator = pie().value((d) => d.value);
32
+ const visibleData = series.data.filter((d) => d.visible);
33
+ const dataReady = pieGenerator(visibleData);
34
+ const arcGenerator = arc()
35
+ .innerRadius(innerRadius)
36
+ .outerRadius(radius)
37
+ .cornerRadius((_c = series.borderRadius) !== null && _c !== void 0 ? _c : 0);
38
+ svgElement.selectAll('*').remove();
39
+ svgElement
40
+ .selectAll('*')
41
+ .data(dataReady)
42
+ .enter()
43
+ .append('path')
44
+ .attr('d', arcGenerator)
45
+ .attr('class', b('segment'))
46
+ .attr('fill', (d) => d.data.color || '')
47
+ .style('stroke', series.borderColor || '')
48
+ .style('stroke-width', (_d = series.borderWidth) !== null && _d !== void 0 ? _d : 1);
49
+ }, [boundsWidth, boundsHeight, series, onSeriesMouseMove, onSeriesMouseLeave, svgContainer]);
50
+ return React.createElement("g", { ref: ref, className: b(), transform: `translate(${x}, ${y})` });
51
+ }
@@ -1,9 +1,11 @@
1
1
  import React from 'react';
2
2
  import { ChartOptions } from '../useChartOptions/types';
3
- import { ChartScale } from '../useScales';
3
+ import { ChartScale } from '../useAxisScales';
4
4
  import { OnSeriesMouseLeave, OnSeriesMouseMove } from '../useTooltip/types';
5
5
  import { ScatterSeries } from '../../../../../types/widget-data';
6
6
  type PrepareScatterSeriesArgs = {
7
+ top: number;
8
+ left: number;
7
9
  series: ScatterSeries[];
8
10
  xAxis: ChartOptions['xAxis'];
9
11
  xScale: ChartScale;
@@ -1,7 +1,7 @@
1
1
  import { pointer } from 'd3';
2
2
  import React from 'react';
3
- import block from 'bem-cn-lite';
4
- const b = block('chartkit-d3-scatter');
3
+ import { block } from '../../../../../utils/cn';
4
+ const b = block('d3-scatter');
5
5
  const DEFAULT_SCATTER_POINT_RADIUS = 4;
6
6
  const prepareCategoricalScatterData = (data) => {
7
7
  return data.filter((d) => typeof d.category === 'string');
@@ -33,7 +33,7 @@ const getPointProperties = (args) => {
33
33
  return { r, cx, cy };
34
34
  };
35
35
  export function prepareScatterSeries(args) {
36
- const { series, xAxis, xScale, yAxis, yScale, onSeriesMouseMove, onSeriesMouseLeave, key, svgContainer, } = args;
36
+ const { top, left, series, xAxis, xScale, yAxis, yScale, onSeriesMouseMove, onSeriesMouseLeave, key, svgContainer, } = args;
37
37
  return series.reduce((result, s) => {
38
38
  var _a;
39
39
  const preparedData = xAxis.type === 'category' || ((_a = yAxis[0]) === null || _a === void 0 ? void 0 : _a.type) === 'category'
@@ -48,12 +48,13 @@ export function prepareScatterSeries(args) {
48
48
  yScale,
49
49
  });
50
50
  return (React.createElement("circle", Object.assign({ key: `${i}-${key}`, className: b('point'), fill: s.color }, pointProps, { onMouseMove: function (e) {
51
+ const [x, y] = pointer(e, svgContainer);
51
52
  onSeriesMouseMove === null || onSeriesMouseMove === void 0 ? void 0 : onSeriesMouseMove({
52
53
  hovered: {
53
54
  data: point,
54
55
  series: s,
55
56
  },
56
- pointerPosition: pointer(e, svgContainer),
57
+ pointerPosition: [x - left, y - top],
57
58
  });
58
59
  }, onMouseLeave: onSeriesMouseLeave })));
59
60
  }));
@@ -0,0 +1,16 @@
1
+ .chartkit-d3-scatter__point {
2
+ stroke-width: 1px;
3
+ }
4
+
5
+ .chartkit-d3_hovered .chartkit-d3-scatter__point {
6
+ opacity: 0.5;
7
+ }
8
+
9
+ .chartkit-d3-scatter__point:hover {
10
+ stroke: #fff;
11
+ opacity: 1;
12
+ }
13
+
14
+ .chartkit-d3-pie__segment {
15
+ stroke: var(--g-color-base-background);
16
+ }
@@ -1,10 +1,16 @@
1
1
  import type { AxisDomain } from 'd3';
2
2
  import type { ChartKitWidgetSeries, ChartKitWidgetAxisType, ChartKitWidgetAxisLabels } from '../../../../types/widget-data';
3
+ export * from './math';
4
+ /**
5
+ * Checks whether the series should be drawn with axes.
6
+ *
7
+ * @param series - The series object to check.
8
+ * @returns `true` if the series should be drawn with axes, `false` otherwise.
9
+ */
3
10
  export declare const isAxisRelatedSeries: (series: ChartKitWidgetSeries) => boolean;
4
11
  export declare const getDomainDataXBySeries: (series: ChartKitWidgetSeries[]) => unknown[];
5
12
  export declare const getDomainDataYBySeries: (series: ChartKitWidgetSeries[]) => unknown[];
6
13
  export declare const getSeriesNames: (series: ChartKitWidgetSeries[]) => string[];
7
- export declare const getVisibleSeriesNames: (series: ChartKitWidgetSeries[]) => string[];
8
14
  export declare const getOnlyVisibleSeries: <T extends ChartKitWidgetSeries<any>>(series: T[]) => T[];
9
15
  export declare const parseTransformStyle: (style: string | null) => {
10
16
  x?: number | undefined;
@@ -1,7 +1,13 @@
1
1
  import { dateTime } from '@gravity-ui/date-utils';
2
2
  import { formatNumber } from '../../../shared';
3
+ export * from './math';
3
4
  const CHARTS_WITHOUT_AXIS = ['pie'];
4
- // Сhecks whether the series should be drawn with axes
5
+ /**
6
+ * Checks whether the series should be drawn with axes.
7
+ *
8
+ * @param series - The series object to check.
9
+ * @returns `true` if the series should be drawn with axes, `false` otherwise.
10
+ */
5
11
  export const isAxisRelatedSeries = (series) => {
6
12
  return !CHARTS_WITHOUT_AXIS.includes(series.type);
7
13
  };
@@ -26,17 +32,6 @@ export const getSeriesNames = (series) => {
26
32
  return acc;
27
33
  }, []);
28
34
  };
29
- // Uses to get all visible series names array (except `pie` charts)
30
- export const getVisibleSeriesNames = (series) => {
31
- return series.reduce((acc, s) => {
32
- var _a;
33
- const visible = (_a = s.visible) !== null && _a !== void 0 ? _a : true;
34
- if ('name' in s && typeof s.name === 'string' && visible) {
35
- acc.push(s.name);
36
- }
37
- return acc;
38
- }, []);
39
- };
40
35
  export const getOnlyVisibleSeries = (series) => {
41
36
  return series.filter((s) => s.visible);
42
37
  };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Calculates a numeric property based on the given arguments.
3
+ *
4
+ * @param {Object} args - The arguments for the calculation.
5
+ * @param {string | number | null} args.value - The value to calculate the property for.
6
+ * @param {number} args.base - The base value to use in the calculation.
7
+ * @return {number | undefined} The calculated numeric property, or undefined if the value is invalid.
8
+ * @example
9
+ * const result1 = calculateNumericProperty({value: 1});
10
+ * console.log(result1); // Output: 1
11
+ * const result2 = calculateNumericProperty({value: '10px'});
12
+ * console.log(result2); // Output: 10
13
+ * const result3 = calculateNumericProperty({value: '50%', base: 200});
14
+ * console.log(result3); // Output: 100
15
+ * const result4 = calculateNumericProperty({value: '50%'});
16
+ * console.log(result4); // Output: undefined
17
+ * const result5 = calculateNumericProperty({value: 'invalid_value'});
18
+ * console.log(result5); // Output: undefined
19
+ */
20
+ export declare const calculateNumericProperty: (args: {
21
+ value?: string | number | null;
22
+ base?: number;
23
+ }) => number | undefined;
@@ -0,0 +1,43 @@
1
+ import isNil from 'lodash/isNil';
2
+ const isStringValueInPercent = (value = '') => {
3
+ return value.endsWith('%') && !Number.isNaN(Number.parseFloat(value));
4
+ };
5
+ const isStringValueInPixel = (value = '') => {
6
+ return value.endsWith('px') && !Number.isNaN(Number.parseFloat(value));
7
+ };
8
+ /**
9
+ * Calculates a numeric property based on the given arguments.
10
+ *
11
+ * @param {Object} args - The arguments for the calculation.
12
+ * @param {string | number | null} args.value - The value to calculate the property for.
13
+ * @param {number} args.base - The base value to use in the calculation.
14
+ * @return {number | undefined} The calculated numeric property, or undefined if the value is invalid.
15
+ * @example
16
+ * const result1 = calculateNumericProperty({value: 1});
17
+ * console.log(result1); // Output: 1
18
+ * const result2 = calculateNumericProperty({value: '10px'});
19
+ * console.log(result2); // Output: 10
20
+ * const result3 = calculateNumericProperty({value: '50%', base: 200});
21
+ * console.log(result3); // Output: 100
22
+ * const result4 = calculateNumericProperty({value: '50%'});
23
+ * console.log(result4); // Output: undefined
24
+ * const result5 = calculateNumericProperty({value: 'invalid_value'});
25
+ * console.log(result5); // Output: undefined
26
+ */
27
+ export const calculateNumericProperty = (args) => {
28
+ const { value = '', base } = args;
29
+ if (isNil(value)) {
30
+ return undefined;
31
+ }
32
+ if (typeof value === 'string') {
33
+ if (isStringValueInPercent(value) && typeof base === 'number') {
34
+ const fraction = Number.parseFloat(value) / 100;
35
+ return base * fraction;
36
+ }
37
+ if (isStringValueInPixel(value)) {
38
+ return Number.parseFloat(value);
39
+ }
40
+ return undefined;
41
+ }
42
+ return value;
43
+ };
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import Highcharts from 'highcharts';
3
- import HighchartsReact from 'highcharts-react-official';
3
+ import HighchartsReact from './HighchartsReact';
4
4
  import get from 'lodash/get';
5
5
  import { settings } from '../../../../libs';
6
6
  import { settingsEventEmitter } from '../../../../libs/settings/settings';
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import Highcharts from 'highcharts';
3
+ interface HighchartsReactRefObject {
4
+ chart: Highcharts.Chart | null | undefined;
5
+ container: React.RefObject<HTMLDivElement | undefined>;
6
+ }
7
+ interface HighchartsReactProps {
8
+ [key: string]: any;
9
+ constructorType?: keyof typeof Highcharts;
10
+ containerProps?: {
11
+ [key: string]: any;
12
+ };
13
+ highcharts?: typeof Highcharts;
14
+ options: Highcharts.Options;
15
+ callback?: Highcharts.ChartCallbackFunction;
16
+ }
17
+ export declare const HighchartsReact: React.ForwardRefExoticComponent<React.PropsWithoutRef<HighchartsReactProps> & React.RefAttributes<HighchartsReactRefObject>>;
18
+ export default HighchartsReact;
@@ -0,0 +1,46 @@
1
+ /* eslint no-console: ["error", { allow: ["warn", "error"]}] */
2
+ import React from 'react';
3
+ const useIsomorphicLayoutEffect = typeof window === 'undefined' ? React.useEffect : React.useLayoutEffect;
4
+ export const HighchartsReact = React.memo(React.forwardRef(function HighchartsReact(props, ref) {
5
+ const containerRef = React.useRef(null);
6
+ const chartRef = React.useRef();
7
+ useIsomorphicLayoutEffect(() => {
8
+ function createChart() {
9
+ const { highcharts: HighchartsComponent } = props;
10
+ const constructorType = props.constructorType || 'chart';
11
+ if (!HighchartsComponent) {
12
+ console.warn('The "highcharts" property was not passed.');
13
+ }
14
+ else if (!HighchartsComponent[constructorType]) {
15
+ console.warn('The "constructorType" property is incorrect or some ' +
16
+ 'required module is not imported.');
17
+ }
18
+ else if (props.options) {
19
+ chartRef.current = HighchartsComponent[constructorType](containerRef.current, props.options, props.callback);
20
+ }
21
+ else {
22
+ console.warn('The "options" property was not passed.');
23
+ }
24
+ }
25
+ if (!chartRef.current) {
26
+ createChart();
27
+ }
28
+ }, [props.options, props.allowChartUpdate, props.containerProps, props.highcharts, props.constructorType]);
29
+ useIsomorphicLayoutEffect(() => {
30
+ return () => {
31
+ if (chartRef.current) {
32
+ chartRef.current.destroy();
33
+ chartRef.current = null;
34
+ }
35
+ };
36
+ }, []);
37
+ React.useImperativeHandle(ref, () => ({
38
+ get chart() {
39
+ return chartRef.current;
40
+ },
41
+ container: containerRef,
42
+ }), []);
43
+ return React.createElement("div", Object.assign({}, props.containerProps, { ref: containerRef }));
44
+ }));
45
+ HighchartsReact.displayName = 'HighchartsReact';
46
+ export default HighchartsReact;
@@ -1,9 +1,9 @@
1
1
  import { __rest } from "tslib";
2
2
  import React from 'react';
3
3
  import SplitPane, { Pane } from 'react-split-pane';
4
- import block from 'bem-cn-lite';
4
+ import { cn } from '../../../../../utils/cn';
5
5
  import './StyledSplitPane.css';
6
- const b = block('styled-split-pane');
6
+ const b = cn('styled-split-pane');
7
7
  const resizerClassName = b('pane-resizer');
8
8
  export const StyledSplitPane = (_a) => {
9
9
  var { paneOneRender, paneTwoRender } = _a, splitPaneProps = __rest(_a, ["paneOneRender", "paneTwoRender"]);
@@ -1,12 +1,12 @@
1
1
  /* eslint callback-return: 0 */
2
2
  import React from 'react';
3
- import block from 'bem-cn-lite';
4
3
  import { debounce, get } from 'lodash';
5
4
  import { getRandomCKId } from '../../../../../utils';
5
+ import { cn } from '../../../../../utils/cn';
6
6
  import { chartTypesWithoutCrosshair } from '../../helpers/config/config';
7
7
  import { StyledSplitPane } from '../StyledSplitPane/StyledSplitPane';
8
8
  import './WithSplitPane.css';
9
- const b = block('with-split-pane');
9
+ const b = cn('with-split-pane');
10
10
  const PANE_RESIZER_HEIGHT = 24;
11
11
  const CHART_SECTION_PERCENTAGE = 0.6;
12
12
  const MIN_TOOLTIP_SECTION_HEIGHT = 62;
@@ -1,6 +1,5 @@
1
1
  /* eslint new-cap: 0, complexity: 0 */
2
2
  import Highcharts from 'highcharts';
3
- import block from 'bem-cn-lite';
4
3
  import merge from 'lodash/merge';
5
4
  import mergeWith from 'lodash/mergeWith';
6
5
  import get from 'lodash/get';
@@ -13,13 +12,14 @@ import debounce from 'lodash/debounce';
13
12
  import { dateTime } from '@gravity-ui/date-utils';
14
13
  import { i18n } from '../../../../../i18n';
15
14
  import { formatNumber } from '../../../../shared';
15
+ import { block } from '../../../../../utils/cn';
16
16
  import { getCommentsOnLine, drawComments, hideComments, drawOnlyRendererComments, } from '../comments/drawing';
17
17
  import formatTooltip, { TOOLTIP_ROW_CLASS_NAME, SERIES_NAME_DATA_ATTRIBUTE, TOOLTIP_HEADER_CLASS_NAME, TOOLTIP_LIST_CLASS_NAME, TOOLTIP_FOOTER_CLASS_NAME, TOOLTIP_CONTAINER_CLASS_NAME, TOOLTIP_ROW_NAME_CLASS_NANE, } from '../tooltip';
18
18
  import defaultOptions from './options';
19
19
  import { calculatePrecision, isTooltipShared, isSafari, mergeArrayWithObject, concatStrings, buildNavigatorFallback, addShowInNavigatorToSeries, setNavigatorDefaultPeriod, numberFormat, getFormatOptionsFromLine, checkTooltipPinningAvailability, getSortedData, } from './utils';
20
20
  import { handleLegendItemClick } from './handleLegendItemClick';
21
21
  import { getChartKitFormattedValue } from './utils/getChartKitFormattedValue';
22
- const b = block('chartkit-tooltip');
22
+ const b = block('tooltip');
23
23
  const TOOLTIP_OFFSET_FROM_CURSOR = 15;
24
24
  const TOOLTIP_ROOT_CLASS_NAME = 'chartkit-highcharts-tooltip-container';
25
25
  const MOBILE_TOOLTIP_OFFSET_FROM_POINTER = 30;
@@ -1,10 +1,10 @@
1
1
  /** Default options for Highcharts & Highstock */
2
- import block from 'bem-cn-lite';
3
2
  import merge from 'lodash/merge';
4
3
  import { i18n } from '../../../../../i18n';
4
+ import { block } from '../../../../../utils/cn';
5
5
  import { getChartKitFormattedValue } from './utils';
6
6
  import LocalStorage from './utils/localStorage';
7
- const b = block('chartkit-tooltip');
7
+ const b = block('tooltip');
8
8
  function getTooltipHeaderFormat(format, showColor) {
9
9
  return `<div class="${b('header')}">
10
10
  ${showColor
@@ -4,3 +4,4 @@ export { IndicatorPlugin } from './indicator';
4
4
  export type { IndicatorWidgetData } from './indicator/types';
5
5
  export { HighchartsPlugin } from './highcharts';
6
6
  export * from './highcharts/types';
7
+ export { HighchartsReact } from './highcharts/renderer/components/HighchartsReact';