@react-aria/interactions 3.19.1 → 3.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/usePress.ts CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  import {disableTextSelection, restoreTextSelection} from './textSelection';
19
19
  import {DOMAttributes, FocusableElement, PressEvent as IPressEvent, PointerType, PressEvents} from '@react-types/shared';
20
- import {focusWithoutScrolling, isMac, isVirtualClick, isVirtualPointerEvent, mergeProps, openLink, useEffectEvent, useGlobalListeners, useSyncRef} from '@react-aria/utils';
20
+ import {focusWithoutScrolling, getOwnerDocument, getOwnerWindow, isMac, isVirtualClick, isVirtualPointerEvent, mergeProps, openLink, useEffectEvent, useGlobalListeners, useSyncRef} from '@react-aria/utils';
21
21
  import {PressResponderContext} from './context';
22
22
  import {RefObject, useContext, useEffect, useMemo, useRef, useState} from 'react';
23
23
 
@@ -53,13 +53,13 @@ interface PressState {
53
53
  activePointerId: any,
54
54
  target: FocusableElement | null,
55
55
  isOverTarget: boolean,
56
- pointerType: PointerType,
56
+ pointerType: PointerType | null,
57
57
  userSelect?: string,
58
58
  metaKeyEvents?: Map<string, KeyboardEvent>
59
59
  }
60
60
 
61
61
  interface EventBase {
62
- currentTarget: EventTarget,
62
+ currentTarget: EventTarget | null,
63
63
  shiftKey: boolean,
64
64
  ctrlKey: boolean,
65
65
  metaKey: boolean,
@@ -157,7 +157,7 @@ export function usePress(props: PressHookProps): PressResult {
157
157
  let triggerPressStart = useEffectEvent((originalEvent: EventBase, pointerType: PointerType) => {
158
158
  let state = ref.current;
159
159
  if (isDisabled || state.didFirePressStart) {
160
- return;
160
+ return false;
161
161
  }
162
162
 
163
163
  let shouldStopPropagation = true;
@@ -181,7 +181,7 @@ export function usePress(props: PressHookProps): PressResult {
181
181
  let triggerPressEnd = useEffectEvent((originalEvent: EventBase, pointerType: PointerType, wasPressed = true) => {
182
182
  let state = ref.current;
183
183
  if (!state.didFirePressStart) {
184
- return;
184
+ return false;
185
185
  }
186
186
 
187
187
  state.ignoreClickAfterPress = true;
@@ -214,7 +214,7 @@ export function usePress(props: PressHookProps): PressResult {
214
214
  let triggerPressUp = useEffectEvent((originalEvent: EventBase, pointerType: PointerType) => {
215
215
  let state = ref.current;
216
216
  if (isDisabled) {
217
- return;
217
+ return false;
218
218
  }
219
219
 
220
220
  if (onPressUp) {
@@ -230,8 +230,8 @@ export function usePress(props: PressHookProps): PressResult {
230
230
 
231
231
  let cancel = useEffectEvent((e: EventBase) => {
232
232
  let state = ref.current;
233
- if (state.isPressed) {
234
- if (state.isOverTarget) {
233
+ if (state.isPressed && state.target) {
234
+ if (state.isOverTarget && state.pointerType != null) {
235
235
  triggerPressEnd(createEvent(state.target, e), state.pointerType, false);
236
236
  }
237
237
  state.isPressed = false;
@@ -271,7 +271,7 @@ export function usePress(props: PressHookProps): PressResult {
271
271
 
272
272
  // Focus may move before the key up event, so register the event on the document
273
273
  // instead of the same element where the key down event occurred.
274
- addGlobalListener(document, 'keyup', onKeyUp, false);
274
+ addGlobalListener(getOwnerDocument(e.currentTarget), 'keyup', onKeyUp, false);
275
275
  }
276
276
 
277
277
  if (shouldStopPropagation) {
@@ -286,14 +286,14 @@ export function usePress(props: PressHookProps): PressResult {
286
286
  // https://bugs.webkit.org/show_bug.cgi?id=55291
287
287
  // https://bugzilla.mozilla.org/show_bug.cgi?id=1299553
288
288
  if (e.metaKey && isMac()) {
289
- state.metaKeyEvents.set(e.key, e.nativeEvent);
289
+ state.metaKeyEvents?.set(e.key, e.nativeEvent);
290
290
  }
291
291
  } else if (e.key === 'Meta') {
292
292
  state.metaKeyEvents = new Map();
293
293
  }
294
294
  },
295
295
  onKeyUp(e) {
296
- if (isValidKeyboardEvent(e.nativeEvent, e.currentTarget) && !e.repeat && e.currentTarget.contains(e.target as Element)) {
296
+ if (isValidKeyboardEvent(e.nativeEvent, e.currentTarget) && !e.repeat && e.currentTarget.contains(e.target as Element) && state.target) {
297
297
  triggerPressUp(createEvent(state.target, e), 'keyboard');
298
298
  }
299
299
  },
@@ -332,7 +332,7 @@ export function usePress(props: PressHookProps): PressResult {
332
332
  };
333
333
 
334
334
  let onKeyUp = (e: KeyboardEvent) => {
335
- if (state.isPressed && isValidKeyboardEvent(e, state.target)) {
335
+ if (state.isPressed && state.target && isValidKeyboardEvent(e, state.target)) {
336
336
  if (shouldPreventDefaultKeyboard(e.target as Element, e.key)) {
337
337
  e.preventDefault();
338
338
  }
@@ -362,9 +362,9 @@ export function usePress(props: PressHookProps): PressResult {
362
362
  // and those haven't received keyup events already, fire keyup events ourselves.
363
363
  // See comment above for more info about the macOS bug causing this.
364
364
  let events = state.metaKeyEvents;
365
- state.metaKeyEvents = null;
365
+ state.metaKeyEvents = undefined;
366
366
  for (let event of events.values()) {
367
- state.target.dispatchEvent(new KeyboardEvent('keyup', event));
367
+ state.target?.dispatchEvent(new KeyboardEvent('keyup', event));
368
368
  }
369
369
  }
370
370
  };
@@ -410,9 +410,9 @@ export function usePress(props: PressHookProps): PressResult {
410
410
 
411
411
  shouldStopPropagation = triggerPressStart(e, state.pointerType);
412
412
 
413
- addGlobalListener(document, 'pointermove', onPointerMove, false);
414
- addGlobalListener(document, 'pointerup', onPointerUp, false);
415
- addGlobalListener(document, 'pointercancel', onPointerCancel, false);
413
+ addGlobalListener(getOwnerDocument(e.currentTarget), 'pointermove', onPointerMove, false);
414
+ addGlobalListener(getOwnerDocument(e.currentTarget), 'pointerup', onPointerUp, false);
415
+ addGlobalListener(getOwnerDocument(e.currentTarget), 'pointercancel', onPointerCancel, false);
416
416
  }
417
417
 
418
418
  if (shouldStopPropagation) {
@@ -459,12 +459,12 @@ export function usePress(props: PressHookProps): PressResult {
459
459
  return;
460
460
  }
461
461
 
462
- if (isOverTarget(e, state.target)) {
463
- if (!state.isOverTarget) {
462
+ if (state.target && isOverTarget(e, state.target)) {
463
+ if (!state.isOverTarget && state.pointerType != null) {
464
464
  state.isOverTarget = true;
465
465
  triggerPressStart(createEvent(state.target, e), state.pointerType);
466
466
  }
467
- } else if (state.isOverTarget) {
467
+ } else if (state.target && state.isOverTarget && state.pointerType != null) {
468
468
  state.isOverTarget = false;
469
469
  triggerPressEnd(createEvent(state.target, e), state.pointerType, false);
470
470
  cancelOnPointerExit(e);
@@ -472,10 +472,10 @@ export function usePress(props: PressHookProps): PressResult {
472
472
  };
473
473
 
474
474
  let onPointerUp = (e: PointerEvent) => {
475
- if (e.pointerId === state.activePointerId && state.isPressed && e.button === 0) {
476
- if (isOverTarget(e, state.target)) {
475
+ if (e.pointerId === state.activePointerId && state.isPressed && e.button === 0 && state.target) {
476
+ if (isOverTarget(e, state.target) && state.pointerType != null) {
477
477
  triggerPressEnd(createEvent(state.target, e), state.pointerType);
478
- } else if (state.isOverTarget) {
478
+ } else if (state.isOverTarget && state.pointerType != null) {
479
479
  triggerPressEnd(createEvent(state.target, e), state.pointerType, false);
480
480
  }
481
481
 
@@ -534,7 +534,7 @@ export function usePress(props: PressHookProps): PressResult {
534
534
  e.stopPropagation();
535
535
  }
536
536
 
537
- addGlobalListener(document, 'mouseup', onMouseUp, false);
537
+ addGlobalListener(getOwnerDocument(e.currentTarget), 'mouseup', onMouseUp, false);
538
538
  };
539
539
 
540
540
  pressProps.onMouseEnter = (e) => {
@@ -543,7 +543,7 @@ export function usePress(props: PressHookProps): PressResult {
543
543
  }
544
544
 
545
545
  let shouldStopPropagation = true;
546
- if (state.isPressed && !state.ignoreEmulatedMouseEvents) {
546
+ if (state.isPressed && !state.ignoreEmulatedMouseEvents && state.pointerType != null) {
547
547
  state.isOverTarget = true;
548
548
  shouldStopPropagation = triggerPressStart(e, state.pointerType);
549
549
  }
@@ -559,7 +559,7 @@ export function usePress(props: PressHookProps): PressResult {
559
559
  }
560
560
 
561
561
  let shouldStopPropagation = true;
562
- if (state.isPressed && !state.ignoreEmulatedMouseEvents) {
562
+ if (state.isPressed && !state.ignoreEmulatedMouseEvents && state.pointerType != null) {
563
563
  state.isOverTarget = false;
564
564
  shouldStopPropagation = triggerPressEnd(e, state.pointerType, false);
565
565
  cancelOnPointerExit(e);
@@ -594,9 +594,9 @@ export function usePress(props: PressHookProps): PressResult {
594
594
  return;
595
595
  }
596
596
 
597
- if (isOverTarget(e, state.target)) {
597
+ if (state.target && isOverTarget(e, state.target) && state.pointerType != null) {
598
598
  triggerPressEnd(createEvent(state.target, e), state.pointerType);
599
- } else if (state.isOverTarget) {
599
+ } else if (state.target && state.isOverTarget && state.pointerType != null) {
600
600
  triggerPressEnd(createEvent(state.target, e), state.pointerType, false);
601
601
  }
602
602
 
@@ -634,7 +634,7 @@ export function usePress(props: PressHookProps): PressResult {
634
634
  e.stopPropagation();
635
635
  }
636
636
 
637
- addGlobalListener(window, 'scroll', onScroll, true);
637
+ addGlobalListener(getOwnerWindow(e.currentTarget), 'scroll', onScroll, true);
638
638
  };
639
639
 
640
640
  pressProps.onTouchMove = (e) => {
@@ -650,11 +650,11 @@ export function usePress(props: PressHookProps): PressResult {
650
650
  let touch = getTouchById(e.nativeEvent, state.activePointerId);
651
651
  let shouldStopPropagation = true;
652
652
  if (touch && isOverTarget(touch, e.currentTarget)) {
653
- if (!state.isOverTarget) {
653
+ if (!state.isOverTarget && state.pointerType != null) {
654
654
  state.isOverTarget = true;
655
655
  shouldStopPropagation = triggerPressStart(e, state.pointerType);
656
656
  }
657
- } else if (state.isOverTarget) {
657
+ } else if (state.isOverTarget && state.pointerType != null) {
658
658
  state.isOverTarget = false;
659
659
  shouldStopPropagation = triggerPressEnd(e, state.pointerType, false);
660
660
  cancelOnPointerExit(e);
@@ -677,10 +677,10 @@ export function usePress(props: PressHookProps): PressResult {
677
677
 
678
678
  let touch = getTouchById(e.nativeEvent, state.activePointerId);
679
679
  let shouldStopPropagation = true;
680
- if (touch && isOverTarget(touch, e.currentTarget)) {
680
+ if (touch && isOverTarget(touch, e.currentTarget) && state.pointerType != null) {
681
681
  triggerPressUp(e, state.pointerType);
682
682
  shouldStopPropagation = triggerPressEnd(e, state.pointerType);
683
- } else if (state.isOverTarget) {
683
+ } else if (state.isOverTarget && state.pointerType != null) {
684
684
  shouldStopPropagation = triggerPressEnd(e, state.pointerType, false);
685
685
  }
686
686
 
@@ -692,7 +692,7 @@ export function usePress(props: PressHookProps): PressResult {
692
692
  state.activePointerId = null;
693
693
  state.isOverTarget = false;
694
694
  state.ignoreEmulatedMouseEvents = true;
695
- if (!allowTextSelectionOnPress) {
695
+ if (state.target && !allowTextSelectionOnPress) {
696
696
  restoreTextSelection(state.target);
697
697
  }
698
698
  removeAllGlobalListeners();
@@ -750,7 +750,7 @@ export function usePress(props: PressHookProps): PressResult {
750
750
  return () => {
751
751
  if (!allowTextSelectionOnPress) {
752
752
  // eslint-disable-next-line react-hooks/exhaustive-deps
753
- restoreTextSelection(ref.current.target);
753
+ restoreTextSelection(ref.current.target ?? undefined);
754
754
  }
755
755
  };
756
756
  }, [allowTextSelectionOnPress]);
@@ -773,8 +773,8 @@ function isValidKeyboardEvent(event: KeyboardEvent, currentTarget: Element): boo
773
773
  // "Spacebar" is for IE 11
774
774
  return (
775
775
  (key === 'Enter' || key === ' ' || key === 'Spacebar' || code === 'Space') &&
776
- !((element instanceof HTMLInputElement && !isValidInputKey(element, key)) ||
777
- element instanceof HTMLTextAreaElement ||
776
+ !((element instanceof getOwnerWindow(element).HTMLInputElement && !isValidInputKey(element, key)) ||
777
+ element instanceof getOwnerWindow(element).HTMLTextAreaElement ||
778
778
  element.isContentEditable) &&
779
779
  // Links should only trigger with Enter key
780
780
  !((role === 'link' || (!role && isHTMLAnchorLink(element))) && key !== 'Enter')
@@ -830,8 +830,18 @@ interface EventPoint {
830
830
  }
831
831
 
832
832
  function getPointClientRect(point: EventPoint): Rect {
833
- let offsetX = (point.width / 2) || point.radiusX || 0;
834
- let offsetY = (point.height / 2) || point.radiusY || 0;
833
+ let offsetX = 0;
834
+ let offsetY = 0;
835
+ if (point.width !== undefined) {
836
+ offsetX = (point.width / 2);
837
+ } else if (point.radiusX !== undefined) {
838
+ offsetX = point.radiusX;
839
+ }
840
+ if (point.height !== undefined) {
841
+ offsetY = (point.height / 2);
842
+ } else if (point.radiusY !== undefined) {
843
+ offsetY = point.radiusY;
844
+ }
835
845
 
836
846
  return {
837
847
  top: point.clientY - offsetY,
@@ -37,5 +37,5 @@ export function useScrollWheel(props: ScrollWheelProps, ref: RefObject<HTMLEleme
37
37
  }
38
38
  }, [onScroll]);
39
39
 
40
- useEvent(ref, 'wheel', isDisabled ? null : onScrollHandler);
40
+ useEvent(ref, 'wheel', isDisabled ? undefined : onScrollHandler);
41
41
  }
package/src/utils.ts CHANGED
@@ -64,7 +64,7 @@ export class SyntheticFocusEvent<Target = Element> implements ReactFocusEvent<Ta
64
64
  export function useSyntheticBlurEvent<Target = Element>(onBlur: (e: ReactFocusEvent<Target>) => void) {
65
65
  let stateRef = useRef({
66
66
  isFocused: false,
67
- observer: null as MutationObserver
67
+ observer: null as MutationObserver | null
68
68
  });
69
69
 
70
70
  // Clean up MutationObserver on unmount. See below.
@@ -98,12 +98,12 @@ export function useSyntheticBlurEvent<Target = Element>(onBlur: (e: ReactFocusEv
98
98
  stateRef.current.isFocused = true;
99
99
 
100
100
  let target = e.target;
101
- let onBlurHandler = (e: FocusEvent) => {
101
+ let onBlurHandler: EventListenerOrEventListenerObject | null = (e) => {
102
102
  stateRef.current.isFocused = false;
103
103
 
104
104
  if (target.disabled) {
105
105
  // For backward compatibility, dispatch a (fake) React synthetic event.
106
- dispatchBlur(new SyntheticFocusEvent('blur', e));
106
+ dispatchBlur(new SyntheticFocusEvent('blur', e as FocusEvent));
107
107
  }
108
108
 
109
109
  // We no longer need the MutationObserver once the target is blurred.
@@ -117,7 +117,7 @@ export function useSyntheticBlurEvent<Target = Element>(onBlur: (e: ReactFocusEv
117
117
 
118
118
  stateRef.current.observer = new MutationObserver(() => {
119
119
  if (stateRef.current.isFocused && target.disabled) {
120
- stateRef.current.observer.disconnect();
120
+ stateRef.current.observer?.disconnect();
121
121
  let relatedTargetEl = target === document.activeElement ? null : document.activeElement;
122
122
  target.dispatchEvent(new FocusEvent('blur', {relatedTarget: relatedTargetEl}));
123
123
  target.dispatchEvent(new FocusEvent('focusout', {bubbles: true, relatedTarget: relatedTargetEl}));