@gravity-ui/charts 1.35.1 → 1.36.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 (101) hide show
  1. package/dist/cjs/components/AxisX/AxisX.js +18 -8
  2. package/dist/cjs/components/AxisX/prepare-axis-data.js +12 -0
  3. package/dist/cjs/components/AxisX/styles.css +7 -2
  4. package/dist/cjs/components/AxisX/types.d.ts +5 -0
  5. package/dist/cjs/components/AxisY/AxisY.js +16 -8
  6. package/dist/cjs/components/AxisY/prepare-axis-data.js +14 -0
  7. package/dist/cjs/components/AxisY/styles.css +7 -2
  8. package/dist/cjs/components/AxisY/types.d.ts +5 -0
  9. package/dist/cjs/components/ChartInner/index.js +2 -0
  10. package/dist/cjs/components/ChartInner/styles.css +1 -0
  11. package/dist/cjs/components/ChartInner/useChartInnerHandlers.d.ts +3 -0
  12. package/dist/cjs/components/ChartInner/useChartInnerHandlers.js +26 -3
  13. package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +1 -0
  14. package/dist/cjs/components/Tooltip/ChartTooltipContent.d.ts +3 -1
  15. package/dist/cjs/components/Tooltip/ChartTooltipContent.js +2 -2
  16. package/dist/cjs/components/Tooltip/DefaultTooltipContent/Row.js +1 -1
  17. package/dist/cjs/components/Tooltip/index.js +5 -2
  18. package/dist/cjs/components/Tooltip/styles.css +7 -0
  19. package/dist/cjs/constants/datetime.d.ts +8 -0
  20. package/dist/cjs/constants/datetime.js +8 -0
  21. package/dist/cjs/constants/defaults/axis.d.ts +4 -0
  22. package/dist/cjs/constants/defaults/axis.js +4 -0
  23. package/dist/cjs/constants/index.d.ts +1 -1
  24. package/dist/cjs/constants/index.js +1 -1
  25. package/dist/cjs/hooks/useAxis/types.d.ts +8 -1
  26. package/dist/cjs/hooks/useAxis/utils.d.ts +1 -1
  27. package/dist/cjs/hooks/useAxis/x-axis.js +9 -3
  28. package/dist/cjs/hooks/useAxis/y-axis.js +7 -1
  29. package/dist/cjs/hooks/useAxisScales/x-scale.d.ts +1 -1
  30. package/dist/cjs/hooks/useAxisScales/y-scale.d.ts +1 -1
  31. package/dist/cjs/hooks/useNormalizedOriginalData/index.d.ts +1 -0
  32. package/dist/cjs/hooks/useTooltip/index.d.ts +3 -1
  33. package/dist/cjs/hooks/useTooltip/index.js +7 -3
  34. package/dist/cjs/types/chart/axis.d.ts +17 -3
  35. package/dist/cjs/types/chart/base.d.ts +1 -1
  36. package/dist/cjs/types/chart/tooltip.d.ts +5 -1
  37. package/dist/cjs/utils/chart/axis/common.d.ts +1 -3
  38. package/dist/cjs/utils/chart/axis/common.js +2 -10
  39. package/dist/cjs/utils/chart/axis/x-axis.js +3 -2
  40. package/dist/cjs/utils/chart/format.js +17 -2
  41. package/dist/cjs/utils/chart/get-hovered-plots.d.ts +14 -0
  42. package/dist/cjs/utils/chart/get-hovered-plots.js +67 -0
  43. package/dist/cjs/utils/chart/ticks/datetime.d.ts +8 -0
  44. package/dist/cjs/utils/chart/ticks/datetime.js +50 -0
  45. package/dist/cjs/utils/chart/ticks/index.d.ts +6 -0
  46. package/dist/cjs/utils/chart/ticks/index.js +17 -0
  47. package/dist/cjs/utils/chart/time.d.ts +1 -0
  48. package/dist/cjs/utils/chart/time.js +9 -0
  49. package/dist/esm/components/AxisX/AxisX.js +18 -8
  50. package/dist/esm/components/AxisX/prepare-axis-data.js +12 -0
  51. package/dist/esm/components/AxisX/styles.css +7 -2
  52. package/dist/esm/components/AxisX/types.d.ts +5 -0
  53. package/dist/esm/components/AxisY/AxisY.js +16 -8
  54. package/dist/esm/components/AxisY/prepare-axis-data.js +14 -0
  55. package/dist/esm/components/AxisY/styles.css +7 -2
  56. package/dist/esm/components/AxisY/types.d.ts +5 -0
  57. package/dist/esm/components/ChartInner/index.js +2 -0
  58. package/dist/esm/components/ChartInner/styles.css +1 -0
  59. package/dist/esm/components/ChartInner/useChartInnerHandlers.d.ts +3 -0
  60. package/dist/esm/components/ChartInner/useChartInnerHandlers.js +26 -3
  61. package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +1 -0
  62. package/dist/esm/components/Tooltip/ChartTooltipContent.d.ts +3 -1
  63. package/dist/esm/components/Tooltip/ChartTooltipContent.js +2 -2
  64. package/dist/esm/components/Tooltip/DefaultTooltipContent/Row.js +1 -1
  65. package/dist/esm/components/Tooltip/index.js +5 -2
  66. package/dist/esm/components/Tooltip/styles.css +7 -0
  67. package/dist/esm/constants/datetime.d.ts +8 -0
  68. package/dist/esm/constants/datetime.js +8 -0
  69. package/dist/esm/constants/defaults/axis.d.ts +4 -0
  70. package/dist/esm/constants/defaults/axis.js +4 -0
  71. package/dist/esm/constants/index.d.ts +1 -1
  72. package/dist/esm/constants/index.js +1 -1
  73. package/dist/esm/hooks/useAxis/types.d.ts +8 -1
  74. package/dist/esm/hooks/useAxis/utils.d.ts +1 -1
  75. package/dist/esm/hooks/useAxis/x-axis.js +9 -3
  76. package/dist/esm/hooks/useAxis/y-axis.js +7 -1
  77. package/dist/esm/hooks/useAxisScales/x-scale.d.ts +1 -1
  78. package/dist/esm/hooks/useAxisScales/y-scale.d.ts +1 -1
  79. package/dist/esm/hooks/useNormalizedOriginalData/index.d.ts +1 -0
  80. package/dist/esm/hooks/useTooltip/index.d.ts +3 -1
  81. package/dist/esm/hooks/useTooltip/index.js +7 -3
  82. package/dist/esm/types/chart/axis.d.ts +17 -3
  83. package/dist/esm/types/chart/base.d.ts +1 -1
  84. package/dist/esm/types/chart/tooltip.d.ts +5 -1
  85. package/dist/esm/utils/chart/axis/common.d.ts +1 -3
  86. package/dist/esm/utils/chart/axis/common.js +2 -10
  87. package/dist/esm/utils/chart/axis/x-axis.js +3 -2
  88. package/dist/esm/utils/chart/format.js +17 -2
  89. package/dist/esm/utils/chart/get-hovered-plots.d.ts +14 -0
  90. package/dist/esm/utils/chart/get-hovered-plots.js +67 -0
  91. package/dist/esm/utils/chart/ticks/datetime.d.ts +8 -0
  92. package/dist/esm/utils/chart/ticks/datetime.js +50 -0
  93. package/dist/esm/utils/chart/ticks/index.d.ts +6 -0
  94. package/dist/esm/utils/chart/ticks/index.js +17 -0
  95. package/dist/esm/utils/chart/time.d.ts +1 -0
  96. package/dist/esm/utils/chart/time.js +9 -0
  97. package/package.json +1 -1
  98. package/dist/cjs/constants/date.d.ts +0 -1
  99. package/dist/cjs/constants/date.js +0 -1
  100. package/dist/esm/constants/date.d.ts +0 -1
  101. package/dist/esm/constants/date.js +0 -1
@@ -16,8 +16,12 @@ export type AxisSvgLabelData = {
16
16
  export type AxisTickLine = {
17
17
  points: PointPosition[];
18
18
  };
19
+ export type AxisTickMarkData = {
20
+ points: PointPosition[];
21
+ };
19
22
  export type AxisTickData = {
20
23
  line: AxisTickLine | null;
24
+ mark: AxisTickMarkData | null;
21
25
  svgLabel: AxisSvgLabelData | null;
22
26
  htmlLabel: HtmlItem | null;
23
27
  };
@@ -70,6 +74,7 @@ export type AxisDomainData = {
70
74
  };
71
75
  export type AxisXData = {
72
76
  id: string;
77
+ gridEnabled: boolean;
73
78
  title: AxisTitleData | null;
74
79
  domain: AxisDomainData | null;
75
80
  ticks: AxisTickData[];
@@ -15,7 +15,7 @@ export const AxisY = (props) => {
15
15
  htmlElements.push(preparedAxisData.title);
16
16
  }
17
17
  React.useEffect(() => {
18
- var _a;
18
+ var _a, _b, _c;
19
19
  if (!ref.current) {
20
20
  return () => { };
21
21
  }
@@ -38,15 +38,17 @@ export const AxisY = (props) => {
38
38
  .attr('class', b('title'))
39
39
  .append('text')
40
40
  .attr('text-anchor', 'start')
41
- .style('dominant-baseline', 'text-after-edge')
42
- .style('transform', `translate(${preparedAxisData.title.x}px, ${preparedAxisData.title.y}px) rotate(${preparedAxisData.title.rotate}deg) translate(0px, ${preparedAxisData.title.offset}px)`)
41
+ .attr('transform', `translate(${preparedAxisData.title.x}, ${preparedAxisData.title.y}) rotate(${preparedAxisData.title.rotate}) translate(0, ${preparedAxisData.title.offset})`)
43
42
  .attr('font-size', preparedAxisData.title.style.fontSize)
43
+ .attr('font-weight', (_b = preparedAxisData.title.style.fontWeight) !== null && _b !== void 0 ? _b : null)
44
+ .attr('fill', (_c = preparedAxisData.title.style.fontColor) !== null && _c !== void 0 ? _c : null)
44
45
  .selectAll('tspan')
45
46
  .data(preparedAxisData.title.content)
46
47
  .join('tspan')
47
48
  .html((d) => d.text)
48
49
  .attr('x', (d) => d.x)
49
50
  .attr('y', (d) => d.y)
51
+ .attr('dominant-baseline', 'text-after-edge')
50
52
  .attr('text-anchor', 'start');
51
53
  }
52
54
  if (preparedAxisData.domain) {
@@ -71,13 +73,19 @@ export const AxisY = (props) => {
71
73
  if (tickData.line) {
72
74
  tickSelection.append('path').attr('d', lineGenerator(tickData.line.points));
73
75
  }
76
+ if (tickData.mark) {
77
+ tickSelection
78
+ .append('path')
79
+ .attr('class', b('mark', { grid: preparedAxisData.gridEnabled }))
80
+ .attr('d', lineGenerator(tickData.mark.points));
81
+ }
74
82
  if (tickData.svgLabel) {
75
83
  const label = tickData.svgLabel;
76
84
  const textSelection = tickSelection
77
85
  .append('text')
78
- .style('transform', [
79
- `translate(${label.x}px, ${label.y}px)`,
80
- label.angle ? `rotate(${label.angle}deg)` : '',
86
+ .attr('transform', [
87
+ `translate(${label.x}, ${label.y})`,
88
+ label.angle ? `rotate(${label.angle})` : '',
81
89
  ]
82
90
  .filter(Boolean)
83
91
  .join(' '));
@@ -110,7 +118,7 @@ export const AxisY = (props) => {
110
118
  .join('g')
111
119
  .attr(plotDataAttr, 1)
112
120
  .attr(plotBandDataAttr, 1)
113
- .style('transform', (d) => `translate(${d.x}px, ${d.y}px)`);
121
+ .attr('transform', (d) => `translate(${d.x}, ${d.y})`);
114
122
  plotBandsSelection
115
123
  .append('rect')
116
124
  .attr('width', (d) => d.width)
@@ -151,7 +159,7 @@ export const AxisY = (props) => {
151
159
  .join('g')
152
160
  .attr(plotDataAttr, 1)
153
161
  .attr(plotLineDataAttr, 1)
154
- .style('transform', (d) => `translate(${d.x}px, ${d.y}px)`);
162
+ .attr('transform', (d) => `translate(${d.x}, ${d.y})`);
155
163
  plotLinesSelection
156
164
  .append('path')
157
165
  .attr('d', (d) => lineGenerator(d.points))
@@ -175,8 +175,21 @@ export async function prepareYAxisData({ axis, split, scale, top: topOffset, wid
175
175
  ],
176
176
  }
177
177
  : null;
178
+ let mark = null;
179
+ if (axis.tickMarks.enabled) {
180
+ const isLeft = axis.position === 'left';
181
+ const markX = isLeft ? 0 : width;
182
+ const dir = isLeft ? -1 : 1;
183
+ mark = {
184
+ points: [
185
+ [markX, y],
186
+ [markX + dir * axis.tickMarks.length, y],
187
+ ],
188
+ };
189
+ }
178
190
  ticks.push({
179
191
  line: tickLine,
192
+ mark,
180
193
  svgLabel,
181
194
  htmlLabel,
182
195
  });
@@ -273,6 +286,7 @@ export async function prepareYAxisData({ axis, split, scale, top: topOffset, wid
273
286
  }
274
287
  return {
275
288
  id: getUniqId(),
289
+ gridEnabled: axis.grid.enabled,
276
290
  title,
277
291
  ticks,
278
292
  domain,
@@ -7,9 +7,14 @@
7
7
  dominant-baseline: text-after-edge;
8
8
  }
9
9
  .gcharts-y-axis__tick {
10
- stroke: var(--g-color-line-generic);
10
+ stroke: var(--gcharts-axis-tick-color);
11
+ }
12
+ .gcharts-y-axis__mark {
13
+ stroke: var(--gcharts-axis-tick-mark-color, var(--g-color-line-generic-active));
14
+ }
15
+ .gcharts-y-axis__mark_grid {
16
+ stroke: var(--gcharts-axis-tick-mark-color, var(--gcharts-axis-tick-color));
11
17
  }
12
18
  .gcharts-y-axis__title {
13
- dominant-baseline: text-after-edge;
14
19
  fill: var(--g-color-text-secondary);
15
20
  }
@@ -16,8 +16,12 @@ export type AxisSvgLabelData = {
16
16
  export type AxisTickLine = {
17
17
  points: PointPosition[];
18
18
  };
19
+ export type AxisTickMarkData = {
20
+ points: PointPosition[];
21
+ };
19
22
  export type AxisTickData = {
20
23
  line: AxisTickLine | null;
24
+ mark: AxisTickMarkData | null;
21
25
  svgLabel: AxisSvgLabelData | null;
22
26
  htmlLabel: HtmlItem | null;
23
27
  };
@@ -81,6 +85,7 @@ export type AxisDomainData = {
81
85
  };
82
86
  export type AxisYData = {
83
87
  id: string;
88
+ gridEnabled: boolean;
84
89
  title: HtmlAxisTitleData | SvgAxisTitleData | null;
85
90
  domain: AxisDomainData | null;
86
91
  ticks: AxisTickData[];
@@ -93,6 +93,8 @@ export const ChartInner = (props) => {
93
93
  unpinTooltip,
94
94
  xAxis,
95
95
  yAxis,
96
+ xScale,
97
+ yScale,
96
98
  tooltipThrottle: preparedTooltip.throttle,
97
99
  isOutsideBounds,
98
100
  });
@@ -1,6 +1,7 @@
1
1
  .gcharts-chart {
2
2
  --gcharts-data-labels: var(--g-color-text-secondary);
3
3
  --gcharts-shape-border-color: var(--g-color-base-background);
4
+ --gcharts-axis-tick-color: var(--g-color-line-generic);
4
5
  position: absolute;
5
6
  inset-block-start: 0;
6
7
  inset-inline-start: 0;
@@ -1,6 +1,7 @@
1
1
  import type React from 'react';
2
2
  import type { Dispatch } from 'd3';
3
3
  import type { PreparedXAxis, PreparedYAxis, ShapeData } from '../../hooks';
4
+ import type { ChartScale } from '../../hooks/useAxisScales/types';
4
5
  import type { useChartInnerState } from './useChartInnerState';
5
6
  type ChartInnerState = ReturnType<typeof useChartInnerState>;
6
7
  type Props = {
@@ -16,6 +17,8 @@ type Props = {
16
17
  unpinTooltip: ChartInnerState['unpinTooltip'];
17
18
  xAxis: PreparedXAxis | null;
18
19
  yAxis: PreparedYAxis[];
20
+ xScale?: ChartScale;
21
+ yScale?: (ChartScale | undefined)[];
19
22
  tooltipThrottle: number;
20
23
  isOutsideBounds: (x: number, y: number) => boolean;
21
24
  };
@@ -4,8 +4,9 @@ import throttle from 'lodash/throttle';
4
4
  import { IS_TOUCH_ENABLED } from '../../constants';
5
5
  import { EventType } from '../../utils';
6
6
  import { getClosestPoints } from '../../utils/chart/get-closest-data';
7
+ import { getHoveredPlots } from '../../utils/chart/get-hovered-plots';
7
8
  export function useChartInnerHandlers(props) {
8
- const { boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, dispatcher, shapesData, svgContainer, togglePinTooltip, tooltipPinned, unpinTooltip, xAxis, yAxis, tooltipThrottle, isOutsideBounds, } = props;
9
+ const { boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, dispatcher, shapesData, svgContainer, togglePinTooltip, tooltipPinned, unpinTooltip, xAxis, yAxis, xScale, yScale, tooltipThrottle, isOutsideBounds, } = props;
9
10
  const handleMove = ([pointerX, pointerY], event) => {
10
11
  if (tooltipPinned) {
11
12
  return;
@@ -24,11 +25,22 @@ export function useChartInnerHandlers(props) {
24
25
  boundsHeight,
25
26
  boundsWidth,
26
27
  });
27
- dispatcher.call(EventType.HOVER_SHAPE, event.target, closest, [pointerX, pointerY]);
28
+ const { plotLines, plotBands } = getHoveredPlots({
29
+ pointerX: x,
30
+ pointerY: y,
31
+ xAxis,
32
+ yAxis,
33
+ xScale,
34
+ yScale,
35
+ });
36
+ const hoveredPlotsArg = { lines: plotLines, bands: plotBands };
37
+ dispatcher.call(EventType.HOVER_SHAPE, event.target, closest, [pointerX, pointerY], hoveredPlotsArg);
28
38
  dispatcher.call(EventType.POINTERMOVE_CHART, {}, {
29
39
  hovered: closest,
30
40
  xAxis,
31
41
  yAxis: yAxis[0],
42
+ hoveredPlotLines: plotLines,
43
+ hoveredPlotBands: plotBands,
32
44
  }, event);
33
45
  };
34
46
  const handleMouseMove = (event) => {
@@ -77,11 +89,22 @@ export function useChartInnerHandlers(props) {
77
89
  dispatcher.call(EventType.CLICK_CHART, undefined, { point: selected.data, series: selected.series }, event);
78
90
  const nextTooltipFixed = !tooltipPinned;
79
91
  if (!nextTooltipFixed) {
80
- dispatcher.call(EventType.HOVER_SHAPE, event.target, items, [pointerX, pointerY]);
92
+ const { plotLines, plotBands } = getHoveredPlots({
93
+ pointerX: x,
94
+ pointerY: y,
95
+ xAxis,
96
+ yAxis,
97
+ xScale,
98
+ yScale,
99
+ });
100
+ const hoveredPlotsArg = { lines: plotLines, bands: plotBands };
101
+ dispatcher.call(EventType.HOVER_SHAPE, event.target, items, [pointerX, pointerY], hoveredPlotsArg);
81
102
  dispatcher.call(EventType.POINTERMOVE_CHART, {}, {
82
103
  hovered: items,
83
104
  xAxis,
84
105
  yAxis: yAxis[0],
106
+ hoveredPlotLines: plotLines,
107
+ hoveredPlotBands: plotBands,
85
108
  }, event);
86
109
  }
87
110
  togglePinTooltip === null || togglePinTooltip === void 0 ? void 0 : togglePinTooltip(nextTooltipFixed, event);
@@ -77,6 +77,7 @@ export declare function useChartInnerProps(props: Props): {
77
77
  ticks: {
78
78
  pixelInterval?: number;
79
79
  };
80
+ tickMarks: import("../../hooks").PreparedAxisTickMarks;
80
81
  position: "left" | "right" | "top" | "bottom";
81
82
  plotIndex: number;
82
83
  plotLines: import("../../hooks").PreparedAxisPlotLine[];
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { ChartTooltip, ChartXAxis, ChartYAxis, TooltipDataChunk } from '../../types';
2
+ import type { ChartTooltip, ChartTooltipRendererArgs, ChartXAxis, ChartYAxis, TooltipDataChunk } from '../../types';
3
3
  export interface ChartTooltipContentProps {
4
4
  hovered?: TooltipDataChunk[];
5
5
  pinned?: boolean;
@@ -7,6 +7,8 @@ export interface ChartTooltipContentProps {
7
7
  rowRenderer?: ChartTooltip['rowRenderer'];
8
8
  valueFormat?: ChartTooltip['valueFormat'];
9
9
  headerFormat?: ChartTooltip['headerFormat'];
10
+ hoveredPlotLines?: ChartTooltipRendererArgs['hoveredPlotLines'];
11
+ hoveredPlotBands?: ChartTooltipRendererArgs['hoveredPlotBands'];
10
12
  totals?: ChartTooltip['totals'];
11
13
  xAxis?: ChartXAxis | null;
12
14
  yAxis?: ChartYAxis;
@@ -2,11 +2,11 @@ import React from 'react';
2
2
  import isNil from 'lodash/isNil';
3
3
  import { DefaultTooltipContent } from './DefaultTooltipContent';
4
4
  export const ChartTooltipContent = React.memo((props) => {
5
- const { hovered, xAxis, yAxis, renderer, rowRenderer, valueFormat, headerFormat, totals, pinned, qa, } = props;
5
+ const { hovered, hoveredPlotLines, hoveredPlotBands, xAxis, yAxis, renderer, rowRenderer, valueFormat, headerFormat, totals, pinned, qa, } = props;
6
6
  if (!hovered) {
7
7
  return null;
8
8
  }
9
- const customTooltip = renderer === null || renderer === void 0 ? void 0 : renderer({ hovered, xAxis, yAxis });
9
+ const customTooltip = renderer === null || renderer === void 0 ? void 0 : renderer({ hovered, hoveredPlotLines, hoveredPlotBands, xAxis, yAxis });
10
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
  });
12
12
  ChartTooltipContent.displayName = 'ChartTooltipContent';
@@ -14,6 +14,6 @@ export function Row(props) {
14
14
  }, [color, colorSymbol]);
15
15
  return (React.createElement("div", { className: b('content-row', { active, striped }, className), style: style },
16
16
  colorItem,
17
- label,
17
+ React.createElement("span", { className: b('content-row-label') }, label),
18
18
  value && React.createElement("span", { className: b('content-row-value') }, value)));
19
19
  }
@@ -7,7 +7,10 @@ import './styles.css';
7
7
  const b = block('tooltip');
8
8
  export const Tooltip = (props) => {
9
9
  const { tooltip, xAxis, yAxis, svgContainer, dispatcher, tooltipPinned, onOutsideClick } = props;
10
- const { hovered, pointerPosition } = useTooltip({ dispatcher, tooltip });
10
+ const { hovered, hoveredPlotLines, hoveredPlotBands, pointerPosition } = useTooltip({
11
+ dispatcher,
12
+ tooltip,
13
+ });
11
14
  const containerRect = (svgContainer === null || svgContainer === void 0 ? void 0 : svgContainer.getBoundingClientRect()) || { left: 0, top: 0 };
12
15
  const left = ((pointerPosition === null || pointerPosition === void 0 ? void 0 : pointerPosition[0]) || 0) + containerRect.left;
13
16
  const top = ((pointerPosition === null || pointerPosition === void 0 ? void 0 : pointerPosition[1]) || 0) + containerRect.top;
@@ -23,5 +26,5 @@ export const Tooltip = (props) => {
23
26
  }, [left, top]);
24
27
  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
28
  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, qa: tooltip.qa })))) : null;
29
+ React.createElement(ChartTooltipContent, { hovered: hovered, hoveredPlotLines: hoveredPlotLines, hoveredPlotBands: hoveredPlotBands, 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
30
  };
@@ -45,14 +45,21 @@
45
45
  font-weight: 600;
46
46
  background-color: var(--g-color-base-info-medium);
47
47
  }
48
+ .gcharts-tooltip__content-row-label {
49
+ overflow: hidden;
50
+ white-space: nowrap;
51
+ text-overflow: ellipsis;
52
+ }
48
53
  .gcharts-tooltip__content-row-color {
49
54
  display: inline-block;
55
+ flex-shrink: 0;
50
56
  width: 16px;
51
57
  height: 8px;
52
58
  border-radius: 2px;
53
59
  background-color: #dddddd;
54
60
  }
55
61
  .gcharts-tooltip__content-row-value {
62
+ flex-shrink: 0;
56
63
  margin-inline-start: auto;
57
64
  }
58
65
  .gcharts-tooltip__content-row-totals {
@@ -0,0 +1,8 @@
1
+ export declare const DEFAULT_DATE_FORMAT = "DD.MM.YY";
2
+ export declare const SECOND = 1000;
3
+ export declare const MINUTE: number;
4
+ export declare const HOUR: number;
5
+ export declare const DAY: number;
6
+ export declare const WEEK: number;
7
+ export declare const MONTH: number;
8
+ export declare const YEAR: number;
@@ -0,0 +1,8 @@
1
+ export const DEFAULT_DATE_FORMAT = 'DD.MM.YY';
2
+ export const SECOND = 1000;
3
+ export const MINUTE = SECOND * 60;
4
+ export const HOUR = MINUTE * 60;
5
+ export const DAY = HOUR * 24;
6
+ export const WEEK = DAY * 7;
7
+ export const MONTH = DAY * 30;
8
+ export const YEAR = DAY * 365;
@@ -12,5 +12,9 @@ type AxisCrosshairDefaults = Required<AxisCrosshair>;
12
12
  export declare const axisCrosshairDefaults: AxisCrosshairDefaults;
13
13
  export declare const xAxisTitleDefaults: AxisTitleDefaults;
14
14
  export declare const yAxisTitleDefaults: AxisTitleDefaults;
15
+ export declare const axisTickMarksDefaults: {
16
+ enabled: boolean;
17
+ length: number;
18
+ };
15
19
  export declare const DEFAULT_AXIS_TYPE: ChartAxisType;
16
20
  export {};
@@ -25,4 +25,8 @@ export const axisCrosshairDefaults = {
25
25
  };
26
26
  export const xAxisTitleDefaults = Object.assign(Object.assign({}, axisTitleDefaults), { margin: 4 });
27
27
  export const yAxisTitleDefaults = Object.assign(Object.assign({}, axisTitleDefaults), { margin: 8 });
28
+ export const axisTickMarksDefaults = {
29
+ enabled: false,
30
+ length: 6,
31
+ };
28
32
  export const DEFAULT_AXIS_TYPE = 'linear';
@@ -1,6 +1,6 @@
1
1
  export * from './axis';
2
2
  export * from './chart-types';
3
- export * from './date';
3
+ export * from './datetime';
4
4
  export * from './defaults';
5
5
  export * from './layout-algorithms';
6
6
  export * from './line-styles';
@@ -1,6 +1,6 @@
1
1
  export * from './axis';
2
2
  export * from './chart-types';
3
- export * from './date';
3
+ export * from './datetime';
4
4
  export * from './defaults';
5
5
  export * from './layout-algorithms';
6
6
  export * from './line-styles';
@@ -1,6 +1,6 @@
1
1
  import type React from 'react';
2
2
  import type { DashStyle } from '../../constants';
3
- import type { AxisCrosshair, AxisPlotBand, BaseTextStyle, ChartAxis, ChartAxisLabels, ChartAxisRangeSlider, ChartAxisTitleAlignment, ChartAxisType, DeepRequired, PlotLayerPlacement } from '../../types';
3
+ import type { AxisCrosshair, AxisPlotBand, BaseTextStyle, ChartAxis, ChartAxisLabels, ChartAxisRangeSlider, ChartAxisTitleAlignment, ChartAxisType, DeepRequired, MeaningfulAny, PlotLayerPlacement } from '../../types';
4
4
  type PreparedAxisLabels = Omit<ChartAxisLabels, 'enabled' | 'padding' | 'style' | 'autoRotation'> & Required<Pick<ChartAxisLabels, 'enabled' | 'padding' | 'margin' | 'rotation' | 'html'>> & {
5
5
  style: BaseTextStyle;
6
6
  rotation: number;
@@ -10,6 +10,7 @@ type PreparedAxisLabels = Omit<ChartAxisLabels, 'enabled' | 'padding' | 'style'
10
10
  maxWidth: number;
11
11
  };
12
12
  export type PreparedAxisPlotBand = Required<AxisPlotBand> & {
13
+ custom?: MeaningfulAny;
13
14
  label: {
14
15
  text: string;
15
16
  style: BaseTextStyle;
@@ -25,6 +26,7 @@ export type PreparedAxisPlotLine = {
25
26
  dashStyle: DashStyle;
26
27
  opacity: number;
27
28
  layerPlacement: PlotLayerPlacement;
29
+ custom?: MeaningfulAny;
28
30
  label: {
29
31
  text: string;
30
32
  style: BaseTextStyle;
@@ -35,6 +37,10 @@ export type PreparedAxisPlotLine = {
35
37
  export type PreparedRangeSlider = DeepRequired<Omit<ChartAxisRangeSlider, 'defaultRange'>> & {
36
38
  defaultRange?: ChartAxisRangeSlider['defaultRange'];
37
39
  };
40
+ export type PreparedAxisTickMarks = {
41
+ enabled: boolean;
42
+ length: number;
43
+ };
38
44
  type PreparedBaseAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines' | 'plotBands'> & {
39
45
  type: ChartAxisType;
40
46
  labels: PreparedAxisLabels;
@@ -58,6 +64,7 @@ type PreparedBaseAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines' | 'plotB
58
64
  ticks: {
59
65
  pixelInterval?: number;
60
66
  };
67
+ tickMarks: PreparedAxisTickMarks;
61
68
  position: 'left' | 'right' | 'top' | 'bottom';
62
69
  plotIndex: number;
63
70
  plotLines: PreparedAxisPlotLine[];
@@ -3,7 +3,7 @@ export declare function prepareAxisPlotLabel(d: AxisPlot): {
3
3
  text: string;
4
4
  style: {
5
5
  fontSize: string;
6
- fontWeight?: string;
6
+ fontWeight?: string | number;
7
7
  fontColor: string;
8
8
  };
9
9
  padding: number;
@@ -1,6 +1,6 @@
1
1
  import get from 'lodash/get';
2
- import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, SERIES_TYPE, axisCrosshairDefaults, axisLabelsDefaults, xAxisTitleDefaults, } from '../../constants';
3
- import { calculateCos, calculateNumericProperty, formatAxisTickLabel, getDefaultDateFormat, getHorizontalHtmlTextHeight, getHorizontalSvgTextHeight, getLabelsSize, getMinSpaceBetween, getTextSizeFn, isAxisRelatedSeries, wrapText, } from '../../utils';
2
+ import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, SERIES_TYPE, axisCrosshairDefaults, axisLabelsDefaults, axisTickMarksDefaults, xAxisTitleDefaults, } from '../../constants';
3
+ import { TIME_UNITS, calculateCos, calculateNumericProperty, formatAxisTickLabel, getDefaultDateFormat, getHorizontalHtmlTextHeight, getHorizontalSvgTextHeight, getLabelsSize, getMinSpaceBetween, getTextSizeFn, isAxisRelatedSeries, wrapText, } from '../../utils';
4
4
  import { getXAxisTickValues } from '../../utils/chart/axis/x-axis';
5
5
  import { createXScale } from '../useAxisScales';
6
6
  import { getPreparedRangeSlider } from './range-slider';
@@ -17,7 +17,7 @@ async function setLabelSettings({ axis, seriesData, width, axisLabels, }) {
17
17
  const labelLineHeight = (await getTextSize('Tmp')).height;
18
18
  const tickValues = getXAxisTickValues({ axis, scale, labelLineHeight, series: seriesData });
19
19
  const tickStep = getMinSpaceBetween(tickValues, (d) => Number(d.value));
20
- if (axis.type === 'datetime' && !(axisLabels === null || axisLabels === void 0 ? void 0 : axisLabels.dateFormat)) {
20
+ if (axis.type === 'datetime' && !(axisLabels === null || axisLabels === void 0 ? void 0 : axisLabels.dateFormat) && tickStep >= TIME_UNITS.day) {
21
21
  axis.labels.dateFormat = getDefaultDateFormat(tickStep);
22
22
  }
23
23
  const labels = tickValues.map((tick) => formatAxisTickLabel({
@@ -141,6 +141,10 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, boundsWidth,
141
141
  })
142
142
  : (_j = xAxis === null || xAxis === void 0 ? void 0 : xAxis.ticks) === null || _j === void 0 ? void 0 : _j.pixelInterval,
143
143
  },
144
+ tickMarks: {
145
+ enabled: get(xAxis, 'tickMarks.enabled', axisTickMarksDefaults.enabled),
146
+ length: get(xAxis, 'tickMarks.length', axisTickMarksDefaults.length),
147
+ },
144
148
  position: 'bottom',
145
149
  plotIndex: 0,
146
150
  plotLines: get(xAxis, 'plotLines', []).map((d) => ({
@@ -150,6 +154,7 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, boundsWidth,
150
154
  dashStyle: get(d, 'dashStyle', DASH_STYLE.Solid),
151
155
  opacity: get(d, 'opacity', 1),
152
156
  layerPlacement: get(d, 'layerPlacement', 'before'),
157
+ custom: d.custom,
153
158
  label: prepareAxisPlotLabel(d),
154
159
  })),
155
160
  plotBands: get(xAxis, 'plotBands', []).map((d) => ({
@@ -158,6 +163,7 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, boundsWidth,
158
163
  from: get(d, 'from', 0),
159
164
  to: get(d, 'to', 0),
160
165
  layerPlacement: get(d, 'layerPlacement', 'before'),
166
+ custom: d.custom,
161
167
  label: prepareAxisPlotLabel(d),
162
168
  })),
163
169
  crosshair: {
@@ -1,6 +1,6 @@
1
1
  import get from 'lodash/get';
2
2
  import { getTickValues } from '../../components/AxisY/utils';
3
- import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TYPE, SERIES_TYPE, axisCrosshairDefaults, axisLabelsDefaults, yAxisTitleDefaults, } from '../../constants';
3
+ import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TYPE, SERIES_TYPE, axisCrosshairDefaults, axisLabelsDefaults, axisTickMarksDefaults, yAxisTitleDefaults, } from '../../constants';
4
4
  import { calculateNumericProperty, formatAxisTickLabel, getDefaultDateFormat, getDefaultMinYAxisValue, getHorizontalHtmlTextHeight, getHorizontalSvgTextHeight, getLabelsSize, getMinSpaceBetween, getTextSizeFn, isAxisRelatedSeries, shouldSyncAxisWithPrimary, wrapText, } from '../../utils';
5
5
  import { createYScale } from '../useAxisScales';
6
6
  import { prepareAxisPlotLabel } from './utils';
@@ -160,6 +160,10 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
160
160
  })
161
161
  : (_q = axisItem.ticks) === null || _q === void 0 ? void 0 : _q.pixelInterval,
162
162
  },
163
+ tickMarks: {
164
+ enabled: get(axisItem, 'tickMarks.enabled', axisTickMarksDefaults.enabled),
165
+ length: get(axisItem, 'tickMarks.length', axisTickMarksDefaults.length),
166
+ },
163
167
  position: axisPosition,
164
168
  plotIndex: get(axisItem, 'plotIndex', 0),
165
169
  plotLines: get(axisItem, 'plotLines', []).map((d) => ({
@@ -169,6 +173,7 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
169
173
  dashStyle: get(d, 'dashStyle', DASH_STYLE.Solid),
170
174
  opacity: get(d, 'opacity', 1),
171
175
  layerPlacement: get(d, 'layerPlacement', 'before'),
176
+ custom: d.custom,
172
177
  label: prepareAxisPlotLabel(d),
173
178
  })),
174
179
  plotBands: get(axisItem, 'plotBands', []).map((d) => ({
@@ -177,6 +182,7 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
177
182
  from: get(d, 'from', 0),
178
183
  to: get(d, 'to', 0),
179
184
  layerPlacement: get(d, 'layerPlacement', 'before'),
185
+ custom: d.custom,
180
186
  label: prepareAxisPlotLabel(d),
181
187
  })),
182
188
  crosshair: {
@@ -6,4 +6,4 @@ export declare function createXScale(args: {
6
6
  series: (PreparedSeries | ChartSeries)[];
7
7
  rangeSliderState?: RangeSliderState;
8
8
  zoomStateX?: [number, number];
9
- }): import("d3-scale").ScaleBand<string> | import("d3-scale").ScaleLinear<number, number, never> | import("d3-scale").ScaleTime<number, number, never> | undefined;
9
+ }): import("d3-scale").ScaleLinear<number, number, never> | import("d3-scale").ScaleBand<string> | import("d3-scale").ScaleTime<number, number, never> | undefined;
@@ -7,4 +7,4 @@ export declare function createYScale(args: {
7
7
  primaryAxis?: PreparedAxis;
8
8
  primaryTicksCount?: number;
9
9
  zoomStateY?: [number, number];
10
- }): import("d3-scale").ScaleBand<string> | import("d3-scale").ScaleLinear<number, number, never> | import("d3-scale").ScaleTime<number, number, never> | undefined;
10
+ }): import("d3-scale").ScaleLinear<number, number, never> | import("d3-scale").ScaleBand<string> | import("d3-scale").ScaleTime<number, number, never> | undefined;
@@ -27,6 +27,7 @@ export declare function useNormalizedOriginalData(props: UseOriginalDataProps):
27
27
  maxPadding?: number;
28
28
  plotLines?: import("../..").AxisPlotLine[];
29
29
  plotBands?: import("../..").AxisPlotBand[];
30
+ tickMarks?: import("../..").ChartAxisTickMarks;
30
31
  visible?: boolean;
31
32
  order?: "sortAsc" | "sortDesc" | "reverse";
32
33
  startOnTick?: boolean;
@@ -1,5 +1,5 @@
1
1
  import type { Dispatch } from 'd3';
2
- import type { PointPosition, TooltipDataChunk } from '../../types';
2
+ import type { AxisPlotBand, AxisPlotLine, PointPosition, TooltipDataChunk } from '../../types';
3
3
  import type { PreparedTooltip } from '../useChartOptions/types';
4
4
  type Args = {
5
5
  dispatcher: Dispatch<object>;
@@ -7,6 +7,8 @@ type Args = {
7
7
  };
8
8
  export declare const useTooltip: ({ dispatcher, tooltip }: Args) => {
9
9
  hovered: TooltipDataChunk[] | undefined;
10
+ hoveredPlotLines: AxisPlotLine[] | undefined;
11
+ hoveredPlotBands: AxisPlotBand[] | undefined;
10
12
  pointerPosition: PointPosition | undefined;
11
13
  };
12
14
  export {};
@@ -1,16 +1,18 @@
1
1
  import React from 'react';
2
2
  import isEqual from 'lodash/isEqual';
3
3
  export const useTooltip = ({ dispatcher, tooltip }) => {
4
- const [{ hovered, pointerPosition }, setTooltipState] = React.useState({});
4
+ const [{ hovered, hoveredPlotLines, hoveredPlotBands, pointerPosition }, setTooltipState] = React.useState({});
5
5
  const prevHovered = React.useRef(hovered);
6
6
  React.useEffect(() => {
7
7
  if (tooltip === null || tooltip === void 0 ? void 0 : tooltip.enabled) {
8
- dispatcher.on('hover-shape.tooltip', (nextHovered, nextPointerPosition) => {
8
+ dispatcher.on('hover-shape.tooltip', (nextHovered, nextPointerPosition, nextHoveredPlots) => {
9
9
  const filteredNextHovered = nextHovered === null || nextHovered === void 0 ? void 0 : nextHovered.filter((item) => 'y' in item.data ? item.data.y !== null : true);
10
10
  const isHoveredChanged = !isEqual(prevHovered.current, filteredNextHovered);
11
11
  const newTooltipState = {
12
- pointerPosition: nextPointerPosition,
13
12
  hovered: isHoveredChanged ? filteredNextHovered : prevHovered.current,
13
+ hoveredPlotLines: nextHoveredPlots === null || nextHoveredPlots === void 0 ? void 0 : nextHoveredPlots.lines,
14
+ hoveredPlotBands: nextHoveredPlots === null || nextHoveredPlots === void 0 ? void 0 : nextHoveredPlots.bands,
15
+ pointerPosition: nextPointerPosition,
14
16
  };
15
17
  if (isHoveredChanged) {
16
18
  prevHovered.current = filteredNextHovered;
@@ -26,6 +28,8 @@ export const useTooltip = ({ dispatcher, tooltip }) => {
26
28
  }, [dispatcher, tooltip]);
27
29
  return {
28
30
  hovered,
31
+ hoveredPlotLines,
32
+ hoveredPlotBands,
29
33
  pointerPosition,
30
34
  };
31
35
  };