props) { const { name, value } = props; const { filterText } = this.props; if (!filterText) { return true; } const jsonString = JSON.stringify({ [name]: value }).toLowerCase(); return jsonString.includes(filterText.toLowerCase()); } getSelectedPath(targetSearchResult) { if (!targetSearchResult) { return null; } return `/${targetSearchResult.label}`; } /** * If target is selected, let's scroll the content * so the property is visible. This is used for search result navigation, * which happens when the user clicks on a search result. */ scrollSelectedIntoView() { const { targetSearchResult, resetTargetSearchResult, selectPath } = this.props; if (!targetSearchResult) { return; } const path = typeof selectPath == "function" ? selectPath(targetSearchResult) : this.getSelectedPath(targetSearchResult); const element = document.getElementById(path); if (element) { element.scrollIntoView({ block: "center" }); } resetTargetSearchResult(); } onContextMenuRow(member, evt) { evt.preventDefault(); const { object } = member; // Select the right clicked row this.selectRow({ props: { member } }); // if data exists and can be copied, then show the contextmenu if (typeof object === "object") { if (!this.contextMenu) { this.contextMenu = new PropertiesViewContextMenu({ customFormatters: this.props.contextMenuFormatters, }); } this.contextMenu.open(evt, window.getSelection(), { member, object: this.props.object, }); } } renderValueWithRep(props) { const { member } = props; /* Hide strings with following conditions * - the `value` object has a `value` property (only happens in Cookies panel) */ if (typeof member.value === "object" && member.value?.value) { return null; } return Rep( Object.assign(props, { // FIXME: A workaround for the issue in StringRep // Force StringRep to crop the text every time member: Object.assign({}, member, { open: false }), mode: this.props.mode || MODE.TINY, cropLimit: this.props.cropLimit, noGrip: true, }) ); } render() { const { useBaseTreeViewExpand, expandedNodes, object, renderValue, targetSearchResult, selectPath, } = this.props; let currentExpandedNodes; // In the TreeView, when the component is re-rendered // the state of `expandedNodes` is persisted by default // e.g. when you open a node and filter the properties list, // the node remains open. // We have the prop `useBaseTreeViewExpand` to flag when we want to use // this functionality or not. if (!useBaseTreeViewExpand) { currentExpandedNodes = expandedNodes || TreeViewClass.getExpandedNodes(object, { maxLevel: AUTO_EXPAND_MAX_LEVEL, maxNodes: AUTO_EXPAND_MAX_NODES, }); } else { // Ensure passing a stable expanded Set, // so that TreeView doesn't reset to default prop's Set // on each new received props. currentExpandedNodes = this.expandedNodes; } return div( { className: "properties-view" }, div( { className: "tree-container" }, TreeView({ ...this.props, ref: () => this.scrollSelectedIntoView(), columns: [{ id: "value", width: "100%" }], expandedNodes: currentExpandedNodes, onFilter: props => this.onFilter(props), renderValue: renderValue || this.renderValueWithRep, onContextMenuRow: this.onContextMenuRow, selected: typeof selectPath == "function" ? selectPath(targetSearchResult) : this.getSelectedPath(targetSearchResult), }) ) ); } } module.exports = connect(null, dispatch => ({ resetTargetSearchResult: () => dispatch(setTargetSearchResult(null)), }))(PropertiesVi