@gravity-ui/charts 1.6.6 → 1.7.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 (37) hide show
  1. package/dist/cjs/components/ChartInner/useChartInnerProps.js +2 -1
  2. package/dist/cjs/hooks/useChartOptions/index.js +4 -2
  3. package/dist/cjs/hooks/useChartOptions/types.d.ts +1 -0
  4. package/dist/cjs/hooks/useSeries/index.d.ts +1 -0
  5. package/dist/cjs/hooks/useSeries/index.js +3 -3
  6. package/dist/cjs/hooks/useSeries/prepare-pie.d.ts +1 -0
  7. package/dist/cjs/hooks/useSeries/prepare-pie.js +3 -3
  8. package/dist/cjs/hooks/useSeries/prepare-radar.d.ts +1 -0
  9. package/dist/cjs/hooks/useSeries/prepare-radar.js +3 -3
  10. package/dist/cjs/hooks/useSeries/prepare-waterfall.d.ts +1 -0
  11. package/dist/cjs/hooks/useSeries/prepare-waterfall.js +3 -3
  12. package/dist/cjs/hooks/useSeries/prepareSeries.d.ts +1 -0
  13. package/dist/cjs/hooks/useSeries/prepareSeries.js +9 -2
  14. package/dist/cjs/hooks/useShapes/pie/prepare-data.js +50 -24
  15. package/dist/cjs/types/index.d.ts +6 -0
  16. package/dist/cjs/utils/chart/axis-generators/bottom.js +1 -1
  17. package/dist/cjs/utils/chart/text.js +29 -7
  18. package/dist/cjs/utils/chart-ui/pie-center-text.js +5 -2
  19. package/dist/esm/components/ChartInner/useChartInnerProps.js +2 -1
  20. package/dist/esm/hooks/useChartOptions/index.js +4 -2
  21. package/dist/esm/hooks/useChartOptions/types.d.ts +1 -0
  22. package/dist/esm/hooks/useSeries/index.d.ts +1 -0
  23. package/dist/esm/hooks/useSeries/index.js +3 -3
  24. package/dist/esm/hooks/useSeries/prepare-pie.d.ts +1 -0
  25. package/dist/esm/hooks/useSeries/prepare-pie.js +3 -3
  26. package/dist/esm/hooks/useSeries/prepare-radar.d.ts +1 -0
  27. package/dist/esm/hooks/useSeries/prepare-radar.js +3 -3
  28. package/dist/esm/hooks/useSeries/prepare-waterfall.d.ts +1 -0
  29. package/dist/esm/hooks/useSeries/prepare-waterfall.js +3 -3
  30. package/dist/esm/hooks/useSeries/prepareSeries.d.ts +1 -0
  31. package/dist/esm/hooks/useSeries/prepareSeries.js +9 -2
  32. package/dist/esm/hooks/useShapes/pie/prepare-data.js +50 -24
  33. package/dist/esm/types/index.d.ts +6 -0
  34. package/dist/esm/utils/chart/axis-generators/bottom.js +1 -1
  35. package/dist/esm/utils/chart/text.js +29 -7
  36. package/dist/esm/utils/chart-ui/pie-center-text.js +5 -2
  37. package/package.json +1 -1
@@ -8,7 +8,7 @@ export function useChartInnerProps(props) {
8
8
  const { width, height, data, dispatcher, htmlLayout, svgContainer } = props;
9
9
  const prevWidth = usePrevious(width);
10
10
  const prevHeight = usePrevious(height);
11
- const { chart, title, tooltip } = useChartOptions({ data });
11
+ const { chart, title, tooltip, colors } = useChartOptions({ data });
12
12
  const xAxis = React.useMemo(() => getPreparedXAxis({ xAxis: data.xAxis, width, series: data.series.data }), [data, width]);
13
13
  const yAxis = React.useMemo(() => getPreparedYAxis({
14
14
  series: data.series.data,
@@ -22,6 +22,7 @@ export function useChartInnerProps(props) {
22
22
  series: data.series,
23
23
  legend: data.legend,
24
24
  preparedYAxis: yAxis,
25
+ colors,
25
26
  });
26
27
  const { boundsWidth, boundsHeight } = useChartDimensions({
27
28
  width,
@@ -1,9 +1,10 @@
1
1
  import React from 'react';
2
+ import { DEFAULT_PALETTE } from '../../constants';
2
3
  import { getPreparedChart } from './chart';
3
4
  import { getPreparedTitle } from './title';
4
5
  import { getPreparedTooltip } from './tooltip';
5
6
  export const useChartOptions = (args) => {
6
- const { data: { chart, title, tooltip }, } = args;
7
+ const { data: { chart, title, tooltip, colors }, } = args;
7
8
  const options = React.useMemo(() => {
8
9
  const preparedTitle = getPreparedTitle({ title });
9
10
  const preparedTooltip = getPreparedTooltip({ tooltip });
@@ -15,7 +16,8 @@ export const useChartOptions = (args) => {
15
16
  chart: preparedChart,
16
17
  title: preparedTitle,
17
18
  tooltip: preparedTooltip,
19
+ colors: colors !== null && colors !== void 0 ? colors : DEFAULT_PALETTE,
18
20
  };
19
- }, [chart, title, tooltip]);
21
+ }, [chart, colors, title, tooltip]);
20
22
  return options;
21
23
  };
@@ -56,5 +56,6 @@ export type ChartOptions = {
56
56
  chart: PreparedChart;
57
57
  tooltip: PreparedTooltip;
58
58
  title?: PreparedTitle;
59
+ colors: string[];
59
60
  };
60
61
  export {};
@@ -8,6 +8,7 @@ type Args = {
8
8
  legend: ChartData['legend'];
9
9
  series: ChartData['series'];
10
10
  preparedYAxis: PreparedAxis[];
11
+ colors: string[];
11
12
  };
12
13
  export declare const useSeries: (args: Args) => {
13
14
  legendItems: import("./types").LegendItem[][];
@@ -1,17 +1,16 @@
1
1
  import React from 'react';
2
2
  import { group, scaleOrdinal } from 'd3';
3
- import { DEFAULT_PALETTE } from '../../constants';
4
3
  import { getSeriesNames } from '../../utils';
5
4
  import { getLegendComponents, getPreparedLegend } from './prepare-legend';
6
5
  import { getPreparedOptions } from './prepare-options';
7
6
  import { prepareSeries } from './prepareSeries';
8
7
  import { getActiveLegendItems, getAllLegendItems } from './utils';
9
8
  export const useSeries = (args) => {
10
- const { chartWidth, chartHeight, chartMargin, legend, preparedYAxis, series: { data: series, options: seriesOptions }, } = args;
9
+ const { chartWidth, chartHeight, chartMargin, legend, preparedYAxis, series: { data: series, options: seriesOptions }, colors, } = args;
11
10
  const preparedLegend = React.useMemo(() => getPreparedLegend({ legend, series }), [legend, series]);
12
11
  const preparedSeries = React.useMemo(() => {
13
12
  const seriesNames = getSeriesNames(series);
14
- const colorScale = scaleOrdinal(seriesNames, DEFAULT_PALETTE);
13
+ const colorScale = scaleOrdinal(seriesNames, colors);
15
14
  const groupedSeries = group(series, (item) => item.type);
16
15
  return Array.from(groupedSeries).reduce((acc, [seriesType, seriesList]) => {
17
16
  acc.push(...prepareSeries({
@@ -20,6 +19,7 @@ export const useSeries = (args) => {
20
19
  seriesOptions,
21
20
  legend: preparedLegend,
22
21
  colorScale,
22
+ colors,
23
23
  }));
24
24
  return acc;
25
25
  }, []);
@@ -4,6 +4,7 @@ type PreparePieSeriesArgs = {
4
4
  series: PieSeries;
5
5
  seriesOptions?: ChartSeriesOptions;
6
6
  legend: PreparedLegend;
7
+ colors: string[];
7
8
  };
8
9
  export declare function preparePieSeries(args: PreparePieSeriesArgs): PreparedSeries[];
9
10
  export {};
@@ -1,13 +1,13 @@
1
1
  import { scaleOrdinal } from 'd3';
2
2
  import get from 'lodash/get';
3
- import { DEFAULT_DATALABELS_STYLE, DEFAULT_PALETTE } from '../../constants';
3
+ import { DEFAULT_DATALABELS_STYLE } from '../../constants';
4
4
  import { getUniqId } from '../../utils';
5
5
  import { DEFAULT_DATALABELS_PADDING } from './constants';
6
6
  import { prepareLegendSymbol } from './utils';
7
7
  export function preparePieSeries(args) {
8
- const { series, seriesOptions, legend } = args;
8
+ const { series, seriesOptions, legend, colors } = args;
9
9
  const dataNames = series.data.map((d) => d.name);
10
- const colorScale = scaleOrdinal(dataNames, DEFAULT_PALETTE);
10
+ const colorScale = scaleOrdinal(dataNames, colors);
11
11
  const stackId = getUniqId();
12
12
  const seriesHoverState = get(seriesOptions, 'pie.states.hover');
13
13
  const preparedSeries = series.data.map((dataItem, i) => {
@@ -4,6 +4,7 @@ type PrepareRadarSeriesArgs = {
4
4
  series: RadarSeries[];
5
5
  seriesOptions?: ChartSeriesOptions;
6
6
  legend: PreparedLegend;
7
+ colors: string[];
7
8
  };
8
9
  export declare const DEFAULT_MARKER: {
9
10
  enabled: boolean;
@@ -1,7 +1,7 @@
1
1
  import { scaleOrdinal } from 'd3';
2
2
  import get from 'lodash/get';
3
3
  import merge from 'lodash/merge';
4
- import { DEFAULT_DATALABELS_STYLE, DEFAULT_PALETTE } from '../../constants';
4
+ import { DEFAULT_DATALABELS_STYLE } from '../../constants';
5
5
  import { getUniqId } from '../../utils';
6
6
  import { DEFAULT_DATALABELS_PADDING, DEFAULT_HALO_OPTIONS, DEFAULT_POINT_MARKER_OPTIONS, } from './constants';
7
7
  import { prepareLegendSymbol } from './utils';
@@ -26,8 +26,8 @@ function prepareMarker(series, seriesOptions) {
26
26
  }
27
27
  export function prepareRadarSeries(args) {
28
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);
29
+ const { series: radarSeries, seriesOptions, legend, colors } = args;
30
+ const colorScale = scaleOrdinal(radarSeries.map((s, index) => { var _a; return (_a = s.name) !== null && _a !== void 0 ? _a : `Series ${index + 1}`; }), colors);
31
31
  const categories = (_b = (_a = radarSeries.find((s) => s.categories)) === null || _a === void 0 ? void 0 : _a.categories) !== null && _b !== void 0 ? _b : [];
32
32
  return radarSeries.map((series, index) => {
33
33
  var _a, _b, _c, _d, _e, _f;
@@ -5,6 +5,7 @@ type PrepareWaterfallSeriesArgs = {
5
5
  colorScale: ScaleOrdinal<string, string>;
6
6
  series: WaterfallSeries[];
7
7
  legend: PreparedLegend;
8
+ colors: string[];
8
9
  };
9
10
  export declare function prepareWaterfallSeries(args: PrepareWaterfallSeriesArgs): PreparedSeries[];
10
11
  export {};
@@ -1,12 +1,12 @@
1
1
  import get from 'lodash/get';
2
- import { DEFAULT_DATALABELS_STYLE, DEFAULT_PALETTE } from '../../constants';
2
+ import { DEFAULT_DATALABELS_STYLE } from '../../constants';
3
3
  import { getUniqId } from '../../utils';
4
4
  import { DEFAULT_DATALABELS_PADDING } from './constants';
5
5
  import { prepareLegendSymbol } from './utils';
6
6
  export function prepareWaterfallSeries(args) {
7
7
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
8
- const { colorScale, series: seriesList, legend } = args;
9
- const [, negativeColor, positiveColor] = DEFAULT_PALETTE;
8
+ const { colorScale, series: seriesList, legend, colors } = args;
9
+ const [, negativeColor, positiveColor] = colors;
10
10
  const series = seriesList[0];
11
11
  const common = {
12
12
  id: '',
@@ -6,5 +6,6 @@ export declare function prepareSeries(args: {
6
6
  series: ChartSeries[];
7
7
  seriesOptions?: ChartSeriesOptions;
8
8
  legend: PreparedLegend;
9
+ colors: string[];
9
10
  colorScale: ScaleOrdinal<string, string>;
10
11
  }): PreparedSeries[];
@@ -10,11 +10,16 @@ import { prepareScatterSeries } from './prepare-scatter';
10
10
  import { prepareTreemap } from './prepare-treemap';
11
11
  import { prepareWaterfallSeries } from './prepare-waterfall';
12
12
  export function prepareSeries(args) {
13
- const { type, series, seriesOptions, legend, colorScale } = args;
13
+ const { type, series, seriesOptions, legend, colors, colorScale } = args;
14
14
  switch (type) {
15
15
  case 'pie': {
16
16
  return series.reduce((acc, singleSeries) => {
17
- acc.push(...preparePieSeries({ series: singleSeries, seriesOptions, legend }));
17
+ acc.push(...preparePieSeries({
18
+ series: singleSeries,
19
+ seriesOptions,
20
+ legend,
21
+ colors,
22
+ }));
18
23
  return acc;
19
24
  }, []);
20
25
  }
@@ -66,6 +71,7 @@ export function prepareSeries(args) {
66
71
  series: series,
67
72
  legend,
68
73
  colorScale,
74
+ colors,
69
75
  });
70
76
  }
71
77
  case 'sankey': {
@@ -81,6 +87,7 @@ export function prepareSeries(args) {
81
87
  series: series,
82
88
  seriesOptions,
83
89
  legend,
90
+ colors,
84
91
  });
85
92
  }
86
93
  default: {
@@ -1,7 +1,7 @@
1
- import { arc, group, line as lineGenerator } from 'd3';
1
+ import { arc, group, line as lineGenerator, max } from 'd3';
2
2
  import merge from 'lodash/merge';
3
3
  import { DEFAULT_DATALABELS_STYLE } from '../../../constants';
4
- import { calculateNumericProperty, getLabelsSize, getLeftPosition, isLabelsOverlapping, } from '../../../utils';
4
+ import { calculateNumericProperty, getLabelsSize, getLeftPosition, getTextSizeFn, isLabelsOverlapping, } from '../../../utils';
5
5
  import { getFormattedValue } from '../../../utils/chart/format';
6
6
  import { getCurveFactory, getInscribedAngle, pieGenerator } from './utils';
7
7
  const FULL_CIRCLE = Math.PI * 2;
@@ -31,7 +31,8 @@ export function preparePieData(args) {
31
31
  const minRadius = typeof propsMinRadius === 'number' ? propsMinRadius : maxRadius * 0.3;
32
32
  const groupedPieSeries = group(preparedSeries, (pieSeries) => pieSeries.stackId);
33
33
  const dataLabelsStyle = merge({}, DEFAULT_DATALABELS_STYLE, (_b = (_a = preparedSeries[0]) === null || _a === void 0 ? void 0 : _a.dataLabels) === null || _b === void 0 ? void 0 : _b.style);
34
- const prepareItem = (stackId, items) => {
34
+ const prepareItem = ({ stackId, items, labels, }) => {
35
+ var _a;
35
36
  const series = items[0];
36
37
  const { center, borderWidth, borderColor, borderRadius, dataLabels } = series;
37
38
  const data = {
@@ -53,15 +54,13 @@ export function preparePieData(args) {
53
54
  size: series.states.hover.halo.size,
54
55
  },
55
56
  };
56
- const { maxHeight: labelHeight } = getLabelsSize({
57
- labels: ['Some Label'],
58
- style: dataLabelsStyle,
59
- });
57
+ const labelMaxHeight = (_a = max(Object.values(labels).map((l) => { var _a, _b; return (_b = (_a = l.size) === null || _a === void 0 ? void 0 : _a.height) !== null && _b !== void 0 ? _b : 0; }))) !== null && _a !== void 0 ? _a : 0;
60
58
  const segments = items.map((item) => {
61
59
  var _a;
62
60
  let maxSegmentRadius = maxRadius;
63
61
  if (dataLabels.enabled) {
64
- maxSegmentRadius -= dataLabels.distance + dataLabels.connectorPadding + labelHeight;
62
+ maxSegmentRadius -=
63
+ dataLabels.distance + dataLabels.connectorPadding + labelMaxHeight;
65
64
  }
66
65
  const segmentRadius = (_a = calculateNumericProperty({ value: item.radius, base: maxSegmentRadius })) !== null && _a !== void 0 ? _a : maxSegmentRadius;
67
66
  return {
@@ -78,8 +77,40 @@ export function preparePieData(args) {
78
77
  data.segments = pieGenerator(segments);
79
78
  return data;
80
79
  };
80
+ const getLabels = ({ series }) => {
81
+ const { dataLabels } = series[0];
82
+ if (!dataLabels.enabled) {
83
+ return {};
84
+ }
85
+ const getTextSize = getTextSizeFn({ style: dataLabelsStyle });
86
+ return series.reduce((acc, d) => {
87
+ const text = getFormattedValue(Object.assign({ value: d.data.label || d.data.value }, d.dataLabels));
88
+ let labelWidth = 0;
89
+ let labelHeight = 0;
90
+ if (dataLabels.html) {
91
+ const size = getLabelsSize({
92
+ labels: [text],
93
+ style: dataLabelsStyle,
94
+ html: true,
95
+ });
96
+ labelWidth = size.maxWidth;
97
+ labelHeight = size.maxHeight;
98
+ }
99
+ else {
100
+ const size = getTextSize(text);
101
+ labelWidth = size.width;
102
+ labelHeight = size.height;
103
+ }
104
+ const label = {
105
+ text,
106
+ size: { width: labelWidth, height: labelHeight },
107
+ };
108
+ acc[d.id] = label;
109
+ return acc;
110
+ }, {});
111
+ };
81
112
  const prepareLabels = (prepareLabelsArgs) => {
82
- const { data, series, allowOverlow = true } = prepareLabelsArgs;
113
+ const { data, series, labels: labelsData, allowOverlow = true } = prepareLabelsArgs;
83
114
  const { dataLabels } = series[0];
84
115
  const labels = [];
85
116
  const htmlLabels = [];
@@ -93,12 +124,7 @@ export function preparePieData(args) {
93
124
  if (curveFactory) {
94
125
  line = line.curve(curveFactory);
95
126
  }
96
- const { style, connectorPadding, distance } = dataLabels;
97
- const { maxHeight: labelHeight } = getLabelsSize({
98
- labels: ['Some Label'],
99
- style: dataLabelsStyle,
100
- html: shouldUseHtml,
101
- });
127
+ const { connectorPadding, distance } = dataLabels;
102
128
  const connectorStartPointGenerator = arc()
103
129
  .innerRadius((d) => d.data.radius)
104
130
  .outerRadius((d) => d.data.radius);
@@ -114,14 +140,11 @@ export function preparePieData(args) {
114
140
  let shouldStopLabelPlacement = false;
115
141
  // eslint-disable-next-line complexity
116
142
  series.forEach((d, index) => {
143
+ var _a, _b;
117
144
  const prevLabel = labels[labels.length - 1];
118
- const text = getFormattedValue(Object.assign({ value: d.data.label || d.data.value }, d.dataLabels));
119
- const labelSize = getLabelsSize({
120
- labels: [text],
121
- style: dataLabelsStyle,
122
- html: shouldUseHtml,
123
- });
124
- const labelWidth = labelSize.maxWidth;
145
+ const { text = '', size: labelSize } = labelsData[d.id];
146
+ const labelWidth = (_a = labelSize === null || labelSize === void 0 ? void 0 : labelSize.width) !== null && _a !== void 0 ? _a : 0;
147
+ const labelHeight = (_b = labelSize === null || labelSize === void 0 ? void 0 : labelSize.height) !== null && _b !== void 0 ? _b : 0;
125
148
  const relatedSegment = data.segments[index];
126
149
  /**
127
150
  * Compute the label coordinates on the label arc for a given angle.
@@ -159,7 +182,7 @@ export function preparePieData(args) {
159
182
  text,
160
183
  x,
161
184
  y,
162
- style,
185
+ style: dataLabelsStyle,
163
186
  size: { width: labelWidth, height: labelHeight },
164
187
  maxWidth: labelWidth,
165
188
  textAnchor: midAngle < Math.PI ? 'start' : 'end',
@@ -251,9 +274,11 @@ export function preparePieData(args) {
251
274
  };
252
275
  return Array.from(groupedPieSeries).map(([stackId, items]) => {
253
276
  var _a;
254
- const data = prepareItem(stackId, items);
277
+ const seriesLabels = getLabels({ series: items });
278
+ const data = prepareItem({ stackId, items, labels: seriesLabels });
255
279
  const preparedLabels = prepareLabels({
256
280
  data,
281
+ labels: seriesLabels,
257
282
  series: items,
258
283
  });
259
284
  let maxLeftRightFreeSpace = Infinity;
@@ -329,6 +354,7 @@ export function preparePieData(args) {
329
354
  const { labels, htmlLabels, connectors } = prepareLabels({
330
355
  data,
331
356
  series: items,
357
+ labels: seriesLabels,
332
358
  allowOverlow: false,
333
359
  });
334
360
  if (typeof ((_a = items[0]) === null || _a === void 0 ? void 0 : _a.innerRadius) !== 'undefined') {
@@ -71,4 +71,10 @@ export interface ChartData<T = MeaningfulAny> {
71
71
  * It can be used to visualize related information on multiple charts.
72
72
  */
73
73
  split?: ChartSplit;
74
+ /** The color list of palette.
75
+ * If no color is set in series, the colors would be adopted sequentially and circularly from this list as the colors of series.
76
+ *
77
+ * @default ['#4DA2F1', '#FF3D64', '#8AD554', '#FFC636', '#FFB9DD', '#84D1EE', '#FF91A1', '#54A520', '#DB9100', '#BA74B3', '#1F68A9', '#ED65A9', '#0FA08D', '#FF7E00', '#E8B0A4', '#52A6C5', '#BE2443', '#70C1AF', '#FFB46C', '#DCA3D7']
78
+ * */
79
+ colors?: string[];
74
80
  }
@@ -21,7 +21,7 @@ export function axisBottom(args) {
21
21
  const position = getXTickPosition({ scale, offset });
22
22
  const values = getXAxisItems({ scale, count: ticksCount, maxCount: maxTickCount });
23
23
  const labelHeight = getLabelsSize({
24
- labels: values,
24
+ labels: values.map(labelFormat),
25
25
  style: labelsStyle,
26
26
  }).maxHeight;
27
27
  return function (selection) {
@@ -165,11 +165,27 @@ export function wrapText(args) {
165
165
  return acc;
166
166
  }, []);
167
167
  }
168
+ const entityMap = {
169
+ '&': '&amp;',
170
+ '<': '&lt;',
171
+ '>': '&gt;',
172
+ '"': '&quot;',
173
+ "'": '&#39;',
174
+ '/': '&#x2F;',
175
+ '`': '&#x60;',
176
+ '=': '&#x3D;',
177
+ };
178
+ function unescapeHtml(str) {
179
+ return Object.entries(entityMap).reduce((result, [key, value]) => {
180
+ return result.replace(value, key);
181
+ }, str);
182
+ }
168
183
  export function getTextSizeFn({ style }) {
169
184
  const map = {};
170
185
  const setSymbolSize = (s) => {
186
+ const labels = [s === ' ' ? '&nbsp;' : s];
171
187
  const size = getLabelsSize({
172
- labels: [s],
188
+ labels,
173
189
  style,
174
190
  });
175
191
  map[s] = { width: size.maxWidth, height: size.maxHeight };
@@ -177,7 +193,7 @@ export function getTextSizeFn({ style }) {
177
193
  return (str) => {
178
194
  let width = 0;
179
195
  let height = 0;
180
- [...str].forEach((s) => {
196
+ [...unescapeHtml(str)].forEach((s) => {
181
197
  if (!map[s]) {
182
198
  setSymbolSize(s);
183
199
  }
@@ -187,14 +203,20 @@ export function getTextSizeFn({ style }) {
187
203
  return { width, height };
188
204
  };
189
205
  }
206
+ // We ignore an inaccuracy of less than a pixel.
207
+ // To do this, we round the font size down when comparing it, and the size of the allowed space up.
190
208
  export function getTextWithElipsis({ text: originalText, getTextWidth, maxWidth, }) {
191
- let text = originalText;
192
- let textLength = getTextWidth(text);
193
- while (textLength > maxWidth && text.length > 1) {
209
+ let textWidth = Math.floor(getTextWidth(originalText));
210
+ const textMaxWidth = Math.ceil(maxWidth);
211
+ if (textWidth <= textMaxWidth) {
212
+ return originalText;
213
+ }
214
+ let text = originalText + '…';
215
+ while (textWidth > textMaxWidth && text.length > 2) {
194
216
  text = text.slice(0, -2) + '…';
195
- textLength = getTextWidth(text);
217
+ textWidth = Math.floor(getTextWidth(text));
196
218
  }
197
- if (textLength > maxWidth) {
219
+ if (textWidth > maxWidth) {
198
220
  text = '';
199
221
  }
200
222
  return text;
@@ -21,7 +21,8 @@ export function pieCenterText(text, options) {
21
21
  if (padding < args.series.innerRadius) {
22
22
  availableSpace -= padding * 2;
23
23
  }
24
- fontSize = Math.max((_b = options === null || options === void 0 ? void 0 : options.minFontSize) !== null && _b !== void 0 ? _b : MIN_FONT_SIZE, (fontSize * availableSpace) / Math.max(textSize.maxWidth, textSize.maxHeight));
24
+ const minFontSize = (_b = options === null || options === void 0 ? void 0 : options.minFontSize) !== null && _b !== void 0 ? _b : MIN_FONT_SIZE;
25
+ fontSize = Math.max(minFontSize, Math.ceil((fontSize * availableSpace) / Math.max(textSize.maxWidth, textSize.maxHeight)));
25
26
  const tempWrapper = select(document.body).append('svg');
26
27
  const container = tempWrapper.append('g');
27
28
  const textSelection = container
@@ -34,7 +35,9 @@ export function pieCenterText(text, options) {
34
35
  .attr('text-anchor', 'middle')
35
36
  .attr('dominant-baseline', 'middle')
36
37
  .text(text);
37
- handleOverflowingText(tspan.node(), availableSpace);
38
+ if (fontSize <= minFontSize) {
39
+ handleOverflowingText(tspan.node(), availableSpace);
40
+ }
38
41
  const result = container.node();
39
42
  tempWrapper.remove();
40
43
  return result;
@@ -8,7 +8,7 @@ export function useChartInnerProps(props) {
8
8
  const { width, height, data, dispatcher, htmlLayout, svgContainer } = props;
9
9
  const prevWidth = usePrevious(width);
10
10
  const prevHeight = usePrevious(height);
11
- const { chart, title, tooltip } = useChartOptions({ data });
11
+ const { chart, title, tooltip, colors } = useChartOptions({ data });
12
12
  const xAxis = React.useMemo(() => getPreparedXAxis({ xAxis: data.xAxis, width, series: data.series.data }), [data, width]);
13
13
  const yAxis = React.useMemo(() => getPreparedYAxis({
14
14
  series: data.series.data,
@@ -22,6 +22,7 @@ export function useChartInnerProps(props) {
22
22
  series: data.series,
23
23
  legend: data.legend,
24
24
  preparedYAxis: yAxis,
25
+ colors,
25
26
  });
26
27
  const { boundsWidth, boundsHeight } = useChartDimensions({
27
28
  width,
@@ -1,9 +1,10 @@
1
1
  import React from 'react';
2
+ import { DEFAULT_PALETTE } from '../../constants';
2
3
  import { getPreparedChart } from './chart';
3
4
  import { getPreparedTitle } from './title';
4
5
  import { getPreparedTooltip } from './tooltip';
5
6
  export const useChartOptions = (args) => {
6
- const { data: { chart, title, tooltip }, } = args;
7
+ const { data: { chart, title, tooltip, colors }, } = args;
7
8
  const options = React.useMemo(() => {
8
9
  const preparedTitle = getPreparedTitle({ title });
9
10
  const preparedTooltip = getPreparedTooltip({ tooltip });
@@ -15,7 +16,8 @@ export const useChartOptions = (args) => {
15
16
  chart: preparedChart,
16
17
  title: preparedTitle,
17
18
  tooltip: preparedTooltip,
19
+ colors: colors !== null && colors !== void 0 ? colors : DEFAULT_PALETTE,
18
20
  };
19
- }, [chart, title, tooltip]);
21
+ }, [chart, colors, title, tooltip]);
20
22
  return options;
21
23
  };
@@ -56,5 +56,6 @@ export type ChartOptions = {
56
56
  chart: PreparedChart;
57
57
  tooltip: PreparedTooltip;
58
58
  title?: PreparedTitle;
59
+ colors: string[];
59
60
  };
60
61
  export {};
@@ -8,6 +8,7 @@ type Args = {
8
8
  legend: ChartData['legend'];
9
9
  series: ChartData['series'];
10
10
  preparedYAxis: PreparedAxis[];
11
+ colors: string[];
11
12
  };
12
13
  export declare const useSeries: (args: Args) => {
13
14
  legendItems: import("./types").LegendItem[][];
@@ -1,17 +1,16 @@
1
1
  import React from 'react';
2
2
  import { group, scaleOrdinal } from 'd3';
3
- import { DEFAULT_PALETTE } from '../../constants';
4
3
  import { getSeriesNames } from '../../utils';
5
4
  import { getLegendComponents, getPreparedLegend } from './prepare-legend';
6
5
  import { getPreparedOptions } from './prepare-options';
7
6
  import { prepareSeries } from './prepareSeries';
8
7
  import { getActiveLegendItems, getAllLegendItems } from './utils';
9
8
  export const useSeries = (args) => {
10
- const { chartWidth, chartHeight, chartMargin, legend, preparedYAxis, series: { data: series, options: seriesOptions }, } = args;
9
+ const { chartWidth, chartHeight, chartMargin, legend, preparedYAxis, series: { data: series, options: seriesOptions }, colors, } = args;
11
10
  const preparedLegend = React.useMemo(() => getPreparedLegend({ legend, series }), [legend, series]);
12
11
  const preparedSeries = React.useMemo(() => {
13
12
  const seriesNames = getSeriesNames(series);
14
- const colorScale = scaleOrdinal(seriesNames, DEFAULT_PALETTE);
13
+ const colorScale = scaleOrdinal(seriesNames, colors);
15
14
  const groupedSeries = group(series, (item) => item.type);
16
15
  return Array.from(groupedSeries).reduce((acc, [seriesType, seriesList]) => {
17
16
  acc.push(...prepareSeries({
@@ -20,6 +19,7 @@ export const useSeries = (args) => {
20
19
  seriesOptions,
21
20
  legend: preparedLegend,
22
21
  colorScale,
22
+ colors,
23
23
  }));
24
24
  return acc;
25
25
  }, []);
@@ -4,6 +4,7 @@ type PreparePieSeriesArgs = {
4
4
  series: PieSeries;
5
5
  seriesOptions?: ChartSeriesOptions;
6
6
  legend: PreparedLegend;
7
+ colors: string[];
7
8
  };
8
9
  export declare function preparePieSeries(args: PreparePieSeriesArgs): PreparedSeries[];
9
10
  export {};
@@ -1,13 +1,13 @@
1
1
  import { scaleOrdinal } from 'd3';
2
2
  import get from 'lodash/get';
3
- import { DEFAULT_DATALABELS_STYLE, DEFAULT_PALETTE } from '../../constants';
3
+ import { DEFAULT_DATALABELS_STYLE } from '../../constants';
4
4
  import { getUniqId } from '../../utils';
5
5
  import { DEFAULT_DATALABELS_PADDING } from './constants';
6
6
  import { prepareLegendSymbol } from './utils';
7
7
  export function preparePieSeries(args) {
8
- const { series, seriesOptions, legend } = args;
8
+ const { series, seriesOptions, legend, colors } = args;
9
9
  const dataNames = series.data.map((d) => d.name);
10
- const colorScale = scaleOrdinal(dataNames, DEFAULT_PALETTE);
10
+ const colorScale = scaleOrdinal(dataNames, colors);
11
11
  const stackId = getUniqId();
12
12
  const seriesHoverState = get(seriesOptions, 'pie.states.hover');
13
13
  const preparedSeries = series.data.map((dataItem, i) => {
@@ -4,6 +4,7 @@ type PrepareRadarSeriesArgs = {
4
4
  series: RadarSeries[];
5
5
  seriesOptions?: ChartSeriesOptions;
6
6
  legend: PreparedLegend;
7
+ colors: string[];
7
8
  };
8
9
  export declare const DEFAULT_MARKER: {
9
10
  enabled: boolean;
@@ -1,7 +1,7 @@
1
1
  import { scaleOrdinal } from 'd3';
2
2
  import get from 'lodash/get';
3
3
  import merge from 'lodash/merge';
4
- import { DEFAULT_DATALABELS_STYLE, DEFAULT_PALETTE } from '../../constants';
4
+ import { DEFAULT_DATALABELS_STYLE } from '../../constants';
5
5
  import { getUniqId } from '../../utils';
6
6
  import { DEFAULT_DATALABELS_PADDING, DEFAULT_HALO_OPTIONS, DEFAULT_POINT_MARKER_OPTIONS, } from './constants';
7
7
  import { prepareLegendSymbol } from './utils';
@@ -26,8 +26,8 @@ function prepareMarker(series, seriesOptions) {
26
26
  }
27
27
  export function prepareRadarSeries(args) {
28
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);
29
+ const { series: radarSeries, seriesOptions, legend, colors } = args;
30
+ const colorScale = scaleOrdinal(radarSeries.map((s, index) => { var _a; return (_a = s.name) !== null && _a !== void 0 ? _a : `Series ${index + 1}`; }), colors);
31
31
  const categories = (_b = (_a = radarSeries.find((s) => s.categories)) === null || _a === void 0 ? void 0 : _a.categories) !== null && _b !== void 0 ? _b : [];
32
32
  return radarSeries.map((series, index) => {
33
33
  var _a, _b, _c, _d, _e, _f;
@@ -5,6 +5,7 @@ type PrepareWaterfallSeriesArgs = {
5
5
  colorScale: ScaleOrdinal<string, string>;
6
6
  series: WaterfallSeries[];
7
7
  legend: PreparedLegend;
8
+ colors: string[];
8
9
  };
9
10
  export declare function prepareWaterfallSeries(args: PrepareWaterfallSeriesArgs): PreparedSeries[];
10
11
  export {};
@@ -1,12 +1,12 @@
1
1
  import get from 'lodash/get';
2
- import { DEFAULT_DATALABELS_STYLE, DEFAULT_PALETTE } from '../../constants';
2
+ import { DEFAULT_DATALABELS_STYLE } from '../../constants';
3
3
  import { getUniqId } from '../../utils';
4
4
  import { DEFAULT_DATALABELS_PADDING } from './constants';
5
5
  import { prepareLegendSymbol } from './utils';
6
6
  export function prepareWaterfallSeries(args) {
7
7
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
8
- const { colorScale, series: seriesList, legend } = args;
9
- const [, negativeColor, positiveColor] = DEFAULT_PALETTE;
8
+ const { colorScale, series: seriesList, legend, colors } = args;
9
+ const [, negativeColor, positiveColor] = colors;
10
10
  const series = seriesList[0];
11
11
  const common = {
12
12
  id: '',
@@ -6,5 +6,6 @@ export declare function prepareSeries(args: {
6
6
  series: ChartSeries[];
7
7
  seriesOptions?: ChartSeriesOptions;
8
8
  legend: PreparedLegend;
9
+ colors: string[];
9
10
  colorScale: ScaleOrdinal<string, string>;
10
11
  }): PreparedSeries[];
@@ -10,11 +10,16 @@ import { prepareScatterSeries } from './prepare-scatter';
10
10
  import { prepareTreemap } from './prepare-treemap';
11
11
  import { prepareWaterfallSeries } from './prepare-waterfall';
12
12
  export function prepareSeries(args) {
13
- const { type, series, seriesOptions, legend, colorScale } = args;
13
+ const { type, series, seriesOptions, legend, colors, colorScale } = args;
14
14
  switch (type) {
15
15
  case 'pie': {
16
16
  return series.reduce((acc, singleSeries) => {
17
- acc.push(...preparePieSeries({ series: singleSeries, seriesOptions, legend }));
17
+ acc.push(...preparePieSeries({
18
+ series: singleSeries,
19
+ seriesOptions,
20
+ legend,
21
+ colors,
22
+ }));
18
23
  return acc;
19
24
  }, []);
20
25
  }
@@ -66,6 +71,7 @@ export function prepareSeries(args) {
66
71
  series: series,
67
72
  legend,
68
73
  colorScale,
74
+ colors,
69
75
  });
70
76
  }
71
77
  case 'sankey': {
@@ -81,6 +87,7 @@ export function prepareSeries(args) {
81
87
  series: series,
82
88
  seriesOptions,
83
89
  legend,
90
+ colors,
84
91
  });
85
92
  }
86
93
  default: {
@@ -1,7 +1,7 @@
1
- import { arc, group, line as lineGenerator } from 'd3';
1
+ import { arc, group, line as lineGenerator, max } from 'd3';
2
2
  import merge from 'lodash/merge';
3
3
  import { DEFAULT_DATALABELS_STYLE } from '../../../constants';
4
- import { calculateNumericProperty, getLabelsSize, getLeftPosition, isLabelsOverlapping, } from '../../../utils';
4
+ import { calculateNumericProperty, getLabelsSize, getLeftPosition, getTextSizeFn, isLabelsOverlapping, } from '../../../utils';
5
5
  import { getFormattedValue } from '../../../utils/chart/format';
6
6
  import { getCurveFactory, getInscribedAngle, pieGenerator } from './utils';
7
7
  const FULL_CIRCLE = Math.PI * 2;
@@ -31,7 +31,8 @@ export function preparePieData(args) {
31
31
  const minRadius = typeof propsMinRadius === 'number' ? propsMinRadius : maxRadius * 0.3;
32
32
  const groupedPieSeries = group(preparedSeries, (pieSeries) => pieSeries.stackId);
33
33
  const dataLabelsStyle = merge({}, DEFAULT_DATALABELS_STYLE, (_b = (_a = preparedSeries[0]) === null || _a === void 0 ? void 0 : _a.dataLabels) === null || _b === void 0 ? void 0 : _b.style);
34
- const prepareItem = (stackId, items) => {
34
+ const prepareItem = ({ stackId, items, labels, }) => {
35
+ var _a;
35
36
  const series = items[0];
36
37
  const { center, borderWidth, borderColor, borderRadius, dataLabels } = series;
37
38
  const data = {
@@ -53,15 +54,13 @@ export function preparePieData(args) {
53
54
  size: series.states.hover.halo.size,
54
55
  },
55
56
  };
56
- const { maxHeight: labelHeight } = getLabelsSize({
57
- labels: ['Some Label'],
58
- style: dataLabelsStyle,
59
- });
57
+ const labelMaxHeight = (_a = max(Object.values(labels).map((l) => { var _a, _b; return (_b = (_a = l.size) === null || _a === void 0 ? void 0 : _a.height) !== null && _b !== void 0 ? _b : 0; }))) !== null && _a !== void 0 ? _a : 0;
60
58
  const segments = items.map((item) => {
61
59
  var _a;
62
60
  let maxSegmentRadius = maxRadius;
63
61
  if (dataLabels.enabled) {
64
- maxSegmentRadius -= dataLabels.distance + dataLabels.connectorPadding + labelHeight;
62
+ maxSegmentRadius -=
63
+ dataLabels.distance + dataLabels.connectorPadding + labelMaxHeight;
65
64
  }
66
65
  const segmentRadius = (_a = calculateNumericProperty({ value: item.radius, base: maxSegmentRadius })) !== null && _a !== void 0 ? _a : maxSegmentRadius;
67
66
  return {
@@ -78,8 +77,40 @@ export function preparePieData(args) {
78
77
  data.segments = pieGenerator(segments);
79
78
  return data;
80
79
  };
80
+ const getLabels = ({ series }) => {
81
+ const { dataLabels } = series[0];
82
+ if (!dataLabels.enabled) {
83
+ return {};
84
+ }
85
+ const getTextSize = getTextSizeFn({ style: dataLabelsStyle });
86
+ return series.reduce((acc, d) => {
87
+ const text = getFormattedValue(Object.assign({ value: d.data.label || d.data.value }, d.dataLabels));
88
+ let labelWidth = 0;
89
+ let labelHeight = 0;
90
+ if (dataLabels.html) {
91
+ const size = getLabelsSize({
92
+ labels: [text],
93
+ style: dataLabelsStyle,
94
+ html: true,
95
+ });
96
+ labelWidth = size.maxWidth;
97
+ labelHeight = size.maxHeight;
98
+ }
99
+ else {
100
+ const size = getTextSize(text);
101
+ labelWidth = size.width;
102
+ labelHeight = size.height;
103
+ }
104
+ const label = {
105
+ text,
106
+ size: { width: labelWidth, height: labelHeight },
107
+ };
108
+ acc[d.id] = label;
109
+ return acc;
110
+ }, {});
111
+ };
81
112
  const prepareLabels = (prepareLabelsArgs) => {
82
- const { data, series, allowOverlow = true } = prepareLabelsArgs;
113
+ const { data, series, labels: labelsData, allowOverlow = true } = prepareLabelsArgs;
83
114
  const { dataLabels } = series[0];
84
115
  const labels = [];
85
116
  const htmlLabels = [];
@@ -93,12 +124,7 @@ export function preparePieData(args) {
93
124
  if (curveFactory) {
94
125
  line = line.curve(curveFactory);
95
126
  }
96
- const { style, connectorPadding, distance } = dataLabels;
97
- const { maxHeight: labelHeight } = getLabelsSize({
98
- labels: ['Some Label'],
99
- style: dataLabelsStyle,
100
- html: shouldUseHtml,
101
- });
127
+ const { connectorPadding, distance } = dataLabels;
102
128
  const connectorStartPointGenerator = arc()
103
129
  .innerRadius((d) => d.data.radius)
104
130
  .outerRadius((d) => d.data.radius);
@@ -114,14 +140,11 @@ export function preparePieData(args) {
114
140
  let shouldStopLabelPlacement = false;
115
141
  // eslint-disable-next-line complexity
116
142
  series.forEach((d, index) => {
143
+ var _a, _b;
117
144
  const prevLabel = labels[labels.length - 1];
118
- const text = getFormattedValue(Object.assign({ value: d.data.label || d.data.value }, d.dataLabels));
119
- const labelSize = getLabelsSize({
120
- labels: [text],
121
- style: dataLabelsStyle,
122
- html: shouldUseHtml,
123
- });
124
- const labelWidth = labelSize.maxWidth;
145
+ const { text = '', size: labelSize } = labelsData[d.id];
146
+ const labelWidth = (_a = labelSize === null || labelSize === void 0 ? void 0 : labelSize.width) !== null && _a !== void 0 ? _a : 0;
147
+ const labelHeight = (_b = labelSize === null || labelSize === void 0 ? void 0 : labelSize.height) !== null && _b !== void 0 ? _b : 0;
125
148
  const relatedSegment = data.segments[index];
126
149
  /**
127
150
  * Compute the label coordinates on the label arc for a given angle.
@@ -159,7 +182,7 @@ export function preparePieData(args) {
159
182
  text,
160
183
  x,
161
184
  y,
162
- style,
185
+ style: dataLabelsStyle,
163
186
  size: { width: labelWidth, height: labelHeight },
164
187
  maxWidth: labelWidth,
165
188
  textAnchor: midAngle < Math.PI ? 'start' : 'end',
@@ -251,9 +274,11 @@ export function preparePieData(args) {
251
274
  };
252
275
  return Array.from(groupedPieSeries).map(([stackId, items]) => {
253
276
  var _a;
254
- const data = prepareItem(stackId, items);
277
+ const seriesLabels = getLabels({ series: items });
278
+ const data = prepareItem({ stackId, items, labels: seriesLabels });
255
279
  const preparedLabels = prepareLabels({
256
280
  data,
281
+ labels: seriesLabels,
257
282
  series: items,
258
283
  });
259
284
  let maxLeftRightFreeSpace = Infinity;
@@ -329,6 +354,7 @@ export function preparePieData(args) {
329
354
  const { labels, htmlLabels, connectors } = prepareLabels({
330
355
  data,
331
356
  series: items,
357
+ labels: seriesLabels,
332
358
  allowOverlow: false,
333
359
  });
334
360
  if (typeof ((_a = items[0]) === null || _a === void 0 ? void 0 : _a.innerRadius) !== 'undefined') {
@@ -71,4 +71,10 @@ export interface ChartData<T = MeaningfulAny> {
71
71
  * It can be used to visualize related information on multiple charts.
72
72
  */
73
73
  split?: ChartSplit;
74
+ /** The color list of palette.
75
+ * If no color is set in series, the colors would be adopted sequentially and circularly from this list as the colors of series.
76
+ *
77
+ * @default ['#4DA2F1', '#FF3D64', '#8AD554', '#FFC636', '#FFB9DD', '#84D1EE', '#FF91A1', '#54A520', '#DB9100', '#BA74B3', '#1F68A9', '#ED65A9', '#0FA08D', '#FF7E00', '#E8B0A4', '#52A6C5', '#BE2443', '#70C1AF', '#FFB46C', '#DCA3D7']
78
+ * */
79
+ colors?: string[];
74
80
  }
@@ -21,7 +21,7 @@ export function axisBottom(args) {
21
21
  const position = getXTickPosition({ scale, offset });
22
22
  const values = getXAxisItems({ scale, count: ticksCount, maxCount: maxTickCount });
23
23
  const labelHeight = getLabelsSize({
24
- labels: values,
24
+ labels: values.map(labelFormat),
25
25
  style: labelsStyle,
26
26
  }).maxHeight;
27
27
  return function (selection) {
@@ -165,11 +165,27 @@ export function wrapText(args) {
165
165
  return acc;
166
166
  }, []);
167
167
  }
168
+ const entityMap = {
169
+ '&': '&amp;',
170
+ '<': '&lt;',
171
+ '>': '&gt;',
172
+ '"': '&quot;',
173
+ "'": '&#39;',
174
+ '/': '&#x2F;',
175
+ '`': '&#x60;',
176
+ '=': '&#x3D;',
177
+ };
178
+ function unescapeHtml(str) {
179
+ return Object.entries(entityMap).reduce((result, [key, value]) => {
180
+ return result.replace(value, key);
181
+ }, str);
182
+ }
168
183
  export function getTextSizeFn({ style }) {
169
184
  const map = {};
170
185
  const setSymbolSize = (s) => {
186
+ const labels = [s === ' ' ? '&nbsp;' : s];
171
187
  const size = getLabelsSize({
172
- labels: [s],
188
+ labels,
173
189
  style,
174
190
  });
175
191
  map[s] = { width: size.maxWidth, height: size.maxHeight };
@@ -177,7 +193,7 @@ export function getTextSizeFn({ style }) {
177
193
  return (str) => {
178
194
  let width = 0;
179
195
  let height = 0;
180
- [...str].forEach((s) => {
196
+ [...unescapeHtml(str)].forEach((s) => {
181
197
  if (!map[s]) {
182
198
  setSymbolSize(s);
183
199
  }
@@ -187,14 +203,20 @@ export function getTextSizeFn({ style }) {
187
203
  return { width, height };
188
204
  };
189
205
  }
206
+ // We ignore an inaccuracy of less than a pixel.
207
+ // To do this, we round the font size down when comparing it, and the size of the allowed space up.
190
208
  export function getTextWithElipsis({ text: originalText, getTextWidth, maxWidth, }) {
191
- let text = originalText;
192
- let textLength = getTextWidth(text);
193
- while (textLength > maxWidth && text.length > 1) {
209
+ let textWidth = Math.floor(getTextWidth(originalText));
210
+ const textMaxWidth = Math.ceil(maxWidth);
211
+ if (textWidth <= textMaxWidth) {
212
+ return originalText;
213
+ }
214
+ let text = originalText + '…';
215
+ while (textWidth > textMaxWidth && text.length > 2) {
194
216
  text = text.slice(0, -2) + '…';
195
- textLength = getTextWidth(text);
217
+ textWidth = Math.floor(getTextWidth(text));
196
218
  }
197
- if (textLength > maxWidth) {
219
+ if (textWidth > maxWidth) {
198
220
  text = '';
199
221
  }
200
222
  return text;
@@ -21,7 +21,8 @@ export function pieCenterText(text, options) {
21
21
  if (padding < args.series.innerRadius) {
22
22
  availableSpace -= padding * 2;
23
23
  }
24
- fontSize = Math.max((_b = options === null || options === void 0 ? void 0 : options.minFontSize) !== null && _b !== void 0 ? _b : MIN_FONT_SIZE, (fontSize * availableSpace) / Math.max(textSize.maxWidth, textSize.maxHeight));
24
+ const minFontSize = (_b = options === null || options === void 0 ? void 0 : options.minFontSize) !== null && _b !== void 0 ? _b : MIN_FONT_SIZE;
25
+ fontSize = Math.max(minFontSize, Math.ceil((fontSize * availableSpace) / Math.max(textSize.maxWidth, textSize.maxHeight)));
25
26
  const tempWrapper = select(document.body).append('svg');
26
27
  const container = tempWrapper.append('g');
27
28
  const textSelection = container
@@ -34,7 +35,9 @@ export function pieCenterText(text, options) {
34
35
  .attr('text-anchor', 'middle')
35
36
  .attr('dominant-baseline', 'middle')
36
37
  .text(text);
37
- handleOverflowingText(tspan.node(), availableSpace);
38
+ if (fontSize <= minFontSize) {
39
+ handleOverflowingText(tspan.node(), availableSpace);
40
+ }
38
41
  const result = container.node();
39
42
  tempWrapper.remove();
40
43
  return result;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/charts",
3
- "version": "1.6.6",
3
+ "version": "1.7.0",
4
4
  "description": "React component used to render charts",
5
5
  "license": "MIT",
6
6
  "main": "dist/cjs/index.js",