-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathd3-chart-wrapper.tsx
More file actions
101 lines (98 loc) · 3.03 KB
/
d3-chart-wrapper.tsx
File metadata and controls
101 lines (98 loc) · 3.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
'use client';
import React from 'react';
export interface D3ChartWrapperProps {
chartId: string;
svgRef: React.RefObject<SVGSVGElement | null>;
tooltipRef: React.RefObject<HTMLDivElement | null>;
setContainerRef: (el: HTMLDivElement | null) => void;
dimensions: { width: number; height: number };
pinnedPoint: unknown | null;
isPinned: () => boolean;
dismissTooltip: () => void;
hideTooltipElements: (
tooltipRef: React.RefObject<HTMLDivElement | null>,
svgRef: React.RefObject<SVGSVGElement | null>,
) => void;
legendElement: React.ReactNode;
noDataOverlay?: React.ReactNode;
caption?: React.ReactNode;
instructions?: string;
testId?: string;
grabCursor?: boolean;
}
export function D3ChartWrapper({
chartId,
svgRef,
tooltipRef,
setContainerRef,
dimensions,
pinnedPoint,
isPinned,
dismissTooltip,
hideTooltipElements,
legendElement,
noDataOverlay,
caption,
instructions = 'Shift+Scroll to zoom • Drag to pan • Double-click to reset • Click a point to pin tooltip',
testId,
grabCursor = true,
}: D3ChartWrapperProps) {
return (
<div id={chartId} data-testid={testId}>
{caption && <figcaption>{caption}</figcaption>}
<div className="flex flex-col lg:flex-row w-full">
<div ref={setContainerRef} className="relative flex-1 min-w-0">
<div className="relative">
<svg
ref={svgRef}
width="100%"
height={dimensions.height}
style={{ cursor: grabCursor ? 'grab' : undefined }}
onMouseDown={
grabCursor
? (e) => {
(e.currentTarget as SVGSVGElement).style.cursor = 'grabbing';
}
: undefined
}
onMouseUp={
grabCursor
? (e) => {
(e.currentTarget as SVGSVGElement).style.cursor = 'grab';
}
: undefined
}
onClick={() => {
if (isPinned()) {
dismissTooltip();
hideTooltipElements(tooltipRef, svgRef);
}
}}
/>
<div
ref={tooltipRef}
data-chart-tooltip
style={{
position: 'absolute',
opacity: pinnedPoint ? 1 : 0,
pointerEvents: pinnedPoint ? 'auto' : 'none',
display: pinnedPoint ? 'block' : 'none',
zIndex: 50,
}}
/>
{noDataOverlay}
</div>
<p className="no-export text-xs text-muted-foreground text-center mt-2">{instructions}</p>
<div className="overflow-hidden max-h-0">
<div id={`${chartId}-export`} className="p-4"></div>
</div>
</div>
{legendElement && (
<div className="w-full h-96 lg:h-[575px] lg:w-48 lg:shrink-0 relative mt-3 lg:mt-0">
{legendElement}
</div>
)}
</div>
</div>
);
}