import React, { useCallback, useEffect, useState } from 'react'; import { Domain } from '../../utils/types'; export type SelectRegionProps = { domain: Domain, width: number, height: number, dragRegionHeight: number, leftMargin: number, onSelectionEnd: (domain: Domain) => void }; const SelectRegion: React.FC = props => { const [ domain, setDomain ] = useState(undefined); const [ selecting, setSelecting ] = useState(false); const onKeyDown = useCallback( (e: KeyboardEvent) => { if (e.key === "Control" || e.key === "Shift") setSelecting(true); }, []); const onKeyUp = useCallback( (e: KeyboardEvent) => { if (e.key === "Control" || e.key === "Shift") setSelecting(false); }, []); useEffect( () => { document.addEventListener("keydown", onKeyDown); document.addEventListener("keyup", onKeyUp); return () => { document.removeEventListener("keydown", onKeyDown, false); document.removeEventListener("keyup", onKeyUp, false); }; }, [ onKeyDown, onKeyUp ]); const onMouseDown = useCallback((e: React.MouseEvent) => { if (!selecting) return; const r = (e.target as SVGRectElement).getBoundingClientRect(); setDomain({ start: (e.clientX - r.left) * props.width / r.width, end: (e.clientX - r.left) * props.width / r.width }); }, [ props.width, selecting ]); const onMouseMove = useCallback((e: React.MouseEvent) => { if (!selecting) return; const r = (e.target as SVGRectElement).getBoundingClientRect(); domain && setDomain({ start: domain.start, end: (e.clientX - r.left) * props.width / r.width }); }, [ props.width, domain, selecting ]); const onMouseUp = useCallback((e: React.MouseEvent) => { if (!selecting) return; const r = (e.target as SVGRectElement).getBoundingClientRect(); const cend = (e.clientX - r.left) * props.width / r.width; const start = ((domain?.start || 0) - props.leftMargin) * (props.domain.end - props.domain.start) / (props.width - props.leftMargin) + props.domain.start; const end = (cend - props.leftMargin) * (props.domain.end - props.domain.start) / (props.width - props.leftMargin) + props.domain.start; domain && props.onSelectionEnd && props.onSelectionEnd({ start: Math.floor(start), end: Math.floor(end) }); setDomain(undefined); }, [ props.width, props.leftMargin, props.onSelectionEnd, selecting, domain ]); return ( <> { domain && selecting && ( )} ); } export default SelectRegion;