From ade23c386e4a216ce0c178a00b6fd7ef139447a6 Mon Sep 17 00:00:00 2001 From: Marek Mihok Date: Thu, 3 Aug 2023 12:11:55 +0200 Subject: [PATCH] feat: Allow dynamic value change for range slider #1154 (#2094) --- ui/src/range_slider.test.tsx | 27 +++++++++++++++++++++++++++ ui/src/range_slider.tsx | 27 +++++++++++++++++---------- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/ui/src/range_slider.test.tsx b/ui/src/range_slider.test.tsx index 8c4044cc31..97fc2b7b36 100644 --- a/ui/src/range_slider.test.tsx +++ b/ui/src/range_slider.test.tsx @@ -60,6 +60,33 @@ describe('rangeSlider.tsx', () => { expect(wave.args[name]).toMatchObject([50, 100]) }) + it('Set args when value is updated to different value', () => { + const { rerender } = render() + expect(wave.args[name]).toMatchObject([40, 60]) + rerender() + expect(wave.args[name]).toMatchObject([30, 70]) + }) + + it('Set args when value is updated to initial value', () => { + const { container, getAllByRole, rerender } = render() + expect(wave.args[name]).toMatchObject([40, 60]) + + container.querySelector('.ms-Slider-line')!.getBoundingClientRect = () => defaultRect + fireEvent.mouseDown(getAllByRole('slider')[0]!, mouseEvent) + expect(wave.args[name]).toMatchObject([50, 60]) + + rerender() + expect(wave.args[name]).toMatchObject([40, 60]) + }) + + it('Changes out of bounds values when min/max is updated', () => { + const { rerender } = render() + expect(wave.args[name]).toMatchObject([30, 60]) + + rerender() + expect(wave.args[name]).toMatchObject([40, 50]) + }) + it('Calls sync on slide', () => { const pushMock = jest.fn() wave.push = pushMock diff --git a/ui/src/range_slider.tsx b/ui/src/range_slider.tsx index f0279e6924..29b88de34f 100644 --- a/ui/src/range_slider.tsx +++ b/ui/src/range_slider.tsx @@ -54,17 +54,24 @@ export interface RangeSlider { export const XRangeSlider = ({ model }: { model: RangeSlider }) => { const - { min = 0, max = 100, step = 1, min_value, max_value = max, disabled, trigger, name, label } = model, - onChange = React.useCallback((_val: U, val_range?: [U, U]) => { if (val_range) wave.args[name] = val_range }, [name]), + { min = 0, max = 100, step = 1, min_value = min, max_value = max, disabled, trigger, name, label } = model, + [valRange, setValRange] = React.useState<[U, U]>([min_value, max_value]), + onChange = React.useCallback((_val: U, val_range?: [U, U]) => { + if (val_range) { + wave.args[name] = val_range + model.min_value = val_range[0] + model.max_value = val_range[1] + setValRange(val_range) + } + }, [model, name]), onChanged = React.useCallback(() => { if (trigger) wave.push() }, [trigger]) React.useEffect(() => { - wave.args[name] = [ - typeof min_value == 'number' && min_value > min && min_value <= max ? min_value : min, - typeof max_value == 'number' && max_value > min && max_value <= max ? max_value : max, - ] - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) + const lowerValue = typeof min_value == 'number' && min_value > min && min_value <= max ? min_value : min + const upperValue = typeof max_value == 'number' && max_value > min && max_value <= max ? max_value : max + wave.args[name] = [lowerValue, upperValue] + setValRange([lowerValue, upperValue]) + }, [min_value, max_value, min, max, name]) return (
@@ -74,8 +81,8 @@ export const XRangeSlider = ({ model }: { model: RangeSlider }) => { min={min} step={step} label={label} - defaultLowerValue={min_value} - defaultValue={max_value} + lowerValue={valRange[0]} + value={valRange[1]} disabled={disabled} onChange={onChange} onChanged={onChanged}