diff --git a/desktop/app/src/ui/components/elements-inspector/elements.tsx b/desktop/app/src/ui/components/elements-inspector/elements.tsx index 11d5b6bbb..0c9a3f1dd 100644 --- a/desktop/app/src/ui/components/elements-inspector/elements.tsx +++ b/desktop/app/src/ui/components/elements-inspector/elements.tsx @@ -223,6 +223,7 @@ type ElementsRowProps = { style?: Object; contextMenuExtensions: Array; decorateRow?: DecorateRow; + forwardedRef: React.Ref | null; }; type ElementsRowState = { @@ -324,6 +325,7 @@ class ElementsRow extends PureComponent { even, matchingSearchQuery, decorateRow, + forwardedRef, } = this.props; const hasChildren = element.children && element.children.length > 0; @@ -378,6 +380,7 @@ class ElementsRow extends PureComponent { return ( { static defaultProps = { alternateRowColor: true, }; + _outerRef = React.createRef(); constructor(props: ElementsProps, context: Object) { super(props, context); this.state = { @@ -514,6 +518,22 @@ export class Elements extends PureComponent { 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 { 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 { render() { return ( - + {this.state.flatElements.map(this.buildRow)} diff --git a/desktop/app/src/ui/components/table/ManagedTable.tsx b/desktop/app/src/ui/components/table/ManagedTable.tsx index 11971de0e..57d745396 100644 --- a/desktop/app/src/ui/components/table/ManagedTable.tsx +++ b/desktop/app/src/ui/components/table/ManagedTable.tsx @@ -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); diff --git a/desktop/plugins/layout/Search.tsx b/desktop/plugins/layout/Search.tsx index 6a833a3ec..b1ed9d502 100644 --- a/desktop/plugins/layout/Search.tsx +++ b/desktop/plugins/layout/Search.tsx @@ -68,7 +68,7 @@ export default class Search extends Component { this.timer = setTimeout(() => this.performSearch(value), 200); }; - onKeyDown = (e: React.KeyboardEvent) => { + onKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { this.performSearch(this.state.value); }