@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
@@ -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 {};
@@ -0,0 +1,362 @@
1
+ // Derived from d3-sankey v0.12.3 (https://github.com/d3/d3-sankey)
2
+ // Copyright 2015-2021 Mike Bostock — ISC License
3
+ //
4
+ // Changes:
5
+ // - Ported to TypeScript with explicit generic types (SankeyComputedNode, SankeyComputedLink)
6
+ // - sankeyLinkHorizontal() implemented via linkHorizontal() from d3-shape
7
+ // - Removed unused alignment helpers (left, right, center); only justify is kept
8
+ // - No d3-sankey dependency; uses d3-array and d3-shape (already project dependencies)
9
+ import { max, min, sum } from 'd3-array';
10
+ import { linkHorizontal } from 'd3-shape';
11
+ function justify(node, n) {
12
+ return node.sourceLinks.length ? node.depth : n - 1;
13
+ }
14
+ function ascendingBreadth(a, b) {
15
+ return a.y0 - b.y0;
16
+ }
17
+ function ascendingSourceBreadth(a, b) {
18
+ return ascendingBreadth(a.source, b.source) || a.index - b.index;
19
+ }
20
+ function ascendingTargetBreadth(a, b) {
21
+ return ascendingBreadth(a.target, b.target) || a.index - b.index;
22
+ }
23
+ function nodeValue(d) {
24
+ return d.value;
25
+ }
26
+ function linkValue(d) {
27
+ return d.value;
28
+ }
29
+ export function sankey() {
30
+ let x0 = 0, y0 = 0, x1 = 1, y1 = 1;
31
+ let dx = 24; // nodeWidth
32
+ let dy = 8, py; // nodePadding
33
+ let getId = (_d, i) => i;
34
+ let align = justify;
35
+ let sort;
36
+ let linkSort;
37
+ let iterations = 6;
38
+ function generator(input) {
39
+ // Mutate input in-place (same as original d3-sankey): layout props are added
40
+ // directly to node/link objects so that source/target references stay consistent.
41
+ const graph = {
42
+ nodes: input.nodes,
43
+ links: input.links,
44
+ };
45
+ computeNodeLinks(graph);
46
+ computeNodeValues(graph);
47
+ computeNodeDepths(graph);
48
+ computeNodeHeights(graph);
49
+ computeNodeBreadths(graph);
50
+ computeLinkBreadths(graph);
51
+ return graph;
52
+ }
53
+ generator.nodeId = function (fn) {
54
+ getId = fn;
55
+ return generator;
56
+ };
57
+ generator.nodeAlign = function (fn) {
58
+ align = fn;
59
+ return generator;
60
+ };
61
+ generator.nodeSort = function (fn) {
62
+ sort = fn;
63
+ return generator;
64
+ };
65
+ generator.nodeWidth = function (value) {
66
+ dx = value;
67
+ return generator;
68
+ };
69
+ generator.nodePadding = function (value) {
70
+ dy = py = value;
71
+ return generator;
72
+ };
73
+ generator.linkSort = function (fn) {
74
+ linkSort = fn;
75
+ return generator;
76
+ };
77
+ generator.extent = function ([[left, top], [right, bottom]]) {
78
+ x0 = left;
79
+ y0 = top;
80
+ x1 = right;
81
+ y1 = bottom;
82
+ return generator;
83
+ };
84
+ generator.iterations = function (value) {
85
+ iterations = value;
86
+ return generator;
87
+ };
88
+ function computeNodeLinks(graph) {
89
+ for (const [i, node] of graph.nodes.entries()) {
90
+ node.index = i;
91
+ node.sourceLinks = [];
92
+ node.targetLinks = [];
93
+ }
94
+ const nodeById = new Map(graph.nodes.map((d, i) => [getId(d, i), d]));
95
+ for (const [i, link] of graph.links.entries()) {
96
+ link.index = i;
97
+ const unresolved = link;
98
+ if (typeof unresolved.source !== 'object') {
99
+ unresolved.source = findNode(nodeById, unresolved.source);
100
+ }
101
+ if (typeof unresolved.target !== 'object') {
102
+ unresolved.target = findNode(nodeById, unresolved.target);
103
+ }
104
+ link.source.sourceLinks.push(link);
105
+ link.target.targetLinks.push(link);
106
+ }
107
+ if (linkSort !== null && linkSort !== undefined) {
108
+ for (const { sourceLinks, targetLinks } of graph.nodes) {
109
+ sourceLinks.sort(linkSort);
110
+ targetLinks.sort(linkSort);
111
+ }
112
+ }
113
+ }
114
+ function computeNodeValues(graph) {
115
+ for (const node of graph.nodes) {
116
+ node.value =
117
+ node.fixedValue === undefined
118
+ ? Math.max(sum(node.sourceLinks, linkValue), sum(node.targetLinks, linkValue))
119
+ : node.fixedValue;
120
+ }
121
+ }
122
+ function computeNodeDepths(graph) {
123
+ const n = graph.nodes.length;
124
+ let current = new Set(graph.nodes);
125
+ let next = new Set();
126
+ let x = 0;
127
+ while (current.size) {
128
+ for (const node of current) {
129
+ node.depth = x;
130
+ for (const { target } of node.sourceLinks) {
131
+ next.add(target);
132
+ }
133
+ }
134
+ if (++x > n)
135
+ throw new Error('circular link');
136
+ current = next;
137
+ next = new Set();
138
+ }
139
+ }
140
+ function computeNodeHeights(graph) {
141
+ const n = graph.nodes.length;
142
+ let current = new Set(graph.nodes);
143
+ let next = new Set();
144
+ let x = 0;
145
+ while (current.size) {
146
+ for (const node of current) {
147
+ node.height = x;
148
+ for (const { source } of node.targetLinks) {
149
+ next.add(source);
150
+ }
151
+ }
152
+ if (++x > n)
153
+ throw new Error('circular link');
154
+ current = next;
155
+ next = new Set();
156
+ }
157
+ }
158
+ function computeNodeLayers(graph) {
159
+ var _a;
160
+ const x = ((_a = max(graph.nodes, (d) => d.depth)) !== null && _a !== void 0 ? _a : 0) + 1;
161
+ const kx = (x1 - x0 - dx) / (x - 1);
162
+ const columns = new Array(x);
163
+ for (const node of graph.nodes) {
164
+ const i = Math.max(0, Math.min(x - 1, Math.floor(align(node, x))));
165
+ node.layer = i;
166
+ node.x0 = x0 + i * kx;
167
+ node.x1 = node.x0 + dx;
168
+ if (columns[i])
169
+ columns[i].push(node);
170
+ else
171
+ columns[i] = [node];
172
+ }
173
+ if (sort) {
174
+ for (const column of columns) {
175
+ column.sort(sort);
176
+ }
177
+ }
178
+ return columns;
179
+ }
180
+ function initializeNodeBreadths(columns) {
181
+ var _a;
182
+ const ky = (_a = min(columns, (c) => (y1 - y0 - (c.length - 1) * py) / sum(c, nodeValue))) !== null && _a !== void 0 ? _a : 0;
183
+ for (const nodes of columns) {
184
+ let y = y0;
185
+ for (const node of nodes) {
186
+ node.y0 = y;
187
+ node.y1 = y + node.value * ky;
188
+ y = node.y1 + py;
189
+ for (const link of node.sourceLinks) {
190
+ link.width = link.value * ky;
191
+ }
192
+ }
193
+ y = (y1 - y + py) / (nodes.length + 1);
194
+ for (let i = 0; i < nodes.length; ++i) {
195
+ const node = nodes[i];
196
+ node.y0 += y * (i + 1);
197
+ node.y1 += y * (i + 1);
198
+ }
199
+ reorderLinks(nodes);
200
+ }
201
+ }
202
+ function computeNodeBreadths(graph) {
203
+ var _a;
204
+ const columns = computeNodeLayers(graph);
205
+ py = Math.min(dy, (y1 - y0) / (((_a = max(columns, (c) => c.length)) !== null && _a !== void 0 ? _a : 1) - 1));
206
+ initializeNodeBreadths(columns);
207
+ for (let i = 0; i < iterations; ++i) {
208
+ const alpha = Math.pow(0.99, i);
209
+ const beta = Math.max(1 - alpha, (i + 1) / iterations);
210
+ relaxRightToLeft(columns, alpha, beta);
211
+ relaxLeftToRight(columns, alpha, beta);
212
+ }
213
+ }
214
+ function computeLinkBreadths(graph) {
215
+ for (const node of graph.nodes) {
216
+ let ly0 = node.y0;
217
+ let ly1 = ly0;
218
+ for (const link of node.sourceLinks) {
219
+ link.y0 = ly0 + link.width / 2;
220
+ ly0 += link.width;
221
+ }
222
+ for (const link of node.targetLinks) {
223
+ link.y1 = ly1 + link.width / 2;
224
+ ly1 += link.width;
225
+ }
226
+ }
227
+ }
228
+ function relaxLeftToRight(columns, alpha, beta) {
229
+ for (let i = 1, n = columns.length; i < n; ++i) {
230
+ const column = columns[i];
231
+ for (const target of column) {
232
+ let y = 0;
233
+ let w = 0;
234
+ for (const { source, value } of target.targetLinks) {
235
+ const v = value * (target.layer - source.layer);
236
+ y += targetTop(source, target) * v;
237
+ w += v;
238
+ }
239
+ if (!(w > 0))
240
+ continue;
241
+ const d = (y / w - target.y0) * alpha;
242
+ target.y0 += d;
243
+ target.y1 += d;
244
+ reorderNodeLinks(target);
245
+ }
246
+ if (sort === undefined)
247
+ column.sort(ascendingBreadth);
248
+ resolveCollisions(column, beta);
249
+ }
250
+ }
251
+ function relaxRightToLeft(columns, alpha, beta) {
252
+ for (let n = columns.length, i = n - 2; i >= 0; --i) {
253
+ const column = columns[i];
254
+ for (const source of column) {
255
+ let y = 0;
256
+ let w = 0;
257
+ for (const { target, value } of source.sourceLinks) {
258
+ const v = value * (target.layer - source.layer);
259
+ y += sourceTop(source, target) * v;
260
+ w += v;
261
+ }
262
+ if (!(w > 0))
263
+ continue;
264
+ const d = (y / w - source.y0) * alpha;
265
+ source.y0 += d;
266
+ source.y1 += d;
267
+ reorderNodeLinks(source);
268
+ }
269
+ if (sort === undefined)
270
+ column.sort(ascendingBreadth);
271
+ resolveCollisions(column, beta);
272
+ }
273
+ }
274
+ function resolveCollisions(nodes, alpha) {
275
+ const i = Math.floor(nodes.length / 2);
276
+ const subject = nodes[i];
277
+ resolveCollisionsBottomToTop(nodes, subject.y0 - py, i - 1, alpha);
278
+ resolveCollisionsTopToBottom(nodes, subject.y1 + py, i + 1, alpha);
279
+ resolveCollisionsBottomToTop(nodes, y1, nodes.length - 1, alpha);
280
+ resolveCollisionsTopToBottom(nodes, y0, 0, alpha);
281
+ }
282
+ function resolveCollisionsTopToBottom(nodes, y, i, alpha) {
283
+ for (; i < nodes.length; ++i) {
284
+ const node = nodes[i];
285
+ const d = (y - node.y0) * alpha;
286
+ if (d > 1e-6) {
287
+ node.y0 += d;
288
+ node.y1 += d;
289
+ }
290
+ y = node.y1 + py;
291
+ }
292
+ }
293
+ function resolveCollisionsBottomToTop(nodes, y, i, alpha) {
294
+ for (; i >= 0; --i) {
295
+ const node = nodes[i];
296
+ const d = (node.y1 - y) * alpha;
297
+ if (d > 1e-6) {
298
+ node.y0 -= d;
299
+ node.y1 -= d;
300
+ }
301
+ y = node.y0 - py;
302
+ }
303
+ }
304
+ function reorderNodeLinks(node) {
305
+ if (linkSort === undefined) {
306
+ for (const { source: { sourceLinks }, } of node.targetLinks) {
307
+ sourceLinks.sort(ascendingTargetBreadth);
308
+ }
309
+ for (const { target: { targetLinks }, } of node.sourceLinks) {
310
+ targetLinks.sort(ascendingSourceBreadth);
311
+ }
312
+ }
313
+ }
314
+ function reorderLinks(nodes) {
315
+ if (linkSort === undefined) {
316
+ for (const { sourceLinks, targetLinks } of nodes) {
317
+ sourceLinks.sort(ascendingTargetBreadth);
318
+ targetLinks.sort(ascendingSourceBreadth);
319
+ }
320
+ }
321
+ }
322
+ function targetTop(source, target) {
323
+ let y = source.y0 - ((source.sourceLinks.length - 1) * py) / 2;
324
+ for (const { target: node, width } of source.sourceLinks) {
325
+ if (node === target)
326
+ break;
327
+ y += width + py;
328
+ }
329
+ for (const { source: node, width } of target.targetLinks) {
330
+ if (node === source)
331
+ break;
332
+ y -= width;
333
+ }
334
+ return y;
335
+ }
336
+ function sourceTop(source, target) {
337
+ let y = target.y0 - ((target.targetLinks.length - 1) * py) / 2;
338
+ for (const { source: node, width } of target.targetLinks) {
339
+ if (node === source)
340
+ break;
341
+ y += width + py;
342
+ }
343
+ for (const { target: node, width } of source.sourceLinks) {
344
+ if (node === target)
345
+ break;
346
+ y -= width;
347
+ }
348
+ return y;
349
+ }
350
+ return generator;
351
+ }
352
+ export function sankeyLinkHorizontal() {
353
+ return linkHorizontal()
354
+ .source((d) => [d.source.x1, d.y0])
355
+ .target((d) => [d.target.x0, d.y1]);
356
+ }
357
+ function findNode(nodeById, id) {
358
+ const node = nodeById.get(id);
359
+ if (!node)
360
+ throw new Error('missing: ' + id);
361
+ return node;
362
+ }
@@ -3,7 +3,7 @@
3
3
  .gcharts-radar__label,
4
4
  .gcharts-heatmap__label,
5
5
  .gcharts-funnel__label {
6
- dominant-baseline: text-before-edge;
6
+ dominant-baseline: hanging;
7
7
  }
8
8
 
9
9
  .gcharts-scatter__point {
@@ -17,7 +17,7 @@
17
17
  font-size: 11px;
18
18
  font-weight: bold;
19
19
  fill: var(--g-color-text-complementary);
20
- dominant-baseline: text-before-edge;
20
+ dominant-baseline: hanging;
21
21
  }
22
22
 
23
23
  .gcharts-bar-x__label {
@@ -28,14 +28,14 @@
28
28
  .gcharts-bar-y__label {
29
29
  user-select: none;
30
30
  fill: var(--g-color-text-complementary);
31
- dominant-baseline: text-after-edge;
31
+ dominant-baseline: hanging;
32
32
  }
33
33
 
34
34
  .gcharts-treemap__label {
35
35
  user-select: none;
36
36
  pointer-events: none;
37
37
  fill: var(--g-color-text-complementary);
38
- dominant-baseline: text-before-edge;
38
+ dominant-baseline: hanging;
39
39
  }
40
40
 
41
41
  .gcharts-waterfall__connector {
@@ -22,6 +22,7 @@ async function getLabels(args) {
22
22
  const label = getFormattedValue(Object.assign({ value: text }, args.options));
23
23
  let labelMaxHeight = 0;
24
24
  let labelMaxWidth = 0;
25
+ let hangingOffset = 0;
25
26
  if (html) {
26
27
  const size = (_a = (await getLabelsSize({
27
28
  labels: [label],
@@ -35,9 +36,10 @@ async function getLabels(args) {
35
36
  const size = await getTextSize(label);
36
37
  labelMaxHeight = size.height;
37
38
  labelMaxWidth = size.width;
39
+ hangingOffset = size.hangingOffset;
38
40
  }
39
41
  let x = left;
40
- const y = prevLabelsHeight + d.y0 + padding;
42
+ const y = prevLabelsHeight + d.y0 + padding + hangingOffset;
41
43
  const labelWidth = Math.min(labelMaxWidth, spaceWidth);
42
44
  const labelHeight = Math.min(labelMaxHeight, availableSpaceHeight);
43
45
  if (!labelWidth || y > d.y1) {
@@ -1,5 +1,5 @@
1
1
  import type { Dispatch } from 'd3-dispatch';
2
- import type { AxisPlotBand, AxisPlotLine, PointPosition, TooltipDataChunk } from '../../types';
2
+ import type { AxisPlotBand, AxisPlotLine, AxisPlotShape, PointPosition, TooltipDataChunk } from '../../types';
3
3
  import type { PreparedTooltip } from '../types';
4
4
  import type { PreparedXAxis, PreparedYAxis } from '../useAxis/types';
5
5
  type Args = {
@@ -10,8 +10,9 @@ type Args = {
10
10
  };
11
11
  export declare const useTooltip: ({ dispatcher, tooltip, xAxis, yAxis }: Args) => {
12
12
  hovered: TooltipDataChunk[] | undefined;
13
- hoveredPlotLines: AxisPlotLine[] | undefined;
14
13
  hoveredPlotBands: AxisPlotBand[] | undefined;
14
+ hoveredPlotLines: AxisPlotLine[] | undefined;
15
+ hoveredPlotShapes: AxisPlotShape[] | undefined;
15
16
  pointerPosition: PointPosition | undefined;
16
17
  };
17
18
  export {};