Skip to content

Commit 10bac54

Browse files
authored
Feat/event coordinates (#6482)
* feat(use-press/longpress): add x and y coordinates
1 parent 74fc719 commit 10bac54

File tree

7 files changed

+969
-189
lines changed

7 files changed

+969
-189
lines changed

packages/@react-aria/interactions/src/useHover.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,3 @@ export function useHover(props: HoverProps): HoverResult {
204204
isHovered
205205
};
206206
}
207-

packages/@react-aria/interactions/src/usePress.ts

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {chain, focusWithoutScrolling, getOwnerDocument, getOwnerWindow, isMac, i
1919
import {disableTextSelection, restoreTextSelection} from './textSelection';
2020
import {DOMAttributes, FocusableElement, PressEvent as IPressEvent, PointerType, PressEvents} from '@react-types/shared';
2121
import {PressResponderContext} from './context';
22-
import {RefObject, useContext, useEffect, useMemo, useRef, useState} from 'react';
22+
import {RefObject, TouchEvent as RTouchEvent, useContext, useEffect, useMemo, useRef, useState} from 'react';
2323

2424
export interface PressProps extends PressEvents {
2525
/** Whether the target is in a controlled press state (e.g. an overlay it triggers is open). */
@@ -63,7 +63,10 @@ interface EventBase {
6363
shiftKey: boolean,
6464
ctrlKey: boolean,
6565
metaKey: boolean,
66-
altKey: boolean
66+
altKey: boolean,
67+
clientX?: number,
68+
clientY?: number,
69+
targetTouches?: Array<{clientX?: number, clientY?: number}>
6770
}
6871

6972
export interface PressResult {
@@ -94,16 +97,37 @@ class PressEvent implements IPressEvent {
9497
ctrlKey: boolean;
9598
metaKey: boolean;
9699
altKey: boolean;
100+
x: number;
101+
y: number;
97102
#shouldStopPropagation = true;
98103

99-
constructor(type: IPressEvent['type'], pointerType: PointerType, originalEvent: EventBase) {
104+
constructor(type: IPressEvent['type'], pointerType: PointerType, originalEvent: EventBase, state?: PressState) {
105+
let currentTarget = state?.target ?? originalEvent.currentTarget;
106+
const rect: DOMRect | undefined = (currentTarget as Element)?.getBoundingClientRect();
107+
let x, y = 0;
108+
let clientX, clientY: number | null = null;
109+
if (originalEvent.clientX != null && originalEvent.clientY != null) {
110+
clientX = originalEvent.clientX;
111+
clientY = originalEvent.clientY;
112+
}
113+
if (rect) {
114+
if (clientX != null && clientY != null) {
115+
x = clientX - rect.left;
116+
y = clientY - rect.top;
117+
} else {
118+
x = rect.width / 2;
119+
y = rect.height / 2;
120+
}
121+
}
100122
this.type = type;
101123
this.pointerType = pointerType;
102124
this.target = originalEvent.currentTarget as Element;
103125
this.shiftKey = originalEvent.shiftKey;
104126
this.metaKey = originalEvent.metaKey;
105127
this.ctrlKey = originalEvent.ctrlKey;
106128
this.altKey = originalEvent.altKey;
129+
this.x = x;
130+
this.y = y;
107131
}
108132

109133
continuePropagation() {
@@ -628,7 +652,7 @@ export function usePress(props: PressHookProps): PressResult {
628652
disableTextSelection(state.target);
629653
}
630654

631-
let shouldStopPropagation = triggerPressStart(e, state.pointerType);
655+
let shouldStopPropagation = triggerPressStart(createTouchEvent(state.target, e), state.pointerType);
632656
if (shouldStopPropagation) {
633657
e.stopPropagation();
634658
}
@@ -651,12 +675,12 @@ export function usePress(props: PressHookProps): PressResult {
651675
if (touch && isOverTarget(touch, e.currentTarget)) {
652676
if (!state.isOverTarget && state.pointerType != null) {
653677
state.isOverTarget = true;
654-
shouldStopPropagation = triggerPressStart(e, state.pointerType);
678+
shouldStopPropagation = triggerPressStart(createTouchEvent(state.target!, e), state.pointerType);
655679
}
656680
} else if (state.isOverTarget && state.pointerType != null) {
657681
state.isOverTarget = false;
658-
shouldStopPropagation = triggerPressEnd(e, state.pointerType, false);
659-
cancelOnPointerExit(e);
682+
shouldStopPropagation = triggerPressEnd(createTouchEvent(state.target!, e), state.pointerType, false);
683+
cancelOnPointerExit(createTouchEvent(state.target!, e));
660684
}
661685

662686
if (shouldStopPropagation) {
@@ -677,10 +701,10 @@ export function usePress(props: PressHookProps): PressResult {
677701
let touch = getTouchById(e.nativeEvent, state.activePointerId);
678702
let shouldStopPropagation = true;
679703
if (touch && isOverTarget(touch, e.currentTarget) && state.pointerType != null) {
680-
triggerPressUp(e, state.pointerType);
681-
shouldStopPropagation = triggerPressEnd(e, state.pointerType);
704+
triggerPressUp(createTouchEvent(state.target!, e), state.pointerType);
705+
shouldStopPropagation = triggerPressEnd(createTouchEvent(state.target!, e), state.pointerType);
682706
} else if (state.isOverTarget && state.pointerType != null) {
683-
shouldStopPropagation = triggerPressEnd(e, state.pointerType, false);
707+
shouldStopPropagation = triggerPressEnd(createTouchEvent(state.target!, e), state.pointerType, false);
684708
}
685709

686710
if (shouldStopPropagation) {
@@ -704,7 +728,7 @@ export function usePress(props: PressHookProps): PressResult {
704728

705729
e.stopPropagation();
706730
if (state.isPressed) {
707-
cancel(e);
731+
cancel(createTouchEvent(state.target!, e));
708732
}
709733
};
710734

@@ -802,13 +826,35 @@ function getTouchById(
802826
return null;
803827
}
804828

829+
function createTouchEvent(target: FocusableElement, e: RTouchEvent<FocusableElement>): EventBase {
830+
let clientX = 0;
831+
let clientY = 0;
832+
if (e.targetTouches && e.targetTouches.length === 1) {
833+
clientX = e.targetTouches[0].clientX;
834+
clientY = e.targetTouches[0].clientY;
835+
}
836+
return {
837+
currentTarget: target,
838+
shiftKey: e.shiftKey,
839+
ctrlKey: e.ctrlKey,
840+
metaKey: e.metaKey,
841+
altKey: e.altKey,
842+
clientX,
843+
clientY
844+
};
845+
}
846+
805847
function createEvent(target: FocusableElement, e: EventBase): EventBase {
848+
let clientX = e.clientX;
849+
let clientY = e.clientY;
806850
return {
807851
currentTarget: target,
808852
shiftKey: e.shiftKey,
809853
ctrlKey: e.ctrlKey,
810854
metaKey: e.metaKey,
811-
altKey: e.altKey
855+
altKey: e.altKey,
856+
clientX,
857+
clientY
812858
};
813859
}
814860

0 commit comments

Comments
 (0)