diff --git a/lib/Paneset/PaneResizeContainer.js b/lib/Paneset/PaneResizeContainer.js
index e959244af..3efb481fc 100644
--- a/lib/Paneset/PaneResizeContainer.js
+++ b/lib/Paneset/PaneResizeContainer.js
@@ -1,4 +1,4 @@
-import React, { useState, useRef, useEffect, useCallback } from 'react';
+import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
import PropTypes from 'prop-types';
import cloneDeep from 'lodash/cloneDeep';
import isEqual from 'lodash/isEqual';
@@ -13,7 +13,7 @@ const PaneResizeContainer = ({ isRoot, children, onElementResize, parentElement,
const [cursorX, setCursorX] = useState(0);
const [handles, setHandles] = useState([]);
const [activeHandle, setActiveHandle] = useState(null);
- const [update, setUpdate] = useState(0); // eslint-disable-line no-unused-vars
+ const [update, setUpdate] = useState(0);
const [blocking, setBlocking] = useState(null);
let container = useRef();
if (resizeContainerRef) {
@@ -142,9 +142,8 @@ const PaneResizeContainer = ({ isRoot, children, onElementResize, parentElement,
document.removeEventListener('mousemove', updateCursor);
document.removeEventListener('mouseup', handleMouseUp);
document.body.style.userSelect = 'auto';
- document.body.style.webkitUserSelect = 'auto';
- document.body.style.msUserSelect = 'auto';
document.body.style.msUserSelect = 'auto';
+ document.body.style.mozUserSelect = 'auto';
setDragging(false);
}, [updateCursor]);
@@ -158,7 +157,6 @@ const PaneResizeContainer = ({ isRoot, children, onElementResize, parentElement,
document.addEventListener('mousemove', updateCursor);
document.addEventListener('mouseup', handleMouseUp);
document.body.style.userSelect = 'none';
- document.body.style.webkitUserSelect = 'none';
document.body.style.msUserSelect = 'none';
document.body.style.mozUserSelect = 'none';
}, [handleMouseUp, handles, updateCursor]);
@@ -184,37 +182,48 @@ const PaneResizeContainer = ({ isRoot, children, onElementResize, parentElement,
});
};
- const renderHandles = useCallback(() => {
+ // Reads the DOM (forces layout) to locate each handle. Must only rerun when the handle set,
+ // container/window size, or blocking state changes - never merely because cursorX/dragging/
+ // activeHandle changed during a drag, since handles don't move until the drag ends.
+ const computeHandlePositions = useCallback(() => {
handleData.current = [];
- const handleElements = handles.map((h) => {
+ return handles.map((h) => {
const rect = h.getRef()?.current?.getBoundingClientRect();
- if (rect) {
- if (rect.left === 0) {
- handleData.current.push({ id: h.id, elementId: h.elementId, x: 0, y: 50 });
- return false;
- }
+ if (!rect) return null;
- if (!containerRect.current) {
- containerRect.current = container.current?.getBoundingClientRect();
- }
- const newLeft = rect.left - (containerRect.current ? containerRect.current.left : 0);
- const top = rect.top - (containerRect.current ? containerRect.current.top : 0);
- handleData.current.push({ id: h.id, elementId: h.elementId, x: newLeft, y: top });
- return (
-
- );
+ if (rect.left === 0) {
+ handleData.current.push({ id: h.id, elementId: h.elementId, x: 0, y: 50 });
+ return { id: h.id, render: false };
+ }
+
+ if (!containerRect.current) {
+ containerRect.current = container.current?.getBoundingClientRect();
}
- return null;
+ const newLeft = rect.left - (containerRect.current ? containerRect.current.left : 0);
+ const top = rect.top - (containerRect.current ? containerRect.current.top : 0);
+ handleData.current.push({ id: h.id, elementId: h.elementId, x: newLeft, y: top });
+ return { id: h.id, x: newLeft, render: true };
});
+ }, [handles]); // eslint-disable-line react-hooks/exhaustive-deps
+
+ const handlePositions = useMemo(
+ () => (blocking ? [] : computeHandlePositions()),
+ [computeHandlePositions, update, blocking]
+ );
- return handleElements;
- }, [activeHandle, handleHandleMouseDown, handles]);
+ // No DOM reads here, so this is cheap to rerun on every render (mousedown/mousemove/mouseup).
+ const renderHandles = () => handlePositions.map((pos) => {
+ if (!pos || !pos.render) return null;
+ return (
+
+ );
+ });
// this is the equivalent of `forceUpdate` for functional components.
const updateHandle = () => {
diff --git a/lib/Paneset/Paneset.js b/lib/Paneset/Paneset.js
index 838dbbd75..330403c2e 100644
--- a/lib/Paneset/Paneset.js
+++ b/lib/Paneset/Paneset.js
@@ -374,33 +374,7 @@ class Paneset extends React.Component {
]);
}
- setStyle = () => {
- if (this.isThisMounted()) {
- const {
- paneset,
- isRoot
- } = this.props;
-
- // for nested, non-root panesets, we resize their element to the edge of the screen.
- // this resolves a cropping behavior (impetus for STCOM-953) and allows
- // paneset to accurately resize its children (overflow: hidden)
- if (paneset && !isRoot) {
- const containerBounds = this.container.current?.getBoundingClientRect();
- if (containerBounds.right < window.offsetWidth) {
- this.setState((curState) => {
- const {
- left, right
- } = containerBounds;
- const newStyle = { flex: `0 0 ${right - left}px` };
- return {
- changeType: 'nested-resize-end',
- style: { ...curState.style, ...newStyle }
- };
- });
- }
- }
- }
- }
+ setStyle = () => {}
resizePanes = (panes, widths) => {
if (widths !== null) {