UNPKG

rc-dock

Version:

dock layout for react component

345 lines (344 loc) 16.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DockPanel = void 0; const React = __importStar(require("react")); const DockData_1 = require("./DockData"); const DockTabs_1 = require("./DockTabs"); const DragDropDiv_1 = require("./dragdrop/DragDropDiv"); const DragManager_1 = require("./dragdrop/DragManager"); const DockDropLayer_1 = require("./DockDropLayer"); const Algorithm_1 = require("./Algorithm"); const DockDropEdge_1 = require("./DockDropEdge"); const Utils_1 = require("./Utils"); const classnames_1 = __importDefault(require("classnames")); class DockPanel extends React.PureComponent { constructor() { super(...arguments); this.getRef = (r) => { this._ref = r; if (r) { let { parent } = this.props.panelData; if (((parent === null || parent === void 0 ? void 0 : parent.mode) === 'float')) { r.addEventListener('pointerdown', this.onFloatPointerDown, { capture: true, passive: true }); } } }; this.state = { dropFromPanel: null, draggingHeader: false }; this.onDragOver = (e) => { if (DockPanel._droppingPanel === this) { return; } let dockId = this.context.getDockId(); let tab = DragManager_1.DragState.getData('tab', dockId); let panel = DragManager_1.DragState.getData('panel', dockId); if (tab || panel) { DockPanel.droppingPanel = this; } if (tab) { if (tab.parent) { this.setState({ dropFromPanel: tab.parent }); } else { // add a fake panel this.setState({ dropFromPanel: { activeId: '', tabs: [], group: tab.group } }); } } else if (panel) { this.setState({ dropFromPanel: panel }); } }; // drop to move in float mode this.onPanelHeaderDragStart = (event) => { let { panelData } = this.props; let { parent, x, y, z } = panelData; let dockId = this.context.getDockId(); if ((parent === null || parent === void 0 ? void 0 : parent.mode) === 'float') { this._movingX = x; this._movingY = y; // hide the panel, but not create drag layer element event.setData({ panel: panelData, tabGroup: panelData.group }, dockId); event.startDrag(null, null); this.onFloatPointerDown(); } else { let tabGroup = this.context.getGroup(panelData.group); let [panelWidth, panelHeight] = Algorithm_1.getFloatPanelSize(this._ref, tabGroup); event.setData({ panel: panelData, panelSize: [panelWidth, panelHeight], tabGroup: panelData.group }, dockId); event.startDrag(null); } this.setState({ draggingHeader: true }); }; this.onPanelHeaderDragMove = (e) => { var _a; let { panelData } = this.props; if (((_a = panelData.parent) === null || _a === void 0 ? void 0 : _a.mode) !== 'float') { return; } let { width, height } = this.context.getLayoutSize(); panelData.x = this._movingX + e.dx; panelData.y = this._movingY + e.dy; if (width > 200 && height > 200) { if (panelData.y < 0) { panelData.y = 0; } else if (panelData.y > height - 16) { panelData.y = height - 16; } if (panelData.x + panelData.w < 16) { panelData.x = 16 - panelData.w; } else if (panelData.x > width - 16) { panelData.x = width - 16; } } this.forceUpdate(); }; this.onPanelHeaderDragEnd = (e) => { var _a; this.setState({ draggingHeader: false }); if (e.dropped === false) { let { panelData } = this.props; if (((_a = panelData.parent) === null || _a === void 0 ? void 0 : _a.mode) === 'float') { // in float mode, the position change needs to be sent to the layout this.context.onSilentChange(this.props.panelData.activeId, 'move'); } } }; this.onPanelCornerDragT = (e) => { this.onPanelCornerDrag(e, 't'); }; this.onPanelCornerDragB = (e) => { this.onPanelCornerDrag(e, 'b'); }; this.onPanelCornerDragL = (e) => { this.onPanelCornerDrag(e, 'l'); }; this.onPanelCornerDragR = (e) => { this.onPanelCornerDrag(e, 'r'); }; this.onPanelCornerDragTL = (e) => { this.onPanelCornerDrag(e, 'tl'); }; this.onPanelCornerDragTR = (e) => { this.onPanelCornerDrag(e, 'tr'); }; this.onPanelCornerDragBL = (e) => { this.onPanelCornerDrag(e, 'bl'); }; this.onPanelCornerDragBR = (e) => { this.onPanelCornerDrag(e, 'br'); }; this.onPanelCornerDragMove = (e) => { let { panelData } = this.props; let { dx, dy } = e; if (this._movingCorner.startsWith('t')) { // when moving top corners, dont let it move header out of screen let { width, height } = this.context.getLayoutSize(); if (this._movingY + dy < 0) { dy = -this._movingY; } else if (this._movingY + dy > height - 16) { dy = height - 16 - this._movingY; } } switch (this._movingCorner) { case 't': { panelData.y = this._movingY + dy; panelData.h = this._movingH - dy; break; } case 'b': { panelData.h = this._movingH + dy; break; } case 'l': { panelData.x = this._movingX + dx; panelData.w = this._movingW - dx; break; } case 'r': { panelData.w = this._movingW + dx; break; } case 'tl': { panelData.x = this._movingX + dx; panelData.w = this._movingW - dx; panelData.y = this._movingY + dy; panelData.h = this._movingH - dy; break; } case 'tr': { panelData.w = this._movingW + dx; panelData.y = this._movingY + dy; panelData.h = this._movingH - dy; break; } case 'bl': { panelData.x = this._movingX + dx; panelData.w = this._movingW - dx; panelData.h = this._movingH + dy; break; } case 'br': { panelData.w = this._movingW + dx; panelData.h = this._movingH + dy; break; } } panelData.w = Math.max(panelData.w || 0, panelData.minWidth || 0); panelData.h = Math.max(panelData.h || 0, panelData.minHeight || 0); this.forceUpdate(); }; this.onPanelCornerDragEnd = (e) => { this.context.onSilentChange(this.props.panelData.activeId, 'move'); }; this.onFloatPointerDown = () => { let { panelData } = this.props; let { z } = panelData; let newZ = Algorithm_1.nextZIndex(z); if (newZ !== z) { panelData.z = newZ; this.forceUpdate(); } }; this.onPanelClicked = (e) => { const target = e.nativeEvent.target; if (!this._ref.contains(this._ref.ownerDocument.activeElement) && target instanceof Node && this._ref.contains(target)) { this._ref.querySelector('.dock-bar').focus(); } }; this._unmounted = false; } static set droppingPanel(panel) { if (DockPanel._droppingPanel === panel) { return; } if (DockPanel._droppingPanel) { DockPanel._droppingPanel.onDragOverOtherPanel(); } DockPanel._droppingPanel = panel; } onDragOverOtherPanel() { this.setState({ dropFromPanel: null }); } onPanelCornerDrag(e, corner) { let { parent, x, y, w, h } = this.props.panelData; if ((parent === null || parent === void 0 ? void 0 : parent.mode) === 'float') { this._movingCorner = corner; this._movingX = x; this._movingY = y; this._movingW = w; this._movingH = h; e.startDrag(null, null); } } render() { let { dropFromPanel, draggingHeader } = this.state; let { panelData, size } = this.props; let { minWidth, minHeight, group, id, parent, panelLock } = panelData; let styleName = group; let tabGroup = this.context.getGroup(group); let { widthFlex, heightFlex } = tabGroup; if (panelLock) { let { panelStyle, widthFlex: panelWidthFlex, heightFlex: panelHeightFlex } = panelLock; if (panelStyle) { styleName = panelStyle; } if (typeof panelWidthFlex === 'number') { widthFlex = panelWidthFlex; } if (typeof panelHeightFlex === 'number') { heightFlex = panelHeightFlex; } } let panelClass = classnames_1.default(Utils_1.groupClassNames(styleName)); let isMax = (parent === null || parent === void 0 ? void 0 : parent.mode) === 'maximize'; let isFloat = (parent === null || parent === void 0 ? void 0 : parent.mode) === 'float'; let isHBox = (parent === null || parent === void 0 ? void 0 : parent.mode) === 'horizontal'; let isVBox = (parent === null || parent === void 0 ? void 0 : parent.mode) === 'vertical'; let onPanelHeaderDragStart = this.onPanelHeaderDragStart; if (isMax) { dropFromPanel = null; onPanelHeaderDragStart = null; } let cls = `dock-panel ${panelClass ? panelClass : ''}${dropFromPanel ? ' dock-panel-dropping' : ''}${draggingHeader ? ' dragging' : ''}`; let flex = 1; if (isHBox && widthFlex != null) { flex = widthFlex; } else if (isVBox && heightFlex != null) { flex = heightFlex; } let flexGrow = flex * size; let flexShrink = flex * 1000000; if (flexShrink < 1) { flexShrink = 1; } let style = { minWidth, minHeight, flex: `${flexGrow} ${flexShrink} ${size}px` }; if (isFloat) { style.left = panelData.x; style.top = panelData.y; style.width = panelData.w; style.height = panelData.h; style.zIndex = panelData.z; } let droppingLayer; if (dropFromPanel) { let dropFromGroup = this.context.getGroup(dropFromPanel.group); let dockId = this.context.getDockId(); if (!dropFromGroup.tabLocked || DragManager_1.DragState.getData('tab', dockId) == null) { // not allowed locked tab to create new panel let DockDropClass = this.context.useEdgeDrop() ? DockDropEdge_1.DockDropEdge : DockDropLayer_1.DockDropLayer; droppingLayer = React.createElement(DockDropClass, { panelData: panelData, panelElement: this._ref, dropFromPanel: dropFromPanel }); } } return (React.createElement(DragDropDiv_1.DragDropDiv, { getRef: this.getRef, className: cls, style: style, "data-dockid": id, onDragOverT: isFloat ? null : this.onDragOver, onClick: this.onPanelClicked }, React.createElement(DockTabs_1.DockTabs, { panelData: panelData, onPanelDragStart: onPanelHeaderDragStart, onPanelDragMove: this.onPanelHeaderDragMove, onPanelDragEnd: this.onPanelHeaderDragEnd }), isFloat ? [ React.createElement(DragDropDiv_1.DragDropDiv, { key: "drag-size-t", className: "dock-panel-drag-size dock-panel-drag-size-t", onDragStartT: this.onPanelCornerDragT, onDragMoveT: this.onPanelCornerDragMove, onDragEndT: this.onPanelCornerDragEnd }), React.createElement(DragDropDiv_1.DragDropDiv, { key: "drag-size-b", className: "dock-panel-drag-size dock-panel-drag-size-b", onDragStartT: this.onPanelCornerDragB, onDragMoveT: this.onPanelCornerDragMove, onDragEndT: this.onPanelCornerDragEnd }), React.createElement(DragDropDiv_1.DragDropDiv, { key: "drag-size-l", className: "dock-panel-drag-size dock-panel-drag-size-l", onDragStartT: this.onPanelCornerDragL, onDragMoveT: this.onPanelCornerDragMove, onDragEndT: this.onPanelCornerDragEnd }), React.createElement(DragDropDiv_1.DragDropDiv, { key: "drag-size-r", className: "dock-panel-drag-size dock-panel-drag-size-r", onDragStartT: this.onPanelCornerDragR, onDragMoveT: this.onPanelCornerDragMove, onDragEndT: this.onPanelCornerDragEnd }), React.createElement(DragDropDiv_1.DragDropDiv, { key: "drag-size-t-l", className: "dock-panel-drag-size dock-panel-drag-size-t-l", onDragStartT: this.onPanelCornerDragTL, onDragMoveT: this.onPanelCornerDragMove, onDragEndT: this.onPanelCornerDragEnd }), React.createElement(DragDropDiv_1.DragDropDiv, { key: "drag-size-t-r", className: "dock-panel-drag-size dock-panel-drag-size-t-r", onDragStartT: this.onPanelCornerDragTR, onDragMoveT: this.onPanelCornerDragMove, onDragEndT: this.onPanelCornerDragEnd }), React.createElement(DragDropDiv_1.DragDropDiv, { key: "drag-size-b-l", className: "dock-panel-drag-size dock-panel-drag-size-b-l", onDragStartT: this.onPanelCornerDragBL, onDragMoveT: this.onPanelCornerDragMove, onDragEndT: this.onPanelCornerDragEnd }), React.createElement(DragDropDiv_1.DragDropDiv, { key: "drag-size-b-r", className: "dock-panel-drag-size dock-panel-drag-size-b-r", onDragStartT: this.onPanelCornerDragBR, onDragMoveT: this.onPanelCornerDragMove, onDragEndT: this.onPanelCornerDragEnd }) ] : null, droppingLayer)); } componentWillUnmount() { if (DockPanel._droppingPanel === this) { DockPanel.droppingPanel = null; } if (this._ref) { this._ref.removeEventListener('pointerdown', this.onFloatPointerDown, { capture: true }); } this._unmounted = true; } } exports.DockPanel = DockPanel; DockPanel.contextType = DockData_1.DockContextType;