pstream is dead; long live pstream taciturnaxolotl.github.io/pstream-ng/
at main 89 lines 2.7 kB view raw
1import React, { RefObject, useCallback, useEffect, useState } from "react"; 2 3export type MouseActivity = React.MouseEvent<HTMLElement> | MouseEvent; 4 5type ActivityEvent = MouseActivity | React.TouchEvent<HTMLElement> | TouchEvent; 6 7export function makePercentageString(num: number) { 8 return `${num.toFixed(2)}%`; 9} 10 11export function makePercentage(num: number) { 12 return Number(Math.max(0, Math.min(num, 100)).toFixed(2)); 13} 14 15function isClickEvent( 16 evt: ActivityEvent, 17): evt is React.MouseEvent<HTMLElement> | MouseEvent { 18 return ( 19 evt.type === "mousedown" || 20 evt.type === "mouseup" || 21 evt.type === "mousemove" 22 ); 23} 24 25const getEventX = (evt: ActivityEvent) => { 26 return isClickEvent(evt) ? evt.pageX : evt.changedTouches[0].pageX; 27}; 28 29export function useProgressBar( 30 barRef: RefObject<HTMLElement>, 31 commit: (percentage: number) => void, 32 commitImmediately = false, 33) { 34 const [mouseDown, setMouseDown] = useState<boolean>(false); 35 const [progress, setProgress] = useState<number>(0); 36 37 useEffect(() => { 38 function mouseMove(ev: ActivityEvent) { 39 if (!mouseDown || !barRef.current) return; 40 const rect = barRef.current.getBoundingClientRect(); 41 const pos = (getEventX(ev) - rect.left) / barRef.current.offsetWidth; 42 setProgress(pos * 100); 43 if (commitImmediately) commit(pos); 44 } 45 46 function mouseUp(ev: ActivityEvent) { 47 if (!mouseDown) return; 48 setMouseDown(false); 49 document.body.removeAttribute("data-no-select"); 50 51 if (!barRef.current) return; 52 const rect = barRef.current.getBoundingClientRect(); 53 const pos = (getEventX(ev) - rect.left) / barRef.current.offsetWidth; 54 commit(pos); 55 } 56 57 document.addEventListener("mousemove", mouseMove); 58 document.addEventListener("touchmove", mouseMove); 59 document.addEventListener("mouseup", mouseUp); 60 document.addEventListener("touchend", mouseUp); 61 62 return () => { 63 document.removeEventListener("mousemove", mouseMove); 64 document.removeEventListener("touchmove", mouseMove); 65 document.removeEventListener("mouseup", mouseUp); 66 document.removeEventListener("touchend", mouseUp); 67 }; 68 }, [mouseDown, barRef, commit, commitImmediately]); 69 70 const dragMouseDown = useCallback( 71 (ev: ActivityEvent) => { 72 setMouseDown(true); 73 document.body.setAttribute("data-no-select", "true"); 74 75 if (!barRef.current) return; 76 const rect = barRef.current.getBoundingClientRect(); 77 const pos = 78 ((getEventX(ev) - rect.left) / barRef.current.offsetWidth) * 100; 79 setProgress(pos); 80 }, 81 [setProgress, barRef], 82 ); 83 84 return { 85 dragging: mouseDown, 86 dragPercentage: progress, 87 dragMouseDown, 88 }; 89}