websync / components /input /InputSlider.tsx
Shivam
Initial commit: Web-SyncPlay moved into Streamer
d092f57
import styles from "./InputSlider.module.css"
import React, {
CSSProperties,
FC,
MouseEventHandler,
TouchEventHandler,
useState,
} from "react"
import classNames from "classnames"
import { Tooltip } from "react-tooltip"
import { secondsToTime } from "../../lib/utils"
interface Props {
min?: number
max?: number
step?: number
value: number
onChange: (value: number) => void
className?: string
setSeeking?: (seeking: boolean) => void
showValueHover?: boolean
}
const InputSlider: FC<Props> = ({
min = 0,
max = 1,
step = 0.001,
value,
onChange,
className = "",
setSeeking,
showValueHover = false,
}) => {
const [hoverValue, setHoverValue] = useState(0)
const [time, setTime] = useState(secondsToTime(hoverValue))
if (min < 0) {
console.error("Slider with min value below 0:", min)
return <></>
}
const valueStyle = {
"--value": (value / (max - min)) * 100 + "%",
}
const startSeek:
| MouseEventHandler<HTMLInputElement>
| TouchEventHandler<HTMLInputElement> = () => {
if (setSeeking) {
setSeeking(true)
}
}
const stopSeek:
| MouseEventHandler<HTMLInputElement>
| TouchEventHandler<HTMLInputElement> = () => {
if (setSeeking) {
setSeeking(false)
}
}
const calcSliderPos = (e: React.MouseEvent<HTMLInputElement>) => {
const target = e.target as HTMLInputElement
return (e.nativeEvent.offsetX / target.clientWidth) * max
}
return (
<div
className={classNames(styles.slider, "flex px-1 items-center", className)}
>
<input
data-tooltip-content={""}
id={"slider"}
data-tooltip-variant={"dark"}
type={"range"}
min={min}
max={max}
step={step}
value={value}
onMouseMove={(event) => {
setHoverValue(calcSliderPos(event))
setTime(secondsToTime(calcSliderPos(event)))
}}
onMouseDown={startSeek as MouseEventHandler}
onTouchStart={startSeek as TouchEventHandler}
onMouseUp={stopSeek as MouseEventHandler}
onTouchEnd={stopSeek as TouchEventHandler}
onChange={(event) => {
const v = parseFloat(event.target.value)
event.target.style.setProperty(
"--value",
(v / (max - min)) * 100 + "%"
)
onChange(v)
}}
style={valueStyle as CSSProperties}
/>
{showValueHover && (
<Tooltip
anchorId={"slider"}
place={"top"}
//arrowColor={"var(--dark-700)"}
content={time}
style={{
backgroundColor: "var(--dark-700)",
}}
/>
)}
</div>
)
}
export default InputSlider