UNPKG

dockview-core

Version:

Zero dependency layout manager supporting tabs, groups, grids and splitviews for vanilla TypeScript

305 lines (304 loc) 11.4 kB
"use strict"; /** * 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; }