diff --git a/packages/studio/src/components/editor/propertyPanelFlatPrimitives.test.tsx b/packages/studio/src/components/editor/propertyPanelFlatPrimitives.test.tsx
index dcb8dd6dd4..0e3d5eb928 100644
--- a/packages/studio/src/components/editor/propertyPanelFlatPrimitives.test.tsx
+++ b/packages/studio/src/components/editor/propertyPanelFlatPrimitives.test.tsx
@@ -280,6 +280,82 @@ describe("FlatSlider", () => {
expect(onCommit).toHaveBeenCalledWith(10);
act(() => root.unmount());
});
+
+ it("commits continuously while dragging, not just on the initial pointerdown", () => {
+ const onCommit = vi.fn();
+ const { host, root } = renderInto(
+ ,
+ );
+ const track = host.querySelector('[data-flat-slider-track="true"]');
+ if (!track) throw new Error("expected a track element");
+ Object.defineProperty(track, "getBoundingClientRect", {
+ value: () => ({ left: 0, width: 200, top: 0, height: 20, right: 200, bottom: 20 }),
+ });
+ act(() => {
+ track.dispatchEvent(
+ new PointerEvent("pointerdown", { bubbles: true, clientX: 20, pointerId: 1 }),
+ );
+ });
+ expect(onCommit).toHaveBeenLastCalledWith(10);
+ act(() => {
+ track.dispatchEvent(
+ new PointerEvent("pointermove", { bubbles: true, clientX: 160, pointerId: 1 }),
+ );
+ });
+ expect(onCommit).toHaveBeenLastCalledWith(80);
+ act(() => {
+ track.dispatchEvent(
+ new PointerEvent("pointermove", { bubbles: true, clientX: 100, pointerId: 1 }),
+ );
+ });
+ expect(onCommit).toHaveBeenLastCalledWith(50);
+ act(() => {
+ track.dispatchEvent(new PointerEvent("pointerup", { bubbles: true, pointerId: 1 }));
+ });
+ act(() => root.unmount());
+ });
+
+ it("ignores pointermove once a drag has ended (pointer capture released)", () => {
+ const onCommit = vi.fn();
+ const { host, root } = renderInto(
+ ,
+ );
+ const track = host.querySelector('[data-flat-slider-track="true"]');
+ if (!track) throw new Error("expected a track element");
+ Object.defineProperty(track, "getBoundingClientRect", {
+ value: () => ({ left: 0, width: 200, top: 0, height: 20, right: 200, bottom: 20 }),
+ });
+ act(() => {
+ track.dispatchEvent(
+ new PointerEvent("pointerdown", { bubbles: true, clientX: 20, pointerId: 1 }),
+ );
+ track.dispatchEvent(new PointerEvent("pointerup", { bubbles: true, pointerId: 1 }));
+ });
+ onCommit.mockClear();
+ act(() => {
+ track.dispatchEvent(
+ new PointerEvent("pointermove", { bubbles: true, clientX: 160, pointerId: 1 }),
+ );
+ });
+ expect(onCommit).not.toHaveBeenCalled();
+ act(() => root.unmount());
+ });
});
describe("FlatSlider — Grade extensions", () => {
diff --git a/packages/studio/src/components/editor/propertyPanelFlatPrimitives.tsx b/packages/studio/src/components/editor/propertyPanelFlatPrimitives.tsx
index f2cdf6220b..52eba79a3e 100644
--- a/packages/studio/src/components/editor/propertyPanelFlatPrimitives.tsx
+++ b/packages/studio/src/components/editor/propertyPanelFlatPrimitives.tsx
@@ -262,8 +262,18 @@ export function FlatSlider({
className={`relative h-5 flex-1 ${disabled ? "cursor-not-allowed" : "cursor-pointer"}`}
onPointerDown={(e) => {
if (disabled) return;
+ e.currentTarget.setPointerCapture(e.pointerId);
commitFromClientX(e.clientX, e.currentTarget.getBoundingClientRect());
}}
+ onPointerMove={(e) => {
+ if (disabled || !e.currentTarget.hasPointerCapture(e.pointerId)) return;
+ commitFromClientX(e.clientX, e.currentTarget.getBoundingClientRect());
+ }}
+ onPointerUp={(e) => {
+ if (e.currentTarget.hasPointerCapture(e.pointerId)) {
+ e.currentTarget.releasePointerCapture(e.pointerId);
+ }
+ }}
>
{centerTick && (