24
import Icon from '../Icon';
25
import {SettingsContext} from '../Settings/SettingsContext';
26
import {BridgeContext, StoreContext, OptionsContext} from '../context';
27
-import Element from './Element';
27
+import ComponentsTreeElement from './Element';
28
import InspectHostNodesToggle from './InspectHostNodesToggle';
29
import OwnersStack from './OwnersStack';
30
import ComponentSearchInput from './ComponentSearchInput';
93
94
const treeRef = useRef<HTMLDivElement | null>(null);
95
const focusTargetRef = useRef<HTMLDivElement | null>(null);
96
- const listRef = useRef(null);
97
- const listDOMElementRef = useRef(null);
96
+ const listDOMElementRef = useRef<Element | null>(null);
97
+ const setListDOMElementRef = useCallback((listDOMElement: Element) => {
98
+ listDOMElementRef.current = listDOMElement;
99
+
100
+ // Controls the initial horizontal offset of the Tree if the element was pre-selected. For example, via Elements panel in browser DevTools.
101
+ // Initial vertical offset is controlled via initialScrollOffset prop of the FixedSizeList component.
102
+ if (
103
+ !componentsPanelVisible ||
104
+ inspectedElementIndex == null ||
105
+ listDOMElement == null
106
+ ) {
107
+ return;
108
+ }
109
+
110
+ const element = store.getElementAtIndex(inspectedElementIndex);
111
+ if (element == null) {
112
+ return;
113
+ }
114
+
115
+ const viewportLeft = listDOMElement.scrollLeft;
116
+ const viewportRight = viewportLeft + listDOMElement.clientWidth;
117
+ const elementLeft = calculateElementOffset(element.depth);
118
+ // Because of virtualization, this element might not be rendered yet; we can't look up its width.
119
+ // Assuming that it may take up to the half of the viewport.
120
+ const elementRight = elementLeft + listDOMElement.clientWidth / 2;
121
+
122
+ const isElementFullyVisible =
123
+ elementLeft >= viewportLeft && elementRight <= viewportRight;
124
+
125
+ if (!isElementFullyVisible) {
126
+ const horizontalDelta =
127
+ Math.min(0, elementLeft - viewportLeft) +
128
+ Math.max(0, elementRight - viewportRight);
129
+
130
+ // $FlowExpectedError[incompatible-call] Flow doesn't support instant as an option for behavior.
131
+ listDOMElement.scrollBy({
132
+ left: horizontalDelta,
133
+ behavior: 'instant',
134
+ });
135
+ }
136
+ }, []);
137
138
useEffect(() => {
139
if (!componentsPanelVisible || inspectedElementIndex == null) {
157
}
158
const elementLeft = calculateElementOffset(element.depth);
159
// Because of virtualization, this element might not be rendered yet; we can't look up its width.
121
- // Assuming that it may take up to the half of the vieport.
160
+ // Assuming that it may take up to the half of the viewport.
161
const elementRight = elementLeft + listDOMElement.clientWidth / 2;
162
const elementTop = inspectedElementIndex * lineHeight;
163
const elementBottom = elementTop + lineHeight;
176
Math.min(0, elementLeft - viewportLeft) +
177
Math.max(0, elementRight - viewportRight);
178
179
+ // $FlowExpectedError[incompatible-call] Flow doesn't support instant as an option for behavior.
180
listDOMElement.scrollBy({
181
top: verticalDelta,
182
left: horizontalDelta,
511
itemData={itemData}
512
itemKey={itemKey}
513
itemSize={lineHeight}
474
- ref={listRef}
475
- outerRef={listDOMElementRef}
514
+ outerRef={setListDOMElementRef}
515
overscanCount={10}
516
width={width}>
478
- {Element}
517
+ {ComponentsTreeElement}
518
</FixedSizeList>
519
)}
520
</AutoSizer>