22import * as React from 'react' ;
33import classNames from 'classnames' ;
44import useMobile from 'rc-util/lib/hooks/useMobile' ;
5+ import raf from 'rc-util/lib/raf' ;
56
67/**
78 * When click and hold on a button - the speed of auto changing the value.
@@ -32,13 +33,20 @@ export default function StepHandler({
3233} : StepHandlerProps ) {
3334 // ======================== Step ========================
3435 const stepTimeoutRef = React . useRef < any > ( ) ;
36+ const frameIds = React . useRef < number [ ] > ( [ ] ) ;
3537
3638 const onStepRef = React . useRef < StepHandlerProps [ 'onStep' ] > ( ) ;
3739 onStepRef . current = onStep ;
3840
41+ const onStopStep = ( ) => {
42+ clearTimeout ( stepTimeoutRef . current ) ;
43+ } ;
44+
45+
3946 // We will interval update step when hold mouse down
4047 const onStepMouseDown = ( e : React . MouseEvent , up : boolean ) => {
4148 e . preventDefault ( ) ;
49+ onStopStep ( ) ;
4250
4351 onStepRef . current ( up ) ;
4452
@@ -53,11 +61,10 @@ export default function StepHandler({
5361 stepTimeoutRef . current = setTimeout ( loopStep , STEP_DELAY ) ;
5462 } ;
5563
56- const onStopStep = ( ) => {
57- clearTimeout ( stepTimeoutRef . current ) ;
58- } ;
59-
60- React . useEffect ( ( ) => onStopStep , [ ] ) ;
64+ React . useEffect ( ( ) => ( ) => {
65+ onStopStep ( ) ;
66+ frameIds . current . forEach ( id => raf . cancel ( id ) ) ;
67+ } , [ ] ) ;
6168
6269 // ======================= Render =======================
6370 const isMobile = useMobile ( ) ;
@@ -74,11 +81,18 @@ export default function StepHandler({
7481 [ `${ handlerClassName } -down-disabled` ] : downDisabled ,
7582 } ) ;
7683
84+ // fix: https://github.com/ant-design/ant-design/issues/43088
85+ // In Safari, When we fire onmousedown and onmouseup events in quick succession,
86+ // there may be a problem that the onmouseup events are executed first,
87+ // resulting in a disordered program execution.
88+ // So, we need to use requestAnimationFrame to ensure that the onmouseup event is executed after the onmousedown event.
89+ const safeOnStopStep = ( ) => frameIds . current . push ( raf ( onStopStep ) ) ;
90+
7791 const sharedHandlerProps = {
7892 unselectable : 'on' as const ,
7993 role : 'button' ,
80- onMouseUp : onStopStep ,
81- onMouseLeave : onStopStep ,
94+ onMouseUp : safeOnStopStep ,
95+ onMouseLeave : safeOnStopStep ,
8296 } ;
8397
8498 return (
0 commit comments