@centreon/ui 25.2.2 → 25.2.4

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centreon/ui",
3
- "version": "25.2.2",
3
+ "version": "25.2.4",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "update:deps": "pnpx npm-check-updates -i --format group",
@@ -61,14 +61,14 @@ const checkWidth = (orientation): void => {
61
61
  cy.get('g[class*="visx-rows"] > line')
62
62
  .eq(0)
63
63
  .should('have.attr', 'x2')
64
- .and('equal', '1135');
64
+ .and('equal', '1145');
65
65
 
66
66
  return;
67
67
  }
68
68
  cy.get('g[class*="visx-rows"] > line')
69
69
  .eq(0)
70
70
  .should('have.attr', 'x2')
71
- .and('equal', '1170');
71
+ .and('equal', '1180');
72
72
  };
73
73
 
74
74
  describe('Bar chart', () => {
@@ -1,10 +1,8 @@
1
- import { memo, useMemo } from 'react';
2
-
3
- import { Group } from '@visx/group';
4
1
  import { scaleBand, scaleOrdinal } from '@visx/scale';
5
2
  import { BarGroupHorizontal, BarGroup as VisxBarGroup } from '@visx/shape';
6
3
  import { ScaleLinear } from 'd3-scale';
7
4
  import { difference, equals, keys, omit, pick, pluck, uniq } from 'ramda';
5
+ import { memo, useMemo } from 'react';
8
6
 
9
7
  import { useDeepMemo } from '../../utils';
10
8
  import {
@@ -14,8 +12,7 @@ import {
14
12
  getUnits
15
13
  } from '../common/timeSeries';
16
14
  import { Line, TimeValue } from '../common/timeSeries/models';
17
-
18
- import BarStack from './BarStack';
15
+ import MemoizedGroup from './MemoizedGroup';
19
16
  import { BarStyle } from './models';
20
17
 
21
18
  // Minimum value for logarithmic scale to avoid log(0)
@@ -161,60 +158,23 @@ const BarGroup = ({
161
158
  {...barComponentBaseProps}
162
159
  >
163
160
  {(barGroups) =>
164
- barGroups.map((barGroup) => (
165
- <Group
166
- key={`bar-group-${barGroup.index}-${barGroup.x0}`}
167
- left={barGroup.x0}
168
- top={barGroup.y0}
169
- >
170
- {barGroup.bars.map((bar) => {
171
- const isStackedBar = bar.key.startsWith('stacked-');
172
- const linesBar = isStackedBar
173
- ? stackedLinesTimeSeriesPerUnit[bar.key.replace('stacked-', '')]
174
- .lines
175
- : (notStackedLines.find(({ metric_id }) =>
176
- equals(metric_id, Number(bar.key))
177
- ) as Line);
178
- const timeSeriesBar = isStackedBar
179
- ? stackedLinesTimeSeriesPerUnit[bar.key.replace('stacked-', '')]
180
- .timeSeries
181
- : notStackedTimeSeries.map((timeSerie) => ({
182
- timeTick: timeSerie.timeTick,
183
- [bar.key]: timeSerie[Number(bar.key)]
184
- }));
185
-
186
- return isStackedBar ? (
187
- <BarStack
188
- key={`bar-${barGroup.index}-${bar.width}-${bar.y}-${bar.height}-${bar.x}`}
189
- barIndex={barGroup.index}
190
- barPadding={isHorizontal ? bar.x : bar.y}
191
- barStyle={barStyle}
192
- barWidth={isHorizontal ? bar.width : bar.height}
193
- isHorizontal={isHorizontal}
194
- isTooltipHidden={isTooltipHidden}
195
- lines={linesBar}
196
- timeSeries={timeSeriesBar}
197
- yScale={yScalesPerUnit[bar.key.replace('stacked-', '')]}
198
- neutralValue={neutralValue}
199
- />
200
- ) : (
201
- <BarStack
202
- key={`bar-${barGroup.index}-${bar.width}-${bar.y}-${bar.height}-${bar.x}`}
203
- barIndex={barGroup.index}
204
- barPadding={isHorizontal ? bar.x : bar.y}
205
- barStyle={barStyle}
206
- barWidth={isHorizontal ? bar.width : bar.height}
207
- isHorizontal={isHorizontal}
208
- isTooltipHidden={isTooltipHidden}
209
- lines={[linesBar]}
210
- timeSeries={timeSeriesBar}
211
- yScale={yScalesPerUnit[linesBar.unit]}
212
- neutralValue={neutralValue}
213
- />
214
- );
215
- })}
216
- </Group>
217
- ))
161
+ barGroups.map((barGroup, index) => {
162
+ return (
163
+ <MemoizedGroup
164
+ key={`bar-group-${barGroup.index}-${barGroup.x0}`}
165
+ barGroup={barGroup}
166
+ barStyle={barStyle}
167
+ stackedLinesTimeSeriesPerUnit={stackedLinesTimeSeriesPerUnit}
168
+ notStackedTimeSeries={notStackedTimeSeries}
169
+ notStackedLines={notStackedLines}
170
+ isTooltipHidden={isTooltipHidden}
171
+ isHorizontal={isHorizontal}
172
+ neutralValue={neutralValue}
173
+ yScalesPerUnit={yScalesPerUnit}
174
+ barIndex={index}
175
+ />
176
+ );
177
+ })
218
178
  }
219
179
  </BarComponent>
220
180
  );
@@ -0,0 +1,123 @@
1
+ import { Group } from '@visx/group';
2
+ import { BarGroup } from '@visx/shape/lib/types';
3
+ import { ScaleLinear } from 'd3-scale';
4
+ import { equals, omit } from 'ramda';
5
+ import { memo } from 'react';
6
+ import { Line, TimeValue } from '../common/timeSeries/models';
7
+ import BarStack from './BarStack';
8
+ import { BarStyle } from './models';
9
+
10
+ interface Props {
11
+ neutralValue: number;
12
+ isTooltipHidden: boolean;
13
+ barStyle: BarStyle;
14
+ yScalesPerUnit: Record<string, ScaleLinear<number, number>>;
15
+ stackedLinesTimeSeriesPerUnit: Record<
16
+ string,
17
+ { lines: Array<Line>; timeSeries: Array<TimeValue> }
18
+ >;
19
+ notStackedLines: Array<Line>;
20
+ notStackedTimeSeries: Array<TimeValue>;
21
+ isHorizontal: boolean;
22
+ barGroup: BarGroup<'id'>;
23
+ barIndex: number;
24
+ }
25
+
26
+ const MemoizedGroup = ({
27
+ barGroup,
28
+ stackedLinesTimeSeriesPerUnit,
29
+ notStackedLines,
30
+ notStackedTimeSeries,
31
+ isHorizontal,
32
+ barStyle,
33
+ isTooltipHidden,
34
+ neutralValue,
35
+ yScalesPerUnit,
36
+ barIndex
37
+ }: Props): JSX.Element | null => {
38
+ const hasEmptyValues = barGroup.bars.every(({ key, value }) => {
39
+ if (key.startsWith('stacked-')) {
40
+ const timeValueBar =
41
+ stackedLinesTimeSeriesPerUnit[key.replace('stacked-', '')].timeSeries[
42
+ barIndex
43
+ ];
44
+
45
+ return Object.values(omit(['timeTick'], timeValueBar)).every(
46
+ (value) => !value
47
+ );
48
+ }
49
+
50
+ return !value;
51
+ });
52
+
53
+ if (hasEmptyValues) {
54
+ return null;
55
+ }
56
+
57
+ return (
58
+ <Group left={barGroup.x0} top={barGroup.y0}>
59
+ {barGroup.bars.map((bar) => {
60
+ const isStackedBar = bar.key.startsWith('stacked-');
61
+ const linesBar = isStackedBar
62
+ ? stackedLinesTimeSeriesPerUnit[bar.key.replace('stacked-', '')].lines
63
+ : (notStackedLines.find(({ metric_id }) =>
64
+ equals(metric_id, Number(bar.key))
65
+ ) as Line);
66
+ const timeSeriesBar = isStackedBar
67
+ ? stackedLinesTimeSeriesPerUnit[bar.key.replace('stacked-', '')]
68
+ .timeSeries
69
+ : notStackedTimeSeries.map((timeSerie) => ({
70
+ timeTick: timeSerie.timeTick,
71
+ [bar.key]: timeSerie[Number(bar.key)]
72
+ }));
73
+
74
+ return isStackedBar ? (
75
+ <BarStack
76
+ key={`bar-${barGroup.index}-${bar.width}-${bar.y}-${bar.height}-${bar.x}`}
77
+ barIndex={barGroup.index}
78
+ barPadding={isHorizontal ? bar.x : bar.y}
79
+ barStyle={barStyle}
80
+ barWidth={isHorizontal ? bar.width : bar.height}
81
+ isHorizontal={isHorizontal}
82
+ isTooltipHidden={isTooltipHidden}
83
+ lines={linesBar as Array<Line>}
84
+ timeSeries={timeSeriesBar}
85
+ yScale={yScalesPerUnit[bar.key.replace('stacked-', '')]}
86
+ neutralValue={neutralValue}
87
+ />
88
+ ) : (
89
+ <BarStack
90
+ key={`bar-${barGroup.index}-${bar.width}-${bar.y}-${bar.height}-${bar.x}`}
91
+ barIndex={barGroup.index}
92
+ barPadding={isHorizontal ? bar.x : bar.y}
93
+ barStyle={barStyle}
94
+ barWidth={isHorizontal ? bar.width : bar.height}
95
+ isHorizontal={isHorizontal}
96
+ isTooltipHidden={isTooltipHidden}
97
+ lines={[linesBar as Line]}
98
+ timeSeries={timeSeriesBar}
99
+ yScale={yScalesPerUnit[(linesBar as Line).unit]}
100
+ neutralValue={neutralValue}
101
+ />
102
+ );
103
+ })}
104
+ </Group>
105
+ );
106
+ };
107
+
108
+ export default memo(
109
+ MemoizedGroup,
110
+ (prevProps, nextProps) =>
111
+ equals(prevProps.barGroup, nextProps.barGroup) &&
112
+ equals(
113
+ prevProps.stackedLinesTimeSeriesPerUnit,
114
+ nextProps.stackedLinesTimeSeriesPerUnit
115
+ ) &&
116
+ equals(prevProps.notStackedLines, nextProps.notStackedLines) &&
117
+ equals(prevProps.notStackedTimeSeries, nextProps.notStackedTimeSeries) &&
118
+ equals(prevProps.isHorizontal, nextProps.isHorizontal) &&
119
+ equals(prevProps.barStyle, nextProps.barStyle) &&
120
+ equals(prevProps.isTooltipHidden, nextProps.isTooltipHidden) &&
121
+ equals(prevProps.neutralValue, nextProps.neutralValue) &&
122
+ equals(prevProps.barIndex, nextProps.barIndex)
123
+ );
@@ -13,6 +13,7 @@ import { useIntersection } from '../Chart/useChartIntersection';
13
13
  import BaseChart from '../common/BaseChart/BaseChart';
14
14
  import ChartSvgWrapper from '../common/BaseChart/ChartSvgWrapper';
15
15
  import { useComputeBaseChartDimensions } from '../common/BaseChart/useComputeBaseChartDimensions';
16
+ import { useComputeYAxisMaxCharacters } from '../common/BaseChart/useComputeYAxisMaxCharacters';
16
17
  import Thresholds from '../common/Thresholds/Thresholds';
17
18
  import { Thresholds as ThresholdsModel } from '../common/models';
18
19
  import {
@@ -22,7 +23,6 @@ import {
22
23
  } from '../common/timeSeries';
23
24
  import { Line } from '../common/timeSeries/models';
24
25
  import { useTooltipStyles } from '../common/useTooltipStyles';
25
-
26
26
  import BarGroup from './BarGroup';
27
27
  import BarChartTooltip from './Tooltip/BarChartTooltip';
28
28
  import { tooltipDataAtom } from './atoms';
@@ -58,7 +58,7 @@ const ResponsiveBarChart = ({
58
58
  barStyle,
59
59
  skipIntersectionObserver
60
60
  }: Props): JSX.Element => {
61
- const { title, timeSeries, baseAxis, lines } = graphData;
61
+ const { title, timeSeries, baseAxis, lines } = graphData || {};
62
62
 
63
63
  const { classes, cx } = useTooltipStyles();
64
64
 
@@ -70,19 +70,30 @@ const ResponsiveBarChart = ({
70
70
  const { isInViewport } = useIntersection({ element: graphRef?.current });
71
71
 
72
72
  const displayedLines = useMemo(
73
- () => linesGraph.filter(({ display }) => display),
73
+ () => (linesGraph || []).filter(({ display }) => display),
74
74
  [linesGraph]
75
75
  );
76
76
 
77
77
  const [firstUnit, secondUnit] = getUnits(displayedLines);
78
78
  const allUnits = getUnits(lines);
79
79
 
80
+ const { maxLeftAxisCharacters, maxRightAxisCharacters } =
81
+ useComputeYAxisMaxCharacters({
82
+ graphData,
83
+ thresholds,
84
+ thresholdUnit,
85
+ axis,
86
+ firstUnit,
87
+ secondUnit
88
+ });
89
+
80
90
  const { legendRef, graphWidth, graphHeight } = useComputeBaseChartDimensions({
81
91
  hasSecondUnit: Boolean(secondUnit),
82
92
  height,
83
93
  legendDisplay: legend?.display,
84
94
  legendPlacement: legend?.placement,
85
- width
95
+ width,
96
+ maxAxisCharacters: maxRightAxisCharacters || maxLeftAxisCharacters
86
97
  });
87
98
 
88
99
  const thresholdValues = flatten([
@@ -216,6 +227,8 @@ const ResponsiveBarChart = ({
216
227
  svgRef={graphSvgRef}
217
228
  timeSeries={timeSeries}
218
229
  xScale={xScale}
230
+ maxAxisCharacters={maxLeftAxisCharacters}
231
+ hasSecondUnit={Boolean(secondUnit)}
219
232
  >
220
233
  <>
221
234
  <BarGroup
@@ -129,13 +129,13 @@ const initializeCustomUnits = ({
129
129
  };
130
130
 
131
131
  const checkGraphWidth = (): void => {
132
- cy.findByTestId('graph-interaction-zone')
133
- .should('have.attr', 'width')
134
- .and('equal', '1170');
135
-
136
132
  cy.findByTestId('graph-interaction-zone')
137
133
  .should('have.attr', 'height')
138
134
  .and('equal', '393');
135
+
136
+ cy.findByTestId('graph-interaction-zone').then((graph) => {
137
+ expect(Number(graph[0].attributes.width.value)).to.be.greaterThan(1170);
138
+ });
139
139
  };
140
140
 
141
141
  describe('Line chart', () => {
@@ -158,8 +158,7 @@ describe('Line chart', () => {
158
158
  cy.contains('06/18/2023').should('be.visible');
159
159
 
160
160
  cy.contains('0.45 s').should('be.visible');
161
- cy.contains('75.93%').should('be.visible');
162
- cy.contains('0.43 s').should('be.visible');
161
+ cy.contains('73.65%').should('be.visible');
163
162
 
164
163
  cy.makeSnapshot();
165
164
  });
@@ -181,7 +180,7 @@ describe('Line chart', () => {
181
180
  cy.get('[data-metric="connTime"]').should(
182
181
  'have.attr',
183
182
  'data-highlight',
184
- 'true'
183
+ 'false'
185
184
  );
186
185
 
187
186
  cy.makeSnapshot();
@@ -194,7 +193,7 @@ describe('Line chart', () => {
194
193
 
195
194
  cy.contains('Min: 70.31').should('be.visible');
196
195
 
197
- cy.findByTestId('graph-interaction-zone').realMouseMove(1185, 100);
196
+ cy.findByTestId('graph-interaction-zone').realMouseMove(1198, 100);
198
197
 
199
198
  cy.get('[data-metric="querytime"]').should('not.exist');
200
199
 
@@ -208,10 +207,10 @@ describe('Line chart', () => {
208
207
 
209
208
  cy.contains('Min: 70.31').should('be.visible');
210
209
 
211
- cy.findByTestId('graph-interaction-zone').realMouseMove(1152, 100);
210
+ cy.findByTestId('graph-interaction-zone').realMouseMove(1170, 100);
212
211
 
213
212
  cy.get('[data-metric="querytime"]').should('be.visible');
214
- cy.get('[data-metric="hitratio"]').should('not.exist');
213
+ cy.get('[data-metric="hitratio"]').should('be.visible');
215
214
 
216
215
  cy.makeSnapshot();
217
216
  });
@@ -225,12 +224,12 @@ describe('Line chart', () => {
225
224
 
226
225
  cy.findByTestId('graph-interaction-zone').realMouseMove(452, 26);
227
226
 
228
- cy.get('[data-metric="connTime"]').should(
227
+ cy.get('[data-metric="hitratio"]').should(
229
228
  'have.attr',
230
229
  'data-highlight',
231
230
  'true'
232
231
  );
233
- cy.get('[data-metric="hitratio"]').should('not.exist');
232
+ cy.get('[data-metric="querytime"]').should('not.exist');
234
233
 
235
234
  cy.makeSnapshot();
236
235
  });
@@ -286,7 +285,7 @@ describe('Line chart', () => {
286
285
 
287
286
  cy.findByTestId('graph-interaction-zone')
288
287
  .should('have.attr', 'width')
289
- .and('equal', '1212');
288
+ .and('equal', '1200');
290
289
 
291
290
  cy.findByLabelText('Centreon-Server: Round-Trip Average Time')
292
291
  .find('[data-icon="true"]')
@@ -362,8 +361,6 @@ describe('Line chart', () => {
362
361
  cy.get('[data-as-list="true"]').should('exist');
363
362
 
364
363
  cy.contains(':00 AM').should('be.visible');
365
-
366
- cy.makeSnapshot();
367
364
  });
368
365
 
369
366
  it('displays the legend on the right side of the graph as list when the corresponding props are set', () => {
@@ -373,8 +370,6 @@ describe('Line chart', () => {
373
370
  cy.get('[data-as-list="true"]').should('exist');
374
371
 
375
372
  cy.contains(':00 AM').should('be.visible');
376
-
377
- cy.makeSnapshot();
378
373
  });
379
374
  });
380
375
 
@@ -530,8 +525,7 @@ describe('Line chart', () => {
530
525
 
531
526
  checkGraphWidth();
532
527
  cy.contains(':00 AM').should('be.visible');
533
- cy.get('circle[cx="4.0625"]').should('be.visible');
534
- cy.get('circle[cy="105.21757370835121"]').should('be.visible');
528
+ cy.get('circle[cx="37.625"]').should('be.visible');
535
529
 
536
530
  cy.makeSnapshot();
537
531
  });
@@ -583,7 +577,6 @@ describe('Lines and bars', () => {
583
577
  cy.get('path[data-metric="3"]').should('be.visible');
584
578
  cy.get('path[data-metric="3"]').should('be.visible');
585
579
  cy.findByTestId('stacked-bar-10-0-7650.368581547736').should('be.visible');
586
- cy.findByTestId('stacked-bar-2-0-10').should('be.visible');
587
580
 
588
581
  cy.makeSnapshot();
589
582
  });
@@ -634,7 +627,6 @@ describe('Lines and bars', () => {
634
627
  cy.get('path[data-metric="3"]').should('be.visible');
635
628
  cy.get('path[data-metric="3"]').should('be.visible');
636
629
  cy.findByTestId('stacked-bar-10-0-7650.368581547736').should('be.visible');
637
- cy.findByTestId('stacked-bar-2-0-10').should('be.visible');
638
630
 
639
631
  cy.makeSnapshot();
640
632
  });
@@ -669,7 +669,7 @@ export const linesAndBarsMixedCenteredZero: Story = {
669
669
  )
670
670
  };
671
671
  const CustomYUnits = (props): JSX.Element => {
672
- const [leftUnit, setLeftUnit] = useState('b');
672
+ const [leftUnit, setLeftUnit] = useState('B');
673
673
  const [rightUnit, setRightUnit] = useState('ms');
674
674
 
675
675
  return (
@@ -16,6 +16,7 @@ import BarGroup from '../BarChart/BarGroup';
16
16
  import BaseChart from '../common/BaseChart/BaseChart';
17
17
  import ChartSvgWrapper from '../common/BaseChart/ChartSvgWrapper';
18
18
  import { useComputeBaseChartDimensions } from '../common/BaseChart/useComputeBaseChartDimensions';
19
+ import { useComputeYAxisMaxCharacters } from '../common/BaseChart/useComputeYAxisMaxCharacters';
19
20
  import Thresholds from '../common/Thresholds/Thresholds';
20
21
  import type { Thresholds as ThresholdsModel } from '../common/models';
21
22
  import {
@@ -25,7 +26,6 @@ import {
25
26
  getYScalePerUnit
26
27
  } from '../common/timeSeries';
27
28
  import type { Line } from '../common/timeSeries/models';
28
-
29
29
  import Lines from './BasicComponents/Lines';
30
30
  import {
31
31
  canDisplayThreshold,
@@ -140,13 +140,24 @@ const Chart = ({
140
140
  [displayedLines]
141
141
  );
142
142
 
143
+ const { maxLeftAxisCharacters, maxRightAxisCharacters } =
144
+ useComputeYAxisMaxCharacters({
145
+ graphData,
146
+ thresholds,
147
+ thresholdUnit,
148
+ axis,
149
+ firstUnit,
150
+ secondUnit
151
+ });
152
+
143
153
  const { legendRef, graphWidth, graphHeight } = useComputeBaseChartDimensions({
144
154
  hasSecondUnit: Boolean(secondUnit),
145
155
  height,
146
156
  legendDisplay: legend?.display,
147
157
  legendHeight: legend?.height,
148
158
  legendPlacement: legend?.placement,
149
- width
159
+ width,
160
+ maxAxisCharacters: maxRightAxisCharacters || maxLeftAxisCharacters
150
161
  });
151
162
 
152
163
  const xScale = useMemo(
@@ -283,39 +294,45 @@ const Chart = ({
283
294
  svgRef={graphSvgRef}
284
295
  timeSeries={timeSeries}
285
296
  xScale={xScale}
297
+ maxAxisCharacters={maxLeftAxisCharacters}
298
+ hasSecondUnit={Boolean(secondUnit)}
286
299
  >
287
300
  <>
288
- <BarGroup
289
- barStyle={barStyle}
290
- isTooltipHidden={false}
291
- lines={linesDisplayedAsBar}
292
- orientation="horizontal"
293
- size={graphHeight - margin.top - 5}
294
- timeSeries={timeSeries}
295
- xScale={xScaleBand}
296
- yScalesPerUnit={yScalesPerUnit}
297
- />
298
- <Lines
299
- areaTransparency={lineStyle?.areaTransparency}
300
- curve={lineStyle?.curve || 'linear'}
301
- dashLength={lineStyle?.dashLength}
302
- dashOffset={lineStyle?.dashOffset}
303
- displayAnchor={displayAnchor}
304
- displayedLines={linesDisplayedAsLine}
305
- dotOffset={lineStyle?.dotOffset}
306
- graphSvgRef={graphSvgRef}
307
- height={graphHeight - margin.top}
308
- lineWidth={lineStyle?.lineWidth}
309
- scale={axis?.scale}
310
- scaleLogarithmicBase={axis?.scaleLogarithmicBase}
311
- showArea={lineStyle?.showArea}
312
- showPoints={lineStyle?.showPoints}
313
- timeSeries={timeSeries}
314
- width={graphWidth}
315
- xScale={xScale}
316
- yScalesPerUnit={yScalesPerUnit}
317
- {...shapeLines}
318
- />
301
+ {!isEmpty(linesDisplayedAsBar) && (
302
+ <BarGroup
303
+ barStyle={barStyle}
304
+ isTooltipHidden={false}
305
+ lines={linesDisplayedAsBar}
306
+ orientation="horizontal"
307
+ size={graphHeight - margin.top - 5}
308
+ timeSeries={timeSeries}
309
+ xScale={xScaleBand}
310
+ yScalesPerUnit={yScalesPerUnit}
311
+ />
312
+ )}
313
+ {!isEmpty(linesDisplayedAsLine) && (
314
+ <Lines
315
+ areaTransparency={lineStyle?.areaTransparency}
316
+ curve={lineStyle?.curve || 'linear'}
317
+ dashLength={lineStyle?.dashLength}
318
+ dashOffset={lineStyle?.dashOffset}
319
+ displayAnchor={displayAnchor}
320
+ displayedLines={linesDisplayedAsLine}
321
+ dotOffset={lineStyle?.dotOffset}
322
+ graphSvgRef={graphSvgRef}
323
+ height={graphHeight - margin.top}
324
+ lineWidth={lineStyle?.lineWidth}
325
+ scale={axis?.scale}
326
+ scaleLogarithmicBase={axis?.scaleLogarithmicBase}
327
+ showArea={lineStyle?.showArea}
328
+ showPoints={lineStyle?.showPoints}
329
+ timeSeries={timeSeries}
330
+ width={graphWidth}
331
+ xScale={xScale}
332
+ yScalesPerUnit={yScalesPerUnit}
333
+ {...shapeLines}
334
+ />
335
+ )}
319
336
  <InteractionWithGraph
320
337
  annotationData={{ ...annotationEvent }}
321
338
  commonData={{
@@ -11,7 +11,7 @@ const GuidingLines = ({
11
11
  graphHeight,
12
12
  graphWidth
13
13
  }: GuidingLinesModel): JSX.Element | null => {
14
- const { positionX, positionY } = useTickGraph({
14
+ const { positionX, positionY, guidingLinesRef } = useTickGraph({
15
15
  timeSeries,
16
16
  xScale
17
17
  });
@@ -20,7 +20,7 @@ const GuidingLines = ({
20
20
  }
21
21
 
22
22
  return (
23
- <>
23
+ <g ref={guidingLinesRef}>
24
24
  <Shape.Line
25
25
  fill="dotted"
26
26
  from={{ x: positionX, y: 0 }}
@@ -38,7 +38,7 @@ const GuidingLines = ({
38
38
  strokeWidth={1}
39
39
  to={{ x: graphWidth, y: positionY }}
40
40
  />
41
- </>
41
+ </g>
42
42
  );
43
43
  };
44
44
 
@@ -1,4 +1,4 @@
1
- import { useEffect, useState } from 'react';
1
+ import { MutableRefObject, useEffect, useMemo, useRef, useState } from 'react';
2
2
 
3
3
  import { ScaleLinear } from 'd3-scale';
4
4
  import { useAtomValue } from 'jotai';
@@ -15,6 +15,7 @@ interface AnchorPointResult {
15
15
  tickAxisBottom: Date | null;
16
16
  tickAxisLeft: string | null;
17
17
  tickAxisRight: string | null;
18
+ guidingLinesRef: MutableRefObject<SVGGElement | null>;
18
19
  }
19
20
 
20
21
  interface Props {
@@ -34,6 +35,7 @@ const useTickGraph = ({
34
35
  lines = [],
35
36
  baseAxis = 1000
36
37
  }: Props): AnchorPointResult => {
38
+ const guidingLinesRef = useRef<SVGGElement | null>(null);
37
39
  const [tickAxisBottom, setTickAxisBottom] = useState<Date | null>(null);
38
40
  const [tickAxisLeft, setTickAxisLeft] = useState<string | null>(null);
39
41
  const [tickAxisRight, setTickAxisRight] = useState<string | null>(null);
@@ -42,12 +44,22 @@ const useTickGraph = ({
42
44
 
43
45
  const mousePosition = useAtomValue(mousePositionAtom);
44
46
 
47
+ const paddingLeftString = useMemo(
48
+ () =>
49
+ (
50
+ guidingLinesRef.current?.parentElement?.parentElement?.attributes
51
+ ?.transform.value || ''
52
+ ).match(/translate\(([0-9\.]+), ([0-9\.]+)\)/)?.[1] || '0',
53
+ [
54
+ guidingLinesRef.current?.parentElement?.parentElement?.attributes
55
+ ?.transform.value
56
+ ]
57
+ );
58
+
45
59
  const positionX = mousePosition
46
- ? mousePosition[0] - margin.left - 4
47
- : undefined;
48
- const positionY = mousePosition
49
- ? mousePosition[1] - margin.top + 2
60
+ ? mousePosition[0] - Number(paddingLeftString) - 1
50
61
  : undefined;
62
+ const positionY = mousePosition ? mousePosition[1] - margin.top : undefined;
51
63
 
52
64
  useEffect(() => {
53
65
  if (!mousePosition) {
@@ -86,7 +98,8 @@ const useTickGraph = ({
86
98
  positionY,
87
99
  tickAxisBottom,
88
100
  tickAxisLeft,
89
- tickAxisRight
101
+ tickAxisRight,
102
+ guidingLinesRef
90
103
  };
91
104
  };
92
105
  export default useTickGraph;
@@ -97,7 +97,7 @@ const Axes = ({
97
97
  tickLabelProps={() => ({
98
98
  ...axisLeft.tickLabelProps(),
99
99
  angle: yAxisTickLabelRotation,
100
- dx: isHorizontal ? -8 : 4,
100
+ dx: isHorizontal ? -4 : 4,
101
101
  dy: isHorizontal ? 4 : -6
102
102
  })}
103
103
  tickLength={2}