summaryrefslogtreecommitdiffstats
path: root/devtools/client/shared/components/splitter/GridElementWidthResizer.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/shared/components/splitter/GridElementWidthResizer.js')
-rw-r--r--devtools/client/shared/components/splitter/GridElementWidthResizer.js138
1 files changed, 138 insertions, 0 deletions
diff --git a/devtools/client/shared/components/splitter/GridElementWidthResizer.js b/devtools/client/shared/components/splitter/GridElementWidthResizer.js
new file mode 100644
index 0000000000..c6ab6f3e14
--- /dev/null
+++ b/devtools/client/shared/components/splitter/GridElementWidthResizer.js
@@ -0,0 +1,138 @@
+/* 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";
+
+const {
+ Component,
+ createFactory,
+} = require("resource://devtools/client/shared/vendor/react.js");
+const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js");
+const Draggable = createFactory(
+ require("resource://devtools/client/shared/components/splitter/Draggable.js")
+);
+
+class GridElementWidthResizer extends Component {
+ static get propTypes() {
+ return {
+ getControlledElementNode: PropTypes.func.isRequired,
+ enabled: PropTypes.bool,
+ position: PropTypes.string.isRequired,
+ className: PropTypes.string,
+ onResizeEnd: PropTypes.func,
+ };
+ }
+
+ constructor(props) {
+ super(props);
+
+ this.onStartMove = this.onStartMove.bind(this);
+ this.onStopMove = this.onStopMove.bind(this);
+ this.onMove = this.onMove.bind(this);
+ this.state = {
+ dragging: false,
+ isRTLElement: false,
+ defaultCursor: null,
+ defaultWidth: null,
+ };
+ }
+
+ componentDidUpdate(prevProps) {
+ if (prevProps.enabled === true && this.props.enabled === false) {
+ this.onStopMove();
+ const controlledElementNode = this.props.getControlledElementNode();
+ controlledElementNode.style.width = this.state.defaultWidth;
+ }
+ }
+
+ // Dragging Events
+
+ /**
+ * Set 'resizing' cursor on entire document during splitter dragging.
+ * This avoids cursor-flickering that happens when the mouse leaves
+ * the splitter bar area (happens frequently).
+ */
+ onStartMove() {
+ const controlledElementNode = this.props.getControlledElementNode();
+ if (!controlledElementNode) {
+ return;
+ }
+
+ const doc = controlledElementNode.ownerDocument;
+ const defaultCursor = doc.documentElement.style.cursor;
+ const defaultWidth = doc.documentElement.style.width;
+ doc.documentElement.style.cursor = "ew-resize";
+ doc.firstElementChild.classList.add("dragging");
+
+ this.setState({
+ dragging: true,
+ isRTLElement:
+ controlledElementNode.ownerDocument.defaultView.getComputedStyle(
+ controlledElementNode
+ ).direction === "rtl",
+ defaultCursor,
+ defaultWidth,
+ });
+ }
+
+ onStopMove() {
+ const controlledElementNode = this.props.getControlledElementNode();
+ if (!this.state.dragging || !controlledElementNode) {
+ return;
+ }
+ const doc = controlledElementNode.ownerDocument;
+ doc.documentElement.style.cursor = this.state.defaultCursor;
+ doc.firstElementChild.classList.remove("dragging");
+
+ this.setState({
+ dragging: false,
+ });
+
+ if (this.props.onResizeEnd) {
+ const { width } = controlledElementNode.getBoundingClientRect();
+ this.props.onResizeEnd(width);
+ }
+ }
+
+ /**
+ * Adjust size of the controlled panel.
+ */
+ onMove(x) {
+ const controlledElementNode = this.props.getControlledElementNode();
+ if (!this.state.dragging || !controlledElementNode) {
+ return;
+ }
+ const nodeBounds = controlledElementNode.getBoundingClientRect();
+ const { isRTLElement } = this.state;
+ const { position } = this.props;
+
+ const size =
+ (isRTLElement && position === "end") ||
+ (!isRTLElement && position === "start")
+ ? nodeBounds.width + (nodeBounds.left - x)
+ : x - nodeBounds.left;
+
+ controlledElementNode.style.width = `${size}px`;
+ }
+
+ render() {
+ if (!this.props.enabled) {
+ return null;
+ }
+
+ const classNames = ["grid-element-width-resizer", this.props.position];
+ if (this.props.className) {
+ classNames.push(this.props.className);
+ }
+
+ return Draggable({
+ className: classNames.join(" "),
+ onStart: this.onStartMove,
+ onStop: this.onStopMove,
+ onMove: this.onMove,
+ });
+ }
+}
+
+module.exports = GridElementWidthResizer;