Scroll to Inspected Element

Summary:
changelog: Add scroll to inspected element in layout plugin

Before this diff, when one inspected an element, one needed to scroll down to see highlighted line for that element. This diff added automatic scroll to inspected element. It will scroll so that the line is in middle of the app.

Also, fix direct state mutation and this error:
```
Public property 'onKeyDown' of exported class has or is using private name 'Element'.
```

Reviewed By: passy, mweststrate

Differential Revision: D20798587

fbshipit-source-id: 763eb63cd51abd73940e301e36e89232033722c3
This commit is contained in:
Chaiwat Ekkaewnumchai
2020-04-03 03:01:25 -07:00
committed by Facebook GitHub Bot
parent e68cbe8ecd
commit e37bccaf04
3 changed files with 47 additions and 5 deletions

View File

@@ -223,6 +223,7 @@ type ElementsRowProps = {
style?: Object;
contextMenuExtensions: Array<ContextMenuExtension>;
decorateRow?: DecorateRow;
forwardedRef: React.Ref<HTMLDivElement> | null;
};
type ElementsRowState = {
@@ -324,6 +325,7 @@ class ElementsRow extends PureComponent<ElementsRowProps, ElementsRowState> {
even,
matchingSearchQuery,
decorateRow,
forwardedRef,
} = this.props;
const hasChildren = element.children && element.children.length > 0;
@@ -378,6 +380,7 @@ class ElementsRow extends PureComponent<ElementsRowProps, ElementsRowState> {
return (
<ElementsRowContainer
ref={forwardedRef}
buildItems={this.getContextMenu}
key={id}
level={level}
@@ -465,6 +468,7 @@ export class Elements extends PureComponent<ElementsProps, ElementsState> {
static defaultProps = {
alternateRowColor: true,
};
_outerRef = React.createRef<HTMLDivElement>();
constructor(props: ElementsProps, context: Object) {
super(props, context);
this.state = {
@@ -514,6 +518,22 @@ export class Elements extends PureComponent<ElementsProps, ElementsState> {
return {flatElements, flatKeys, maxDepth};
}
_calculateScrollTop(
parentHeight: number,
parentOffsetTop: number,
childHeight: number,
childOffsetTop: number,
): number {
const childOffsetMid = childOffsetTop + childHeight / 2;
if (
parentOffsetTop < childOffsetMid &&
childOffsetMid < parentOffsetTop + parentHeight
) {
return parentOffsetTop;
}
return childOffsetMid - parentHeight / 2;
}
selectElement = (key: ElementID) => {
this.props.onElementSelected(key);
};
@@ -651,6 +671,25 @@ export class Elements extends PureComponent<ElementsProps, ElementsState> {
childrenCount={childrenCount}
contextMenuExtensions={contextMenuExtensions || []}
decorateRow={decorateRow}
forwardedRef={
selected == row.key
? (selectedRow) => {
if (!selectedRow || !this._outerRef.current) {
return;
}
const outer = this._outerRef.current;
outer.scrollTo(
0,
this._calculateScrollTop(
outer.offsetHeight,
outer.scrollTop,
selectedRow.offsetHeight,
selectedRow.offsetTop,
),
);
}
: null
}
/>
);
};
@@ -658,7 +697,10 @@ export class Elements extends PureComponent<ElementsProps, ElementsState> {
render() {
return (
<ElementsBox>
<ElementsContainer onKeyDown={this.onKeyDown} tabIndex={0}>
<ElementsContainer
onKeyDown={this.onKeyDown}
tabIndex={0}
ref={this._outerRef}>
{this.state.flatElements.map(this.buildRow)}
</ElementsContainer>
</ElementsBox>

View File

@@ -431,15 +431,15 @@ export class ManagedTable extends React.Component<
highlightedRows.add(row.key);
} else if (e.shiftKey && this.props.multiHighlight) {
// range select
const lastItemKey = Array.from(this.state.highlightedRows).pop()!;
const lastItemKey = Array.from(highlightedRows).pop()!;
highlightedRows = new Set([
...highlightedRows,
...this.selectInRange(lastItemKey, row.key),
]);
} else {
// single select
this.state.highlightedRows.clear();
this.state.highlightedRows.add(row.key);
highlightedRows.clear();
highlightedRows.add(row.key);
}
this.onRowHighlighted(highlightedRows);

View File

@@ -68,7 +68,7 @@ export default class Search extends Component<Props, State> {
this.timer = setTimeout(() => this.performSearch(value), 200);
};
onKeyDown = (e: React.KeyboardEvent) => {
onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
this.performSearch(this.state.value);
}