diff --git a/packages/ui/src/Slider.test.ts b/packages/ui/src/Slider.test.ts index 287db2da..ae67b3ee 100644 --- a/packages/ui/src/Slider.test.ts +++ b/packages/ui/src/Slider.test.ts @@ -121,6 +121,25 @@ describe('Slider', () => { expect(range.getHigh()).toBe(80); }); + it('does not fire onChange while initializing custom range values', () => { + const onChange = vi.fn(); + + const range = new RangeInput({}, { + min: 0, + max: 100, + low: 20, + high: 80, + onChange, + }); + + expect(range.getLow()).toBe(20); + expect(range.getHigh()).toBe(80); + expect(onChange).not.toHaveBeenCalled(); + + range.setRange(25, 75); + expect(onChange).toHaveBeenCalledWith(25, 75); + }); + it('renders two handles', () => { vi.spyOn(caps, 'unicode', 'get').mockReturnValue(false); @@ -153,4 +172,4 @@ describe('Slider', () => { expect(handles).toBe(2); }); -}); \ No newline at end of file +}); diff --git a/packages/ui/src/Slider.ts b/packages/ui/src/Slider.ts index 335cc73d..f6b5fae8 100644 --- a/packages/ui/src/Slider.ts +++ b/packages/ui/src/Slider.ts @@ -151,13 +151,12 @@ export class RangeInput extends Widget { this.onChange = opts.onChange; -this._low = this._min; -this._high = this._max; - -this.setRange( - opts.low ?? this._min, - opts.high ?? this._max, -); + const [low, high] = this._normalizeRange( + opts.low ?? this._min, + opts.high ?? this._max, + ); + this._low = low; + this._high = high; } handleKey(event: KeyEvent): void { @@ -192,40 +191,39 @@ this.setRange( return this._high; } - setRange(low: number, high: number): void { - const nextLow = Math.max( - this._min, - Math.min(this._max, low), - ); - - const nextHigh = Math.max( - this._min, - Math.min(this._max, high), - ); - - const normalizedLow = Math.min( - nextLow, - nextHigh, - ); - - const normalizedHigh = Math.max( - nextLow, - nextHigh, - ); - - if ( - normalizedLow === this._low && - normalizedHigh === this._high - ) { - return; + private _normalizeRange(low: number, high: number): [number, number] { + const nextLow = Math.max( + this._min, + Math.min(this._max, low), + ); + + const nextHigh = Math.max( + this._min, + Math.min(this._max, high), + ); + + return [ + Math.min(nextLow, nextHigh), + Math.max(nextLow, nextHigh), + ]; } - this._low = normalizedLow; - this._high = normalizedHigh; + setRange(low: number, high: number): void { + const [normalizedLow, normalizedHigh] = this._normalizeRange(low, high); - this.onChange?.(this._low, this._high); - this.markDirty(); -} + if ( + normalizedLow === this._low && + normalizedHigh === this._high + ) { + return; + } + + this._low = normalizedLow; + this._high = normalizedHigh; + + this.onChange?.(this._low, this._high); + this.markDirty(); + } protected _renderSelf(screen: Screen): void { const { x, y, width } = this._rect; @@ -264,4 +262,4 @@ this.setRange( attrs, ); } -} \ No newline at end of file +}