summaryrefslogtreecommitdiffstats
path: root/devtools/client/shared/components/tree/TreeCell.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/shared/components/tree/TreeCell.js')
-rw-r--r--devtools/client/shared/components/tree/TreeCell.js145
1 files changed, 145 insertions, 0 deletions
diff --git a/devtools/client/shared/components/tree/TreeCell.js b/devtools/client/shared/components/tree/TreeCell.js
new file mode 100644
index 0000000000..ba5cd43715
--- /dev/null
+++ b/devtools/client/shared/components/tree/TreeCell.js
@@ -0,0 +1,145 @@
+/* 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/. */
+"use strict";
+
+// Make this available to both AMD and CJS environments
+define(function(require, exports, module) {
+ const { Component } = require("devtools/client/shared/vendor/react");
+ const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+ const dom = require("devtools/client/shared/vendor/react-dom-factories");
+ const { input, span, td } = dom;
+
+ /**
+ * This template represents a cell in TreeView row. It's rendered
+ * using <td> element (the row is <tr> and the entire tree is <table>).
+ */
+ class TreeCell extends Component {
+ // See TreeView component for detailed property explanation.
+ static get propTypes() {
+ return {
+ value: PropTypes.any,
+ decorator: PropTypes.object,
+ id: PropTypes.string.isRequired,
+ member: PropTypes.object.isRequired,
+ renderValue: PropTypes.func.isRequired,
+ enableInput: PropTypes.bool,
+ };
+ }
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ inputEnabled: false,
+ };
+
+ this.getCellClass = this.getCellClass.bind(this);
+ this.updateInputEnabled = this.updateInputEnabled.bind(this);
+ }
+
+ /**
+ * Optimize cell rendering. Rerender cell content only if
+ * the value or expanded state changes.
+ */
+ shouldComponentUpdate(nextProps, nextState) {
+ return (
+ this.props.value != nextProps.value ||
+ this.state !== nextState ||
+ this.props.member.open != nextProps.member.open
+ );
+ }
+
+ getCellClass(object, id) {
+ const decorator = this.props.decorator;
+ if (!decorator || !decorator.getCellClass) {
+ return [];
+ }
+
+ // Decorator can return a simple string or array of strings.
+ let classNames = decorator.getCellClass(object, id);
+ if (!classNames) {
+ return [];
+ }
+
+ if (typeof classNames == "string") {
+ classNames = [classNames];
+ }
+
+ return classNames;
+ }
+
+ updateInputEnabled(evt) {
+ this.setState(
+ Object.assign({}, this.state, {
+ inputEnabled: evt.target.nodeName.toLowerCase() !== "input",
+ })
+ );
+ }
+
+ render() {
+ let {
+ member,
+ id,
+ value,
+ decorator,
+ renderValue,
+ enableInput,
+ } = this.props;
+ const type = member.type || "";
+
+ // Compute class name list for the <td> element.
+ const classNames = this.getCellClass(member.object, id) || [];
+ classNames.push("treeValueCell");
+ classNames.push(type + "Cell");
+
+ // Render value using a default render function or custom
+ // provided function from props or a decorator.
+ renderValue = renderValue || defaultRenderValue;
+ if (decorator?.renderValue) {
+ renderValue = decorator.renderValue(member.object, id) || renderValue;
+ }
+
+ const props = Object.assign({}, this.props, {
+ object: value,
+ });
+
+ let cellElement;
+ if (enableInput && this.state.inputEnabled && type !== "object") {
+ classNames.push("inputEnabled");
+ cellElement = input({
+ autoFocus: true,
+ onBlur: this.updateInputEnabled,
+ readOnly: true,
+ value,
+ "aria-labelledby": id,
+ });
+ } else {
+ cellElement = span(
+ {
+ onClick: type !== "object" ? this.updateInputEnabled : null,
+ "aria-labelledby": id,
+ },
+ renderValue(props)
+ );
+ }
+
+ // Render me!
+ return td(
+ {
+ className: classNames.join(" "),
+ role: "presentation",
+ },
+ cellElement
+ );
+ }
+ }
+
+ // Default value rendering.
+ const defaultRenderValue = props => {
+ return props.object + "";
+ };
+
+ // Exports from this module
+ module.exports = TreeCell;
+});