@@ -89,7 +89,13 @@ export function CircleSelector({
8989 pressed . current . lastRegisteredInput = 0 ;
9090 }
9191
92- function onMove ( event : React . MouseEvent < HTMLDivElement > ) {
92+ function onMove ( this : HTMLDivElement , event : MouseEvent | TouchEvent ) {
93+ function isTouchEvent ( event : Event ) : event is TouchEvent {
94+ return ( event as any ) . touches ;
95+ }
96+
97+ event . preventDefault ( ) ;
98+
9399 /* Debounce and check for mouse press */
94100 const currentTime = new Date ( ) . getTime ( ) ;
95101 // Mouse movement only, so the input must not change the value
@@ -116,10 +122,10 @@ export function CircleSelector({
116122 }
117123
118124 // Rectangle containing all elements. Offsets are relative to the viewport.
119- const targetDimensionsInViewport : DOMRect = event . currentTarget . getBoundingClientRect ( ) ;
125+ const targetDimensionsInViewport : DOMRect = this . getBoundingClientRect ( ) ;
120126 const cursorPosition : Vector = new CartesianPoint (
121- event . clientX - targetDimensionsInViewport . left ,
122- event . clientY - targetDimensionsInViewport . top
127+ ( isTouchEvent ( event ) ? event . touches [ 0 ] . clientX : event . clientX ) - targetDimensionsInViewport . left ,
128+ ( isTouchEvent ( event ) ? event . touches [ 0 ] . clientY : event . clientY ) - targetDimensionsInViewport . top
123129 ) ;
124130
125131 const pointOnCircleCartesian = calculateClosestPointOnCircle ( cursorPosition ) ;
@@ -147,7 +153,26 @@ export function CircleSelector({
147153 setValue ( percentage ) ;
148154 }
149155
150- return < div onMouseMove = { onMove }
156+ const containerRef = React . useRef < HTMLDivElement > ( null ) ;
157+ React . useEffect ( ( ) => {
158+ const element = containerRef . current ;
159+ if ( ! element ) {
160+ return ;
161+ }
162+
163+ // Necessary as event listeners must not be passive (Event#preventDefault fails otherwise)
164+ element . addEventListener ( "mousemove" , onMove , { passive : false } ) ;
165+ element . addEventListener ( "touchmove" , onMove , { passive : false } ) ;
166+
167+ return ( ) => {
168+ element . removeEventListener ( "mousemove" , onMove ) ;
169+ element . removeEventListener ( "touchmove" , onMove ) ;
170+ }
171+ // eslint demands 'onMove' to be in the dependencies array as well
172+ // eslint-disable-next-line react-hooks/exhaustive-deps
173+ } , [ containerRef ] ) ;
174+
175+ return < div ref = { containerRef }
151176 onTouchStart = { onPress } onTouchEnd = { onRelease } onMouseDown = { onPress } onMouseUp = { onRelease } >
152177 < svg width = { width } height = { width } >
153178 < OpenCircleSvg
0 commit comments