@gravity-ui/charts 1.42.3 → 1.43.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 (127) hide show
  1. package/dist/cjs/components/AxisX/AxisX.js +31 -4
  2. package/dist/cjs/components/AxisX/prepare-axis-data.js +58 -13
  3. package/dist/cjs/components/AxisX/types.d.ts +18 -1
  4. package/dist/cjs/components/AxisY/AxisY.js +31 -4
  5. package/dist/cjs/components/AxisY/prepare-axis-data.js +68 -21
  6. package/dist/cjs/components/AxisY/prepare-axis-title.js +8 -3
  7. package/dist/cjs/components/AxisY/styles.css +1 -1
  8. package/dist/cjs/components/AxisY/types.d.ts +18 -1
  9. package/dist/cjs/components/ChartInner/index.js +21 -15
  10. package/dist/cjs/components/ChartInner/useChartInnerHandlers.js +6 -5
  11. package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +3 -2
  12. package/dist/cjs/components/ChartInner/useChartInnerProps.js +22 -11
  13. package/dist/cjs/components/ChartInner/useDefaultState.js +4 -3
  14. package/dist/cjs/components/ChartInner/utils/chart.js +1 -1
  15. package/dist/cjs/components/ChartInner/utils/normalized-original-data.d.ts +1 -0
  16. package/dist/cjs/components/ChartInner/utils/title.d.ts +3 -2
  17. package/dist/cjs/components/ChartInner/utils/title.js +69 -11
  18. package/dist/cjs/components/Legend/index.js +8 -11
  19. package/dist/cjs/components/Legend/styles.css +1 -1
  20. package/dist/cjs/components/Title/index.js +3 -5
  21. package/dist/cjs/components/Tooltip/ChartTooltipContent.d.ts +2 -1
  22. package/dist/cjs/components/Tooltip/ChartTooltipContent.js +3 -2
  23. package/dist/cjs/components/Tooltip/index.js +2 -2
  24. package/dist/cjs/components/utils/axis-title.js +1 -1
  25. package/dist/cjs/core/axes/types.d.ts +26 -9
  26. package/dist/cjs/core/axes/x-axis.js +16 -3
  27. package/dist/cjs/core/axes/y-axis.js +21 -8
  28. package/dist/cjs/core/constants/defaults/axis.d.ts +1 -0
  29. package/dist/cjs/core/constants/defaults/axis.js +1 -0
  30. package/dist/cjs/core/layout/split.d.ts +2 -2
  31. package/dist/cjs/core/layout/split.js +22 -19
  32. package/dist/cjs/core/scales/y-scale.js +37 -13
  33. package/dist/cjs/core/series/prepare-legend.js +7 -7
  34. package/dist/cjs/core/series/types.d.ts +2 -0
  35. package/dist/cjs/core/types/chart/axis.d.ts +43 -1
  36. package/dist/cjs/core/types/chart/title.d.ts +10 -0
  37. package/dist/cjs/core/types/chart/tooltip.d.ts +3 -1
  38. package/dist/cjs/core/utils/axis-generators/bottom.js +6 -16
  39. package/dist/cjs/core/utils/common.d.ts +0 -4
  40. package/dist/cjs/core/utils/common.js +1 -14
  41. package/dist/cjs/core/utils/get-hovered-plots.d.ts +3 -2
  42. package/dist/cjs/core/utils/get-hovered-plots.js +28 -4
  43. package/dist/cjs/core/utils/labels.d.ts +1 -0
  44. package/dist/cjs/core/utils/labels.js +5 -5
  45. package/dist/cjs/core/utils/text.d.ts +1 -0
  46. package/dist/cjs/core/utils/text.js +16 -2
  47. package/dist/cjs/hooks/types.d.ts +5 -2
  48. package/dist/cjs/hooks/useShapes/area/prepare-data.js +12 -7
  49. package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +12 -4
  50. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +3 -2
  51. package/dist/cjs/hooks/useShapes/funnel/prepare-data.js +4 -1
  52. package/dist/cjs/hooks/useShapes/heatmap/prepare-data.js +1 -1
  53. package/dist/cjs/hooks/useShapes/line/prepare-data.js +4 -1
  54. package/dist/cjs/hooks/useShapes/pie/prepare-data.js +9 -2
  55. package/dist/cjs/hooks/useShapes/radar/prepare-data.js +17 -7
  56. package/dist/cjs/hooks/useShapes/sankey/prepare-data.js +1 -1
  57. package/dist/cjs/hooks/useShapes/sankey/sankey-layout.d.ts +49 -0
  58. package/dist/cjs/hooks/useShapes/sankey/sankey-layout.js +362 -0
  59. package/dist/cjs/hooks/useShapes/styles.css +4 -4
  60. package/dist/cjs/hooks/useShapes/treemap/prepare-data.js +3 -1
  61. package/dist/cjs/hooks/useTooltip/index.d.ts +3 -2
  62. package/dist/cjs/hooks/useTooltip/index.js +5 -3
  63. package/dist/cjs/types/chart-ui.d.ts +1 -0
  64. package/dist/esm/components/AxisX/AxisX.js +31 -4
  65. package/dist/esm/components/AxisX/prepare-axis-data.js +58 -13
  66. package/dist/esm/components/AxisX/types.d.ts +18 -1
  67. package/dist/esm/components/AxisY/AxisY.js +31 -4
  68. package/dist/esm/components/AxisY/prepare-axis-data.js +68 -21
  69. package/dist/esm/components/AxisY/prepare-axis-title.js +8 -3
  70. package/dist/esm/components/AxisY/styles.css +1 -1
  71. package/dist/esm/components/AxisY/types.d.ts +18 -1
  72. package/dist/esm/components/ChartInner/index.js +21 -15
  73. package/dist/esm/components/ChartInner/useChartInnerHandlers.js +6 -5
  74. package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +3 -2
  75. package/dist/esm/components/ChartInner/useChartInnerProps.js +22 -11
  76. package/dist/esm/components/ChartInner/useDefaultState.js +4 -3
  77. package/dist/esm/components/ChartInner/utils/chart.js +1 -1
  78. package/dist/esm/components/ChartInner/utils/normalized-original-data.d.ts +1 -0
  79. package/dist/esm/components/ChartInner/utils/title.d.ts +3 -2
  80. package/dist/esm/components/ChartInner/utils/title.js +69 -11
  81. package/dist/esm/components/Legend/index.js +8 -11
  82. package/dist/esm/components/Legend/styles.css +1 -1
  83. package/dist/esm/components/Title/index.js +3 -5
  84. package/dist/esm/components/Tooltip/ChartTooltipContent.d.ts +2 -1
  85. package/dist/esm/components/Tooltip/ChartTooltipContent.js +3 -2
  86. package/dist/esm/components/Tooltip/index.js +2 -2
  87. package/dist/esm/components/utils/axis-title.js +1 -1
  88. package/dist/esm/core/axes/types.d.ts +26 -9
  89. package/dist/esm/core/axes/x-axis.js +16 -3
  90. package/dist/esm/core/axes/y-axis.js +21 -8
  91. package/dist/esm/core/constants/defaults/axis.d.ts +1 -0
  92. package/dist/esm/core/constants/defaults/axis.js +1 -0
  93. package/dist/esm/core/layout/split.d.ts +2 -2
  94. package/dist/esm/core/layout/split.js +22 -19
  95. package/dist/esm/core/scales/y-scale.js +37 -13
  96. package/dist/esm/core/series/prepare-legend.js +7 -7
  97. package/dist/esm/core/series/types.d.ts +2 -0
  98. package/dist/esm/core/types/chart/axis.d.ts +43 -1
  99. package/dist/esm/core/types/chart/title.d.ts +10 -0
  100. package/dist/esm/core/types/chart/tooltip.d.ts +3 -1
  101. package/dist/esm/core/utils/axis-generators/bottom.js +6 -16
  102. package/dist/esm/core/utils/common.d.ts +0 -4
  103. package/dist/esm/core/utils/common.js +1 -14
  104. package/dist/esm/core/utils/get-hovered-plots.d.ts +3 -2
  105. package/dist/esm/core/utils/get-hovered-plots.js +28 -4
  106. package/dist/esm/core/utils/labels.d.ts +1 -0
  107. package/dist/esm/core/utils/labels.js +5 -5
  108. package/dist/esm/core/utils/text.d.ts +1 -0
  109. package/dist/esm/core/utils/text.js +16 -2
  110. package/dist/esm/hooks/types.d.ts +5 -2
  111. package/dist/esm/hooks/useShapes/area/prepare-data.js +12 -7
  112. package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +12 -4
  113. package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +3 -2
  114. package/dist/esm/hooks/useShapes/funnel/prepare-data.js +4 -1
  115. package/dist/esm/hooks/useShapes/heatmap/prepare-data.js +1 -1
  116. package/dist/esm/hooks/useShapes/line/prepare-data.js +4 -1
  117. package/dist/esm/hooks/useShapes/pie/prepare-data.js +9 -2
  118. package/dist/esm/hooks/useShapes/radar/prepare-data.js +17 -7
  119. package/dist/esm/hooks/useShapes/sankey/prepare-data.js +1 -1
  120. package/dist/esm/hooks/useShapes/sankey/sankey-layout.d.ts +49 -0
  121. package/dist/esm/hooks/useShapes/sankey/sankey-layout.js +362 -0
  122. package/dist/esm/hooks/useShapes/styles.css +4 -4
  123. package/dist/esm/hooks/useShapes/treemap/prepare-data.js +3 -1
  124. package/dist/esm/hooks/useTooltip/index.d.ts +3 -2
  125. package/dist/esm/hooks/useTooltip/index.js +5 -3
  126. package/dist/esm/types/chart-ui.d.ts +1 -0
  127. package/package.json +1 -3
@@ -43,20 +43,20 @@ export function filterOverlappingLabels(labels) {
43
43
  return result;
44
44
  }
45
45
  export function getSvgLabelConstraintedPosition(args) {
46
- const { boundsHeight, boundsWidth, height, width, x, y } = args;
46
+ const { boundsHeight, boundsWidth, height, width, x, y, hangingOffset } = args;
47
47
  let resultX = x;
48
- let resultY = y;
48
+ let resultY = y - height / 2 + hangingOffset;
49
49
  if (x < 0) {
50
50
  resultX = 0;
51
51
  }
52
52
  if (x + width > boundsWidth) {
53
53
  resultX = boundsWidth - width;
54
54
  }
55
- if (y - height < 0) {
55
+ if (resultY < 0) {
56
56
  resultY = 0;
57
57
  }
58
- if (y > boundsHeight) {
59
- resultY = boundsHeight;
58
+ if (resultY + height > boundsHeight) {
59
+ resultY = boundsHeight - height + hangingOffset;
60
60
  }
61
61
  return { x: resultX, y: resultY };
62
62
  }
@@ -27,6 +27,7 @@ export declare function getTextSizeFn({ style }: {
27
27
  }): (str: string) => Promise<{
28
28
  width: number;
29
29
  height: number;
30
+ hangingOffset: number;
30
31
  }>;
31
32
  export declare function getTextWithElipsis({ text: originalText, getTextWidth, maxWidth, }: {
32
33
  text: string;
@@ -189,14 +189,28 @@ export function getTextSizeFn({ style }) {
189
189
  const defaultFontFamily = computedStyle.getPropertyValue('font-family');
190
190
  const defaultFontSize = computedStyle.getPropertyValue('font-size');
191
191
  const defaultFontWeight = computedStyle.getPropertyValue('font-weight');
192
+ const resolveCSSVar = (value) => {
193
+ const match = value.match(/^var\(\s*([\w-]+)/);
194
+ if (match) {
195
+ return computedStyle.getPropertyValue(match[1]).trim() || value;
196
+ }
197
+ return value;
198
+ };
192
199
  return async (str) => {
193
- var _a, _b;
194
200
  await document.fonts.ready;
195
- context.font = `${(_a = style === null || style === void 0 ? void 0 : style.fontWeight) !== null && _a !== void 0 ? _a : defaultFontWeight} ${(_b = style === null || style === void 0 ? void 0 : style.fontSize) !== null && _b !== void 0 ? _b : defaultFontSize} ${defaultFontFamily}`;
201
+ const fontWeight = (style === null || style === void 0 ? void 0 : style.fontWeight)
202
+ ? resolveCSSVar(String(style.fontWeight))
203
+ : defaultFontWeight;
204
+ const fontSize = (style === null || style === void 0 ? void 0 : style.fontSize) ? resolveCSSVar(style.fontSize) : defaultFontSize;
205
+ context.font = `${fontWeight} ${fontSize} ${defaultFontFamily}`;
196
206
  const textMetric = context.measureText(unescapeHtml(str));
207
+ // we calculate hanging based on an approximate algorithm from chromium
208
+ // https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/html/canvas/text_metrics.cc;l=32;drc=7cf6ac3dd6dca800fbc0d28e80a7732d4ea90340?q=member_hanging_&ss=chromium%2Fchromium%2Fsrc
209
+ // it would be possible to use native, but the browsers are not working in harmony right now
197
210
  return {
198
211
  width: textMetric.width,
199
212
  height: textMetric.fontBoundingBoxDescent + textMetric.fontBoundingBoxAscent,
213
+ hangingOffset: textMetric.fontBoundingBoxAscent * 0.2,
200
214
  };
201
215
  };
202
216
  }
@@ -1,4 +1,5 @@
1
- import type { ChartBrush, ChartData, ChartMargin, ChartZoom, DeepRequired } from '../types';
1
+ import type { TextRowData } from '../components/types';
2
+ import type { ChartBrush, ChartData, ChartMargin, ChartTitle, ChartZoom, DeepRequired } from '../types';
2
3
  export type PreparedZoom = DeepRequired<Omit<ChartZoom, 'enabled' | 'brush'>> & DeepRequired<{
3
4
  brush: ChartBrush;
4
5
  }>;
@@ -6,8 +7,10 @@ export type PreparedChart = {
6
7
  margin: ChartMargin;
7
8
  zoom: PreparedZoom | null;
8
9
  };
9
- export type PreparedTitle = ChartData['title'] & {
10
+ export type PreparedTitle = Omit<ChartTitle, 'margin'> & {
10
11
  height: number;
12
+ margin: number;
13
+ contentRows: TextRowData[];
11
14
  };
12
15
  export type PreparedTooltip = ChartData['tooltip'] & {
13
16
  enabled: boolean;
@@ -1,4 +1,4 @@
1
- import { group } from 'd3-array';
1
+ import { group, min } from 'd3-array';
2
2
  import isNil from 'lodash/isNil';
3
3
  import round from 'lodash/round';
4
4
  import { getDataCategoryValue, getLabelsSize, getTextSizeFn } from '../../../core/utils';
@@ -60,7 +60,7 @@ async function prepareDataLabels({ series, points, xMax, yAxisTop, isOutsideBoun
60
60
  else {
61
61
  const labelSize = await getTextSize(text);
62
62
  const x = Math.min(xMax - labelSize.width, Math.max(0, point.x - labelSize.width / 2));
63
- const y = Math.max(yAxisTop, point.y - series.dataLabels.padding - labelSize.height);
63
+ const y = Math.max(yAxisTop, point.y - series.dataLabels.padding - labelSize.height + labelSize.hangingOffset);
64
64
  svgLabels.push({
65
65
  text,
66
66
  x,
@@ -76,7 +76,7 @@ async function prepareDataLabels({ series, points, xMax, yAxisTop, isOutsideBoun
76
76
  return { svgLabels, htmlLabels };
77
77
  }
78
78
  export const prepareAreaData = async (args) => {
79
- var _a, _b, _c;
79
+ var _a, _b, _c, _d;
80
80
  const { series, xAxis, xScale, yAxis, yScale, split, isOutsideBounds, isRangeSlider } = args;
81
81
  const [_xMin, xRangeMax] = xScale.range();
82
82
  const xMax = xRangeMax;
@@ -144,12 +144,17 @@ export const prepareAreaData = async (args) => {
144
144
  continue;
145
145
  }
146
146
  const yAxisTop = ((_a = split.plots[plotIndex]) === null || _a === void 0 ? void 0 : _a.top) || 0;
147
- const yMin = (_b = getYValue({
148
- point: { y: 0 },
147
+ let base = 0;
148
+ if (seriesYAxis.type === 'logarithmic') {
149
+ const domainData = seriesYScale.domain();
150
+ base = (_b = min(domainData)) !== null && _b !== void 0 ? _b : 0;
151
+ }
152
+ const yMin = (_c = getYValue({
153
+ point: { y: base },
149
154
  points: s.data,
150
155
  yAxis: seriesYAxis,
151
156
  yScale: seriesYScale,
152
- })) !== null && _b !== void 0 ? _b : 0;
157
+ })) !== null && _c !== void 0 ? _c : 0;
153
158
  const seriesData = s.data.reduce((m, d) => {
154
159
  const key = String(xAxis.type === 'category'
155
160
  ? getDataCategoryValue({
@@ -309,7 +314,7 @@ export const prepareAreaData = async (args) => {
309
314
  for (let itemIndex = 0; itemIndex < seriesStackData.length; itemIndex++) {
310
315
  const item = seriesStackData[itemIndex];
311
316
  const currentYAxis = yAxis[item.series.yAxis];
312
- const itemYAxisTop = ((_c = split.plots[currentYAxis.plotIndex]) === null || _c === void 0 ? void 0 : _c.top) || 0;
317
+ const itemYAxisTop = ((_d = split.plots[currentYAxis.plotIndex]) === null || _d === void 0 ? void 0 : _d.top) || 0;
313
318
  if (item.series.dataLabels.enabled && !isRangeSlider) {
314
319
  const labelsData = await prepareDataLabels({
315
320
  series: item.series,
@@ -1,4 +1,4 @@
1
- import { ascending, descending, max, reverse, sort } from 'd3-array';
1
+ import { ascending, descending, max, min, reverse, sort } from 'd3-array';
2
2
  import get from 'lodash/get';
3
3
  import { getDataCategoryValue, getLabelsSize } from '../../../core/utils';
4
4
  import { getFormattedValue } from '../../../core/utils/format';
@@ -35,7 +35,7 @@ async function getLabelData(d, xMax) {
35
35
  };
36
36
  }
37
37
  export const prepareBarXData = async (args) => {
38
- var _a, _b, _c, _d, _e;
38
+ var _a, _b, _c, _d, _e, _f;
39
39
  const { series, seriesOptions, xAxis, xScale, yAxis, yScale, boundsHeight: plotHeight, split, isRangeSlider, } = args;
40
40
  const stackGap = seriesOptions['bar-x'].stackGap;
41
41
  const categories = (_a = xAxis === null || xAxis === void 0 ? void 0 : xAxis.categories) !== null && _a !== void 0 ? _a : [];
@@ -145,7 +145,15 @@ export const prepareBarXData = async (args) => {
145
145
  const x = xCenter - currentGroupWidth / 2 + (rectWidth + rectGap) * groupItemIndex;
146
146
  const yDataValue = ((_d = yValue.data.y) !== null && _d !== void 0 ? _d : 0);
147
147
  const y = seriesYScale(yDataValue);
148
- const base = seriesYScale(0);
148
+ let base = 0;
149
+ if (seriesYAxis.type === 'logarithmic') {
150
+ const domainData = seriesYScale.domain();
151
+ const yMinValue = (_e = min(domainData)) !== null && _e !== void 0 ? _e : 0;
152
+ base = seriesYScale(yMinValue);
153
+ }
154
+ else {
155
+ base = seriesYScale(0);
156
+ }
149
157
  const isLastStackItem = yValueIndex === sortedData.length - 1;
150
158
  const height = Math.abs(base - y);
151
159
  let shapeHeight = height - (stackItems.length ? stackGap : 0);
@@ -198,7 +206,7 @@ export const prepareBarXData = async (args) => {
198
206
  barData.x >= xMax ||
199
207
  barData.y + barData.height <= 0 ||
200
208
  barData.y >= plotHeight;
201
- const isZeroValue = ((_e = barData.data.y) !== null && _e !== void 0 ? _e : 0) === 0;
209
+ const isZeroValue = ((_f = barData.data.y) !== null && _f !== void 0 ? _f : 0) === 0;
202
210
  if (barData.series.dataLabels.enabled &&
203
211
  !isRangeSlider &&
204
212
  (!isBarOutsideBounds || isZeroValue)) {
@@ -171,7 +171,7 @@ export async function prepareBarYData(args) {
171
171
  map.set(dataLabels.style, getTextSizeFn({ style: dataLabels.style }));
172
172
  }
173
173
  const getTextSize = map.get(dataLabels.style);
174
- const { width, height } = await getTextSize(content);
174
+ const { width, height, hangingOffset } = await getTextSize(content);
175
175
  const x = dataLabels.inside
176
176
  ? prepared.x + prepared.width / 2 - width / 2
177
177
  : prepared.x + prepared.width + dataLabels.padding;
@@ -181,7 +181,8 @@ export async function prepareBarYData(args) {
181
181
  height,
182
182
  width,
183
183
  x,
184
- y: y + height / 2,
184
+ y,
185
+ hangingOffset,
185
186
  });
186
187
  labels.push({
187
188
  size: { width, height },
@@ -62,7 +62,10 @@ export async function prepareFunnelData(args) {
62
62
  }
63
63
  svgLabels.push({
64
64
  x,
65
- y: getSegmentY(index) + itemHeight / 2 - labelSize.height / 2,
65
+ y: getSegmentY(index) +
66
+ itemHeight / 2 -
67
+ labelSize.height / 2 +
68
+ labelSize.hangingOffset,
66
69
  text: labelContent,
67
70
  style: s.dataLabels.style,
68
71
  size: labelSize,
@@ -82,7 +82,7 @@ export async function prepareHeatmapData({ series, xAxis, xScale, yAxis, yScale,
82
82
  if (text) {
83
83
  svgDataLabels.push({
84
84
  x: item.x + item.width / 2 - size.width / 2,
85
- y: item.y + item.height / 2 - size.height / 2,
85
+ y: item.y + item.height / 2 - size.height / 2 + size.hangingOffset,
86
86
  text,
87
87
  style: series.dataLabels.style,
88
88
  });
@@ -68,7 +68,10 @@ export const prepareLineData = async (args) => {
68
68
  const text = getFormattedValue(Object.assign({ value: labelValue }, s.dataLabels));
69
69
  const labelSize = await getTextSize(text);
70
70
  const style = s.dataLabels.style;
71
- const y = Math.max(yAxisTop, point.y - s.dataLabels.padding - labelSize.height);
71
+ const y = Math.max(yAxisTop, point.y -
72
+ s.dataLabels.padding -
73
+ labelSize.height +
74
+ labelSize.hangingOffset);
72
75
  const x = Math.min(xMax - labelSize.width, Math.max(0, point.x - labelSize.width / 2));
73
76
  const labelData = {
74
77
  text,
@@ -95,6 +95,7 @@ export function preparePieData(args) {
95
95
  const text = getFormattedValue(Object.assign({ value: (_a = d.data.label) !== null && _a !== void 0 ? _a : d.data.value }, d.dataLabels));
96
96
  let labelWidth = 0;
97
97
  let labelHeight = 0;
98
+ let labelHangingOffset = 0;
98
99
  if (dataLabels.html) {
99
100
  const size = await getLabelsSize({
100
101
  labels: [text],
@@ -108,10 +109,11 @@ export function preparePieData(args) {
108
109
  const size = await getTextSize(text);
109
110
  labelWidth = size.width;
110
111
  labelHeight = size.height;
112
+ labelHangingOffset = size.hangingOffset;
111
113
  }
112
114
  const label = {
113
115
  text,
114
- size: { width: labelWidth, height: labelHeight },
116
+ size: { width: labelWidth, height: labelHeight, hangingOffset: labelHangingOffset },
115
117
  };
116
118
  acc[d.id] = label;
117
119
  }
@@ -165,11 +167,16 @@ export function preparePieData(args) {
165
167
  * @returns {[number, number]} A tuple [x, y] relative to the pie center.
166
168
  */
167
169
  const getLabelPosition = (angle) => {
170
+ var _a;
168
171
  let [x, y] = labelArcGenerator.centroid(Object.assign(Object.assign({}, relatedSegment), { startAngle: angle, endAngle: angle }));
169
172
  if (shouldUseHtml) {
170
173
  x = x < 0 ? x - labelWidth : x;
174
+ y = y < 0 ? y - labelHeight : y;
175
+ }
176
+ else {
177
+ const hangingOffset = (_a = labelSize === null || labelSize === void 0 ? void 0 : labelSize.hangingOffset) !== null && _a !== void 0 ? _a : 0;
178
+ y = y < 0 ? y - labelHeight + hangingOffset : y + hangingOffset;
171
179
  }
172
- y = y < 0 ? y - labelHeight : y;
173
180
  return [x, y];
174
181
  };
175
182
  const getConnectorPoints = (angle) => {
@@ -1,7 +1,7 @@
1
1
  import { range } from 'd3-array';
2
2
  import { scaleLinear } from 'd3-scale';
3
3
  import { curveLinearClosed, line } from 'd3-shape';
4
- import { getLabelsSize } from '../../../core/utils';
4
+ import { getLabelsSize, getTextSizeFn } from '../../../core/utils';
5
5
  import { getFormattedValue } from '../../../core/utils/format';
6
6
  export async function prepareRadarData(args) {
7
7
  const { series: preparedSeries, boundsWidth, boundsHeight } = args;
@@ -116,18 +116,28 @@ export async function prepareRadarData(args) {
116
116
  const shouldUseHtml = dataLabels.html;
117
117
  data.labels = await Promise.all(categories.map(async (category, index) => {
118
118
  const text = getFormattedValue(Object.assign({ value: category.key }, dataLabels));
119
- const labelSize = await getLabelsSize({ labels: [text], style });
120
119
  const angle = index * angleStep - Math.PI / 2;
121
120
  // Position label slightly outside the point
122
121
  const labelRadius = data.radius + 10;
123
122
  let x = center[0] + Math.cos(angle) * labelRadius;
124
123
  let y = center[1] + Math.sin(angle) * labelRadius;
124
+ let labelWidth = 0;
125
+ let labelHeight = 0;
125
126
  if (shouldUseHtml) {
126
- x = x < center[0] ? x - labelSize.maxWidth : x;
127
- y = y - labelSize.maxHeight;
127
+ const labelSize = await getLabelsSize({ labels: [text], style });
128
+ labelWidth = labelSize.maxWidth;
129
+ labelHeight = labelSize.maxHeight;
130
+ x = x < center[0] ? x - labelWidth : x;
131
+ y = y - labelHeight;
128
132
  }
129
133
  else {
130
- y = y < center[1] ? y - labelSize.maxHeight : y;
134
+ const labelSize = await getTextSizeFn({ style })(text);
135
+ labelWidth = labelSize.width;
136
+ labelHeight = labelSize.height;
137
+ y =
138
+ y < center[1]
139
+ ? y - labelHeight + labelSize.hangingOffset
140
+ : y + labelSize.hangingOffset;
131
141
  }
132
142
  x = Math.max(-boundsWidth / 2, x);
133
143
  return {
@@ -135,8 +145,8 @@ export async function prepareRadarData(args) {
135
145
  x,
136
146
  y,
137
147
  style,
138
- size: { width: labelSize.maxWidth, height: labelSize.maxHeight },
139
- maxWidth: labelSize.maxWidth,
148
+ size: { width: labelWidth, height: labelHeight },
149
+ maxWidth: labelWidth,
140
150
  textAnchor: angle > Math.PI / 2 && angle < (3 * Math.PI) / 2 ? 'end' : 'start',
141
151
  series: { id: series.id },
142
152
  };
@@ -1,5 +1,5 @@
1
- import { sankey, sankeyLinkHorizontal } from 'd3-sankey';
2
1
  import { getFormattedValue } from '../../../core/utils/format';
2
+ import { sankey, sankeyLinkHorizontal } from './sankey-layout';
3
3
  export function prepareSankeyData(args) {
4
4
  const { series, width, height } = args;
5
5
  const htmlElements = [];
@@ -0,0 +1,49 @@
1
+ type SankeyLayoutNodeProps = {
2
+ index: number;
3
+ depth: number;
4
+ height: number;
5
+ layer: number;
6
+ value: number;
7
+ fixedValue?: number;
8
+ x0: number;
9
+ x1: number;
10
+ y0: number;
11
+ y1: number;
12
+ };
13
+ type SankeyLayoutLinkProps = {
14
+ index: number;
15
+ value: number;
16
+ width: number;
17
+ y0: number;
18
+ y1: number;
19
+ };
20
+ export type SankeyComputedNode<N, L> = N & SankeyLayoutNodeProps & {
21
+ sourceLinks: SankeyComputedLink<N, L>[];
22
+ targetLinks: SankeyComputedLink<N, L>[];
23
+ };
24
+ export type SankeyComputedLink<N, L> = L & SankeyLayoutLinkProps & {
25
+ source: SankeyComputedNode<N, L>;
26
+ target: SankeyComputedNode<N, L>;
27
+ };
28
+ export type SankeyGraph<N, L> = {
29
+ nodes: SankeyComputedNode<N, L>[];
30
+ links: SankeyComputedLink<N, L>[];
31
+ };
32
+ type AlignFn<N, L> = (node: SankeyComputedNode<N, L>, n: number) => number;
33
+ type SortFn<T> = (a: T, b: T) => number;
34
+ export declare function sankey<N, L>(): {
35
+ (input: {
36
+ nodes: N[];
37
+ links: L[];
38
+ }): SankeyGraph<N, L>;
39
+ nodeId(fn: (d: N, i: number) => string | number): /*elided*/ any;
40
+ nodeAlign(fn: AlignFn<N, L>): /*elided*/ any;
41
+ nodeSort(fn: SortFn<SankeyComputedNode<N, L>> | undefined): /*elided*/ any;
42
+ nodeWidth(value: number): /*elided*/ any;
43
+ nodePadding(value: number): /*elided*/ any;
44
+ linkSort(fn: SortFn<SankeyComputedLink<N, L>> | undefined): /*elided*/ any;
45
+ extent([[left, top], [right, bottom]]: [[number, number], [number, number]]): /*elided*/ any;
46
+ iterations(value: number): /*elided*/ any;
47
+ };
48
+ export declare function sankeyLinkHorizontal<N, L>(): import("d3-shape").Link<any, SankeyComputedLink<N, L>, [number, number]>;
49
+ export {};