@samitouri / QOS-React-2 / commits / b5af4fe3c6

Remove FocusScope (#16267)

Dominic Gannaway committed Jul 31, 2019 at 17:40 UTC b5af4fe3c64e1ac254e8fd101fec2f8e414aabf6
7 files changed -473
packages/react-events/docs/FocusScope.md deleted
-37
@@ -1,37 +0,0 @@
1 -# FocusScope
2 -
3 -The `FocusScope` module can be used to manage focus within its subtree.
4 -
5 -```js
6 -// Example
7 -const Modal = () => (
8 - <FocusScope
9 - autoFocus={true}
10 - contain={true}
11 - restoreFocus={true}
12 - >
13 - <h1>Focus contained within modal</h1>
14 - <input placeholder="Focusable input" />
15 - <div role="button" tabIndex={0}>Focusable element</div>
16 - <input placeholder="Non-focusable input" tabIndex={-1} />
17 - <Press onPress={onPressClose}>
18 - <div role="button" tabIndex={0}>Close</div>
19 - </Press>
20 - </FocusScope>
21 -);
22 -```
23 -
24 -## Props
25 -
26 -### autoFocus: boolean = false
27 -
28 -Automatically moves focus to the first focusable element within scope.
29 -
30 -### contain: boolean = false
31 -
32 -Contain focus within the subtree of the `FocusScope` instance.
33 -
34 -### restoreFocus: boolean = false
35 -
36 -Automatically restores focus to element that was last focused before focus moved
37 -within the scope.
packages/react-events/focus-scope.js deleted
-12
@@ -1,12 +0,0 @@
1 -/**
2 - * Copyright (c) Facebook, Inc. and its affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -'use strict';
11 -
12 -module.exports = require('./src/dom/FocusScope');
packages/react-events/npm/focus-scope.js deleted
-7
@@ -1,7 +0,0 @@
1 -'use strict';
2 -
3 -if (process.env.NODE_ENV === 'production') {
4 - module.exports = require('./cjs/react-events-focus-scope.production.min.js');
5 -} else {
6 - module.exports = require('./cjs/react-events-focus-scope.development.js');
7 -}
packages/react-events/package.json
-1
@@ -18,7 +18,6 @@
18 "swipe.js",
19 "drag.js",
20 "scroll.js",
21 - "focus-scope.js",
21 "input.js",
22 "keyboard.js",
23 "build-info.json",
packages/react-events/src/dom/FocusScope.js deleted
-167
@@ -1,167 +0,0 @@
1 -/**
2 - * Copyright (c) Facebook, Inc. and its affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -import type {
10 - ReactDOMResponderEvent,
11 - ReactDOMResponderContext,
12 -} from 'shared/ReactDOMTypes';
13 -
14 -import React from 'react';
15 -
16 -type FocusScopeProps = {
17 - autoFocus: Boolean,
18 - contain: Boolean,
19 - restoreFocus: Boolean,
20 -};
21 -
22 -type FocusScopeState = {
23 - nodeToRestore: null | HTMLElement,
24 - currentFocusedNode: null | HTMLElement,
25 -};
26 -
27 -const targetEventTypes = ['keydown_active'];
28 -const rootEventTypes = ['focus'];
29 -
30 -function focusElement(element: ?HTMLElement) {
31 - if (element != null) {
32 - try {
33 - element.focus();
34 - } catch (err) {}
35 - }
36 -}
37 -
38 -function getFirstFocusableElement(
39 - context: ReactDOMResponderContext,
40 - state: FocusScopeState,
41 -): ?HTMLElement {
42 - const elements = context.getFocusableElementsInScope(false);
43 - if (elements.length > 0) {
44 - return elements[0];
45 - }
46 -}
47 -
48 -const focusScopeResponderImpl = {
49 - targetEventTypes,
50 - rootEventTypes,
51 - getInitialState(): FocusScopeState {
52 - return {
53 - nodeToRestore: null,
54 - currentFocusedNode: null,
55 - };
56 - },
57 - onEvent(
58 - event: ReactDOMResponderEvent,
59 - context: ReactDOMResponderContext,
60 - props: FocusScopeProps,
61 - state: FocusScopeState,
62 - ) {
63 - const {type, nativeEvent} = event;
64 -
65 - if (type === 'keydown' && nativeEvent.key === 'Tab') {
66 - const focusedElement = context.getActiveDocument().activeElement;
67 - if (
68 - focusedElement !== null &&
69 - context.isTargetWithinResponder(focusedElement)
70 - ) {
71 - const {altkey, ctrlKey, metaKey, shiftKey} = (nativeEvent: any);
72 - // Skip if any of these keys are being pressed
73 - if (altkey || ctrlKey || metaKey) {
74 - return;
75 - }
76 - const elements = context.getFocusableElementsInScope(false);
77 - const position = elements.indexOf(focusedElement);
78 - const lastPosition = elements.length - 1;
79 - let nextElement = null;
80 -
81 - if (shiftKey) {
82 - if (position === 0) {
83 - if (props.contain) {
84 - nextElement = elements[lastPosition];
85 - } else {
86 - // Out of bounds
87 - // TODO remove this, this is hacky
88 - const allElements = context.getFocusableElementsInScope(true);
89 - const prevPosition = allElements.indexOf(focusedElement) - 1;
90 - nextElement = allElements[prevPosition] || null;
91 - return;
92 - }
93 - } else {
94 - nextElement = elements[position - 1];
95 - }
96 - } else {
97 - if (position === lastPosition) {
98 - if (props.contain) {
99 - nextElement = elements[0];
100 - } else {
101 - // Out of bounds
102 - // TODO remove this, this is hacky
103 - const allElements = context.getFocusableElementsInScope(true);
104 - const nextPosition = allElements.indexOf(focusedElement) + 1;
105 - nextElement = allElements[nextPosition] || null;
106 - }
107 - } else {
108 - nextElement = elements[position + 1];
109 - }
110 - }
111 - if (nextElement !== null) {
112 - focusElement(nextElement);
113 - state.currentFocusedNode = nextElement;
114 - ((nativeEvent: any): KeyboardEvent).preventDefault();
115 - }
116 - }
117 - }
118 - },
119 - onRootEvent(
120 - event: ReactDOMResponderEvent,
121 - context: ReactDOMResponderContext,
122 - props: FocusScopeProps,
123 - state: FocusScopeState,
124 - ) {
125 - const {target} = event;
126 -
127 - // Handle global focus containment
128 - if (props.contain) {
129 - if (!context.isTargetWithinResponder(target)) {
130 - const currentFocusedNode = state.currentFocusedNode;
131 - if (currentFocusedNode !== null) {
132 - focusElement(currentFocusedNode);
133 - } else if (props.autoFocus) {
134 - const firstElement = getFirstFocusableElement(context, state);
135 - focusElement(firstElement);
136 - }
137 - }
138 - }
139 - },
140 - onMount(
141 - context: ReactDOMResponderContext,
142 - props: FocusScopeProps,
143 - state: FocusScopeState,
144 - ): void {
145 - if (props.restoreFocus) {
146 - state.nodeToRestore = context.getActiveDocument().activeElement;
147 - }
148 - if (props.autoFocus) {
149 - const firstElement = getFirstFocusableElement(context, state);
150 - focusElement(firstElement);
151 - }
152 - },
153 - onUnmount(
154 - context: ReactDOMResponderContext,
155 - props: FocusScopeProps,
156 - state: FocusScopeState,
157 - ): void {
158 - if (props.restoreFocus && state.nodeToRestore !== null) {
159 - focusElement(state.nodeToRestore);
160 - }
161 - },
162 -};
163 -
164 -export const FocusScopeResponder = React.unstable_createResponder(
165 - 'FocusSocpe',
166 - focusScopeResponderImpl,
167 -);
packages/react-events/src/dom/__tests__/FocusScope-test.internal.js deleted
-234
@@ -1,234 +0,0 @@
1 -/**
2 - * Copyright (c) Facebook, Inc. and its affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @emails react-core
8 - */
9 -
10 -'use strict';
11 -
12 -let React;
13 -let ReactFeatureFlags;
14 -let ReactDOM;
15 -let FocusScopeResponder;
16 -
17 -const createTabForward = type => {
18 - const event = new KeyboardEvent('keydown', {
19 - key: 'Tab',
20 - bubbles: true,
21 - cancelable: true,
22 - });
23 - return event;
24 -};
25 -
26 -const createTabBackward = type => {
27 - const event = new KeyboardEvent('keydown', {
28 - key: 'Tab',
29 - shiftKey: true,
30 - bubbles: true,
31 - cancelable: true,
32 - });
33 - return event;
34 -};
35 -
36 -describe('FocusScope event responder', () => {
37 - let container;
38 -
39 - beforeEach(() => {
40 - jest.resetModules();
41 - ReactFeatureFlags = require('shared/ReactFeatureFlags');
42 - ReactFeatureFlags.enableFlareAPI = true;
43 - React = require('react');
44 - ReactDOM = require('react-dom');
45 - FocusScopeResponder = require('react-events/focus-scope')
46 - .FocusScopeResponder;
47 - container = document.createElement('div');
48 - document.body.appendChild(container);
49 - });
50 -
51 - afterEach(() => {
52 - ReactDOM.render(null, container);
53 - document.body.removeChild(container);
54 - container = null;
55 - });
56 -
57 - it('should work as expected with autofocus', () => {
58 - const inputRef = React.createRef();
59 - const input2Ref = React.createRef();
60 - const buttonRef = React.createRef();
61 - const butto2nRef = React.createRef();
62 - const divRef = React.createRef();
63 -
64 - const SimpleFocusScope = () => (
65 - <div responders={<FocusScopeResponder autoFocus={true} />}>
66 - <input ref={inputRef} />
67 - <button ref={buttonRef} />
68 - <div ref={divRef} tabIndex={0} />
69 - <input ref={input2Ref} tabIndex={-1} />
70 - <button ref={butto2nRef} />
71 - </div>
72 - );
73 -
74 - ReactDOM.render(<SimpleFocusScope />, container);
75 - expect(document.activeElement).toBe(inputRef.current);
76 - document.activeElement.dispatchEvent(createTabForward());
77 - expect(document.activeElement).toBe(buttonRef.current);
78 - document.activeElement.dispatchEvent(createTabForward());
79 - expect(document.activeElement).toBe(divRef.current);
80 - document.activeElement.dispatchEvent(createTabForward());
81 - expect(document.activeElement).toBe(butto2nRef.current);
82 - document.activeElement.dispatchEvent(createTabBackward());
83 - expect(document.activeElement).toBe(divRef.current);
84 - });
85 -
86 - it('should work as expected with autoFocus and contain', () => {
87 - const inputRef = React.createRef();
88 - const input2Ref = React.createRef();
89 - const buttonRef = React.createRef();
90 - const button2Ref = React.createRef();
91 -
92 - const SimpleFocusScope = () => (
93 - <div responders={<FocusScopeResponder autoFocus={true} contain={true} />}>
94 - <input ref={inputRef} tabIndex={-1} />
95 - <button ref={buttonRef} id={1} />
96 - <button ref={button2Ref} id={2} />
97 - <input ref={input2Ref} tabIndex={-1} />
98 - </div>
99 - );
100 -
101 - ReactDOM.render(<SimpleFocusScope />, container);
102 - expect(document.activeElement).toBe(buttonRef.current);
103 - document.activeElement.dispatchEvent(createTabForward());
104 - expect(document.activeElement).toBe(button2Ref.current);
105 - document.activeElement.dispatchEvent(createTabForward());
106 - expect(document.activeElement).toBe(buttonRef.current);
107 - document.activeElement.dispatchEvent(createTabForward());
108 - expect(document.activeElement).toBe(button2Ref.current);
109 - document.activeElement.dispatchEvent(createTabBackward());
110 - expect(document.activeElement).toBe(buttonRef.current);
111 - document.activeElement.dispatchEvent(createTabBackward());
112 - expect(document.activeElement).toBe(button2Ref.current);
113 - });
114 -
115 - it('should work as expected when nested', () => {
116 - const inputRef = React.createRef();
117 - const input2Ref = React.createRef();
118 - const buttonRef = React.createRef();
119 - const button2Ref = React.createRef();
120 - const button3Ref = React.createRef();
121 - const button4Ref = React.createRef();
122 -
123 - const SimpleFocusScope = () => (
124 - <div responders={<FocusScopeResponder />}>
125 - <input ref={inputRef} tabIndex={-1} />
126 - <button ref={buttonRef} id={1} />
127 - <div responders={<FocusScopeResponder />}>
128 - <button ref={button2Ref} id={2} />
129 - <button ref={button3Ref} id={3} />
130 - </div>
131 - <input ref={input2Ref} tabIndex={-1} />
132 - <button ref={button4Ref} id={4} />
133 - </div>
134 - );
135 -
136 - ReactDOM.render(<SimpleFocusScope />, container);
137 - buttonRef.current.focus();
138 - expect(document.activeElement).toBe(buttonRef.current);
139 - document.activeElement.dispatchEvent(createTabForward());
140 - expect(document.activeElement).toBe(button2Ref.current);
141 - document.activeElement.dispatchEvent(createTabForward());
142 - expect(document.activeElement).toBe(button3Ref.current);
143 - document.activeElement.dispatchEvent(createTabForward());
144 - expect(document.activeElement).toBe(button4Ref.current);
145 - document.activeElement.dispatchEvent(createTabBackward());
146 - expect(document.activeElement).toBe(button3Ref.current);
147 - document.activeElement.dispatchEvent(createTabBackward());
148 - expect(document.activeElement).toBe(button2Ref.current);
149 - });
150 -
151 - it('should work as expected when nested with scope that is contained', () => {
152 - const inputRef = React.createRef();
153 - const input2Ref = React.createRef();
154 - const buttonRef = React.createRef();
155 - const button2Ref = React.createRef();
156 - const button3Ref = React.createRef();
157 - const button4Ref = React.createRef();
158 -
159 - const SimpleFocusScope = () => (
160 - <div responders={<FocusScopeResponder />}>
161 - <input ref={inputRef} tabIndex={-1} />
162 - <button ref={buttonRef} id={1} />
163 - <div responders={<FocusScopeResponder contain={true} />}>
164 - <button ref={button2Ref} id={2} />
165 - <button ref={button3Ref} id={3} />
166 - </div>
167 - <input ref={input2Ref} tabIndex={-1} />
168 - <button ref={button4Ref} id={4} />
169 - </div>
170 - );
171 -
172 - ReactDOM.render(<SimpleFocusScope />, container);
173 - buttonRef.current.focus();
174 - expect(document.activeElement).toBe(buttonRef.current);
175 - document.activeElement.dispatchEvent(createTabForward());
176 - expect(document.activeElement).toBe(button2Ref.current);
177 - document.activeElement.dispatchEvent(createTabForward());
178 - expect(document.activeElement).toBe(button3Ref.current);
179 - document.activeElement.dispatchEvent(createTabForward());
180 - expect(document.activeElement).toBe(button2Ref.current);
181 - document.activeElement.dispatchEvent(createTabBackward());
182 - expect(document.activeElement).toBe(button3Ref.current);
183 - document.activeElement.dispatchEvent(createTabBackward());
184 - expect(document.activeElement).toBe(button2Ref.current);
185 - });
186 -
187 - it('should work as expected with suspense fallbacks', () => {
188 - const buttonRef = React.createRef();
189 - const button2Ref = React.createRef();
190 - const button3Ref = React.createRef();
191 - const button4Ref = React.createRef();
192 - const button5Ref = React.createRef();
193 -
194 - function SuspendedComponent() {
195 - throw new Promise(() => {
196 - // Never resolve
197 - });
198 - }
199 -
200 - function Component() {
201 - return (
202 - <React.Fragment>
203 - <button ref={button5Ref} id={5} />
204 - <SuspendedComponent />
205 - </React.Fragment>
206 - );
207 - }
208 -
209 - const SimpleFocusScope = () => (
210 - <div responders={<FocusScopeResponder />}>
211 - <button ref={buttonRef} id={1} />
212 - <button ref={button2Ref} id={2} />
213 - <React.Suspense fallback={<button ref={button3Ref} id={3} />}>
214 - <Component />
215 - </React.Suspense>
216 - <button ref={button4Ref} id={4} />
217 - </div>
218 - );
219 -
220 - ReactDOM.render(<SimpleFocusScope />, container);
221 - buttonRef.current.focus();
222 - expect(document.activeElement).toBe(buttonRef.current);
223 - document.activeElement.dispatchEvent(createTabForward());
224 - expect(document.activeElement).toBe(button2Ref.current);
225 - document.activeElement.dispatchEvent(createTabForward());
226 - expect(document.activeElement).toBe(button3Ref.current);
227 - document.activeElement.dispatchEvent(createTabForward());
228 - expect(document.activeElement).toBe(button4Ref.current);
229 - document.activeElement.dispatchEvent(createTabBackward());
230 - expect(document.activeElement).toBe(button3Ref.current);
231 - document.activeElement.dispatchEvent(createTabBackward());
232 - expect(document.activeElement).toBe(button2Ref.current);
233 - });
234 -});
scripts/rollup/bundles.js
-15
@@ -464,21 +464,6 @@ const bundles = [
464 externals: ['react'],
465 },
466
467 - {
468 - bundleTypes: [
469 - UMD_DEV,
470 - UMD_PROD,
471 - NODE_DEV,
472 - NODE_PROD,
473 - FB_WWW_DEV,
474 - FB_WWW_PROD,
475 - ],
476 - moduleType: NON_FIBER_RENDERER,
477 - entry: 'react-events/focus-scope',
478 - global: 'ReactEventsFocusScope',
479 - externals: ['react'],
480 - },
481 -
467 {
468 bundleTypes: [
469 UMD_DEV,