36 lines
1010 B
TypeScript
36 lines
1010 B
TypeScript
import { useEffect, useRef, useState } from 'react'
|
|
|
|
/**
|
|
* Throttles a value so each distinct value stays visible for at least `minMs`.
|
|
* Prevents fast-cycling progress text from flickering past before it's readable.
|
|
*
|
|
* Unlike debounce (wait for quiet) or throttle (limit rate), this guarantees
|
|
* each value gets its minimum screen time before being replaced.
|
|
*/
|
|
export function useMinDisplayTime<T>(value: T, minMs: number): T {
|
|
const [displayed, setDisplayed] = useState(value)
|
|
const lastShownAtRef = useRef(0)
|
|
|
|
useEffect(() => {
|
|
const elapsed = Date.now() - lastShownAtRef.current
|
|
if (elapsed >= minMs) {
|
|
lastShownAtRef.current = Date.now()
|
|
setDisplayed(value)
|
|
return
|
|
}
|
|
const timer = setTimeout(
|
|
(shownAtRef, setFn, v) => {
|
|
shownAtRef.current = Date.now()
|
|
setFn(v)
|
|
},
|
|
minMs - elapsed,
|
|
lastShownAtRef,
|
|
setDisplayed,
|
|
value,
|
|
)
|
|
return () => clearTimeout(timer)
|
|
}, [value, minMs])
|
|
|
|
return displayed
|
|
}
|