@gravity-ui/charts 1.15.0 → 1.17.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 (141) hide show
  1. package/dist/{esm/components/Axis → cjs/components/AxisX}/AxisX.js +1 -15
  2. package/dist/cjs/components/{Axis → AxisY}/AxisY.d.ts +2 -10
  3. package/dist/cjs/components/AxisY/AxisY.js +173 -0
  4. package/dist/cjs/components/AxisY/prepare-axis-data.d.ts +9 -0
  5. package/dist/cjs/components/AxisY/prepare-axis-data.js +306 -0
  6. package/dist/cjs/components/AxisY/styles.css +15 -0
  7. package/dist/cjs/components/AxisY/types.d.ts +81 -0
  8. package/dist/cjs/components/AxisY/types.js +1 -0
  9. package/dist/cjs/components/AxisY/utils.d.ts +12 -0
  10. package/dist/cjs/components/AxisY/utils.js +71 -0
  11. package/dist/cjs/components/ChartInner/index.js +31 -3
  12. package/dist/cjs/components/ChartInner/useChartInnerProps.js +13 -1
  13. package/dist/cjs/components/Tooltip/ChartTooltipContent.d.ts +4 -2
  14. package/dist/cjs/components/Tooltip/ChartTooltipContent.js +2 -2
  15. package/dist/cjs/components/Tooltip/DefaultTooltipContent/Row.d.ts +2 -1
  16. package/dist/cjs/components/Tooltip/DefaultTooltipContent/Row.js +3 -3
  17. package/dist/cjs/components/Tooltip/DefaultTooltipContent/{RowTotals.d.ts → RowWithAggregation.d.ts} +2 -1
  18. package/dist/cjs/components/Tooltip/DefaultTooltipContent/{RowTotals.js → RowWithAggregation.js} +3 -3
  19. package/dist/cjs/components/Tooltip/DefaultTooltipContent/index.d.ts +4 -2
  20. package/dist/cjs/components/Tooltip/DefaultTooltipContent/index.js +174 -114
  21. package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.d.ts +7 -1
  22. package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.js +12 -7
  23. package/dist/cjs/components/Tooltip/index.js +1 -1
  24. package/dist/cjs/components/Tooltip/styles.css +11 -1
  25. package/dist/cjs/constants/date.d.ts +1 -0
  26. package/dist/cjs/constants/date.js +1 -0
  27. package/dist/cjs/constants/index.d.ts +1 -0
  28. package/dist/cjs/constants/index.js +1 -0
  29. package/dist/cjs/hooks/useChartOptions/types.d.ts +7 -1
  30. package/dist/cjs/hooks/useChartOptions/x-axis.js +5 -5
  31. package/dist/cjs/hooks/useChartOptions/y-axis.d.ts +3 -1
  32. package/dist/cjs/hooks/useChartOptions/y-axis.js +20 -20
  33. package/dist/cjs/hooks/useCrosshair/index.js +2 -1
  34. package/dist/cjs/hooks/useSeries/prepare-area.js +1 -0
  35. package/dist/cjs/hooks/useSeries/prepare-bar-x.js +1 -0
  36. package/dist/cjs/hooks/useSeries/prepare-bar-y.d.ts +1 -0
  37. package/dist/cjs/hooks/useSeries/prepare-bar-y.js +1 -0
  38. package/dist/cjs/hooks/useSeries/prepare-line.js +1 -0
  39. package/dist/cjs/hooks/useSeries/prepare-pie.js +1 -0
  40. package/dist/cjs/hooks/useSeries/prepare-radar.js +1 -0
  41. package/dist/cjs/hooks/useSeries/prepare-sankey.js +1 -0
  42. package/dist/cjs/hooks/useSeries/prepare-scatter.js +1 -0
  43. package/dist/cjs/hooks/useSeries/prepare-treemap.js +1 -0
  44. package/dist/cjs/hooks/useSeries/prepare-waterfall.js +1 -0
  45. package/dist/cjs/hooks/useSeries/types.d.ts +2 -1
  46. package/dist/cjs/i18n/keysets/en.json +2 -1
  47. package/dist/cjs/i18n/keysets/ru.json +2 -1
  48. package/dist/cjs/index.d.ts +1 -1
  49. package/dist/cjs/index.js +1 -1
  50. package/dist/cjs/types/chart/axis.d.ts +11 -1
  51. package/dist/cjs/types/chart/base.d.ts +14 -0
  52. package/dist/cjs/types/chart/tooltip.d.ts +5 -1
  53. package/dist/cjs/utils/chart/axis-generators/bottom.js +3 -3
  54. package/dist/cjs/utils/chart/axis.d.ts +14 -8
  55. package/dist/cjs/utils/chart/axis.js +34 -9
  56. package/dist/cjs/utils/chart/format.d.ts +9 -2
  57. package/dist/cjs/utils/chart/format.js +40 -5
  58. package/dist/cjs/utils/chart/index.d.ts +6 -17
  59. package/dist/cjs/utils/chart/index.js +6 -43
  60. package/dist/cjs/utils/chart/text.d.ts +2 -1
  61. package/dist/cjs/utils/chart/text.js +3 -10
  62. package/dist/cjs/utils/misc.d.ts +1 -0
  63. package/dist/cjs/utils/misc.js +6 -0
  64. package/dist/{cjs/components/Axis → esm/components/AxisX}/AxisX.js +1 -15
  65. package/dist/esm/components/{Axis → AxisY}/AxisY.d.ts +2 -10
  66. package/dist/esm/components/AxisY/AxisY.js +173 -0
  67. package/dist/esm/components/AxisY/prepare-axis-data.d.ts +9 -0
  68. package/dist/esm/components/AxisY/prepare-axis-data.js +306 -0
  69. package/dist/esm/components/AxisY/styles.css +15 -0
  70. package/dist/esm/components/AxisY/types.d.ts +81 -0
  71. package/dist/esm/components/AxisY/types.js +1 -0
  72. package/dist/esm/components/AxisY/utils.d.ts +12 -0
  73. package/dist/esm/components/AxisY/utils.js +71 -0
  74. package/dist/esm/components/ChartInner/index.js +31 -3
  75. package/dist/esm/components/ChartInner/useChartInnerProps.js +13 -1
  76. package/dist/esm/components/Tooltip/ChartTooltipContent.d.ts +4 -2
  77. package/dist/esm/components/Tooltip/ChartTooltipContent.js +2 -2
  78. package/dist/esm/components/Tooltip/DefaultTooltipContent/Row.d.ts +2 -1
  79. package/dist/esm/components/Tooltip/DefaultTooltipContent/Row.js +3 -3
  80. package/dist/esm/components/Tooltip/DefaultTooltipContent/{RowTotals.d.ts → RowWithAggregation.d.ts} +2 -1
  81. package/dist/esm/components/Tooltip/DefaultTooltipContent/{RowTotals.js → RowWithAggregation.js} +3 -3
  82. package/dist/esm/components/Tooltip/DefaultTooltipContent/index.d.ts +4 -2
  83. package/dist/esm/components/Tooltip/DefaultTooltipContent/index.js +174 -114
  84. package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.d.ts +7 -1
  85. package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.js +12 -7
  86. package/dist/esm/components/Tooltip/index.js +1 -1
  87. package/dist/esm/components/Tooltip/styles.css +11 -1
  88. package/dist/esm/constants/date.d.ts +1 -0
  89. package/dist/esm/constants/date.js +1 -0
  90. package/dist/esm/constants/index.d.ts +1 -0
  91. package/dist/esm/constants/index.js +1 -0
  92. package/dist/esm/hooks/useChartOptions/types.d.ts +7 -1
  93. package/dist/esm/hooks/useChartOptions/x-axis.js +5 -5
  94. package/dist/esm/hooks/useChartOptions/y-axis.d.ts +3 -1
  95. package/dist/esm/hooks/useChartOptions/y-axis.js +20 -20
  96. package/dist/esm/hooks/useCrosshair/index.js +2 -1
  97. package/dist/esm/hooks/useSeries/prepare-area.js +1 -0
  98. package/dist/esm/hooks/useSeries/prepare-bar-x.js +1 -0
  99. package/dist/esm/hooks/useSeries/prepare-bar-y.d.ts +1 -0
  100. package/dist/esm/hooks/useSeries/prepare-bar-y.js +1 -0
  101. package/dist/esm/hooks/useSeries/prepare-line.js +1 -0
  102. package/dist/esm/hooks/useSeries/prepare-pie.js +1 -0
  103. package/dist/esm/hooks/useSeries/prepare-radar.js +1 -0
  104. package/dist/esm/hooks/useSeries/prepare-sankey.js +1 -0
  105. package/dist/esm/hooks/useSeries/prepare-scatter.js +1 -0
  106. package/dist/esm/hooks/useSeries/prepare-treemap.js +1 -0
  107. package/dist/esm/hooks/useSeries/prepare-waterfall.js +1 -0
  108. package/dist/esm/hooks/useSeries/types.d.ts +2 -1
  109. package/dist/esm/i18n/keysets/en.json +2 -1
  110. package/dist/esm/i18n/keysets/ru.json +2 -1
  111. package/dist/esm/index.d.ts +1 -1
  112. package/dist/esm/index.js +1 -1
  113. package/dist/esm/types/chart/axis.d.ts +11 -1
  114. package/dist/esm/types/chart/base.d.ts +14 -0
  115. package/dist/esm/types/chart/tooltip.d.ts +5 -1
  116. package/dist/esm/utils/chart/axis-generators/bottom.js +3 -3
  117. package/dist/esm/utils/chart/axis.d.ts +14 -8
  118. package/dist/esm/utils/chart/axis.js +34 -9
  119. package/dist/esm/utils/chart/format.d.ts +9 -2
  120. package/dist/esm/utils/chart/format.js +40 -5
  121. package/dist/esm/utils/chart/index.d.ts +6 -17
  122. package/dist/esm/utils/chart/index.js +6 -43
  123. package/dist/esm/utils/chart/text.d.ts +2 -1
  124. package/dist/esm/utils/chart/text.js +3 -10
  125. package/dist/esm/utils/misc.d.ts +1 -0
  126. package/dist/esm/utils/misc.js +6 -0
  127. package/package.json +1 -1
  128. package/dist/cjs/components/Axis/AxisY.js +0 -416
  129. package/dist/cjs/components/Axis/index.d.ts +0 -2
  130. package/dist/cjs/components/Axis/index.js +0 -2
  131. package/dist/cjs/components/Tooltip/utils.d.ts +0 -30
  132. package/dist/cjs/components/Tooltip/utils.js +0 -126
  133. package/dist/esm/components/Axis/AxisY.js +0 -416
  134. package/dist/esm/components/Axis/index.d.ts +0 -2
  135. package/dist/esm/components/Axis/index.js +0 -2
  136. package/dist/esm/components/Tooltip/utils.d.ts +0 -30
  137. package/dist/esm/components/Tooltip/utils.js +0 -126
  138. /package/dist/cjs/components/{Axis → AxisX}/AxisX.d.ts +0 -0
  139. /package/dist/cjs/components/{Axis → AxisX}/styles.css +0 -0
  140. /package/dist/esm/components/{Axis → AxisX}/AxisX.d.ts +0 -0
  141. /package/dist/esm/components/{Axis → AxisX}/styles.css +0 -0
@@ -2,11 +2,13 @@ import React from 'react';
2
2
  import type { ChartTooltip, ChartXAxis, ChartYAxis, TooltipDataChunk, ValueFormat } from '../../../types';
3
3
  type Props = {
4
4
  hovered: TooltipDataChunk[];
5
+ pinned?: boolean;
6
+ rowRenderer?: ChartTooltip['rowRenderer'];
5
7
  totals?: ChartTooltip['totals'];
6
8
  valueFormat?: ValueFormat;
9
+ headerFormat?: ChartTooltip['headerFormat'];
7
10
  xAxis?: ChartXAxis | null;
8
11
  yAxis?: ChartYAxis;
9
- rowRenderer?: ChartTooltip['rowRenderer'];
10
12
  };
11
- export declare const DefaultTooltipContent: ({ hovered, xAxis, yAxis, valueFormat, totals, rowRenderer, }: Props) => React.JSX.Element;
13
+ export declare const DefaultTooltipContent: ({ hovered, pinned, rowRenderer, totals, valueFormat, headerFormat, xAxis, yAxis, }: Props) => React.JSX.Element;
12
14
  export {};
@@ -1,15 +1,26 @@
1
1
  import React from 'react';
2
2
  import { Divider } from '@gravity-ui/uikit';
3
3
  import get from 'lodash/get';
4
- import { block } from '../../../utils';
4
+ import isEqual from 'lodash/isEqual';
5
+ import { usePrevious } from '../../../hooks';
6
+ import { i18n } from '../../../i18n';
7
+ import { block, hasVerticalScrollbar } from '../../../utils';
5
8
  import { getFormattedValue } from '../../../utils/chart/format';
6
9
  import { Row } from './Row';
7
- import { RowTotals } from './RowTotals';
10
+ import { RowWithAggregation } from './RowWithAggregation';
8
11
  import { getDefaultValueFormat, getHoveredValues, getMeasureValue, getPreparedAggregation, getXRowData, } from './utils';
9
12
  const b = block('tooltip');
10
- export const DefaultTooltipContent = ({ hovered, xAxis, yAxis, valueFormat, totals, rowRenderer, }) => {
13
+ export const DefaultTooltipContent = ({ hovered, pinned, rowRenderer, totals, valueFormat, headerFormat, xAxis, yAxis, }) => {
14
+ var _a;
15
+ const [visibleRows, setVisibleRows] = React.useState();
16
+ const [maxContentRowsHeight, setMaxContentRowsHeight] = React.useState();
17
+ const [scrollBarWidth, setScrollBarWidth] = React.useState(0);
18
+ const contentRowsRef = React.useRef(null);
11
19
  const measureValue = getMeasureValue({ data: hovered, xAxis, yAxis });
12
20
  const hoveredValues = getHoveredValues({ hovered, xAxis, yAxis });
21
+ const prevHoveredValues = usePrevious(hoveredValues);
22
+ const visibleHovered = pinned || !visibleRows ? hovered : hovered.slice(0, visibleRows);
23
+ const restHoveredValues = pinned || !visibleRows ? [] : hoveredValues.slice(visibleRows);
13
24
  const renderRow = ({ id, name, color, active, striped, value, formattedValue, }) => {
14
25
  if (typeof rowRenderer === 'function') {
15
26
  return rowRenderer({
@@ -26,120 +37,169 @@ export const DefaultTooltipContent = ({ hovered, xAxis, yAxis, valueFormat, tota
26
37
  }
27
38
  return (React.createElement(Row, { key: id, active: active, color: color, label: React.createElement("span", { dangerouslySetInnerHTML: { __html: name } }), striped: striped, value: formattedValue }));
28
39
  };
29
- return (React.createElement("div", { className: b('content') },
30
- measureValue && (React.createElement("div", { className: b('series-name'), dangerouslySetInnerHTML: { __html: measureValue } })),
31
- // eslint-disable-next-line complexity
32
- hovered.map((seriesItem, i) => {
33
- var _a;
34
- const { data, series, closest } = seriesItem;
35
- const id = `${get(series, 'id')}_${i}`;
36
- const color = get(data, 'color') || get(series, 'color');
37
- const active = closest && hovered.length > 1;
38
- const striped = (i + 1) % 2 === 0;
39
- switch (series.type) {
40
- case 'scatter':
41
- case 'line':
42
- case 'area':
43
- case 'bar-x': {
44
- const format = valueFormat || getDefaultValueFormat({ axis: yAxis });
45
- const formattedValue = getFormattedValue({
46
- value: hoveredValues[i],
47
- format,
48
- });
49
- return renderRow({
50
- id,
51
- active,
52
- color,
53
- name: series.name,
54
- striped,
55
- value: hoveredValues[i],
56
- formattedValue,
57
- });
58
- }
59
- case 'waterfall': {
60
- const isTotal = get(data, 'total', false);
61
- const subTotalValue = (_a = seriesItem.subTotal) !== null && _a !== void 0 ? _a : 0;
62
- const format = valueFormat || getDefaultValueFormat({ axis: yAxis });
63
- const subTotal = getFormattedValue({
64
- value: subTotalValue,
65
- format,
66
- });
67
- const formattedValue = getFormattedValue({
68
- value: hoveredValues[i],
69
- format,
70
- });
71
- return (React.createElement(React.Fragment, { key: id },
72
- !isTotal && (React.createElement(React.Fragment, null,
73
- React.createElement("div", { className: b('series-name') }, getXRowData(data, xAxis)),
74
- React.createElement(Row, { label: series.name, value: formattedValue }))),
75
- React.createElement(Row, { label: isTotal ? 'Total' : 'Subtotal', value: subTotal })));
76
- }
77
- case 'bar-y': {
78
- const format = valueFormat || getDefaultValueFormat({ axis: xAxis });
79
- const formattedValue = getFormattedValue({
80
- value: hoveredValues[i],
81
- format,
82
- });
83
- return renderRow({
84
- id,
85
- active,
86
- color,
87
- name: series.name,
88
- striped,
89
- value: hoveredValues[i],
90
- formattedValue,
91
- });
92
- }
93
- case 'pie':
94
- case 'treemap': {
95
- const seriesData = data;
96
- const formattedValue = getFormattedValue({
97
- value: hoveredValues[i],
98
- format: valueFormat || { type: 'number' },
99
- });
100
- return renderRow({
101
- id,
102
- color,
103
- name: [seriesData.name || seriesData.id].flat().join('\n'),
104
- value: hoveredValues[i],
105
- formattedValue,
106
- });
107
- }
108
- case 'sankey': {
109
- const { target, data: source } = seriesItem;
110
- const formattedValue = getFormattedValue({
111
- value: hoveredValues[i],
112
- format: valueFormat || { type: 'number' },
113
- });
114
- return renderRow({
115
- id,
116
- color,
117
- name: `${source.name} → ${target === null || target === void 0 ? void 0 : target.name}`,
118
- value: hoveredValues[i],
119
- formattedValue,
120
- });
121
- }
122
- case 'radar': {
123
- const radarSeries = series;
124
- const formattedValue = getFormattedValue({
125
- value: hoveredValues[i],
126
- format: valueFormat || { type: 'number' },
127
- });
128
- return renderRow({
129
- id,
130
- color,
131
- active,
132
- name: radarSeries.name || radarSeries.id,
133
- value: hoveredValues[i],
134
- formattedValue,
135
- });
40
+ const formattedHeadValue = headerFormat
41
+ ? getFormattedValue({
42
+ value: measureValue === null || measureValue === void 0 ? void 0 : measureValue.value,
43
+ format: headerFormat,
44
+ })
45
+ : measureValue === null || measureValue === void 0 ? void 0 : measureValue.formattedValue;
46
+ React.useEffect(() => {
47
+ if (!contentRowsRef.current) {
48
+ return;
49
+ }
50
+ if (!hasVerticalScrollbar(contentRowsRef.current)) {
51
+ return;
52
+ }
53
+ if (!isEqual(hoveredValues, prevHoveredValues)) {
54
+ const { clientHeight } = contentRowsRef.current;
55
+ const { top: containerTop } = contentRowsRef.current.getBoundingClientRect();
56
+ const rows = contentRowsRef.current.querySelectorAll(`.${b('content-row')}`);
57
+ let nextVisibleRows = 0;
58
+ let nextMaxContentRowsHeight = 0;
59
+ for (let i = 0; i < rows.length; i++) {
60
+ const row = rows[i];
61
+ const { top, height } = row.getBoundingClientRect();
62
+ if (top - containerTop + height <= clientHeight) {
63
+ nextVisibleRows += 1;
64
+ nextMaxContentRowsHeight += height;
136
65
  }
137
- default: {
138
- return null;
66
+ else {
67
+ break;
139
68
  }
140
69
  }
141
- }),
70
+ setVisibleRows(nextVisibleRows - 1);
71
+ setMaxContentRowsHeight(nextMaxContentRowsHeight);
72
+ }
73
+ }, [hoveredValues, prevHoveredValues]);
74
+ React.useEffect(() => {
75
+ if (!contentRowsRef.current) {
76
+ return;
77
+ }
78
+ if (pinned) {
79
+ const { offsetWidth, clientWidth } = contentRowsRef.current;
80
+ setScrollBarWidth(offsetWidth - clientWidth);
81
+ }
82
+ else {
83
+ setScrollBarWidth(0);
84
+ }
85
+ }, [pinned]);
86
+ return (React.createElement("div", { className: b('content') },
87
+ formattedHeadValue && (React.createElement("div", { className: b('series-name'), dangerouslySetInnerHTML: { __html: formattedHeadValue } })),
88
+ React.createElement("div", { className: b('content-rows', { pinned }), ref: contentRowsRef, style: { maxHeight: maxContentRowsHeight } },
89
+ visibleHovered.map((seriesItem, i) => {
90
+ var _a;
91
+ const { data, series, closest } = seriesItem;
92
+ const id = `${get(series, 'id')}_${i}`;
93
+ const color = get(data, 'color') || get(series, 'color');
94
+ // TODO: improve action item display https://github.com/gravity-ui/charts/issues/208
95
+ const active = closest && hovered.length > 1;
96
+ const striped = (i + 1) % 2 === 0;
97
+ const rowValueFormat = get(series, 'tooltip.valueFormat', valueFormat);
98
+ switch (series.type) {
99
+ case 'scatter':
100
+ case 'line':
101
+ case 'area':
102
+ case 'bar-x': {
103
+ const format = rowValueFormat || getDefaultValueFormat({ axis: yAxis });
104
+ const formattedValue = getFormattedValue({
105
+ value: hoveredValues[i],
106
+ format,
107
+ });
108
+ return renderRow({
109
+ id,
110
+ active,
111
+ color,
112
+ name: series.name,
113
+ striped,
114
+ value: hoveredValues[i],
115
+ formattedValue,
116
+ });
117
+ }
118
+ case 'waterfall': {
119
+ const isTotal = get(data, 'total', false);
120
+ const subTotalValue = (_a = seriesItem.subTotal) !== null && _a !== void 0 ? _a : 0;
121
+ const format = rowValueFormat || getDefaultValueFormat({ axis: yAxis });
122
+ const subTotal = getFormattedValue({
123
+ value: subTotalValue,
124
+ format,
125
+ });
126
+ const formattedValue = getFormattedValue({
127
+ value: hoveredValues[i],
128
+ format,
129
+ });
130
+ return (React.createElement(React.Fragment, { key: id },
131
+ !isTotal && (React.createElement(React.Fragment, null,
132
+ React.createElement("div", { className: b('series-name') }, getXRowData(data, xAxis)),
133
+ React.createElement(Row, { label: series.name, value: formattedValue }))),
134
+ React.createElement(Row, { label: isTotal ? 'Total' : 'Subtotal', value: subTotal })));
135
+ }
136
+ case 'bar-y': {
137
+ const format = rowValueFormat || getDefaultValueFormat({ axis: xAxis });
138
+ const formattedValue = getFormattedValue({
139
+ value: hoveredValues[i],
140
+ format,
141
+ });
142
+ return renderRow({
143
+ id,
144
+ active,
145
+ color,
146
+ name: series.name,
147
+ striped,
148
+ value: hoveredValues[i],
149
+ formattedValue,
150
+ });
151
+ }
152
+ case 'pie':
153
+ case 'treemap': {
154
+ const seriesData = data;
155
+ const formattedValue = getFormattedValue({
156
+ value: hoveredValues[i],
157
+ format: rowValueFormat || { type: 'number' },
158
+ });
159
+ return renderRow({
160
+ id,
161
+ color,
162
+ name: [seriesData.name || seriesData.id].flat().join('\n'),
163
+ value: hoveredValues[i],
164
+ formattedValue,
165
+ });
166
+ }
167
+ case 'sankey': {
168
+ const { target, data: source } = seriesItem;
169
+ const formattedValue = getFormattedValue({
170
+ value: hoveredValues[i],
171
+ format: rowValueFormat || { type: 'number' },
172
+ });
173
+ return renderRow({
174
+ id,
175
+ color,
176
+ name: `${source.name} → ${target === null || target === void 0 ? void 0 : target.name}`,
177
+ value: hoveredValues[i],
178
+ formattedValue,
179
+ });
180
+ }
181
+ case 'radar': {
182
+ const radarSeries = series;
183
+ const formattedValue = getFormattedValue({
184
+ value: hoveredValues[i],
185
+ format: rowValueFormat || { type: 'number' },
186
+ });
187
+ return renderRow({
188
+ id,
189
+ color,
190
+ active,
191
+ name: radarSeries.name || radarSeries.id,
192
+ value: hoveredValues[i],
193
+ formattedValue,
194
+ });
195
+ }
196
+ default: {
197
+ return null;
198
+ }
199
+ }
200
+ }),
201
+ Boolean(restHoveredValues.length) && (React.createElement(Row, { label: i18n('tooltip', 'label_more', { count: restHoveredValues.length }), striped: (visibleHovered.length + 1) % 2 === 0 }))),
142
202
  (totals === null || totals === void 0 ? void 0 : totals.enabled) && hovered.length > 1 && (React.createElement(React.Fragment, null,
143
203
  React.createElement(Divider, { className: b('content-row-totals-divider') }),
144
- React.createElement(RowTotals, { aggregation: getPreparedAggregation({ hovered, totals, xAxis, yAxis }), label: totals.label, values: hoveredValues, valueFormat: valueFormat })))));
204
+ React.createElement(RowWithAggregation, { aggregation: getPreparedAggregation({ hovered, totals, xAxis, yAxis }), label: totals.label, style: { marginRight: scrollBarWidth }, values: hoveredValues, valueFormat: (_a = totals.valueFormat) !== null && _a !== void 0 ? _a : valueFormat })))));
145
205
  };
@@ -9,7 +9,13 @@ export declare const getMeasureValue: ({ data, xAxis, yAxis, valueFormat, }: {
9
9
  xAxis?: ChartXAxis | null;
10
10
  yAxis?: ChartYAxis;
11
11
  valueFormat?: ValueFormat;
12
- }) => string | null;
12
+ }) => {
13
+ value: string | null;
14
+ formattedValue?: undefined;
15
+ } | {
16
+ value: string | number | undefined;
17
+ formattedValue: string;
18
+ } | null;
13
19
  export declare function getHoveredValues(args: {
14
20
  hovered: TooltipDataChunk[];
15
21
  xAxis?: ChartXAxis | null;
@@ -1,8 +1,8 @@
1
1
  import get from 'lodash/get';
2
+ import { DEFAULT_DATE_FORMAT } from '../../../constants';
2
3
  import { i18n } from '../../../i18n';
3
4
  import { getDataCategoryValue } from '../../../utils';
4
5
  import { getFormattedValue } from '../../../utils/chart/format';
5
- const DEFAULT_DATE_FORMAT = 'DD.MM.YY';
6
6
  function getRowData(fieldName, data, axis) {
7
7
  switch (axis === null || axis === void 0 ? void 0 : axis.type) {
8
8
  case 'category': {
@@ -39,25 +39,30 @@ export function getDefaultValueFormat({ axis, }) {
39
39
  }
40
40
  }
41
41
  export const getMeasureValue = ({ data, xAxis, yAxis, valueFormat, }) => {
42
- var _a, _b, _c, _d;
42
+ var _a, _b, _c, _d, _e, _f;
43
43
  if (data.every((item) => ['pie', 'treemap', 'waterfall', 'sankey'].includes(item.series.type))) {
44
44
  return null;
45
45
  }
46
46
  if (data.some((item) => item.series.type === 'radar')) {
47
- return (_b = (_a = data[0].category) === null || _a === void 0 ? void 0 : _a.key) !== null && _b !== void 0 ? _b : null;
47
+ const value = (_b = (_a = data[0].category) === null || _a === void 0 ? void 0 : _a.key) !== null && _b !== void 0 ? _b : null;
48
+ return { value };
48
49
  }
49
50
  if (data.some((item) => item.series.type === 'bar-y')) {
51
+ const value = getYRowData((_c = data[0]) === null || _c === void 0 ? void 0 : _c.data, yAxis);
50
52
  const format = valueFormat !== null && valueFormat !== void 0 ? valueFormat : getDefaultValueFormat({ axis: yAxis });
51
- return getFormattedValue({
52
- value: getYRowData((_c = data[0]) === null || _c === void 0 ? void 0 : _c.data, yAxis),
53
+ const formattedValue = getFormattedValue({
54
+ value: getYRowData((_d = data[0]) === null || _d === void 0 ? void 0 : _d.data, yAxis),
53
55
  format,
54
56
  });
57
+ return { value, formattedValue };
55
58
  }
59
+ const value = getXRowData((_e = data[0]) === null || _e === void 0 ? void 0 : _e.data, xAxis);
56
60
  const format = valueFormat !== null && valueFormat !== void 0 ? valueFormat : getDefaultValueFormat({ axis: xAxis });
57
- return getFormattedValue({
58
- value: getXRowData((_d = data[0]) === null || _d === void 0 ? void 0 : _d.data, xAxis),
61
+ const formattedValue = getFormattedValue({
62
+ value: getXRowData((_f = data[0]) === null || _f === void 0 ? void 0 : _f.data, xAxis),
59
63
  format,
60
64
  });
65
+ return { value, formattedValue };
61
66
  };
62
67
  export function getHoveredValues(args) {
63
68
  const { hovered, xAxis, yAxis } = args;
@@ -23,5 +23,5 @@ export const Tooltip = (props) => {
23
23
  }, [left, top]);
24
24
  return (hovered === null || hovered === void 0 ? void 0 : hovered.length) ? (React.createElement(Popup, { anchorElement: anchor, className: b({ pinned: tooltipPinned }), disableTransition: true, floatingStyles: tooltipPinned ? undefined : { pointerEvents: 'none' }, offset: { mainAxis: 20 }, onOpenChange: tooltipPinned ? handleOnOpenChange : undefined, open: true, placement: ['right', 'left', 'top', 'bottom'] },
25
25
  React.createElement("div", { className: b('popup-content') },
26
- React.createElement(ChartTooltipContent, { hovered: hovered, xAxis: xAxis, yAxis: yAxis, renderer: tooltip.renderer, rowRenderer: tooltip.rowRenderer, valueFormat: tooltip.valueFormat, totals: tooltip.totals })))) : null;
26
+ React.createElement(ChartTooltipContent, { hovered: hovered, pinned: tooltipPinned, renderer: tooltip.renderer, rowRenderer: tooltip.rowRenderer, totals: tooltip.totals, valueFormat: tooltip.valueFormat, headerFormat: tooltip.headerFormat, xAxis: xAxis, yAxis: yAxis })))) : null;
27
27
  };
@@ -1,4 +1,5 @@
1
1
  .gcharts-tooltip {
2
+ padding: var(--gcharts-tooltip-content-padding, 8px 0);
2
3
  box-shadow: 0 2px 12px var(--g-color-sfx-shadow);
3
4
  }
4
5
  .gcharts-tooltip__popup-content {
@@ -7,7 +8,16 @@
7
8
  background-color: var(--g-color-infographics-tooltip-bg);
8
9
  }
9
10
  .gcharts-tooltip__content {
10
- padding: var(--gcharts-tooltip-content-padding, 8px 0);
11
+ display: flex;
12
+ overflow: hidden;
13
+ flex-direction: column;
14
+ max-height: 90vh;
15
+ }
16
+ .gcharts-tooltip__content-rows {
17
+ overflow: hidden;
18
+ }
19
+ .gcharts-tooltip__content-rows_pinned {
20
+ overflow: auto;
11
21
  }
12
22
  .gcharts-tooltip__series-name {
13
23
  padding: 2px 14px 6px;
@@ -0,0 +1 @@
1
+ export declare const DEFAULT_DATE_FORMAT = "DD.MM.YY";
@@ -0,0 +1 @@
1
+ export const DEFAULT_DATE_FORMAT = 'DD.MM.YY';
@@ -1,5 +1,6 @@
1
1
  export * from './axis';
2
2
  export * from './chart-types';
3
+ export * from './date';
3
4
  export * from './defaults';
4
5
  export * from './layout-algorithms';
5
6
  export * from './line-styles';
@@ -1,5 +1,6 @@
1
1
  export * from './axis';
2
2
  export * from './chart-types';
3
+ export * from './date';
3
4
  export * from './defaults';
4
5
  export * from './layout-algorithms';
5
6
  export * from './line-styles';
@@ -13,7 +13,13 @@ export type PreparedChart = {
13
13
  margin: ChartMargin;
14
14
  zoom: PreparedZoom | null;
15
15
  };
16
- export type PreparedAxisPlotBand = Required<AxisPlotBand>;
16
+ export type PreparedAxisPlotBand = Required<AxisPlotBand> & {
17
+ label: {
18
+ text: string;
19
+ style: BaseTextStyle;
20
+ padding: number;
21
+ };
22
+ };
17
23
  export type PreparedAxisCrosshair = Required<AxisCrosshair>;
18
24
  export type PreparedAxisPlotLine = {
19
25
  value: number;
@@ -1,12 +1,12 @@
1
1
  import get from 'lodash/get';
2
2
  import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, axisCrosshairDefaults, axisLabelsDefaults, xAxisTitleDefaults, } from '../../constants';
3
- import { calculateCos, formatAxisTickLabel, getClosestPointsRange, getHorizontalHtmlTextHeight, getHorizontalSvgTextHeight, getLabelsSize, getMaxTickCount, getTicksCount, getXAxisItems, hasOverlappingLabels, wrapText, } from '../../utils';
3
+ import { calculateCos, calculateNumericProperty, formatAxisTickLabel, getAxisItems, getClosestPointsRange, getHorizontalHtmlTextHeight, getHorizontalSvgTextHeight, getLabelsSize, getMaxTickCount, getTicksCount, hasOverlappingLabels, wrapText, } from '../../utils';
4
4
  import { createXScale } from '../useAxisScales';
5
5
  import { getAxisCategories, prepareAxisPlotLabel } from './utils';
6
6
  async function getLabelSettings({ axis, seriesData, seriesOptions, width, autoRotation = true, }) {
7
7
  const scale = createXScale({ axis, series: seriesData, seriesOptions, boundsWidth: width });
8
8
  const tickCount = getTicksCount({ axis, range: width });
9
- const ticks = getXAxisItems({
9
+ const ticks = getAxisItems({
10
10
  scale: scale,
11
11
  count: tickCount,
12
12
  maxCount: getMaxTickCount({ width, axis }),
@@ -41,7 +41,7 @@ async function getLabelSettings({ axis, seriesData, seriesOptions, width, autoRo
41
41
  return { height: Math.min(maxHeight, labelsHeight), rotation };
42
42
  }
43
43
  export const getPreparedXAxis = async ({ xAxis, seriesData, seriesOptions, width, }) => {
44
- var _a;
44
+ var _a, _b, _c;
45
45
  const titleText = get(xAxis, 'title.text', '');
46
46
  const titleStyle = Object.assign(Object.assign({}, xAxisTitleDefaults.style), get(xAxis, 'title.style'));
47
47
  const titleMaxRowsCount = get(xAxis, 'title.maxRowCount', xAxisTitleDefaults.maxRowCount);
@@ -74,7 +74,7 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, seriesOptions, width
74
74
  width: 0,
75
75
  height: 0,
76
76
  lineHeight: labelsLineHeight,
77
- maxWidth: get(xAxis, 'labels.maxWidth', axisLabelsDefaults.maxWidth),
77
+ maxWidth: (_b = calculateNumericProperty({ base: width, value: (_a = xAxis === null || xAxis === void 0 ? void 0 : xAxis.labels) === null || _a === void 0 ? void 0 : _a.maxWidth })) !== null && _b !== void 0 ? _b : axisLabelsDefaults.maxWidth,
78
78
  html: labelsHtml,
79
79
  },
80
80
  lineColor: get(xAxis, 'lineColor'),
@@ -134,7 +134,7 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, seriesOptions, width
134
134
  seriesData,
135
135
  seriesOptions,
136
136
  width,
137
- autoRotation: (_a = xAxis === null || xAxis === void 0 ? void 0 : xAxis.labels) === null || _a === void 0 ? void 0 : _a.autoRotation,
137
+ autoRotation: (_c = xAxis === null || xAxis === void 0 ? void 0 : xAxis.labels) === null || _c === void 0 ? void 0 : _c.autoRotation,
138
138
  });
139
139
  preparedXAxis.labels.height = height;
140
140
  preparedXAxis.labels.rotation = rotation;
@@ -1,8 +1,10 @@
1
1
  import type { ChartSeries, ChartYAxis } from '../../types';
2
2
  import type { PreparedSeriesOptions } from '../useSeries/types';
3
3
  import type { PreparedAxis } from './types';
4
- export declare const getPreparedYAxis: ({ height, seriesData, seriesOptions, yAxis, }: {
4
+ export declare const getPreparedYAxis: ({ height, boundsHeight, width, seriesData, seriesOptions, yAxis, }: {
5
5
  height: number;
6
+ boundsHeight: number;
7
+ width: number;
6
8
  seriesData: ChartSeries[];
7
9
  seriesOptions: PreparedSeriesOptions;
8
10
  yAxis: ChartYAxis[] | undefined;
@@ -1,27 +1,25 @@
1
1
  import get from 'lodash/get';
2
+ import { getTickValues } from '../../components/AxisY/utils';
2
3
  import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TYPE, axisCrosshairDefaults, axisLabelsDefaults, yAxisTitleDefaults, } from '../../constants';
3
- import { formatAxisTickLabel, getClosestPointsRange, getDefaultMinYAxisValue, getHorizontalHtmlTextHeight, getHorizontalSvgTextHeight, getLabelsSize, getScaleTicks, isAxisRelatedSeries, wrapText, } from '../../utils';
4
+ import { calculateNumericProperty, getDefaultMinYAxisValue, getHorizontalHtmlTextHeight, getHorizontalSvgTextHeight, getLabelFormatter, getLabelsSize, getTextSizeFn, isAxisRelatedSeries, wrapText, } from '../../utils';
4
5
  import { createYScale } from '../useAxisScales';
5
6
  import { getAxisCategories, prepareAxisPlotLabel } from './utils';
6
7
  const getAxisLabelMaxWidth = async (args) => {
7
- const { axis, seriesData, seriesOptions } = args;
8
+ const { axis, seriesData, seriesOptions, height } = args;
8
9
  if (!axis.labels.enabled) {
9
10
  return { height: 0, width: 0 };
10
11
  }
11
12
  const scale = createYScale({
12
13
  axis,
13
- boundsHeight: 1,
14
+ boundsHeight: height,
14
15
  series: seriesData,
15
16
  seriesOptions,
16
17
  });
17
- const ticks = getScaleTicks(scale);
18
- // FIXME: it is necessary to filter data, since we do not draw overlapping ticks
19
- const step = getClosestPointsRange(axis, ticks);
20
- const labels = ticks.map((tick) => formatAxisTickLabel({
21
- axis,
22
- value: tick,
23
- step,
24
- }));
18
+ const getTextSize = getTextSizeFn({ style: axis.labels.style });
19
+ const labelLineHeight = (await getTextSize('Tmp')).height;
20
+ const tickValues = getTickValues({ axis, scale, labelLineHeight });
21
+ const labelFormatter = getLabelFormatter({ axis, scale });
22
+ const labels = tickValues.map((tick) => labelFormatter(tick.value));
25
23
  const size = await getLabelsSize({
26
24
  labels,
27
25
  style: axis.labels.style,
@@ -30,7 +28,7 @@ const getAxisLabelMaxWidth = async (args) => {
30
28
  });
31
29
  return { height: size.maxHeight, width: size.maxWidth };
32
30
  };
33
- export const getPreparedYAxis = ({ height, seriesData, seriesOptions, yAxis, }) => {
31
+ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, seriesOptions, yAxis, }) => {
34
32
  const axisByPlot = [];
35
33
  const axisItems = yAxis || [{}];
36
34
  const hasAxisRelatedSeries = seriesData.some(isAxisRelatedSeries);
@@ -38,7 +36,7 @@ export const getPreparedYAxis = ({ height, seriesData, seriesOptions, yAxis, })
38
36
  return Promise.resolve([]);
39
37
  }
40
38
  return Promise.all(axisItems.map(async (axisItem) => {
41
- var _a, _b;
39
+ var _a, _b, _c, _d, _e, _f, _g;
42
40
  const plotIndex = get(axisItem, 'plotIndex', 0);
43
41
  const firstPlotAxis = !axisByPlot[plotIndex];
44
42
  if (firstPlotAxis) {
@@ -71,9 +69,7 @@ export const getPreparedYAxis = ({ height, seriesData, seriesOptions, yAxis, })
71
69
  margin: labelsEnabled
72
70
  ? get(axisItem, 'labels.margin', axisLabelsDefaults.margin)
73
71
  : 0,
74
- padding: labelsEnabled
75
- ? get(axisItem, 'labels.padding', axisLabelsDefaults.padding)
76
- : 0,
72
+ padding: labelsEnabled ? get(axisItem, 'labels.padding', 4) : 0,
77
73
  dateFormat: get(axisItem, 'labels.dateFormat'),
78
74
  numberFormat: get(axisItem, 'labels.numberFormat'),
79
75
  style: labelsStyle,
@@ -81,7 +77,7 @@ export const getPreparedYAxis = ({ height, seriesData, seriesOptions, yAxis, })
81
77
  width: 0,
82
78
  height: 0,
83
79
  lineHeight: labelsLineHeight,
84
- maxWidth: get(axisItem, 'labels.maxWidth', axisLabelsDefaults.maxWidth),
80
+ maxWidth: (_b = calculateNumericProperty({ base: width, value: (_a = axisItem.labels) === null || _a === void 0 ? void 0 : _a.maxWidth })) !== null && _b !== void 0 ? _b : axisLabelsDefaults.maxWidth,
85
81
  html: labelsHtml,
86
82
  },
87
83
  lineColor: get(axisItem, 'lineColor'),
@@ -96,15 +92,18 @@ export const getPreparedYAxis = ({ height, seriesData, seriesOptions, yAxis, })
96
92
  align: get(axisItem, 'title.align', yAxisTitleDefaults.align),
97
93
  maxRowCount: titleMaxRowsCount,
98
94
  },
99
- min: (_a = get(axisItem, 'min')) !== null && _a !== void 0 ? _a : getDefaultMinYAxisValue(seriesData),
95
+ min: (_c = get(axisItem, 'min')) !== null && _c !== void 0 ? _c : getDefaultMinYAxisValue(seriesData),
100
96
  max: get(axisItem, 'max'),
101
97
  maxPadding: get(axisItem, 'maxPadding', 0.05),
102
98
  grid: {
103
99
  enabled: get(axisItem, 'grid.enabled', firstPlotAxis ||
104
- (!firstPlotAxis && !((_b = axisByPlot[plotIndex][0].visible) !== null && _b !== void 0 ? _b : true))),
100
+ (!firstPlotAxis && !((_d = axisByPlot[plotIndex][0].visible) !== null && _d !== void 0 ? _d : true))),
105
101
  },
106
102
  ticks: {
107
- pixelInterval: get(axisItem, 'ticks.pixelInterval'),
103
+ pixelInterval: (_f = (_e = axisItem.ticks) === null || _e === void 0 ? void 0 : _e.pixelInterval) !== null && _f !== void 0 ? _f : calculateNumericProperty({
104
+ base: height,
105
+ value: (_g = axisItem.ticks) === null || _g === void 0 ? void 0 : _g.interval,
106
+ }),
108
107
  },
109
108
  position: get(axisItem, 'position', defaultAxisPosition),
110
109
  plotIndex: get(axisItem, 'plotIndex', 0),
@@ -142,6 +141,7 @@ export const getPreparedYAxis = ({ height, seriesData, seriesOptions, yAxis, })
142
141
  axis: preparedAxis,
143
142
  seriesData,
144
143
  seriesOptions,
144
+ height: boundsHeight,
145
145
  });
146
146
  preparedAxis.labels.height = labelsHeight;
147
147
  preparedAxis.labels.width =
@@ -68,6 +68,7 @@ export const useCrosshair = (props) => {
68
68
  }
69
69
  if (yAxis.crosshair.enabled && (hovered === null || hovered === void 0 ? void 0 : hovered.length)) {
70
70
  const crosshairDataAttr = `data-crosshair-y-line-${index}`;
71
+ const crosshairPosition = getAxisPlotsPosition(yAxis, split);
71
72
  const crosshairSelection = svgElement
72
73
  .selectAll(`[${crosshairDataAttr}]`)
73
74
  .data(hovered.filter((node) => {
@@ -82,7 +83,7 @@ export const useCrosshair = (props) => {
82
83
  .attr(plotCrosshairDataAttr, 1)
83
84
  .attr(crosshairDataAttr, 1)
84
85
  .style('transform', yAxis.crosshair.snap
85
- ? getAxisPlotsPosition(yAxis, split)
86
+ ? `translate(${crosshairPosition[0]}px, ${crosshairPosition[1]}px)`
86
87
  : 'translate(0, 0)');
87
88
  crosshairSelection
88
89
  .append('path')
@@ -59,6 +59,7 @@ export function prepareArea(args) {
59
59
  marker: prepareMarker(series, seriesOptions),
60
60
  cursor: get(series, 'cursor', null),
61
61
  yAxis: get(series, 'yAxis', 0),
62
+ tooltip: series.tooltip,
62
63
  };
63
64
  return prepared;
64
65
  }, []);