@gravity-ui/charts 1.39.1 → 1.41.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 (44) hide show
  1. package/README.md +4 -24
  2. package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +2 -38
  3. package/dist/cjs/components/ChartInner/utils/axis.d.ts +1 -37
  4. package/dist/cjs/components/Tooltip/DefaultTooltipContent/Row.js +4 -4
  5. package/dist/cjs/components/Tooltip/DefaultTooltipContent/RowWithAggregation.js +3 -2
  6. package/dist/cjs/components/Tooltip/DefaultTooltipContent/index.js +128 -118
  7. package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.d.ts +6 -0
  8. package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.js +41 -0
  9. package/dist/cjs/components/Tooltip/index.js +2 -0
  10. package/dist/cjs/components/Tooltip/styles.css +33 -7
  11. package/dist/cjs/components/index.d.ts +4 -1
  12. package/dist/cjs/components/index.js +8 -3
  13. package/dist/cjs/hooks/useAxis/index.d.ts +1 -37
  14. package/dist/cjs/hooks/useAxis/types.d.ts +6 -4
  15. package/dist/cjs/hooks/useAxisScales/index.d.ts +2 -2
  16. package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +3 -2
  17. package/dist/cjs/hooks/useShapes/bar-x/types.d.ts +5 -0
  18. package/dist/cjs/hooks/useTooltip/index.d.ts +4 -1
  19. package/dist/cjs/hooks/useTooltip/index.js +12 -5
  20. package/dist/cjs/types/chart/axis.d.ts +2 -1
  21. package/dist/cjs/types/chart/tooltip.d.ts +44 -1
  22. package/dist/cjs/utils/chart/zoom.js +2 -2
  23. package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +2 -38
  24. package/dist/esm/components/ChartInner/utils/axis.d.ts +1 -37
  25. package/dist/esm/components/Tooltip/DefaultTooltipContent/Row.js +4 -4
  26. package/dist/esm/components/Tooltip/DefaultTooltipContent/RowWithAggregation.js +3 -2
  27. package/dist/esm/components/Tooltip/DefaultTooltipContent/index.js +128 -118
  28. package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.d.ts +6 -0
  29. package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.js +41 -0
  30. package/dist/esm/components/Tooltip/index.js +2 -0
  31. package/dist/esm/components/Tooltip/styles.css +33 -7
  32. package/dist/esm/components/index.d.ts +4 -1
  33. package/dist/esm/components/index.js +8 -3
  34. package/dist/esm/hooks/useAxis/index.d.ts +1 -37
  35. package/dist/esm/hooks/useAxis/types.d.ts +6 -4
  36. package/dist/esm/hooks/useAxisScales/index.d.ts +2 -2
  37. package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +3 -2
  38. package/dist/esm/hooks/useShapes/bar-x/types.d.ts +5 -0
  39. package/dist/esm/hooks/useTooltip/index.d.ts +4 -1
  40. package/dist/esm/hooks/useTooltip/index.js +12 -5
  41. package/dist/esm/types/chart/axis.d.ts +2 -1
  42. package/dist/esm/types/chart/tooltip.d.ts +44 -1
  43. package/dist/esm/utils/chart/zoom.js +2 -2
  44. package/package.json +2 -1
package/README.md CHANGED
@@ -1,31 +1,11 @@
1
- # Gravity UI Charts
1
+ # Gravity UI Charts · [![npm package](https://img.shields.io/npm/v/@gravity-ui/charts)](https://www.npmjs.com/package/@gravity-ui/charts) [![License](https://img.shields.io/github/license/gravity-ui/charts)](LICENSE) [![CI](https://img.shields.io/github/actions/workflow/status/gravity-ui/charts/.github/workflows/ci.yml?label=CI&logo=github)](https://github.com/gravity-ui/charts/actions/workflows/ci.yml?query=branch:main) [![storybook](https://img.shields.io/badge/Storybook-deployed-ff4685)](https://preview.gravity-ui.com/charts/)
2
2
 
3
- A flexible JavaScript library for data visualization and chart rendering using React.
4
-
5
- [![npm package](https://img.shields.io/npm/v/@gravity-ui/charts)](https://www.npmjs.com/package/@gravity-ui/charts) [![CI](https://img.shields.io/github/actions/workflow/status/gravity-ui/charts/.github/workflows/ci.yml?label=CI&logo=github)](https://github.com/gravity-ui/charts/actions/workflows/ci.yml?query=branch:main) [![storybook](https://img.shields.io/badge/Storybook-deployed-ff4685)](https://preview.gravity-ui.com/charts/)
3
+ React charting library with 10+ chart types: area, bar, line, pie, scatter, treemap, and more.
6
4
 
7
5
  ## Documentation
8
6
 
9
7
  - [Overview](https://gravity-ui.github.io/charts/pages/overview.html)
8
+ - [Get started](https://gravity-ui.github.io/charts/pages/get-started.html)
9
+ - [Development](https://gravity-ui.github.io/charts/pages/development.html)
10
10
  - [API](https://gravity-ui.github.io/charts/pages/api/overview.html)
11
11
  - [Guides](https://gravity-ui.github.io/charts/pages/guides/tooltip.html)
12
-
13
- ## Get started
14
-
15
- ### Install
16
-
17
- ```shell
18
- npm install @gravity-ui/uikit @gravity-ui/charts
19
- ```
20
-
21
- ### Development
22
-
23
- To start the development server with storybook run the following:
24
-
25
- ```shell
26
- npm run start
27
- ```
28
-
29
- ## Contributing
30
-
31
- Please refer to the [contributing document](https://github.com/gravity-ui/charts/blob/main/CONTRIBUTING.md) if you wish to make pull requests.
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { Dispatch } from 'd3';
3
- import type { ChartScale, LegendItem, OnLegendItemClick, PreparedLegend, PreparedSeries, PreparedSplit, PreparedXAxis, RangeSliderState, ShapeData, ZoomState } from '../../hooks';
3
+ import type { ChartScale, LegendItem, OnLegendItemClick, PreparedLegend, PreparedSeries, PreparedSplit, PreparedXAxis, PreparedYAxis, RangeSliderState, ShapeData, ZoomState } from '../../hooks';
4
4
  import type { PreparedChart } from '../../hooks/types';
5
5
  import type { LegendConfig } from '../../types';
6
6
  import type { ChartInnerProps } from './types';
@@ -21,43 +21,7 @@ export declare function useChartInnerProps(props: Props): {
21
21
  boundsHeight: number;
22
22
  boundsWidth: number;
23
23
  xAxis: PreparedXAxis | null;
24
- yAxis: (Omit<import("../../types").ChartAxis, "type" | "labels" | "plotLines" | "plotBands"> & {
25
- type: import("../../types").ChartAxisType;
26
- labels: Omit<import("../../types").ChartAxisLabels, "style" | "enabled" | "padding" | "autoRotation"> & Required<Pick<import("../../types").ChartAxisLabels, "margin" | "enabled" | "html" | "rotation" | "padding">> & {
27
- style: import("../../types").BaseTextStyle;
28
- rotation: number;
29
- height: number;
30
- width: number;
31
- lineHeight: number;
32
- maxWidth: number;
33
- };
34
- title: {
35
- height: number;
36
- width: number;
37
- text: string;
38
- margin: number;
39
- style: import("../../types").BaseTextStyle;
40
- align: import("../../types").ChartAxisTitleAlignment;
41
- maxRowCount: number;
42
- rotation: number;
43
- maxWidth: number;
44
- html: boolean;
45
- };
46
- min?: number;
47
- grid: {
48
- enabled: boolean;
49
- };
50
- maxPadding: number;
51
- ticks: {
52
- pixelInterval?: number;
53
- };
54
- tickMarks: import("../../hooks").PreparedAxisTickMarks;
55
- position: "left" | "right" | "top" | "bottom";
56
- plotIndex: number;
57
- plotLines: import("../../hooks").PreparedAxisPlotLine[];
58
- plotBands: import("../../hooks").PreparedAxisPlotBand[];
59
- crosshair: Required<import("../../types").AxisCrosshair>;
60
- })[];
24
+ yAxis: PreparedYAxis[];
61
25
  shapesData: ShapeData[];
62
26
  shapesReady: boolean;
63
27
  handleLegendItemClick: OnLegendItemClick;
@@ -5,40 +5,4 @@ export declare function recalculateYAxisLabelsWidth(props: {
5
5
  seriesData: PreparedSeries[];
6
6
  yAxis: PreparedYAxis[];
7
7
  yScale?: (ChartScale | undefined)[];
8
- }): Promise<(Omit<import("../../..").ChartAxis, "type" | "labels" | "plotLines" | "plotBands"> & {
9
- type: import("../../..").ChartAxisType;
10
- labels: Omit<import("../../..").ChartAxisLabels, "style" | "enabled" | "padding" | "autoRotation"> & Required<Pick<import("../../..").ChartAxisLabels, "margin" | "enabled" | "html" | "rotation" | "padding">> & {
11
- style: import("../../..").BaseTextStyle;
12
- rotation: number;
13
- height: number;
14
- width: number;
15
- lineHeight: number;
16
- maxWidth: number;
17
- };
18
- title: {
19
- height: number;
20
- width: number;
21
- text: string;
22
- margin: number;
23
- style: import("../../..").BaseTextStyle;
24
- align: import("../../..").ChartAxisTitleAlignment;
25
- maxRowCount: number;
26
- rotation: number;
27
- maxWidth: number;
28
- html: boolean;
29
- };
30
- min?: number;
31
- grid: {
32
- enabled: boolean;
33
- };
34
- maxPadding: number;
35
- ticks: {
36
- pixelInterval?: number;
37
- };
38
- tickMarks: import("../../../hooks").PreparedAxisTickMarks;
39
- position: "left" | "right" | "top" | "bottom";
40
- plotIndex: number;
41
- plotLines: import("../../../hooks").PreparedAxisPlotLine[];
42
- plotBands: import("../../../hooks").PreparedAxisPlotBand[];
43
- crosshair: Required<import("../../..").AxisCrosshair>;
44
- })[]>;
8
+ }): Promise<PreparedYAxis[]>;
@@ -12,8 +12,8 @@ export function Row(props) {
12
12
  }
13
13
  return null;
14
14
  }, [color, colorSymbol]);
15
- return (React.createElement("div", { className: b('content-row', { active, striped }, className), style: style },
16
- colorItem,
17
- React.createElement("span", { className: b('content-row-label') }, label),
18
- value && React.createElement("span", { className: b('content-row-value') }, value)));
15
+ return (React.createElement("tr", { className: b('content-row', { active, striped }, className), style: style },
16
+ colorItem && React.createElement("td", { className: b('content-row-color-cell') }, colorItem),
17
+ React.createElement("td", { className: b('content-row-label-cell') }, label),
18
+ value && React.createElement("td", { className: b('content-row-value-cell') }, value)));
19
19
  }
@@ -1,7 +1,6 @@
1
1
  import React from 'react';
2
2
  import { block } from '../../../utils';
3
3
  import { getFormattedValue } from '../../../utils/chart/format';
4
- import { Row } from './Row';
5
4
  import { getBuiltInAggregatedValue, getBuiltInAggregationLabel } from './utils';
6
5
  const b = block('tooltip');
7
6
  export function RowWithAggregation(props) {
@@ -19,5 +18,7 @@ export function RowWithAggregation(props) {
19
18
  format: valueFormat || { type: 'number' },
20
19
  })
21
20
  : resultValue;
22
- return (React.createElement(Row, { className: b('content-row-totals'), label: resultLabel, style: style, value: formattedResultValue }));
21
+ return (React.createElement("div", { className: b('content-row', { totals: true }), style: style },
22
+ React.createElement("span", { className: b('content-row-totals-label') }, resultLabel),
23
+ formattedResultValue && (React.createElement("span", { className: b('content-row-totals-value') }, formattedResultValue))));
23
24
  }
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Divider } from '@gravity-ui/uikit';
3
+ import parse from 'html-react-parser';
3
4
  import get from 'lodash/get';
4
5
  import isEqual from 'lodash/isEqual';
5
6
  import { usePrevious } from '../../../hooks';
@@ -35,7 +36,7 @@ export const DefaultTooltipContent = ({ hovered, pinned, rowRenderer, totals, va
35
36
  hovered,
36
37
  });
37
38
  if (typeof result === 'string') {
38
- return React.createElement("div", { key: id, dangerouslySetInnerHTML: { __html: result } });
39
+ return React.createElement(React.Fragment, { key: id }, parse(result));
39
40
  }
40
41
  return result;
41
42
  }
@@ -75,127 +76,136 @@ export const DefaultTooltipContent = ({ hovered, pinned, rowRenderer, totals, va
75
76
  setScrollBarWidth(0);
76
77
  }
77
78
  }, [pinned]);
79
+ const rowsContent = (React.createElement(React.Fragment, null, visibleHovered.map((seriesItem, i) => {
80
+ var _a;
81
+ const { data, series, closest } = seriesItem;
82
+ const id = `${get(series, 'id')}_${i}`;
83
+ const color = get(data, 'color') || get(series, 'color');
84
+ // TODO: improve active item display https://github.com/gravity-ui/charts/issues/208
85
+ const active = closest && hovered.length > 1;
86
+ const striped = (i + 1) % 2 === 0;
87
+ const rowValueFormat = get(series, 'tooltip.valueFormat', valueFormat);
88
+ switch (series.type) {
89
+ case 'scatter':
90
+ case 'line':
91
+ case 'area':
92
+ case 'bar-x': {
93
+ const format = rowValueFormat || getDefaultValueFormat({ axis: yAxis });
94
+ const formattedValue = getFormattedValue({
95
+ value: hoveredValues[i],
96
+ format,
97
+ });
98
+ return renderRow({
99
+ id,
100
+ active,
101
+ color,
102
+ name: series.name,
103
+ striped,
104
+ value: hoveredValues[i],
105
+ formattedValue,
106
+ series,
107
+ });
108
+ }
109
+ case 'waterfall': {
110
+ const isTotal = get(data, 'total', false);
111
+ const subTotalValue = (_a = seriesItem.subTotal) !== null && _a !== void 0 ? _a : 0;
112
+ const format = rowValueFormat || getDefaultValueFormat({ axis: yAxis });
113
+ const subTotal = getFormattedValue({
114
+ value: subTotalValue,
115
+ format,
116
+ });
117
+ const formattedValue = getFormattedValue({
118
+ value: hoveredValues[i],
119
+ format,
120
+ });
121
+ return (React.createElement(React.Fragment, { key: id },
122
+ !isTotal && (React.createElement(React.Fragment, null,
123
+ React.createElement("div", { className: b('series-name') }, getXRowData(data, xAxis)),
124
+ React.createElement(Row, { label: series.name, value: formattedValue }))),
125
+ React.createElement(Row, { label: isTotal ? 'Total' : 'Subtotal', value: subTotal })));
126
+ }
127
+ case 'bar-y': {
128
+ const format = rowValueFormat || getDefaultValueFormat({ axis: xAxis });
129
+ const formattedValue = getFormattedValue({
130
+ value: hoveredValues[i],
131
+ format,
132
+ });
133
+ return renderRow({
134
+ id,
135
+ active,
136
+ color,
137
+ name: series.name,
138
+ striped,
139
+ value: hoveredValues[i],
140
+ formattedValue,
141
+ });
142
+ }
143
+ case 'pie':
144
+ case 'heatmap':
145
+ case 'treemap':
146
+ case 'funnel': {
147
+ const seriesData = data;
148
+ const formattedValue = getFormattedValue({
149
+ value: hoveredValues[i],
150
+ format: rowValueFormat || { type: 'number' },
151
+ });
152
+ return renderRow({
153
+ id,
154
+ color,
155
+ name: [seriesData.name || seriesData.id].flat().join('\n'),
156
+ value: hoveredValues[i],
157
+ formattedValue,
158
+ });
159
+ }
160
+ case 'sankey': {
161
+ const { target, data: source } = seriesItem;
162
+ const formattedValue = getFormattedValue({
163
+ value: hoveredValues[i],
164
+ format: rowValueFormat || { type: 'number' },
165
+ });
166
+ return renderRow({
167
+ id,
168
+ color,
169
+ name: `${source.name} → ${target === null || target === void 0 ? void 0 : target.name}`,
170
+ value: hoveredValues[i],
171
+ formattedValue,
172
+ });
173
+ }
174
+ case 'radar': {
175
+ const radarSeries = series;
176
+ const formattedValue = getFormattedValue({
177
+ value: hoveredValues[i],
178
+ format: rowValueFormat || { type: 'number' },
179
+ });
180
+ return renderRow({
181
+ id,
182
+ color,
183
+ active,
184
+ name: radarSeries.name || radarSeries.id,
185
+ value: hoveredValues[i],
186
+ formattedValue,
187
+ });
188
+ }
189
+ default: {
190
+ return null;
191
+ }
192
+ }
193
+ })));
78
194
  return (React.createElement("div", { className: b('content'), "data-qa": qa },
79
195
  formattedHeadValue && (React.createElement("div", { className: b('series-name') },
80
196
  React.createElement("div", { className: b('series-name-text'), dangerouslySetInnerHTML: { __html: formattedHeadValue } }))),
81
197
  React.createElement("div", { className: b('content-rows', { pinned }), ref: contentRowsRef, style: pinned ? { maxHeight: maxContentRowsHeight } : undefined },
82
- visibleHovered.map((seriesItem, i) => {
83
- var _a;
84
- const { data, series, closest } = seriesItem;
85
- const id = `${get(series, 'id')}_${i}`;
86
- const color = get(data, 'color') || get(series, 'color');
87
- // TODO: improve action item display https://github.com/gravity-ui/charts/issues/208
88
- const active = closest && hovered.length > 1;
89
- const striped = (i + 1) % 2 === 0;
90
- const rowValueFormat = get(series, 'tooltip.valueFormat', valueFormat);
91
- switch (series.type) {
92
- case 'scatter':
93
- case 'line':
94
- case 'area':
95
- case 'bar-x': {
96
- const format = rowValueFormat || getDefaultValueFormat({ axis: yAxis });
97
- const formattedValue = getFormattedValue({
98
- value: hoveredValues[i],
99
- format,
100
- });
101
- return renderRow({
102
- id,
103
- active,
104
- color,
105
- name: series.name,
106
- striped,
107
- value: hoveredValues[i],
108
- formattedValue,
109
- series,
110
- });
111
- }
112
- case 'waterfall': {
113
- const isTotal = get(data, 'total', false);
114
- const subTotalValue = (_a = seriesItem.subTotal) !== null && _a !== void 0 ? _a : 0;
115
- const format = rowValueFormat || getDefaultValueFormat({ axis: yAxis });
116
- const subTotal = getFormattedValue({
117
- value: subTotalValue,
118
- format,
119
- });
120
- const formattedValue = getFormattedValue({
121
- value: hoveredValues[i],
122
- format,
123
- });
124
- return (React.createElement(React.Fragment, { key: id },
125
- !isTotal && (React.createElement(React.Fragment, null,
126
- React.createElement("div", { className: b('series-name') }, getXRowData(data, xAxis)),
127
- React.createElement(Row, { label: series.name, value: formattedValue }))),
128
- React.createElement(Row, { label: isTotal ? 'Total' : 'Subtotal', value: subTotal })));
129
- }
130
- case 'bar-y': {
131
- const format = rowValueFormat || getDefaultValueFormat({ axis: xAxis });
132
- const formattedValue = getFormattedValue({
133
- value: hoveredValues[i],
134
- format,
135
- });
136
- return renderRow({
137
- id,
138
- active,
139
- color,
140
- name: series.name,
141
- striped,
142
- value: hoveredValues[i],
143
- formattedValue,
144
- });
145
- }
146
- case 'pie':
147
- case 'heatmap':
148
- case 'treemap':
149
- case 'funnel': {
150
- const seriesData = data;
151
- const formattedValue = getFormattedValue({
152
- value: hoveredValues[i],
153
- format: rowValueFormat || { type: 'number' },
154
- });
155
- return renderRow({
156
- id,
157
- color,
158
- name: [seriesData.name || seriesData.id].flat().join('\n'),
159
- value: hoveredValues[i],
160
- formattedValue,
161
- });
162
- }
163
- case 'sankey': {
164
- const { target, data: source } = seriesItem;
165
- const formattedValue = getFormattedValue({
166
- value: hoveredValues[i],
167
- format: rowValueFormat || { type: 'number' },
168
- });
169
- return renderRow({
170
- id,
171
- color,
172
- name: `${source.name} → ${target === null || target === void 0 ? void 0 : target.name}`,
173
- value: hoveredValues[i],
174
- formattedValue,
175
- });
176
- }
177
- case 'radar': {
178
- const radarSeries = series;
179
- const formattedValue = getFormattedValue({
180
- value: hoveredValues[i],
181
- format: rowValueFormat || { type: 'number' },
182
- });
183
- return renderRow({
184
- id,
185
- color,
186
- active,
187
- name: radarSeries.name || radarSeries.id,
188
- value: hoveredValues[i],
189
- formattedValue,
190
- });
191
- }
192
- default: {
193
- return null;
194
- }
195
- }
196
- }),
197
- Boolean(restHoveredValues.length) && (React.createElement(Row, { label: i18n('tooltip', 'label_more', { count: restHoveredValues.length }), striped: (visibleHovered.length + 1) % 2 === 0 }))),
198
+ React.createElement("table", { className: b('content-rows-table') },
199
+ React.createElement("tbody", null, rowsContent))),
200
+ Boolean(restHoveredValues.length) && (React.createElement("div", { className: b('content-row', {
201
+ striped: (visibleHovered.length + 1) % 2 === 0,
202
+ }) }, i18n('tooltip', 'label_more', { count: restHoveredValues.length }))),
198
203
  (totals === null || totals === void 0 ? void 0 : totals.enabled) && hovered.length > 1 && (React.createElement(React.Fragment, null,
199
204
  React.createElement(Divider, { className: b('content-row-totals-divider') }),
200
- 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 })))));
205
+ React.createElement(RowWithAggregation, { aggregation: getPreparedAggregation({
206
+ hovered,
207
+ totals,
208
+ xAxis,
209
+ yAxis,
210
+ }), label: totals.label, style: { marginRight: scrollBarWidth }, values: hoveredValues, valueFormat: (_a = totals.valueFormat) !== null && _a !== void 0 ? _a : valueFormat })))));
201
211
  };
@@ -35,6 +35,12 @@ export declare function getPreparedAggregation(args: {
35
35
  xAxis?: ChartXAxis | null;
36
36
  yAxis?: ChartYAxis;
37
37
  }): ChartTooltipTotalsBuiltInAggregation | (() => ChartTooltipTotalsAggregationValue);
38
+ export declare function getSortedHovered(args: {
39
+ hovered: TooltipDataChunk[];
40
+ sorting?: ChartTooltip['sorting'];
41
+ xAxis?: ChartXAxis | null;
42
+ yAxis?: ChartYAxis;
43
+ }): TooltipDataChunk[];
38
44
  export declare function getTooltipRowColorSymbol({ series, color, height, width, }: {
39
45
  color?: string;
40
46
  series?: TooltipDataChunk['series'];
@@ -130,6 +130,47 @@ export function getPreparedAggregation(args) {
130
130
  }
131
131
  return 'sum';
132
132
  }
133
+ export function getSortedHovered(args) {
134
+ var _a;
135
+ const { hovered, sorting, xAxis, yAxis } = args;
136
+ if (!sorting) {
137
+ return hovered;
138
+ }
139
+ if (typeof sorting === 'function') {
140
+ return [...hovered].sort(sorting);
141
+ }
142
+ switch (sorting.key) {
143
+ case 'value': {
144
+ const values = getHoveredValues({ hovered, xAxis, yAxis });
145
+ const direction = (_a = sorting.direction) !== null && _a !== void 0 ? _a : 'asc';
146
+ const compareValue = (a, b) => {
147
+ const aNil = a === null || a === undefined;
148
+ const bNil = b === null || b === undefined;
149
+ if (aNil && bNil) {
150
+ return 0;
151
+ }
152
+ if (aNil) {
153
+ return -1;
154
+ }
155
+ if (bNil) {
156
+ return 1;
157
+ }
158
+ if (typeof a === 'number' && typeof b === 'number') {
159
+ return a - b;
160
+ }
161
+ return String(a).localeCompare(String(b));
162
+ };
163
+ const indices = hovered.map((_, i) => i);
164
+ indices.sort((i, j) => direction === 'asc'
165
+ ? compareValue(values[i], values[j])
166
+ : compareValue(values[j], values[i]));
167
+ return indices.map((i) => hovered[i]);
168
+ }
169
+ default: {
170
+ return hovered;
171
+ }
172
+ }
173
+ }
133
174
  export function getTooltipRowColorSymbol({ series, color, height = 8, width = 16, }) {
134
175
  if ((series === null || series === void 0 ? void 0 : series.type) === 'line') {
135
176
  const colorSymbol = create('svg').attr('height', height).attr('width', width);
@@ -10,6 +10,8 @@ export const Tooltip = (props) => {
10
10
  const { hovered, hoveredPlotLines, hoveredPlotBands, pointerPosition } = useTooltip({
11
11
  dispatcher,
12
12
  tooltip,
13
+ xAxis,
14
+ yAxis,
13
15
  });
14
16
  const containerRect = (svgContainer === null || svgContainer === void 0 ? void 0 : svgContainer.getBoundingClientRect()) || { left: 0, top: 0 };
15
17
  const left = ((pointerPosition === null || pointerPosition === void 0 ? void 0 : pointerPosition[0]) || 0) + containerRect.left;
@@ -3,8 +3,12 @@
3
3
  background-color: var(--g-color-infographics-tooltip-bg);
4
4
  box-shadow: 0 2px 12px var(--g-color-sfx-shadow);
5
5
  }
6
+ tr.gcharts-tooltip__content-row {
7
+ display: table-row;
8
+ padding: 0;
9
+ }
10
+
6
11
  .gcharts-tooltip__popup-content {
7
- max-width: 450px;
8
12
  text-wrap: nowrap;
9
13
  border-radius: 4px;
10
14
  }
@@ -20,7 +24,13 @@
20
24
  .gcharts-tooltip__content-rows_pinned {
21
25
  overflow: auto;
22
26
  }
27
+ .gcharts-tooltip__content-rows-table {
28
+ width: 100%;
29
+ padding: 0;
30
+ border-collapse: collapse;
31
+ }
23
32
  .gcharts-tooltip__series-name {
33
+ max-width: 450px;
24
34
  padding: 2px 14px 6px;
25
35
  font-size: 13px;
26
36
  font-weight: 600;
@@ -45,8 +55,23 @@
45
55
  font-weight: 600;
46
56
  background-color: var(--g-color-base-info-medium);
47
57
  }
48
- .gcharts-tooltip__content-row-label {
58
+ .gcharts-tooltip__content-row_totals {
59
+ color: var(--g-color-text-complementary);
60
+ }
61
+ .gcharts-tooltip__content-row-totals-label {
49
62
  overflow: hidden;
63
+ max-width: 400px;
64
+ white-space: nowrap;
65
+ text-overflow: ellipsis;
66
+ }
67
+ .gcharts-tooltip__content-row-totals-value {
68
+ flex-shrink: 0;
69
+ margin-inline-start: auto;
70
+ }
71
+ .gcharts-tooltip__content-row-label-cell {
72
+ overflow: hidden;
73
+ max-width: 400px;
74
+ padding: 2px 4px;
50
75
  white-space: nowrap;
51
76
  text-overflow: ellipsis;
52
77
  }
@@ -58,12 +83,13 @@
58
83
  border-radius: 2px;
59
84
  background-color: #dddddd;
60
85
  }
61
- .gcharts-tooltip__content-row-value {
62
- flex-shrink: 0;
63
- margin-inline-start: auto;
86
+ .gcharts-tooltip__content-row-color-cell {
87
+ width: 16px;
88
+ padding: 2px 4px 2px 14px;
64
89
  }
65
- .gcharts-tooltip__content-row-totals {
66
- color: var(--g-color-text-complementary);
90
+ .gcharts-tooltip__content-row-value-cell {
91
+ padding: 2px 14px 2px 4px;
92
+ text-align: end;
67
93
  }
68
94
  .gcharts-tooltip__content-row-totals-divider {
69
95
  margin-block: 5px 5px;
@@ -1,8 +1,11 @@
1
1
  import React from 'react';
2
2
  import type { ChartData } from '../types';
3
3
  export * from './Tooltip/ChartTooltipContent';
4
+ export interface ChartReflowOptions {
5
+ immediate?: boolean;
6
+ }
4
7
  export interface ChartRef {
5
- reflow: () => void;
8
+ reflow: (options?: ChartReflowOptions) => void;
6
9
  }
7
10
  export interface ChartDimentions {
8
11
  height: number;
@@ -30,10 +30,15 @@ export const Chart = React.forwardRef(function Chart(props, forwardedRef) {
30
30
  return debounced.current;
31
31
  }, [handleResize]);
32
32
  React.useImperativeHandle(forwardedRef, () => ({
33
- reflow() {
34
- debuncedHandleResize();
33
+ reflow(options) {
34
+ if (options === null || options === void 0 ? void 0 : options.immediate) {
35
+ handleResize();
36
+ }
37
+ else {
38
+ debuncedHandleResize();
39
+ }
35
40
  },
36
- }), [debuncedHandleResize]);
41
+ }), [debuncedHandleResize, handleResize]);
37
42
  React.useEffect(() => {
38
43
  // dimensions initialize
39
44
  handleResize();
@@ -16,43 +16,7 @@ interface UseAxesProps {
16
16
  }
17
17
  export declare function getAxes(props: UseAxesProps): Promise<{
18
18
  xAxis: import("./types").PreparedXAxis | null;
19
- yAxis: (Omit<import("../../types").ChartAxis, "type" | "labels" | "plotLines" | "plotBands"> & {
20
- type: import("../../types").ChartAxisType;
21
- labels: Omit<import("../../types").ChartAxisLabels, "style" | "enabled" | "padding" | "autoRotation"> & Required<Pick<import("../../types").ChartAxisLabels, "margin" | "enabled" | "html" | "rotation" | "padding">> & {
22
- style: import("../../types").BaseTextStyle;
23
- rotation: number;
24
- height: number;
25
- width: number;
26
- lineHeight: number;
27
- maxWidth: number;
28
- };
29
- title: {
30
- height: number;
31
- width: number;
32
- text: string;
33
- margin: number;
34
- style: import("../../types").BaseTextStyle;
35
- align: import("../../types").ChartAxisTitleAlignment;
36
- maxRowCount: number;
37
- rotation: number;
38
- maxWidth: number;
39
- html: boolean;
40
- };
41
- min?: number;
42
- grid: {
43
- enabled: boolean;
44
- };
45
- maxPadding: number;
46
- ticks: {
47
- pixelInterval?: number;
48
- };
49
- tickMarks: import("./types").PreparedAxisTickMarks;
50
- position: "left" | "right" | "top" | "bottom";
51
- plotIndex: number;
52
- plotLines: import("./types").PreparedAxisPlotLine[];
53
- plotBands: import("./types").PreparedAxisPlotBand[];
54
- crosshair: Required<import("../../types").AxisCrosshair>;
55
- })[];
19
+ yAxis: import("./types").PreparedYAxis[];
56
20
  }>;
57
21
  export declare function useAxis(props: UseAxesProps): AxesState;
58
22
  export {};