@gravity-ui/chartkit 5.6.0 → 5.8.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 (50) hide show
  1. package/build/plugins/d3/examples/area/NegativeValues.d.ts +2 -0
  2. package/build/plugins/d3/examples/area/NegativeValues.js +24 -0
  3. package/build/plugins/d3/examples/bar-x/NegativeValues.d.ts +2 -0
  4. package/build/plugins/d3/examples/bar-x/NegativeValues.js +41 -0
  5. package/build/plugins/d3/examples/bar-y/NegativeValues.d.ts +2 -0
  6. package/build/plugins/d3/examples/bar-y/NegativeValues.js +40 -0
  7. package/build/plugins/d3/renderer/components/AxisX.d.ts +2 -1
  8. package/build/plugins/d3/renderer/components/AxisX.js +13 -3
  9. package/build/plugins/d3/renderer/components/AxisY.d.ts +4 -3
  10. package/build/plugins/d3/renderer/components/AxisY.js +17 -8
  11. package/build/plugins/d3/renderer/components/Chart.js +14 -3
  12. package/build/plugins/d3/renderer/components/PlotTitle.d.ts +7 -0
  13. package/build/plugins/d3/renderer/components/PlotTitle.js +12 -0
  14. package/build/plugins/d3/renderer/components/styles.css +7 -1
  15. package/build/plugins/d3/renderer/hooks/index.d.ts +1 -0
  16. package/build/plugins/d3/renderer/hooks/index.js +1 -0
  17. package/build/plugins/d3/renderer/hooks/useAxisScales/index.d.ts +3 -1
  18. package/build/plugins/d3/renderer/hooks/useAxisScales/index.js +30 -14
  19. package/build/plugins/d3/renderer/hooks/useChartDimensions/utils.js +13 -2
  20. package/build/plugins/d3/renderer/hooks/useChartOptions/types.d.ts +1 -0
  21. package/build/plugins/d3/renderer/hooks/useChartOptions/x-axis.d.ts +2 -2
  22. package/build/plugins/d3/renderer/hooks/useChartOptions/x-axis.js +14 -2
  23. package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.d.ts +2 -2
  24. package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.js +18 -8
  25. package/build/plugins/d3/renderer/hooks/useSeries/prepare-bar-y.js +2 -1
  26. package/build/plugins/d3/renderer/hooks/useShapes/area/prepare-data.js +15 -5
  27. package/build/plugins/d3/renderer/hooks/useShapes/bar-x/prepare-data.js +5 -3
  28. package/build/plugins/d3/renderer/hooks/useShapes/bar-y/prepare-data.js +5 -3
  29. package/build/plugins/d3/renderer/hooks/useShapes/index.d.ts +2 -1
  30. package/build/plugins/d3/renderer/hooks/useShapes/index.js +2 -1
  31. package/build/plugins/d3/renderer/hooks/useShapes/line/prepare-data.d.ts +6 -4
  32. package/build/plugins/d3/renderer/hooks/useShapes/line/prepare-data.js +6 -3
  33. package/build/plugins/d3/renderer/hooks/useSplit/index.d.ts +14 -0
  34. package/build/plugins/d3/renderer/hooks/useSplit/index.js +57 -0
  35. package/build/plugins/d3/renderer/hooks/useSplit/types.d.ts +17 -0
  36. package/build/plugins/d3/renderer/hooks/useSplit/types.js +1 -0
  37. package/build/plugins/d3/renderer/utils/axis-generators/bottom.d.ts +1 -1
  38. package/build/plugins/d3/renderer/utils/axis-generators/bottom.js +16 -8
  39. package/build/plugins/d3/renderer/utils/axis.d.ts +6 -2
  40. package/build/plugins/d3/renderer/utils/axis.js +7 -0
  41. package/build/plugins/d3/renderer/utils/index.d.ts +4 -1
  42. package/build/plugins/d3/renderer/utils/index.js +51 -25
  43. package/build/plugins/highcharts/renderer/helpers/config/config.js +2 -2
  44. package/build/types/widget-data/axis.d.ts +10 -0
  45. package/build/types/widget-data/bar-y.d.ts +2 -1
  46. package/build/types/widget-data/index.d.ts +8 -3
  47. package/build/types/widget-data/index.js +1 -0
  48. package/build/types/widget-data/split.d.ts +13 -0
  49. package/build/types/widget-data/split.js +1 -0
  50. package/package.json +1 -1
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const NegativeValues: () => React.JSX.Element;
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import { ChartKit } from '../../../../components/ChartKit';
3
+ import { ExampleWrapper } from '../ExampleWrapper';
4
+ export const NegativeValues = () => {
5
+ const data = [
6
+ { x: 0, y: 10 },
7
+ { x: 1, y: 20 },
8
+ { x: 2, y: -30 },
9
+ { x: 3, y: 100 },
10
+ ];
11
+ const widgetData = {
12
+ series: {
13
+ data: [
14
+ {
15
+ type: 'area',
16
+ data: data,
17
+ name: 'Min temperature',
18
+ },
19
+ ],
20
+ },
21
+ };
22
+ return (React.createElement(ExampleWrapper, null,
23
+ React.createElement(ChartKit, { type: "d3", data: widgetData })));
24
+ };
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const NegativeValues: () => React.JSX.Element;
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import { dateTime } from '@gravity-ui/date-utils';
3
+ import { ChartKit } from '../../../../components/ChartKit';
4
+ import { ExampleWrapper } from '../ExampleWrapper';
5
+ import marsWeatherData from '../mars-weather';
6
+ export const NegativeValues = () => {
7
+ const data = marsWeatherData.map((d) => ({
8
+ x: dateTime({ input: d.terrestrial_date, format: 'YYYY-MM-DD' }).valueOf(),
9
+ y: d.min_temp,
10
+ }));
11
+ const widgetData = {
12
+ series: {
13
+ data: [
14
+ {
15
+ type: 'bar-x',
16
+ data: data,
17
+ name: 'Min temperature',
18
+ },
19
+ ],
20
+ },
21
+ yAxis: [
22
+ {
23
+ title: {
24
+ text: 'Min temperature',
25
+ },
26
+ },
27
+ ],
28
+ xAxis: {
29
+ type: 'datetime',
30
+ title: {
31
+ text: 'Terrestrial date',
32
+ },
33
+ ticks: { pixelInterval: 200 },
34
+ },
35
+ title: {
36
+ text: 'Mars weather',
37
+ },
38
+ };
39
+ return (React.createElement(ExampleWrapper, null,
40
+ React.createElement(ChartKit, { type: "d3", data: widgetData })));
41
+ };
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const NegativeValues: () => React.JSX.Element;
@@ -0,0 +1,40 @@
1
+ import React from 'react';
2
+ import { dateTime } from '@gravity-ui/date-utils';
3
+ import { ChartKit } from '../../../../components/ChartKit';
4
+ import { ExampleWrapper } from '../ExampleWrapper';
5
+ import marsWeatherData from '../mars-weather';
6
+ export const NegativeValues = () => {
7
+ const data = marsWeatherData.map((d) => ({
8
+ y: dateTime({ input: d.terrestrial_date, format: 'YYYY-MM-DD' }).valueOf(),
9
+ x: d.min_temp,
10
+ }));
11
+ const widgetData = {
12
+ series: {
13
+ data: [
14
+ {
15
+ type: 'bar-y',
16
+ data: data,
17
+ name: 'Min temperature',
18
+ },
19
+ ],
20
+ },
21
+ xAxis: {
22
+ title: {
23
+ text: 'Min temperature',
24
+ },
25
+ },
26
+ yAxis: [
27
+ {
28
+ type: 'datetime',
29
+ title: {
30
+ text: 'Terrestrial date',
31
+ },
32
+ },
33
+ ],
34
+ title: {
35
+ text: 'Mars weather',
36
+ },
37
+ };
38
+ return (React.createElement(ExampleWrapper, null,
39
+ React.createElement(ChartKit, { type: "d3", data: widgetData })));
40
+ };
@@ -1,10 +1,11 @@
1
1
  import React from 'react';
2
- import type { ChartScale, PreparedAxis } from '../hooks';
2
+ import type { ChartScale, PreparedAxis, PreparedSplit } from '../hooks';
3
3
  type Props = {
4
4
  axis: PreparedAxis;
5
5
  width: number;
6
6
  height: number;
7
7
  scale: ChartScale;
8
+ split: PreparedSplit;
8
9
  };
9
10
  export declare const AxisX: React.NamedExoticComponent<Props>;
10
11
  export {};
@@ -18,16 +18,26 @@ function getLabelFormatter({ axis, scale }) {
18
18
  });
19
19
  };
20
20
  }
21
- export const AxisX = React.memo(function AxisX({ axis, width, height, scale }) {
21
+ export const AxisX = React.memo(function AxisX(props) {
22
+ const { axis, width, height: totalHeight, scale, split } = props;
22
23
  const ref = React.useRef(null);
23
24
  React.useEffect(() => {
24
25
  if (!ref.current) {
25
26
  return;
26
27
  }
28
+ let tickItems = [];
29
+ if (axis.grid.enabled) {
30
+ tickItems = new Array(split.plots.length || 1).fill(null).map((_, index) => {
31
+ var _a, _b;
32
+ const top = ((_a = split.plots[index]) === null || _a === void 0 ? void 0 : _a.top) || 0;
33
+ const height = ((_b = split.plots[index]) === null || _b === void 0 ? void 0 : _b.height) || totalHeight;
34
+ return [-top, -(top + height)];
35
+ });
36
+ }
27
37
  const xAxisGenerator = axisBottom({
28
38
  scale: scale,
29
39
  ticks: {
30
- size: axis.grid.enabled ? height * -1 : 0,
40
+ items: tickItems,
31
41
  labelFormat: getLabelFormatter({ axis, scale }),
32
42
  labelsPaddings: axis.labels.padding,
33
43
  labelsMargin: axis.labels.margin,
@@ -59,6 +69,6 @@ export const AxisX = React.memo(function AxisX({ axis, width, height, scale }) {
59
69
  .text(axis.title.text)
60
70
  .call(setEllipsisForOverflowText, width);
61
71
  }
62
- }, [axis, width, height, scale]);
72
+ }, [axis, width, totalHeight, scale, split]);
63
73
  return React.createElement("g", { ref: ref });
64
74
  });
@@ -1,10 +1,11 @@
1
1
  import React from 'react';
2
- import type { ChartScale, PreparedAxis } from '../hooks';
2
+ import type { ChartScale, PreparedAxis, PreparedSplit } from '../hooks';
3
3
  type Props = {
4
- axises: PreparedAxis[];
4
+ axes: PreparedAxis[];
5
5
  scale: ChartScale[];
6
6
  width: number;
7
7
  height: number;
8
+ split: PreparedSplit;
8
9
  };
9
- export declare const AxisY: ({ axises, width, height, scale }: Props) => React.JSX.Element;
10
+ export declare const AxisY: (props: Props) => React.JSX.Element;
10
11
  export {};
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { axisLeft, axisRight, line, select } from 'd3';
3
3
  import { block } from '../../../../utils/cn';
4
- import { calculateCos, calculateSin, formatAxisTickLabel, getClosestPointsRange, getScaleTicks, getTicksCount, parseTransformStyle, setEllipsisForOverflowText, setEllipsisForOverflowTexts, } from '../utils';
4
+ import { calculateCos, calculateSin, formatAxisTickLabel, getAxisHeight, getClosestPointsRange, getScaleTicks, getTicksCount, parseTransformStyle, setEllipsisForOverflowText, setEllipsisForOverflowTexts, } from '../utils';
5
5
  const b = block('d3-axis');
6
6
  function transformLabel(args) {
7
7
  const { node, axis } = args;
@@ -51,7 +51,9 @@ function getAxisGenerator(args) {
51
51
  }
52
52
  return axisGenerator;
53
53
  }
54
- export const AxisY = ({ axises, width, height, scale }) => {
54
+ export const AxisY = (props) => {
55
+ const { axes, width, height: totalHeight, scale, split } = props;
56
+ const height = getAxisHeight({ split, boundsHeight: totalHeight });
55
57
  const ref = React.useRef(null);
56
58
  React.useEffect(() => {
57
59
  if (!ref.current) {
@@ -61,15 +63,22 @@ export const AxisY = ({ axises, width, height, scale }) => {
61
63
  svgElement.selectAll('*').remove();
62
64
  const axisSelection = svgElement
63
65
  .selectAll('axis')
64
- .data(axises)
66
+ .data(axes)
65
67
  .join('g')
66
68
  .attr('class', b())
67
- .style('transform', (_d, index) => (index === 0 ? '' : `translate(${width}px, 0)`));
69
+ .style('transform', (d) => {
70
+ var _a;
71
+ const top = ((_a = split.plots[d.plotIndex]) === null || _a === void 0 ? void 0 : _a.top) || 0;
72
+ if (d.position === 'left') {
73
+ return `translate(0, ${top}px)`;
74
+ }
75
+ return `translate(${width}px, 0)`;
76
+ });
68
77
  axisSelection.each((d, index, node) => {
69
78
  const seriesScale = scale[index];
70
79
  const axisItem = select(node[index]);
71
80
  const yAxisGenerator = getAxisGenerator({
72
- axisGenerator: index === 0
81
+ axisGenerator: d.position === 'left'
73
82
  ? axisLeft(seriesScale)
74
83
  : axisRight(seriesScale),
75
84
  preparedAxis: d,
@@ -136,13 +145,13 @@ export const AxisY = ({ axises, width, height, scale }) => {
136
145
  .attr('class', b('title'))
137
146
  .attr('text-anchor', 'middle')
138
147
  .attr('dy', (d) => -(d.title.margin + d.labels.margin + d.labels.width))
139
- .attr('dx', (_d, index) => (index === 0 ? -height / 2 : height / 2))
148
+ .attr('dx', (d) => (d.position === 'left' ? -height / 2 : height / 2))
140
149
  .attr('font-size', (d) => d.title.style.fontSize)
141
- .attr('transform', (_d, index) => (index === 0 ? 'rotate(-90)' : 'rotate(90)'))
150
+ .attr('transform', (d) => (d.position === 'left' ? 'rotate(-90)' : 'rotate(90)'))
142
151
  .text((d) => d.title.text)
143
152
  .each((_d, index, node) => {
144
153
  return setEllipsisForOverflowText(select(node[index]), height);
145
154
  });
146
- }, [axises, width, height, scale]);
155
+ }, [axes, width, height, scale, split]);
147
156
  return React.createElement("g", { ref: ref, className: b('container') });
148
157
  };
@@ -7,10 +7,12 @@ import { useAxisScales, useChartDimensions, useChartOptions, useSeries, useShape
7
7
  import { getYAxisWidth } from '../hooks/useChartDimensions/utils';
8
8
  import { getPreparedXAxis } from '../hooks/useChartOptions/x-axis';
9
9
  import { getPreparedYAxis } from '../hooks/useChartOptions/y-axis';
10
+ import { useSplit } from '../hooks/useSplit';
10
11
  import { getClosestPoints } from '../utils/get-closest-data';
11
12
  import { AxisX } from './AxisX';
12
13
  import { AxisY } from './AxisY';
13
14
  import { Legend } from './Legend';
15
+ import { PlotTitle } from './PlotTitle';
14
16
  import { Title } from './Title';
15
17
  import { Tooltip } from './Tooltip';
16
18
  import './styles.css';
@@ -27,7 +29,10 @@ export const Chart = (props) => {
27
29
  data,
28
30
  });
29
31
  const xAxis = React.useMemo(() => getPreparedXAxis({ xAxis: data.xAxis, width, series: data.series.data }), [data, width]);
30
- const yAxis = React.useMemo(() => getPreparedYAxis({ series: data.series.data, yAxis: data.yAxis }), [data, width]);
32
+ const yAxis = React.useMemo(() => getPreparedYAxis({
33
+ series: data.series.data,
34
+ yAxis: data.yAxis,
35
+ }), [data]);
31
36
  const { legendItems, legendConfig, preparedSeries, preparedSeriesOptions, preparedLegend, handleLegendItemClick, } = useSeries({
32
37
  chartWidth: width,
33
38
  chartHeight: height,
@@ -45,12 +50,14 @@ export const Chart = (props) => {
45
50
  preparedYAxis: yAxis,
46
51
  preparedSeries: preparedSeries,
47
52
  });
53
+ const preparedSplit = useSplit({ split: data.split, boundsHeight, chartWidth: width });
48
54
  const { xScale, yScale } = useAxisScales({
49
55
  boundsWidth,
50
56
  boundsHeight,
51
57
  series: preparedSeries,
52
58
  xAxis,
53
59
  yAxis,
60
+ split: preparedSplit,
54
61
  });
55
62
  const { shapes, shapesData } = useShapes({
56
63
  boundsWidth,
@@ -62,6 +69,7 @@ export const Chart = (props) => {
62
69
  xScale,
63
70
  yAxis,
64
71
  yScale,
72
+ split: preparedSplit,
65
73
  });
66
74
  const clickHandler = (_b = (_a = data.chart) === null || _a === void 0 ? void 0 : _a.events) === null || _b === void 0 ? void 0 : _b.click;
67
75
  React.useEffect(() => {
@@ -97,11 +105,14 @@ export const Chart = (props) => {
97
105
  return (React.createElement(React.Fragment, null,
98
106
  React.createElement("svg", { ref: svgRef, className: b(), width: width, height: height, onMouseMove: throttledHandleMouseMove, onMouseLeave: handleMouseLeave },
99
107
  title && React.createElement(Title, Object.assign({}, title, { chartWidth: width })),
108
+ React.createElement("g", { transform: `translate(0, ${boundsOffsetTop})` }, preparedSplit.plots.map((plot, index) => {
109
+ return React.createElement(PlotTitle, { key: `plot-${index}`, title: plot.title });
110
+ })),
100
111
  React.createElement("g", { width: boundsWidth, height: boundsHeight, transform: `translate(${[boundsOffsetLeft, boundsOffsetTop].join(',')})` },
101
112
  xScale && (yScale === null || yScale === void 0 ? void 0 : yScale.length) && (React.createElement(React.Fragment, null,
102
- React.createElement(AxisY, { axises: yAxis, width: boundsWidth, height: boundsHeight, scale: yScale }),
113
+ React.createElement(AxisY, { axes: yAxis, width: boundsWidth, height: boundsHeight, scale: yScale, split: preparedSplit }),
103
114
  React.createElement("g", { transform: `translate(0, ${boundsHeight})` },
104
- React.createElement(AxisX, { axis: xAxis, width: boundsWidth, height: boundsHeight, scale: xScale })))),
115
+ React.createElement(AxisX, { axis: xAxis, width: boundsWidth, height: boundsHeight, scale: xScale, split: preparedSplit })))),
105
116
  shapes),
106
117
  preparedLegend.enabled && (React.createElement(Legend, { chartSeries: preparedSeries, boundsWidth: boundsWidth, legend: preparedLegend, items: legendItems, config: legendConfig, onItemClick: handleLegendItemClick }))),
107
118
  React.createElement(Tooltip, { dispatcher: dispatcher, tooltip: tooltip, svgContainer: svgRef.current, xAxis: xAxis, yAxis: yAxis[0] })));
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { PreparedPlotTitle } from '../hooks/useSplit/types';
3
+ type Props = {
4
+ title?: PreparedPlotTitle;
5
+ };
6
+ export declare const PlotTitle: (props: Props) => React.JSX.Element | null;
7
+ export {};
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { block } from '../../../../utils/cn';
3
+ const b = block('d3-plot-title');
4
+ export const PlotTitle = (props) => {
5
+ const { title } = props;
6
+ if (!title) {
7
+ return null;
8
+ }
9
+ const { x, y, text, style, height } = title;
10
+ return (React.createElement("text", { className: b(), dx: x, dy: y, dominantBaseline: "middle", textAnchor: "middle", style: Object.assign({ lineHeight: `${height}px` }, style) },
11
+ React.createElement("tspan", null, text)));
12
+ };
@@ -11,7 +11,7 @@
11
11
  alignment-baseline: after-edge;
12
12
  }
13
13
 
14
- .chartkit-d3-axis .tick line {
14
+ .chartkit-d3-axis .tick line, .chartkit-d3-axis .tick path {
15
15
  stroke: var(--g-color-line-generic);
16
16
  }
17
17
 
@@ -79,6 +79,12 @@
79
79
  fill: var(--g-color-text-primary);
80
80
  }
81
81
 
82
+ .chartkit-d3-plot-title {
83
+ font-size: var(--g-text-subheader-3-font-size);
84
+ font-weight: var(--g-text-subheader-font-weight);
85
+ fill: var(--g-color-text-secondary);
86
+ }
87
+
82
88
  .chartkit-d3-tooltip[class] {
83
89
  --g-popup-border-width: 0;
84
90
  pointer-events: none;
@@ -7,3 +7,4 @@ export * from './useSeries/types';
7
7
  export * from './useShapes';
8
8
  export * from './useTooltip';
9
9
  export * from './useTooltip/types';
10
+ export * from './useSplit/types';
@@ -7,3 +7,4 @@ export * from './useSeries/types';
7
7
  export * from './useShapes';
8
8
  export * from './useTooltip';
9
9
  export * from './useTooltip/types';
10
+ export * from './useSplit/types';
@@ -1,7 +1,8 @@
1
1
  import type { ScaleBand, ScaleLinear, ScaleTime } from 'd3';
2
2
  import { ChartKitWidgetAxis, ChartKitWidgetSeries } from '../../../../../types';
3
3
  import type { PreparedAxis } from '../useChartOptions/types';
4
- import { PreparedSeries } from '../useSeries/types';
4
+ import type { PreparedSeries } from '../useSeries/types';
5
+ import type { PreparedSplit } from '../useSplit/types';
5
6
  export type ChartScale = ScaleLinear<number, number> | ScaleBand<string> | ScaleTime<number, number>;
6
7
  type Args = {
7
8
  boundsWidth: number;
@@ -9,6 +10,7 @@ type Args = {
9
10
  series: PreparedSeries[];
10
11
  xAxis: PreparedAxis;
11
12
  yAxis: PreparedAxis[];
13
+ split: PreparedSplit;
12
14
  };
13
15
  type ReturnValue = {
14
16
  xScale?: ChartScale;
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { extent, scaleBand, scaleLinear, scaleUtc } from 'd3';
3
3
  import get from 'lodash/get';
4
4
  import { DEFAULT_AXIS_TYPE } from '../../constants';
5
- import { getDataCategoryValue, getDomainDataXBySeries, getDomainDataYBySeries, getOnlyVisibleSeries, isAxisRelatedSeries, isSeriesWithCategoryValues, } from '../../utils';
5
+ import { CHART_SERIES_WITH_VOLUME_ON_Y_AXIS, getAxisHeight, getDataCategoryValue, getDefaultMaxXAxisValue, getDomainDataXBySeries, getDomainDataYBySeries, getOnlyVisibleSeries, isAxisRelatedSeries, isSeriesWithCategoryValues, } from '../../utils';
6
6
  const isNumericalArrayData = (data) => {
7
7
  return data.every((d) => typeof d === 'number' || d === null);
8
8
  };
@@ -28,9 +28,13 @@ export function createYScale(axis, series, boundsHeight) {
28
28
  const domain = getDomainDataYBySeries(series);
29
29
  const range = [boundsHeight, boundsHeight * axis.maxPadding];
30
30
  if (isNumericalArrayData(domain)) {
31
- const [domainYMin, yMax] = extent(domain);
31
+ const [domainYMin, domainMax] = extent(domain);
32
32
  const yMinValue = typeof yMin === 'number' ? yMin : domainYMin;
33
- return scaleLinear().domain([yMinValue, yMax]).range(range).nice();
33
+ let yMaxValue = domainMax;
34
+ if (series.some((s) => CHART_SERIES_WITH_VOLUME_ON_Y_AXIS.includes(s.type))) {
35
+ yMaxValue = Math.max(yMaxValue, 0);
36
+ }
37
+ return scaleLinear().domain([yMinValue, yMaxValue]).range(range).nice();
34
38
  }
35
39
  break;
36
40
  }
@@ -69,8 +73,11 @@ function calculateXAxisPadding(series) {
69
73
  switch (s.type) {
70
74
  case 'bar-y': {
71
75
  // Since labels can be located to the right of the bar, need to add an additional space
72
- const labelsMaxWidth = get(s, 'dataLabels.maxWidth', 0);
73
- result = Math.max(result, labelsMaxWidth);
76
+ const inside = get(s, 'dataLabels.inside');
77
+ if (!inside) {
78
+ const labelsMaxWidth = get(s, 'dataLabels.maxWidth', 0);
79
+ result = Math.max(result, labelsMaxWidth);
80
+ }
74
81
  break;
75
82
  }
76
83
  }
@@ -79,6 +86,7 @@ function calculateXAxisPadding(series) {
79
86
  }
80
87
  export function createXScale(axis, series, boundsWidth) {
81
88
  const xMin = get(axis, 'min');
89
+ const xMax = getDefaultMaxXAxisValue(series);
82
90
  const xType = get(axis, 'type', DEFAULT_AXIS_TYPE);
83
91
  const xCategories = get(axis, 'categories');
84
92
  const xTimestamps = get(axis, 'timestamps');
@@ -89,9 +97,10 @@ export function createXScale(axis, series, boundsWidth) {
89
97
  case 'linear': {
90
98
  const domain = getDomainDataXBySeries(series);
91
99
  if (isNumericalArrayData(domain)) {
92
- const [domainXMin, xMax] = extent(domain);
100
+ const [domainXMin, domainXMax] = extent(domain);
93
101
  const xMinValue = typeof xMin === 'number' ? xMin : domainXMin;
94
- return scaleLinear().domain([xMinValue, xMax]).range(xRange).nice();
102
+ const xMaxValue = typeof xMax === 'number' ? Math.max(xMax, domainXMax) : domainXMax;
103
+ return scaleLinear().domain([xMinValue, xMaxValue]).range(xRange).nice();
95
104
  }
96
105
  break;
97
106
  }
@@ -128,7 +137,7 @@ export function createXScale(axis, series, boundsWidth) {
128
137
  throw new Error('Failed to create xScale');
129
138
  }
130
139
  const createScales = (args) => {
131
- const { boundsWidth, boundsHeight, series, xAxis, yAxis } = args;
140
+ const { boundsWidth, boundsHeight, series, xAxis, yAxis, split } = args;
132
141
  let visibleSeries = getOnlyVisibleSeries(series);
133
142
  // Reassign to all series in case of all series unselected,
134
143
  // otherwise we will get an empty space without grid
@@ -141,7 +150,8 @@ const createScales = (args) => {
141
150
  return seriesAxisIndex === index;
142
151
  });
143
152
  const visibleAxisSeries = getOnlyVisibleSeries(axisSeries);
144
- return createYScale(axis, visibleAxisSeries.length ? visibleAxisSeries : axisSeries, boundsHeight);
153
+ const axisHeight = getAxisHeight({ boundsHeight, split });
154
+ return createYScale(axis, visibleAxisSeries.length ? visibleAxisSeries : axisSeries, axisHeight);
145
155
  }),
146
156
  };
147
157
  };
@@ -149,15 +159,21 @@ const createScales = (args) => {
149
159
  * Uses to create scales for axis related series
150
160
  */
151
161
  export const useAxisScales = (args) => {
152
- const { boundsWidth, boundsHeight, series, xAxis, yAxis } = args;
153
- const scales = React.useMemo(() => {
162
+ const { boundsWidth, boundsHeight, series, xAxis, yAxis, split } = args;
163
+ return React.useMemo(() => {
154
164
  let xScale;
155
165
  let yScale;
156
166
  const hasAxisRelatedSeries = series.some(isAxisRelatedSeries);
157
167
  if (hasAxisRelatedSeries) {
158
- ({ xScale, yScale } = createScales({ boundsWidth, boundsHeight, series, xAxis, yAxis }));
168
+ ({ xScale, yScale } = createScales({
169
+ boundsWidth,
170
+ boundsHeight,
171
+ series,
172
+ xAxis,
173
+ yAxis,
174
+ split,
175
+ }));
159
176
  }
160
177
  return { xScale, yScale };
161
- }, [boundsWidth, boundsHeight, series, xAxis, yAxis]);
162
- return scales;
178
+ }, [boundsWidth, boundsHeight, series, xAxis, yAxis, split]);
163
179
  };
@@ -16,6 +16,17 @@ export function getYAxisWidth(axis) {
16
16
  return result;
17
17
  }
18
18
  export function getWidthOccupiedByYAxis(args) {
19
- const { preparedAxis = [] } = args;
20
- return preparedAxis.reduce((sum, axis) => sum + getYAxisWidth(axis), 0);
19
+ const { preparedAxis } = args;
20
+ let leftAxisWidth = 0;
21
+ let rightAxisWidth = 0;
22
+ preparedAxis === null || preparedAxis === void 0 ? void 0 : preparedAxis.forEach((axis) => {
23
+ const axisWidth = getYAxisWidth(axis);
24
+ if (axis.position === 'right') {
25
+ rightAxisWidth = Math.max(rightAxisWidth, axisWidth);
26
+ }
27
+ else {
28
+ leftAxisWidth = Math.max(leftAxisWidth, axisWidth);
29
+ }
30
+ });
31
+ return leftAxisWidth + rightAxisWidth;
21
32
  }
@@ -28,6 +28,7 @@ export type PreparedAxis = Omit<ChartKitWidgetAxis, 'type' | 'labels'> & {
28
28
  pixelInterval?: number;
29
29
  };
30
30
  position: 'left' | 'right' | 'top' | 'bottom';
31
+ plotIndex: number;
31
32
  };
32
33
  export type PreparedTitle = ChartKitWidgetData['title'] & {
33
34
  height: number;
@@ -1,7 +1,7 @@
1
- import type { ChartKitWidgetAxis, ChartKitWidgetSeries } from '../../../../../types';
1
+ import type { ChartKitWidgetSeries, ChartKitWidgetXAxis } from '../../../../../types';
2
2
  import type { PreparedAxis } from './types';
3
3
  export declare const getPreparedXAxis: ({ xAxis, series, width, }: {
4
- xAxis?: ChartKitWidgetAxis | undefined;
4
+ xAxis?: import("../../../../../types").ChartKitWidgetAxis | undefined;
5
5
  series: ChartKitWidgetSeries[];
6
6
  width: number;
7
7
  }) => PreparedAxis;
@@ -1,6 +1,6 @@
1
1
  import get from 'lodash/get';
2
2
  import { DEFAULT_AXIS_LABEL_FONT_SIZE, axisLabelsDefaults, xAxisTitleDefaults, } from '../../constants';
3
- import { calculateCos, formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsSize, getMaxTickCount, getTicksCount, getXAxisItems, hasOverlappingLabels, } from '../../utils';
3
+ import { CHART_SERIES_WITH_VOLUME_ON_X_AXIS, calculateCos, formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsSize, getMaxTickCount, getTicksCount, getXAxisItems, hasOverlappingLabels, } from '../../utils';
4
4
  import { createXScale } from '../useAxisScales';
5
5
  function getLabelSettings({ axis, series, width, autoRotation = true, }) {
6
6
  const scale = createXScale(axis, series, width);
@@ -36,6 +36,17 @@ function getLabelSettings({ axis, series, width, autoRotation = true, }) {
36
36
  const maxHeight = rotation ? calculateCos(rotation) * axis.labels.maxWidth : labelsHeight;
37
37
  return { height: Math.min(maxHeight, labelsHeight), rotation };
38
38
  }
39
+ function getAxisMin(axis, series) {
40
+ const min = axis === null || axis === void 0 ? void 0 : axis.min;
41
+ if (typeof min === 'undefined' &&
42
+ (series === null || series === void 0 ? void 0 : series.some((s) => CHART_SERIES_WITH_VOLUME_ON_X_AXIS.includes(s.type)))) {
43
+ return series.reduce((minValue, s) => {
44
+ const minYValue = s.data.reduce((res, d) => Math.min(res, get(d, 'x', 0)), 0);
45
+ return Math.min(minValue, minYValue);
46
+ }, 0);
47
+ }
48
+ return min;
49
+ }
39
50
  export const getPreparedXAxis = ({ xAxis, series, width, }) => {
40
51
  var _a;
41
52
  const titleText = get(xAxis, 'title.text', '');
@@ -71,7 +82,7 @@ export const getPreparedXAxis = ({ xAxis, series, width, }) => {
71
82
  ? getHorisontalSvgTextHeight({ text: titleText, style: titleStyle })
72
83
  : 0,
73
84
  },
74
- min: get(xAxis, 'min'),
85
+ min: getAxisMin(xAxis, series),
75
86
  maxPadding: get(xAxis, 'maxPadding', 0.01),
76
87
  grid: {
77
88
  enabled: get(xAxis, 'grid.enabled', true),
@@ -80,6 +91,7 @@ export const getPreparedXAxis = ({ xAxis, series, width, }) => {
80
91
  pixelInterval: get(xAxis, 'ticks.pixelInterval'),
81
92
  },
82
93
  position: 'bottom',
94
+ plotIndex: 0,
83
95
  };
84
96
  const { height, rotation } = getLabelSettings({
85
97
  axis: preparedXAxis,
@@ -1,6 +1,6 @@
1
- import type { ChartKitWidgetData, ChartKitWidgetSeries } from '../../../../../types';
1
+ import type { ChartKitWidgetSeries, ChartKitWidgetYAxis } from '../../../../../types';
2
2
  import type { PreparedAxis } from './types';
3
3
  export declare const getPreparedYAxis: ({ series, yAxis, }: {
4
4
  series: ChartKitWidgetSeries[];
5
- yAxis: ChartKitWidgetData['yAxis'];
5
+ yAxis: ChartKitWidgetYAxis[] | undefined;
6
6
  }) => PreparedAxis[];