UNPKG

flexlayout-react

Version:

A multi-tab docking layout manager

192 lines 8.53 kB
import * as React from "react"; import { Actions } from "../model/Actions"; import { BorderNode } from "../model/BorderNode"; import { RowNode } from "../model/RowNode"; import { Orientation } from "../Orientation"; import { CLASSES } from "../Types"; import { enablePointerOnIFrames, isDesktop, startDrag } from "./Utils"; import { Rect } from "../Rect"; /** @internal */ export const Splitter = (props) => { const { layout, node, index, horizontal } = props; const [dragging, setDragging] = React.useState(false); const selfRef = React.useRef(null); const extendedRef = React.useRef(null); const pBounds = React.useRef([]); const outlineDiv = React.useRef(undefined); const handleDiv = React.useRef(undefined); const dragStartX = React.useRef(0); const dragStartY = React.useRef(0); const initalSizes = React.useRef({ initialSizes: [], sum: 0, startPosition: 0 }); // const throttleTimer = React.useRef<NodeJS.Timeout | undefined>(undefined); const size = node.getModel().getSplitterSize(); let extra = node.getModel().getSplitterExtra(); if (!isDesktop()) { // make hit test area on mobile at least 20px extra = Math.max(20, extra + size) - size; } React.useEffect(() => { var _a, _b; // Android fix: must have passive touchstart handler to prevent default handling (_a = selfRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener("touchstart", onTouchStart, { passive: false }); (_b = extendedRef.current) === null || _b === void 0 ? void 0 : _b.addEventListener("touchstart", onTouchStart, { passive: false }); return () => { var _a, _b; (_a = selfRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener("touchstart", onTouchStart); (_b = extendedRef.current) === null || _b === void 0 ? void 0 : _b.removeEventListener("touchstart", onTouchStart); }; }, []); const onTouchStart = (event) => { event.preventDefault(); event.stopImmediatePropagation(); }; const onPointerDown = (event) => { var _a; event.stopPropagation(); if (node instanceof RowNode) { initalSizes.current = node.getSplitterInitials(index); } enablePointerOnIFrames(false, layout.getCurrentDocument()); startDrag(event.currentTarget.ownerDocument, event, onDragMove, onDragEnd, onDragCancel); pBounds.current = node.getSplitterBounds(index, true); const rootdiv = layout.getRootDiv(); outlineDiv.current = layout.getCurrentDocument().createElement("div"); outlineDiv.current.style.flexDirection = horizontal ? "row" : "column"; outlineDiv.current.className = layout.getClassName(CLASSES.FLEXLAYOUT__SPLITTER_DRAG); outlineDiv.current.style.cursor = node.getOrientation() === Orientation.VERT ? "ns-resize" : "ew-resize"; if (node.getModel().isSplitterEnableHandle()) { handleDiv.current = layout.getCurrentDocument().createElement("div"); handleDiv.current.className = cm(CLASSES.FLEXLAYOUT__SPLITTER_HANDLE) + " " + (horizontal ? cm(CLASSES.FLEXLAYOUT__SPLITTER_HANDLE_HORZ) : cm(CLASSES.FLEXLAYOUT__SPLITTER_HANDLE_VERT)); outlineDiv.current.appendChild(handleDiv.current); } const r = (_a = selfRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect(); const rect = new Rect(r.x - layout.getDomRect().x, r.y - layout.getDomRect().y, r.width, r.height); dragStartX.current = event.clientX - r.x; dragStartY.current = event.clientY - r.y; rect.positionElement(outlineDiv.current); if (rootdiv) { rootdiv.appendChild(outlineDiv.current); } setDragging(true); }; const onDragCancel = () => { const rootdiv = layout.getRootDiv(); if (rootdiv && outlineDiv.current) { rootdiv.removeChild(outlineDiv.current); } outlineDiv.current = undefined; setDragging(false); }; const onDragMove = (x, y) => { if (outlineDiv.current) { const clientRect = layout.getDomRect(); if (!clientRect) { return; } if (node.getOrientation() === Orientation.VERT) { outlineDiv.current.style.top = getBoundPosition(y - clientRect.y - dragStartY.current) + "px"; } else { outlineDiv.current.style.left = getBoundPosition(x - clientRect.x - dragStartX.current) + "px"; } if (layout.isRealtimeResize()) { updateLayout(true); } } }; const onDragEnd = () => { if (outlineDiv.current) { updateLayout(false); const rootdiv = layout.getRootDiv(); if (rootdiv && outlineDiv.current) { rootdiv.removeChild(outlineDiv.current); } outlineDiv.current = undefined; } enablePointerOnIFrames(true, layout.getCurrentDocument()); setDragging(false); }; const updateLayout = (realtime) => { const redraw = () => { if (outlineDiv.current) { let value = 0; if (node.getOrientation() === Orientation.VERT) { value = outlineDiv.current.offsetTop; } else { value = outlineDiv.current.offsetLeft; } if (node instanceof BorderNode) { const pos = node.calculateSplit(node, value); layout.doAction(Actions.adjustBorderSplit(node.getId(), pos)); } else { const init = initalSizes.current; const weights = node.calculateSplit(index, value, init.initialSizes, init.sum, init.startPosition); layout.doAction(Actions.adjustWeights(node.getId(), weights)); } } }; redraw(); }; const getBoundPosition = (p) => { const bounds = pBounds.current; let rtn = p; if (p < bounds[0]) { rtn = bounds[0]; } if (p > bounds[1]) { rtn = bounds[1]; } return rtn; }; const cm = layout.getClassName; const style = { cursor: horizontal ? "ew-resize" : "ns-resize", flexDirection: horizontal ? "column" : "row" }; let className = cm(CLASSES.FLEXLAYOUT__SPLITTER) + " " + cm(CLASSES.FLEXLAYOUT__SPLITTER_ + node.getOrientation().getName()); if (node instanceof BorderNode) { className += " " + cm(CLASSES.FLEXLAYOUT__SPLITTER_BORDER); } else { if (node.getModel().getMaximizedTabset(layout.getWindowId()) !== undefined) { style.display = "none"; } } if (horizontal) { style.width = size + "px"; style.minWidth = size + "px"; } else { style.height = size + "px"; style.minHeight = size + "px"; } let handle; if (!dragging && node.getModel().isSplitterEnableHandle()) { handle = (React.createElement("div", { className: cm(CLASSES.FLEXLAYOUT__SPLITTER_HANDLE) + " " + (horizontal ? cm(CLASSES.FLEXLAYOUT__SPLITTER_HANDLE_HORZ) : cm(CLASSES.FLEXLAYOUT__SPLITTER_HANDLE_VERT)) })); } if (extra === 0) { return (React.createElement("div", { className: className, style: style, ref: selfRef, "data-layout-path": node.getPath() + "/s" + (index - 1), onPointerDown: onPointerDown }, handle)); } else { // add extended transparent div for hit testing const style2 = {}; if (node.getOrientation() === Orientation.HORZ) { style2.height = "100%"; style2.width = size + extra + "px"; style2.cursor = "ew-resize"; } else { style2.height = size + extra + "px"; style2.width = "100%"; style2.cursor = "ns-resize"; } const className2 = cm(CLASSES.FLEXLAYOUT__SPLITTER_EXTRA); return (React.createElement("div", { className: className, style: style, ref: selfRef, "data-layout-path": node.getPath() + "/s" + (index - 1), onPointerDown: onPointerDown }, React.createElement("div", { style: style2, ref: extendedRef, className: className2, onPointerDown: onPointerDown }))); } }; //# sourceMappingURL=Splitter.js.map