/* eslint-disable @typescript-eslint/no-use-before-define */ import React, { useRef, useState, useMemo } from "react"; import { scaleLinear } from "@visx/scale"; import { Brush } from "@visx/brush"; import { Bounds } from "@visx/brush/lib/types"; import BaseBrush, { BaseBrushState, UpdateBrush, } from "@visx/brush/lib/BaseBrush"; import { PatternLines } from "@visx/pattern"; import { Group } from "@visx/group"; import { LinearGradient } from "@visx/gradient"; import { extent } from "@visx/vendor/d3-array"; import { BrushHandleRenderProps } from "@visx/brush/lib/BrushHandle"; import AreaChart from "./Area"; const brushMargin = { top: 0, bottom: 15, left: 50, right: 20 }; const chartSeparation = 30; const PATTERN_ID = "brush_pattern"; const GRADIENT_ID = "brush_gradient"; export const accentColor = "#f6acc8"; export const background = "#584153"; export const background2 = "#af8baf"; const getWeek = (d: any) => d.week; const getIndice = (d: any) => d.indice_base_100; export interface week_distribution { indice_base_100: number; week: number; } export type BrushProps = { data: week_distribution[]; width: number; height: number; margin?: { top: number; right: number; bottom: number; left: number }; compact?: boolean; }; function BrushChart({ data, compact = false, width, height, margin = { top: 20, left: 50, bottom: 20, right: 20, }, }: BrushProps) { const brushRef = useRef(null); const [filteredData, setFilteredData] = useState(data); const onBrushChange = (domain: Bounds | null) => { if (!domain) return; const { x0, x1, y0, y1 } = domain; const dataCopy = data.filter((d) => { const x = getWeek(d); const y = getIndice(d); return x > x0 && x < x1 && y > y0 && y < y1; }); setFilteredData(dataCopy); }; const innerHeight = height - margin.top - margin.bottom; const topChartBottomMargin = compact ? chartSeparation / 2 : chartSeparation + 10; const topChartHeight = 0.8 * innerHeight - topChartBottomMargin; const bottomChartHeight = innerHeight - topChartHeight - chartSeparation; const xMax = Math.max(width - margin.left - margin.right, 0); const yMax = Math.max(topChartHeight, 0); const xBrushMax = Math.max(width - brushMargin.left - brushMargin.right, 0); const yBrushMax = Math.max( bottomChartHeight - brushMargin.top - brushMargin.bottom, 0 ); const weekScale = useMemo( () => scaleLinear({ range: [0, xMax], domain: extent(data, getWeek) as [number, number], }), [xMax, data] ); const brushWeekScale = useMemo( () => scaleLinear({ range: [0, xBrushMax], domain: extent(data, getWeek) as [number, number], }), [xBrushMax, data] ); const indiceScale = useMemo( () => scaleLinear({ range: [topChartHeight, 0], domain: [70, 105], }), [topChartHeight, data] ); const initialBrushPosition = useMemo( () => ({ start: { x: brushWeekScale(data[0].week) }, end: { x: brushWeekScale(data[10].week) }, }), [brushWeekScale] ); const handleClearClick = () => { if (brushRef?.current) { setFilteredData(data); brushRef.current.reset(); } }; const handleResetClick = () => { if (brushRef?.current) { const updater: UpdateBrush = (prevBrush) => { const newExtent = brushRef.current!.getExtent( initialBrushPosition.start, initialBrushPosition.end ); const newState: BaseBrushState = { ...prevBrush, start: { y: newExtent.y0, x: newExtent.x0 }, end: { y: newExtent.y1, x: newExtent.x1 }, extent: newExtent, }; return newState; }; brushRef.current.updateBrush(updater); } }; return (
setFilteredData(data)} selectedBoxStyle={{ fill: `url(#${PATTERN_ID})`, stroke: "white", }} useWindowMoveEvents renderBrushHandle={(props) => } />
); } function BrushHandle({ x, height, isBrushActive }: BrushHandleRenderProps) { const pathWidth = 8; const pathHeight = 15; if (!isBrushActive) { return null; } return ( ); } export default BrushChart;