@react-aria/interactions 3.27.0 → 3.27.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/dist/focusSafely.main.js +1 -0
- package/dist/focusSafely.main.js.map +1 -1
- package/dist/focusSafely.mjs +1 -0
- package/dist/focusSafely.module.js +1 -0
- package/dist/focusSafely.module.js.map +1 -1
- package/dist/main.js.map +1 -1
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/useFocus.main.js +4 -3
- package/dist/useFocus.main.js.map +1 -1
- package/dist/useFocus.mjs +5 -4
- package/dist/useFocus.module.js +5 -4
- package/dist/useFocus.module.js.map +1 -1
- package/dist/useFocusVisible.main.js +9 -7
- package/dist/useFocusVisible.main.js.map +1 -1
- package/dist/useFocusVisible.mjs +10 -8
- package/dist/useFocusVisible.module.js +10 -8
- package/dist/useFocusVisible.module.js.map +1 -1
- package/dist/useFocusWithin.main.js +8 -6
- package/dist/useFocusWithin.main.js.map +1 -1
- package/dist/useFocusWithin.mjs +9 -7
- package/dist/useFocusWithin.module.js +9 -7
- package/dist/useFocusWithin.module.js.map +1 -1
- package/dist/useHover.main.js +5 -5
- package/dist/useHover.main.js.map +1 -1
- package/dist/useHover.mjs +6 -6
- package/dist/useHover.module.js +6 -6
- package/dist/useHover.module.js.map +1 -1
- package/dist/useInteractOutside.main.js +5 -4
- package/dist/useInteractOutside.main.js.map +1 -1
- package/dist/useInteractOutside.mjs +6 -5
- package/dist/useInteractOutside.module.js +6 -5
- package/dist/useInteractOutside.module.js.map +1 -1
- package/dist/usePress.main.js +19 -19
- package/dist/usePress.main.js.map +1 -1
- package/dist/usePress.mjs +19 -19
- package/dist/usePress.module.js +19 -19
- package/dist/usePress.module.js.map +1 -1
- package/dist/utils.main.js +8 -7
- package/dist/utils.main.js.map +1 -1
- package/dist/utils.mjs +9 -8
- package/dist/utils.module.js +9 -8
- package/dist/utils.module.js.map +1 -1
- package/package.json +4 -4
- package/src/focusSafely.ts +4 -0
- package/src/index.ts +1 -1
- package/src/useFocus.ts +4 -3
- package/src/useFocusVisible.ts +12 -10
- package/src/useFocusWithin.ts +8 -6
- package/src/useHover.ts +6 -6
- package/src/useInteractOutside.ts +6 -5
- package/src/usePress.ts +29 -27
- package/src/utils.ts +12 -11
package/src/usePress.ts
CHANGED
|
@@ -72,7 +72,7 @@ interface PressState {
|
|
|
72
72
|
isOverTarget: boolean,
|
|
73
73
|
pointerType: PointerType | null,
|
|
74
74
|
userSelect?: string,
|
|
75
|
-
metaKeyEvents?: Map<string, KeyboardEvent>,
|
|
75
|
+
metaKeyEvents?: Map<string, globalThis.KeyboardEvent>,
|
|
76
76
|
disposables: Array<() => void>
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -339,12 +339,12 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
339
339
|
if (isElemKeyPressed) {
|
|
340
340
|
let onKeyUp = (e: KeyboardEvent) => {
|
|
341
341
|
if (state.isPressed && state.target && isValidKeyboardEvent(e, state.target)) {
|
|
342
|
-
if (shouldPreventDefaultKeyboard(getEventTarget(e), e.key)) {
|
|
342
|
+
if (shouldPreventDefaultKeyboard(getEventTarget(e) as Element, e.key)) {
|
|
343
343
|
e.preventDefault();
|
|
344
344
|
}
|
|
345
345
|
|
|
346
|
-
let target = getEventTarget(e);
|
|
347
|
-
let wasPressed = nodeContains(state.target,
|
|
346
|
+
let target = getEventTarget(e) as Element;
|
|
347
|
+
let wasPressed = nodeContains(state.target, target);
|
|
348
348
|
triggerPressEndEvent(createEvent(state.target, e), 'keyboard', wasPressed);
|
|
349
349
|
if (wasPressed) {
|
|
350
350
|
triggerSyntheticClickEvent(e, state.target);
|
|
@@ -379,8 +379,8 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
379
379
|
// instead of the same element where the key down event occurred. Make it capturing so that it will trigger
|
|
380
380
|
// before stopPropagation from useKeyboard on a child element may happen and thus we can still call triggerPress for the parent element.
|
|
381
381
|
let originalTarget = state.target;
|
|
382
|
-
let pressUp = (e) => {
|
|
383
|
-
if (originalTarget && isValidKeyboardEvent(e, originalTarget) && !e.repeat && nodeContains(originalTarget, getEventTarget(e)) && state.target) {
|
|
382
|
+
let pressUp = (e: KeyboardEvent) => {
|
|
383
|
+
if (originalTarget && isValidKeyboardEvent(e, originalTarget) && !e.repeat && nodeContains(originalTarget, getEventTarget(e) as Element) && state.target) {
|
|
384
384
|
triggerPressUpEvent(createEvent(state.target, e), 'keyboard');
|
|
385
385
|
}
|
|
386
386
|
};
|
|
@@ -398,7 +398,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
398
398
|
if (isPointerPressed === 'pointer') {
|
|
399
399
|
let onPointerUp = (e: PointerEvent) => {
|
|
400
400
|
if (e.pointerId === state.activePointerId && state.isPressed && e.button === 0 && state.target) {
|
|
401
|
-
if (nodeContains(state.target, getEventTarget(e)) && state.pointerType != null) {
|
|
401
|
+
if (nodeContains(state.target, getEventTarget(e) as Element) && state.pointerType != null) {
|
|
402
402
|
// Wait for onClick to fire onPress. This avoids browser issues when the DOM
|
|
403
403
|
// is mutated between onPointerUp and onClick, and is more compatible with third party libraries.
|
|
404
404
|
// https://github.com/adobe/react-spectrum/issues/1513
|
|
@@ -422,7 +422,9 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
422
422
|
}, 80);
|
|
423
423
|
// Use a capturing listener to track if a click occurred.
|
|
424
424
|
// If stopPropagation is called it may never reach our handler.
|
|
425
|
-
|
|
425
|
+
if (e.currentTarget) {
|
|
426
|
+
addGlobalListener(e.currentTarget, 'click', () => clicked = true, true);
|
|
427
|
+
}
|
|
426
428
|
state.disposables.push(() => clearTimeout(timeout));
|
|
427
429
|
} else {
|
|
428
430
|
cancelEvent(e);
|
|
@@ -471,7 +473,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
471
473
|
};
|
|
472
474
|
} else if (isPointerPressed === 'touch' && process.env.NODE_ENV === 'test') {
|
|
473
475
|
let onScroll = (e: Event) => {
|
|
474
|
-
if (state.isPressed && nodeContains(getEventTarget(e), state.target)) {
|
|
476
|
+
if (state.isPressed && nodeContains(getEventTarget(e) as Element, state.target)) {
|
|
475
477
|
cancelEvent({
|
|
476
478
|
currentTarget: state.target,
|
|
477
479
|
shiftKey: false,
|
|
@@ -493,8 +495,8 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
493
495
|
let state = ref.current;
|
|
494
496
|
let pressProps: DOMAttributes = {
|
|
495
497
|
onKeyDown(e) {
|
|
496
|
-
if (isValidKeyboardEvent(e.nativeEvent, e.currentTarget) && nodeContains(e.currentTarget, getEventTarget(e
|
|
497
|
-
if (shouldPreventDefaultKeyboard(getEventTarget(e
|
|
498
|
+
if (isValidKeyboardEvent(e.nativeEvent, e.currentTarget as Element) && nodeContains(e.currentTarget as Element, getEventTarget(e) as Element)) {
|
|
499
|
+
if (shouldPreventDefaultKeyboard(getEventTarget(e) as Element, e.key)) {
|
|
498
500
|
e.preventDefault();
|
|
499
501
|
}
|
|
500
502
|
|
|
@@ -529,7 +531,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
529
531
|
}
|
|
530
532
|
},
|
|
531
533
|
onClick(e) {
|
|
532
|
-
if (e && !nodeContains(e.currentTarget, getEventTarget(e
|
|
534
|
+
if (e && !nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
533
535
|
return;
|
|
534
536
|
}
|
|
535
537
|
|
|
@@ -568,7 +570,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
568
570
|
if (typeof PointerEvent !== 'undefined') {
|
|
569
571
|
pressProps.onPointerDown = (e) => {
|
|
570
572
|
// Only handle left clicks, and ignore events that bubbled through portals.
|
|
571
|
-
if (e.button !== 0 || !nodeContains(e.currentTarget, getEventTarget(e
|
|
573
|
+
if (e.button !== 0 || !nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
572
574
|
return;
|
|
573
575
|
}
|
|
574
576
|
|
|
@@ -599,7 +601,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
599
601
|
|
|
600
602
|
// Release pointer capture so that touch interactions can leave the original target.
|
|
601
603
|
// This enables onPointerLeave and onPointerEnter to fire.
|
|
602
|
-
let target = getEventTarget(e
|
|
604
|
+
let target = getEventTarget(e);
|
|
603
605
|
if ('releasePointerCapture' in target) {
|
|
604
606
|
if ('hasPointerCapture' in target) {
|
|
605
607
|
if (target.hasPointerCapture(e.pointerId)) {
|
|
@@ -617,7 +619,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
617
619
|
};
|
|
618
620
|
|
|
619
621
|
pressProps.onMouseDown = (e) => {
|
|
620
|
-
if (!nodeContains(e.currentTarget, getEventTarget(e
|
|
622
|
+
if (!nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
621
623
|
return;
|
|
622
624
|
}
|
|
623
625
|
|
|
@@ -635,7 +637,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
635
637
|
|
|
636
638
|
pressProps.onPointerUp = (e) => {
|
|
637
639
|
// iOS fires pointerup with zero width and height, so check the pointerType recorded during pointerdown.
|
|
638
|
-
if (!nodeContains(e.currentTarget, getEventTarget(e
|
|
640
|
+
if (!nodeContains(e.currentTarget, getEventTarget(e)) || state.pointerType === 'virtual') {
|
|
639
641
|
return;
|
|
640
642
|
}
|
|
641
643
|
|
|
@@ -662,7 +664,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
662
664
|
|
|
663
665
|
|
|
664
666
|
pressProps.onDragStart = (e) => {
|
|
665
|
-
if (!nodeContains(e.currentTarget, getEventTarget(e
|
|
667
|
+
if (!nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
666
668
|
return;
|
|
667
669
|
}
|
|
668
670
|
|
|
@@ -675,7 +677,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
675
677
|
|
|
676
678
|
pressProps.onMouseDown = (e) => {
|
|
677
679
|
// Only handle left clicks
|
|
678
|
-
if (e.button !== 0 || !nodeContains(e.currentTarget, getEventTarget(e
|
|
680
|
+
if (e.button !== 0 || !nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
679
681
|
return;
|
|
680
682
|
}
|
|
681
683
|
|
|
@@ -705,7 +707,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
705
707
|
};
|
|
706
708
|
|
|
707
709
|
pressProps.onMouseEnter = (e) => {
|
|
708
|
-
if (!nodeContains(e.currentTarget, getEventTarget(e
|
|
710
|
+
if (!nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
709
711
|
return;
|
|
710
712
|
}
|
|
711
713
|
|
|
@@ -721,7 +723,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
721
723
|
};
|
|
722
724
|
|
|
723
725
|
pressProps.onMouseLeave = (e) => {
|
|
724
|
-
if (!nodeContains(e.currentTarget, getEventTarget(e
|
|
726
|
+
if (!nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
725
727
|
return;
|
|
726
728
|
}
|
|
727
729
|
|
|
@@ -738,7 +740,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
738
740
|
};
|
|
739
741
|
|
|
740
742
|
pressProps.onMouseUp = (e) => {
|
|
741
|
-
if (!nodeContains(e.currentTarget, getEventTarget(e
|
|
743
|
+
if (!nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
742
744
|
return;
|
|
743
745
|
}
|
|
744
746
|
|
|
@@ -748,7 +750,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
748
750
|
};
|
|
749
751
|
|
|
750
752
|
pressProps.onTouchStart = (e) => {
|
|
751
|
-
if (!nodeContains(e.currentTarget, getEventTarget(e
|
|
753
|
+
if (!nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
752
754
|
return;
|
|
753
755
|
}
|
|
754
756
|
|
|
@@ -775,7 +777,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
775
777
|
};
|
|
776
778
|
|
|
777
779
|
pressProps.onTouchMove = (e) => {
|
|
778
|
-
if (!nodeContains(e.currentTarget, getEventTarget(e
|
|
780
|
+
if (!nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
779
781
|
return;
|
|
780
782
|
}
|
|
781
783
|
|
|
@@ -803,7 +805,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
803
805
|
};
|
|
804
806
|
|
|
805
807
|
pressProps.onTouchEnd = (e) => {
|
|
806
|
-
if (!nodeContains(e.currentTarget, getEventTarget(e
|
|
808
|
+
if (!nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
807
809
|
return;
|
|
808
810
|
}
|
|
809
811
|
|
|
@@ -838,7 +840,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
838
840
|
};
|
|
839
841
|
|
|
840
842
|
pressProps.onTouchCancel = (e) => {
|
|
841
|
-
if (!nodeContains(e.currentTarget, getEventTarget(e
|
|
843
|
+
if (!nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
842
844
|
return;
|
|
843
845
|
}
|
|
844
846
|
|
|
@@ -849,7 +851,7 @@ export function usePress(props: PressHookProps): PressResult {
|
|
|
849
851
|
};
|
|
850
852
|
|
|
851
853
|
pressProps.onDragStart = (e) => {
|
|
852
|
-
if (!nodeContains(e.currentTarget, getEventTarget(e
|
|
854
|
+
if (!nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
853
855
|
return;
|
|
854
856
|
}
|
|
855
857
|
|
|
@@ -922,7 +924,7 @@ function isHTMLAnchorLink(target: Element): target is HTMLAnchorElement {
|
|
|
922
924
|
return target.tagName === 'A' && target.hasAttribute('href');
|
|
923
925
|
}
|
|
924
926
|
|
|
925
|
-
function isValidKeyboardEvent(event: KeyboardEvent, currentTarget: Element): boolean {
|
|
927
|
+
function isValidKeyboardEvent(event: KeyboardEvent | globalThis.KeyboardEvent, currentTarget: Element): boolean {
|
|
926
928
|
const {key, code} = event;
|
|
927
929
|
const element = currentTarget as HTMLElement;
|
|
928
930
|
const role = element.getAttribute('role');
|
package/src/utils.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import {FocusableElement} from '@react-types/shared';
|
|
14
|
-
import {focusWithoutScrolling, getOwnerWindow, isFocusable, useLayoutEffect} from '@react-aria/utils';
|
|
14
|
+
import {focusWithoutScrolling, getActiveElement, getEventTarget, getOwnerWindow, isFocusable, useLayoutEffect} from '@react-aria/utils';
|
|
15
15
|
import {FocusEvent as ReactFocusEvent, SyntheticEvent, useCallback, useRef} from 'react';
|
|
16
16
|
|
|
17
17
|
// Turn a native event into a React synthetic event.
|
|
@@ -54,15 +54,16 @@ export function useSyntheticBlurEvent<Target extends Element = Element>(onBlur:
|
|
|
54
54
|
// Most browsers fire a native focusout event in this case, except for Firefox. In that case, we use a
|
|
55
55
|
// MutationObserver to watch for the disabled attribute, and dispatch these events ourselves.
|
|
56
56
|
// For browsers that do, focusout fires before the MutationObserver, so onBlur should not fire twice.
|
|
57
|
+
let eventTarget = getEventTarget(e);
|
|
57
58
|
if (
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
eventTarget instanceof HTMLButtonElement ||
|
|
60
|
+
eventTarget instanceof HTMLInputElement ||
|
|
61
|
+
eventTarget instanceof HTMLTextAreaElement ||
|
|
62
|
+
eventTarget instanceof HTMLSelectElement
|
|
62
63
|
) {
|
|
63
64
|
stateRef.current.isFocused = true;
|
|
64
65
|
|
|
65
|
-
let target =
|
|
66
|
+
let target = eventTarget;
|
|
66
67
|
let onBlurHandler: EventListenerOrEventListenerObject | null = (e) => {
|
|
67
68
|
stateRef.current.isFocused = false;
|
|
68
69
|
|
|
@@ -84,7 +85,7 @@ export function useSyntheticBlurEvent<Target extends Element = Element>(onBlur:
|
|
|
84
85
|
stateRef.current.observer = new MutationObserver(() => {
|
|
85
86
|
if (stateRef.current.isFocused && target.disabled) {
|
|
86
87
|
stateRef.current.observer?.disconnect();
|
|
87
|
-
let relatedTargetEl = target ===
|
|
88
|
+
let relatedTargetEl = target === getActiveElement() ? null : getActiveElement();
|
|
88
89
|
target.dispatchEvent(new FocusEvent('blur', {relatedTarget: relatedTargetEl}));
|
|
89
90
|
target.dispatchEvent(new FocusEvent('focusout', {bubbles: true, relatedTarget: relatedTargetEl}));
|
|
90
91
|
}
|
|
@@ -117,13 +118,13 @@ export function preventFocus(target: FocusableElement | null): (() => void) | un
|
|
|
117
118
|
ignoreFocusEvent = true;
|
|
118
119
|
let isRefocusing = false;
|
|
119
120
|
let onBlur = (e: FocusEvent) => {
|
|
120
|
-
if (e
|
|
121
|
+
if (getEventTarget(e) === activeElement || isRefocusing) {
|
|
121
122
|
e.stopImmediatePropagation();
|
|
122
123
|
}
|
|
123
124
|
};
|
|
124
125
|
|
|
125
126
|
let onFocusOut = (e: FocusEvent) => {
|
|
126
|
-
if (e
|
|
127
|
+
if (getEventTarget(e) === activeElement || isRefocusing) {
|
|
127
128
|
e.stopImmediatePropagation();
|
|
128
129
|
|
|
129
130
|
// If there was no focusable ancestor, we don't expect a focus event.
|
|
@@ -137,13 +138,13 @@ export function preventFocus(target: FocusableElement | null): (() => void) | un
|
|
|
137
138
|
};
|
|
138
139
|
|
|
139
140
|
let onFocus = (e: FocusEvent) => {
|
|
140
|
-
if (e
|
|
141
|
+
if (getEventTarget(e) === target || isRefocusing) {
|
|
141
142
|
e.stopImmediatePropagation();
|
|
142
143
|
}
|
|
143
144
|
};
|
|
144
145
|
|
|
145
146
|
let onFocusIn = (e: FocusEvent) => {
|
|
146
|
-
if (e
|
|
147
|
+
if (getEventTarget(e) === target || isRefocusing) {
|
|
147
148
|
e.stopImmediatePropagation();
|
|
148
149
|
|
|
149
150
|
if (!isRefocusing) {
|