Skip to content

Commit 33692bd

Browse files
authored
[number field] Fix pointer lock release when soft clicking in Firefox (#3378)
1 parent d2de90b commit 33692bd

File tree

1 file changed

+28
-19
lines changed

1 file changed

+28
-19
lines changed

packages/react/src/number-field/scrub-area/NumberFieldScrubArea.tsx

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
import * as React from 'react';
33
import * as ReactDOM from 'react-dom';
44
import { ownerWindow, ownerDocument } from '@base-ui-components/utils/owner';
5-
import { isWebKit } from '@base-ui-components/utils/detectBrowser';
6-
import { useValueAsRef } from '@base-ui-components/utils/useValueAsRef';
5+
import { isFirefox, isWebKit } from '@base-ui-components/utils/detectBrowser';
76
import { useStableCallback } from '@base-ui-components/utils/useStableCallback';
7+
import { useTimeout } from '@base-ui-components/utils/useTimeout';
88
import type { BaseUIComponentProps, HTMLProps } from '../../utils/types';
99
import { useNumberFieldRootContext } from '../root/NumberFieldRootContext';
1010
import type { NumberFieldRoot } from '../root/NumberFieldRoot';
@@ -43,7 +43,6 @@ export const NumberFieldScrubArea = React.forwardRef(function NumberFieldScrubAr
4343
setIsScrubbing,
4444
disabled,
4545
readOnly,
46-
value,
4746
inputRef,
4847
incrementValue,
4948
getStepAmount,
@@ -52,15 +51,15 @@ export const NumberFieldScrubArea = React.forwardRef(function NumberFieldScrubAr
5251
valueRef,
5352
} = useNumberFieldRootContext();
5453

55-
const latestValueRef = useValueAsRef(value);
56-
5754
const scrubAreaRef = React.useRef<HTMLSpanElement>(null);
5855

5956
const isScrubbingRef = React.useRef(false);
6057
const scrubAreaCursorRef = React.useRef<HTMLSpanElement>(null);
6158
const virtualCursorCoords = React.useRef({ x: 0, y: 0 });
6259
const visualScaleRef = React.useRef(1);
6360

61+
const exitPointerLockTimeout = useTimeout();
62+
6463
const [isTouchInput, setIsTouchInput] = React.useState(false);
6564
const [isPointerLockDenied, setIsPointerLockDenied] = React.useState(false);
6665

@@ -146,18 +145,27 @@ export const NumberFieldScrubArea = React.forwardRef(function NumberFieldScrubAr
146145
let cumulativeDelta = 0;
147146

148147
function handleScrubPointerUp(event: PointerEvent) {
149-
try {
150-
// Avoid errors in testing environments.
151-
ownerDocument(scrubAreaRef.current).exitPointerLock();
152-
} catch {
153-
//
154-
} finally {
155-
isScrubbingRef.current = false;
156-
onScrubbingChange(false, event);
157-
onValueCommitted(
158-
lastChangedValueRef.current ?? valueRef.current,
159-
createGenericEventDetails(REASONS.scrub, event),
160-
);
148+
function handler() {
149+
try {
150+
ownerDocument(scrubAreaRef.current).exitPointerLock();
151+
} catch {
152+
// Ignore errors.
153+
} finally {
154+
isScrubbingRef.current = false;
155+
onScrubbingChange(false, event);
156+
onValueCommitted(
157+
lastChangedValueRef.current ?? valueRef.current,
158+
createGenericEventDetails(REASONS.scrub, event),
159+
);
160+
}
161+
}
162+
163+
if (isFirefox) {
164+
// Firefox needs a small delay here when soft-clicking as the pointer
165+
// lock will not release otherwise.
166+
exitPointerLockTimeout.start(20, handler);
167+
} else {
168+
handler();
161169
}
162170
}
163171

@@ -197,16 +205,16 @@ export const NumberFieldScrubArea = React.forwardRef(function NumberFieldScrubAr
197205
win.addEventListener('pointermove', handleScrubPointerMove, true);
198206

199207
return () => {
208+
exitPointerLockTimeout.clear();
200209
win.removeEventListener('pointerup', handleScrubPointerUp, true);
201210
win.removeEventListener('pointermove', handleScrubPointerMove, true);
202211
};
203212
},
204213
[
205214
disabled,
206215
readOnly,
207-
isScrubbing,
208216
incrementValue,
209-
latestValueRef,
217+
isScrubbing,
210218
getStepAmount,
211219
inputRef,
212220
onScrubbingChange,
@@ -216,6 +224,7 @@ export const NumberFieldScrubArea = React.forwardRef(function NumberFieldScrubAr
216224
lastChangedValueRef,
217225
onValueCommitted,
218226
valueRef,
227+
exitPointerLockTimeout,
219228
],
220229
);
221230

0 commit comments

Comments
 (0)