Use focus state from elements tree instead of ownerDocument
Lucas Cordeiro committed
Apr 9, 2019 at 18:58 UTC
1c57ca0a1c00705a679e26bc6950d2bf28ec9e82
2 files changed
+38
-31
src/devtools/views/Components/Element.js
+2
-29
@@ -2,10 +2,8 @@
2
3
import React, {
4
Fragment,
5
- useState,
5
useCallback,
6
useContext,
8
- useEffect,
7
useLayoutEffect,
8
useMemo,
9
useRef,
@@ -37,13 +35,12 @@ export default function ElementView({ data, index, style }: Props) {
35
const bridge = useContext(BridgeContext);
36
const store = useContext(StoreContext);
37
40
- const [windowFocused, setWindowFocused] = useState<boolean>(true);
41
-
38
const element = getElementAtIndex(index);
39
40
const id = element === null ? null : element.id;
41
const isSelected = selectedElementID === id;
42
const lastScrolledIDRef = data.lastScrolledIDRef;
43
+ const treeFocused = data.treeFocused;
44
45
const handleDoubleClick = useCallback(() => {
46
if (id !== null) {
@@ -53,30 +50,6 @@ export default function ElementView({ data, index, style }: Props) {
50
51
const ref = useRef<HTMLSpanElement | null>(null);
52
56
- useEffect(() => {
57
- if (ref.current === null || !isSelected) {
58
- return () => {};
59
- }
60
-
61
- const handleFocus = () => {
62
- setWindowFocused(true);
63
- };
64
-
65
- const handleBlur = () => {
66
- setWindowFocused(false);
67
- };
68
-
69
- const ownerDocument = ref.current.ownerDocument.defaultView;
70
-
71
- ownerDocument.addEventListener('focus', handleFocus);
72
- ownerDocument.addEventListener('blur', handleBlur);
73
-
74
- return () => {
75
- ownerDocument.removeEventListener('focus', handleFocus);
76
- ownerDocument.removeEventListener('blur', handleBlur);
77
- };
78
- }, [isSelected]);
79
-
53
// The tree above has its own autoscrolling, but it only works for rows.
54
// However, even when the row gets into the viewport, the component name
55
// might be too far left or right on the screen. Adjust it in this case.
@@ -147,7 +120,7 @@ export default function ElementView({ data, index, style }: Props) {
120
return (
121
<div
122
className={
150
- isSelected && windowFocused
123
+ isSelected && treeFocused
124
? styles.SelectedElement
125
: isSelected
126
? styles.InactiveElement
src/devtools/views/Components/Tree.js
+36
-2
@@ -1,6 +1,7 @@
1
// @flow
2
3
import React, {
4
+ useState,
5
useCallback,
6
useContext,
7
useEffect,
@@ -27,6 +28,7 @@ export type ItemData = {|
28
numElements: number,
29
getElementAtIndex: (index: number) => Element | null,
30
lastScrolledIDRef: { current: number | null },
31
+ treeFocused: boolean,
32
|};
33
34
type Props = {||};
@@ -46,6 +48,9 @@ export default function Tree(props: Props) {
48
// $FlowFixMe https://github.com/facebook/flow/issues/7341
49
const listRef = useRef<FixedSizeList<ItemData> | null>(null);
50
const treeRef = useRef<HTMLDivElement | null>(null);
51
+ const elementsRef = useRef<HTMLDivElement | null>(null);
52
+
53
+ const [treeFocused, setTreeFocused] = useState<boolean>(false);
54
55
const { lineHeight } = useContext(SettingsContext);
56
@@ -112,6 +117,30 @@ export default function Tree(props: Props) {
117
selectPreviousElementInTree,
118
]);
119
120
+ useEffect(() => {
121
+ if (elementsRef.current === null) {
122
+ return () => {};
123
+ }
124
+
125
+ const handleFocusIn = () => {
126
+ setTreeFocused(true);
127
+ };
128
+
129
+ const handleFocusOut = () => {
130
+ setTreeFocused(false);
131
+ };
132
+
133
+ const elementsElement = elementsRef.current;
134
+
135
+ elementsElement.addEventListener('focusin', handleFocusIn);
136
+ elementsElement.addEventListener('focusout', handleFocusOut);
137
+
138
+ return () => {
139
+ elementsElement.removeEventListener('focusin', handleFocusIn);
140
+ elementsElement.removeEventListener('focusout', handleFocusOut);
141
+ };
142
+ }, []);
143
+
144
// Let react-window know to re-render any time the underlying tree data changes.
145
// This includes the owner context, since it controls a filtered view of the tree.
146
const itemData = useMemo<ItemData>(
@@ -120,8 +149,9 @@ export default function Tree(props: Props) {
149
numElements,
150
getElementAtIndex,
151
lastScrolledIDRef,
152
+ treeFocused,
153
}),
124
- [baseDepth, numElements, getElementAtIndex, lastScrolledIDRef]
154
+ [baseDepth, numElements, getElementAtIndex, lastScrolledIDRef, treeFocused]
155
);
156
157
const handleMouseLeave = useCallback(() => {
@@ -134,7 +164,11 @@ export default function Tree(props: Props) {
164
{ownerStack.length > 0 ? <OwnersStack /> : <SearchInput />}
165
<InspectHostNodesToggle />
166
</div>
137
- <div className={styles.AutoSizerWrapper} onMouseLeave={handleMouseLeave}>
167
+ <div
168
+ className={styles.AutoSizerWrapper}
169
+ onMouseLeave={handleMouseLeave}
170
+ ref={elementsRef}
171
+ >
172
<AutoSizer>
173
{({ height, width }) => (
174
// $FlowFixMe https://github.com/facebook/flow/issues/7341