Left arrow selects parent in tree
Brian Vaughn committed
Feb 27, 2019 at 13:49 UTC
0153eaedee768336d3e849b18c8889a13c752e1b
4 files changed
+48
-4
src/devtools/store.js
+2
-2
@@ -118,7 +118,7 @@ export default class Store extends EventEmitter {
118
}
119
}
120
121
- return ((currentElement: any): Element);
121
+ return ((currentElement: any): Element) || null;
122
}
123
124
getElementIDAtIndex(index: number): number | null {
@@ -141,7 +141,7 @@ export default class Store extends EventEmitter {
141
getIndexOfElementID(id: number): number | null {
142
const element = this.getElementByID(id);
143
144
- if (element === null) {
144
+ if (element === null || element.parentID === 0) {
145
return null;
146
}
147
src/devtools/views/SearchInput.js
+12
-1
@@ -31,6 +31,16 @@ export default function SearchInput(props: Props) {
31
setSearchText('');
32
}, [setSearchText]);
33
34
+ const handleKeyDown = useCallback(event => {
35
+ if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {
36
+ // It's convenient for up/down arrow keys to change the selected element when focused on the search input.
37
+ // But e.g. left/right arrow keys should move the text cursor.
38
+ // For now just block everything except for up/down arrow keys.
39
+ // TODO Revisit this approach.
40
+ event.stopPropagation();
41
+ }
42
+ }, []);
43
+
44
const handleInputKeyPress = useCallback(
45
({ key }) => {
46
if (key === 'Enter') {
@@ -62,8 +72,9 @@ export default function SearchInput(props: Props) {
72
<Icon className={styles.InputIcon} type="search" />
73
<input
74
className={styles.Input}
65
- onKeyPress={handleInputKeyPress}
75
onChange={handleTextChange}
76
+ onKeyDown={handleKeyDown}
77
+ onKeyPress={handleInputKeyPress}
78
placeholder="Search (text or /regex/)"
79
ref={inputRef}
80
value={searchText}
src/devtools/views/Tree.js
+14
-1
@@ -28,6 +28,7 @@ export default function Tree(props: Props) {
28
ownerStack,
29
selectedElementIndex,
30
selectNextElementInTree,
31
+ selectParentElementInTree,
32
selectPreviousElementInTree,
33
} = useContext(TreeContext);
34
const listRef = useRef<FixedSizeList<any> | null>(null);
@@ -51,6 +52,14 @@ export default function Tree(props: Props) {
52
selectNextElementInTree();
53
event.preventDefault();
54
break;
55
+ case 'ArrowLeft':
56
+ console.log('LEFT');
57
+ selectParentElementInTree();
58
+ break;
59
+ case 'ArrowRight':
60
+ selectNextElementInTree();
61
+ event.preventDefault();
62
+ break;
63
case 'ArrowUp':
64
selectPreviousElementInTree();
65
event.preventDefault();
@@ -63,7 +72,11 @@ export default function Tree(props: Props) {
72
return () => {
73
window.removeEventListener('keydown', handleKeyDown);
74
};
66
- }, [selectNextElementInTree, selectPreviousElementInTree]);
75
+ }, [
76
+ selectNextElementInTree,
77
+ selectParentElementInTree,
78
+ selectPreviousElementInTree,
79
+ ]);
80
81
// Let react-window know to re-render any time the underlying tree data changes.
82
// This includes the owner context, since it controls a filtered view of the tree.
src/devtools/views/TreeContext.js
+20
@@ -41,6 +41,7 @@ type Context = {|
41
selectElementAtIndex(index: number): void,
42
selectElementByID(id: number | null): void,
43
selectNextElementInTree(): void,
44
+ selectParentElementInTree(): void,
45
selectPreviousElementInTree(): void,
46
47
// Search
@@ -91,6 +92,7 @@ type Action = {|
92
| 'SELECT_ELEMENT_AT_INDEX'
93
| 'SELECT_ELEMENT_BY_ID'
94
| 'SELECT_NEXT_ELEMENT_IN_TREE'
95
+ | 'SELECT_PARENT_ELEMENT_IN_TREE'
96
| 'SELECT_PREVIOUS_ELEMENT_IN_TREE'
97
| 'SELECT_OWNER'
98
| 'SET_SEARCH_TEXT',
@@ -138,6 +140,17 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
140
selectedElementIndex++;
141
}
142
break;
143
+ case 'SELECT_PARENT_ELEMENT_IN_TREE':
144
+ if (selectedElementIndex !== null) {
145
+ const selectedElement = store.getElementAtIndex(
146
+ ((selectedElementIndex: any): number)
147
+ );
148
+ if (selectedElement !== null && selectedElement.parentID !== null) {
149
+ selectedElementIndex =
150
+ store.getIndexOfElementID(selectedElement.parentID) || 0;
151
+ }
152
+ }
153
+ break;
154
case 'SELECT_PREVIOUS_ELEMENT_IN_TREE':
155
if (selectedElementIndex !== null && selectedElementIndex > 0) {
156
selectedElementIndex--;
@@ -502,6 +515,7 @@ function TreeContextController({ children, viewElementSource }: Props) {
515
case 'SELECT_ELEMENT_AT_INDEX':
516
case 'SELECT_ELEMENT_BY_ID':
517
case 'SELECT_NEXT_ELEMENT_IN_TREE':
518
+ case 'SELECT_PARENT_ELEMENT_IN_TREE':
519
case 'SELECT_PREVIOUS_ELEMENT_IN_TREE':
520
case 'SELECT_OWNER':
521
case 'SET_SEARCH_TEXT':
@@ -572,6 +586,10 @@ function TreeContextController({ children, viewElementSource }: Props) {
586
() => dispatch({ type: 'SELECT_NEXT_ELEMENT_IN_TREE' }),
587
[dispatch]
588
);
589
+ const selectParentElementInTree = useCallback(
590
+ () => dispatch({ type: 'SELECT_PARENT_ELEMENT_IN_TREE' }),
591
+ [dispatch]
592
+ );
593
const selectPreviousElementInTree = useCallback(
594
() => dispatch({ type: 'SELECT_PREVIOUS_ELEMENT_IN_TREE' }),
595
[dispatch]
@@ -592,6 +610,7 @@ function TreeContextController({ children, viewElementSource }: Props) {
610
selectElementByID,
611
selectElementAtIndex,
612
selectNextElementInTree,
613
+ selectParentElementInTree,
614
selectPreviousElementInTree,
615
616
// Search
@@ -619,6 +638,7 @@ function TreeContextController({ children, viewElementSource }: Props) {
638
selectElementAtIndex,
639
selectElementByID,
640
selectNextElementInTree,
641
+ selectParentElementInTree,
642
selectOwner,
643
selectPreviousElementInTree,
644
setSearchText,