dockview-core
Version:
Zero dependency layout manager supporting tabs, groups, grids and splitviews for vanilla TypeScript
335 lines (334 loc) • 13.8 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Droptarget = exports.WillShowOverlayEvent = void 0;
exports.directionToPosition = directionToPosition;
exports.positionToDirection = positionToDirection;
exports.calculateQuadrantAsPercentage = calculateQuadrantAsPercentage;
exports.calculateQuadrantAsPixels = calculateQuadrantAsPixels;
var events_1 = require("../events");
var lifecycle_1 = require("../lifecycle");
var dnd_1 = require("./dnd");
var dropOverlay_1 = require("./dropOverlay");
var WillShowOverlayEvent = /** @class */ (function (_super) {
__extends(WillShowOverlayEvent, _super);
function WillShowOverlayEvent(options) {
var _this = _super.call(this) || this;
_this.options = options;
return _this;
}
Object.defineProperty(WillShowOverlayEvent.prototype, "nativeEvent", {
get: function () {
return this.options.nativeEvent;
},
enumerable: false,
configurable: true
});
Object.defineProperty(WillShowOverlayEvent.prototype, "position", {
get: function () {
return this.options.position;
},
enumerable: false,
configurable: true
});
return WillShowOverlayEvent;
}(events_1.DockviewEvent));
exports.WillShowOverlayEvent = WillShowOverlayEvent;
function directionToPosition(direction) {
switch (direction) {
case 'above':
return 'top';
case 'below':
return 'bottom';
case 'left':
return 'left';
case 'right':
return 'right';
case 'within':
return 'center';
default:
throw new Error("invalid direction '".concat(direction, "'"));
}
}
function positionToDirection(position) {
switch (position) {
case 'top':
return 'above';
case 'bottom':
return 'below';
case 'left':
return 'left';
case 'right':
return 'right';
case 'center':
return 'within';
default:
throw new Error("invalid position '".concat(position, "'"));
}
}
var DEFAULT_ACTIVATION_SIZE = {
value: 20,
type: 'percentage',
};
var Droptarget = /** @class */ (function (_super) {
__extends(Droptarget, _super);
function Droptarget(element, options) {
var _this = _super.call(this) || this;
_this.element = element;
_this.options = options;
_this._onDrop = new events_1.Emitter();
_this.onDrop = _this._onDrop.event;
_this._onWillShowOverlay = new events_1.Emitter();
_this.onWillShowOverlay = _this._onWillShowOverlay.event;
_this._disabled = false;
// use a set to take advantage of #<set>.has
_this._acceptedTargetZonesSet = new Set(_this.options.acceptedTargetZones);
_this.dnd = new dnd_1.DragAndDropObserver(_this.element, {
onDragEnter: function () {
var _a, _b, _c;
(_c = (_b = (_a = _this.options).getOverrideTarget) === null || _b === void 0 ? void 0 : _b.call(_a)) === null || _c === void 0 ? void 0 : _c.getElements();
},
onDragOver: function (e) {
var _a, _b, _c, _d, _e, _f, _g;
Droptarget.ACTUAL_TARGET = _this;
var overrideTarget = (_b = (_a = _this.options).getOverrideTarget) === null || _b === void 0 ? void 0 : _b.call(_a);
if (_this._acceptedTargetZonesSet.size === 0) {
if (overrideTarget) {
return;
}
_this.removeDropTarget();
return;
}
var target = (_e = (_d = (_c = _this.options).getOverlayOutline) === null || _d === void 0 ? void 0 : _d.call(_c)) !== null && _e !== void 0 ? _e : _this.element;
var width = target.offsetWidth;
var height = target.offsetHeight;
if (width === 0 || height === 0) {
return; // avoid div!0
}
var rect = e.currentTarget.getBoundingClientRect();
var x = ((_f = e.clientX) !== null && _f !== void 0 ? _f : 0) - rect.left;
var y = ((_g = e.clientY) !== null && _g !== void 0 ? _g : 0) - rect.top;
var quadrant = _this.calculateQuadrant(_this._acceptedTargetZonesSet, x, y, width, height);
/**
* If the event has already been used by another DropTarget instance
* then don't show a second drop target, only one target should be
* active at any one time
*/
if (_this.isAlreadyUsed(e) || quadrant === null) {
// no drop target should be displayed
_this.removeDropTarget();
return;
}
if (!_this.options.canDisplayOverlay(e, quadrant)) {
if (overrideTarget) {
return;
}
_this.removeDropTarget();
return;
}
var willShowOverlayEvent = new WillShowOverlayEvent({
nativeEvent: e,
position: quadrant,
});
/**
* Provide an opportunity to prevent the overlay appearing and in turn
* any dnd behaviours
*/
_this._onWillShowOverlay.fire(willShowOverlayEvent);
if (willShowOverlayEvent.defaultPrevented) {
_this.removeDropTarget();
return;
}
_this.markAsUsed(e);
if (overrideTarget) {
//
}
else if (!_this.targetElement) {
var els = (0, dropOverlay_1.createOverlayElements)();
_this.targetElement = els.dropzone;
_this.overlayElement = els.selection;
_this._state = 'center';
target.classList.add('dv-drop-target');
target.append(_this.targetElement);
}
_this.toggleClasses(quadrant, width, height);
_this._state = quadrant;
},
onDragLeave: function () {
var _a, _b;
var target = (_b = (_a = _this.options).getOverrideTarget) === null || _b === void 0 ? void 0 : _b.call(_a);
if (target) {
return;
}
_this.removeDropTarget();
},
onDragEnd: function (e) {
var _a, _b;
var target = (_b = (_a = _this.options).getOverrideTarget) === null || _b === void 0 ? void 0 : _b.call(_a);
if (target && Droptarget.ACTUAL_TARGET === _this) {
if (_this._state) {
// only stop the propagation of the event if we are dealing with it
// which is only when the target has state
e.stopPropagation();
_this._onDrop.fire({
position: _this._state,
nativeEvent: e,
});
}
}
_this.removeDropTarget();
target === null || target === void 0 ? void 0 : target.clear();
},
onDrop: function (e) {
var _a, _b, _c;
e.preventDefault();
var state = _this._state;
_this.removeDropTarget();
(_c = (_b = (_a = _this.options).getOverrideTarget) === null || _b === void 0 ? void 0 : _b.call(_a)) === null || _c === void 0 ? void 0 : _c.clear();
if (state) {
// only stop the propagation of the event if we are dealing with it
// which is only when the target has state
e.stopPropagation();
_this._onDrop.fire({ position: state, nativeEvent: e });
}
},
});
_this.addDisposables(_this._onDrop, _this._onWillShowOverlay, _this.dnd);
return _this;
}
Object.defineProperty(Droptarget.prototype, "disabled", {
get: function () {
return this._disabled;
},
set: function (value) {
this._disabled = value;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Droptarget.prototype, "state", {
get: function () {
return this._state;
},
enumerable: false,
configurable: true
});
Droptarget.prototype.setTargetZones = function (acceptedTargetZones) {
this._acceptedTargetZonesSet = new Set(acceptedTargetZones);
};
Droptarget.prototype.setOverlayModel = function (model) {
this.options.overlayModel = model;
};
Droptarget.prototype.dispose = function () {
this.removeDropTarget();
_super.prototype.dispose.call(this);
};
/**
* Add a property to the event object for other potential listeners to check
*/
Droptarget.prototype.markAsUsed = function (event) {
event[Droptarget.USED_EVENT_ID] = true;
};
/**
* Check is the event has already been used by another instance of DropTarget
*/
Droptarget.prototype.isAlreadyUsed = function (event) {
var value = event[Droptarget.USED_EVENT_ID];
return typeof value === 'boolean' && value;
};
Droptarget.prototype.toggleClasses = function (quadrant, width, height) {
var _a, _b, _c, _d, _e;
var target = (_b = (_a = this.options).getOverrideTarget) === null || _b === void 0 ? void 0 : _b.call(_a);
if (target) {
var outlineEl = (_e = (_d = (_c = this.options).getOverlayOutline) === null || _d === void 0 ? void 0 : _d.call(_c)) !== null && _e !== void 0 ? _e : this.element;
(0, dropOverlay_1.renderAnchoredOverlay)({
outlineElement: outlineEl,
targetModel: target,
quadrant: quadrant,
width: width,
height: height,
overlayModel: this.options.overlayModel,
className: this.options.className,
});
return;
}
if (!this.overlayElement) {
return;
}
(0, dropOverlay_1.renderInPlaceOverlay)(this.overlayElement, quadrant, width, height, this.options.overlayModel);
};
Droptarget.prototype.calculateQuadrant = function (overlayType, x, y, width, height) {
var _a, _b;
var activationSizeOptions = (_b = (_a = this.options.overlayModel) === null || _a === void 0 ? void 0 : _a.activationSize) !== null && _b !== void 0 ? _b : DEFAULT_ACTIVATION_SIZE;
var isPercentage = activationSizeOptions.type === 'percentage';
if (isPercentage) {
return calculateQuadrantAsPercentage(overlayType, x, y, width, height, activationSizeOptions.value);
}
return calculateQuadrantAsPixels(overlayType, x, y, width, height, activationSizeOptions.value);
};
Droptarget.prototype.removeDropTarget = function () {
var _a;
if (this.targetElement) {
this._state = undefined;
(_a = this.targetElement.parentElement) === null || _a === void 0 ? void 0 : _a.classList.remove('dv-drop-target');
this.targetElement.remove();
this.targetElement = undefined;
this.overlayElement = undefined;
}
};
Droptarget.USED_EVENT_ID = '__dockview_droptarget_event_is_used__';
return Droptarget;
}(lifecycle_1.CompositeDisposable));
exports.Droptarget = Droptarget;
function calculateQuadrantAsPercentage(overlayType, x, y, width, height, threshold) {
var xp = (100 * x) / width;
var yp = (100 * y) / height;
if (overlayType.has('left') && xp < threshold) {
return 'left';
}
if (overlayType.has('right') && xp > 100 - threshold) {
return 'right';
}
if (overlayType.has('top') && yp < threshold) {
return 'top';
}
if (overlayType.has('bottom') && yp > 100 - threshold) {
return 'bottom';
}
if (!overlayType.has('center')) {
return null;
}
return 'center';
}
function calculateQuadrantAsPixels(overlayType, x, y, width, height, threshold) {
if (overlayType.has('left') && x < threshold) {
return 'left';
}
if (overlayType.has('right') && x > width - threshold) {
return 'right';
}
if (overlayType.has('top') && y < threshold) {
return 'top';
}
if (overlayType.has('bottom') && y > height - threshold) {
return 'bottom';
}
if (!overlayType.has('center')) {
return null;
}
return 'center';
}