UNPKG

dockview

Version:

Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support

102 lines (101 loc) 4.24 kB
import { addDisposableListener, Emitter } from '../events'; import { CompositeDisposable } from '../lifecycle'; import { getPanelData, LocalSelectionTransfer, PanelTransfer, } from '../dnd/dataTransfer'; import { getElementsByTagName, toggleClass } from '../dom'; import { Droptarget } from '../dnd/droptarget'; import { DockviewDropTargets } from './dnd'; export var MouseEventKind; (function (MouseEventKind) { MouseEventKind["CLICK"] = "CLICK"; MouseEventKind["CONTEXT_MENU"] = "CONTEXT_MENU"; })(MouseEventKind || (MouseEventKind = {})); export class Tab extends CompositeDisposable { constructor(panelId, accessor, group) { super(); this.panelId = panelId; this.accessor = accessor; this.group = group; this._onChanged = new Emitter(); this.onChanged = this._onChanged.event; this._onDropped = new Emitter(); this.onDrop = this._onDropped.event; this.panelTransfer = LocalSelectionTransfer.getInstance(); this.iframes = []; this.addDisposables(this._onChanged, this._onDropped); this._element = document.createElement('div'); this._element.className = 'tab'; this._element.tabIndex = 0; this._element.draggable = true; this.addDisposables(addDisposableListener(this._element, 'dragstart', (event) => { this.iframes = [ ...getElementsByTagName('iframe'), ...getElementsByTagName('webview'), ]; for (const iframe of this.iframes) { iframe.style.pointerEvents = 'none'; } this.element.classList.add('dragged'); setTimeout(() => this.element.classList.remove('dragged'), 0); this.panelTransfer.setData([ new PanelTransfer(this.accessor.id, this.group.id, this.panelId), ], PanelTransfer.prototype); if (event.dataTransfer) { event.dataTransfer.effectAllowed = 'move'; } }), addDisposableListener(this._element, 'dragend', (ev) => { for (const iframe of this.iframes) { iframe.style.pointerEvents = 'auto'; } this.iframes = []; this.panelTransfer.clearData(PanelTransfer.prototype); }), addDisposableListener(this._element, 'mousedown', (event) => { if (event.defaultPrevented) { return; } /** * TODO: alternative to stopPropagation * * I need to stop the event propagation here since otherwise it'll be intercepted by event handlers * on the tabs-container. I cannot use event.preventDefault() since I need the on DragStart event to occur */ event.stopPropagation(); this._onChanged.fire({ kind: MouseEventKind.CLICK, event }); }), addDisposableListener(this._element, 'contextmenu', (event) => { this._onChanged.fire({ kind: MouseEventKind.CONTEXT_MENU, event, }); })); this.droptarget = new Droptarget(this._element, { validOverlays: 'none', canDisplayOverlay: (event) => { const data = getPanelData(); if (data) { return this.panelId !== data.panelId; } return this.group.model.canDisplayOverlay(event, DockviewDropTargets.Tab); }, }); this.addDisposables(this.droptarget.onDrop((event) => { this._onDropped.fire(event); })); } get element() { return this._element; } setActive(isActive) { toggleClass(this.element, 'active-tab', isActive); toggleClass(this.element, 'inactive-tab', !isActive); } setContent(part) { if (this.content) { this._element.removeChild(this.content.element); } this.content = part; this._element.appendChild(this.content.element); } dispose() { super.dispose(); this.droptarget.dispose(); } }