@gravity-ui/charts 1.12.0 → 1.13.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 (71) hide show
  1. package/dist/cjs/components/Axis/AxisX.js +62 -36
  2. package/dist/cjs/components/Axis/AxisY.js +67 -31
  3. package/dist/cjs/components/ChartInner/styles.css +1 -0
  4. package/dist/cjs/components/ChartInner/useChartInnerProps.js +3 -3
  5. package/dist/cjs/components/Tooltip/DefaultTooltipContent/index.js +1 -1
  6. package/dist/cjs/hooks/useAxisScales/index.js +19 -6
  7. package/dist/cjs/hooks/useChartOptions/types.d.ts +5 -0
  8. package/dist/cjs/hooks/useChartOptions/utils.d.ts +11 -0
  9. package/dist/cjs/hooks/useChartOptions/utils.js +27 -0
  10. package/dist/cjs/hooks/useChartOptions/x-axis.js +5 -1
  11. package/dist/cjs/hooks/useChartOptions/y-axis.js +5 -1
  12. package/dist/cjs/hooks/useSeries/prepare-area.d.ts +1 -1
  13. package/dist/cjs/hooks/useSeries/prepare-bar-y.d.ts +3 -0
  14. package/dist/cjs/hooks/useSeries/prepare-bar-y.js +5 -2
  15. package/dist/cjs/hooks/useSeries/prepare-line.d.ts +1 -1
  16. package/dist/cjs/hooks/useSeries/prepare-radar.d.ts +1 -1
  17. package/dist/cjs/hooks/useSeries/types.d.ts +3 -0
  18. package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +15 -12
  19. package/dist/cjs/hooks/useShapes/bar-y/index.d.ts +2 -2
  20. package/dist/cjs/hooks/useShapes/bar-y/index.js +5 -9
  21. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.d.ts +2 -2
  22. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +65 -47
  23. package/dist/cjs/hooks/useShapes/bar-y/types.d.ts +7 -2
  24. package/dist/cjs/hooks/useShapes/index.js +1 -1
  25. package/dist/cjs/hooks/utils/bar-y.d.ts +3 -3
  26. package/dist/cjs/hooks/utils/bar-y.js +7 -21
  27. package/dist/cjs/types/chart/axis.d.ts +13 -1
  28. package/dist/cjs/types/chart/bar-y.d.ts +10 -0
  29. package/dist/cjs/types/chart/series.d.ts +10 -0
  30. package/dist/cjs/utils/chart/axis-generators/bottom.js +26 -13
  31. package/dist/cjs/utils/chart/get-closest-data.js +13 -12
  32. package/dist/cjs/utils/chart/index.js +1 -1
  33. package/dist/cjs/utils/chart/series/sorting.d.ts +6 -2
  34. package/dist/cjs/utils/chart/series/sorting.js +29 -4
  35. package/dist/cjs/utils/chart/zoom.js +2 -1
  36. package/dist/esm/components/Axis/AxisX.js +62 -36
  37. package/dist/esm/components/Axis/AxisY.js +67 -31
  38. package/dist/esm/components/ChartInner/styles.css +1 -0
  39. package/dist/esm/components/ChartInner/useChartInnerProps.js +3 -3
  40. package/dist/esm/components/Tooltip/DefaultTooltipContent/index.js +1 -1
  41. package/dist/esm/hooks/useAxisScales/index.js +19 -6
  42. package/dist/esm/hooks/useChartOptions/types.d.ts +5 -0
  43. package/dist/esm/hooks/useChartOptions/utils.d.ts +11 -0
  44. package/dist/esm/hooks/useChartOptions/utils.js +27 -0
  45. package/dist/esm/hooks/useChartOptions/x-axis.js +5 -1
  46. package/dist/esm/hooks/useChartOptions/y-axis.js +5 -1
  47. package/dist/esm/hooks/useSeries/prepare-area.d.ts +1 -1
  48. package/dist/esm/hooks/useSeries/prepare-bar-y.d.ts +3 -0
  49. package/dist/esm/hooks/useSeries/prepare-bar-y.js +5 -2
  50. package/dist/esm/hooks/useSeries/prepare-line.d.ts +1 -1
  51. package/dist/esm/hooks/useSeries/prepare-radar.d.ts +1 -1
  52. package/dist/esm/hooks/useSeries/types.d.ts +3 -0
  53. package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +15 -12
  54. package/dist/esm/hooks/useShapes/bar-y/index.d.ts +2 -2
  55. package/dist/esm/hooks/useShapes/bar-y/index.js +5 -9
  56. package/dist/esm/hooks/useShapes/bar-y/prepare-data.d.ts +2 -2
  57. package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +65 -47
  58. package/dist/esm/hooks/useShapes/bar-y/types.d.ts +7 -2
  59. package/dist/esm/hooks/useShapes/index.js +1 -1
  60. package/dist/esm/hooks/utils/bar-y.d.ts +3 -3
  61. package/dist/esm/hooks/utils/bar-y.js +7 -21
  62. package/dist/esm/types/chart/axis.d.ts +13 -1
  63. package/dist/esm/types/chart/bar-y.d.ts +10 -0
  64. package/dist/esm/types/chart/series.d.ts +10 -0
  65. package/dist/esm/utils/chart/axis-generators/bottom.js +26 -13
  66. package/dist/esm/utils/chart/get-closest-data.js +13 -12
  67. package/dist/esm/utils/chart/index.js +1 -1
  68. package/dist/esm/utils/chart/series/sorting.d.ts +6 -2
  69. package/dist/esm/utils/chart/series/sorting.js +29 -4
  70. package/dist/esm/utils/chart/zoom.js +2 -1
  71. package/package.json +1 -1
@@ -51,17 +51,6 @@ export const AxisX = React.memo(function AxisX(props) {
51
51
  }
52
52
  const svgElement = select(ref.current);
53
53
  svgElement.selectAll('*').remove();
54
- const plotDataAttr = 'data-plot-x';
55
- let plotBeforeContainer = null;
56
- let plotAfterContainer = null;
57
- if (plotBeforeRef === null || plotBeforeRef === void 0 ? void 0 : plotBeforeRef.current) {
58
- plotBeforeContainer = select(plotBeforeRef.current);
59
- plotBeforeContainer.selectAll(`[${plotDataAttr}]`).remove();
60
- }
61
- if (plotAfterRef === null || plotAfterRef === void 0 ? void 0 : plotAfterRef.current) {
62
- plotAfterContainer = select(plotAfterRef.current);
63
- plotAfterContainer.selectAll(`[${plotDataAttr}]`).remove();
64
- }
65
54
  if (!axis.visible) {
66
55
  return;
67
56
  }
@@ -122,6 +111,17 @@ export const AxisX = React.memo(function AxisX(props) {
122
111
  }
123
112
  });
124
113
  }
114
+ const plotDataAttr = 'data-plot-x';
115
+ let plotBeforeContainer = null;
116
+ let plotAfterContainer = null;
117
+ if (plotBeforeRef === null || plotBeforeRef === void 0 ? void 0 : plotBeforeRef.current) {
118
+ plotBeforeContainer = select(plotBeforeRef.current);
119
+ plotBeforeContainer.selectAll(`[${plotDataAttr}]`).remove();
120
+ }
121
+ if (plotAfterRef === null || plotAfterRef === void 0 ? void 0 : plotAfterRef.current) {
122
+ plotAfterContainer = select(plotAfterRef.current);
123
+ plotAfterContainer.selectAll(`[${plotDataAttr}]`).remove();
124
+ }
125
125
  // add plot bands
126
126
  if (axis.plotBands.length > 0) {
127
127
  const plotBandDataAttr = 'plot-x-band';
@@ -136,25 +136,38 @@ export const AxisX = React.memo(function AxisX(props) {
136
136
  .join('g')
137
137
  .attr(plotDataAttr, 1)
138
138
  .attr(plotBandDataAttr, 1);
139
- plotBandsSelection
140
- .append('rect')
141
- .attr('x', (band) => {
142
- var _a, _b;
139
+ plotBandsSelection.each(function () {
140
+ var _a, _b, _c, _e;
141
+ const plotBandSelection = select(this);
142
+ const band = plotBandSelection.datum();
143
143
  const { from, to } = getBandsPosition({ band, axisScale, axis: 'x' });
144
144
  const halfBandwidth = ((_b = (_a = axisScale.bandwidth) === null || _a === void 0 ? void 0 : _a.call(axisScale)) !== null && _b !== void 0 ? _b : 0) / 2;
145
145
  const startPos = halfBandwidth + Math.min(from, to);
146
- return Math.max(0, startPos);
147
- })
148
- .attr('width', (band) => {
149
- const { from, to } = getBandsPosition({ band, axisScale, axis: 'x' });
150
- const startPos = width - Math.min(from, to);
151
- const endPos = Math.min(Math.abs(to - from), startPos);
152
- return Math.min(endPos, width);
153
- })
154
- .attr('y', 0)
155
- .attr('height', totalHeight)
156
- .attr('fill', (band) => band.color)
157
- .attr('opacity', (band) => band.opacity);
146
+ const x = Math.max(0, startPos);
147
+ plotBandSelection
148
+ .append('rect')
149
+ .attr('x', x)
150
+ .attr('width', () => {
151
+ const endPos = Math.min(Math.abs(to - from), width - Math.min(from, to));
152
+ return Math.min(endPos, width);
153
+ })
154
+ .attr('y', 0)
155
+ .attr('height', totalHeight)
156
+ .attr('fill', () => band.color)
157
+ .attr('opacity', () => band.opacity);
158
+ if (band.label.text) {
159
+ const labelPadding = (_e = (_c = band.label) === null || _c === void 0 ? void 0 : _c.padding) !== null && _e !== void 0 ? _e : 0;
160
+ plotBandSelection
161
+ .append('text')
162
+ .text(band.label.text)
163
+ .style('fill', () => { var _a, _b; return (_b = (_a = band.label.style) === null || _a === void 0 ? void 0 : _a.fontColor) !== null && _b !== void 0 ? _b : null; })
164
+ .style('font-size', () => { var _a, _b; return (_b = (_a = band.label.style) === null || _a === void 0 ? void 0 : _a.fontSize) !== null && _b !== void 0 ? _b : null; })
165
+ .style('font-weight', () => { var _a, _b; return (_b = (_a = band.label.style) === null || _a === void 0 ? void 0 : _a.fontWeight) !== null && _b !== void 0 ? _b : null; })
166
+ .style('dominant-baseline', 'text-before-edge')
167
+ .style('text-anchor', 'end')
168
+ .style('transform', `translate(${x + labelPadding}px, ${labelPadding}px) rotate(-90deg)`);
169
+ }
170
+ });
158
171
  };
159
172
  setPlotBands(plotBeforeContainer, axis.plotBands.filter((d) => d.layerPlacement === 'before'));
160
173
  setPlotBands(plotAfterContainer, axis.plotBands.filter((d) => d.layerPlacement === 'after'));
@@ -174,20 +187,33 @@ export const AxisX = React.memo(function AxisX(props) {
174
187
  .attr(plotDataAttr, 1)
175
188
  .attr(plotLineDataAttr, 1);
176
189
  const lineGenerator = line();
177
- plotLinesSelection
178
- .append('path')
179
- .attr('d', (plotLine) => {
190
+ plotLinesSelection.each(function () {
191
+ const itemSelection = select(this);
192
+ const plotLine = itemSelection.datum();
180
193
  const plotLineValue = Number(axisScale(plotLine.value));
181
194
  const points = [
182
195
  [plotLineValue, 0],
183
196
  [plotLineValue, totalHeight],
184
197
  ];
185
- return lineGenerator(points);
186
- })
187
- .attr('stroke', (plotLine) => plotLine.color)
188
- .attr('stroke-width', (plotLine) => plotLine.width)
189
- .attr('stroke-dasharray', (plotLine) => getLineDashArray(plotLine.dashStyle, plotLine.width))
190
- .attr('opacity', (plotLine) => plotLine.opacity);
198
+ itemSelection
199
+ .append('path')
200
+ .attr('d', lineGenerator(points))
201
+ .attr('stroke', plotLine.color)
202
+ .attr('stroke-width', plotLine.width)
203
+ .attr('stroke-dasharray', getLineDashArray(plotLine.dashStyle, plotLine.width))
204
+ .attr('opacity', plotLine.opacity);
205
+ if (plotLine.label.text) {
206
+ itemSelection
207
+ .append('text')
208
+ .text(plotLine.label.text)
209
+ .style('fill', () => { var _a; return (_a = plotLine.label.style.fontColor) !== null && _a !== void 0 ? _a : null; })
210
+ .attr('font-size', plotLine.label.style.fontSize)
211
+ .style('font-weight', () => { var _a; return (_a = plotLine.label.style.fontWeight) !== null && _a !== void 0 ? _a : null; })
212
+ .style('dominant-baseline', 'text-after-edge')
213
+ .style('text-anchor', 'end')
214
+ .style('transform', `translate(${plotLineValue - plotLine.label.padding}px, ${plotLine.label.padding}px) rotate(-90deg)`);
215
+ }
216
+ });
191
217
  };
192
218
  setPlotLines(plotBeforeContainer, axis.plotLines.filter((d) => d.layerPlacement === 'before'));
193
219
  setPlotLines(plotAfterContainer, axis.plotLines.filter((d) => d.layerPlacement === 'after'));
@@ -172,16 +172,28 @@ export const AxisY = (props) => {
172
172
  let elementY = 0;
173
173
  axisItem
174
174
  .selectAll('.tick')
175
- .filter(function (_d, tickIndex) {
176
- const tickNode = this;
177
- const r = tickNode.getBoundingClientRect();
178
- if (r.bottom > elementY && tickIndex !== 0) {
175
+ .nodes()
176
+ .map((element) => {
177
+ const r = element.getBoundingClientRect();
178
+ return {
179
+ top: r.top,
180
+ bottom: r.bottom,
181
+ node: element,
182
+ };
183
+ }, {})
184
+ .sort((item1, item2) => {
185
+ return item2.top - item1.top;
186
+ })
187
+ .filter(function ({ top, bottom }, tickIndex) {
188
+ if (bottom > elementY && tickIndex !== 0) {
179
189
  return true;
180
190
  }
181
- elementY = r.top - d.labels.padding;
191
+ elementY = top - d.labels.padding;
182
192
  return false;
183
193
  })
184
- .remove();
194
+ .forEach((item) => {
195
+ item.node.remove();
196
+ });
185
197
  }
186
198
  if (d.plotBands.length > 0) {
187
199
  const plotBandDataAttr = `data-plot-y-band-${index}`;
@@ -197,25 +209,36 @@ export const AxisY = (props) => {
197
209
  .attr(plotDataAttr, 1)
198
210
  .attr(plotBandDataAttr, 1)
199
211
  .style('transform', getAxisPlotsPosition(d, split));
200
- plotBandsSelection
201
- .append('rect')
202
- .attr('x', 0)
203
- .attr('width', width)
204
- .attr('y', (band) => {
205
- var _a, _b;
212
+ plotBandsSelection.each(function () {
213
+ var _a, _b, _c, _e;
214
+ const plotBandSelection = select(this);
215
+ const band = plotBandSelection.datum();
206
216
  const { from, to } = getBandsPosition({ band, axisScale, axis: 'y' });
207
217
  const halfBandwidth = ((_b = (_a = axisScale.bandwidth) === null || _a === void 0 ? void 0 : _a.call(axisScale)) !== null && _b !== void 0 ? _b : 0) / 2;
208
218
  const startPos = halfBandwidth + Math.min(from, to);
209
- return Math.max(0, startPos);
210
- })
211
- .attr('height', (band) => {
212
- const { from, to } = getBandsPosition({ band, axisScale, axis: 'y' });
213
- const startPos = height - Math.min(from, to);
214
- const endPos = Math.min(Math.abs(to - from), startPos);
215
- return Math.min(endPos, height);
216
- })
217
- .attr('fill', (band) => band.color)
218
- .attr('opacity', (band) => band.opacity);
219
+ const endPos = Math.min(Math.abs(to - from), height - Math.min(from, to));
220
+ const y = Math.max(0, startPos);
221
+ plotBandSelection
222
+ .append('rect')
223
+ .attr('x', 0)
224
+ .attr('width', width)
225
+ .attr('y', y)
226
+ .attr('height', Math.min(endPos, height))
227
+ .attr('fill', () => band.color)
228
+ .attr('opacity', () => band.opacity);
229
+ if (band.label.text) {
230
+ const labelPadding = (_e = (_c = band.label) === null || _c === void 0 ? void 0 : _c.padding) !== null && _e !== void 0 ? _e : 0;
231
+ plotBandSelection
232
+ .append('text')
233
+ .text(band.label.text)
234
+ .style('fill', () => { var _a, _b; return (_b = (_a = band.label.style) === null || _a === void 0 ? void 0 : _a.fontColor) !== null && _b !== void 0 ? _b : null; })
235
+ .style('font-size', () => { var _a, _b; return (_b = (_a = band.label.style) === null || _a === void 0 ? void 0 : _a.fontSize) !== null && _b !== void 0 ? _b : null; })
236
+ .style('font-weight', () => { var _a, _b; return (_b = (_a = band.label.style) === null || _a === void 0 ? void 0 : _a.fontWeight) !== null && _b !== void 0 ? _b : null; })
237
+ .style('dominant-baseline', 'text-before-edge')
238
+ .attr('x', labelPadding)
239
+ .attr('y', y + labelPadding);
240
+ }
241
+ });
219
242
  };
220
243
  setPlotBands(plotBeforeContainer, d.plotBands.filter((item) => item.layerPlacement === 'before'));
221
244
  setPlotBands(plotAfterContainer, d.plotBands.filter((item) => item.layerPlacement === 'after'));
@@ -234,20 +257,32 @@ export const AxisY = (props) => {
234
257
  .attr(plotDataAttr, 1)
235
258
  .attr(plotLineDataAttr, 1)
236
259
  .style('transform', getAxisPlotsPosition(d, split));
237
- plotLinesSelection
238
- .append('path')
239
- .attr('d', (plotLine) => {
260
+ plotLinesSelection.each(function () {
261
+ const itemSelection = select(this);
262
+ const plotLine = itemSelection.datum();
240
263
  const plotLineValue = Number(axisScale(plotLine.value));
241
264
  const points = [
242
265
  [0, plotLineValue],
243
266
  [width, plotLineValue],
244
267
  ];
245
- return lineGenerator(points);
246
- })
247
- .attr('stroke', (plotLine) => plotLine.color)
248
- .attr('stroke-width', (plotLine) => plotLine.width)
249
- .attr('stroke-dasharray', (plotLine) => getLineDashArray(plotLine.dashStyle, plotLine.width))
250
- .attr('opacity', (plotLine) => plotLine.opacity);
268
+ itemSelection
269
+ .append('path')
270
+ .attr('d', lineGenerator(points))
271
+ .attr('stroke', plotLine.color)
272
+ .attr('stroke-width', plotLine.width)
273
+ .attr('stroke-dasharray', getLineDashArray(plotLine.dashStyle, plotLine.width))
274
+ .attr('opacity', plotLine.opacity);
275
+ if (plotLine.label.text) {
276
+ itemSelection
277
+ .append('text')
278
+ .text(plotLine.label.text)
279
+ .style('fill', () => { var _a; return (_a = plotLine.label.style.fontColor) !== null && _a !== void 0 ? _a : null; })
280
+ .attr('font-size', plotLine.label.style.fontSize)
281
+ .style('font-weight', () => { var _a; return (_a = plotLine.label.style.fontWeight) !== null && _a !== void 0 ? _a : null; })
282
+ .attr('x', plotLine.label.padding)
283
+ .attr('y', plotLineValue - plotLine.label.padding);
284
+ }
285
+ });
251
286
  };
252
287
  setPlotLines(plotBeforeContainer, d.plotLines.filter((item) => item.layerPlacement === 'before'));
253
288
  setPlotLines(plotAfterContainer, d.plotLines.filter((item) => item.layerPlacement === 'after'));
@@ -317,6 +352,7 @@ export const AxisY = (props) => {
317
352
  lineGenerator,
318
353
  plotBeforeRef,
319
354
  plotAfterRef,
355
+ topLimit,
320
356
  ]);
321
357
  return React.createElement("g", { ref: ref, className: b('container') });
322
358
  };
@@ -1,5 +1,6 @@
1
1
  .gcharts-chart {
2
2
  --gcharts-data-labels: var(--g-color-text-secondary);
3
+ --gcharts-shape-border-color: var(--g-color-base-background);
3
4
  position: absolute;
4
5
  inset-block-start: 0;
5
6
  inset-inline-start: 0;
@@ -26,8 +26,8 @@ export function useChartInnerProps(props) {
26
26
  }, [data.series.options]);
27
27
  const [zoomState, setZoomState] = React.useState({});
28
28
  const sortedSeriesData = React.useMemo(() => {
29
- return getSortedSeriesData(data.series.data);
30
- }, [data.series.data]);
29
+ return getSortedSeriesData({ seriesData: data.series.data, yAxes: data.yAxis });
30
+ }, [data.series.data, data.yAxis]);
31
31
  const { zoomedSeriesData, zoomedShapesSeriesData } = React.useMemo(() => {
32
32
  return getZoomedSeriesData({
33
33
  seriesData: sortedSeriesData,
@@ -54,7 +54,7 @@ export function useChartInnerProps(props) {
54
54
  const { preparedSeries, preparedLegend, handleLegendItemClick } = useSeries({
55
55
  colors,
56
56
  legend: data.legend,
57
- originalSeriesData: data.series.data,
57
+ originalSeriesData: sortedSeriesData,
58
58
  seriesData: zoomedSeriesData,
59
59
  seriesOptions: data.series.options,
60
60
  });
@@ -17,7 +17,7 @@ export const DefaultTooltipContent = ({ hovered, xAxis, yAxis, valueFormat, tota
17
17
  var _a;
18
18
  const { data, series, closest } = seriesItem;
19
19
  const id = `${get(series, 'id')}_${i}`;
20
- const color = get(series, 'color');
20
+ const color = get(data, 'color') || get(series, 'color');
21
21
  const active = closest && hovered.length > 1;
22
22
  const striped = (i + 1) % 2 === 0;
23
23
  switch (series.type) {
@@ -3,7 +3,7 @@ import { extent, scaleBand, scaleLinear, scaleLog, scaleUtc } from 'd3';
3
3
  import get from 'lodash/get';
4
4
  import { DEFAULT_AXIS_TYPE, SeriesType } from '../../constants';
5
5
  import { CHART_SERIES_WITH_VOLUME_ON_Y_AXIS, getAxisHeight, getDataCategoryValue, getDefaultMaxXAxisValue, getDefaultMinXAxisValue, getDomainDataXBySeries, getDomainDataYBySeries, getOnlyVisibleSeries, isAxisRelatedSeries, isSeriesWithCategoryValues, } from '../../utils';
6
- import { getBarYLayoutForNumericScale } from '../utils';
6
+ import { getBarYLayoutForNumericScale, groupBarYDataByYValue } from '../utils';
7
7
  const X_AXIS_ZOOM_PADDING = 0.02;
8
8
  function isNumericalArrayData(data) {
9
9
  return data.every((d) => typeof d === 'number' || d === null);
@@ -28,11 +28,19 @@ function getYScaleRange(args) {
28
28
  case 'datetime':
29
29
  case 'linear':
30
30
  case 'logarithmic': {
31
+ let range = [boundsHeight, boundsHeight * axis.maxPadding];
32
+ switch (axis.order) {
33
+ case 'sortDesc':
34
+ case 'reverse': {
35
+ range.reverse();
36
+ }
37
+ }
31
38
  const barYSeries = series.filter((s) => s.type === SeriesType.BarY);
32
39
  if (barYSeries.length) {
40
+ const groupedData = groupBarYDataByYValue(barYSeries, [axis]);
33
41
  const { barSize, dataLength } = getBarYLayoutForNumericScale({
34
42
  plotHeight: boundsHeight - boundsHeight * axis.maxPadding,
35
- series: barYSeries,
43
+ groupedData,
36
44
  seriesOptions: seriesOptions,
37
45
  });
38
46
  if (dataLength > 1) {
@@ -51,12 +59,10 @@ function getYScaleRange(args) {
51
59
  return acc + count;
52
60
  }, 0);
53
61
  const offset = (barSize * Math.max(offsetMultiplier, 1)) / 2;
54
- const start = boundsHeight - offset;
55
- const end = boundsHeight * axis.maxPadding + offset;
56
- return [start, end];
62
+ range = [range[0] - offset, range[1] + offset];
57
63
  }
58
64
  }
59
- return [boundsHeight, boundsHeight * axis.maxPadding];
65
+ return range;
60
66
  }
61
67
  case 'category': {
62
68
  return [boundsHeight, 0];
@@ -151,6 +157,13 @@ export function createXScale(args) {
151
157
  const xAxisZoomPadding = boundsWidth * X_AXIS_ZOOM_PADDING;
152
158
  const xRange = [0, boundsWidth - xAxisMaxPadding];
153
159
  const xRangeZoom = [0 + xAxisZoomPadding, boundsWidth - xAxisZoomPadding];
160
+ switch (axis.order) {
161
+ case 'sortDesc':
162
+ case 'reverse': {
163
+ xRange.reverse();
164
+ xRangeZoom.reverse();
165
+ }
166
+ }
154
167
  switch (xType) {
155
168
  case 'linear':
156
169
  case 'logarithmic': {
@@ -22,6 +22,11 @@ export type PreparedAxisPlotLine = {
22
22
  dashStyle: DashStyle;
23
23
  opacity: number;
24
24
  layerPlacement: PlotLayerPlacement;
25
+ label: {
26
+ text: string;
27
+ style: BaseTextStyle;
28
+ padding: number;
29
+ };
25
30
  };
26
31
  export type PreparedAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines' | 'plotBands'> & {
27
32
  type: ChartAxisType;
@@ -0,0 +1,11 @@
1
+ import type { AxisPlot, ChartYAxis } from '../../types';
2
+ export declare function prepareAxisPlotLabel(d: AxisPlot): {
3
+ text: string;
4
+ style: {
5
+ fontSize: string;
6
+ fontWeight?: string;
7
+ fontColor: string;
8
+ };
9
+ padding: number;
10
+ };
11
+ export declare function getAxisCategories(axis?: ChartYAxis): string[] | undefined;
@@ -0,0 +1,27 @@
1
+ import { ascending, descending, reverse, sort } from 'd3';
2
+ import { DEFAULT_AXIS_LABEL_FONT_SIZE } from '../../constants';
3
+ export function prepareAxisPlotLabel(d) {
4
+ var _a, _b, _c, _d, _e;
5
+ return {
6
+ text: (_b = (_a = d.label) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : '',
7
+ style: Object.assign({ fontSize: DEFAULT_AXIS_LABEL_FONT_SIZE, fontColor: 'var(--g-color-text-secondary)' }, (_c = d.label) === null || _c === void 0 ? void 0 : _c.style),
8
+ padding: (_e = (_d = d.label) === null || _d === void 0 ? void 0 : _d.padding) !== null && _e !== void 0 ? _e : 5,
9
+ };
10
+ }
11
+ export function getAxisCategories(axis) {
12
+ const categories = axis === null || axis === void 0 ? void 0 : axis.categories;
13
+ if (categories) {
14
+ switch (axis.order) {
15
+ case 'reverse': {
16
+ return reverse(categories);
17
+ }
18
+ case 'sortAsc': {
19
+ return sort(categories, (a, b) => ascending(a, b));
20
+ }
21
+ case 'sortDesc': {
22
+ return sort(categories, (a, b) => descending(a, b));
23
+ }
24
+ }
25
+ }
26
+ return categories;
27
+ }
@@ -2,6 +2,7 @@ import get from 'lodash/get';
2
2
  import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, axisCrosshairDefaults, axisLabelsDefaults, xAxisTitleDefaults, } from '../../constants';
3
3
  import { calculateCos, formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsSize, getMaxTickCount, getTicksCount, getXAxisItems, hasOverlappingLabels, wrapText, } from '../../utils';
4
4
  import { createXScale } from '../useAxisScales';
5
+ import { getAxisCategories, prepareAxisPlotLabel } from './utils';
5
6
  async function getLabelSettings({ axis, seriesData, width, autoRotation = true, }) {
6
7
  const scale = createXScale({ axis, series: seriesData, boundsWidth: width });
7
8
  const tickCount = getTicksCount({ axis, range: width });
@@ -69,7 +70,7 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, }) => {
69
70
  maxWidth: get(xAxis, 'labels.maxWidth', axisLabelsDefaults.maxWidth),
70
71
  },
71
72
  lineColor: get(xAxis, 'lineColor'),
72
- categories: get(xAxis, 'categories'),
73
+ categories: getAxisCategories(xAxis),
73
74
  timestamps: get(xAxis, 'timestamps'),
74
75
  title: {
75
76
  text: titleText,
@@ -98,6 +99,7 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, }) => {
98
99
  dashStyle: get(d, 'dashStyle', DASH_STYLE.Solid),
99
100
  opacity: get(d, 'opacity', 1),
100
101
  layerPlacement: get(d, 'layerPlacement', 'before'),
102
+ label: prepareAxisPlotLabel(d),
101
103
  })),
102
104
  plotBands: get(xAxis, 'plotBands', []).map((d) => ({
103
105
  color: get(d, 'color', 'var(--g-color-base-brand)'),
@@ -105,6 +107,7 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, }) => {
105
107
  from: get(d, 'from', 0),
106
108
  to: get(d, 'to', 0),
107
109
  layerPlacement: get(d, 'layerPlacement', 'before'),
110
+ label: prepareAxisPlotLabel(d),
108
111
  })),
109
112
  crosshair: {
110
113
  enabled: get(xAxis, 'crosshair.enabled', axisCrosshairDefaults.enabled),
@@ -116,6 +119,7 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, }) => {
116
119
  opacity: get(xAxis, 'crosshair.opacity', axisCrosshairDefaults.opacity),
117
120
  },
118
121
  visible: get(xAxis, 'visible', true),
122
+ order: xAxis === null || xAxis === void 0 ? void 0 : xAxis.order,
119
123
  };
120
124
  const { height, rotation } = await getLabelSettings({
121
125
  axis: preparedXAxis,
@@ -2,6 +2,7 @@ import get from 'lodash/get';
2
2
  import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TYPE, axisCrosshairDefaults, axisLabelsDefaults, yAxisTitleDefaults, } from '../../constants';
3
3
  import { formatAxisTickLabel, getClosestPointsRange, getDefaultMinYAxisValue, getHorisontalSvgTextHeight, getLabelsSize, getScaleTicks, isAxisRelatedSeries, wrapText, } from '../../utils';
4
4
  import { createYScale } from '../useAxisScales';
5
+ import { getAxisCategories, prepareAxisPlotLabel } from './utils';
5
6
  const getAxisLabelMaxWidth = async (args) => {
6
7
  const { axis, seriesData, seriesOptions } = args;
7
8
  if (!axis.labels.enabled) {
@@ -78,7 +79,7 @@ export const getPreparedYAxis = ({ height, seriesData, seriesOptions, yAxis, })
78
79
  maxWidth: get(axisItem, 'labels.maxWidth', axisLabelsDefaults.maxWidth),
79
80
  },
80
81
  lineColor: get(axisItem, 'lineColor'),
81
- categories: get(axisItem, 'categories'),
82
+ categories: getAxisCategories(axisItem),
82
83
  timestamps: get(axisItem, 'timestamps'),
83
84
  title: {
84
85
  text: titleText,
@@ -108,6 +109,7 @@ export const getPreparedYAxis = ({ height, seriesData, seriesOptions, yAxis, })
108
109
  dashStyle: get(d, 'dashStyle', DASH_STYLE.Solid),
109
110
  opacity: get(d, 'opacity', 1),
110
111
  layerPlacement: get(d, 'layerPlacement', 'before'),
112
+ label: prepareAxisPlotLabel(d),
111
113
  })),
112
114
  plotBands: get(axisItem, 'plotBands', []).map((d) => ({
113
115
  color: get(d, 'color', 'var(--g-color-base-brand)'),
@@ -115,6 +117,7 @@ export const getPreparedYAxis = ({ height, seriesData, seriesOptions, yAxis, })
115
117
  from: get(d, 'from', 0),
116
118
  to: get(d, 'to', 0),
117
119
  layerPlacement: get(d, 'layerPlacement', 'before'),
120
+ label: prepareAxisPlotLabel(d),
118
121
  })),
119
122
  crosshair: {
120
123
  enabled: get(axisItem, 'crosshair.enabled', axisCrosshairDefaults.enabled),
@@ -126,6 +129,7 @@ export const getPreparedYAxis = ({ height, seriesData, seriesOptions, yAxis, })
126
129
  opacity: get(axisItem, 'crosshair.opacity', axisCrosshairDefaults.opacity),
127
130
  },
128
131
  visible: get(axisItem, 'visible', true),
132
+ order: axisItem.order,
129
133
  };
130
134
  if (labelsEnabled) {
131
135
  preparedAxis.labels.width = await getAxisLabelMaxWidth({
@@ -6,8 +6,8 @@ export declare const DEFAULT_MARKER: {
6
6
  enabled: boolean;
7
7
  symbol: `${import("../../constants").SymbolType}`;
8
8
  radius: number;
9
- borderColor: string;
10
9
  borderWidth: number;
10
+ borderColor: string;
11
11
  };
12
12
  type PrepareAreaSeriesArgs = {
13
13
  colorScale: ScaleOrdinal<string, string>;
@@ -20,8 +20,11 @@ export declare function prepareBarYSeries(args: PrepareBarYSeriesArgs): Promise<
20
20
  maxWidth: number;
21
21
  html: boolean;
22
22
  format?: import("../../types").ValueFormat;
23
+ allowOverlap: boolean;
23
24
  };
24
25
  borderRadius: number;
26
+ borderWidth: number;
27
+ borderColor: string;
25
28
  } & {
26
29
  color: string;
27
30
  name: string;
@@ -4,7 +4,7 @@ import { getLabelsSize, getUniqId } from '../../utils';
4
4
  import { getFormattedValue } from '../../utils/chart/format';
5
5
  import { getSeriesStackId, prepareLegendSymbol } from './utils';
6
6
  async function prepareDataLabels(series) {
7
- var _a, _b;
7
+ var _a, _b, _c, _d;
8
8
  const enabled = get(series, 'dataLabels.enabled', false);
9
9
  const style = Object.assign({}, DEFAULT_DATALABELS_STYLE, (_a = series.dataLabels) === null || _a === void 0 ? void 0 : _a.style);
10
10
  const html = get(series, 'dataLabels.html', false);
@@ -25,12 +25,13 @@ async function prepareDataLabels(series) {
25
25
  maxWidth,
26
26
  html,
27
27
  format: (_b = series.dataLabels) === null || _b === void 0 ? void 0 : _b.format,
28
+ allowOverlap: (_d = (_c = series.dataLabels) === null || _c === void 0 ? void 0 : _c.allowOverlap) !== null && _d !== void 0 ? _d : false,
28
29
  };
29
30
  }
30
31
  export function prepareBarYSeries(args) {
31
32
  const { colorScale, series: seriesList, seriesOptions, legend } = args;
32
33
  return Promise.all(seriesList.map(async (series) => {
33
- var _a, _b, _c;
34
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
34
35
  const name = series.name || '';
35
36
  const color = series.color || colorScale(name);
36
37
  return {
@@ -49,6 +50,8 @@ export function prepareBarYSeries(args) {
49
50
  dataLabels: await prepareDataLabels(series),
50
51
  cursor: get(series, 'cursor', null),
51
52
  borderRadius: (_c = (_a = series.borderRadius) !== null && _a !== void 0 ? _a : (_b = seriesOptions === null || seriesOptions === void 0 ? void 0 : seriesOptions['bar-y']) === null || _b === void 0 ? void 0 : _b.borderRadius) !== null && _c !== void 0 ? _c : 0,
53
+ borderWidth: (_f = (_d = series.borderWidth) !== null && _d !== void 0 ? _d : (_e = seriesOptions === null || seriesOptions === void 0 ? void 0 : seriesOptions['bar-y']) === null || _e === void 0 ? void 0 : _e.borderWidth) !== null && _f !== void 0 ? _f : 0,
54
+ borderColor: (_j = (_g = series.borderColor) !== null && _g !== void 0 ? _g : (_h = seriesOptions === null || seriesOptions === void 0 ? void 0 : seriesOptions['bar-y']) === null || _h === void 0 ? void 0 : _h.borderColor) !== null && _j !== void 0 ? _j : 'var(--gcharts-shape-border-color)',
52
55
  };
53
56
  }));
54
57
  }
@@ -8,8 +8,8 @@ export declare const DEFAULT_MARKER: {
8
8
  enabled: boolean;
9
9
  symbol: `${import("../../constants").SymbolType}`;
10
10
  radius: number;
11
- borderColor: string;
12
11
  borderWidth: number;
12
+ borderColor: string;
13
13
  };
14
14
  type PrepareLineSeriesArgs = {
15
15
  colorScale: ScaleOrdinal<string, string>;
@@ -10,8 +10,8 @@ export declare const DEFAULT_MARKER: {
10
10
  enabled: boolean;
11
11
  radius: number;
12
12
  symbol: `${import("../../constants").SymbolType}`;
13
- borderColor: string;
14
13
  borderWidth: number;
14
+ borderColor: string;
15
15
  };
16
16
  export declare function prepareRadarSeries(args: PrepareRadarSeriesArgs): PreparedRadarSeries[];
17
17
  export {};
@@ -130,8 +130,11 @@ export type PreparedBarYSeries = {
130
130
  maxWidth: number;
131
131
  html: boolean;
132
132
  format?: ValueFormat;
133
+ allowOverlap: boolean;
133
134
  };
134
135
  borderRadius: number;
136
+ borderWidth: number;
137
+ borderColor: string;
135
138
  } & BasePreparedSeries;
136
139
  export type PreparedPieSeries = {
137
140
  type: PieSeries['type'];