import React, { memo, useCallback, useMemo } from 'react' import { useResizeDetector } from 'react-resize-detector' import { emphasize, useTheme } from '@mui/material/styles' import { XYChart, Axis, Grid, LineSeries, GlyphSeries } from '@visx/xychart' import DateFormatter from '../helper/DateFormatter' import NoData from './NoData' import NumberFormatter from '../helper/NumberFormatter' import TooltipComponent from './TooltipComponent' import { mapCurveType } from './mapCurveType' import { PlotCurveTypes } from '../../reducers/Charts' import { Point, Tooltip } from './Model' import { useCustomXDomain } from './effects/useCustomXDomain' import { useCustomYDomain } from './effects/useCustomYDomain' const abbreviate = require('number-abbreviate') export interface Props { data: Array<{ x: number; y: number }> interpolation?: PlotCurveTypes range?: [number?, number?] timeRangeStart?: number color?: string } const CHART_HEIGHT = 150 export default memo((props: Props) => { const theme = useTheme() const [tooltip, setTooltip] = React.useState() const [hoveredPoint, setHoveredPoint] = React.useState() const { width = 300, ref } = useResizeDetector() const chartContainerRef = React.useRef(null) const hintFormatter = React.useCallback( (point: any) => [ { title: Time, value: }, { title: Value, value: }, { title: Raw, value: {point.y} }, ], [] ) const onMouseLeave = React.useCallback(() => { setTooltip(undefined) setHoveredPoint(undefined) }, []) const showTooltip = React.useCallback( (point: Point) => { if (!chartContainerRef.current) { return } setHoveredPoint(point) setTooltip({ point, value: hintFormatter(point), element: chartContainerRef.current }) }, [hintFormatter] ) const paletteColor = theme.palette.mode === 'light' ? theme.palette.secondary.dark : theme.palette.primary.light const color = props.color ? props.color : paletteColor const highlightSelectedPoint = useCallback( (point: Point) => { const highlight = hoveredPoint && hoveredPoint.x === point.x && hoveredPoint.y === point.y return highlight ? emphasize(color, 0.8) : color }, [hoveredPoint, color] ) const formatYAxis = useCallback((num: number) => abbreviate(num), []) const formatXAxis = useCallback((timestamp: number) => { const date = new Date(timestamp) const hours = date.getHours().toString().padStart(2, '0') const minutes = date.getMinutes().toString().padStart(2, '0') const seconds = date.getSeconds().toString().padStart(2, '0') return `${hours}:${minutes}:${seconds}` }, []) const xDomain = useCustomXDomain(props) const yDomain = useCustomYDomain(props) const { data } = props const hasData = data.length > 0 const dummyDomain: [number, number] = [-1, 1] const dummyData = [{ x: -2, y: -2 }] const accessors = useMemo( () => ({ xAccessor: (d: Point) => d.x, yAccessor: (d: Point) => d.y, }), [] ) return (
{data.length === 0 ? : null}
({ fontSize: 11, fill: theme.palette.text.secondary })} /> ({ fontSize: 10, fill: theme.palette.text.secondary, textAnchor: 'middle' })} /> { if (datum && datum.datum) { const point = datum.datum as Point showTooltip(point) } }} /> { const point = glyphProps.datum as Point const pointColor = highlightSelectedPoint(point) return }} />
{/* Custom tooltip outside of visx to maintain exact same appearance */}
) })