mui-extended
Version:
Extended UI Components built on Material UI
269 lines (268 loc) • 12 kB
JavaScript
import { __assign, __extends } from "tslib";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Box } from "@mui/material";
import { Children, Component } from "react";
import { Pane } from "./Pane";
import { Resizer } from "./Resizer";
var unFocus = function (window) {
if (window.document.getSelection) {
window.document.getSelection().empty();
}
else {
try {
window.getSelection().removeAllRanges();
// eslint-disable-next-line no-empty
}
catch (e) { }
}
};
function getDefaultSize(defaultSize, minSize, maxSize, draggedSize) {
if (typeof draggedSize === "number") {
var min = typeof minSize === "number" ? minSize : 0;
var max = typeof maxSize === "number" && maxSize >= 0 ? maxSize : Infinity;
return Math.max(min, Math.min(max, draggedSize));
}
if (defaultSize !== undefined) {
return defaultSize;
}
return minSize;
}
function removeNullChildren(children) {
return Children.toArray(children).filter(function (c) { return c; });
}
/**
* This component is rendered in `absolute` position stretching 100% height and width of the parent `relative` element
*/
var SplitPane = /** @class */ (function (_super) {
__extends(SplitPane, _super);
function SplitPane(props) {
var _this = _super.call(this, props) || this;
_this.onMouseDown = _this.onMouseDown.bind(_this);
_this.onTouchStart = _this.onTouchStart.bind(_this);
_this.onMouseMove = _this.onMouseMove.bind(_this);
_this.onTouchMove = _this.onTouchMove.bind(_this);
_this.onMouseUp = _this.onMouseUp.bind(_this);
// order of setting panel sizes.
// 1. size
// 2. getDefaultSize(defaultSize, minsize, maxSize)
var size = props.size, defaultSize = props.defaultSize, minSize = props.minSize, maxSize = props.maxSize;
var initialSize = size !== undefined
? size
: getDefaultSize(defaultSize, minSize, maxSize, null);
_this.state = {
active: false,
resized: false,
primaryPaneSize: initialSize,
// these are props that are needed in static functions. ie: gDSFP
instanceProps: {
size: size
}
};
return _this;
}
SplitPane.prototype.componentDidMount = function () {
document.addEventListener("mouseup", this.onMouseUp);
document.addEventListener("mousemove", this.onMouseMove);
document.addEventListener("touchmove", this.onTouchMove);
this.setState(SplitPane.getSizeUpdate(this.props, this.state));
};
SplitPane.getDerivedStateFromProps = function (nextProps, prevState) {
return SplitPane.getSizeUpdate(nextProps, prevState);
};
SplitPane.prototype.componentWillUnmount = function () {
document.removeEventListener("mouseup", this.onMouseUp);
document.removeEventListener("mousemove", this.onMouseMove);
document.removeEventListener("touchmove", this.onTouchMove);
};
SplitPane.prototype.onMouseDown = function (event) {
var eventWithTouches = Object.assign({}, event, {
touches: [{ clientX: event.clientX, clientY: event.clientY }]
});
this.onTouchStart(eventWithTouches);
};
SplitPane.prototype.onTouchStart = function (event) {
var _a = this.props, allowResize = _a.allowResize, onDragStarted = _a.onDragStarted, split = _a.split;
if (allowResize) {
unFocus(window);
var position = split === "vertical"
? event.touches[0].clientX
: event.touches[0].clientY;
if (typeof onDragStarted === "function") {
onDragStarted();
}
this.setState({
active: true,
position: position
});
}
};
SplitPane.prototype.onMouseMove = function (event) {
var eventWithTouches = Object.assign({}, event, {
touches: [{ clientX: event.clientX, clientY: event.clientY }]
});
this.onTouchMove(eventWithTouches);
};
SplitPane.prototype.onTouchMove = function (event) {
var _a = this.props, allowResize = _a.allowResize, maxSize = _a.maxSize, minSize = _a.minSize, onChange = _a.onChange, split = _a.split, step = _a.step;
var _b = this.state, active = _b.active, position = _b.position;
if (allowResize && active) {
unFocus(window);
var isPrimaryFirst = this.props.primary === "first";
var ref = isPrimaryFirst ? this.pane1 : this.pane2;
var ref2 = isPrimaryFirst ? this.pane2 : this.pane1;
if (ref) {
var node = ref;
var node2 = ref2;
if (node.getBoundingClientRect) {
var width = node.getBoundingClientRect().width;
var height = node.getBoundingClientRect().height;
var current = split === "vertical"
? event.touches[0].clientX
: event.touches[0].clientY;
var size = split === "vertical" ? width : height;
var positionDelta = position - current;
if (step) {
if (Math.abs(positionDelta) < step) {
return;
}
// Integer division
// eslint-disable-next-line no-bitwise
positionDelta = ~~(positionDelta / step) * step;
}
var sizeDelta = isPrimaryFirst ? positionDelta : -positionDelta;
var pane1Order = parseInt(window.getComputedStyle(node).order);
var pane2Order = parseInt(window.getComputedStyle(node2).order);
if (pane1Order > pane2Order) {
sizeDelta = -sizeDelta;
}
var newMaxSize = maxSize;
if (maxSize !== undefined && maxSize <= 0) {
var splitPane = this.splitPane;
if (split === "vertical") {
newMaxSize = splitPane.getBoundingClientRect().width + maxSize;
}
else {
newMaxSize = splitPane.getBoundingClientRect().height + maxSize;
}
}
var newSize = size - sizeDelta;
var newPosition = position - positionDelta;
if (newSize < minSize) {
newSize = minSize;
}
else if (maxSize !== undefined && newSize > newMaxSize) {
newSize = newMaxSize;
}
else {
this.setState({
position: newPosition,
resized: true
});
}
if (onChange)
onChange(newSize);
this.setState({ draggedSize: newSize, primaryPaneSize: newSize });
}
}
}
};
SplitPane.prototype.onMouseUp = function () {
var _a = this.props, allowResize = _a.allowResize, onDragFinished = _a.onDragFinished;
var _b = this.state, active = _b.active, draggedSize = _b.draggedSize;
if (allowResize && active) {
if (typeof onDragFinished === "function") {
onDragFinished(draggedSize);
}
this.setState({ active: false });
}
};
// we have to check values since gDSFP is called on every render and more in StrictMode
SplitPane.getSizeUpdate = function (props, state) {
var newState = {};
var instanceProps = state.instanceProps;
if (instanceProps.size === props.size && props.size !== undefined) {
return {};
}
var newSize = props.size !== undefined
? props.size
: getDefaultSize(props.defaultSize, props.minSize, props.maxSize, state.draggedSize);
if (props.size !== undefined) {
newState.draggedSize = newSize;
}
newState.primaryPaneSize = newSize;
newState.instanceProps = { size: props.size };
return newState;
};
SplitPane.prototype.render = function () {
var _this = this;
var _a = this.props, split = _a.split, onResizerClick = _a.onResizerClick, onResizerDoubleClick = _a.onResizerDoubleClick, sx = _a.sx, resizerSx = _a.resizerSx, primary = _a.primary, children = _a.children, hidePrimary = _a.hidePrimary;
var primaryPaneSize = this.state.primaryPaneSize;
var resizerSize = 7;
var notNullChildren = removeNullChildren(children);
var style = __assign({ display: "flex", flex: 1, height: "100%", position: "absolute", outline: "none", overflow: "hidden" }, sx);
if (split === "vertical") {
Object.assign(style, {
flexDirection: "row",
left: 0,
right: 0
});
}
else {
Object.assign(style, {
bottom: 0,
flexDirection: "column",
minHeight: "100%",
top: 0,
width: "100%"
});
}
var pane1Sx = {
transition: "margin ease-in-out 500ms"
};
var pane2Sx = {
transition: "margin ease-in-out 500ms"
};
var resizerSxForSlide = {
transition: "all ease-in-out 500ms"
};
if (hidePrimary) {
var offsetPaneMargin = -1 * primaryPaneSize + "px";
var offsetResizerMargin = -1 * resizerSize + "px";
if (split == "vertical") {
if (primary == "first") {
pane1Sx.marginLeft = offsetPaneMargin;
resizerSxForSlide.marginLeft = offsetResizerMargin;
}
else {
pane2Sx.marginRight = offsetPaneMargin;
resizerSxForSlide.marginRight = offsetResizerMargin;
}
}
else {
if (primary == "first") {
pane1Sx.marginTop = offsetPaneMargin;
resizerSxForSlide.marginTop = offsetResizerMargin;
}
else {
pane2Sx.marginBottom = offsetPaneMargin;
resizerSxForSlide.marginBottom = offsetResizerMargin;
}
}
}
return (_jsxs(Box, { id: "split-pane-root", ref: function (node) {
_this.splitPane = node;
}, sx: style, children: [_jsx(Pane, { ref: function (node) {
_this.pane1 = node;
}, size: primary == "first" ? primaryPaneSize : undefined, split: split, sx: pane1Sx, children: notNullChildren[0] }, "pane1"), _jsx(Resizer, { onClick: onResizerClick, onDoubleClick: onResizerDoubleClick, onMouseDown: function (event) { return _this.onMouseDown(event.nativeEvent); }, onTouchStart: function (event) { return _this.onTouchStart(event.nativeEvent); }, onTouchEnd: this.onMouseUp, sx: __assign(__assign({}, resizerSx), resizerSxForSlide), split: split, size: resizerSize }, "resizer"), _jsx(Pane, { ref: function (node) {
_this.pane2 = node;
}, size: primary == "second" ? primaryPaneSize : undefined, split: split, sx: pane2Sx, children: notNullChildren[1] }, "pane2")] }));
};
SplitPane.defaultProps = {
allowResize: true,
minSize: 100,
primary: "first",
split: "vertical"
};
return SplitPane;
}(Component));
export { SplitPane };