UNPKG

dockview

Version:

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

144 lines (143 loc) 5.6 kB
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'); } } }