[react-ui] FocusGrid -> ReactFocusTable + tweaks and fixes (#16806)
Dominic Gannaway committed
Sep 17, 2019 at 19:22 UTC
f40ceb0010eaddab8cad94c67189837c495a5b57
6 files changed
+482
-283
packages/react-reconciler/src/ReactFiberScope.js
+4
@@ -143,6 +143,10 @@ export function createScopeMethods(
143
}
144
return null;
145
},
146
+ getProps(): Object {
147
+ const currentFiber = ((instance.fiber: any): Fiber);
148
+ return currentFiber.memoizedProps;
149
+ },
150
getScopedNodes(): null | Array<Object> {
151
const currentFiber = ((instance.fiber: any): Fiber);
152
const child = currentFiber.child;
packages/react-ui/accessibility/src/FocusGrid.js
deleted
-131
@@ -1,131 +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
-import type {KeyboardEvent} from 'react-ui/events/keyboard';
11
-
12
-import React from 'react';
13
-import {tabFocusableImpl} from './TabbableScope';
14
-import {useKeyboard} from 'react-ui/events/keyboard';
15
-
16
-type GridComponentProps = {
17
- children: React.Node,
18
-};
19
-
20
-const {useRef} = React;
21
-
22
-function focusCell(cell) {
23
- const tabbableNodes = cell.getScopedNodes();
24
- if (tabbableNodes !== null && tabbableNodes.length > 0) {
25
- tabbableNodes[0].focus();
26
- }
27
-}
28
-
29
-function focusCellByRowIndex(row, rowIndex) {
30
- const cells = row.getChildren();
31
- const cell = cells[rowIndex];
32
- if (cell) {
33
- focusCell(cell);
34
- }
35
-}
36
-
37
-function getRowCells(currentCell) {
38
- const row = currentCell.getParent();
39
- if (parent !== null) {
40
- const cells = row.getChildren();
41
- const rowIndex = cells.indexOf(currentCell);
42
- return [cells, rowIndex];
43
- }
44
- return [null, 0];
45
-}
46
-
47
-function getColumns(currentCell) {
48
- const row = currentCell.getParent();
49
- if (parent !== null) {
50
- const grid = row.getParent();
51
- const columns = grid.getChildren();
52
- const columnIndex = columns.indexOf(row);
53
- return [columns, columnIndex];
54
- }
55
- return [null, 0];
56
-}
57
-
58
-export function createFocusGrid(): Array<React.Component> {
59
- const GridScope = React.unstable_createScope(tabFocusableImpl);
60
-
61
- function GridContainer({children}): GridComponentProps {
62
- return <GridScope>{children}</GridScope>;
63
- }
64
-
65
- function GridRow({children}): GridComponentProps {
66
- return <GridScope>{children}</GridScope>;
67
- }
68
-
69
- function GridCell({children}): GridComponentProps {
70
- const scopeRef = useRef(null);
71
- const keyboard = useKeyboard({
72
- onKeyDown(event: KeyboardEvent): boolean {
73
- const currentCell = scopeRef.current;
74
- switch (event.key) {
75
- case 'UpArrow': {
76
- const [cells, rowIndex] = getRowCells(currentCell);
77
- if (cells !== null) {
78
- const [columns, columnIndex] = getColumns(currentCell);
79
- if (columns !== null) {
80
- if (columnIndex > 0) {
81
- const column = columns[columnIndex - 1];
82
- focusCellByRowIndex(column, rowIndex);
83
- }
84
- }
85
- }
86
- return false;
87
- }
88
- case 'DownArrow': {
89
- const [cells, rowIndex] = getRowCells(currentCell);
90
- if (cells !== null) {
91
- const [columns, columnIndex] = getColumns(currentCell);
92
- if (columns !== null) {
93
- if (columnIndex !== -1 && columnIndex !== columns.length - 1) {
94
- const column = columns[columnIndex + 1];
95
- focusCellByRowIndex(column, rowIndex);
96
- }
97
- }
98
- }
99
- return false;
100
- }
101
- case 'LeftArrow': {
102
- const [cells, rowIndex] = getRowCells(currentCell);
103
- if (cells !== null) {
104
- if (rowIndex > 0) {
105
- focusCell(cells[rowIndex - 1]);
106
- }
107
- }
108
- return false;
109
- }
110
- case 'RightArrow': {
111
- const [cells, rowIndex] = getRowCells(currentCell);
112
- if (cells !== null) {
113
- if (rowIndex !== -1 && rowIndex !== cells.length - 1) {
114
- focusCell(cells[rowIndex + 1]);
115
- }
116
- }
117
- return false;
118
- }
119
- }
120
- return true;
121
- },
122
- });
123
- return (
124
- <GridScope listeners={keyboard} ref={scopeRef}>
125
- {children}
126
- </GridScope>
127
- );
128
- }
129
-
130
- return [GridContainer, GridRow, GridCell];
131
-}
packages/react-ui/accessibility/src/ReactFocusTable.js
new
+220
@@ -0,0 +1,220 @@
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
+import type {ReactScopeMethods} from 'shared/ReactTypes';
11
+import type {KeyboardEvent} from 'react-ui/events/keyboard';
12
+
13
+import React from 'react';
14
+import {tabFocusableImpl} from './TabbableScope';
15
+import {useKeyboard} from 'react-ui/events/keyboard';
16
+
17
+type FocusCellProps = {
18
+ children?: React.Node,
19
+};
20
+
21
+type FocusRowProps = {
22
+ children: React.Node,
23
+};
24
+
25
+type FocusTableProps = {|
26
+ children: React.Node,
27
+ id?: string,
28
+ onKeyboardOut?: (
29
+ direction: 'left' | 'right' | 'up' | 'down',
30
+ focusTableByID: (id: string) => void,
31
+ ) => void,
32
+|};
33
+
34
+const {useRef} = React;
35
+
36
+export function focusFirstCellOnTable(table: ReactScopeMethods): void {
37
+ const rows = table.getChildren();
38
+ if (rows !== null) {
39
+ const firstRow = rows[0];
40
+ if (firstRow !== null) {
41
+ const cells = firstRow.getChildren();
42
+ if (cells !== null) {
43
+ const firstCell = cells[0];
44
+ if (firstCell !== null) {
45
+ const tabbableNodes = firstCell.getScopedNodes();
46
+ if (tabbableNodes !== null) {
47
+ const firstElem = tabbableNodes[0];
48
+ if (firstElem !== null) {
49
+ firstElem.focus();
50
+ }
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
56
+}
57
+
58
+function focusCell(cell: ReactScopeMethods): void {
59
+ const tabbableNodes = cell.getScopedNodes();
60
+ if (tabbableNodes !== null && tabbableNodes.length > 0) {
61
+ tabbableNodes[0].focus();
62
+ }
63
+}
64
+
65
+function focusCellByRowIndex(row: ReactScopeMethods, rowIndex: number): void {
66
+ const cells = row.getChildren();
67
+ if (cells !== null) {
68
+ const cell = cells[rowIndex];
69
+ if (cell) {
70
+ focusCell(cell);
71
+ }
72
+ }
73
+}
74
+
75
+function getRowCells(currentCell: ReactScopeMethods) {
76
+ const row = currentCell.getParent();
77
+ if (row !== null && row.getProps().type === 'row') {
78
+ const cells = row.getChildren();
79
+ if (cells !== null) {
80
+ const rowIndex = cells.indexOf(currentCell);
81
+ return [cells, rowIndex];
82
+ }
83
+ }
84
+ return [null, 0];
85
+}
86
+
87
+function getRows(currentCell: ReactScopeMethods) {
88
+ const row = currentCell.getParent();
89
+ if (row !== null && row.getProps().type === 'row') {
90
+ const table = row.getParent();
91
+ if (table !== null && table.getProps().type === 'table') {
92
+ const rows = table.getChildren();
93
+ if (rows !== null) {
94
+ const columnIndex = rows.indexOf(row);
95
+ return [rows, columnIndex];
96
+ }
97
+ }
98
+ }
99
+ return [null, 0];
100
+}
101
+
102
+function triggerNavigateOut(
103
+ currentCell: ReactScopeMethods,
104
+ direction: 'left' | 'right' | 'up' | 'down',
105
+): void {
106
+ const row = currentCell.getParent();
107
+ if (row !== null && row.getProps().type === 'row') {
108
+ const table = row.getParent();
109
+ if (table !== null) {
110
+ const props = table.getProps();
111
+ const onKeyboardOut = props.onKeyboardOut;
112
+ if (props.type === 'table' && typeof onKeyboardOut === 'function') {
113
+ const focusTableByID = (id: string) => {
114
+ const topLevelTables = table.getChildrenFromRoot();
115
+ if (topLevelTables !== null) {
116
+ for (let i = 0; i < topLevelTables.length; i++) {
117
+ const topLevelTable = topLevelTables[i];
118
+ if (topLevelTable.getProps().id === id) {
119
+ focusFirstCellOnTable(topLevelTable);
120
+ return;
121
+ }
122
+ }
123
+ }
124
+ };
125
+ onKeyboardOut(direction, focusTableByID);
126
+ }
127
+ }
128
+ }
129
+}
130
+
131
+export function createFocusTable(): Array<React.Component> {
132
+ const TableScope = React.unstable_createScope(tabFocusableImpl);
133
+
134
+ function Table({children, onKeyboardOut, id}): FocusTableProps {
135
+ return (
136
+ <TableScope type="table" onKeyboardOut={onKeyboardOut} id={id}>
137
+ {children}
138
+ </TableScope>
139
+ );
140
+ }
141
+
142
+ function Row({children}): FocusRowProps {
143
+ return <TableScope type="row">{children}</TableScope>;
144
+ }
145
+
146
+ function Cell({children}): FocusCellProps {
147
+ const scopeRef = useRef(null);
148
+ const keyboard = useKeyboard({
149
+ onKeyDown(event: KeyboardEvent): boolean {
150
+ const currentCell = scopeRef.current;
151
+ switch (event.key) {
152
+ case 'UpArrow': {
153
+ const [cells, rowIndex] = getRowCells(currentCell);
154
+ if (cells !== null) {
155
+ const [columns, columnIndex] = getRows(currentCell);
156
+ if (columns !== null) {
157
+ if (columnIndex > 0) {
158
+ const column = columns[columnIndex - 1];
159
+ focusCellByRowIndex(column, rowIndex);
160
+ } else if (columnIndex === 0) {
161
+ triggerNavigateOut(currentCell, 'up');
162
+ }
163
+ }
164
+ }
165
+ return false;
166
+ }
167
+ case 'DownArrow': {
168
+ const [cells, rowIndex] = getRowCells(currentCell);
169
+ if (cells !== null) {
170
+ const [columns, columnIndex] = getRows(currentCell);
171
+ if (columns !== null) {
172
+ if (columnIndex !== -1) {
173
+ if (columnIndex === columns.length - 1) {
174
+ triggerNavigateOut(currentCell, 'down');
175
+ } else {
176
+ const column = columns[columnIndex + 1];
177
+ focusCellByRowIndex(column, rowIndex);
178
+ }
179
+ }
180
+ }
181
+ }
182
+ return false;
183
+ }
184
+ case 'LeftArrow': {
185
+ const [cells, rowIndex] = getRowCells(currentCell);
186
+ if (cells !== null) {
187
+ if (rowIndex > 0) {
188
+ focusCell(cells[rowIndex - 1]);
189
+ } else if (rowIndex === 0) {
190
+ triggerNavigateOut(currentCell, 'left');
191
+ }
192
+ }
193
+ return false;
194
+ }
195
+ case 'RightArrow': {
196
+ const [cells, rowIndex] = getRowCells(currentCell);
197
+ if (cells !== null) {
198
+ if (rowIndex !== -1) {
199
+ if (rowIndex === cells.length - 1) {
200
+ triggerNavigateOut(currentCell, 'right');
201
+ } else {
202
+ focusCell(cells[rowIndex + 1]);
203
+ }
204
+ }
205
+ }
206
+ return false;
207
+ }
208
+ }
209
+ return true;
210
+ },
211
+ });
212
+ return (
213
+ <TableScope listeners={keyboard} ref={scopeRef} type="cell">
214
+ {children}
215
+ </TableScope>
216
+ );
217
+ }
218
+
219
+ return [Table, Row, Cell];
220
+}
packages/react-ui/accessibility/src/__tests__/FocusGrid-test.internal.js
deleted
-152
@@ -1,152 +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
-import {createEventTarget} from 'react-ui/events/src/dom/testing-library';
11
-
12
-let React;
13
-let ReactFeatureFlags;
14
-let createFocusGrid;
15
-
16
-describe('TabFocusController', () => {
17
- beforeEach(() => {
18
- jest.resetModules();
19
- ReactFeatureFlags = require('shared/ReactFeatureFlags');
20
- ReactFeatureFlags.enableScopeAPI = true;
21
- ReactFeatureFlags.enableFlareAPI = true;
22
- createFocusGrid = require('../FocusGrid').createFocusGrid;
23
- React = require('react');
24
- });
25
-
26
- describe('ReactDOM', () => {
27
- let ReactDOM;
28
- let container;
29
-
30
- beforeEach(() => {
31
- ReactDOM = require('react-dom');
32
- container = document.createElement('div');
33
- document.body.appendChild(container);
34
- });
35
-
36
- afterEach(() => {
37
- document.body.removeChild(container);
38
- container = null;
39
- });
40
-
41
- it('handles tab operations', () => {
42
- const [
43
- FocusGridContainer,
44
- FocusGridRow,
45
- FocusGridCell,
46
- ] = createFocusGrid();
47
- const firstButtonRef = React.createRef();
48
-
49
- const Test = () => (
50
- <FocusGridContainer>
51
- <table>
52
- <tbody>
53
- <FocusGridRow>
54
- <tr>
55
- <FocusGridCell>
56
- <td>
57
- <button ref={firstButtonRef}>A1</button>
58
- </td>
59
- </FocusGridCell>
60
- <FocusGridCell>
61
- <td>
62
- <button>A2</button>
63
- </td>
64
- </FocusGridCell>
65
- <FocusGridCell>
66
- <td>
67
- <button>A3</button>
68
- </td>
69
- </FocusGridCell>
70
- </tr>
71
- </FocusGridRow>
72
- <FocusGridRow>
73
- <tr>
74
- <FocusGridCell>
75
- <td>
76
- <button>B1</button>
77
- </td>
78
- </FocusGridCell>
79
- <FocusGridCell>
80
- <td>
81
- <button>B2</button>
82
- </td>
83
- </FocusGridCell>
84
- <FocusGridCell>
85
- <td>
86
- <button>B3</button>
87
- </td>
88
- </FocusGridCell>
89
- </tr>
90
- </FocusGridRow>
91
- <FocusGridRow>
92
- <tr>
93
- <FocusGridCell>
94
- <td>
95
- <button>C1</button>
96
- </td>
97
- </FocusGridCell>
98
- <FocusGridCell>
99
- <td>
100
- <button>C2</button>
101
- </td>
102
- </FocusGridCell>
103
- <FocusGridCell>
104
- <td>
105
- <button>C3</button>
106
- </td>
107
- </FocusGridCell>
108
- </tr>
109
- </FocusGridRow>
110
- </tbody>
111
- </table>
112
- </FocusGridContainer>
113
- );
114
-
115
- ReactDOM.render(<Test />, container);
116
- const a1 = createEventTarget(firstButtonRef.current);
117
- a1.focus();
118
- a1.keydown({
119
- key: 'RightArrow',
120
- });
121
- expect(document.activeElement.textContent).toBe('A2');
122
-
123
- const a2 = createEventTarget(document.activeElement);
124
- a2.keydown({
125
- key: 'DownArrow',
126
- });
127
- expect(document.activeElement.textContent).toBe('B2');
128
-
129
- const b2 = createEventTarget(document.activeElement);
130
- b2.keydown({
131
- key: 'LeftArrow',
132
- });
133
- expect(document.activeElement.textContent).toBe('B1');
134
-
135
- const b1 = createEventTarget(document.activeElement);
136
- b1.keydown({
137
- key: 'DownArrow',
138
- });
139
- expect(document.activeElement.textContent).toBe('C1');
140
-
141
- const c1 = createEventTarget(document.activeElement);
142
- c1.keydown({
143
- key: 'DownArrow',
144
- });
145
- expect(document.activeElement.textContent).toBe('C1');
146
- c1.keydown({
147
- key: 'UpArrow',
148
- });
149
- expect(document.activeElement.textContent).toBe('B1');
150
- });
151
- });
152
-});
packages/react-ui/accessibility/src/__tests__/ReactFocusTable-test.internal.js
new
+257
@@ -0,0 +1,257 @@
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
+import {createEventTarget} from 'react-ui/events/src/dom/testing-library';
11
+
12
+let React;
13
+let ReactFeatureFlags;
14
+let createFocusTable;
15
+
16
+describe('ReactFocusTable', () => {
17
+ beforeEach(() => {
18
+ jest.resetModules();
19
+ ReactFeatureFlags = require('shared/ReactFeatureFlags');
20
+ ReactFeatureFlags.enableScopeAPI = true;
21
+ ReactFeatureFlags.enableFlareAPI = true;
22
+ createFocusTable = require('../ReactFocusTable').createFocusTable;
23
+ React = require('react');
24
+ });
25
+
26
+ describe('ReactDOM', () => {
27
+ let ReactDOM;
28
+ let container;
29
+
30
+ beforeEach(() => {
31
+ ReactDOM = require('react-dom');
32
+ container = document.createElement('div');
33
+ document.body.appendChild(container);
34
+ });
35
+
36
+ afterEach(() => {
37
+ document.body.removeChild(container);
38
+ container = null;
39
+ });
40
+
41
+ function createFocusTableComponent() {
42
+ const [FocusTable, FocusTableRow, FocusTableCell] = createFocusTable();
43
+
44
+ return ({onKeyboardOut, id}) => (
45
+ <FocusTable onKeyboardOut={onKeyboardOut} id={id}>
46
+ <table>
47
+ <tbody>
48
+ <FocusTableRow>
49
+ <tr>
50
+ <FocusTableCell>
51
+ <td>
52
+ <button>A1</button>
53
+ </td>
54
+ </FocusTableCell>
55
+ <FocusTableCell>
56
+ <td>
57
+ <button>A2</button>
58
+ </td>
59
+ </FocusTableCell>
60
+ <FocusTableCell>
61
+ <td>
62
+ <button>A3</button>
63
+ </td>
64
+ </FocusTableCell>
65
+ </tr>
66
+ </FocusTableRow>
67
+ <FocusTableRow>
68
+ <tr>
69
+ <FocusTableCell>
70
+ <td>
71
+ <button>B1</button>
72
+ </td>
73
+ </FocusTableCell>
74
+ <FocusTableCell>
75
+ <td>
76
+ <button>B2</button>
77
+ </td>
78
+ </FocusTableCell>
79
+ <FocusTableCell>
80
+ <td>
81
+ <button>B3</button>
82
+ </td>
83
+ </FocusTableCell>
84
+ </tr>
85
+ </FocusTableRow>
86
+ <FocusTableRow>
87
+ <tr>
88
+ <FocusTableCell>
89
+ <td>
90
+ <button>C1</button>
91
+ </td>
92
+ </FocusTableCell>
93
+ <FocusTableCell>
94
+ <td>
95
+ <button>C2</button>
96
+ </td>
97
+ </FocusTableCell>
98
+ <FocusTableCell>
99
+ <td>
100
+ <button>C3</button>
101
+ </td>
102
+ </FocusTableCell>
103
+ </tr>
104
+ </FocusTableRow>
105
+ </tbody>
106
+ </table>
107
+ </FocusTable>
108
+ );
109
+ }
110
+
111
+ it('handles keyboard arrow operations', () => {
112
+ const Test = createFocusTableComponent();
113
+
114
+ ReactDOM.render(<Test />, container);
115
+ const buttons = document.querySelectorAll('button');
116
+ const a1 = createEventTarget(buttons[0]);
117
+ a1.focus();
118
+ a1.keydown({
119
+ key: 'RightArrow',
120
+ });
121
+ expect(document.activeElement.textContent).toBe('A2');
122
+
123
+ const a2 = createEventTarget(document.activeElement);
124
+ a2.keydown({
125
+ key: 'DownArrow',
126
+ });
127
+ expect(document.activeElement.textContent).toBe('B2');
128
+
129
+ const b2 = createEventTarget(document.activeElement);
130
+ b2.keydown({
131
+ key: 'LeftArrow',
132
+ });
133
+ expect(document.activeElement.textContent).toBe('B1');
134
+
135
+ const b1 = createEventTarget(document.activeElement);
136
+ b1.keydown({
137
+ key: 'DownArrow',
138
+ });
139
+ expect(document.activeElement.textContent).toBe('C1');
140
+
141
+ const c1 = createEventTarget(document.activeElement);
142
+ c1.keydown({
143
+ key: 'DownArrow',
144
+ });
145
+ expect(document.activeElement.textContent).toBe('C1');
146
+ c1.keydown({
147
+ key: 'UpArrow',
148
+ });
149
+ expect(document.activeElement.textContent).toBe('B1');
150
+ });
151
+
152
+ it('handles keyboard arrow operations between tables', () => {
153
+ const leftSidebarRef = React.createRef();
154
+ const FocusTable = createFocusTableComponent();
155
+
156
+ function Test() {
157
+ return (
158
+ <div>
159
+ <h1>Title</h1>
160
+ <aside ref={leftSidebarRef}>
161
+ <h2>Left Sidebar</h2>
162
+ <FocusTable
163
+ id="left-sidebar"
164
+ onKeyboardOut={(direction, focusTableByID) => {
165
+ if (direction === 'right') {
166
+ focusTableByID('content');
167
+ }
168
+ }}
169
+ />
170
+ </aside>
171
+ <section>
172
+ <h2>Content</h2>
173
+ <FocusTable
174
+ id="content"
175
+ onKeyboardOut={(direction, focusTableByID) => {
176
+ if (direction === 'right') {
177
+ focusTableByID('right-sidebar');
178
+ } else if (direction === 'left') {
179
+ focusTableByID('left-sidebar');
180
+ }
181
+ }}
182
+ />
183
+ </section>
184
+ <aside>
185
+ <h2>Right Sidebar</h2>
186
+ <FocusTable
187
+ id="right-sidebar"
188
+ onKeyboardOut={(direction, focusTableByID) => {
189
+ if (direction === 'left') {
190
+ focusTableByID('content');
191
+ }
192
+ }}
193
+ />
194
+ </aside>
195
+ </div>
196
+ );
197
+ }
198
+
199
+ ReactDOM.render(<Test />, container);
200
+ const buttons = document.querySelectorAll('button');
201
+ let a1 = createEventTarget(buttons[0]);
202
+ a1.focus();
203
+ a1.keydown({
204
+ key: 'RightArrow',
205
+ });
206
+ expect(document.activeElement.textContent).toBe('A2');
207
+
208
+ let a2 = createEventTarget(document.activeElement);
209
+ a2.keydown({
210
+ key: 'RightArrow',
211
+ });
212
+ expect(document.activeElement.textContent).toBe('A3');
213
+
214
+ let a3 = createEventTarget(document.activeElement);
215
+ a3.keydown({
216
+ key: 'RightArrow',
217
+ });
218
+ expect(document.activeElement.textContent).toBe('A1');
219
+
220
+ a1 = createEventTarget(document.activeElement);
221
+ a1.keydown({
222
+ key: 'RightArrow',
223
+ });
224
+ expect(document.activeElement.textContent).toBe('A2');
225
+
226
+ a2 = createEventTarget(document.activeElement);
227
+ a2.keydown({
228
+ key: 'RightArrow',
229
+ });
230
+ expect(document.activeElement.textContent).toBe('A3');
231
+
232
+ a3 = createEventTarget(document.activeElement);
233
+ a3.keydown({
234
+ key: 'RightArrow',
235
+ });
236
+ expect(document.activeElement.textContent).toBe('A1');
237
+
238
+ a1 = createEventTarget(document.activeElement);
239
+ a1.keydown({
240
+ key: 'RightArrow',
241
+ });
242
+ expect(document.activeElement.textContent).toBe('A2');
243
+
244
+ a2 = createEventTarget(document.activeElement);
245
+ a2.keydown({
246
+ key: 'RightArrow',
247
+ });
248
+ expect(document.activeElement.textContent).toBe('A3');
249
+
250
+ a3 = createEventTarget(document.activeElement);
251
+ a3.keydown({
252
+ key: 'RightArrow',
253
+ });
254
+ expect(document.activeElement.textContent).toBe('A3');
255
+ });
256
+ });
257
+});
packages/shared/ReactTypes.js
+1
@@ -168,6 +168,7 @@ export type ReactScopeMethods = {|
168
getChildren(): null | Array<ReactScopeMethods>,
169
getChildrenFromRoot(): null | Array<ReactScopeMethods>,
170
getParent(): null | ReactScopeMethods,
171
+ getProps(): Object,
172
getScopedNodes(): null | Array<Object>,
173
|};
174