@gravity-ui/charts 1.34.2 → 1.34.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -95,8 +95,34 @@ export async function prepareXAxisData({ axis, boundsOffsetLeft, boundsOffsetRig
95
95
  const ticks = [];
96
96
  const getTextSize = getTextSizeFn({ style: axis.labels.style });
97
97
  const labelLineHeight = (await getTextSize('Tmp')).height;
98
- const values = getXAxisTickValues({ scale, axis, labelLineHeight, series });
99
- const tickStep = getMinSpaceBetween(values, (d) => Number(d.value));
98
+ let values = getXAxisTickValues({ scale, axis, labelLineHeight, series });
99
+ let tickStep = getMinSpaceBetween(values, (d) => Number(d.value));
100
+ if (axis.labels.enabled &&
101
+ axis.labels.rotation === 0 &&
102
+ !axis.labels.html &&
103
+ axis.type === 'datetime' &&
104
+ values.length > 1) {
105
+ let maxLabelWidth = 0;
106
+ for (let i = 0; i < values.length; i++) {
107
+ const label = formatAxisTickLabel({
108
+ value: values[i].value,
109
+ axis,
110
+ step: tickStep,
111
+ });
112
+ const size = await getTextSize(label);
113
+ maxLabelWidth = Math.max(maxLabelWidth, size.width);
114
+ }
115
+ const currentSpacing = Math.abs(values[0].x - values[1].x) - axis.labels.padding * 2;
116
+ if (maxLabelWidth > currentSpacing) {
117
+ values = getXAxisTickValues({
118
+ scale,
119
+ axis,
120
+ labelLineHeight: maxLabelWidth,
121
+ series,
122
+ });
123
+ tickStep = getMinSpaceBetween(values, (d) => Number(d.value));
124
+ }
125
+ }
100
126
  const labelMaxWidth = values.length > 1
101
127
  ? Math.abs(values[0].x - values[1].x) - axis.labels.padding * 2
102
128
  : axisWidth;
@@ -37,7 +37,7 @@ async function setLabelSettings({ axis, seriesData, width, axisLabels, }) {
37
37
  }
38
38
  return false;
39
39
  };
40
- const autoRotation = (_a = axisLabels === null || axisLabels === void 0 ? void 0 : axisLabels.autoRotation) !== null && _a !== void 0 ? _a : true;
40
+ const autoRotation = (_a = axisLabels === null || axisLabels === void 0 ? void 0 : axisLabels.autoRotation) !== null && _a !== void 0 ? _a : axis.type !== 'datetime';
41
41
  const overlapping = axis.labels.html ? false : await hasOverlappingLabels();
42
42
  const defaultRotation = overlapping && autoRotation ? -45 : 0;
43
43
  const rotation = axis.labels.html ? 0 : ((_b = axisLabels === null || axisLabels === void 0 ? void 0 : axisLabels.rotation) !== null && _b !== void 0 ? _b : defaultRotation);
@@ -22,7 +22,7 @@ async function prepareDataLabels(series) {
22
22
  const style = Object.assign({}, DEFAULT_DATALABELS_STYLE, (_a = series.dataLabels) === null || _a === void 0 ? void 0 : _a.style);
23
23
  const html = get(series, 'dataLabels.html', false);
24
24
  const labels = enabled
25
- ? series.data.map((d) => getFormattedValue(Object.assign({ value: d.label || d.x }, series.dataLabels)))
25
+ ? series.data.map((d) => { var _a; return getFormattedValue(Object.assign({ value: (_a = d.label) !== null && _a !== void 0 ? _a : d.x }, series.dataLabels)); })
26
26
  : [];
27
27
  const { maxHeight = 0, maxWidth = 0 } = await getLabelsSize({
28
28
  labels,
@@ -28,6 +28,7 @@ function getXValues(series, xAxis, xScale) {
28
28
  return Array.from(xValues);
29
29
  }
30
30
  async function prepareDataLabels({ series, points, xMax, yAxisTop, }) {
31
+ var _a;
31
32
  const svgLabels = [];
32
33
  const htmlLabels = [];
33
34
  const getTextSize = getTextSizeFn({ style: series.dataLabels.style });
@@ -36,7 +37,7 @@ async function prepareDataLabels({ series, points, xMax, yAxisTop, }) {
36
37
  if (point.y === null) {
37
38
  continue;
38
39
  }
39
- const text = getFormattedValue(Object.assign({ value: point.data.label || point.data.y }, series.dataLabels));
40
+ const text = getFormattedValue(Object.assign({ value: (_a = point.data.label) !== null && _a !== void 0 ? _a : point.data.y }, series.dataLabels));
40
41
  if (series.dataLabels.html) {
41
42
  const size = await getLabelsSize({
42
43
  labels: [text],
@@ -6,10 +6,11 @@ import { getSeriesStackId } from '../../useSeries/utils';
6
6
  import { getBarXLayout } from '../../utils/bar-x';
7
7
  const isSeriesDataValid = (d) => d.y !== null;
8
8
  async function getLabelData(d) {
9
+ var _a;
9
10
  if (!d.series.dataLabels.enabled) {
10
11
  return undefined;
11
12
  }
12
- const text = getFormattedValue(Object.assign({ value: d.data.label || d.data.y }, d.series.dataLabels));
13
+ const text = getFormattedValue(Object.assign({ value: (_a = d.data.label) !== null && _a !== void 0 ? _a : d.data.y }, d.series.dataLabels));
13
14
  const style = d.series.dataLabels.style;
14
15
  const html = d.series.dataLabels.html;
15
16
  const { maxHeight: height, maxWidth: width } = await getLabelsSize({
@@ -4,7 +4,7 @@ import { filterOverlappingLabels, getHtmlLabelConstraintedPosition, getLabelsSiz
4
4
  import { getFormattedValue } from '../../../utils/chart/format';
5
5
  import { getBarYLayout, groupBarYDataByYValue } from '../../utils';
6
6
  export async function prepareBarYData(args) {
7
- var _a;
7
+ var _a, _b;
8
8
  const { boundsHeight, boundsWidth, series, seriesOptions, xAxis, yAxis, xScale, yScale: [yScale], } = args;
9
9
  const stackGap = seriesOptions['bar-y'].stackGap;
10
10
  const xLinearScale = xScale;
@@ -139,7 +139,7 @@ export async function prepareBarYData(args) {
139
139
  const dataLabels = prepared.series.dataLabels;
140
140
  if (dataLabels.enabled) {
141
141
  const data = prepared.data;
142
- const content = getFormattedValue(Object.assign({ value: data.label || data.x }, dataLabels));
142
+ const content = getFormattedValue(Object.assign({ value: (_a = data.label) !== null && _a !== void 0 ? _a : data.x }, dataLabels));
143
143
  const y = prepared.y + prepared.height / 2;
144
144
  if (dataLabels.html) {
145
145
  const { maxHeight: height, maxWidth: width } = await getLabelsSize({
@@ -195,7 +195,7 @@ export async function prepareBarYData(args) {
195
195
  }
196
196
  }
197
197
  }
198
- const allowOverlap = (_a = result[0]) === null || _a === void 0 ? void 0 : _a.series.dataLabels.allowOverlap;
198
+ const allowOverlap = (_b = result[0]) === null || _b === void 0 ? void 0 : _b.series.dataLabels.allowOverlap;
199
199
  if (labels.length && !allowOverlap) {
200
200
  labels = filterOverlappingLabels(labels);
201
201
  }
@@ -2,7 +2,8 @@ import { getLabelsSize, getTextSizeFn } from '../../../utils';
2
2
  import { getFormattedValue } from '../../../utils/chart/format';
3
3
  import { getXValue, getYValue } from '../utils';
4
4
  async function getHtmlLabel(point, series, xMax) {
5
- const content = String(point.data.label || point.data.y);
5
+ var _a;
6
+ const content = String((_a = point.data.label) !== null && _a !== void 0 ? _a : point.data.y);
6
7
  const size = await getLabelsSize({ labels: [content], html: true });
7
8
  return {
8
9
  x: Math.min(xMax - size.maxWidth, Math.max(0, point.x)),
@@ -13,7 +14,7 @@ async function getHtmlLabel(point, series, xMax) {
13
14
  };
14
15
  }
15
16
  export const prepareLineData = async (args) => {
16
- var _a, _b, _c;
17
+ var _a, _b, _c, _d;
17
18
  const { series, xAxis, yAxis, xScale, yScale, split, isOutsideBounds, isRangeSlider } = args;
18
19
  const [_xMin, xRangeMax] = xScale.range();
19
20
  const xMax = xRangeMax;
@@ -60,7 +61,7 @@ export const prepareLineData = async (args) => {
60
61
  for (let index = 0; index < points.length; index++) {
61
62
  const point = points[index];
62
63
  if (point.y !== null && point.x !== null) {
63
- const text = getFormattedValue(Object.assign({ value: point.data.label || point.data.y }, s.dataLabels));
64
+ const text = getFormattedValue(Object.assign({ value: (_b = point.data.label) !== null && _b !== void 0 ? _b : point.data.y }, s.dataLabels));
64
65
  const labelSize = await getTextSize(text);
65
66
  const style = s.dataLabels.style;
66
67
  const y = Math.max(yAxisTop, point.y - s.dataLabels.padding - labelSize.height);
@@ -105,11 +106,11 @@ export const prepareLineData = async (args) => {
105
106
  id: s.id,
106
107
  htmlElements,
107
108
  color: s.color,
108
- lineWidth: (_b = (isRangeSlider ? s.rangeSlider.lineWidth : undefined)) !== null && _b !== void 0 ? _b : s.lineWidth,
109
+ lineWidth: (_c = (isRangeSlider ? s.rangeSlider.lineWidth : undefined)) !== null && _c !== void 0 ? _c : s.lineWidth,
109
110
  dashStyle: s.dashStyle,
110
111
  linecap: s.linecap,
111
112
  linejoin: s.linejoin,
112
- opacity: (_c = (isRangeSlider ? s.rangeSlider.opacity : undefined)) !== null && _c !== void 0 ? _c : s.opacity,
113
+ opacity: (_d = (isRangeSlider ? s.rangeSlider.opacity : undefined)) !== null && _d !== void 0 ? _d : s.opacity,
113
114
  };
114
115
  acc.push(result);
115
116
  }
@@ -82,6 +82,7 @@ export function preparePieData(args) {
82
82
  return data;
83
83
  };
84
84
  const getLabels = async ({ series }) => {
85
+ var _a;
85
86
  const { dataLabels } = series[0];
86
87
  if (!dataLabels.enabled) {
87
88
  return {};
@@ -90,7 +91,7 @@ export function preparePieData(args) {
90
91
  const acc = {};
91
92
  for (let i = 0; i < series.length; i++) {
92
93
  const d = series[i];
93
- const text = getFormattedValue(Object.assign({ value: d.data.label || d.data.value }, d.dataLabels));
94
+ const text = getFormattedValue(Object.assign({ value: (_a = d.data.label) !== null && _a !== void 0 ? _a : d.data.value }, d.dataLabels));
94
95
  let labelWidth = 0;
95
96
  let labelHeight = 0;
96
97
  if (dataLabels.html) {
@@ -19,11 +19,14 @@ export interface ChartAxisLabels {
19
19
  dateFormat?: string;
20
20
  numberFormat?: FormatNumberOptions;
21
21
  style?: Partial<BaseTextStyle>;
22
- /** For horizontal axes, enable label rotation to prevent overlapping labels.
22
+ /**
23
+ * For horizontal axes, enable label rotation to prevent overlapping labels.
23
24
  * If there is enough space, labels are not rotated.
24
25
  * As the chart gets narrower, it will start rotating the labels -45 degrees.
25
26
  *
26
27
  * Does not apply to html labels.
28
+ *
29
+ * @default true for all axis types except `datetime` (defaults to false)
27
30
  */
28
31
  autoRotation?: boolean;
29
32
  /** Rotation of the labels in degrees.
@@ -95,8 +95,34 @@ export async function prepareXAxisData({ axis, boundsOffsetLeft, boundsOffsetRig
95
95
  const ticks = [];
96
96
  const getTextSize = getTextSizeFn({ style: axis.labels.style });
97
97
  const labelLineHeight = (await getTextSize('Tmp')).height;
98
- const values = getXAxisTickValues({ scale, axis, labelLineHeight, series });
99
- const tickStep = getMinSpaceBetween(values, (d) => Number(d.value));
98
+ let values = getXAxisTickValues({ scale, axis, labelLineHeight, series });
99
+ let tickStep = getMinSpaceBetween(values, (d) => Number(d.value));
100
+ if (axis.labels.enabled &&
101
+ axis.labels.rotation === 0 &&
102
+ !axis.labels.html &&
103
+ axis.type === 'datetime' &&
104
+ values.length > 1) {
105
+ let maxLabelWidth = 0;
106
+ for (let i = 0; i < values.length; i++) {
107
+ const label = formatAxisTickLabel({
108
+ value: values[i].value,
109
+ axis,
110
+ step: tickStep,
111
+ });
112
+ const size = await getTextSize(label);
113
+ maxLabelWidth = Math.max(maxLabelWidth, size.width);
114
+ }
115
+ const currentSpacing = Math.abs(values[0].x - values[1].x) - axis.labels.padding * 2;
116
+ if (maxLabelWidth > currentSpacing) {
117
+ values = getXAxisTickValues({
118
+ scale,
119
+ axis,
120
+ labelLineHeight: maxLabelWidth,
121
+ series,
122
+ });
123
+ tickStep = getMinSpaceBetween(values, (d) => Number(d.value));
124
+ }
125
+ }
100
126
  const labelMaxWidth = values.length > 1
101
127
  ? Math.abs(values[0].x - values[1].x) - axis.labels.padding * 2
102
128
  : axisWidth;
@@ -37,7 +37,7 @@ async function setLabelSettings({ axis, seriesData, width, axisLabels, }) {
37
37
  }
38
38
  return false;
39
39
  };
40
- const autoRotation = (_a = axisLabels === null || axisLabels === void 0 ? void 0 : axisLabels.autoRotation) !== null && _a !== void 0 ? _a : true;
40
+ const autoRotation = (_a = axisLabels === null || axisLabels === void 0 ? void 0 : axisLabels.autoRotation) !== null && _a !== void 0 ? _a : axis.type !== 'datetime';
41
41
  const overlapping = axis.labels.html ? false : await hasOverlappingLabels();
42
42
  const defaultRotation = overlapping && autoRotation ? -45 : 0;
43
43
  const rotation = axis.labels.html ? 0 : ((_b = axisLabels === null || axisLabels === void 0 ? void 0 : axisLabels.rotation) !== null && _b !== void 0 ? _b : defaultRotation);
@@ -22,7 +22,7 @@ async function prepareDataLabels(series) {
22
22
  const style = Object.assign({}, DEFAULT_DATALABELS_STYLE, (_a = series.dataLabels) === null || _a === void 0 ? void 0 : _a.style);
23
23
  const html = get(series, 'dataLabels.html', false);
24
24
  const labels = enabled
25
- ? series.data.map((d) => getFormattedValue(Object.assign({ value: d.label || d.x }, series.dataLabels)))
25
+ ? series.data.map((d) => { var _a; return getFormattedValue(Object.assign({ value: (_a = d.label) !== null && _a !== void 0 ? _a : d.x }, series.dataLabels)); })
26
26
  : [];
27
27
  const { maxHeight = 0, maxWidth = 0 } = await getLabelsSize({
28
28
  labels,
@@ -28,6 +28,7 @@ function getXValues(series, xAxis, xScale) {
28
28
  return Array.from(xValues);
29
29
  }
30
30
  async function prepareDataLabels({ series, points, xMax, yAxisTop, }) {
31
+ var _a;
31
32
  const svgLabels = [];
32
33
  const htmlLabels = [];
33
34
  const getTextSize = getTextSizeFn({ style: series.dataLabels.style });
@@ -36,7 +37,7 @@ async function prepareDataLabels({ series, points, xMax, yAxisTop, }) {
36
37
  if (point.y === null) {
37
38
  continue;
38
39
  }
39
- const text = getFormattedValue(Object.assign({ value: point.data.label || point.data.y }, series.dataLabels));
40
+ const text = getFormattedValue(Object.assign({ value: (_a = point.data.label) !== null && _a !== void 0 ? _a : point.data.y }, series.dataLabels));
40
41
  if (series.dataLabels.html) {
41
42
  const size = await getLabelsSize({
42
43
  labels: [text],
@@ -6,10 +6,11 @@ import { getSeriesStackId } from '../../useSeries/utils';
6
6
  import { getBarXLayout } from '../../utils/bar-x';
7
7
  const isSeriesDataValid = (d) => d.y !== null;
8
8
  async function getLabelData(d) {
9
+ var _a;
9
10
  if (!d.series.dataLabels.enabled) {
10
11
  return undefined;
11
12
  }
12
- const text = getFormattedValue(Object.assign({ value: d.data.label || d.data.y }, d.series.dataLabels));
13
+ const text = getFormattedValue(Object.assign({ value: (_a = d.data.label) !== null && _a !== void 0 ? _a : d.data.y }, d.series.dataLabels));
13
14
  const style = d.series.dataLabels.style;
14
15
  const html = d.series.dataLabels.html;
15
16
  const { maxHeight: height, maxWidth: width } = await getLabelsSize({
@@ -4,7 +4,7 @@ import { filterOverlappingLabels, getHtmlLabelConstraintedPosition, getLabelsSiz
4
4
  import { getFormattedValue } from '../../../utils/chart/format';
5
5
  import { getBarYLayout, groupBarYDataByYValue } from '../../utils';
6
6
  export async function prepareBarYData(args) {
7
- var _a;
7
+ var _a, _b;
8
8
  const { boundsHeight, boundsWidth, series, seriesOptions, xAxis, yAxis, xScale, yScale: [yScale], } = args;
9
9
  const stackGap = seriesOptions['bar-y'].stackGap;
10
10
  const xLinearScale = xScale;
@@ -139,7 +139,7 @@ export async function prepareBarYData(args) {
139
139
  const dataLabels = prepared.series.dataLabels;
140
140
  if (dataLabels.enabled) {
141
141
  const data = prepared.data;
142
- const content = getFormattedValue(Object.assign({ value: data.label || data.x }, dataLabels));
142
+ const content = getFormattedValue(Object.assign({ value: (_a = data.label) !== null && _a !== void 0 ? _a : data.x }, dataLabels));
143
143
  const y = prepared.y + prepared.height / 2;
144
144
  if (dataLabels.html) {
145
145
  const { maxHeight: height, maxWidth: width } = await getLabelsSize({
@@ -195,7 +195,7 @@ export async function prepareBarYData(args) {
195
195
  }
196
196
  }
197
197
  }
198
- const allowOverlap = (_a = result[0]) === null || _a === void 0 ? void 0 : _a.series.dataLabels.allowOverlap;
198
+ const allowOverlap = (_b = result[0]) === null || _b === void 0 ? void 0 : _b.series.dataLabels.allowOverlap;
199
199
  if (labels.length && !allowOverlap) {
200
200
  labels = filterOverlappingLabels(labels);
201
201
  }
@@ -2,7 +2,8 @@ import { getLabelsSize, getTextSizeFn } from '../../../utils';
2
2
  import { getFormattedValue } from '../../../utils/chart/format';
3
3
  import { getXValue, getYValue } from '../utils';
4
4
  async function getHtmlLabel(point, series, xMax) {
5
- const content = String(point.data.label || point.data.y);
5
+ var _a;
6
+ const content = String((_a = point.data.label) !== null && _a !== void 0 ? _a : point.data.y);
6
7
  const size = await getLabelsSize({ labels: [content], html: true });
7
8
  return {
8
9
  x: Math.min(xMax - size.maxWidth, Math.max(0, point.x)),
@@ -13,7 +14,7 @@ async function getHtmlLabel(point, series, xMax) {
13
14
  };
14
15
  }
15
16
  export const prepareLineData = async (args) => {
16
- var _a, _b, _c;
17
+ var _a, _b, _c, _d;
17
18
  const { series, xAxis, yAxis, xScale, yScale, split, isOutsideBounds, isRangeSlider } = args;
18
19
  const [_xMin, xRangeMax] = xScale.range();
19
20
  const xMax = xRangeMax;
@@ -60,7 +61,7 @@ export const prepareLineData = async (args) => {
60
61
  for (let index = 0; index < points.length; index++) {
61
62
  const point = points[index];
62
63
  if (point.y !== null && point.x !== null) {
63
- const text = getFormattedValue(Object.assign({ value: point.data.label || point.data.y }, s.dataLabels));
64
+ const text = getFormattedValue(Object.assign({ value: (_b = point.data.label) !== null && _b !== void 0 ? _b : point.data.y }, s.dataLabels));
64
65
  const labelSize = await getTextSize(text);
65
66
  const style = s.dataLabels.style;
66
67
  const y = Math.max(yAxisTop, point.y - s.dataLabels.padding - labelSize.height);
@@ -105,11 +106,11 @@ export const prepareLineData = async (args) => {
105
106
  id: s.id,
106
107
  htmlElements,
107
108
  color: s.color,
108
- lineWidth: (_b = (isRangeSlider ? s.rangeSlider.lineWidth : undefined)) !== null && _b !== void 0 ? _b : s.lineWidth,
109
+ lineWidth: (_c = (isRangeSlider ? s.rangeSlider.lineWidth : undefined)) !== null && _c !== void 0 ? _c : s.lineWidth,
109
110
  dashStyle: s.dashStyle,
110
111
  linecap: s.linecap,
111
112
  linejoin: s.linejoin,
112
- opacity: (_c = (isRangeSlider ? s.rangeSlider.opacity : undefined)) !== null && _c !== void 0 ? _c : s.opacity,
113
+ opacity: (_d = (isRangeSlider ? s.rangeSlider.opacity : undefined)) !== null && _d !== void 0 ? _d : s.opacity,
113
114
  };
114
115
  acc.push(result);
115
116
  }
@@ -82,6 +82,7 @@ export function preparePieData(args) {
82
82
  return data;
83
83
  };
84
84
  const getLabels = async ({ series }) => {
85
+ var _a;
85
86
  const { dataLabels } = series[0];
86
87
  if (!dataLabels.enabled) {
87
88
  return {};
@@ -90,7 +91,7 @@ export function preparePieData(args) {
90
91
  const acc = {};
91
92
  for (let i = 0; i < series.length; i++) {
92
93
  const d = series[i];
93
- const text = getFormattedValue(Object.assign({ value: d.data.label || d.data.value }, d.dataLabels));
94
+ const text = getFormattedValue(Object.assign({ value: (_a = d.data.label) !== null && _a !== void 0 ? _a : d.data.value }, d.dataLabels));
94
95
  let labelWidth = 0;
95
96
  let labelHeight = 0;
96
97
  if (dataLabels.html) {
@@ -19,11 +19,14 @@ export interface ChartAxisLabels {
19
19
  dateFormat?: string;
20
20
  numberFormat?: FormatNumberOptions;
21
21
  style?: Partial<BaseTextStyle>;
22
- /** For horizontal axes, enable label rotation to prevent overlapping labels.
22
+ /**
23
+ * For horizontal axes, enable label rotation to prevent overlapping labels.
23
24
  * If there is enough space, labels are not rotated.
24
25
  * As the chart gets narrower, it will start rotating the labels -45 degrees.
25
26
  *
26
27
  * Does not apply to html labels.
28
+ *
29
+ * @default true for all axis types except `datetime` (defaults to false)
27
30
  */
28
31
  autoRotation?: boolean;
29
32
  /** Rotation of the labels in degrees.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/charts",
3
- "version": "1.34.2",
3
+ "version": "1.34.4",
4
4
  "description": "A flexible JavaScript library for data visualization and chart rendering using React",
5
5
  "license": "MIT",
6
6
  "main": "dist/cjs/index.js",