| 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 |
|
|