@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/dist/utils.main.js
CHANGED
|
@@ -61,9 +61,10 @@ function $625cf83917e112ad$export$715c682d09d639cc(onBlur) {
|
|
|
61
61
|
// Most browsers fire a native focusout event in this case, except for Firefox. In that case, we use a
|
|
62
62
|
// MutationObserver to watch for the disabled attribute, and dispatch these events ourselves.
|
|
63
63
|
// For browsers that do, focusout fires before the MutationObserver, so onBlur should not fire twice.
|
|
64
|
-
|
|
64
|
+
let eventTarget = (0, $iJhOP$reactariautils.getEventTarget)(e);
|
|
65
|
+
if (eventTarget instanceof HTMLButtonElement || eventTarget instanceof HTMLInputElement || eventTarget instanceof HTMLTextAreaElement || eventTarget instanceof HTMLSelectElement) {
|
|
65
66
|
stateRef.current.isFocused = true;
|
|
66
|
-
let target =
|
|
67
|
+
let target = eventTarget;
|
|
67
68
|
let onBlurHandler = (e)=>{
|
|
68
69
|
stateRef.current.isFocused = false;
|
|
69
70
|
if (target.disabled) {
|
|
@@ -84,7 +85,7 @@ function $625cf83917e112ad$export$715c682d09d639cc(onBlur) {
|
|
|
84
85
|
if (stateRef.current.isFocused && target.disabled) {
|
|
85
86
|
var _stateRef_current_observer;
|
|
86
87
|
(_stateRef_current_observer = stateRef.current.observer) === null || _stateRef_current_observer === void 0 ? void 0 : _stateRef_current_observer.disconnect();
|
|
87
|
-
let relatedTargetEl = target ===
|
|
88
|
+
let relatedTargetEl = target === (0, $iJhOP$reactariautils.getActiveElement)() ? null : (0, $iJhOP$reactariautils.getActiveElement)();
|
|
88
89
|
target.dispatchEvent(new FocusEvent('blur', {
|
|
89
90
|
relatedTarget: relatedTargetEl
|
|
90
91
|
}));
|
|
@@ -115,10 +116,10 @@ function $625cf83917e112ad$export$cabe61c495ee3649(target) {
|
|
|
115
116
|
$625cf83917e112ad$export$fda7da73ab5d4c48 = true;
|
|
116
117
|
let isRefocusing = false;
|
|
117
118
|
let onBlur = (e)=>{
|
|
118
|
-
if (e
|
|
119
|
+
if ((0, $iJhOP$reactariautils.getEventTarget)(e) === activeElement || isRefocusing) e.stopImmediatePropagation();
|
|
119
120
|
};
|
|
120
121
|
let onFocusOut = (e)=>{
|
|
121
|
-
if (e
|
|
122
|
+
if ((0, $iJhOP$reactariautils.getEventTarget)(e) === activeElement || isRefocusing) {
|
|
122
123
|
e.stopImmediatePropagation();
|
|
123
124
|
// If there was no focusable ancestor, we don't expect a focus event.
|
|
124
125
|
// Re-focus the original active element here.
|
|
@@ -130,10 +131,10 @@ function $625cf83917e112ad$export$cabe61c495ee3649(target) {
|
|
|
130
131
|
}
|
|
131
132
|
};
|
|
132
133
|
let onFocus = (e)=>{
|
|
133
|
-
if (e
|
|
134
|
+
if ((0, $iJhOP$reactariautils.getEventTarget)(e) === target || isRefocusing) e.stopImmediatePropagation();
|
|
134
135
|
};
|
|
135
136
|
let onFocusIn = (e)=>{
|
|
136
|
-
if (e
|
|
137
|
+
if ((0, $iJhOP$reactariautils.getEventTarget)(e) === target || isRefocusing) {
|
|
137
138
|
e.stopImmediatePropagation();
|
|
138
139
|
if (!isRefocusing) {
|
|
139
140
|
isRefocusing = true;
|
package/dist/utils.main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;AAOM,SAAS,yCAA+C,WAAkB;IAC/E,IAAI,QAAQ;IACZ,MAAM,WAAW,GAAG;IACpB,MAAM,kBAAkB,GAAG,IAAM,MAAM,gBAAgB;IACvD,2FAA2F;IAC3F,MAAM,oBAAoB,GAAG,IAAM,AAAC,MAAc,YAAY;IAC9D,MAAM,OAAO,GAAG,KAAO;IACvB,OAAO;AACT;AAEO,SAAS,0CAAe,KAAY,EAAE,MAAe;IAC1D,OAAO,cAAc,CAAC,OAAO,UAAU;QAAC,OAAO;IAAM;IACrD,OAAO,cAAc,CAAC,OAAO,iBAAiB;QAAC,OAAO;IAAM;AAC9D;AAEO,SAAS,0CAAwD,MAA4C;IAClH,IAAI,WAAW,CAAA,GAAA,mBAAK,EAAE;QACpB,WAAW;QACX,UAAU;IACZ;IAEA,mDAAmD;IAEnD,CAAA,GAAA,qCAAc,EAAE;QACd,MAAM,QAAQ,SAAS,OAAO;QAC9B,OAAO;YACL,IAAI,MAAM,QAAQ,EAAE;gBAClB,MAAM,QAAQ,CAAC,UAAU;gBACzB,MAAM,QAAQ,GAAG;YACnB;QACF;IACF,GAAG,EAAE;IAEL,wDAAwD;IACxD,OAAO,CAAA,GAAA,wBAAU,EAAE,CAAC;QAClB,wGAAwG;QACxG,sGAAsG;QACtG,6FAA6F;QAC7F,qGAAqG;QACrG,
|
|
1
|
+
{"mappings":"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","sources":["packages/@react-aria/interactions/src/utils.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {FocusableElement} from '@react-types/shared';\nimport {focusWithoutScrolling, getActiveElement, getEventTarget, getOwnerWindow, isFocusable, useLayoutEffect} from '@react-aria/utils';\nimport {FocusEvent as ReactFocusEvent, SyntheticEvent, useCallback, useRef} from 'react';\n\n// Turn a native event into a React synthetic event.\nexport function createSyntheticEvent<E extends SyntheticEvent>(nativeEvent: Event): E {\n let event = nativeEvent as any as E;\n event.nativeEvent = nativeEvent;\n event.isDefaultPrevented = () => event.defaultPrevented;\n // cancelBubble is technically deprecated in the spec, but still supported in all browsers.\n event.isPropagationStopped = () => (event as any).cancelBubble;\n event.persist = () => {};\n return event;\n}\n\nexport function setEventTarget(event: Event, target: Element): void {\n Object.defineProperty(event, 'target', {value: target});\n Object.defineProperty(event, 'currentTarget', {value: target});\n}\n\nexport function useSyntheticBlurEvent<Target extends Element = Element>(onBlur: (e: ReactFocusEvent<Target>) => void): (e: ReactFocusEvent<Target>) => void {\n let stateRef = useRef({\n isFocused: false,\n observer: null as MutationObserver | null\n });\n\n // Clean up MutationObserver on unmount. See below.\n\n useLayoutEffect(() => {\n const state = stateRef.current;\n return () => {\n if (state.observer) {\n state.observer.disconnect();\n state.observer = null;\n }\n };\n }, []);\n\n // This function is called during a React onFocus event.\n return useCallback((e: ReactFocusEvent<Target>) => {\n // React does not fire onBlur when an element is disabled. https://github.com/facebook/react/issues/9142\n // Most browsers fire a native focusout event in this case, except for Firefox. In that case, we use a\n // MutationObserver to watch for the disabled attribute, and dispatch these events ourselves.\n // For browsers that do, focusout fires before the MutationObserver, so onBlur should not fire twice.\n let eventTarget = getEventTarget(e);\n if (\n eventTarget instanceof HTMLButtonElement ||\n eventTarget instanceof HTMLInputElement ||\n eventTarget instanceof HTMLTextAreaElement ||\n eventTarget instanceof HTMLSelectElement\n ) {\n stateRef.current.isFocused = true;\n\n let target = eventTarget;\n let onBlurHandler: EventListenerOrEventListenerObject | null = (e) => {\n stateRef.current.isFocused = false;\n\n if (target.disabled) {\n // For backward compatibility, dispatch a (fake) React synthetic event.\n let event = createSyntheticEvent<ReactFocusEvent<Target>>(e);\n onBlur?.(event);\n }\n\n // We no longer need the MutationObserver once the target is blurred.\n if (stateRef.current.observer) {\n stateRef.current.observer.disconnect();\n stateRef.current.observer = null;\n }\n };\n\n target.addEventListener('focusout', onBlurHandler, {once: true});\n\n stateRef.current.observer = new MutationObserver(() => {\n if (stateRef.current.isFocused && target.disabled) {\n stateRef.current.observer?.disconnect();\n let relatedTargetEl = target === getActiveElement() ? null : getActiveElement();\n target.dispatchEvent(new FocusEvent('blur', {relatedTarget: relatedTargetEl}));\n target.dispatchEvent(new FocusEvent('focusout', {bubbles: true, relatedTarget: relatedTargetEl}));\n }\n });\n\n stateRef.current.observer.observe(target, {attributes: true, attributeFilter: ['disabled']});\n }\n }, [onBlur]);\n}\n\nexport let ignoreFocusEvent = false;\n\n/**\n * This function prevents the next focus event fired on `target`, without using `event.preventDefault()`.\n * It works by waiting for the series of focus events to occur, and reverts focus back to where it was before.\n * It also makes these events mostly non-observable by using a capturing listener on the window and stopping propagation.\n */\nexport function preventFocus(target: FocusableElement | null): (() => void) | undefined {\n // The browser will focus the nearest focusable ancestor of our target.\n while (target && !isFocusable(target)) {\n target = target.parentElement;\n }\n\n let window = getOwnerWindow(target);\n let activeElement = window.document.activeElement as FocusableElement | null;\n if (!activeElement || activeElement === target) {\n return;\n }\n\n ignoreFocusEvent = true;\n let isRefocusing = false;\n let onBlur = (e: FocusEvent) => {\n if (getEventTarget(e) === activeElement || isRefocusing) {\n e.stopImmediatePropagation();\n }\n };\n\n let onFocusOut = (e: FocusEvent) => {\n if (getEventTarget(e) === activeElement || isRefocusing) {\n e.stopImmediatePropagation();\n\n // If there was no focusable ancestor, we don't expect a focus event.\n // Re-focus the original active element here.\n if (!target && !isRefocusing) {\n isRefocusing = true;\n focusWithoutScrolling(activeElement);\n cleanup();\n }\n }\n };\n\n let onFocus = (e: FocusEvent) => {\n if (getEventTarget(e) === target || isRefocusing) {\n e.stopImmediatePropagation();\n }\n };\n\n let onFocusIn = (e: FocusEvent) => {\n if (getEventTarget(e) === target || isRefocusing) {\n e.stopImmediatePropagation();\n\n if (!isRefocusing) {\n isRefocusing = true;\n focusWithoutScrolling(activeElement);\n cleanup();\n }\n }\n };\n\n window.addEventListener('blur', onBlur, true);\n window.addEventListener('focusout', onFocusOut, true);\n window.addEventListener('focusin', onFocusIn, true);\n window.addEventListener('focus', onFocus, true);\n\n let cleanup = () => {\n cancelAnimationFrame(raf);\n window.removeEventListener('blur', onBlur, true);\n window.removeEventListener('focusout', onFocusOut, true);\n window.removeEventListener('focusin', onFocusIn, true);\n window.removeEventListener('focus', onFocus, true);\n ignoreFocusEvent = false;\n isRefocusing = false;\n };\n\n let raf = requestAnimationFrame(cleanup);\n return cleanup;\n}\n"],"names":[],"version":3,"file":"utils.main.js.map"}
|
package/dist/utils.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {useLayoutEffect as $6dfIe$useLayoutEffect, isFocusable as $6dfIe$isFocusable, getOwnerWindow as $6dfIe$getOwnerWindow, focusWithoutScrolling as $6dfIe$focusWithoutScrolling} from "@react-aria/utils";
|
|
1
|
+
import {useLayoutEffect as $6dfIe$useLayoutEffect, getEventTarget as $6dfIe$getEventTarget, getActiveElement as $6dfIe$getActiveElement, isFocusable as $6dfIe$isFocusable, getOwnerWindow as $6dfIe$getOwnerWindow, focusWithoutScrolling as $6dfIe$focusWithoutScrolling} from "@react-aria/utils";
|
|
2
2
|
import {useRef as $6dfIe$useRef, useCallback as $6dfIe$useCallback} from "react";
|
|
3
3
|
|
|
4
4
|
/*
|
|
@@ -51,9 +51,10 @@ function $8a9cb279dc87e130$export$715c682d09d639cc(onBlur) {
|
|
|
51
51
|
// Most browsers fire a native focusout event in this case, except for Firefox. In that case, we use a
|
|
52
52
|
// MutationObserver to watch for the disabled attribute, and dispatch these events ourselves.
|
|
53
53
|
// For browsers that do, focusout fires before the MutationObserver, so onBlur should not fire twice.
|
|
54
|
-
|
|
54
|
+
let eventTarget = (0, $6dfIe$getEventTarget)(e);
|
|
55
|
+
if (eventTarget instanceof HTMLButtonElement || eventTarget instanceof HTMLInputElement || eventTarget instanceof HTMLTextAreaElement || eventTarget instanceof HTMLSelectElement) {
|
|
55
56
|
stateRef.current.isFocused = true;
|
|
56
|
-
let target =
|
|
57
|
+
let target = eventTarget;
|
|
57
58
|
let onBlurHandler = (e)=>{
|
|
58
59
|
stateRef.current.isFocused = false;
|
|
59
60
|
if (target.disabled) {
|
|
@@ -74,7 +75,7 @@ function $8a9cb279dc87e130$export$715c682d09d639cc(onBlur) {
|
|
|
74
75
|
if (stateRef.current.isFocused && target.disabled) {
|
|
75
76
|
var _stateRef_current_observer;
|
|
76
77
|
(_stateRef_current_observer = stateRef.current.observer) === null || _stateRef_current_observer === void 0 ? void 0 : _stateRef_current_observer.disconnect();
|
|
77
|
-
let relatedTargetEl = target ===
|
|
78
|
+
let relatedTargetEl = target === (0, $6dfIe$getActiveElement)() ? null : (0, $6dfIe$getActiveElement)();
|
|
78
79
|
target.dispatchEvent(new FocusEvent('blur', {
|
|
79
80
|
relatedTarget: relatedTargetEl
|
|
80
81
|
}));
|
|
@@ -105,10 +106,10 @@ function $8a9cb279dc87e130$export$cabe61c495ee3649(target) {
|
|
|
105
106
|
$8a9cb279dc87e130$export$fda7da73ab5d4c48 = true;
|
|
106
107
|
let isRefocusing = false;
|
|
107
108
|
let onBlur = (e)=>{
|
|
108
|
-
if (e
|
|
109
|
+
if ((0, $6dfIe$getEventTarget)(e) === activeElement || isRefocusing) e.stopImmediatePropagation();
|
|
109
110
|
};
|
|
110
111
|
let onFocusOut = (e)=>{
|
|
111
|
-
if (e
|
|
112
|
+
if ((0, $6dfIe$getEventTarget)(e) === activeElement || isRefocusing) {
|
|
112
113
|
e.stopImmediatePropagation();
|
|
113
114
|
// If there was no focusable ancestor, we don't expect a focus event.
|
|
114
115
|
// Re-focus the original active element here.
|
|
@@ -120,10 +121,10 @@ function $8a9cb279dc87e130$export$cabe61c495ee3649(target) {
|
|
|
120
121
|
}
|
|
121
122
|
};
|
|
122
123
|
let onFocus = (e)=>{
|
|
123
|
-
if (e
|
|
124
|
+
if ((0, $6dfIe$getEventTarget)(e) === target || isRefocusing) e.stopImmediatePropagation();
|
|
124
125
|
};
|
|
125
126
|
let onFocusIn = (e)=>{
|
|
126
|
-
if (e
|
|
127
|
+
if ((0, $6dfIe$getEventTarget)(e) === target || isRefocusing) {
|
|
127
128
|
e.stopImmediatePropagation();
|
|
128
129
|
if (!isRefocusing) {
|
|
129
130
|
isRefocusing = true;
|
package/dist/utils.module.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {useLayoutEffect as $6dfIe$useLayoutEffect, isFocusable as $6dfIe$isFocusable, getOwnerWindow as $6dfIe$getOwnerWindow, focusWithoutScrolling as $6dfIe$focusWithoutScrolling} from "@react-aria/utils";
|
|
1
|
+
import {useLayoutEffect as $6dfIe$useLayoutEffect, getEventTarget as $6dfIe$getEventTarget, getActiveElement as $6dfIe$getActiveElement, isFocusable as $6dfIe$isFocusable, getOwnerWindow as $6dfIe$getOwnerWindow, focusWithoutScrolling as $6dfIe$focusWithoutScrolling} from "@react-aria/utils";
|
|
2
2
|
import {useRef as $6dfIe$useRef, useCallback as $6dfIe$useCallback} from "react";
|
|
3
3
|
|
|
4
4
|
/*
|
|
@@ -51,9 +51,10 @@ function $8a9cb279dc87e130$export$715c682d09d639cc(onBlur) {
|
|
|
51
51
|
// Most browsers fire a native focusout event in this case, except for Firefox. In that case, we use a
|
|
52
52
|
// MutationObserver to watch for the disabled attribute, and dispatch these events ourselves.
|
|
53
53
|
// For browsers that do, focusout fires before the MutationObserver, so onBlur should not fire twice.
|
|
54
|
-
|
|
54
|
+
let eventTarget = (0, $6dfIe$getEventTarget)(e);
|
|
55
|
+
if (eventTarget instanceof HTMLButtonElement || eventTarget instanceof HTMLInputElement || eventTarget instanceof HTMLTextAreaElement || eventTarget instanceof HTMLSelectElement) {
|
|
55
56
|
stateRef.current.isFocused = true;
|
|
56
|
-
let target =
|
|
57
|
+
let target = eventTarget;
|
|
57
58
|
let onBlurHandler = (e)=>{
|
|
58
59
|
stateRef.current.isFocused = false;
|
|
59
60
|
if (target.disabled) {
|
|
@@ -74,7 +75,7 @@ function $8a9cb279dc87e130$export$715c682d09d639cc(onBlur) {
|
|
|
74
75
|
if (stateRef.current.isFocused && target.disabled) {
|
|
75
76
|
var _stateRef_current_observer;
|
|
76
77
|
(_stateRef_current_observer = stateRef.current.observer) === null || _stateRef_current_observer === void 0 ? void 0 : _stateRef_current_observer.disconnect();
|
|
77
|
-
let relatedTargetEl = target ===
|
|
78
|
+
let relatedTargetEl = target === (0, $6dfIe$getActiveElement)() ? null : (0, $6dfIe$getActiveElement)();
|
|
78
79
|
target.dispatchEvent(new FocusEvent('blur', {
|
|
79
80
|
relatedTarget: relatedTargetEl
|
|
80
81
|
}));
|
|
@@ -105,10 +106,10 @@ function $8a9cb279dc87e130$export$cabe61c495ee3649(target) {
|
|
|
105
106
|
$8a9cb279dc87e130$export$fda7da73ab5d4c48 = true;
|
|
106
107
|
let isRefocusing = false;
|
|
107
108
|
let onBlur = (e)=>{
|
|
108
|
-
if (e
|
|
109
|
+
if ((0, $6dfIe$getEventTarget)(e) === activeElement || isRefocusing) e.stopImmediatePropagation();
|
|
109
110
|
};
|
|
110
111
|
let onFocusOut = (e)=>{
|
|
111
|
-
if (e
|
|
112
|
+
if ((0, $6dfIe$getEventTarget)(e) === activeElement || isRefocusing) {
|
|
112
113
|
e.stopImmediatePropagation();
|
|
113
114
|
// If there was no focusable ancestor, we don't expect a focus event.
|
|
114
115
|
// Re-focus the original active element here.
|
|
@@ -120,10 +121,10 @@ function $8a9cb279dc87e130$export$cabe61c495ee3649(target) {
|
|
|
120
121
|
}
|
|
121
122
|
};
|
|
122
123
|
let onFocus = (e)=>{
|
|
123
|
-
if (e
|
|
124
|
+
if ((0, $6dfIe$getEventTarget)(e) === target || isRefocusing) e.stopImmediatePropagation();
|
|
124
125
|
};
|
|
125
126
|
let onFocusIn = (e)=>{
|
|
126
|
-
if (e
|
|
127
|
+
if ((0, $6dfIe$getEventTarget)(e) === target || isRefocusing) {
|
|
127
128
|
e.stopImmediatePropagation();
|
|
128
129
|
if (!isRefocusing) {
|
|
129
130
|
isRefocusing = true;
|
package/dist/utils.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;AAAA;;;;;;;;;;CAUC;;AAOM,SAAS,yCAA+C,WAAkB;IAC/E,IAAI,QAAQ;IACZ,MAAM,WAAW,GAAG;IACpB,MAAM,kBAAkB,GAAG,IAAM,MAAM,gBAAgB;IACvD,2FAA2F;IAC3F,MAAM,oBAAoB,GAAG,IAAM,AAAC,MAAc,YAAY;IAC9D,MAAM,OAAO,GAAG,KAAO;IACvB,OAAO;AACT;AAEO,SAAS,0CAAe,KAAY,EAAE,MAAe;IAC1D,OAAO,cAAc,CAAC,OAAO,UAAU;QAAC,OAAO;IAAM;IACrD,OAAO,cAAc,CAAC,OAAO,iBAAiB;QAAC,OAAO;IAAM;AAC9D;AAEO,SAAS,0CAAwD,MAA4C;IAClH,IAAI,WAAW,CAAA,GAAA,aAAK,EAAE;QACpB,WAAW;QACX,UAAU;IACZ;IAEA,mDAAmD;IAEnD,CAAA,GAAA,sBAAc,EAAE;QACd,MAAM,QAAQ,SAAS,OAAO;QAC9B,OAAO;YACL,IAAI,MAAM,QAAQ,EAAE;gBAClB,MAAM,QAAQ,CAAC,UAAU;gBACzB,MAAM,QAAQ,GAAG;YACnB;QACF;IACF,GAAG,EAAE;IAEL,wDAAwD;IACxD,OAAO,CAAA,GAAA,kBAAU,EAAE,CAAC;QAClB,wGAAwG;QACxG,sGAAsG;QACtG,6FAA6F;QAC7F,qGAAqG;QACrG,
|
|
1
|
+
{"mappings":"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","sources":["packages/@react-aria/interactions/src/utils.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {FocusableElement} from '@react-types/shared';\nimport {focusWithoutScrolling, getActiveElement, getEventTarget, getOwnerWindow, isFocusable, useLayoutEffect} from '@react-aria/utils';\nimport {FocusEvent as ReactFocusEvent, SyntheticEvent, useCallback, useRef} from 'react';\n\n// Turn a native event into a React synthetic event.\nexport function createSyntheticEvent<E extends SyntheticEvent>(nativeEvent: Event): E {\n let event = nativeEvent as any as E;\n event.nativeEvent = nativeEvent;\n event.isDefaultPrevented = () => event.defaultPrevented;\n // cancelBubble is technically deprecated in the spec, but still supported in all browsers.\n event.isPropagationStopped = () => (event as any).cancelBubble;\n event.persist = () => {};\n return event;\n}\n\nexport function setEventTarget(event: Event, target: Element): void {\n Object.defineProperty(event, 'target', {value: target});\n Object.defineProperty(event, 'currentTarget', {value: target});\n}\n\nexport function useSyntheticBlurEvent<Target extends Element = Element>(onBlur: (e: ReactFocusEvent<Target>) => void): (e: ReactFocusEvent<Target>) => void {\n let stateRef = useRef({\n isFocused: false,\n observer: null as MutationObserver | null\n });\n\n // Clean up MutationObserver on unmount. See below.\n\n useLayoutEffect(() => {\n const state = stateRef.current;\n return () => {\n if (state.observer) {\n state.observer.disconnect();\n state.observer = null;\n }\n };\n }, []);\n\n // This function is called during a React onFocus event.\n return useCallback((e: ReactFocusEvent<Target>) => {\n // React does not fire onBlur when an element is disabled. https://github.com/facebook/react/issues/9142\n // Most browsers fire a native focusout event in this case, except for Firefox. In that case, we use a\n // MutationObserver to watch for the disabled attribute, and dispatch these events ourselves.\n // For browsers that do, focusout fires before the MutationObserver, so onBlur should not fire twice.\n let eventTarget = getEventTarget(e);\n if (\n eventTarget instanceof HTMLButtonElement ||\n eventTarget instanceof HTMLInputElement ||\n eventTarget instanceof HTMLTextAreaElement ||\n eventTarget instanceof HTMLSelectElement\n ) {\n stateRef.current.isFocused = true;\n\n let target = eventTarget;\n let onBlurHandler: EventListenerOrEventListenerObject | null = (e) => {\n stateRef.current.isFocused = false;\n\n if (target.disabled) {\n // For backward compatibility, dispatch a (fake) React synthetic event.\n let event = createSyntheticEvent<ReactFocusEvent<Target>>(e);\n onBlur?.(event);\n }\n\n // We no longer need the MutationObserver once the target is blurred.\n if (stateRef.current.observer) {\n stateRef.current.observer.disconnect();\n stateRef.current.observer = null;\n }\n };\n\n target.addEventListener('focusout', onBlurHandler, {once: true});\n\n stateRef.current.observer = new MutationObserver(() => {\n if (stateRef.current.isFocused && target.disabled) {\n stateRef.current.observer?.disconnect();\n let relatedTargetEl = target === getActiveElement() ? null : getActiveElement();\n target.dispatchEvent(new FocusEvent('blur', {relatedTarget: relatedTargetEl}));\n target.dispatchEvent(new FocusEvent('focusout', {bubbles: true, relatedTarget: relatedTargetEl}));\n }\n });\n\n stateRef.current.observer.observe(target, {attributes: true, attributeFilter: ['disabled']});\n }\n }, [onBlur]);\n}\n\nexport let ignoreFocusEvent = false;\n\n/**\n * This function prevents the next focus event fired on `target`, without using `event.preventDefault()`.\n * It works by waiting for the series of focus events to occur, and reverts focus back to where it was before.\n * It also makes these events mostly non-observable by using a capturing listener on the window and stopping propagation.\n */\nexport function preventFocus(target: FocusableElement | null): (() => void) | undefined {\n // The browser will focus the nearest focusable ancestor of our target.\n while (target && !isFocusable(target)) {\n target = target.parentElement;\n }\n\n let window = getOwnerWindow(target);\n let activeElement = window.document.activeElement as FocusableElement | null;\n if (!activeElement || activeElement === target) {\n return;\n }\n\n ignoreFocusEvent = true;\n let isRefocusing = false;\n let onBlur = (e: FocusEvent) => {\n if (getEventTarget(e) === activeElement || isRefocusing) {\n e.stopImmediatePropagation();\n }\n };\n\n let onFocusOut = (e: FocusEvent) => {\n if (getEventTarget(e) === activeElement || isRefocusing) {\n e.stopImmediatePropagation();\n\n // If there was no focusable ancestor, we don't expect a focus event.\n // Re-focus the original active element here.\n if (!target && !isRefocusing) {\n isRefocusing = true;\n focusWithoutScrolling(activeElement);\n cleanup();\n }\n }\n };\n\n let onFocus = (e: FocusEvent) => {\n if (getEventTarget(e) === target || isRefocusing) {\n e.stopImmediatePropagation();\n }\n };\n\n let onFocusIn = (e: FocusEvent) => {\n if (getEventTarget(e) === target || isRefocusing) {\n e.stopImmediatePropagation();\n\n if (!isRefocusing) {\n isRefocusing = true;\n focusWithoutScrolling(activeElement);\n cleanup();\n }\n }\n };\n\n window.addEventListener('blur', onBlur, true);\n window.addEventListener('focusout', onFocusOut, true);\n window.addEventListener('focusin', onFocusIn, true);\n window.addEventListener('focus', onFocus, true);\n\n let cleanup = () => {\n cancelAnimationFrame(raf);\n window.removeEventListener('blur', onBlur, true);\n window.removeEventListener('focusout', onFocusOut, true);\n window.removeEventListener('focusin', onFocusIn, true);\n window.removeEventListener('focus', onFocus, true);\n ignoreFocusEvent = false;\n isRefocusing = false;\n };\n\n let raf = requestAnimationFrame(cleanup);\n return cleanup;\n}\n"],"names":[],"version":3,"file":"utils.module.js.map"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-aria/interactions",
|
|
3
|
-
"version": "3.27.
|
|
3
|
+
"version": "3.27.1",
|
|
4
4
|
"description": "Spectrum UI components in React",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@react-aria/ssr": "^3.9.10",
|
|
30
|
-
"@react-aria/utils": "^3.33.
|
|
30
|
+
"@react-aria/utils": "^3.33.1",
|
|
31
31
|
"@react-stately/flags": "^3.1.2",
|
|
32
|
-
"@react-types/shared": "^3.33.
|
|
32
|
+
"@react-types/shared": "^3.33.1",
|
|
33
33
|
"@swc/helpers": "^0.5.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"publishConfig": {
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "8df187370053aa35f553cb388ad670f65e1ab371"
|
|
43
43
|
}
|
package/src/focusSafely.ts
CHANGED
|
@@ -24,6 +24,10 @@ import {getInteractionModality} from './useFocusVisible';
|
|
|
24
24
|
* as page scrolling and screen reader issues with CSS transitions.
|
|
25
25
|
*/
|
|
26
26
|
export function focusSafely(element: FocusableElement): void {
|
|
27
|
+
if (!element.isConnected) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
27
31
|
// If the user is interacting with a virtual cursor, e.g. screen reader, then
|
|
28
32
|
// wait until after any animated transitions that are currently occurring on
|
|
29
33
|
// the page before shifting focus. This avoids issues with VoiceOver on iOS
|
package/src/index.ts
CHANGED
|
@@ -41,7 +41,7 @@ export type {HoverProps, HoverResult} from './useHover';
|
|
|
41
41
|
export type {InteractOutsideProps} from './useInteractOutside';
|
|
42
42
|
export type {KeyboardProps, KeyboardResult} from './useKeyboard';
|
|
43
43
|
export type {PressProps, PressHookProps, PressResult} from './usePress';
|
|
44
|
-
export type {PressEvent, PressEvents, MoveStartEvent, MoveMoveEvent, MoveEndEvent, MoveEvents, HoverEvent, HoverEvents, FocusEvents, KeyboardEvents} from '@react-types/shared';
|
|
44
|
+
export type {PressEvent, PressEvents, LongPressEvent, MoveStartEvent, MoveMoveEvent, MoveEndEvent, MoveEvent, MoveEvents, HoverEvent, HoverEvents, FocusEvents, KeyboardEvents} from '@react-types/shared';
|
|
45
45
|
export type {MoveResult} from './useMove';
|
|
46
46
|
export type {LongPressProps, LongPressResult} from './useLongPress';
|
|
47
47
|
export type {ScrollWheelProps} from './useScrollWheel';
|
package/src/useFocus.ts
CHANGED
|
@@ -43,7 +43,7 @@ export function useFocus<Target extends FocusableElement = FocusableElement>(pro
|
|
|
43
43
|
} = props;
|
|
44
44
|
|
|
45
45
|
const onBlur: FocusProps<Target>['onBlur'] = useCallback((e: FocusEvent<Target>) => {
|
|
46
|
-
if (e
|
|
46
|
+
if (getEventTarget(e) === e.currentTarget) {
|
|
47
47
|
if (onBlurProp) {
|
|
48
48
|
onBlurProp(e);
|
|
49
49
|
}
|
|
@@ -63,9 +63,10 @@ export function useFocus<Target extends FocusableElement = FocusableElement>(pro
|
|
|
63
63
|
// Double check that document.activeElement actually matches e.target in case a previously chained
|
|
64
64
|
// focus handler already moved focus somewhere else.
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
let eventTarget = getEventTarget(e);
|
|
67
|
+
const ownerDocument = getOwnerDocument(eventTarget);
|
|
67
68
|
const activeElement = ownerDocument ? getActiveElement(ownerDocument) : getActiveElement();
|
|
68
|
-
if (
|
|
69
|
+
if (eventTarget === e.currentTarget && eventTarget === activeElement) {
|
|
69
70
|
if (onFocusProp) {
|
|
70
71
|
onFocusProp(e);
|
|
71
72
|
}
|
package/src/useFocusVisible.ts
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// NOTICE file in the root directory of this source tree.
|
|
16
16
|
// See https://github.com/facebook/react/tree/cc7c1aece46a6b69b41958d731e0fd27c94bfc6c/packages/react-interactions
|
|
17
17
|
|
|
18
|
-
import {getOwnerDocument, getOwnerWindow, isMac, isVirtualClick, openLink} from '@react-aria/utils';
|
|
18
|
+
import {getActiveElement, getEventTarget, getOwnerDocument, getOwnerWindow, isMac, isVirtualClick, openLink} from '@react-aria/utils';
|
|
19
19
|
import {ignoreFocusEvent} from './utils';
|
|
20
20
|
import {PointerType} from '@react-types/shared';
|
|
21
21
|
import {useEffect, useState} from 'react';
|
|
@@ -98,7 +98,7 @@ function handleFocusEvent(e: FocusEvent) {
|
|
|
98
98
|
// Firefox fires two extra focus events when the user first clicks into an iframe:
|
|
99
99
|
// first on the window, then on the document. We ignore these events so they don't
|
|
100
100
|
// cause keyboard focus rings to appear.
|
|
101
|
-
if (e
|
|
101
|
+
if (getEventTarget(e) === window || getEventTarget(e) === document || ignoreFocusEvent || !e.isTrusted) {
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
104
104
|
|
|
@@ -302,18 +302,20 @@ const nonTextInputTypes = new Set([
|
|
|
302
302
|
* focus visible style can be properly set.
|
|
303
303
|
*/
|
|
304
304
|
function isKeyboardFocusEvent(isTextInput: boolean, modality: Modality, e: HandlerEvent) {
|
|
305
|
-
let document = getOwnerDocument(e
|
|
306
|
-
|
|
307
|
-
const
|
|
308
|
-
const
|
|
309
|
-
const
|
|
305
|
+
let document = getOwnerDocument(e ? getEventTarget(e) as Element : undefined);
|
|
306
|
+
let eventTarget = e ? getEventTarget(e) as Element : undefined;
|
|
307
|
+
const IHTMLInputElement = typeof window !== 'undefined' ? getOwnerWindow(eventTarget).HTMLInputElement : HTMLInputElement;
|
|
308
|
+
const IHTMLTextAreaElement = typeof window !== 'undefined' ? getOwnerWindow(eventTarget).HTMLTextAreaElement : HTMLTextAreaElement;
|
|
309
|
+
const IHTMLElement = typeof window !== 'undefined' ? getOwnerWindow(eventTarget).HTMLElement : HTMLElement;
|
|
310
|
+
const IKeyboardEvent = typeof window !== 'undefined' ? getOwnerWindow(eventTarget).KeyboardEvent : KeyboardEvent;
|
|
310
311
|
|
|
311
312
|
// For keyboard events that occur on a non-input element that will move focus into input element (aka ArrowLeft going from Datepicker button to the main input group)
|
|
312
313
|
// we need to rely on the user passing isTextInput into here. This way we can skip toggling focus visiblity for said input element
|
|
314
|
+
let activeElement = getActiveElement(document);
|
|
313
315
|
isTextInput = isTextInput ||
|
|
314
|
-
(
|
|
315
|
-
|
|
316
|
-
(
|
|
316
|
+
(activeElement instanceof IHTMLInputElement && !nonTextInputTypes.has(activeElement.type)) ||
|
|
317
|
+
activeElement instanceof IHTMLTextAreaElement ||
|
|
318
|
+
(activeElement instanceof IHTMLElement && activeElement.isContentEditable);
|
|
317
319
|
return !(isTextInput && modality === 'keyboard' && e instanceof IKeyboardEvent && !FOCUS_VISIBLE_INPUT_KEYS[e.key]);
|
|
318
320
|
}
|
|
319
321
|
|
package/src/useFocusWithin.ts
CHANGED
|
@@ -54,7 +54,7 @@ export function useFocusWithin(props: FocusWithinProps): FocusWithinResult {
|
|
|
54
54
|
|
|
55
55
|
let onBlur = useCallback((e: FocusEvent) => {
|
|
56
56
|
// Ignore events bubbling through portals.
|
|
57
|
-
if (!nodeContains(e.currentTarget, e
|
|
57
|
+
if (!nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -78,15 +78,16 @@ export function useFocusWithin(props: FocusWithinProps): FocusWithinResult {
|
|
|
78
78
|
let onSyntheticFocus = useSyntheticBlurEvent(onBlur);
|
|
79
79
|
let onFocus = useCallback((e: FocusEvent) => {
|
|
80
80
|
// Ignore events bubbling through portals.
|
|
81
|
-
if (!nodeContains(e.currentTarget, e
|
|
81
|
+
if (!nodeContains(e.currentTarget, getEventTarget(e))) {
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
// Double check that document.activeElement actually matches e.target in case a previously chained
|
|
86
86
|
// focus handler already moved focus somewhere else.
|
|
87
|
-
|
|
87
|
+
let eventTarget = getEventTarget(e);
|
|
88
|
+
const ownerDocument = getOwnerDocument(eventTarget);
|
|
88
89
|
const activeElement = getActiveElement(ownerDocument);
|
|
89
|
-
if (!state.current.isFocusWithin && activeElement ===
|
|
90
|
+
if (!state.current.isFocusWithin && activeElement === eventTarget) {
|
|
90
91
|
if (onFocusWithin) {
|
|
91
92
|
onFocusWithin(e);
|
|
92
93
|
}
|
|
@@ -103,8 +104,9 @@ export function useFocusWithin(props: FocusWithinProps): FocusWithinResult {
|
|
|
103
104
|
// can manually fire onBlur.
|
|
104
105
|
let currentTarget = e.currentTarget;
|
|
105
106
|
addGlobalListener(ownerDocument, 'focus', e => {
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
let eventTarget = getEventTarget(e);
|
|
108
|
+
if (state.current.isFocusWithin && !nodeContains(currentTarget, eventTarget as Element)) {
|
|
109
|
+
let nativeEvent = new ownerDocument.defaultView!.FocusEvent('blur', {relatedTarget: eventTarget});
|
|
108
110
|
setEventTarget(nativeEvent, currentTarget);
|
|
109
111
|
let event = createSyntheticEvent<FocusEvent>(nativeEvent);
|
|
110
112
|
onBlur(event);
|
package/src/useHover.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// See https://github.com/facebook/react/tree/cc7c1aece46a6b69b41958d731e0fd27c94bfc6c/packages/react-interactions
|
|
17
17
|
|
|
18
18
|
import {DOMAttributes, HoverEvents} from '@react-types/shared';
|
|
19
|
-
import {getOwnerDocument, nodeContains, useGlobalListeners} from '@react-aria/utils';
|
|
19
|
+
import {getEventTarget, getOwnerDocument, nodeContains, useGlobalListeners} from '@react-aria/utils';
|
|
20
20
|
import {useEffect, useMemo, useRef, useState} from 'react';
|
|
21
21
|
|
|
22
22
|
export interface HoverProps extends HoverEvents {
|
|
@@ -108,7 +108,7 @@ export function useHover(props: HoverProps): HoverResult {
|
|
|
108
108
|
let {hoverProps, triggerHoverEnd} = useMemo(() => {
|
|
109
109
|
let triggerHoverStart = (event, pointerType) => {
|
|
110
110
|
state.pointerType = pointerType;
|
|
111
|
-
if (isDisabled || pointerType === 'touch' || state.isHovered || !nodeContains(event.currentTarget, event
|
|
111
|
+
if (isDisabled || pointerType === 'touch' || state.isHovered || !nodeContains(event.currentTarget, getEventTarget(event) as Element)) {
|
|
112
112
|
return;
|
|
113
113
|
}
|
|
114
114
|
|
|
@@ -120,8 +120,8 @@ export function useHover(props: HoverProps): HoverResult {
|
|
|
120
120
|
// even though the originally hovered target may have shrunk in size so it is no longer hovered.
|
|
121
121
|
// However, a pointerover event will be fired on the new target the mouse is over.
|
|
122
122
|
// In Chrome this happens immediately. In Safari and Firefox, it happens upon moving the mouse one pixel.
|
|
123
|
-
addGlobalListener(getOwnerDocument(event
|
|
124
|
-
if (state.isHovered && state.target && !nodeContains(state.target, e
|
|
123
|
+
addGlobalListener(getOwnerDocument(getEventTarget(event) as Element), 'pointerover', e => {
|
|
124
|
+
if (state.isHovered && state.target && !nodeContains(state.target, getEventTarget(e) as Element)) {
|
|
125
125
|
triggerHoverEnd(e, e.pointerType);
|
|
126
126
|
}
|
|
127
127
|
}, {capture: true});
|
|
@@ -180,7 +180,7 @@ export function useHover(props: HoverProps): HoverResult {
|
|
|
180
180
|
};
|
|
181
181
|
|
|
182
182
|
hoverProps.onPointerLeave = (e) => {
|
|
183
|
-
if (!isDisabled && nodeContains(e.currentTarget, e
|
|
183
|
+
if (!isDisabled && nodeContains(e.currentTarget, getEventTarget(e) as Element)) {
|
|
184
184
|
triggerHoverEnd(e, e.pointerType);
|
|
185
185
|
}
|
|
186
186
|
};
|
|
@@ -198,7 +198,7 @@ export function useHover(props: HoverProps): HoverResult {
|
|
|
198
198
|
};
|
|
199
199
|
|
|
200
200
|
hoverProps.onMouseLeave = (e) => {
|
|
201
|
-
if (!isDisabled && nodeContains(e.currentTarget, e
|
|
201
|
+
if (!isDisabled && nodeContains(e.currentTarget, getEventTarget(e) as Element)) {
|
|
202
202
|
triggerHoverEnd(e, 'mouse');
|
|
203
203
|
}
|
|
204
204
|
};
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// NOTICE file in the root directory of this source tree.
|
|
16
16
|
// See https://github.com/facebook/react/tree/cc7c1aece46a6b69b41958d731e0fd27c94bfc6c/packages/react-interactions
|
|
17
17
|
|
|
18
|
-
import {getOwnerDocument, nodeContains, useEffectEvent} from '@react-aria/utils';
|
|
18
|
+
import {getEventTarget, getOwnerDocument, nodeContains, useEffectEvent} from '@react-aria/utils';
|
|
19
19
|
import {RefObject} from '@react-types/shared';
|
|
20
20
|
import {useEffect, useRef} from 'react';
|
|
21
21
|
|
|
@@ -118,14 +118,15 @@ function isValidEvent(event, ref) {
|
|
|
118
118
|
if (event.button > 0) {
|
|
119
119
|
return false;
|
|
120
120
|
}
|
|
121
|
-
|
|
121
|
+
let target = getEventTarget(event) as Element;
|
|
122
|
+
if (target) {
|
|
122
123
|
// if the event target is no longer in the document, ignore
|
|
123
|
-
const ownerDocument =
|
|
124
|
-
if (!ownerDocument || !nodeContains(ownerDocument.documentElement,
|
|
124
|
+
const ownerDocument = target.ownerDocument;
|
|
125
|
+
if (!ownerDocument || !nodeContains(ownerDocument.documentElement, target)) {
|
|
125
126
|
return false;
|
|
126
127
|
}
|
|
127
128
|
// If the target is within a top layer element (e.g. toasts), ignore.
|
|
128
|
-
if (
|
|
129
|
+
if (target.closest('[data-react-aria-top-layer]')) {
|
|
129
130
|
return false;
|
|
130
131
|
}
|
|
131
132
|
}
|