summaryrefslogtreecommitdiffstats
path: root/devtools/client/debugger/src/components/shared/ManagedTree.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /devtools/client/debugger/src/components/shared/ManagedTree.js
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/client/debugger/src/components/shared/ManagedTree.js')
-rw-r--r--devtools/client/debugger/src/components/shared/ManagedTree.js162
1 files changed, 162 insertions, 0 deletions
diff --git a/devtools/client/debugger/src/components/shared/ManagedTree.js b/devtools/client/debugger/src/components/shared/ManagedTree.js
new file mode 100644
index 0000000000..6574782cd0
--- /dev/null
+++ b/devtools/client/debugger/src/components/shared/ManagedTree.js
@@ -0,0 +1,162 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
+
+// @flow
+import React, { Component } from "react";
+import "./ManagedTree.css";
+
+// $FlowIgnore
+const Tree = require("devtools/client/shared/components/Tree");
+
+export type Item = {
+ contents: any,
+ name: string,
+ path: string,
+};
+
+type Props = {
+ autoExpandAll: boolean,
+ autoExpandDepth: number,
+ getChildren: Object => Object[],
+ getPath: (Object, index?: number) => string,
+ getParent: Item => any,
+ getRoots: () => any,
+ highlightItems?: Array<Item>,
+ itemHeight: number,
+ listItems?: Array<Item>,
+ onFocus: (item: any) => void,
+ onExpand?: (item: Item, expanded: Set<string>) => void,
+ onCollapse?: (item: Item, expanded: Set<string>) => void,
+ renderItem: any,
+ focused?: any,
+ expanded?: any,
+};
+
+type State = {
+ expanded: any,
+};
+
+class ManagedTree extends Component<Props, State> {
+ constructor(props: Props) {
+ super(props);
+ this.state = {
+ expanded: props.expanded || new Set(),
+ };
+ }
+
+ static defaultProps = {
+ onFocus: () => {},
+ };
+
+ componentWillReceiveProps(nextProps: Props) {
+ const { listItems, highlightItems } = this.props;
+ if (nextProps.listItems && nextProps.listItems != listItems) {
+ this.expandListItems(nextProps.listItems);
+ }
+
+ if (
+ nextProps.highlightItems &&
+ nextProps.highlightItems != highlightItems &&
+ nextProps.highlightItems.length
+ ) {
+ this.highlightItem(nextProps.highlightItems);
+ }
+ }
+
+ setExpanded = (
+ item: Item,
+ isExpanded: boolean,
+ shouldIncludeChildren: boolean
+ ) => {
+ const expandItem = i => {
+ const path = this.props.getPath(i);
+ if (isExpanded) {
+ expanded.add(path);
+ } else {
+ expanded.delete(path);
+ }
+ };
+ const { expanded } = this.state;
+ expandItem(item);
+
+ if (shouldIncludeChildren) {
+ let parents = [item];
+ while (parents.length) {
+ const children = [];
+ for (const parent of parents) {
+ if (parent.contents?.length) {
+ for (const child of parent.contents) {
+ expandItem(child);
+ children.push(child);
+ }
+ }
+ }
+ parents = children;
+ }
+ }
+ this.setState({ expanded });
+
+ if (isExpanded && this.props.onExpand) {
+ this.props.onExpand(item, expanded);
+ } else if (!isExpanded && this.props.onCollapse) {
+ this.props.onCollapse(item, expanded);
+ }
+ };
+
+ expandListItems(listItems: Array<Item>) {
+ const { expanded } = this.state;
+ listItems.forEach(item => expanded.add(this.props.getPath(item)));
+ this.props.onFocus(listItems[0]);
+ this.setState({ expanded });
+ }
+
+ highlightItem(highlightItems: Array<Item>) {
+ const { expanded } = this.state;
+ // This file is visible, so we highlight it.
+ if (expanded.has(this.props.getPath(highlightItems[0]))) {
+ this.props.onFocus(highlightItems[0]);
+ } else {
+ // Look at folders starting from the top-level until finds a
+ // closed folder and highlights this folder
+ const index = highlightItems
+ .reverse()
+ .findIndex(
+ item =>
+ !expanded.has(this.props.getPath(item)) && item.name !== "root"
+ );
+
+ if (highlightItems[index]) {
+ this.props.onFocus(highlightItems[index]);
+ }
+ }
+ }
+
+ render() {
+ const { expanded } = this.state;
+ return (
+ <div className="managed-tree">
+ <Tree
+ {...this.props}
+ isExpanded={item => expanded.has(this.props.getPath(item))}
+ focused={this.props.focused}
+ getKey={this.props.getPath}
+ onExpand={(item, shouldIncludeChildren) =>
+ this.setExpanded(item, true, shouldIncludeChildren)
+ }
+ onCollapse={(item, shouldIncludeChildren) =>
+ this.setExpanded(item, false, shouldIncludeChildren)
+ }
+ onFocus={this.props.onFocus}
+ renderItem={(...args) =>
+ this.props.renderItem(...args, {
+ setExpanded: this.setExpanded,
+ })
+ }
+ />
+ </div>
+ );
+ }
+}
+
+export default ManagedTree;