mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Left arrow selects parent in tree
This commit is contained in:
@@ -118,7 +118,7 @@ export default class Store extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
return ((currentElement: any): Element);
|
||||
return ((currentElement: any): Element) || null;
|
||||
}
|
||||
|
||||
getElementIDAtIndex(index: number): number | null {
|
||||
@@ -141,7 +141,7 @@ export default class Store extends EventEmitter {
|
||||
getIndexOfElementID(id: number): number | null {
|
||||
const element = this.getElementByID(id);
|
||||
|
||||
if (element === null) {
|
||||
if (element === null || element.parentID === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,16 @@ export default function SearchInput(props: Props) {
|
||||
setSearchText('');
|
||||
}, [setSearchText]);
|
||||
|
||||
const handleKeyDown = useCallback(event => {
|
||||
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {
|
||||
// It's convenient for up/down arrow keys to change the selected element when focused on the search input.
|
||||
// But e.g. left/right arrow keys should move the text cursor.
|
||||
// For now just block everything except for up/down arrow keys.
|
||||
// TODO Revisit this approach.
|
||||
event.stopPropagation();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleInputKeyPress = useCallback(
|
||||
({ key }) => {
|
||||
if (key === 'Enter') {
|
||||
@@ -62,8 +72,9 @@ export default function SearchInput(props: Props) {
|
||||
<Icon className={styles.InputIcon} type="search" />
|
||||
<input
|
||||
className={styles.Input}
|
||||
onKeyPress={handleInputKeyPress}
|
||||
onChange={handleTextChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
onKeyPress={handleInputKeyPress}
|
||||
placeholder="Search (text or /regex/)"
|
||||
ref={inputRef}
|
||||
value={searchText}
|
||||
|
||||
@@ -28,6 +28,7 @@ export default function Tree(props: Props) {
|
||||
ownerStack,
|
||||
selectedElementIndex,
|
||||
selectNextElementInTree,
|
||||
selectParentElementInTree,
|
||||
selectPreviousElementInTree,
|
||||
} = useContext(TreeContext);
|
||||
const listRef = useRef<FixedSizeList<any> | null>(null);
|
||||
@@ -51,6 +52,14 @@ export default function Tree(props: Props) {
|
||||
selectNextElementInTree();
|
||||
event.preventDefault();
|
||||
break;
|
||||
case 'ArrowLeft':
|
||||
console.log('LEFT');
|
||||
selectParentElementInTree();
|
||||
break;
|
||||
case 'ArrowRight':
|
||||
selectNextElementInTree();
|
||||
event.preventDefault();
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
selectPreviousElementInTree();
|
||||
event.preventDefault();
|
||||
@@ -63,7 +72,11 @@ export default function Tree(props: Props) {
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}, [selectNextElementInTree, selectPreviousElementInTree]);
|
||||
}, [
|
||||
selectNextElementInTree,
|
||||
selectParentElementInTree,
|
||||
selectPreviousElementInTree,
|
||||
]);
|
||||
|
||||
// Let react-window know to re-render any time the underlying tree data changes.
|
||||
// This includes the owner context, since it controls a filtered view of the tree.
|
||||
|
||||
@@ -41,6 +41,7 @@ type Context = {|
|
||||
selectElementAtIndex(index: number): void,
|
||||
selectElementByID(id: number | null): void,
|
||||
selectNextElementInTree(): void,
|
||||
selectParentElementInTree(): void,
|
||||
selectPreviousElementInTree(): void,
|
||||
|
||||
// Search
|
||||
@@ -91,6 +92,7 @@ type Action = {|
|
||||
| 'SELECT_ELEMENT_AT_INDEX'
|
||||
| 'SELECT_ELEMENT_BY_ID'
|
||||
| 'SELECT_NEXT_ELEMENT_IN_TREE'
|
||||
| 'SELECT_PARENT_ELEMENT_IN_TREE'
|
||||
| 'SELECT_PREVIOUS_ELEMENT_IN_TREE'
|
||||
| 'SELECT_OWNER'
|
||||
| 'SET_SEARCH_TEXT',
|
||||
@@ -138,6 +140,17 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
|
||||
selectedElementIndex++;
|
||||
}
|
||||
break;
|
||||
case 'SELECT_PARENT_ELEMENT_IN_TREE':
|
||||
if (selectedElementIndex !== null) {
|
||||
const selectedElement = store.getElementAtIndex(
|
||||
((selectedElementIndex: any): number)
|
||||
);
|
||||
if (selectedElement !== null && selectedElement.parentID !== null) {
|
||||
selectedElementIndex =
|
||||
store.getIndexOfElementID(selectedElement.parentID) || 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'SELECT_PREVIOUS_ELEMENT_IN_TREE':
|
||||
if (selectedElementIndex !== null && selectedElementIndex > 0) {
|
||||
selectedElementIndex--;
|
||||
@@ -502,6 +515,7 @@ function TreeContextController({ children, viewElementSource }: Props) {
|
||||
case 'SELECT_ELEMENT_AT_INDEX':
|
||||
case 'SELECT_ELEMENT_BY_ID':
|
||||
case 'SELECT_NEXT_ELEMENT_IN_TREE':
|
||||
case 'SELECT_PARENT_ELEMENT_IN_TREE':
|
||||
case 'SELECT_PREVIOUS_ELEMENT_IN_TREE':
|
||||
case 'SELECT_OWNER':
|
||||
case 'SET_SEARCH_TEXT':
|
||||
@@ -572,6 +586,10 @@ function TreeContextController({ children, viewElementSource }: Props) {
|
||||
() => dispatch({ type: 'SELECT_NEXT_ELEMENT_IN_TREE' }),
|
||||
[dispatch]
|
||||
);
|
||||
const selectParentElementInTree = useCallback(
|
||||
() => dispatch({ type: 'SELECT_PARENT_ELEMENT_IN_TREE' }),
|
||||
[dispatch]
|
||||
);
|
||||
const selectPreviousElementInTree = useCallback(
|
||||
() => dispatch({ type: 'SELECT_PREVIOUS_ELEMENT_IN_TREE' }),
|
||||
[dispatch]
|
||||
@@ -592,6 +610,7 @@ function TreeContextController({ children, viewElementSource }: Props) {
|
||||
selectElementByID,
|
||||
selectElementAtIndex,
|
||||
selectNextElementInTree,
|
||||
selectParentElementInTree,
|
||||
selectPreviousElementInTree,
|
||||
|
||||
// Search
|
||||
@@ -619,6 +638,7 @@ function TreeContextController({ children, viewElementSource }: Props) {
|
||||
selectElementAtIndex,
|
||||
selectElementByID,
|
||||
selectNextElementInTree,
|
||||
selectParentElementInTree,
|
||||
selectOwner,
|
||||
selectPreviousElementInTree,
|
||||
setSearchText,
|
||||
|
||||
Reference in New Issue
Block a user