dockview-core
Version:
Zero dependency layout manager supporting tabs, groups, grids and splitviews for vanilla TypeScript
305 lines (304 loc) • 11.4 kB
JavaScript
;
/**
* Internal module system for dockview.
*
* Modules are feature bundles that register services into the dockview
* component. `registerModules(...)` is the one public entry point — it lets a
* sibling package contribute modules that `DockviewComponent` picks up at
* construction. The richer opt-in surface (a per-component `modules` option,
* framework wrappers) is still reserved for a future version; the module
* authoring API (`defineModule`, the service contracts) remains internal.
*/
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.");
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModuleRegistry = void 0;
exports.defineModule = defineModule;
exports._resetMissingModuleWarnings = _resetMissingModuleWarnings;
exports.assertModule = assertModule;
exports.registerModules = registerModules;
exports.getRegisteredModules = getRegisteredModules;
exports.clearRegisteredModules = clearRegisteredModules;
exports.markDockviewPackageLoaded = markDockviewPackageLoaded;
exports.isDockviewPackageLoaded = isDockviewPackageLoaded;
/**
* Typed helper for defining a module. Enforces that the factory's return
* type matches the slot in ServiceCollection at compile time, replacing
* the manual cast each module file would otherwise need.
*/
function defineModule(config) {
var _a;
return {
moduleName: config.name,
services: (_a = {},
_a[config.serviceKey] = config.create,
_a),
init: config.init
? function (host, services) {
return config.init(host, services[config.serviceKey]);
}
: undefined,
dependsOn: config.dependsOn,
};
}
var _warnedMissingModule = new Set();
/**
* For tests — clears the once-per-key dedup cache used by `assertModule`.
*/
function _resetMissingModuleWarnings() {
_warnedMissingModule.clear();
}
/**
* Returns the service if its module is registered, otherwise logs a
* deduplicated console error and returns `undefined`. Modelled on AG Grid's
* `assertModuleRegistered`: missing modules never throw — they degrade the
* affected feature to a no-op so consuming applications don't crash in
* production.
*
* Use at public-API entry points where the caller wants to surface which
* module is missing. For internal/lifecycle paths, plain `?.` chaining on
* the service slot is preferred — no log, just a silent no-op.
*/
function assertModule(service, moduleName, context) {
if (service !== undefined) {
return service;
}
var key = "".concat(moduleName, "|").concat(context !== null && context !== void 0 ? context : '');
if (_warnedMissingModule.has(key)) {
return undefined;
}
_warnedMissingModule.add(key);
var where = context ? " for ".concat(context) : '';
// eslint-disable-next-line no-console
console.error("dockview: module \"".concat(moduleName, "\" is not registered").concat(where, "."));
return undefined;
}
var ModuleRegistry = /** @class */ (function () {
function ModuleRegistry() {
this._modules = new Map();
this._services = {};
this._initDisposables = [];
}
Object.defineProperty(ModuleRegistry.prototype, "services", {
get: function () {
return this._services;
},
enumerable: false,
configurable: true
});
ModuleRegistry.prototype.register = function (module) {
var e_1, _a;
if (this._modules.has(module.moduleName)) {
return;
}
if (module.dependsOn) {
try {
for (var _b = __values(module.dependsOn), _c = _b.next(); !_c.done; _c = _b.next()) {
var dep = _c.value;
this.register(dep);
}
}
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._modules.set(module.moduleName, module);
};
ModuleRegistry.prototype.initialize = function (host) {
var e_2, _a, e_3, _b;
try {
for (var _c = __values(this._modules.values()), _d = _c.next(); !_d.done; _d = _c.next()) {
var module_1 = _d.value;
if (!module_1.services) {
continue;
}
try {
for (var _e = (e_3 = void 0, __values(Object.entries(module_1.services))), _f = _e.next(); !_f.done; _f = _e.next()) {
var _g = __read(_f.value, 2), name_1 = _g[0], factory = _g[1];
this._services[name_1] = factory(host);
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
}
finally { if (e_3) throw e_3.error; }
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_2) throw e_2.error; }
}
};
ModuleRegistry.prototype.postConstruct = function (host) {
var e_4, _a;
try {
for (var _b = __values(this._modules.values()), _c = _b.next(); !_c.done; _c = _b.next()) {
var module_2 = _c.value;
if (module_2.init) {
this._initDisposables.push(module_2.init(host, this._services));
}
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_4) throw e_4.error; }
}
};
ModuleRegistry.prototype.has = function (moduleName) {
return this._modules.has(moduleName);
};
ModuleRegistry.prototype.dispose = function () {
var e_5, _a, e_6, _b;
try {
// Tear down init() subscriptions first so they stop firing into
// services that are about to be disposed.
for (var _c = __values(this._initDisposables), _d = _c.next(); !_d.done; _d = _c.next()) {
var disposable = _d.value;
disposable.dispose();
}
}
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_5) throw e_5.error; }
}
this._initDisposables.length = 0;
try {
for (var _e = __values(Object.values(this._services)), _f = _e.next(); !_f.done; _f = _e.next()) {
var service = _f.value;
if (service !== undefined &&
typeof service.dispose === 'function') {
service.dispose();
}
}
}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
finally {
try {
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
}
finally { if (e_6) throw e_6.error; }
}
};
return ModuleRegistry;
}());
exports.ModuleRegistry = ModuleRegistry;
/**
* Process-global list of modules registered via {@link registerModules}.
* `DockviewComponent` appends these to its built-in set at construction, so
* importing a package that calls `registerModules(...)` (e.g. `dockview`)
* makes those modules available to every component in the process —
* modelled on AG Grid's `ModuleRegistry.registerModules`.
*/
var _globalModules = [];
/**
* Register modules globally. Idempotent per `moduleName` — registering the
* same module twice is a no-op. Intended to be called once at import time by
* the package that bundles a given set of modules.
*/
function registerModules(modules) {
var e_7, _a;
var _loop_1 = function (module_3) {
if (_globalModules.some(function (m) { return m.moduleName === module_3.moduleName; })) {
return "continue";
}
_globalModules.push(module_3);
};
try {
for (var modules_1 = __values(modules), modules_1_1 = modules_1.next(); !modules_1_1.done; modules_1_1 = modules_1.next()) {
var module_3 = modules_1_1.value;
_loop_1(module_3);
}
}
catch (e_7_1) { e_7 = { error: e_7_1 }; }
finally {
try {
if (modules_1_1 && !modules_1_1.done && (_a = modules_1.return)) _a.call(modules_1);
}
finally { if (e_7) throw e_7.error; }
}
}
/**
* Returns the globally-registered modules (a copy). `DockviewComponent` reads
* this to extend its built-in module set.
*/
function getRegisteredModules() {
return __spreadArray([], __read(_globalModules), false);
}
/**
* For tests — clears the global module registry.
*/
function clearRegisteredModules() {
_globalModules.length = 0;
}
/**
* This marker exists for ONE purpose: a developer warning about the v7 package
* renames. It has no functional effect on dockview's behaviour. Following the
* renames, `dockview-core` is internal and `dockview` is the public JavaScript
* package; `dockview` calls {@link markDockviewPackageLoaded} on import so that
* `dockview-core` can detect — and warn about — being used directly.
*/
var _dockviewPackageLoaded = false;
/**
* Called once by the `dockview` package on import, solely so `dockview-core`
* can warn when it is used directly (see above). Not used for anything else.
*/
function markDockviewPackageLoaded() {
_dockviewPackageLoaded = true;
}
/**
* Whether the `dockview` package has been loaded in this process. Used only to
* gate the "don't use dockview-core directly" developer warning.
*/
function isDockviewPackageLoaded() {
return _dockviewPackageLoaded;
}