UNPKG

14.2 kBJavaScriptView Raw
1var $cR3F8$reactariautils = require("@react-aria/utils");
2var $cR3F8$react = require("react");
3var $cR3F8$reactariassr = require("@react-aria/ssr");
4
5
6function $parcel$export(e, n, v, s) {
7 Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
8}
9
10$parcel$export(module.exports, "addWindowFocusTracking", () => $e77252a287ef94ab$export$2f1888112f558a7d);
11$parcel$export(module.exports, "isFocusVisible", () => $e77252a287ef94ab$export$b9b3dfddab17db27);
12$parcel$export(module.exports, "getInteractionModality", () => $e77252a287ef94ab$export$630ff653c5ada6a9);
13$parcel$export(module.exports, "setInteractionModality", () => $e77252a287ef94ab$export$8397ddfc504fdb9a);
14$parcel$export(module.exports, "useInteractionModality", () => $e77252a287ef94ab$export$98e20ec92f614cfe);
15$parcel$export(module.exports, "useFocusVisible", () => $e77252a287ef94ab$export$ffd9e5021c1fb2d6);
16$parcel$export(module.exports, "useFocusVisibleListener", () => $e77252a287ef94ab$export$ec71b4b83ac08ec3);
17/*
18 * Copyright 2020 Adobe. All rights reserved.
19 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
20 * you may not use this file except in compliance with the License. You may obtain a copy
21 * of the License at http://www.apache.org/licenses/LICENSE-2.0
22 *
23 * Unless required by applicable law or agreed to in writing, software distributed under
24 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
25 * OF ANY KIND, either express or implied. See the License for the specific language
26 * governing permissions and limitations under the License.
27 */ // Portions of the code in this file are based on code from react.
28// Original licensing for the following can be found in the
29// NOTICE file in the root directory of this source tree.
30// See https://github.com/facebook/react/tree/cc7c1aece46a6b69b41958d731e0fd27c94bfc6c/packages/react-interactions
31
32
33
34let $e77252a287ef94ab$var$currentModality = null;
35let $e77252a287ef94ab$var$changeHandlers = new Set();
36let $e77252a287ef94ab$export$d90243b58daecda7 = new Map(); // We use a map here to support setting event listeners across multiple document objects.
37let $e77252a287ef94ab$var$hasEventBeforeFocus = false;
38let $e77252a287ef94ab$var$hasBlurredWindowRecently = false;
39// Only Tab or Esc keys will make focus visible on text input elements
40const $e77252a287ef94ab$var$FOCUS_VISIBLE_INPUT_KEYS = {
41 Tab: true,
42 Escape: true
43};
44function $e77252a287ef94ab$var$triggerChangeHandlers(modality, e) {
45 for (let handler of $e77252a287ef94ab$var$changeHandlers)handler(modality, e);
46}
47/**
48 * Helper function to determine if a KeyboardEvent is unmodified and could make keyboard focus styles visible.
49 */ function $e77252a287ef94ab$var$isValidKey(e) {
50 // Control and Shift keys trigger when navigating back to the tab with keyboard.
51 return !(e.metaKey || !(0, $cR3F8$reactariautils.isMac)() && e.altKey || e.ctrlKey || e.key === 'Control' || e.key === 'Shift' || e.key === 'Meta');
52}
53function $e77252a287ef94ab$var$handleKeyboardEvent(e) {
54 $e77252a287ef94ab$var$hasEventBeforeFocus = true;
55 if ($e77252a287ef94ab$var$isValidKey(e)) {
56 $e77252a287ef94ab$var$currentModality = 'keyboard';
57 $e77252a287ef94ab$var$triggerChangeHandlers('keyboard', e);
58 }
59}
60function $e77252a287ef94ab$var$handlePointerEvent(e) {
61 $e77252a287ef94ab$var$currentModality = 'pointer';
62 if (e.type === 'mousedown' || e.type === 'pointerdown') {
63 $e77252a287ef94ab$var$hasEventBeforeFocus = true;
64 $e77252a287ef94ab$var$triggerChangeHandlers('pointer', e);
65 }
66}
67function $e77252a287ef94ab$var$handleClickEvent(e) {
68 if ((0, $cR3F8$reactariautils.isVirtualClick)(e)) {
69 $e77252a287ef94ab$var$hasEventBeforeFocus = true;
70 $e77252a287ef94ab$var$currentModality = 'virtual';
71 }
72}
73function $e77252a287ef94ab$var$handleFocusEvent(e) {
74 // Firefox fires two extra focus events when the user first clicks into an iframe:
75 // first on the window, then on the document. We ignore these events so they don't
76 // cause keyboard focus rings to appear.
77 if (e.target === window || e.target === document) return;
78 // If a focus event occurs without a preceding keyboard or pointer event, switch to virtual modality.
79 // This occurs, for example, when navigating a form with the next/previous buttons on iOS.
80 if (!$e77252a287ef94ab$var$hasEventBeforeFocus && !$e77252a287ef94ab$var$hasBlurredWindowRecently) {
81 $e77252a287ef94ab$var$currentModality = 'virtual';
82 $e77252a287ef94ab$var$triggerChangeHandlers('virtual', e);
83 }
84 $e77252a287ef94ab$var$hasEventBeforeFocus = false;
85 $e77252a287ef94ab$var$hasBlurredWindowRecently = false;
86}
87function $e77252a287ef94ab$var$handleWindowBlur() {
88 // When the window is blurred, reset state. This is necessary when tabbing out of the window,
89 // for example, since a subsequent focus event won't be fired.
90 $e77252a287ef94ab$var$hasEventBeforeFocus = false;
91 $e77252a287ef94ab$var$hasBlurredWindowRecently = true;
92}
93/**
94 * Setup global event listeners to control when keyboard focus style should be visible.
95 */ function $e77252a287ef94ab$var$setupGlobalFocusEvents(element) {
96 if (typeof window === 'undefined' || $e77252a287ef94ab$export$d90243b58daecda7.get((0, $cR3F8$reactariautils.getOwnerWindow)(element))) return;
97 const windowObject = (0, $cR3F8$reactariautils.getOwnerWindow)(element);
98 const documentObject = (0, $cR3F8$reactariautils.getOwnerDocument)(element);
99 // Programmatic focus() calls shouldn't affect the current input modality.
100 // However, we need to detect other cases when a focus event occurs without
101 // a preceding user event (e.g. screen reader focus). Overriding the focus
102 // method on HTMLElement.prototype is a bit hacky, but works.
103 let focus = windowObject.HTMLElement.prototype.focus;
104 windowObject.HTMLElement.prototype.focus = function() {
105 $e77252a287ef94ab$var$hasEventBeforeFocus = true;
106 focus.apply(this, arguments);
107 };
108 documentObject.addEventListener('keydown', $e77252a287ef94ab$var$handleKeyboardEvent, true);
109 documentObject.addEventListener('keyup', $e77252a287ef94ab$var$handleKeyboardEvent, true);
110 documentObject.addEventListener('click', $e77252a287ef94ab$var$handleClickEvent, true);
111 // Register focus events on the window so they are sure to happen
112 // before React's event listeners (registered on the document).
113 windowObject.addEventListener('focus', $e77252a287ef94ab$var$handleFocusEvent, true);
114 windowObject.addEventListener('blur', $e77252a287ef94ab$var$handleWindowBlur, false);
115 if (typeof PointerEvent !== 'undefined') {
116 documentObject.addEventListener('pointerdown', $e77252a287ef94ab$var$handlePointerEvent, true);
117 documentObject.addEventListener('pointermove', $e77252a287ef94ab$var$handlePointerEvent, true);
118 documentObject.addEventListener('pointerup', $e77252a287ef94ab$var$handlePointerEvent, true);
119 } else {
120 documentObject.addEventListener('mousedown', $e77252a287ef94ab$var$handlePointerEvent, true);
121 documentObject.addEventListener('mousemove', $e77252a287ef94ab$var$handlePointerEvent, true);
122 documentObject.addEventListener('mouseup', $e77252a287ef94ab$var$handlePointerEvent, true);
123 }
124 // Add unmount handler
125 windowObject.addEventListener('beforeunload', ()=>{
126 $e77252a287ef94ab$var$tearDownWindowFocusTracking(element);
127 }, {
128 once: true
129 });
130 $e77252a287ef94ab$export$d90243b58daecda7.set(windowObject, {
131 focus: focus
132 });
133}
134const $e77252a287ef94ab$var$tearDownWindowFocusTracking = (element, loadListener)=>{
135 const windowObject = (0, $cR3F8$reactariautils.getOwnerWindow)(element);
136 const documentObject = (0, $cR3F8$reactariautils.getOwnerDocument)(element);
137 if (loadListener) documentObject.removeEventListener('DOMContentLoaded', loadListener);
138 if (!$e77252a287ef94ab$export$d90243b58daecda7.has(windowObject)) return;
139 windowObject.HTMLElement.prototype.focus = $e77252a287ef94ab$export$d90243b58daecda7.get(windowObject).focus;
140 documentObject.removeEventListener('keydown', $e77252a287ef94ab$var$handleKeyboardEvent, true);
141 documentObject.removeEventListener('keyup', $e77252a287ef94ab$var$handleKeyboardEvent, true);
142 documentObject.removeEventListener('click', $e77252a287ef94ab$var$handleClickEvent, true);
143 windowObject.removeEventListener('focus', $e77252a287ef94ab$var$handleFocusEvent, true);
144 windowObject.removeEventListener('blur', $e77252a287ef94ab$var$handleWindowBlur, false);
145 if (typeof PointerEvent !== 'undefined') {
146 documentObject.removeEventListener('pointerdown', $e77252a287ef94ab$var$handlePointerEvent, true);
147 documentObject.removeEventListener('pointermove', $e77252a287ef94ab$var$handlePointerEvent, true);
148 documentObject.removeEventListener('pointerup', $e77252a287ef94ab$var$handlePointerEvent, true);
149 } else {
150 documentObject.removeEventListener('mousedown', $e77252a287ef94ab$var$handlePointerEvent, true);
151 documentObject.removeEventListener('mousemove', $e77252a287ef94ab$var$handlePointerEvent, true);
152 documentObject.removeEventListener('mouseup', $e77252a287ef94ab$var$handlePointerEvent, true);
153 }
154 $e77252a287ef94ab$export$d90243b58daecda7.delete(windowObject);
155};
156function $e77252a287ef94ab$export$2f1888112f558a7d(element) {
157 const documentObject = (0, $cR3F8$reactariautils.getOwnerDocument)(element);
158 let loadListener;
159 if (documentObject.readyState !== 'loading') $e77252a287ef94ab$var$setupGlobalFocusEvents(element);
160 else {
161 loadListener = ()=>{
162 $e77252a287ef94ab$var$setupGlobalFocusEvents(element);
163 };
164 documentObject.addEventListener('DOMContentLoaded', loadListener);
165 }
166 return ()=>$e77252a287ef94ab$var$tearDownWindowFocusTracking(element, loadListener);
167}
168// Server-side rendering does not have the document object defined
169// eslint-disable-next-line no-restricted-globals
170if (typeof document !== 'undefined') $e77252a287ef94ab$export$2f1888112f558a7d();
171function $e77252a287ef94ab$export$b9b3dfddab17db27() {
172 return $e77252a287ef94ab$var$currentModality !== 'pointer';
173}
174function $e77252a287ef94ab$export$630ff653c5ada6a9() {
175 return $e77252a287ef94ab$var$currentModality;
176}
177function $e77252a287ef94ab$export$8397ddfc504fdb9a(modality) {
178 $e77252a287ef94ab$var$currentModality = modality;
179 $e77252a287ef94ab$var$triggerChangeHandlers(modality, null);
180}
181function $e77252a287ef94ab$export$98e20ec92f614cfe() {
182 $e77252a287ef94ab$var$setupGlobalFocusEvents();
183 let [modality, setModality] = (0, $cR3F8$react.useState)($e77252a287ef94ab$var$currentModality);
184 (0, $cR3F8$react.useEffect)(()=>{
185 let handler = ()=>{
186 setModality($e77252a287ef94ab$var$currentModality);
187 };
188 $e77252a287ef94ab$var$changeHandlers.add(handler);
189 return ()=>{
190 $e77252a287ef94ab$var$changeHandlers.delete(handler);
191 };
192 }, []);
193 return (0, $cR3F8$reactariassr.useIsSSR)() ? null : modality;
194}
195const $e77252a287ef94ab$var$nonTextInputTypes = new Set([
196 'checkbox',
197 'radio',
198 'range',
199 'color',
200 'file',
201 'image',
202 'button',
203 'submit',
204 'reset'
205]);
206/**
207 * If this is attached to text input component, return if the event is a focus event (Tab/Escape keys pressed) so that
208 * focus visible style can be properly set.
209 */ function $e77252a287ef94ab$var$isKeyboardFocusEvent(isTextInput, modality, e) {
210 var _e_target;
211 const IHTMLInputElement = typeof window !== 'undefined' ? (0, $cR3F8$reactariautils.getOwnerWindow)(e === null || e === void 0 ? void 0 : e.target).HTMLInputElement : HTMLInputElement;
212 const IHTMLTextAreaElement = typeof window !== 'undefined' ? (0, $cR3F8$reactariautils.getOwnerWindow)(e === null || e === void 0 ? void 0 : e.target).HTMLTextAreaElement : HTMLTextAreaElement;
213 const IHTMLElement = typeof window !== 'undefined' ? (0, $cR3F8$reactariautils.getOwnerWindow)(e === null || e === void 0 ? void 0 : e.target).HTMLElement : HTMLElement;
214 const IKeyboardEvent = typeof window !== 'undefined' ? (0, $cR3F8$reactariautils.getOwnerWindow)(e === null || e === void 0 ? void 0 : e.target).KeyboardEvent : KeyboardEvent;
215 isTextInput = isTextInput || (e === null || e === void 0 ? void 0 : e.target) instanceof IHTMLInputElement && !$e77252a287ef94ab$var$nonTextInputTypes.has(e === null || e === void 0 ? void 0 : (_e_target = e.target) === null || _e_target === void 0 ? void 0 : _e_target.type) || (e === null || e === void 0 ? void 0 : e.target) instanceof IHTMLTextAreaElement || (e === null || e === void 0 ? void 0 : e.target) instanceof IHTMLElement && (e === null || e === void 0 ? void 0 : e.target.isContentEditable);
216 return !(isTextInput && modality === 'keyboard' && e instanceof IKeyboardEvent && !$e77252a287ef94ab$var$FOCUS_VISIBLE_INPUT_KEYS[e.key]);
217}
218function $e77252a287ef94ab$export$ffd9e5021c1fb2d6(props = {}) {
219 let { isTextInput: isTextInput, autoFocus: autoFocus } = props;
220 let [isFocusVisibleState, setFocusVisible] = (0, $cR3F8$react.useState)(autoFocus || $e77252a287ef94ab$export$b9b3dfddab17db27());
221 $e77252a287ef94ab$export$ec71b4b83ac08ec3((isFocusVisible)=>{
222 setFocusVisible(isFocusVisible);
223 }, [
224 isTextInput
225 ], {
226 isTextInput: isTextInput
227 });
228 return {
229 isFocusVisible: isFocusVisibleState
230 };
231}
232function $e77252a287ef94ab$export$ec71b4b83ac08ec3(fn, deps, opts) {
233 $e77252a287ef94ab$var$setupGlobalFocusEvents();
234 (0, $cR3F8$react.useEffect)(()=>{
235 let handler = (modality, e)=>{
236 if (!$e77252a287ef94ab$var$isKeyboardFocusEvent(!!(opts === null || opts === void 0 ? void 0 : opts.isTextInput), modality, e)) return;
237 fn($e77252a287ef94ab$export$b9b3dfddab17db27());
238 };
239 $e77252a287ef94ab$var$changeHandlers.add(handler);
240 return ()=>{
241 $e77252a287ef94ab$var$changeHandlers.delete(handler);
242 };
243 // eslint-disable-next-line react-hooks/exhaustive-deps
244 }, deps);
245}
246
247
248//# sourceMappingURL=useFocusVisible.main.js.map