fix(core): prevent slider thumb jump on pointer release (#990)

This commit is contained in:
rahim
2026-03-17 23:29:23 -07:00
committed by GitHub
parent fc62ea1c0a
commit b9bada9567
4 changed files with 27 additions and 2 deletions
@@ -155,6 +155,12 @@ export class SliderCore {
return roundToStep(clamp(raw, min, max), step, min);
}
/** Convert percent to a clamped value without applying step rounding. */
rawValueFromPercent(percent: number): number {
const { min, max } = this.#props;
return clamp(min + (percent / 100) * (max - min), min, max);
}
percentFromValue(value: number): number {
const { min, max } = this.#props;
if (max === min) return 0;
@@ -203,6 +203,25 @@ describe('SliderCore', () => {
});
});
describe('rawValueFromPercent', () => {
it('converts percent to value without step rounding', () => {
const core = new SliderCore({ step: 5 });
expect(core.rawValueFromPercent(53)).toBe(53);
expect(core.rawValueFromPercent(47)).toBe(47);
});
it('clamps to range', () => {
const core = new SliderCore();
expect(core.rawValueFromPercent(-10)).toBe(0);
expect(core.rawValueFromPercent(110)).toBe(100);
});
it('respects custom min/max', () => {
const core = new SliderCore({ min: 10, max: 20 });
expect(core.rawValueFromPercent(50)).toBe(15);
});
});
describe('percentFromValue', () => {
it('returns 0 at min', () => {
const core = new SliderCore();
@@ -70,7 +70,7 @@ export class TimeSliderElement extends MediaElement {
getLargeStepPercent: () => this.#core.getLargeStepPercent(),
onValueCommit: (percent) => {
const media = this.#timeState.value;
if (media) media.seek(this.#core.valueFromPercent(percent));
if (media) media.seek(this.#core.rawValueFromPercent(percent));
},
commitThrottle: this.commitThrottle,
onDragStart: () => {
@@ -77,7 +77,7 @@ export const TimeSliderRoot = forwardRef<HTMLDivElement, TimeSliderRootProps>(
getCSSVars: getTimeSliderCSSVars,
onValueCommit: (percent) => {
const media = mediaRef.current;
if (media) media.seek(core.valueFromPercent(percent));
if (media) media.seek(core.rawValueFromPercent(percent));
},
onDragStart,
onDragEnd,