UNPKG

rc-dock

Version:

dock layout for react component

221 lines (220 loc) 8.96 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const react_1 = __importDefault(require("react")); const DockData_1 = require("./DockData"); const rc_tabs_1 = __importDefault(require("rc-tabs")); const TabContent_1 = __importDefault(require("rc-tabs/lib/TabContent")); const DragManager_1 = require("./dragdrop/DragManager"); const DragDropDiv_1 = require("./dragdrop/DragDropDiv"); const DockTabBar_1 = require("./DockTabBar"); const DockTabPane_1 = __importStar(require("./DockTabPane")); const Algorithm_1 = require("./Algorithm"); function findParentPanel(element) { for (let i = 0; i < 10; ++i) { if (!element) { return null; } if (element.classList.contains('dock-panel')) { return element; } element = element.parentElement; } return null; } class TabCache { constructor(context) { this.getRef = (r) => { this._ref = r; }; this.getHitAreaRef = (r) => { this._hitAreaRef = r; }; this.onCloseClick = (e) => { this.context.dockMove(this.data, null, 'remove'); e.stopPropagation(); }; this.onDragStart = (e) => { let panel = findParentPanel(this._ref); let tabGroup = this.context.getGroup(this.data.group); let [panelWidth, panelHeight] = Algorithm_1.getFloatPanelSize(panel, tabGroup); e.setData({ tab: this.data, panelSize: [panelWidth, panelHeight] }, DockData_1.DockContextType); e.startDrag(this._ref.parentElement, this._ref.parentElement); }; this.onDragOver = (e) => { let tab = DragManager_1.DragState.getData('tab', DockData_1.DockContextType); let panel = DragManager_1.DragState.getData('panel', DockData_1.DockContextType); if (tab) { panel = tab.parent; } else if (!panel) { return; } if (panel.group !== this.data.group) { e.reject(); } else if (tab && tab !== this.data) { let direction = this.getDropDirection(e); this.context.setDropRect(this._hitAreaRef, direction, this); e.accept(''); } else if (panel && panel !== this.data.parent) { let direction = this.getDropDirection(e); this.context.setDropRect(this._hitAreaRef, direction, this); e.accept(''); } }; this.onDragLeave = (e) => { this.context.setDropRect(null, 'remove', this); }; this.onDrop = (e) => { let panel; let tab = DragManager_1.DragState.getData('tab', DockData_1.DockContextType); if (tab) { panel = tab.parent; } else { panel = DragManager_1.DragState.getData('panel', DockData_1.DockContextType); } if (tab && tab !== this.data) { let direction = this.getDropDirection(e); this.context.dockMove(tab, this.data, direction); } else if (panel && panel !== this.data.parent) { let direction = this.getDropDirection(e); this.context.dockMove(panel, this.data, direction); } }; this.context = context; } setData(data) { if (data !== this.data) { this.data = data; this.content = this.render(); return true; } return false; } getDropDirection(e) { let rect = this._hitAreaRef.getBoundingClientRect(); let midx = rect.left + rect.width * 0.5; return e.clientX > midx ? 'after-tab' : 'before-tab'; } render() { let { id, title, group, content, closable, cached, cacheContext } = this.data; let tabGroup = this.context.getGroup(group); if (typeof content === 'function') { content = content(this.data); } let tab = (react_1.default.createElement("div", { ref: this.getRef }, title, react_1.default.createElement(DragDropDiv_1.DragDropDiv, { className: 'dock-tab-hit-area', getRef: this.getHitAreaRef, onDragStartT: this.onDragStart, onDragOverT: this.onDragOver, onDropT: this.onDrop, onDragLeaveT: this.onDragLeave }, closable ? react_1.default.createElement("div", { className: 'dock-tab-close-btn', onClick: this.onCloseClick }) : null))); if (cacheContext) { // allow DockTabPane to receive context let DockTabPaneClass = DockTabPane_1.getContextPaneClass(cacheContext); return (react_1.default.createElement(DockTabPaneClass, { key: id, id: id, cached: cached, tab: tab }, content)); } else { return (react_1.default.createElement(DockTabPane_1.default, { key: id, id: id, cached: cached, tab: tab }, content)); } } destroy() { // place holder } } exports.TabCache = TabCache; class DockTabs extends react_1.default.Component { constructor(props, context) { super(props, context); this._cache = new Map(); this.onMaximizeClick = () => { let { panelData } = this.props; this.context.dockMove(panelData, null, 'maximize'); }; this.renderTabBar = () => { let { panelData, onPanelDragStart, onPanelDragMove, onPanelDragEnd } = this.props; let { group: groupName, panelLock } = panelData; let group = this.context.getGroup(groupName); let { panelExtra } = group; if (panelLock) { if (panelLock.panelExtra) { panelExtra = panelLock.panelExtra; } } let panelExtraContent; if (panelExtra) { panelExtraContent = panelExtra(panelData, this.context); } else if (group.maximizable) { panelExtraContent = (react_1.default.createElement("div", { className: 'dock-panel-max-btn', onClick: this.onMaximizeClick })); } return (react_1.default.createElement(DockTabBar_1.DockTabBar, { extraContent: panelExtraContent, onDragStart: onPanelDragStart, onDragMove: onPanelDragMove, onDragEnd: onPanelDragEnd })); }; this.renderTabContent = () => { let { group } = this.props.panelData; let tabGroup = this.context.getGroup(group); let { animated } = tabGroup; return react_1.default.createElement(TabContent_1.default, { animated: animated }); }; this.onTabChange = (activeId) => { this.props.panelData.activeId = activeId; this.context.onSilentChange(activeId); this.forceUpdate(); }; this.updateTabs(props.panelData.tabs); } updateTabs(tabs) { let newCache = new Map(); let reused = 0; for (let tabData of tabs) { let { id } = tabData; if (this._cache.has(id)) { let tab = this._cache.get(id); newCache.set(id, tab); tab.setData(tabData); ++reused; } else { let tab = new TabCache(this.context); newCache.set(id, tab); tab.setData(tabData); } } if (reused !== this._cache.size) { for (let [id, tab] of this._cache) { if (!newCache.has(id)) { tab.destroy(); } } } this._cache = newCache; } shouldComponentUpdate(nextProps, nextState, nextContext) { let { tabs } = nextProps.panelData; // update tab cache this.updateTabs(tabs); return true; } render() { let { group, activeId } = this.props.panelData; let children = []; for (let [id, tab] of this._cache) { children.push(tab.content); } return (react_1.default.createElement(rc_tabs_1.default, { prefixCls: 'dock', renderTabBar: this.renderTabBar, renderTabContent: this.renderTabContent, activeKey: activeId, onChange: this.onTabChange }, children)); } } exports.DockTabs = DockTabs; DockTabs.contextType = DockData_1.DockContextType; DockTabs.propKeys = ['group', 'tabs', 'activeId', 'onTabChange'];