mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Use focus state from elements tree instead of ownerDocument
This commit is contained in:
@@ -2,10 +2,8 @@
|
||||
|
||||
import React, {
|
||||
Fragment,
|
||||
useState,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
@@ -37,13 +35,12 @@ export default function ElementView({ data, index, style }: Props) {
|
||||
const bridge = useContext(BridgeContext);
|
||||
const store = useContext(StoreContext);
|
||||
|
||||
const [windowFocused, setWindowFocused] = useState<boolean>(true);
|
||||
|
||||
const element = getElementAtIndex(index);
|
||||
|
||||
const id = element === null ? null : element.id;
|
||||
const isSelected = selectedElementID === id;
|
||||
const lastScrolledIDRef = data.lastScrolledIDRef;
|
||||
const treeFocused = data.treeFocused;
|
||||
|
||||
const handleDoubleClick = useCallback(() => {
|
||||
if (id !== null) {
|
||||
@@ -53,30 +50,6 @@ export default function ElementView({ data, index, style }: Props) {
|
||||
|
||||
const ref = useRef<HTMLSpanElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (ref.current === null || !isSelected) {
|
||||
return () => {};
|
||||
}
|
||||
|
||||
const handleFocus = () => {
|
||||
setWindowFocused(true);
|
||||
};
|
||||
|
||||
const handleBlur = () => {
|
||||
setWindowFocused(false);
|
||||
};
|
||||
|
||||
const ownerDocument = ref.current.ownerDocument.defaultView;
|
||||
|
||||
ownerDocument.addEventListener('focus', handleFocus);
|
||||
ownerDocument.addEventListener('blur', handleBlur);
|
||||
|
||||
return () => {
|
||||
ownerDocument.removeEventListener('focus', handleFocus);
|
||||
ownerDocument.removeEventListener('blur', handleBlur);
|
||||
};
|
||||
}, [isSelected]);
|
||||
|
||||
// The tree above has its own autoscrolling, but it only works for rows.
|
||||
// However, even when the row gets into the viewport, the component name
|
||||
// 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) {
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
isSelected && windowFocused
|
||||
isSelected && treeFocused
|
||||
? styles.SelectedElement
|
||||
: isSelected
|
||||
? styles.InactiveElement
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import React, {
|
||||
useState,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
@@ -27,6 +28,7 @@ export type ItemData = {|
|
||||
numElements: number,
|
||||
getElementAtIndex: (index: number) => Element | null,
|
||||
lastScrolledIDRef: { current: number | null },
|
||||
treeFocused: boolean,
|
||||
|};
|
||||
|
||||
type Props = {||};
|
||||
@@ -46,6 +48,9 @@ export default function Tree(props: Props) {
|
||||
// $FlowFixMe https://github.com/facebook/flow/issues/7341
|
||||
const listRef = useRef<FixedSizeList<ItemData> | null>(null);
|
||||
const treeRef = useRef<HTMLDivElement | null>(null);
|
||||
const elementsRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const [treeFocused, setTreeFocused] = useState<boolean>(false);
|
||||
|
||||
const { lineHeight } = useContext(SettingsContext);
|
||||
|
||||
@@ -112,6 +117,30 @@ export default function Tree(props: Props) {
|
||||
selectPreviousElementInTree,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (elementsRef.current === null) {
|
||||
return () => {};
|
||||
}
|
||||
|
||||
const handleFocusIn = () => {
|
||||
setTreeFocused(true);
|
||||
};
|
||||
|
||||
const handleFocusOut = () => {
|
||||
setTreeFocused(false);
|
||||
};
|
||||
|
||||
const elementsElement = elementsRef.current;
|
||||
|
||||
elementsElement.addEventListener('focusin', handleFocusIn);
|
||||
elementsElement.addEventListener('focusout', handleFocusOut);
|
||||
|
||||
return () => {
|
||||
elementsElement.removeEventListener('focusin', handleFocusIn);
|
||||
elementsElement.removeEventListener('focusout', handleFocusOut);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 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.
|
||||
const itemData = useMemo<ItemData>(
|
||||
@@ -120,8 +149,9 @@ export default function Tree(props: Props) {
|
||||
numElements,
|
||||
getElementAtIndex,
|
||||
lastScrolledIDRef,
|
||||
treeFocused,
|
||||
}),
|
||||
[baseDepth, numElements, getElementAtIndex, lastScrolledIDRef]
|
||||
[baseDepth, numElements, getElementAtIndex, lastScrolledIDRef, treeFocused]
|
||||
);
|
||||
|
||||
const handleMouseLeave = useCallback(() => {
|
||||
@@ -134,7 +164,11 @@ export default function Tree(props: Props) {
|
||||
{ownerStack.length > 0 ? <OwnersStack /> : <SearchInput />}
|
||||
<InspectHostNodesToggle />
|
||||
</div>
|
||||
<div className={styles.AutoSizerWrapper} onMouseLeave={handleMouseLeave}>
|
||||
<div
|
||||
className={styles.AutoSizerWrapper}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
ref={elementsRef}
|
||||
>
|
||||
<AutoSizer>
|
||||
{({ height, width }) => (
|
||||
// $FlowFixMe https://github.com/facebook/flow/issues/7341
|
||||
|
||||
Reference in New Issue
Block a user