@gravity-ui/charts 1.11.4 → 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 (135) 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 +15 -9
  5. package/dist/cjs/components/Tooltip/ChartTooltipContent.d.ts +1 -0
  6. package/dist/cjs/components/Tooltip/ChartTooltipContent.js +3 -3
  7. package/dist/cjs/components/Tooltip/DefaultTooltipContent/Row.d.ts +9 -0
  8. package/dist/cjs/components/Tooltip/DefaultTooltipContent/Row.js +10 -0
  9. package/dist/cjs/components/Tooltip/DefaultTooltipContent/RowTotals.d.ts +9 -0
  10. package/dist/cjs/components/Tooltip/DefaultTooltipContent/RowTotals.js +23 -0
  11. package/dist/cjs/components/Tooltip/DefaultTooltipContent/index.d.ts +11 -0
  12. package/dist/cjs/components/Tooltip/DefaultTooltipContent/index.js +102 -0
  13. package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.d.ts +30 -0
  14. package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.js +126 -0
  15. package/dist/cjs/components/Tooltip/index.js +1 -1
  16. package/dist/cjs/components/Tooltip/styles.css +14 -2
  17. package/dist/cjs/components/Tooltip/utils.d.ts +30 -0
  18. package/dist/cjs/components/Tooltip/utils.js +126 -0
  19. package/dist/cjs/constants/axis.d.ts +6 -0
  20. package/dist/cjs/constants/axis.js +6 -0
  21. package/dist/cjs/constants/index.d.ts +6 -4
  22. package/dist/cjs/constants/index.js +6 -4
  23. package/dist/cjs/constants/tooltip.d.ts +3 -0
  24. package/dist/cjs/constants/tooltip.js +3 -0
  25. package/dist/cjs/hooks/useAxisScales/index.d.ts +14 -3
  26. package/dist/cjs/hooks/useAxisScales/index.js +86 -22
  27. package/dist/cjs/hooks/useChartOptions/types.d.ts +5 -0
  28. package/dist/cjs/hooks/useChartOptions/utils.d.ts +11 -0
  29. package/dist/cjs/hooks/useChartOptions/utils.js +27 -0
  30. package/dist/cjs/hooks/useChartOptions/x-axis.js +6 -2
  31. package/dist/cjs/hooks/useChartOptions/y-axis.d.ts +4 -2
  32. package/dist/cjs/hooks/useChartOptions/y-axis.js +14 -4
  33. package/dist/cjs/hooks/useSeries/prepare-area.d.ts +1 -1
  34. package/dist/cjs/hooks/useSeries/prepare-bar-y.d.ts +3 -0
  35. package/dist/cjs/hooks/useSeries/prepare-bar-y.js +5 -2
  36. package/dist/cjs/hooks/useSeries/prepare-line.d.ts +1 -1
  37. package/dist/cjs/hooks/useSeries/prepare-radar.d.ts +1 -1
  38. package/dist/cjs/hooks/useSeries/types.d.ts +3 -0
  39. package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +16 -13
  40. package/dist/cjs/hooks/useShapes/bar-y/index.d.ts +2 -2
  41. package/dist/cjs/hooks/useShapes/bar-y/index.js +5 -9
  42. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.d.ts +2 -2
  43. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +80 -107
  44. package/dist/cjs/hooks/useShapes/bar-y/types.d.ts +7 -2
  45. package/dist/cjs/hooks/useShapes/index.js +1 -1
  46. package/dist/cjs/hooks/useShapes/waterfall/prepare-data.js +1 -1
  47. package/dist/cjs/hooks/utils/bar-y.d.ts +27 -0
  48. package/dist/cjs/hooks/utils/bar-y.js +55 -0
  49. package/dist/cjs/hooks/utils/index.d.ts +1 -0
  50. package/dist/cjs/hooks/utils/index.js +1 -0
  51. package/dist/cjs/i18n/keysets/en.json +7 -1
  52. package/dist/cjs/i18n/keysets/ru.json +7 -1
  53. package/dist/cjs/types/chart/axis.d.ts +15 -3
  54. package/dist/cjs/types/chart/bar-y.d.ts +10 -0
  55. package/dist/cjs/types/chart/series.d.ts +10 -0
  56. package/dist/cjs/types/chart/tooltip.d.ts +21 -0
  57. package/dist/cjs/utils/chart/axis-generators/bottom.js +26 -13
  58. package/dist/cjs/utils/chart/get-closest-data.js +13 -12
  59. package/dist/cjs/utils/chart/index.js +1 -1
  60. package/dist/cjs/utils/chart/series/sorting.d.ts +6 -2
  61. package/dist/cjs/utils/chart/series/sorting.js +29 -4
  62. package/dist/cjs/utils/chart/zoom.js +2 -1
  63. package/dist/cjs/validation/index.js +55 -1
  64. package/dist/esm/components/Axis/AxisX.js +62 -36
  65. package/dist/esm/components/Axis/AxisY.js +67 -31
  66. package/dist/esm/components/ChartInner/styles.css +1 -0
  67. package/dist/esm/components/ChartInner/useChartInnerProps.js +15 -9
  68. package/dist/esm/components/Tooltip/ChartTooltipContent.d.ts +1 -0
  69. package/dist/esm/components/Tooltip/ChartTooltipContent.js +3 -3
  70. package/dist/esm/components/Tooltip/DefaultTooltipContent/Row.d.ts +9 -0
  71. package/dist/esm/components/Tooltip/DefaultTooltipContent/Row.js +10 -0
  72. package/dist/esm/components/Tooltip/DefaultTooltipContent/RowTotals.d.ts +9 -0
  73. package/dist/esm/components/Tooltip/DefaultTooltipContent/RowTotals.js +23 -0
  74. package/dist/esm/components/Tooltip/DefaultTooltipContent/index.d.ts +11 -0
  75. package/dist/esm/components/Tooltip/DefaultTooltipContent/index.js +102 -0
  76. package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.d.ts +30 -0
  77. package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.js +126 -0
  78. package/dist/esm/components/Tooltip/index.js +1 -1
  79. package/dist/esm/components/Tooltip/styles.css +14 -2
  80. package/dist/esm/components/Tooltip/utils.d.ts +30 -0
  81. package/dist/esm/components/Tooltip/utils.js +126 -0
  82. package/dist/esm/constants/axis.d.ts +6 -0
  83. package/dist/esm/constants/axis.js +6 -0
  84. package/dist/esm/constants/index.d.ts +6 -4
  85. package/dist/esm/constants/index.js +6 -4
  86. package/dist/esm/constants/tooltip.d.ts +3 -0
  87. package/dist/esm/constants/tooltip.js +3 -0
  88. package/dist/esm/hooks/useAxisScales/index.d.ts +14 -3
  89. package/dist/esm/hooks/useAxisScales/index.js +86 -22
  90. package/dist/esm/hooks/useChartOptions/types.d.ts +5 -0
  91. package/dist/esm/hooks/useChartOptions/utils.d.ts +11 -0
  92. package/dist/esm/hooks/useChartOptions/utils.js +27 -0
  93. package/dist/esm/hooks/useChartOptions/x-axis.js +6 -2
  94. package/dist/esm/hooks/useChartOptions/y-axis.d.ts +4 -2
  95. package/dist/esm/hooks/useChartOptions/y-axis.js +14 -4
  96. package/dist/esm/hooks/useSeries/prepare-area.d.ts +1 -1
  97. package/dist/esm/hooks/useSeries/prepare-bar-y.d.ts +3 -0
  98. package/dist/esm/hooks/useSeries/prepare-bar-y.js +5 -2
  99. package/dist/esm/hooks/useSeries/prepare-line.d.ts +1 -1
  100. package/dist/esm/hooks/useSeries/prepare-radar.d.ts +1 -1
  101. package/dist/esm/hooks/useSeries/types.d.ts +3 -0
  102. package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +16 -13
  103. package/dist/esm/hooks/useShapes/bar-y/index.d.ts +2 -2
  104. package/dist/esm/hooks/useShapes/bar-y/index.js +5 -9
  105. package/dist/esm/hooks/useShapes/bar-y/prepare-data.d.ts +2 -2
  106. package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +80 -107
  107. package/dist/esm/hooks/useShapes/bar-y/types.d.ts +7 -2
  108. package/dist/esm/hooks/useShapes/index.js +1 -1
  109. package/dist/esm/hooks/useShapes/waterfall/prepare-data.js +1 -1
  110. package/dist/esm/hooks/utils/bar-y.d.ts +27 -0
  111. package/dist/esm/hooks/utils/bar-y.js +55 -0
  112. package/dist/esm/hooks/utils/index.d.ts +1 -0
  113. package/dist/esm/hooks/utils/index.js +1 -0
  114. package/dist/esm/i18n/keysets/en.json +7 -1
  115. package/dist/esm/i18n/keysets/ru.json +7 -1
  116. package/dist/esm/types/chart/axis.d.ts +15 -3
  117. package/dist/esm/types/chart/bar-y.d.ts +10 -0
  118. package/dist/esm/types/chart/series.d.ts +10 -0
  119. package/dist/esm/types/chart/tooltip.d.ts +21 -0
  120. package/dist/esm/utils/chart/axis-generators/bottom.js +26 -13
  121. package/dist/esm/utils/chart/get-closest-data.js +13 -12
  122. package/dist/esm/utils/chart/index.js +1 -1
  123. package/dist/esm/utils/chart/series/sorting.d.ts +6 -2
  124. package/dist/esm/utils/chart/series/sorting.js +29 -4
  125. package/dist/esm/utils/chart/zoom.js +2 -1
  126. package/dist/esm/validation/index.js +55 -1
  127. package/package.json +1 -1
  128. package/dist/cjs/components/Tooltip/DefaultContent.d.ts +0 -10
  129. package/dist/cjs/components/Tooltip/DefaultContent.js +0 -187
  130. package/dist/esm/components/Tooltip/DefaultContent.d.ts +0 -10
  131. package/dist/esm/components/Tooltip/DefaultContent.js +0 -187
  132. /package/dist/cjs/hooks/{useShapes/constants.d.ts → constants.d.ts} +0 -0
  133. /package/dist/cjs/hooks/{useShapes/constants.js → constants.js} +0 -0
  134. /package/dist/esm/hooks/{useShapes/constants.d.ts → constants.d.ts} +0 -0
  135. /package/dist/esm/hooks/{useShapes/constants.js → constants.js} +0 -0
@@ -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;
@@ -21,10 +21,13 @@ export function useChartInnerProps(props) {
21
21
  title: data.title,
22
22
  tooltip: data.tooltip,
23
23
  });
24
+ const preparedSeriesOptions = React.useMemo(() => {
25
+ return getPreparedOptions(data.series.options);
26
+ }, [data.series.options]);
24
27
  const [zoomState, setZoomState] = React.useState({});
25
28
  const sortedSeriesData = React.useMemo(() => {
26
- return getSortedSeriesData(data.series.data);
27
- }, [data.series.data]);
29
+ return getSortedSeriesData({ seriesData: data.series.data, yAxes: data.yAxis });
30
+ }, [data.series.data, data.yAxis]);
28
31
  const { zoomedSeriesData, zoomedShapesSeriesData } = React.useMemo(() => {
29
32
  return getZoomedSeriesData({
30
33
  seriesData: sortedSeriesData,
@@ -41,15 +44,17 @@ export function useChartInnerProps(props) {
41
44
  const [yAxis, setYAxis] = React.useState([]);
42
45
  React.useEffect(() => {
43
46
  setYAxis([]);
44
- getPreparedYAxis({ yAxis: data.yAxis, height, seriesData: zoomedSeriesData }).then((val) => setYAxis(val));
45
- }, [data.yAxis, height, zoomedSeriesData]);
46
- const preparedSeriesOptions = React.useMemo(() => {
47
- return getPreparedOptions(data.series.options);
48
- }, [data.series.options]);
47
+ getPreparedYAxis({
48
+ height,
49
+ seriesData: zoomedSeriesData,
50
+ seriesOptions: preparedSeriesOptions,
51
+ yAxis: data.yAxis,
52
+ }).then((val) => setYAxis(val));
53
+ }, [data.yAxis, height, preparedSeriesOptions, zoomedSeriesData]);
49
54
  const { preparedSeries, preparedLegend, handleLegendItemClick } = useSeries({
50
55
  colors,
51
56
  legend: data.legend,
52
- originalSeriesData: data.series.data,
57
+ originalSeriesData: sortedSeriesData,
53
58
  seriesData: zoomedSeriesData,
54
59
  seriesOptions: data.series.options,
55
60
  });
@@ -89,9 +94,10 @@ export function useChartInnerProps(props) {
89
94
  hasZoomX: Boolean(zoomState.x),
90
95
  hasZoomY: Boolean(zoomState.y),
91
96
  series: preparedSeries,
97
+ seriesOptions: preparedSeriesOptions,
98
+ split: preparedSplit,
92
99
  xAxis,
93
100
  yAxis,
94
- split: preparedSplit,
95
101
  });
96
102
  const isOutsideBounds = React.useCallback((x, y) => {
97
103
  return x < 0 || x > boundsWidth || y < 0 || y > boundsHeight;
@@ -6,5 +6,6 @@ export interface ChartTooltipContentProps {
6
6
  yAxis?: ChartYAxis;
7
7
  renderer?: ChartTooltip['renderer'];
8
8
  valueFormat?: ChartTooltip['valueFormat'];
9
+ totals?: ChartTooltip['totals'];
9
10
  }
10
11
  export declare const ChartTooltipContent: (props: ChartTooltipContentProps) => React.JSX.Element | null;
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
2
  import isNil from 'lodash/isNil';
3
- import { DefaultContent } from './DefaultContent';
3
+ import { DefaultTooltipContent } from './DefaultTooltipContent';
4
4
  export const ChartTooltipContent = (props) => {
5
- const { hovered, xAxis, yAxis, renderer, valueFormat } = props;
5
+ const { hovered, xAxis, yAxis, renderer, valueFormat, totals } = props;
6
6
  if (!hovered) {
7
7
  return null;
8
8
  }
9
9
  const customTooltip = renderer === null || renderer === void 0 ? void 0 : renderer({ hovered, xAxis, yAxis });
10
- return isNil(customTooltip) ? (React.createElement(DefaultContent, { hovered: hovered, xAxis: xAxis, yAxis: yAxis, valueFormat: valueFormat })) : (customTooltip);
10
+ return isNil(customTooltip) ? (React.createElement(DefaultTooltipContent, { hovered: hovered, xAxis: xAxis, yAxis: yAxis, valueFormat: valueFormat, totals: totals })) : (customTooltip);
11
11
  };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ export declare function Row(props: {
3
+ label: React.ReactNode;
4
+ value: React.ReactNode;
5
+ active?: boolean;
6
+ className?: string;
7
+ color?: string;
8
+ striped?: boolean;
9
+ }): React.JSX.Element;
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { block } from '../../../utils';
3
+ const b = block('tooltip');
4
+ export function Row(props) {
5
+ const { label, value, active, color, className, striped } = props;
6
+ return (React.createElement("div", { className: b('content-row', { active, striped }, className) },
7
+ color && React.createElement("div", { className: b('content-row-color'), style: { backgroundColor: color } }),
8
+ label,
9
+ React.createElement("span", { className: b('content-row-value') }, value)));
10
+ }
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { ChartTooltipTotalsAggregationValue, ChartTooltipTotalsBuiltInAggregation, ValueFormat } from '../../../types';
3
+ import type { HoveredValue } from './utils';
4
+ export declare function RowTotals(props: {
5
+ aggregation: ChartTooltipTotalsBuiltInAggregation | (() => ChartTooltipTotalsAggregationValue);
6
+ values: HoveredValue[];
7
+ label?: string;
8
+ valueFormat?: ValueFormat;
9
+ }): React.JSX.Element;
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { block } from '../../../utils';
3
+ import { getFormattedValue } from '../../../utils/chart/format';
4
+ import { Row } from './Row';
5
+ import { getBuiltInAggregatedValue, getBuiltInAggregationLabel } from './utils';
6
+ const b = block('tooltip');
7
+ export function RowTotals(props) {
8
+ const { aggregation, label, valueFormat, values } = props;
9
+ let resultLabel = label;
10
+ if (!resultLabel && typeof aggregation === 'string') {
11
+ resultLabel = getBuiltInAggregationLabel({ aggregation });
12
+ }
13
+ const resultValue = typeof aggregation === 'function'
14
+ ? aggregation()
15
+ : getBuiltInAggregatedValue({ aggregation, values });
16
+ const formattedResultValue = typeof resultValue === 'number'
17
+ ? getFormattedValue({
18
+ value: resultValue,
19
+ format: valueFormat || { type: 'number' },
20
+ })
21
+ : resultValue;
22
+ return (React.createElement(Row, { className: b('content-row-totals'), label: resultLabel, value: formattedResultValue }));
23
+ }
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import type { ChartTooltip, ChartXAxis, ChartYAxis, TooltipDataChunk, ValueFormat } from '../../../types';
3
+ type Props = {
4
+ hovered: TooltipDataChunk[];
5
+ totals?: ChartTooltip['totals'];
6
+ valueFormat?: ValueFormat;
7
+ xAxis?: ChartXAxis | null;
8
+ yAxis?: ChartYAxis;
9
+ };
10
+ export declare const DefaultTooltipContent: ({ hovered, xAxis, yAxis, valueFormat, totals }: Props) => React.JSX.Element;
11
+ export {};
@@ -0,0 +1,102 @@
1
+ import React from 'react';
2
+ import { Divider } from '@gravity-ui/uikit';
3
+ import get from 'lodash/get';
4
+ import { block } from '../../../utils';
5
+ import { getFormattedValue } from '../../../utils/chart/format';
6
+ import { Row } from './Row';
7
+ import { RowTotals } from './RowTotals';
8
+ import { getDefaultValueFormat, getHoveredValues, getMeasureValue, getPreparedAggregation, getXRowData, } from './utils';
9
+ const b = block('tooltip');
10
+ export const DefaultTooltipContent = ({ hovered, xAxis, yAxis, valueFormat, totals }) => {
11
+ const measureValue = getMeasureValue({ data: hovered, xAxis, yAxis });
12
+ const hoveredValues = getHoveredValues({ hovered, xAxis, yAxis });
13
+ return (React.createElement("div", { className: b('content') },
14
+ measureValue && React.createElement("div", { className: b('series-name') }, measureValue),
15
+ // eslint-disable-next-line complexity
16
+ hovered.map((seriesItem, i) => {
17
+ var _a;
18
+ const { data, series, closest } = seriesItem;
19
+ const id = `${get(series, 'id')}_${i}`;
20
+ const color = get(data, 'color') || get(series, 'color');
21
+ const active = closest && hovered.length > 1;
22
+ const striped = (i + 1) % 2 === 0;
23
+ switch (series.type) {
24
+ case 'scatter':
25
+ case 'line':
26
+ case 'area':
27
+ case 'bar-x': {
28
+ const format = valueFormat || getDefaultValueFormat({ axis: yAxis });
29
+ const formattedValue = getFormattedValue({
30
+ value: hoveredValues[i],
31
+ format,
32
+ });
33
+ return (React.createElement(Row, { key: id, active: active, color: color, label: series.name, striped: striped, value: formattedValue }));
34
+ }
35
+ case 'waterfall': {
36
+ const isTotal = get(data, 'total', false);
37
+ const subTotalValue = (_a = seriesItem.subTotal) !== null && _a !== void 0 ? _a : 0;
38
+ const format = valueFormat || getDefaultValueFormat({ axis: yAxis });
39
+ const subTotal = getFormattedValue({
40
+ value: subTotalValue,
41
+ format,
42
+ });
43
+ const formattedValue = getFormattedValue({
44
+ value: hoveredValues[i],
45
+ format,
46
+ });
47
+ return (React.createElement(React.Fragment, { key: id },
48
+ !isTotal && (React.createElement(React.Fragment, null,
49
+ React.createElement("div", { className: b('series-name') }, getXRowData(data, xAxis)),
50
+ React.createElement(Row, { label: series.name, value: formattedValue }))),
51
+ React.createElement(Row, { label: isTotal ? 'Total' : 'Subtotal', value: subTotal })));
52
+ }
53
+ case 'bar-y': {
54
+ const format = valueFormat || getDefaultValueFormat({ axis: xAxis });
55
+ const formattedValue = getFormattedValue({
56
+ value: hoveredValues[i],
57
+ format,
58
+ });
59
+ return (React.createElement(Row, { key: id, active: active, color: color, label: series.name, striped: striped, value: formattedValue }));
60
+ }
61
+ case 'pie':
62
+ case 'treemap': {
63
+ const seriesData = data;
64
+ const formattedValue = getFormattedValue({
65
+ value: hoveredValues[i],
66
+ format: valueFormat || { type: 'number' },
67
+ });
68
+ return (React.createElement(Row, { key: id, color: color, label: React.createElement("span", { dangerouslySetInnerHTML: {
69
+ __html: [seriesData.name || seriesData.id]
70
+ .flat()
71
+ .join('\n'),
72
+ } }), value: formattedValue }));
73
+ }
74
+ case 'sankey': {
75
+ const { target, data: source } = seriesItem;
76
+ const formattedValue = getFormattedValue({
77
+ value: hoveredValues[i],
78
+ format: valueFormat || { type: 'number' },
79
+ });
80
+ return (React.createElement(Row, { key: id, color: source.color, label: React.createElement("span", null,
81
+ source.name,
82
+ " \u2192 ", target === null || target === void 0 ? void 0 :
83
+ target.name,
84
+ ":"), value: formattedValue }));
85
+ }
86
+ case 'radar': {
87
+ const radarSeries = series;
88
+ const formattedValue = getFormattedValue({
89
+ value: hoveredValues[i],
90
+ format: valueFormat || { type: 'number' },
91
+ });
92
+ return (React.createElement(Row, { key: id, active: active, color: color, label: radarSeries.name || radarSeries.id, value: formattedValue }));
93
+ }
94
+ default: {
95
+ return null;
96
+ }
97
+ }
98
+ }),
99
+ (totals === null || totals === void 0 ? void 0 : totals.enabled) && hovered.length > 1 && (React.createElement(React.Fragment, null,
100
+ React.createElement(Divider, { className: b('content-row-totals-divider') }),
101
+ React.createElement(RowTotals, { aggregation: getPreparedAggregation({ hovered, totals, xAxis, yAxis }), label: totals.label, values: hoveredValues, valueFormat: valueFormat })))));
102
+ };
@@ -0,0 +1,30 @@
1
+ import type { ChartSeriesData, ChartTooltip, ChartTooltipTotalsAggregationValue, ChartTooltipTotalsBuiltInAggregation, ChartXAxis, ChartYAxis, TooltipDataChunk, ValueFormat } from '../../../types';
2
+ export type HoveredValue = string | number | null | undefined;
3
+ export declare function getXRowData(data: ChartSeriesData, xAxis?: ChartXAxis | null): string | number | undefined;
4
+ export declare function getDefaultValueFormat({ axis, }: {
5
+ axis?: ChartXAxis | ChartYAxis | null;
6
+ }): ValueFormat | undefined;
7
+ export declare const getMeasureValue: ({ data, xAxis, yAxis, valueFormat, }: {
8
+ data: TooltipDataChunk[];
9
+ xAxis?: ChartXAxis | null;
10
+ yAxis?: ChartYAxis;
11
+ valueFormat?: ValueFormat;
12
+ }) => string | null;
13
+ export declare function getHoveredValues(args: {
14
+ hovered: TooltipDataChunk[];
15
+ xAxis?: ChartXAxis | null;
16
+ yAxis?: ChartYAxis;
17
+ }): HoveredValue[];
18
+ export declare function getBuiltInAggregatedValue(args: {
19
+ aggregation: ChartTooltipTotalsBuiltInAggregation;
20
+ values: HoveredValue[];
21
+ }): number | undefined;
22
+ export declare function getBuiltInAggregationLabel(args: {
23
+ aggregation: ChartTooltipTotalsBuiltInAggregation;
24
+ }): string;
25
+ export declare function getPreparedAggregation(args: {
26
+ hovered: TooltipDataChunk[];
27
+ totals?: ChartTooltip['totals'];
28
+ xAxis?: ChartXAxis | null;
29
+ yAxis?: ChartYAxis;
30
+ }): ChartTooltipTotalsBuiltInAggregation | (() => ChartTooltipTotalsAggregationValue);