dockview
Version:
Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support
102 lines (101 loc) • 4.24 kB
JavaScript
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();
}
}