@@ -3,7 +3,7 @@ import { curveCatmullRom, curveLinear, curveMonotoneX } from '@visx/curve';
3
3
import { LinearGradient } from '@visx/gradient' ;
4
4
import { XYChart , AreaSeries , Tooltip , Grid , Axis , DataContext } from '@visx/xychart' ;
5
5
import clsx from 'clsx' ;
6
- import { useId , useMemo , useContext , forwardRef , useImperativeHandle } from 'react' ;
6
+ import { useId , useMemo , useContext , forwardRef , useImperativeHandle , useRef } from 'react' ;
7
7
import { useXYChartTheme , useChartTheme } from '../../providers/theme/theme-provider' ;
8
8
import { Legend } from '../legend' ;
9
9
import { DefaultGlyph } from '../shared/default-glyph' ;
@@ -12,6 +12,7 @@ import { useChartMargin } from '../shared/use-chart-margin';
12
12
import { useElementHeight } from '../shared/use-element-height' ;
13
13
import { withResponsive } from '../shared/with-responsive' ;
14
14
import LineChartAnnotation from './line-chart-annotation' ;
15
+ import LineChartAnnotations from './line-chart-annotations-overlay' ;
15
16
import styles from './line-chart.module.scss' ;
16
17
import type { LineChartAnnotationProps } from './line-chart-annotation' ;
17
18
import type { BaseChartProps , DataPoint , DataPointDate , SeriesData } from '../../types' ;
@@ -185,10 +186,12 @@ const validateData = ( data: SeriesData[] ) => {
185
186
} ;
186
187
187
188
// Inner component to access DataContext and provide scale data to ref
188
- const LineChartInternal : FC < LineChartProps & { chartRef ?: React . Ref < LineChartRef > } > = ( {
189
- chartRef,
190
- ...props
191
- } ) => {
189
+ const LineChartInternal : FC < {
190
+ chartRef ?: React . Ref < LineChartRef > ;
191
+ width : number ;
192
+ height : number ;
193
+ margin ?: { top ?: number ; right ?: number ; bottom ?: number ; left ?: number } ;
194
+ } > = ( { chartRef, width, height, margin } ) => {
192
195
const context = useContext ( DataContext ) ;
193
196
194
197
useImperativeHandle (
@@ -204,12 +207,12 @@ const LineChartInternal: FC< LineChartProps & { chartRef?: React.Ref< LineChartR
204
207
} ;
205
208
} ,
206
209
getChartDimensions : ( ) => ( {
207
- width : props . width ,
208
- height : props . height ,
209
- margin : props . margin || { } ,
210
+ width,
211
+ height,
212
+ margin : margin || { } ,
210
213
} ) ,
211
214
} ) ,
212
- [ context , props . width , props . height , props . margin ]
215
+ [ context , width , height , margin ]
213
216
) ;
214
217
215
218
return null ; // This component only provides the ref interface
@@ -251,6 +254,18 @@ const LineChart = forwardRef< LineChartRef, LineChartProps >(
251
254
const theme = useXYChartTheme ( data ) ;
252
255
const chartId = useId ( ) ; // Ensure unique ids for gradient fill.
253
256
const [ legendRef , legendHeight ] = useElementHeight < HTMLDivElement > ( ) ;
257
+ const internalChartRef = useRef < LineChartRef > ( null ) ;
258
+
259
+ // Forward the external ref to the internal ref
260
+ useImperativeHandle (
261
+ ref ,
262
+ ( ) => ( {
263
+ getScales : ( ) => internalChartRef . current ?. getScales ( ) || null ,
264
+ getChartDimensions : ( ) =>
265
+ internalChartRef . current ?. getChartDimensions ( ) || { width : 0 , height : 0 , margin : { } } ,
266
+ } ) ,
267
+ [ internalChartRef ]
268
+ ) ;
254
269
255
270
const dataSorted = useChartDataTransform ( data ) ;
256
271
@@ -418,54 +433,45 @@ const LineChart = forwardRef< LineChartRef, LineChartProps >(
418
433
showHorizontalCrosshair = { withTooltipCrosshairs ?. showHorizontal }
419
434
/>
420
435
) }
421
- { /* Component to expose scale data via ref */ }
422
- < LineChartInternal
423
- chartRef = { ref }
424
- data = { data }
425
- width = { width }
426
- height = { height }
427
- className = { className }
428
- margin = { margin }
429
- withTooltips = { withTooltips }
430
- withTooltipCrosshairs = { withTooltipCrosshairs }
431
- showLegend = { showLegend }
432
- legendOrientation = { legendOrientation }
433
- legendAlignmentHorizontal = { legendAlignmentHorizontal }
434
- legendAlignmentVertical = { legendAlignmentVertical }
435
- renderGlyph = { renderGlyph }
436
- glyphStyle = { glyphStyle }
437
- legendShape = { legendShape }
438
- withLegendGlyph = { withLegendGlyph }
439
- withGradientFill = { withGradientFill }
440
- smoothing = { smoothing }
441
- curveType = { curveType }
442
- renderTooltip = { renderTooltip }
443
- withStartGlyphs = { withStartGlyphs }
444
- options = { options }
445
- annotations = { annotations }
446
- onPointerDown = { onPointerDown }
447
- onPointerUp = { onPointerUp }
448
- onPointerMove = { onPointerMove }
449
- onPointerOut = { onPointerOut }
450
- />
451
436
452
- { /* Render annotations last so they appear on top of all chart elements */ }
453
437
{ annotations ?. length && (
454
438
< g className = "line-chart__annotations" >
455
- { annotations . map ( ( { datum, ...rest } , index ) =>
439
+ { annotations . map ( ( { datum, styles : datumStyles , ...rest } , index ) =>
456
440
datum ? (
457
441
< LineChartAnnotation
458
442
key = { `annotation-${ datum . date ?. getTime ( ) } -${ datum . value } ` }
459
443
testId = { `annotation-${ index } ` }
460
444
datum = { datum }
445
+ styles = { {
446
+ ...datumStyles ,
447
+ label : { ...datumStyles ?. label , backgroundFill : 'gray' } ,
448
+ } }
461
449
{ ...rest }
462
450
/>
463
451
) : null
464
452
) }
465
453
</ g >
466
454
) }
455
+
456
+ { /* Component to expose scale data via ref */ }
457
+ < LineChartInternal
458
+ chartRef = { internalChartRef }
459
+ width = { width }
460
+ height = { height }
461
+ margin = { margin }
462
+ />
467
463
</ XYChart >
468
464
465
+ { /* Render annotations as external overlay to avoid interaction blocking */ }
466
+ { annotations ?. length && (
467
+ < LineChartAnnotations
468
+ chartRef = { internalChartRef }
469
+ annotations = { annotations }
470
+ chartWidth = { width }
471
+ chartHeight = { height - ( showLegend ? legendHeight : 0 ) }
472
+ />
473
+ ) }
474
+
469
475
{ showLegend && (
470
476
< Legend
471
477
items = { legendItems }
0 commit comments