dockview-core
Version:
Zero dependency layout manager supporting tabs, grids and splitviews
209 lines (208 loc) • 9.38 kB
JavaScript
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 __());
};
})();
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OverlayRenderContainer = void 0;
var dnd_1 = require("../dnd/dnd");
var dom_1 = require("../dom");
var lifecycle_1 = require("../lifecycle");
function createFocusableElement() {
var element = document.createElement('div');
element.tabIndex = -1;
return element;
}
var OverlayRenderContainer = /** @class */ (function (_super) {
__extends(OverlayRenderContainer, _super);
function OverlayRenderContainer(element, accessor) {
var _this = _super.call(this) || this;
_this.element = element;
_this.accessor = accessor;
_this.map = {};
_this._disposed = false;
_this.addDisposables(lifecycle_1.Disposable.from(function () {
var e_1, _a;
try {
for (var _b = __values(Object.values(_this.map)), _c = _b.next(); !_c.done; _c = _b.next()) {
var value = _c.value;
value.disposable.dispose();
value.destroy.dispose();
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
_this._disposed = true;
}));
return _this;
}
OverlayRenderContainer.prototype.detatch = function (panel) {
if (this.map[panel.api.id]) {
var _a = this.map[panel.api.id], disposable = _a.disposable, destroy = _a.destroy;
disposable.dispose();
destroy.dispose();
delete this.map[panel.api.id];
return true;
}
return false;
};
OverlayRenderContainer.prototype.attach = function (options) {
var _this = this;
var panel = options.panel, referenceContainer = options.referenceContainer;
if (!this.map[panel.api.id]) {
var element = createFocusableElement();
element.className = 'dv-render-overlay';
this.map[panel.api.id] = {
panel: panel,
disposable: lifecycle_1.Disposable.NONE,
destroy: lifecycle_1.Disposable.NONE,
element: element,
};
}
var focusContainer = this.map[panel.api.id].element;
if (panel.view.content.element.parentElement !== focusContainer) {
focusContainer.appendChild(panel.view.content.element);
}
if (focusContainer.parentElement !== this.element) {
this.element.appendChild(focusContainer);
}
var resize = function () {
// TODO propagate position to avoid getDomNodePagePosition calls, possible performance bottleneck?
var box = (0, dom_1.getDomNodePagePosition)(referenceContainer.element);
var box2 = (0, dom_1.getDomNodePagePosition)(_this.element);
focusContainer.style.left = "".concat(box.left - box2.left, "px");
focusContainer.style.top = "".concat(box.top - box2.top, "px");
focusContainer.style.width = "".concat(box.width, "px");
focusContainer.style.height = "".concat(box.height, "px");
(0, dom_1.toggleClass)(focusContainer, 'dv-render-overlay-float', panel.group.api.location.type === 'floating');
};
var visibilityChanged = function () {
if (panel.api.isVisible) {
resize();
}
focusContainer.style.display = panel.api.isVisible ? '' : 'none';
};
var observerDisposable = new lifecycle_1.MutableDisposable();
var correctLayerPosition = function () {
if (panel.api.location.type === 'floating') {
queueMicrotask(function () {
var floatingGroup = _this.accessor.floatingGroups.find(function (group) { return group.group === panel.api.group; });
if (!floatingGroup) {
return;
}
var element = floatingGroup.overlay.element;
var update = function () {
var level = Number(element.getAttribute('aria-level'));
focusContainer.style.zIndex = "calc(var(--dv-overlay-z-index, 999) + ".concat(level * 2 + 1, ")");
};
var observer = new MutationObserver(function () {
update();
});
observerDisposable.value = lifecycle_1.Disposable.from(function () {
return observer.disconnect();
});
observer.observe(element, {
attributeFilter: ['aria-level'],
attributes: true,
});
update();
});
}
else {
focusContainer.style.zIndex = ''; // reset the z-index, perhaps CSS will take over here
}
};
var disposable = new lifecycle_1.CompositeDisposable(observerDisposable,
/**
* since container is positioned absoutely we must explicitly forward
* the dnd events for the expect behaviours to continue to occur in terms of dnd
*
* the dnd observer does not need to be conditional on whether the panel is visible since
* non-visible panels are 'display: none' and in such case the dnd observer will not fire.
*/
new dnd_1.DragAndDropObserver(focusContainer, {
onDragEnd: function (e) {
referenceContainer.dropTarget.dnd.onDragEnd(e);
},
onDragEnter: function (e) {
referenceContainer.dropTarget.dnd.onDragEnter(e);
},
onDragLeave: function (e) {
referenceContainer.dropTarget.dnd.onDragLeave(e);
},
onDrop: function (e) {
referenceContainer.dropTarget.dnd.onDrop(e);
},
onDragOver: function (e) {
referenceContainer.dropTarget.dnd.onDragOver(e);
},
}), panel.api.onDidVisibilityChange(function () {
/**
* Control the visibility of the content, however even when not visible (display: none)
* the content is still maintained within the DOM hence DOM specific attributes
* such as scroll position are maintained when next made visible.
*/
visibilityChanged();
}), panel.api.onDidDimensionsChange(function () {
if (!panel.api.isVisible) {
return;
}
resize();
}), panel.api.onDidLocationChange(function () {
correctLayerPosition();
}));
this.map[panel.api.id].destroy = lifecycle_1.Disposable.from(function () {
var _a;
if (panel.view.content.element.parentElement === focusContainer) {
focusContainer.removeChild(panel.view.content.element);
}
(_a = focusContainer.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(focusContainer);
});
correctLayerPosition();
queueMicrotask(function () {
if (_this.isDisposed) {
return;
}
/**
* wait until everything has finished in the current stack-frame call before
* calling the first resize as other size-altering events may still occur before
* the end of the stack-frame.
*/
visibilityChanged();
});
// dispose of logic asoccciated with previous reference-container
this.map[panel.api.id].disposable.dispose();
// and reset the disposable to the active reference-container
this.map[panel.api.id].disposable = disposable;
return focusContainer;
};
return OverlayRenderContainer;
}(lifecycle_1.CompositeDisposable));
exports.OverlayRenderContainer = OverlayRenderContainer;
;