@gravity-ui/charts 1.12.0 → 1.13.1

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 (75) 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/constants/defaults/series-options.d.ts +3 -1
  7. package/dist/cjs/constants/defaults/series-options.js +2 -0
  8. package/dist/cjs/hooks/useAxisScales/index.js +19 -6
  9. package/dist/cjs/hooks/useChartOptions/types.d.ts +5 -0
  10. package/dist/cjs/hooks/useChartOptions/utils.d.ts +11 -0
  11. package/dist/cjs/hooks/useChartOptions/utils.js +27 -0
  12. package/dist/cjs/hooks/useChartOptions/x-axis.js +5 -1
  13. package/dist/cjs/hooks/useChartOptions/y-axis.js +5 -1
  14. package/dist/cjs/hooks/useSeries/prepare-area.d.ts +1 -1
  15. package/dist/cjs/hooks/useSeries/prepare-bar-y.d.ts +3 -0
  16. package/dist/cjs/hooks/useSeries/prepare-bar-y.js +5 -2
  17. package/dist/cjs/hooks/useSeries/prepare-line.d.ts +1 -1
  18. package/dist/cjs/hooks/useSeries/prepare-radar.d.ts +1 -1
  19. package/dist/cjs/hooks/useSeries/types.d.ts +3 -0
  20. package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +24 -15
  21. package/dist/cjs/hooks/useShapes/bar-y/index.d.ts +2 -2
  22. package/dist/cjs/hooks/useShapes/bar-y/index.js +5 -9
  23. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.d.ts +2 -2
  24. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +86 -61
  25. package/dist/cjs/hooks/useShapes/bar-y/types.d.ts +7 -2
  26. package/dist/cjs/hooks/useShapes/index.js +1 -1
  27. package/dist/cjs/hooks/utils/bar-y.d.ts +3 -3
  28. package/dist/cjs/hooks/utils/bar-y.js +7 -21
  29. package/dist/cjs/types/chart/axis.d.ts +13 -1
  30. package/dist/cjs/types/chart/bar-y.d.ts +10 -0
  31. package/dist/cjs/types/chart/series.d.ts +20 -0
  32. package/dist/cjs/utils/chart/axis-generators/bottom.js +26 -13
  33. package/dist/cjs/utils/chart/get-closest-data.js +13 -12
  34. package/dist/cjs/utils/chart/index.js +1 -1
  35. package/dist/cjs/utils/chart/series/sorting.d.ts +6 -2
  36. package/dist/cjs/utils/chart/series/sorting.js +29 -4
  37. package/dist/cjs/utils/chart/zoom.js +2 -1
  38. package/dist/esm/components/Axis/AxisX.js +62 -36
  39. package/dist/esm/components/Axis/AxisY.js +67 -31
  40. package/dist/esm/components/ChartInner/styles.css +1 -0
  41. package/dist/esm/components/ChartInner/useChartInnerProps.js +3 -3
  42. package/dist/esm/components/Tooltip/DefaultTooltipContent/index.js +1 -1
  43. package/dist/esm/constants/defaults/series-options.d.ts +3 -1
  44. package/dist/esm/constants/defaults/series-options.js +2 -0
  45. package/dist/esm/hooks/useAxisScales/index.js +19 -6
  46. package/dist/esm/hooks/useChartOptions/types.d.ts +5 -0
  47. package/dist/esm/hooks/useChartOptions/utils.d.ts +11 -0
  48. package/dist/esm/hooks/useChartOptions/utils.js +27 -0
  49. package/dist/esm/hooks/useChartOptions/x-axis.js +5 -1
  50. package/dist/esm/hooks/useChartOptions/y-axis.js +5 -1
  51. package/dist/esm/hooks/useSeries/prepare-area.d.ts +1 -1
  52. package/dist/esm/hooks/useSeries/prepare-bar-y.d.ts +3 -0
  53. package/dist/esm/hooks/useSeries/prepare-bar-y.js +5 -2
  54. package/dist/esm/hooks/useSeries/prepare-line.d.ts +1 -1
  55. package/dist/esm/hooks/useSeries/prepare-radar.d.ts +1 -1
  56. package/dist/esm/hooks/useSeries/types.d.ts +3 -0
  57. package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +24 -15
  58. package/dist/esm/hooks/useShapes/bar-y/index.d.ts +2 -2
  59. package/dist/esm/hooks/useShapes/bar-y/index.js +5 -9
  60. package/dist/esm/hooks/useShapes/bar-y/prepare-data.d.ts +2 -2
  61. package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +86 -61
  62. package/dist/esm/hooks/useShapes/bar-y/types.d.ts +7 -2
  63. package/dist/esm/hooks/useShapes/index.js +1 -1
  64. package/dist/esm/hooks/utils/bar-y.d.ts +3 -3
  65. package/dist/esm/hooks/utils/bar-y.js +7 -21
  66. package/dist/esm/types/chart/axis.d.ts +13 -1
  67. package/dist/esm/types/chart/bar-y.d.ts +10 -0
  68. package/dist/esm/types/chart/series.d.ts +20 -0
  69. package/dist/esm/utils/chart/axis-generators/bottom.js +26 -13
  70. package/dist/esm/utils/chart/get-closest-data.js +13 -12
  71. package/dist/esm/utils/chart/index.js +1 -1
  72. package/dist/esm/utils/chart/series/sorting.d.ts +6 -2
  73. package/dist/esm/utils/chart/series/sorting.js +29 -4
  74. package/dist/esm/utils/chart/zoom.js +2 -1
  75. package/package.json +1 -1
@@ -79,6 +79,11 @@ export interface ChartSeriesOptions {
79
79
  * @default 0
80
80
  */
81
81
  borderRadius?: number;
82
+ /**
83
+ * The distance between the shapes of the stacked values, in pixels.
84
+ * @default 1
85
+ */
86
+ stackGap?: number;
82
87
  dataSorting?: {
83
88
  /** Determines what data value should be used to sort by.
84
89
  * Possible values are undefined to disable, "name" to sort by series name or "y"
@@ -115,11 +120,26 @@ export interface ChartSeriesOptions {
115
120
  * @default 0.2
116
121
  */
117
122
  groupPadding?: number;
123
+ /**
124
+ * The width of the border surrounding each bar.
125
+ *
126
+ * @default 0
127
+ */
128
+ borderWidth?: number;
129
+ /**
130
+ * The color of the border surrounding each bar.
131
+ */
132
+ borderColor?: string;
118
133
  /**
119
134
  * The corner radius of the border surrounding each bar.
120
135
  * @default 0
121
136
  */
122
137
  borderRadius?: number;
138
+ /**
139
+ * The distance between the shapes of the stacked values, in pixels.
140
+ * @default 1
141
+ */
142
+ stackGap?: number;
123
143
  dataSorting?: {
124
144
  /** Determines what data value should be used to sort by.
125
145
  * Possible values are undefined to disable, "name" to sort by series name or "x"
@@ -93,18 +93,31 @@ export async function axisBottom(args) {
93
93
  let elementX = 0;
94
94
  // add an ellipsis to the labels that go beyond the boundaries of the chart
95
95
  // and remove overlapping labels
96
- labels.each(function (_d, i, nodes) {
97
- var _a, _b;
98
- const currentElement = this;
99
- const currentElementPosition = currentElement.getBoundingClientRect();
96
+ labels
97
+ .nodes()
98
+ .map((element) => {
99
+ const r = element.getBoundingClientRect();
100
+ return {
101
+ left: r.left,
102
+ right: r.right,
103
+ node: element,
104
+ };
105
+ }, {})
106
+ .sort((a, b) => {
107
+ return a.left - b.left;
108
+ })
109
+ .forEach(function (item, i, nodes) {
110
+ var _a, _b, _c, _d;
111
+ const { node, left, right: currentElementPositionRigth } = item;
112
+ const currentElement = node;
100
113
  if (i === 0) {
101
114
  const text = select(currentElement);
102
- const nextElement = nodes[i + 1];
115
+ const nextElement = (_a = nodes[i + 1]) === null || _a === void 0 ? void 0 : _a.node;
103
116
  const nextElementPosition = nextElement === null || nextElement === void 0 ? void 0 : nextElement.getBoundingClientRect();
104
- if (currentElementPosition.left < leftmostLimit) {
105
- const rightmostPossiblePoint = (_a = nextElementPosition === null || nextElementPosition === void 0 ? void 0 : nextElementPosition.left) !== null && _a !== void 0 ? _a : right;
117
+ if (left < leftmostLimit) {
118
+ const rightmostPossiblePoint = (_b = nextElementPosition === null || nextElementPosition === void 0 ? void 0 : nextElementPosition.left) !== null && _b !== void 0 ? _b : right;
106
119
  const remainSpace = rightmostPossiblePoint -
107
- currentElementPosition.right +
120
+ currentElementPositionRigth +
108
121
  x -
109
122
  labelsMargin;
110
123
  text.attr('text-anchor', 'start');
@@ -112,16 +125,16 @@ export async function axisBottom(args) {
112
125
  }
113
126
  }
114
127
  else {
115
- if (currentElementPosition.left < elementX) {
116
- (_b = currentElement.closest('.tick')) === null || _b === void 0 ? void 0 : _b.remove();
128
+ if (left < elementX) {
129
+ (_c = currentElement.closest('.tick')) === null || _c === void 0 ? void 0 : _c.remove();
117
130
  return;
118
131
  }
119
- elementX = currentElementPosition.right + labelsPaddings;
132
+ elementX = currentElementPositionRigth + labelsPaddings;
120
133
  if (i === nodes.length - 1) {
121
- const prevElement = nodes[i - 1];
134
+ const prevElement = (_d = nodes[i - 1]) === null || _d === void 0 ? void 0 : _d.node;
122
135
  const text = select(currentElement);
123
136
  const prevElementPosition = prevElement === null || prevElement === void 0 ? void 0 : prevElement.getBoundingClientRect();
124
- const lackingSpace = Math.max(0, currentElementPosition.right - right);
137
+ const lackingSpace = Math.max(0, currentElementPositionRigth - right);
125
138
  if (lackingSpace) {
126
139
  const remainSpace = right - ((prevElementPosition === null || prevElementPosition === void 0 ? void 0 : prevElementPosition.right) || 0) - labelsPaddings;
127
140
  const translateX = -lackingSpace;
@@ -49,7 +49,7 @@ export function getClosestPoints(args) {
49
49
  const groups = groupBy(shapesData, getSeriesType);
50
50
  // eslint-disable-next-line complexity
51
51
  Object.entries(groups).forEach(([seriesType, list]) => {
52
- var _a, _b;
52
+ var _a, _b, _c;
53
53
  switch (seriesType) {
54
54
  case 'bar-x': {
55
55
  const points = list.map((d) => ({
@@ -106,26 +106,27 @@ export function getClosestPoints(args) {
106
106
  const points = list;
107
107
  const sorted = sort(points, (p) => p.y);
108
108
  const closestYIndex = bisector((p) => p.y).center(sorted, pointerY);
109
- let closestPoints = [];
110
- let closestXIndex = -1;
111
- if (closestYIndex !== -1) {
112
- const closestY = sorted[closestYIndex].y;
113
- closestPoints = sort(points.filter((p) => p.y === closestY), (p) => p.x);
109
+ const closestYPoint = sorted[closestYIndex];
110
+ let selectedPoints = [];
111
+ let closestPointXValue = -1;
112
+ if (closestYPoint) {
113
+ selectedPoints = points.filter((p) => p.data.y === closestYPoint.data.y);
114
+ const closestPoints = sort(selectedPoints.filter((p) => p.y === closestYPoint.y), (p) => p.x);
114
115
  const lastPoint = closestPoints[closestPoints.length - 1];
115
116
  if (pointerX < ((_a = closestPoints[0]) === null || _a === void 0 ? void 0 : _a.x)) {
116
- closestXIndex = 0;
117
+ closestPointXValue = closestPoints[0].x;
117
118
  }
118
119
  else if (lastPoint && pointerX > lastPoint.x + lastPoint.width) {
119
- closestXIndex = closestPoints.length - 1;
120
+ closestPointXValue = lastPoint.x;
120
121
  }
121
122
  else {
122
- closestXIndex = closestPoints.findIndex((p) => pointerX > p.x && pointerX < p.x + p.width);
123
+ closestPointXValue = (_b = closestPoints.find((p) => pointerX > p.x && pointerX < p.x + p.width)) === null || _b === void 0 ? void 0 : _b.x;
123
124
  }
124
125
  }
125
- result.push(...closestPoints.map((p, i) => ({
126
+ result.push(...selectedPoints.map((p) => ({
126
127
  data: p.data,
127
128
  series: p.series,
128
- closest: i === closestXIndex,
129
+ closest: p.x === closestPointXValue && p.y === closestYPoint.y,
129
130
  })));
130
131
  break;
131
132
  }
@@ -164,7 +165,7 @@ export function getClosestPoints(args) {
164
165
  }
165
166
  case 'treemap': {
166
167
  const data = list;
167
- const closestPoint = (_b = data[0]) === null || _b === void 0 ? void 0 : _b.leaves.find((l) => {
168
+ const closestPoint = (_c = data[0]) === null || _c === void 0 ? void 0 : _c.leaves.find((l) => {
168
169
  return (pointerX >= l.x0 && pointerX <= l.x1 && pointerY >= l.y0 && pointerY <= l.y1);
169
170
  });
170
171
  if (closestPoint) {
@@ -238,5 +238,5 @@ export function getClosestPointsRange(axis, points) {
238
238
  if (axis.type === 'category') {
239
239
  return undefined;
240
240
  }
241
- return points[1] - points[0];
241
+ return Math.abs(points[1] - points[0]);
242
242
  }
@@ -1,2 +1,6 @@
1
- import type { ChartSeries } from '../../../types';
2
- export declare function getSortedSeriesData(seriesData: ChartSeries[]): ChartSeries[];
1
+ import type { ChartAxis, ChartSeries } from '../../../types';
2
+ export declare function getSortedSeriesData({ seriesData, yAxes, xAxis, }: {
3
+ seriesData: ChartSeries[];
4
+ yAxes?: ChartAxis[];
5
+ xAxis?: ChartAxis;
6
+ }): ChartSeries[];
@@ -1,12 +1,37 @@
1
1
  import { sort } from 'd3';
2
+ import { isEmpty } from 'lodash';
3
+ import get from 'lodash/get';
2
4
  import { SeriesType } from '../../../constants';
3
- export function getSortedSeriesData(seriesData) {
5
+ import { getAxisCategories } from '../../../hooks/useChartOptions/utils';
6
+ function applyAxisCategoriesOrder({ series, axis, key, }) {
7
+ var _a, _b;
8
+ const originalCategories = (_a = axis === null || axis === void 0 ? void 0 : axis.categories) !== null && _a !== void 0 ? _a : [];
9
+ if (isEmpty(originalCategories)) {
10
+ return series;
11
+ }
12
+ const axisCategories = (_b = getAxisCategories(axis)) !== null && _b !== void 0 ? _b : [];
13
+ const order = Object.fromEntries(axisCategories.map((value, index) => [value, index]));
14
+ const newSeriesData = series.data.map((d) => {
15
+ const value = get(d, key);
16
+ if (typeof value === 'number') {
17
+ return Object.assign(Object.assign({}, d), { [key]: order[originalCategories[value]] });
18
+ }
19
+ return d;
20
+ });
21
+ return Object.assign(Object.assign({}, series), { data: newSeriesData });
22
+ }
23
+ export function getSortedSeriesData({ seriesData, yAxes, xAxis, }) {
4
24
  return seriesData.map((s) => {
5
- switch (s.type) {
25
+ const yAxis = yAxes === null || yAxes === void 0 ? void 0 : yAxes[0];
26
+ let sortedSeries = s;
27
+ sortedSeries = applyAxisCategoriesOrder({ series: sortedSeries, axis: yAxis, key: 'y' });
28
+ sortedSeries = applyAxisCategoriesOrder({ series: sortedSeries, axis: xAxis, key: 'x' });
29
+ switch (sortedSeries.type) {
6
30
  case SeriesType.Area: {
7
- s.data = sort(s.data, (d) => d.x);
31
+ sortedSeries = Object.assign(Object.assign({}, sortedSeries), { data: sort(sortedSeries.data, (d) => d.x) });
32
+ break;
8
33
  }
9
34
  }
10
- return s;
35
+ return sortedSeries;
11
36
  });
12
37
  }
@@ -1,4 +1,5 @@
1
1
  import { SeriesType } from '../../constants';
2
+ import { getAxisCategories } from '../../hooks/useChartOptions/utils';
2
3
  const SERIES_TYPE_WITH_HIDDEN_POINTS = [SeriesType.Area, SeriesType.Line];
3
4
  // eslint-disable-next-line complexity
4
5
  function isValueInRange(args) {
@@ -20,7 +21,7 @@ function isValueInRange(args) {
20
21
  return numValue >= numMin && numValue <= numMax;
21
22
  }
22
23
  case 'category': {
23
- const categories = (axis === null || axis === void 0 ? void 0 : axis.categories) || [];
24
+ const categories = getAxisCategories(axis) || [];
24
25
  if (typeof value === 'string' && typeof min === 'number' && typeof max === 'number') {
25
26
  const valueIndex = categories.indexOf(value);
26
27
  if (min === -1 || max === -1 || valueIndex === -1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/charts",
3
- "version": "1.12.0",
3
+ "version": "1.13.1",
4
4
  "description": "React component used to render charts",
5
5
  "license": "MIT",
6
6
  "main": "dist/cjs/index.js",