@ashxjs/split-view
Version:
Simple react split-view component with resizing divider
46 lines (45 loc) • 2.08 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect, useState, createRef } from "react";
import { LeftPanel } from "../LeftPanel/LeftPanel";
import { styles } from "../styles";
const MIN_WIDTH = 50;
export const SplitView = ({ left, right, defaultLeftPanelWidth, }) => {
const [isDragging, setIsDragging] = useState(false);
const [leftWidth, setLeftWidth] = useState(defaultLeftPanelWidth);
const [xPosition, setXPosition] = useState();
const splitPaneRef = createRef();
useEffect(() => {
document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mouseup", onMouseUp);
return () => {
document.removeEventListener("mousemove", onMouseMove);
document.removeEventListener("mouseup", onMouseUp);
};
});
const onMouseUp = () => {
setIsDragging(false);
};
const onMouseMove = (event) => {
if (isDragging && leftWidth && xPosition) {
const newLeftWidth = leftWidth + event.clientX - xPosition;
setXPosition(event.clientX);
if (newLeftWidth < MIN_WIDTH) {
setLeftWidth(MIN_WIDTH);
return;
}
if (splitPaneRef.current) {
const splitPaneWidth = splitPaneRef.current.clientWidth;
if (newLeftWidth > splitPaneWidth - MIN_WIDTH) {
setLeftWidth(splitPaneWidth - MIN_WIDTH);
return;
}
}
setLeftWidth(newLeftWidth);
}
};
const onMouseDown = (event) => {
setXPosition(event.clientX);
setIsDragging(true);
};
return (_jsxs("div", { style: styles.SplitView, ref: splitPaneRef, children: [_jsx(LeftPanel, { leftWidth: leftWidth, setLeftWidth: setLeftWidth, children: left }), _jsx("div", { style: styles.DividerHitBox, onMouseDown: onMouseDown, children: _jsx("div", { style: styles.Divider, onMouseDown: onMouseDown }) }), _jsx("div", { style: styles.RightPanel, children: right })] }));
};