@gravity-ui/charts 1.17.0 → 1.18.1

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 (115) hide show
  1. package/dist/cjs/components/AxisY/prepare-axis-data.d.ts +4 -2
  2. package/dist/cjs/components/AxisY/prepare-axis-data.js +11 -10
  3. package/dist/cjs/components/AxisY/utils.d.ts +4 -2
  4. package/dist/cjs/components/AxisY/utils.js +47 -23
  5. package/dist/cjs/components/ChartInner/index.js +11 -5
  6. package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +1 -1
  7. package/dist/cjs/components/ChartInner/useChartInnerProps.js +3 -2
  8. package/dist/cjs/components/Tooltip/ChartTooltipContent.d.ts +1 -0
  9. package/dist/cjs/components/Tooltip/ChartTooltipContent.js +2 -2
  10. package/dist/cjs/components/Tooltip/DefaultTooltipContent/index.d.ts +2 -1
  11. package/dist/cjs/components/Tooltip/DefaultTooltipContent/index.js +3 -3
  12. package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.d.ts +4 -3
  13. package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.js +6 -9
  14. package/dist/cjs/components/Tooltip/index.js +1 -1
  15. package/dist/cjs/hooks/useAxisScales/index.d.ts +3 -4
  16. package/dist/cjs/hooks/useAxisScales/index.js +82 -28
  17. package/dist/cjs/hooks/useChartOptions/index.d.ts +3 -1
  18. package/dist/cjs/hooks/useChartOptions/index.js +3 -3
  19. package/dist/cjs/hooks/useChartOptions/tooltip.d.ts +4 -1
  20. package/dist/cjs/hooks/useChartOptions/tooltip.js +18 -3
  21. package/dist/cjs/hooks/useChartOptions/utils.d.ts +5 -2
  22. package/dist/cjs/hooks/useChartOptions/utils.js +2 -3
  23. package/dist/cjs/hooks/useChartOptions/x-axis.js +21 -9
  24. package/dist/cjs/hooks/useChartOptions/y-axis.d.ts +1 -3
  25. package/dist/cjs/hooks/useChartOptions/y-axis.js +23 -12
  26. package/dist/cjs/hooks/useCrosshair/index.d.ts +1 -1
  27. package/dist/cjs/hooks/useCrosshair/index.js +2 -1
  28. package/dist/cjs/hooks/useSeries/prepare-bar-y.js +3 -1
  29. package/dist/cjs/hooks/useShapes/area/prepare-data.d.ts +1 -1
  30. package/dist/cjs/hooks/useShapes/area/prepare-data.js +3 -0
  31. package/dist/cjs/hooks/useShapes/bar-x/prepare-data.d.ts +1 -1
  32. package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +3 -0
  33. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.d.ts +5 -3
  34. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +46 -20
  35. package/dist/cjs/hooks/useShapes/index.d.ts +1 -1
  36. package/dist/cjs/hooks/useShapes/index.js +2 -0
  37. package/dist/cjs/hooks/useShapes/line/prepare-data.d.ts +1 -1
  38. package/dist/cjs/hooks/useShapes/line/prepare-data.js +3 -0
  39. package/dist/cjs/hooks/useShapes/scatter/prepare-data.d.ts +1 -1
  40. package/dist/cjs/hooks/useShapes/scatter/prepare-data.js +6 -0
  41. package/dist/cjs/hooks/useShapes/waterfall/prepare-data.d.ts +1 -1
  42. package/dist/cjs/hooks/useShapes/waterfall/prepare-data.js +6 -3
  43. package/dist/cjs/hooks/useZoom/index.d.ts +1 -1
  44. package/dist/cjs/hooks/useZoom/types.d.ts +1 -1
  45. package/dist/cjs/hooks/useZoom/utils.d.ts +1 -1
  46. package/dist/cjs/hooks/useZoom/utils.js +46 -18
  47. package/dist/cjs/hooks/utils/bar-y.d.ts +7 -10
  48. package/dist/cjs/hooks/utils/bar-y.js +33 -18
  49. package/dist/cjs/types/chart/tooltip.d.ts +3 -0
  50. package/dist/cjs/utils/chart/array.d.ts +1 -0
  51. package/dist/cjs/utils/chart/array.js +12 -0
  52. package/dist/cjs/utils/chart/format.js +2 -2
  53. package/dist/cjs/utils/chart/index.d.ts +1 -0
  54. package/dist/cjs/utils/chart/index.js +3 -1
  55. package/dist/cjs/utils/chart/labels.d.ts +27 -5
  56. package/dist/cjs/utils/chart/labels.js +39 -3
  57. package/dist/cjs/utils/chart/zoom.js +14 -8
  58. package/dist/esm/components/AxisY/prepare-axis-data.d.ts +4 -2
  59. package/dist/esm/components/AxisY/prepare-axis-data.js +11 -10
  60. package/dist/esm/components/AxisY/utils.d.ts +4 -2
  61. package/dist/esm/components/AxisY/utils.js +47 -23
  62. package/dist/esm/components/ChartInner/index.js +11 -5
  63. package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +1 -1
  64. package/dist/esm/components/ChartInner/useChartInnerProps.js +3 -2
  65. package/dist/esm/components/Tooltip/ChartTooltipContent.d.ts +1 -0
  66. package/dist/esm/components/Tooltip/ChartTooltipContent.js +2 -2
  67. package/dist/esm/components/Tooltip/DefaultTooltipContent/index.d.ts +2 -1
  68. package/dist/esm/components/Tooltip/DefaultTooltipContent/index.js +3 -3
  69. package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.d.ts +4 -3
  70. package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.js +6 -9
  71. package/dist/esm/components/Tooltip/index.js +1 -1
  72. package/dist/esm/hooks/useAxisScales/index.d.ts +3 -4
  73. package/dist/esm/hooks/useAxisScales/index.js +82 -28
  74. package/dist/esm/hooks/useChartOptions/index.d.ts +3 -1
  75. package/dist/esm/hooks/useChartOptions/index.js +3 -3
  76. package/dist/esm/hooks/useChartOptions/tooltip.d.ts +4 -1
  77. package/dist/esm/hooks/useChartOptions/tooltip.js +18 -3
  78. package/dist/esm/hooks/useChartOptions/utils.d.ts +5 -2
  79. package/dist/esm/hooks/useChartOptions/utils.js +2 -3
  80. package/dist/esm/hooks/useChartOptions/x-axis.js +21 -9
  81. package/dist/esm/hooks/useChartOptions/y-axis.d.ts +1 -3
  82. package/dist/esm/hooks/useChartOptions/y-axis.js +23 -12
  83. package/dist/esm/hooks/useCrosshair/index.d.ts +1 -1
  84. package/dist/esm/hooks/useCrosshair/index.js +2 -1
  85. package/dist/esm/hooks/useSeries/prepare-bar-y.js +3 -1
  86. package/dist/esm/hooks/useShapes/area/prepare-data.d.ts +1 -1
  87. package/dist/esm/hooks/useShapes/area/prepare-data.js +3 -0
  88. package/dist/esm/hooks/useShapes/bar-x/prepare-data.d.ts +1 -1
  89. package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +3 -0
  90. package/dist/esm/hooks/useShapes/bar-y/prepare-data.d.ts +5 -3
  91. package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +46 -20
  92. package/dist/esm/hooks/useShapes/index.d.ts +1 -1
  93. package/dist/esm/hooks/useShapes/index.js +2 -0
  94. package/dist/esm/hooks/useShapes/line/prepare-data.d.ts +1 -1
  95. package/dist/esm/hooks/useShapes/line/prepare-data.js +3 -0
  96. package/dist/esm/hooks/useShapes/scatter/prepare-data.d.ts +1 -1
  97. package/dist/esm/hooks/useShapes/scatter/prepare-data.js +6 -0
  98. package/dist/esm/hooks/useShapes/waterfall/prepare-data.d.ts +1 -1
  99. package/dist/esm/hooks/useShapes/waterfall/prepare-data.js +6 -3
  100. package/dist/esm/hooks/useZoom/index.d.ts +1 -1
  101. package/dist/esm/hooks/useZoom/types.d.ts +1 -1
  102. package/dist/esm/hooks/useZoom/utils.d.ts +1 -1
  103. package/dist/esm/hooks/useZoom/utils.js +46 -18
  104. package/dist/esm/hooks/utils/bar-y.d.ts +7 -10
  105. package/dist/esm/hooks/utils/bar-y.js +33 -18
  106. package/dist/esm/types/chart/tooltip.d.ts +3 -0
  107. package/dist/esm/utils/chart/array.d.ts +1 -0
  108. package/dist/esm/utils/chart/array.js +12 -0
  109. package/dist/esm/utils/chart/format.js +2 -2
  110. package/dist/esm/utils/chart/index.d.ts +1 -0
  111. package/dist/esm/utils/chart/index.js +3 -1
  112. package/dist/esm/utils/chart/labels.d.ts +27 -5
  113. package/dist/esm/utils/chart/labels.js +39 -3
  114. package/dist/esm/utils/chart/zoom.js +14 -8
  115. package/package.json +1 -1
@@ -96,9 +96,11 @@ export const ChartInner = (props) => {
96
96
  const axisData = await prepareAxisData({
97
97
  axis,
98
98
  scale,
99
+ top: boundsOffsetTop,
99
100
  width: boundsWidth,
100
101
  height: boundsHeight,
101
102
  split: preparedSplit,
103
+ series: preparedSeries,
102
104
  });
103
105
  items.push(axisData);
104
106
  }
@@ -107,7 +109,7 @@ export const ChartInner = (props) => {
107
109
  setYAxisDataItems(items);
108
110
  }
109
111
  })();
110
- }, [boundsHeight, boundsWidth, preparedSplit, yAxis, yScale]);
112
+ }, [boundsHeight, boundsOffsetTop, boundsWidth, preparedSeries, preparedSplit, yAxis, yScale]);
111
113
  return (React.createElement("div", { className: b() },
112
114
  React.createElement("svg", { ref: svgRef, width: width, height: height,
113
115
  // We use onPointerMove here because onMouseMove works incorrectly when the zoom setting is enabled:
@@ -121,10 +123,14 @@ export const ChartInner = (props) => {
121
123
  return React.createElement(PlotTitle, { key: `plot-${index}`, title: plot.title });
122
124
  })),
123
125
  React.createElement("g", { width: boundsWidth, height: boundsHeight, transform: `translate(${[boundsOffsetLeft, boundsOffsetTop].join(',')})`, ref: plotRef },
124
- xScale && (yScale === null || yScale === void 0 ? void 0 : yScale.length) && (React.createElement(React.Fragment, null,
125
- yAxisDataItems.map((axisData, index) => (React.createElement(AxisY, { key: index, htmlLayout: htmlLayout, plotAfterRef: plotAfterRef, plotBeforeRef: plotBeforeRef, preparedAxisData: axisData }))),
126
- xAxis && (React.createElement("g", { transform: `translate(0, ${boundsHeight})` },
127
- React.createElement(AxisX, { axis: xAxis, boundsOffsetLeft: boundsOffsetLeft, boundsOffsetTop: boundsOffsetTop, height: boundsHeight, htmlLayout: htmlLayout, leftmostLimit: svgXPos, plotAfterRef: plotAfterRef, plotBeforeRef: plotBeforeRef, scale: xScale, split: preparedSplit, width: boundsWidth }))))),
126
+ xScale && xAxis && (React.createElement("g", { transform: `translate(0, ${boundsHeight})` },
127
+ React.createElement(AxisX, { axis: xAxis, boundsOffsetLeft: boundsOffsetLeft, boundsOffsetTop: boundsOffsetTop, height: boundsHeight, htmlLayout: htmlLayout, leftmostLimit: svgXPos, plotAfterRef: plotAfterRef, plotBeforeRef: plotBeforeRef, scale: xScale, split: preparedSplit, width: boundsWidth }))),
128
+ Boolean(yAxisDataItems.length) && (React.createElement(React.Fragment, null, yAxisDataItems.map((axisData, index) => {
129
+ if (!axisData) {
130
+ return null;
131
+ }
132
+ return (React.createElement(AxisY, { key: index, htmlLayout: htmlLayout, plotAfterRef: plotAfterRef, plotBeforeRef: plotBeforeRef, preparedAxisData: axisData }));
133
+ }))),
128
134
  React.createElement("g", { ref: plotBeforeRef }),
129
135
  shapes,
130
136
  React.createElement("g", { ref: plotAfterRef })),
@@ -51,6 +51,6 @@ export declare function useChartInnerProps(props: Props): {
51
51
  xAxis: PreparedAxis | null;
52
52
  xScale: import("../../hooks").ChartScale | undefined;
53
53
  yAxis: PreparedAxis[];
54
- yScale: import("../../hooks").ChartScale[] | undefined;
54
+ yScale: (import("../../hooks").ChartScale | undefined)[] | undefined;
55
55
  };
56
56
  export {};
@@ -20,6 +20,8 @@ export function useChartInnerProps(props) {
20
20
  colors: data.colors,
21
21
  title: data.title,
22
22
  tooltip: data.tooltip,
23
+ xAxis: data.xAxis,
24
+ yAxes: data.yAxis,
23
25
  });
24
26
  const preparedSeriesOptions = React.useMemo(() => {
25
27
  return getPreparedOptions(data.series.options);
@@ -64,10 +66,9 @@ export function useChartInnerProps(props) {
64
66
  boundsHeight: estimatedBoundsHeight,
65
67
  width,
66
68
  seriesData: zoomedSeriesData,
67
- seriesOptions: preparedSeriesOptions,
68
69
  yAxis: data.yAxis,
69
70
  }).then((val) => setYAxis(val));
70
- }, [data.yAxis, estimatedBoundsHeight, height, preparedSeriesOptions, width, zoomedSeriesData]);
71
+ }, [data.yAxis, estimatedBoundsHeight, height, width, zoomedSeriesData]);
71
72
  const { preparedSeries, preparedLegend, handleLegendItemClick } = useSeries({
72
73
  colors,
73
74
  legend: data.legend,
@@ -10,5 +10,6 @@ export interface ChartTooltipContentProps {
10
10
  totals?: ChartTooltip['totals'];
11
11
  xAxis?: ChartXAxis | null;
12
12
  yAxis?: ChartYAxis;
13
+ qa?: string;
13
14
  }
14
15
  export declare const ChartTooltipContent: (props: ChartTooltipContentProps) => React.JSX.Element | null;
@@ -2,10 +2,10 @@ import React from 'react';
2
2
  import isNil from 'lodash/isNil';
3
3
  import { DefaultTooltipContent } from './DefaultTooltipContent';
4
4
  export const ChartTooltipContent = (props) => {
5
- const { hovered, xAxis, yAxis, renderer, rowRenderer, valueFormat, headerFormat, totals, pinned, } = props;
5
+ const { hovered, xAxis, yAxis, renderer, rowRenderer, valueFormat, headerFormat, totals, pinned, qa, } = props;
6
6
  if (!hovered) {
7
7
  return null;
8
8
  }
9
9
  const customTooltip = renderer === null || renderer === void 0 ? void 0 : renderer({ hovered, xAxis, yAxis });
10
- return isNil(customTooltip) ? (React.createElement(DefaultTooltipContent, { hovered: hovered, pinned: pinned, rowRenderer: rowRenderer, totals: totals, valueFormat: valueFormat, headerFormat: headerFormat, xAxis: xAxis, yAxis: yAxis })) : (customTooltip);
10
+ return isNil(customTooltip) ? (React.createElement(DefaultTooltipContent, { hovered: hovered, pinned: pinned, rowRenderer: rowRenderer, totals: totals, valueFormat: valueFormat, headerFormat: headerFormat, xAxis: xAxis, yAxis: yAxis, qa: qa })) : (customTooltip);
11
11
  };
@@ -9,6 +9,7 @@ type Props = {
9
9
  headerFormat?: ChartTooltip['headerFormat'];
10
10
  xAxis?: ChartXAxis | null;
11
11
  yAxis?: ChartYAxis;
12
+ qa?: string;
12
13
  };
13
- export declare const DefaultTooltipContent: ({ hovered, pinned, rowRenderer, totals, valueFormat, headerFormat, xAxis, yAxis, }: Props) => React.JSX.Element;
14
+ export declare const DefaultTooltipContent: ({ hovered, pinned, rowRenderer, totals, valueFormat, headerFormat, xAxis, yAxis, qa, }: Props) => React.JSX.Element;
14
15
  export {};
@@ -10,13 +10,13 @@ import { Row } from './Row';
10
10
  import { RowWithAggregation } from './RowWithAggregation';
11
11
  import { getDefaultValueFormat, getHoveredValues, getMeasureValue, getPreparedAggregation, getXRowData, } from './utils';
12
12
  const b = block('tooltip');
13
- export const DefaultTooltipContent = ({ hovered, pinned, rowRenderer, totals, valueFormat, headerFormat, xAxis, yAxis, }) => {
13
+ export const DefaultTooltipContent = ({ hovered, pinned, rowRenderer, totals, valueFormat, headerFormat, xAxis, yAxis, qa, }) => {
14
14
  var _a;
15
15
  const [visibleRows, setVisibleRows] = React.useState();
16
16
  const [maxContentRowsHeight, setMaxContentRowsHeight] = React.useState();
17
17
  const [scrollBarWidth, setScrollBarWidth] = React.useState(0);
18
18
  const contentRowsRef = React.useRef(null);
19
- const measureValue = getMeasureValue({ data: hovered, xAxis, yAxis });
19
+ const measureValue = getMeasureValue({ data: hovered, xAxis, yAxis, headerFormat });
20
20
  const hoveredValues = getHoveredValues({ hovered, xAxis, yAxis });
21
21
  const prevHoveredValues = usePrevious(hoveredValues);
22
22
  const visibleHovered = pinned || !visibleRows ? hovered : hovered.slice(0, visibleRows);
@@ -83,7 +83,7 @@ export const DefaultTooltipContent = ({ hovered, pinned, rowRenderer, totals, va
83
83
  setScrollBarWidth(0);
84
84
  }
85
85
  }, [pinned]);
86
- return (React.createElement("div", { className: b('content') },
86
+ return (React.createElement("div", { className: b('content'), "data-qa": qa },
87
87
  formattedHeadValue && (React.createElement("div", { className: b('series-name'), dangerouslySetInnerHTML: { __html: formattedHeadValue } })),
88
88
  React.createElement("div", { className: b('content-rows', { pinned }), ref: contentRowsRef, style: { maxHeight: maxContentRowsHeight } },
89
89
  visibleHovered.map((seriesItem, i) => {
@@ -1,14 +1,15 @@
1
1
  import type { ChartSeriesData, ChartTooltip, ChartTooltipTotalsAggregationValue, ChartTooltipTotalsBuiltInAggregation, ChartXAxis, ChartYAxis, TooltipDataChunk, ValueFormat } from '../../../types';
2
2
  export type HoveredValue = string | number | null | undefined;
3
3
  export declare function getXRowData(data: ChartSeriesData, xAxis?: ChartXAxis | null): string | number | undefined;
4
- export declare function getDefaultValueFormat({ axis, }: {
4
+ export declare function getDefaultValueFormat({ axis, closestPointsRange, }: {
5
5
  axis?: ChartXAxis | ChartYAxis | null;
6
+ closestPointsRange?: number;
6
7
  }): ValueFormat | undefined;
7
- export declare const getMeasureValue: ({ data, xAxis, yAxis, valueFormat, }: {
8
+ export declare const getMeasureValue: ({ data, xAxis, yAxis, headerFormat, }: {
8
9
  data: TooltipDataChunk[];
9
10
  xAxis?: ChartXAxis | null;
10
11
  yAxis?: ChartYAxis;
11
- valueFormat?: ValueFormat;
12
+ headerFormat?: ChartTooltip["headerFormat"];
12
13
  }) => {
13
14
  value: string | null;
14
15
  formattedValue?: undefined;
@@ -1,7 +1,6 @@
1
1
  import get from 'lodash/get';
2
- import { DEFAULT_DATE_FORMAT } from '../../../constants';
3
2
  import { i18n } from '../../../i18n';
4
- import { getDataCategoryValue } from '../../../utils';
3
+ import { getDataCategoryValue, getDefaultDateFormat } from '../../../utils';
5
4
  import { getFormattedValue } from '../../../utils/chart/format';
6
5
  function getRowData(fieldName, data, axis) {
7
6
  switch (axis === null || axis === void 0 ? void 0 : axis.type) {
@@ -20,7 +19,7 @@ export function getXRowData(data, xAxis) {
20
19
  function getYRowData(data, yAxis) {
21
20
  return getRowData('y', data, yAxis);
22
21
  }
23
- export function getDefaultValueFormat({ axis, }) {
22
+ export function getDefaultValueFormat({ axis, closestPointsRange, }) {
24
23
  switch (axis === null || axis === void 0 ? void 0 : axis.type) {
25
24
  case 'linear':
26
25
  case 'logarithmic': {
@@ -31,14 +30,14 @@ export function getDefaultValueFormat({ axis, }) {
31
30
  case 'datetime': {
32
31
  return {
33
32
  type: 'date',
34
- format: DEFAULT_DATE_FORMAT,
33
+ format: getDefaultDateFormat(closestPointsRange),
35
34
  };
36
35
  }
37
36
  default:
38
37
  return undefined;
39
38
  }
40
39
  }
41
- export const getMeasureValue = ({ data, xAxis, yAxis, valueFormat, }) => {
40
+ export const getMeasureValue = ({ data, xAxis, yAxis, headerFormat, }) => {
42
41
  var _a, _b, _c, _d, _e, _f;
43
42
  if (data.every((item) => ['pie', 'treemap', 'waterfall', 'sankey'].includes(item.series.type))) {
44
43
  return null;
@@ -49,18 +48,16 @@ export const getMeasureValue = ({ data, xAxis, yAxis, valueFormat, }) => {
49
48
  }
50
49
  if (data.some((item) => item.series.type === 'bar-y')) {
51
50
  const value = getYRowData((_c = data[0]) === null || _c === void 0 ? void 0 : _c.data, yAxis);
52
- const format = valueFormat !== null && valueFormat !== void 0 ? valueFormat : getDefaultValueFormat({ axis: yAxis });
53
51
  const formattedValue = getFormattedValue({
54
52
  value: getYRowData((_d = data[0]) === null || _d === void 0 ? void 0 : _d.data, yAxis),
55
- format,
53
+ format: headerFormat,
56
54
  });
57
55
  return { value, formattedValue };
58
56
  }
59
57
  const value = getXRowData((_e = data[0]) === null || _e === void 0 ? void 0 : _e.data, xAxis);
60
- const format = valueFormat !== null && valueFormat !== void 0 ? valueFormat : getDefaultValueFormat({ axis: xAxis });
61
58
  const formattedValue = getFormattedValue({
62
59
  value: getXRowData((_f = data[0]) === null || _f === void 0 ? void 0 : _f.data, xAxis),
63
- format,
60
+ format: headerFormat,
64
61
  });
65
62
  return { value, formattedValue };
66
63
  };
@@ -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, pinned: tooltipPinned, renderer: tooltip.renderer, rowRenderer: tooltip.rowRenderer, totals: tooltip.totals, valueFormat: tooltip.valueFormat, headerFormat: tooltip.headerFormat, xAxis: xAxis, yAxis: yAxis })))) : 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, qa: tooltip.qa })))) : null;
27
27
  };
@@ -17,21 +17,20 @@ type Args = {
17
17
  };
18
18
  type ReturnValue = {
19
19
  xScale?: ChartScale;
20
- yScale?: ChartScale[];
20
+ yScale?: (ChartScale | undefined)[];
21
21
  };
22
22
  export declare function createYScale(args: {
23
23
  axis: PreparedAxis;
24
24
  boundsHeight: number;
25
25
  series: (PreparedSeries | ChartSeries)[];
26
- seriesOptions: PreparedSeriesOptions;
27
- }): ScaleBand<string> | ScaleLinear<number, number, never> | ScaleTime<number, number, never>;
26
+ }): ScaleBand<string> | ScaleLinear<number, number, never> | ScaleTime<number, number, never> | undefined;
28
27
  export declare function createXScale(args: {
29
28
  axis: PreparedAxis | ChartAxis;
30
29
  boundsWidth: number;
31
30
  series: (PreparedSeries | ChartSeries)[];
32
31
  seriesOptions: PreparedSeriesOptions;
33
32
  hasZoomX?: boolean;
34
- }): ScaleBand<string> | ScaleLinear<number, number, never> | ScaleTime<number, number, never>;
33
+ }): ScaleBand<string> | ScaleLinear<number, number, never> | ScaleTime<number, number, never> | undefined;
35
34
  /**
36
35
  * Uses to create scales for axis related series
37
36
  */
@@ -3,11 +3,26 @@ import { extent, scaleBand, scaleLinear, scaleLog, scaleUtc } from 'd3';
3
3
  import get from 'lodash/get';
4
4
  import { DEFAULT_AXIS_TYPE, SeriesType } from '../../constants';
5
5
  import { CHART_SERIES_WITH_VOLUME_ON_Y_AXIS, getAxisHeight, getDataCategoryValue, getDefaultMaxXAxisValue, getDefaultMinXAxisValue, getDomainDataXBySeries, getDomainDataYBySeries, getOnlyVisibleSeries, isAxisRelatedSeries, isSeriesWithCategoryValues, } from '../../utils';
6
- import { getBarYLayoutForNumericScale, groupBarYDataByYValue } from '../utils';
6
+ import { getBandSize } from '../utils';
7
7
  import { getBarXLayoutForNumericScale, groupBarXDataByXValue } from '../utils/bar-x';
8
8
  const X_AXIS_ZOOM_PADDING = 0.02;
9
- function isNumericalArrayData(data) {
10
- return data.every((d) => typeof d === 'number' || d === null);
9
+ function validateArrayData(data) {
10
+ let hasNumberAndNullValues;
11
+ let hasOnlyNullValues;
12
+ for (const d of data) {
13
+ const isNumber = typeof d === 'number';
14
+ const isNull = d === null;
15
+ hasNumberAndNullValues =
16
+ typeof hasNumberAndNullValues === 'undefined'
17
+ ? isNumber || isNull
18
+ : hasNumberAndNullValues && (isNumber || isNull);
19
+ hasOnlyNullValues =
20
+ typeof hasOnlyNullValues === 'undefined' ? isNull : hasOnlyNullValues && isNull;
21
+ if (!hasNumberAndNullValues) {
22
+ break;
23
+ }
24
+ }
25
+ return { hasNumberAndNullValues, hasOnlyNullValues };
11
26
  }
12
27
  function filterCategoriesByVisibleSeries(args) {
13
28
  const { axisDirection, categories, series } = args;
@@ -19,30 +34,18 @@ function filterCategoriesByVisibleSeries(args) {
19
34
  });
20
35
  }
21
36
  });
22
- return categories.filter((c) => visibleCategories.has(c));
37
+ const filteredCategories = categories.filter((c) => visibleCategories.has(c));
38
+ return filteredCategories.length > 0 ? filteredCategories : categories;
23
39
  }
24
40
  // axis is validated in `validation/index.ts`, so the value of `axis.type` is definitely valid.
25
41
  // eslint-disable-next-line consistent-return
26
42
  function getYScaleRange(args) {
27
- const { axis, boundsHeight, series, seriesOptions } = args;
43
+ const { axis, boundsHeight } = args;
28
44
  switch (axis.type) {
29
45
  case 'datetime':
30
46
  case 'linear':
31
47
  case 'logarithmic': {
32
- let range = [boundsHeight, boundsHeight * axis.maxPadding];
33
- const barYSeries = series.filter((s) => s.type === SeriesType.BarY);
34
- if (barYSeries.length) {
35
- const groupedData = groupBarYDataByYValue(barYSeries, [axis]);
36
- if (Object.keys(groupedData).length > 1) {
37
- const { bandSize } = getBarYLayoutForNumericScale({
38
- plotHeight: boundsHeight - boundsHeight * axis.maxPadding,
39
- groupedData,
40
- seriesOptions: seriesOptions,
41
- });
42
- const offset = bandSize / 2;
43
- range = [range[0] - offset, range[1] + offset];
44
- }
45
- }
48
+ const range = [boundsHeight, 0];
46
49
  switch (axis.order) {
47
50
  case 'sortDesc':
48
51
  case 'reverse': {
@@ -56,18 +59,23 @@ function getYScaleRange(args) {
56
59
  }
57
60
  }
58
61
  }
62
+ // eslint-disable-next-line complexity
59
63
  export function createYScale(args) {
60
- const { axis, boundsHeight, series, seriesOptions } = args;
64
+ const { axis, boundsHeight, series } = args;
61
65
  const yMinProps = get(axis, 'min');
62
66
  const yMaxProps = get(axis, 'max');
63
67
  const yCategories = get(axis, 'categories');
64
68
  const yTimestamps = get(axis, 'timestamps');
65
- const range = getYScaleRange({ axis, boundsHeight, series, seriesOptions });
69
+ const range = getYScaleRange({ axis, boundsHeight });
66
70
  switch (axis.type) {
67
71
  case 'linear':
68
72
  case 'logarithmic': {
69
73
  const domain = getDomainDataYBySeries(series);
70
- if (isNumericalArrayData(domain)) {
74
+ const { hasNumberAndNullValues, hasOnlyNullValues } = validateArrayData(domain);
75
+ if (hasOnlyNullValues || domain.length === 0) {
76
+ return undefined;
77
+ }
78
+ if (hasNumberAndNullValues) {
71
79
  const [yMinDomain, yMaxDomain] = extent(domain);
72
80
  const yMin = typeof yMinProps === 'number' ? yMinProps : yMinDomain;
73
81
  let yMax;
@@ -79,7 +87,23 @@ export function createYScale(args) {
79
87
  yMax = hasSeriesWithVolumeOnYAxis ? Math.max(yMaxDomain, 0) : yMaxDomain;
80
88
  }
81
89
  const scaleFn = axis.type === 'logarithmic' ? scaleLog : scaleLinear;
82
- return scaleFn().domain([yMin, yMax]).range(range).nice();
90
+ const scale = scaleFn().domain([yMin, yMax]).range(range);
91
+ let offsetMin = 0;
92
+ let offsetMax = boundsHeight * axis.maxPadding;
93
+ const barYSeries = series.filter((s) => s.type === SeriesType.BarY);
94
+ if (barYSeries.length) {
95
+ if (domain.length > 1) {
96
+ const bandWidth = getBandSize({
97
+ scale: scale,
98
+ domain: domain,
99
+ });
100
+ offsetMin += bandWidth / 2;
101
+ offsetMax += bandWidth / 2;
102
+ }
103
+ }
104
+ const domainOffsetMin = Math.abs(scale.invert(offsetMin) - scale.invert(0));
105
+ const domainOffsetMax = Math.abs(scale.invert(offsetMax) - scale.invert(0));
106
+ return scale.domain([yMin - domainOffsetMin, yMax + domainOffsetMax]);
83
107
  }
84
108
  break;
85
109
  }
@@ -103,11 +127,31 @@ export function createYScale(args) {
103
127
  }
104
128
  else {
105
129
  const domain = getDomainDataYBySeries(series);
106
- if (isNumericalArrayData(domain)) {
130
+ const { hasNumberAndNullValues, hasOnlyNullValues } = validateArrayData(domain);
131
+ if (hasOnlyNullValues || domain.length === 0) {
132
+ return undefined;
133
+ }
134
+ if (hasNumberAndNullValues) {
107
135
  const [yMinTimestamp, yMaxTimestamp] = extent(domain);
108
136
  const yMin = typeof yMinProps === 'number' ? yMinProps : yMinTimestamp;
109
137
  const yMax = typeof yMaxProps === 'number' ? yMaxProps : yMaxTimestamp;
110
- return scaleUtc().domain([yMin, yMax]).range(range).nice();
138
+ const scale = scaleUtc().domain([yMin, yMax]).range(range);
139
+ let offsetMin = 0;
140
+ let offsetMax = boundsHeight * axis.maxPadding;
141
+ const barYSeries = series.filter((s) => s.type === SeriesType.BarY);
142
+ if (barYSeries.length) {
143
+ if (Object.keys(domain).length > 1) {
144
+ const bandWidth = getBandSize({
145
+ scale: scale,
146
+ domain: domain,
147
+ });
148
+ offsetMin += bandWidth / 2;
149
+ offsetMax += bandWidth / 2;
150
+ }
151
+ }
152
+ const domainOffsetMin = Math.abs(scale.invert(offsetMin).getTime() - scale.invert(0).getTime());
153
+ const domainOffsetMax = Math.abs(scale.invert(offsetMax).getTime() - scale.invert(0).getTime());
154
+ return scale.domain([yMin - domainOffsetMin, yMax + domainOffsetMax]);
111
155
  }
112
156
  }
113
157
  }
@@ -178,7 +222,14 @@ export function createXScale(args) {
178
222
  case 'linear':
179
223
  case 'logarithmic': {
180
224
  const domainData = getDomainDataXBySeries(series);
181
- if (isNumericalArrayData(domainData)) {
225
+ const { hasNumberAndNullValues, hasOnlyNullValues } = validateArrayData(domainData);
226
+ if (hasOnlyNullValues || domainData.length === 0) {
227
+ return undefined;
228
+ }
229
+ if (series.some((s) => s.stacking === 'percent')) {
230
+ return scaleLinear().domain([0, 100]).range(range);
231
+ }
232
+ if (hasNumberAndNullValues) {
182
233
  const [xMinDomain, xMaxDomain] = extent(domainData);
183
234
  let xMin;
184
235
  let xMax;
@@ -227,7 +278,11 @@ export function createXScale(args) {
227
278
  case 'datetime': {
228
279
  let domain = null;
229
280
  const domainData = get(axis, 'timestamps') || getDomainDataXBySeries(series);
230
- if (isNumericalArrayData(domainData)) {
281
+ const { hasNumberAndNullValues, hasOnlyNullValues } = validateArrayData(domainData);
282
+ if (hasOnlyNullValues || domainData.length === 0) {
283
+ return undefined;
284
+ }
285
+ if (hasNumberAndNullValues) {
231
286
  const [xMinTimestamp, xMaxTimestamp] = extent(domainData);
232
287
  const xMin = typeof xMinProps === 'number' ? xMinProps : xMinTimestamp;
233
288
  const xMax = typeof xMaxProps === 'number' ? xMaxProps : xMaxTimestamp;
@@ -271,7 +326,6 @@ const createScales = (args) => {
271
326
  axis,
272
327
  boundsHeight: axisHeight,
273
328
  series: visibleAxisSeries.length ? visibleAxisSeries : axisSeries,
274
- seriesOptions,
275
329
  });
276
330
  }),
277
331
  };
@@ -1,4 +1,4 @@
1
- import type { ChartSeries, ChartTitle, ChartTooltip, ChartOptions as GeneralChartOptions } from '../../types';
1
+ import type { ChartSeries, ChartTitle, ChartTooltip, ChartXAxis, ChartYAxis, ChartOptions as GeneralChartOptions } from '../../types';
2
2
  import type { ChartOptions } from './types';
3
3
  type Args = {
4
4
  seriesData: ChartSeries[];
@@ -6,6 +6,8 @@ type Args = {
6
6
  colors?: string[];
7
7
  title?: ChartTitle;
8
8
  tooltip?: ChartTooltip;
9
+ yAxes?: ChartYAxis[];
10
+ xAxis?: ChartXAxis;
9
11
  };
10
12
  export declare const useChartOptions: (args: Args) => ChartOptions;
11
13
  export {};
@@ -4,10 +4,10 @@ import { getPreparedChart } from './chart';
4
4
  import { getPreparedTitle } from './title';
5
5
  import { getPreparedTooltip } from './tooltip';
6
6
  export const useChartOptions = (args) => {
7
- const { chart, colors, seriesData, title, tooltip } = args;
7
+ const { chart, colors, seriesData, title, tooltip, yAxes, xAxis } = args;
8
8
  const options = React.useMemo(() => {
9
9
  const preparedTitle = getPreparedTitle({ title });
10
- const preparedTooltip = getPreparedTooltip({ tooltip });
10
+ const preparedTooltip = getPreparedTooltip({ tooltip, seriesData, yAxes, xAxis });
11
11
  const preparedChart = getPreparedChart({
12
12
  chart,
13
13
  preparedTitle,
@@ -19,6 +19,6 @@ export const useChartOptions = (args) => {
19
19
  title: preparedTitle,
20
20
  tooltip: preparedTooltip,
21
21
  };
22
- }, [chart, colors, seriesData, title, tooltip]);
22
+ }, [chart, colors, seriesData, title, tooltip, xAxis, yAxes]);
23
23
  return options;
24
24
  };
@@ -1,5 +1,8 @@
1
- import type { ChartData } from '../../types';
1
+ import type { ChartData, ChartSeries, ChartXAxis, ChartYAxis } from '../../types';
2
2
  import type { PreparedTooltip } from './types';
3
3
  export declare const getPreparedTooltip: (args: {
4
4
  tooltip: ChartData["tooltip"];
5
+ seriesData: ChartSeries[];
6
+ yAxes?: ChartYAxis[];
7
+ xAxis?: ChartXAxis;
5
8
  }) => PreparedTooltip;
@@ -1,6 +1,21 @@
1
1
  import get from 'lodash/get';
2
+ import { getDefaultValueFormat } from '../../components/Tooltip/DefaultTooltipContent/utils';
3
+ import { getDomainDataXBySeries, getDomainDataYBySeries, getMinSpaceBetween } from '../../utils';
4
+ function getDefaultHeaderFormat({ seriesData, yAxes, xAxis, }) {
5
+ if (seriesData.every((item) => ['pie', 'treemap', 'waterfall', 'sankey', 'radar'].includes(item.type))) {
6
+ return undefined;
7
+ }
8
+ if (seriesData.some((item) => item.type === 'bar-y')) {
9
+ const domainData = getDomainDataYBySeries(seriesData);
10
+ const closestPointsRange = getMinSpaceBetween(domainData, (d) => d);
11
+ return getDefaultValueFormat({ axis: yAxes === null || yAxes === void 0 ? void 0 : yAxes[0], closestPointsRange });
12
+ }
13
+ const domainData = getDomainDataXBySeries(seriesData);
14
+ const closestPointsRange = getMinSpaceBetween(domainData, (d) => d);
15
+ return getDefaultValueFormat({ axis: xAxis, closestPointsRange });
16
+ }
2
17
  export const getPreparedTooltip = (args) => {
3
- var _a;
4
- const { tooltip } = args;
5
- return Object.assign(Object.assign({}, tooltip), { enabled: get(tooltip, 'enabled', true), throttle: (_a = tooltip === null || tooltip === void 0 ? void 0 : tooltip.throttle) !== null && _a !== void 0 ? _a : 0 });
18
+ var _a, _b;
19
+ const { tooltip, seriesData, yAxes, xAxis } = args;
20
+ return Object.assign(Object.assign({}, tooltip), { enabled: get(tooltip, 'enabled', true), throttle: (_a = tooltip === null || tooltip === void 0 ? void 0 : tooltip.throttle) !== null && _a !== void 0 ? _a : 0, headerFormat: (_b = tooltip === null || tooltip === void 0 ? void 0 : tooltip.headerFormat) !== null && _b !== void 0 ? _b : getDefaultHeaderFormat({ seriesData, yAxes, xAxis }) });
6
21
  };
@@ -1,4 +1,4 @@
1
- import type { AxisPlot, ChartYAxis } from '../../types';
1
+ import type { AxisPlot, ChartAxis } from '../../types';
2
2
  export declare function prepareAxisPlotLabel(d: AxisPlot): {
3
3
  text: string;
4
4
  style: {
@@ -8,4 +8,7 @@ export declare function prepareAxisPlotLabel(d: AxisPlot): {
8
8
  };
9
9
  padding: number;
10
10
  };
11
- export declare function getAxisCategories(axis?: ChartYAxis): string[] | undefined;
11
+ export declare function getAxisCategories({ categories, order, }?: {
12
+ categories?: string[];
13
+ order?: ChartAxis['order'];
14
+ }): string[] | undefined;
@@ -8,10 +8,9 @@ export function prepareAxisPlotLabel(d) {
8
8
  padding: (_e = (_d = d.label) === null || _d === void 0 ? void 0 : _d.padding) !== null && _e !== void 0 ? _e : 5,
9
9
  };
10
10
  }
11
- export function getAxisCategories(axis) {
12
- const categories = axis === null || axis === void 0 ? void 0 : axis.categories;
11
+ export function getAxisCategories({ categories, order, } = {}) {
13
12
  if (categories) {
14
- switch (axis.order) {
13
+ switch (order) {
15
14
  case 'reverse': {
16
15
  return reverse(categories);
17
16
  }
@@ -1,10 +1,15 @@
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, calculateNumericProperty, formatAxisTickLabel, getAxisItems, getClosestPointsRange, getHorizontalHtmlTextHeight, getHorizontalSvgTextHeight, getLabelsSize, getMaxTickCount, getTicksCount, hasOverlappingLabels, wrapText, } from '../../utils';
3
+ import { calculateCos, calculateNumericProperty, formatAxisTickLabel, getAxisItems, getClosestPointsRange, getDefaultDateFormat, getHorizontalHtmlTextHeight, getHorizontalSvgTextHeight, getLabelsSize, getMaxTickCount, getTicksCount, hasOverlappingLabels, wrapText, } from '../../utils';
4
4
  import { createXScale } from '../useAxisScales';
5
5
  import { getAxisCategories, prepareAxisPlotLabel } from './utils';
6
- async function getLabelSettings({ axis, seriesData, seriesOptions, width, autoRotation = true, }) {
6
+ async function setLabelSettings({ axis, seriesData, seriesOptions, width, autoRotation = true, }) {
7
7
  const scale = createXScale({ axis, series: seriesData, seriesOptions, boundsWidth: width });
8
+ if (!scale) {
9
+ axis.labels.height = 0;
10
+ axis.labels.rotation = 0;
11
+ return;
12
+ }
8
13
  const tickCount = getTicksCount({ axis, range: width });
9
14
  const ticks = getAxisItems({
10
15
  scale: scale,
@@ -12,6 +17,9 @@ async function getLabelSettings({ axis, seriesData, seriesOptions, width, autoRo
12
17
  maxCount: getMaxTickCount({ width, axis }),
13
18
  });
14
19
  const step = getClosestPointsRange(axis, ticks);
20
+ if (axis.type === 'datetime' && !axis.labels.dateFormat) {
21
+ axis.labels.dateFormat = getDefaultDateFormat(step);
22
+ }
15
23
  const labels = ticks.map((value) => {
16
24
  return formatAxisTickLabel({
17
25
  axis,
@@ -38,10 +46,11 @@ async function getLabelSettings({ axis, seriesData, seriesOptions, width, autoRo
38
46
  })).maxHeight
39
47
  : axis.labels.lineHeight;
40
48
  const maxHeight = rotation ? calculateCos(rotation) * axis.labels.maxWidth : labelsHeight;
41
- return { height: Math.min(maxHeight, labelsHeight), rotation };
49
+ axis.labels.height = Math.min(maxHeight, labelsHeight);
50
+ axis.labels.rotation = rotation;
42
51
  }
43
52
  export const getPreparedXAxis = async ({ xAxis, seriesData, seriesOptions, width, }) => {
44
- var _a, _b, _c;
53
+ var _a, _b, _c, _d, _e;
45
54
  const titleText = get(xAxis, 'title.text', '');
46
55
  const titleStyle = Object.assign(Object.assign({}, xAxisTitleDefaults.style), get(xAxis, 'title.style'));
47
56
  const titleMaxRowsCount = get(xAxis, 'title.maxRowCount', xAxisTitleDefaults.maxRowCount);
@@ -96,7 +105,12 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, seriesOptions, width
96
105
  enabled: get(xAxis, 'grid.enabled', true),
97
106
  },
98
107
  ticks: {
99
- pixelInterval: get(xAxis, 'ticks.pixelInterval'),
108
+ pixelInterval: ((_c = xAxis === null || xAxis === void 0 ? void 0 : xAxis.ticks) === null || _c === void 0 ? void 0 : _c.interval)
109
+ ? calculateNumericProperty({
110
+ base: width,
111
+ value: xAxis.ticks.interval,
112
+ })
113
+ : (_d = xAxis === null || xAxis === void 0 ? void 0 : xAxis.ticks) === null || _d === void 0 ? void 0 : _d.pixelInterval,
100
114
  },
101
115
  position: 'bottom',
102
116
  plotIndex: 0,
@@ -129,14 +143,12 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, seriesOptions, width
129
143
  visible: get(xAxis, 'visible', true),
130
144
  order: xAxis === null || xAxis === void 0 ? void 0 : xAxis.order,
131
145
  };
132
- const { height, rotation } = await getLabelSettings({
146
+ await setLabelSettings({
133
147
  axis: preparedXAxis,
134
148
  seriesData,
135
149
  seriesOptions,
136
150
  width,
137
- autoRotation: (_c = xAxis === null || xAxis === void 0 ? void 0 : xAxis.labels) === null || _c === void 0 ? void 0 : _c.autoRotation,
151
+ autoRotation: (_e = xAxis === null || xAxis === void 0 ? void 0 : xAxis.labels) === null || _e === void 0 ? void 0 : _e.autoRotation,
138
152
  });
139
- preparedXAxis.labels.height = height;
140
- preparedXAxis.labels.rotation = rotation;
141
153
  return preparedXAxis;
142
154
  };
@@ -1,11 +1,9 @@
1
1
  import type { ChartSeries, ChartYAxis } from '../../types';
2
- import type { PreparedSeriesOptions } from '../useSeries/types';
3
2
  import type { PreparedAxis } from './types';
4
- export declare const getPreparedYAxis: ({ height, boundsHeight, width, seriesData, seriesOptions, yAxis, }: {
3
+ export declare const getPreparedYAxis: ({ height, boundsHeight, width, seriesData, yAxis, }: {
5
4
  height: number;
6
5
  boundsHeight: number;
7
6
  width: number;
8
7
  seriesData: ChartSeries[];
9
- seriesOptions: PreparedSeriesOptions;
10
8
  yAxis: ChartYAxis[] | undefined;
11
9
  }) => Promise<PreparedAxis[]>;