dockview
Version:
Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support
144 lines (143 loc) • 5.6 kB
JavaScript
import { toggleClass } from '../dom';
import { Emitter } from '../events';
import { CompositeDisposable } from '../lifecycle';
import { DragAndDropObserver } from './dnd';
export var Position;
(function (Position) {
Position["Top"] = "Top";
Position["Left"] = "Left";
Position["Bottom"] = "Bottom";
Position["Right"] = "Right";
Position["Center"] = "Center";
})(Position || (Position = {}));
function isBooleanValue(canDisplayOverlay) {
return typeof canDisplayOverlay === 'boolean';
}
export class Droptarget extends CompositeDisposable {
constructor(element, options) {
super();
this.element = element;
this.options = options;
this._onDrop = new Emitter();
this.onDrop = this._onDrop.event;
this.addDisposables(new DragAndDropObserver(this.element, {
onDragEnter: (e) => undefined,
onDragOver: (e) => {
if (isBooleanValue(this.options.canDisplayOverlay)) {
if (!this.options.canDisplayOverlay) {
return;
}
}
else if (!this.options.canDisplayOverlay(e)) {
return;
}
if (!this.target) {
this.target = document.createElement('div');
this.target.className = 'drop-target-dropzone';
this.overlay = document.createElement('div');
this.overlay.className = 'drop-target-selection';
this._state = Position.Center;
this.target.appendChild(this.overlay);
this.element.classList.add('drop-target');
this.element.append(this.target);
}
if (this.options.validOverlays === 'none') {
return;
}
if (!this.target || !this.overlay) {
return;
}
const width = this.target.clientWidth;
const height = this.target.clientHeight;
if (width === 0 || height === 0) {
return; // avoid div!0
}
const x = e.offsetX;
const y = e.offsetY;
const xp = (100 * x) / width;
const yp = (100 * y) / height;
let isRight = false;
let isLeft = false;
let isTop = false;
let isBottom = false;
switch (this.options.validOverlays) {
case 'all':
isRight = xp > 80;
isLeft = xp < 20;
isTop = !isRight && !isLeft && yp < 20;
isBottom = !isRight && !isLeft && yp > 80;
break;
case 'vertical':
isTop = yp < 50;
isBottom = yp >= 50;
break;
case 'horizontal':
isLeft = xp < 50;
isRight = xp >= 50;
break;
}
const isSmallX = width < 100;
const isSmallY = height < 100;
toggleClass(this.overlay, 'right', !isSmallX && isRight);
toggleClass(this.overlay, 'left', !isSmallX && isLeft);
toggleClass(this.overlay, 'top', !isSmallY && isTop);
toggleClass(this.overlay, 'bottom', !isSmallY && isBottom);
toggleClass(this.overlay, 'small-right', isSmallX && isRight);
toggleClass(this.overlay, 'small-left', isSmallX && isLeft);
toggleClass(this.overlay, 'small-top', isSmallY && isTop);
toggleClass(this.overlay, 'small-bottom', isSmallY && isBottom);
if (isRight) {
this._state = Position.Right;
}
else if (isLeft) {
this._state = Position.Left;
}
else if (isTop) {
this._state = Position.Top;
}
else if (isBottom) {
this._state = Position.Bottom;
}
else {
this._state = Position.Center;
}
},
onDragLeave: (e) => {
this.removeDropTarget();
},
onDragEnd: (e) => {
this.removeDropTarget();
},
onDrop: (e) => {
e.preventDefault();
e.stopPropagation();
const state = this._state;
this.removeDropTarget();
if (state) {
this._onDrop.fire({ position: state, event: e });
}
},
}));
}
get state() {
return this._state;
}
set validOverlays(value) {
this.options.validOverlays = value;
}
set canDisplayOverlay(value) {
this.options.canDisplayOverlay = value;
}
dispose() {
this._onDrop.dispose();
this.removeDropTarget();
}
removeDropTarget() {
if (this.target) {
this._state = undefined;
this.element.removeChild(this.target);
this.target = undefined;
this.element.classList.remove('drop-target');
}
}
}