// @flow strict import * as React from 'react'; import { colorFillPrimary, colorGrayLightest, colorTextDisabled, } from '../../styles/variables/_color'; import classify from '../../utils/classify'; import type {ButtonSize} from '../Button'; import {Button, BUTTON_SIZE} from '../Button'; import {Input} from '../Input'; import {BodySmall} from '../Text'; import css from './RangeSlider.module.css'; type ClassNames = $ReadOnly<{wrapper?: string}>; export type RangeSliderProps = { min?: number, max?: number, step?: number, value?: number, onChange?: (value: number) => void, // We don't want to send in the event because the icon buttons also modify the value showTicks?: boolean, iconLeftName?: string, btnLeftSize?: ButtonSize, iconRightName?: string, btnRightSize?: ButtonSize, disabled?: boolean, hideLeftBtn?: boolean, hideRightBtn?: boolean, classNames?: ClassNames, ariaLabel?: string, showRange?: boolean, hideValueInput?: boolean, ... }; export const RangeSlider: React$AbstractComponent< RangeSliderProps, HTMLDivElement, > = React.forwardRef( ( { classNames, disabled, min = 0, max = 100, step = 1, value = min, onChange, showTicks, iconLeftName = 'minus', btnLeftSize = BUTTON_SIZE.small, iconRightName = 'plus', btnRightSize = BUTTON_SIZE.small, hideLeftBtn, hideRightBtn, ariaLabel = 'Slider', showRange, hideValueInput, ...restInputProps }: RangeSliderProps, ref, ) => { const progress = ((value - min) / (max - min)) * 100; const btnLeftDisabled = disabled || value <= min; const btnRightDisabled = disabled || value >= max; const progressColor = disabled ? colorTextDisabled : colorFillPrimary; const handleInputChange = (e: SyntheticEvent) => { let inputValue = parseFloat(e.currentTarget.value); // Validate and adjust the value if (isNaN(inputValue) || inputValue < min) { inputValue = min; } else if (inputValue > max) { inputValue = max; } else if (step > 0) { const nearestStep = Math.round(inputValue / step) * step; inputValue = Math.round(nearestStep * 100) / 100; // Adjust to nearest valid step } onChange?.(inputValue); }; const handleChange = (e: SyntheticEvent) => { emitRoundedValue(e.currentTarget.value); }; const emitRoundedValue = (value: number | string) => { const newValue = parseFloat(value); const roundedValue = Math.round(newValue * 100) / 100; // Rounds to two decimal places onChange?.(roundedValue); }; return (
{!hideLeftBtn && !showRange && (
); }, );