1
1
import { scaleTime } from 'd3-scale' ;
2
2
import { area , curveStepAfter } from 'd3-shape' ;
3
+ import { useDarkMode } from 'hooks/theme' ;
3
4
import PulseLoader from 'react-spinners/PulseLoader' ;
4
5
import useResizeObserver from 'use-resize-observer/polyfilled' ;
5
6
6
- function EstimationMarkers ( { datetimes, scaleWidth, className, transform, estimated } ) {
7
+ const DARK_MODE_PATTERN_STROKE = '#404040' ;
8
+ const LIGHT_MODE_PATTERN_STROKE = 'darkgray' ;
9
+ const MARKER_COLOR = '#DB58FF' ;
10
+
11
+ export function EstimationLegendIcon ( ) {
12
+ return (
13
+ < svg xmlns = "http://www.w3.org/2000/svg" width = "12" height = "12" >
14
+ < rect width = "24" height = "24" fill = "url(#pattern)" transform = "scale(0.5)" />
15
+ < line x1 = "0" y1 = "11" x2 = "12" y2 = "11" stroke = "#DB58FF" strokeWidth = "2" />
16
+ </ svg >
17
+ ) ;
18
+ }
19
+
20
+ function EstimationMarkers ( {
21
+ datetimes,
22
+ scaleWidth,
23
+ scaleHeight,
24
+ className,
25
+ transform,
26
+ estimated,
27
+ markerHeight = 3 ,
28
+ } : {
29
+ datetimes : any [ ] | undefined ;
30
+ scaleWidth : number ;
31
+ scaleHeight : number ;
32
+ className ?: string ;
33
+ transform ?: string ;
34
+ estimated ?: boolean [ ] ;
35
+ markerHeight ?: number ;
36
+ } ) {
7
37
const { ref } = useResizeObserver < SVGSVGElement > ( ) ;
38
+ const isDarkMode = useDarkMode ( ) ;
8
39
9
40
if ( datetimes === undefined || estimated == null ) {
10
41
return (
@@ -16,25 +47,58 @@ function EstimationMarkers({ datetimes, scaleWidth, className, transform, estima
16
47
17
48
const startDate = datetimes [ 0 ] ;
18
49
const endDate = datetimes . at ( - 1 ) ;
50
+ if ( ! startDate || ! endDate ) {
51
+ return null ; // No valid dates to render
52
+ }
19
53
const timeScale = scaleTime ( ) . domain ( [ startDate , endDate ] ) . range ( [ 0 , scaleWidth ] ) ;
20
54
21
- const layerArea = area ( )
55
+ const markerPathData = area ( )
22
56
// see https://github.com/d3/d3-shape#curveStep
23
57
. curve ( curveStepAfter )
24
- . x ( timeScale )
58
+ . x ( ( d : any ) => timeScale ( d ) )
59
+ . y0 ( 0 )
60
+ . y1 ( markerHeight )
61
+ . defined ( ( d , index ) => Boolean ( estimated ?. at ( index ) ) ) ;
62
+ const backgroundPathData = area ( )
63
+ . curve ( curveStepAfter )
64
+ . x ( ( d : any ) => timeScale ( d ) )
25
65
. y0 ( 0 )
26
- . y1 ( 3 )
27
- . defined ( ( d , index ) => estimated ?. at ( index ) ) ;
66
+ . y1 ( - scaleHeight )
67
+ . defined ( ( d , index ) => Boolean ( estimated ?. at ( index ) ) ) ;
68
+
69
+ const patternStroke = isDarkMode ? DARK_MODE_PATTERN_STROKE : LIGHT_MODE_PATTERN_STROKE ;
70
+ const patternBackground = isDarkMode ? 'black' : 'white' ;
28
71
29
72
return (
30
73
< svg className = { className } ref = { ref } >
74
+ < defs >
75
+ < pattern
76
+ id = "pattern"
77
+ width = "8"
78
+ height = "8"
79
+ viewBox = "0 0 8 8"
80
+ patternUnits = "userSpaceOnUse"
81
+ >
82
+ < rect width = "8" height = "8" fill = { patternBackground } />
83
+ < path d = "M-5 13L15 -7" stroke = { patternStroke } />
84
+ < path d = "M-1 17L19 -3" stroke = { patternStroke } />
85
+ < path d = "M-10 10L10 -10" stroke = { patternStroke } />
86
+ </ pattern >
87
+ </ defs >
31
88
< g
32
- fill = "orange"
89
+ fill = { MARKER_COLOR }
33
90
textAnchor = "middle"
34
91
transform = { transform }
35
92
style = { { pointerEvents : 'none' } }
36
93
>
37
- < path d = { layerArea ( datetimes ) } />
94
+ < path d = { markerPathData ( datetimes ) || undefined } />
95
+ </ g >
96
+ < g textAnchor = "middle" transform = { transform } style = { { pointerEvents : 'none' } } >
97
+ < path
98
+ d = { backgroundPathData ( datetimes ) || undefined }
99
+ fill = "url(#pattern)"
100
+ opacity = { 0.4 }
101
+ />
38
102
</ g >
39
103
</ svg >
40
104
) ;
0 commit comments