color-q/src/components/LabeledPicker.tsx
2025-01-15 13:41:05 +08:00

62 lines
1.3 KiB
TypeScript

import cx from 'clsx';
import { isEqual, isNil } from 'lodash-es';
import { useEffect, useState } from 'react';
import styles from './LabeledPicker.module.css';
type LabeledPickerProps = {
title?: string;
value?: number;
unit?: string;
onChange: (value: number) => void;
min?: number;
max?: number;
step?: number;
disabled?: boolean;
};
export function LabeledPicker({
title,
value,
unit,
onChange,
min = 0,
max = 100,
step = 1,
disabled = false,
}: LabeledPickerProps) {
const [pickerValue, setPickerValue] = useState(value ?? min);
const handlePickerChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const value = event.target.value as number;
setPickerValue(value);
onChange?.(value);
};
useEffect(() => {
if (!isEqual(value, pickerValue)) {
setPickerValue(value);
}
}, [value]);
return (
<div className={styles.labeled_picker}>
<div className={styles.title_row}>
{!isNil(title) && <label>{title}</label>}
<div className="spacer" />
<span>
{pickerValue} {unit}
</span>
</div>
<input
type="range"
className={cx('picker')}
value={pickerValue}
onChange={handlePickerChange}
min={min}
max={max}
step={step}
disabled={disabled}
/>
</div>
);
}