@trops/dash-core 0.1.434 → 0.1.435

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -14565,27 +14565,18 @@ var LayoutBuilderConfigModal = function LayoutBuilderConfigModal(_ref) {
14565
14565
  return s.key === activeSection;
14566
14566
  }) || sections[0];
14567
14567
 
14568
- // Scope/package label for the footer so the user can tell which
14569
- // package a widget comes from (ambiguous component names like
14570
- // `ProspectListColumn` can live under either `@ai-built/…` or
14571
- // `@trops/pipeline`). Same derivation order as WidgetCardHeader:
14572
- // widget config id → widget config package → layout item workspace.
14568
+ // Footer label: derive @scope/package straight from the layout
14569
+ // item's scoped component id. Strict no workspace fallback.
14573
14570
  var footerPackageLabel = function () {
14574
- if (!itemSelected) return "";
14575
- var cfg = ComponentManager.config(itemSelected.component, itemSelected);
14576
- var dropTrailingComponent = function dropTrailingComponent(s) {
14577
- if (typeof s !== "string") return "";
14578
- var lastDot = s.lastIndexOf(".");
14579
- return lastDot > 0 ? s.slice(0, lastDot) : s;
14580
- };
14581
- var fromId = dropTrailingComponent((cfg === null || cfg === void 0 ? void 0 : cfg.id) || "");
14582
- if (fromId) return fromId;
14583
- if (cfg !== null && cfg !== void 0 && cfg["package"]) return String(cfg["package"]);
14584
- var ws = itemSelected.workspace;
14585
- if (typeof ws === "string" && ws && ws !== "layout") {
14586
- return ws.startsWith("@") ? ws : "@".concat(ws);
14587
- }
14588
- return "";
14571
+ var scopedId = (itemSelected === null || itemSelected === void 0 ? void 0 : itemSelected.component) || "";
14572
+ if (typeof scopedId !== "string") return "";
14573
+ var parts = scopedId.split(".");
14574
+ if (parts.length !== 3) return "";
14575
+ var _parts = _slicedToArray(parts, 2),
14576
+ scope = _parts[0],
14577
+ pkg = _parts[1];
14578
+ if (!scope || !pkg) return "";
14579
+ return "@".concat(scope, "/").concat(pkg);
14589
14580
  }();
14590
14581
  var componentName = itemSelected ? itemSelected["component"] : "";
14591
14582
  var footerLeftContent = footerPackageLabel ? /*#__PURE__*/jsxs("span", {
@@ -18891,29 +18882,21 @@ var WidgetCardHeader = function WidgetCardHeader(_ref) {
18891
18882
  // Get widget name from config or item
18892
18883
  var widgetName = (widgetConfig === null || widgetConfig === void 0 ? void 0 : widgetConfig.displayName) || (widgetConfig === null || widgetConfig === void 0 ? void 0 : widgetConfig.name) || (widgetItem === null || widgetItem === void 0 ? void 0 : widgetItem.name) || (widgetItem === null || widgetItem === void 0 ? void 0 : widgetItem.component);
18893
18884
 
18894
- // Build a scope/package subtitle so ambiguous component names like
18895
- // `ProspectListColumn` (which might come from `@ai-built/…` or
18896
- // `@trops/pipeline`) are disambiguated in the layout builder. Derives
18897
- // from whatever identity the config / layout item carries:
18898
- // - widgetConfig.id: e.g. "@ai-built/prospectlistcolumn.ProspectListColumn"
18899
- // - widgetConfig.package: e.g. "@ai-built/prospectlistcolumn"
18900
- // - widgetItem.workspace: fallback hint ("ai-built" / "@trops/pipeline")
18901
- // Falls back to empty string so we can skip rendering if we have
18902
- // nothing meaningful beyond the component name itself.
18885
+ // Derive the "@scope/package" label from the layout item's scoped
18886
+ // component id (`scope.package.Component`). Strict the layout item
18887
+ // is the source of truth. If the item isn't scoped (a legacy layout
18888
+ // that LayoutModel couldn't migrate, or a missing widget) the label
18889
+ // is empty rather than guessed from the workspace category.
18903
18890
  var packageLabel = function () {
18904
- var dropTrailingComponent = function dropTrailingComponent(s) {
18905
- if (typeof s !== "string") return "";
18906
- var lastDot = s.lastIndexOf(".");
18907
- return lastDot > 0 ? s.slice(0, lastDot) : s;
18908
- };
18909
- var fromId = dropTrailingComponent((widgetConfig === null || widgetConfig === void 0 ? void 0 : widgetConfig.id) || "");
18910
- if (fromId) return fromId;
18911
- if (widgetConfig !== null && widgetConfig !== void 0 && widgetConfig["package"]) return String(widgetConfig["package"]);
18912
- var wsHint = widgetItem === null || widgetItem === void 0 ? void 0 : widgetItem.workspace;
18913
- if (typeof wsHint === "string" && wsHint && wsHint !== "layout") {
18914
- return wsHint.startsWith("@") ? wsHint : "@".concat(wsHint);
18915
- }
18916
- return "";
18891
+ var scopedId = (widgetItem === null || widgetItem === void 0 ? void 0 : widgetItem.component) || (widgetConfig === null || widgetConfig === void 0 ? void 0 : widgetConfig.id) || "";
18892
+ if (typeof scopedId !== "string") return "";
18893
+ var parts = scopedId.split(".");
18894
+ if (parts.length !== 3) return "";
18895
+ var _parts = _slicedToArray(parts, 2),
18896
+ scope = _parts[0],
18897
+ pkg = _parts[1];
18898
+ if (!scope || !pkg) return "";
18899
+ return "@".concat(scope, "/").concat(pkg);
18917
18900
  }();
18918
18901
 
18919
18902
  // Get provider requirements from widget config (not from item directly)
@@ -27497,10 +27480,10 @@ function addChildToLayoutItem(childComponent, layoutItem, workspace) {
27497
27480
  * widgets share the same bare name
27498
27481
  * @returns {boolean} true if the widget can be rendered
27499
27482
  */
27500
- function isWidgetResolvable(componentKey, data) {
27483
+ function isWidgetResolvable(componentKey) {
27501
27484
  // Layout containers are always resolvable (handled specially by WidgetFactory)
27502
27485
  if (ComponentManager.isLayoutContainer(componentKey)) return true;
27503
- var config = ComponentManager.resolve(componentKey, data);
27486
+ var config = ComponentManager.resolve(componentKey);
27504
27487
  return !!(config && typeof config.component === "function");
27505
27488
  }
27506
27489
 
@@ -27530,6 +27513,52 @@ function isWidgetResolvable(componentKey, data) {
27530
27513
  // isMinOrderForItem
27531
27514
  // }
27532
27515
 
27516
+ /**
27517
+ * One-shot legacy bare-name → canonical scoped-id migration.
27518
+ *
27519
+ * Pre-v0.1.435 dashboards stored layout items with bare component
27520
+ * names (`component: "PipelineKanban"`). Post-v0.1.435 the registry
27521
+ * is keyed strictly by scoped ids (`scope.package.Component`) and
27522
+ * `resolveComponentKey` does no fallback scanning. This helper
27523
+ * bridges the two: at workspace-load time, walk the registry once
27524
+ * and rewrite any bare name that maps unambiguously to a scoped
27525
+ * registration.
27526
+ *
27527
+ * Behavior (deliberately strict):
27528
+ * - Already-scoped (3 dot-separated parts) → return verbatim.
27529
+ * - Bare name with exactly one matching registry key ending in
27530
+ * `.${bareName}` → return the scoped key.
27531
+ * - Zero matches OR multiple matches → return verbatim. The
27532
+ * renderer surfaces `WidgetNotFound` rather than guessing wrong;
27533
+ * the user can resave or republish to fix the layout.
27534
+ *
27535
+ * Should be called once per layout item on workspace load. After the
27536
+ * workspace is saved, every item carries a scoped id and this helper
27537
+ * is a no-op.
27538
+ *
27539
+ * @param {Object} componentMap - The live registry map keyed by scoped ids
27540
+ * @param {string} component - The layout item's `component` field
27541
+ * @returns {string} - The canonical scoped id, or the input unchanged
27542
+ */
27543
+ function migrateBareComponentName(componentMap, component) {
27544
+ if (!componentMap || typeof component !== "string" || !component) {
27545
+ return component;
27546
+ }
27547
+ // Already scoped — fast path. Three dot-separated parts is the
27548
+ // canonical shape (`scope.package.Component`); anything else
27549
+ // (bare names, two-part forms, four-part typos) goes through the
27550
+ // suffix scan.
27551
+ if (component.split(".").length === 3) return component;
27552
+ // Already in the registry under its current key — also a fast path.
27553
+ if (component in componentMap) return component;
27554
+ var suffix = ".".concat(component);
27555
+ var matches = Object.keys(componentMap).filter(function (k) {
27556
+ return k.endsWith(suffix);
27557
+ });
27558
+ if (matches.length === 1) return matches[0];
27559
+ return component;
27560
+ }
27561
+
27533
27562
  function ownKeys$C(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
27534
27563
  function _objectSpread$C(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$C(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$C(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
27535
27564
  function _createForOfIteratorHelper$k(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray$k(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
@@ -27607,6 +27636,14 @@ var LayoutModel = function LayoutModel(layoutItem, workspaceLayout, dashboardId)
27607
27636
  layout.component = obj["componentName"];
27608
27637
  }
27609
27638
 
27639
+ // Legacy bare-name migration. Pre-v0.1.435 layouts stored
27640
+ // `component: "PipelineKanban"`; the registry is now strictly
27641
+ // keyed by `scope.package.Component`. If the layout item still
27642
+ // carries a bare name AND the registry has exactly one matching
27643
+ // scoped key, rewrite to the scoped form. The next save persists
27644
+ // the migration. Idempotent — already-scoped names pass through.
27645
+ layout.component = migrateBareComponentName(ComponentManager.componentMap(), layout.component);
27646
+
27610
27647
  /**
27611
27648
  * @param {String} direction Layout direction (row|col)
27612
27649
  * @deprecated Use grid layout instead of flexbox direction
@@ -27668,7 +27705,10 @@ var LayoutModel = function LayoutModel(layoutItem, workspaceLayout, dashboardId)
27668
27705
 
27669
27706
  layout.uuid = dashboardId !== undefined ? "".concat(dashboardId, "-").concat(layout["component"], "-").concat(layout.id) : "".concat(layout["component"], "-").concat(layout.id);
27670
27707
 
27671
- /// widget configuration
27708
+ // Resolve widget configuration — strict scoped lookup. By this
27709
+ // point `layout.component` has already been migrated from any
27710
+ // legacy bare name above, so config() either returns the live
27711
+ // entry or null (renderer shows WidgetNotFound).
27672
27712
  var widgetConfig = ComponentManager.config(layout["component"], obj);
27673
27713
  layout.userPrefs = {};
27674
27714
  layout.widgetConfig = widgetConfig;
@@ -27683,16 +27723,6 @@ var LayoutModel = function LayoutModel(layoutItem, workspaceLayout, dashboardId)
27683
27723
  if (Array.isArray(widgetConfig.eventHandlers)) {
27684
27724
  layout.eventHandlers = widgetConfig.eventHandlers;
27685
27725
  }
27686
- // Migrate legacy bare `component` references to the canonical
27687
- // scoped form (`scope.package.Component`). ComponentManager.config
27688
- // returns the resolved scoped key on `widgetConfig.component`, so
27689
- // we just lift it. Idempotent: items already scoped pass through
27690
- // unchanged because resolveComponentKey returns the input verbatim
27691
- // when it's already in the map. Persisted on next save — no
27692
- // separate migration step needed.
27693
- if (typeof widgetConfig.component === "string" && widgetConfig.component && widgetConfig.component !== layout.component) {
27694
- layout.component = widgetConfig.component;
27695
- }
27696
27726
  }
27697
27727
 
27698
27728
  // Merge user-entered config values (from EnhancedWidgetDropdown) into userPrefs
@@ -31378,6 +31408,34 @@ var ContextModel = /*#__PURE__*/function () {
31378
31408
  }]);
31379
31409
  }();
31380
31410
 
31411
+ /**
31412
+ * Resolve a component reference to its registry key.
31413
+ *
31414
+ * Strict exact-match lookup. Layout items carry the canonical scoped
31415
+ * id (`scope.package.Component`); the registry stores entries under
31416
+ * the same key. If the layout item's `component` doesn't match a
31417
+ * registered key exactly, the renderer shows `WidgetNotFound` — there
31418
+ * is no suffix-scan fallback and no `packageId` hint, because both
31419
+ * could silently resolve a typo / legacy bare name to the wrong widget.
31420
+ *
31421
+ * Legacy dashboards that still carry a bare `component` (pre-scope
31422
+ * migration) are handled in `LayoutModel`, which performs a one-shot
31423
+ * suffix-scan rewrite on load. By the time `resolveComponentKey` is
31424
+ * called, every layout item is expected to have a fully scoped id.
31425
+ *
31426
+ * Pure function. No side effects. Stays outside ComponentManager so
31427
+ * it can be tested in isolation without the Models/Layout import chain.
31428
+ *
31429
+ * @param {Object} componentMap - The registry map keyed by scoped ids
31430
+ * @param {string} component - The scoped id from the layout item
31431
+ * @returns {string|null} The matching registry key, or null
31432
+ */
31433
+ function resolveComponentKey(componentMap, component) {
31434
+ if (!componentMap || !component) return null;
31435
+ if (typeof component !== "string") return null;
31436
+ return component in componentMap ? component : null;
31437
+ }
31438
+
31381
31439
  /**
31382
31440
  * scopedComponentId.js
31383
31441
  *
@@ -31444,57 +31502,48 @@ function bareComponentName(idOrName) {
31444
31502
  return parts[parts.length - 1] || "";
31445
31503
  }
31446
31504
 
31505
+ var _componentMap = {};
31506
+ var _containerComponent = null;
31507
+ var _gridContainerComponent = null;
31508
+
31447
31509
  /**
31448
- * Resolve a component name to a registry key. Returns null if no
31449
- * match exists.
31510
+ * Compute the canonical `scope.package.Component` id for a widget
31511
+ * config. Throws if the config doesn't carry enough origin metadata
31512
+ * to derive an id.
31450
31513
  *
31451
- * Pure function — depends only on the passed-in `componentMap` and
31452
- * `data`. Lives outside ComponentManager so it can be tested without
31453
- * pulling in the full Component/Layout import chain (and so other
31454
- * call sites can route through it without circular deps).
31514
+ * Order of precedence:
31515
+ * - `config.id` already scoped (3 dot-separated parts, no leading "@")
31516
+ * - `config.scope` + `config.packageName` + (`config.name` |
31517
+ * `config.component?.displayName` | `config.component?.name`)
31518
+ * - Otherwise throw — the config is missing origin info and would
31519
+ * register under an ambiguous key.
31455
31520
  *
31456
- * Lookup order (the LAYOUT ITEM is the source of truth):
31457
- * 1. EXACT match on `component` covers the new scoped form
31458
- * (`scope.package.X`) and any legacy `.dash.js` that already
31459
- * set `config.id` to a scoped value.
31460
- * 2. If `component` is bare (no dots) AND we have a packageId hint
31461
- * on the layout item, build the scoped id and try that.
31462
- * 3. Bare-name fallback: scan the map for any key ending in
31463
- * `.${component}`. If exactly one matches, use it. If multiple
31464
- * match (the collision case), prefer the one matching the
31465
- * layout item's `packageId` / `_sourcePackage`; otherwise fall
31466
- * through to the first match (deterministic, but also logs a
31467
- * warning so callers can spot the ambiguity).
31468
- *
31469
- * Step (3) is the back-compat path for layouts authored before
31470
- * scoped registration landed. New layouts ALWAYS resolve via step (1).
31521
+ * The `widgetKey` is consulted ONLY when both above paths fail and
31522
+ * the key itself is already a scoped id; this preserves compat with
31523
+ * callers that pass a fully-qualified registration key.
31471
31524
  */
31472
- function resolveComponentKey(componentMap, component, data) {
31473
- if (!componentMap || !component) return null;
31474
- if (component in componentMap) return component;
31475
- if (typeof component !== "string") return null;
31476
- if (component.includes(".")) return null;
31477
- var packageId = (data === null || data === void 0 ? void 0 : data.packageId) || (data === null || data === void 0 ? void 0 : data._sourcePackage) || (data === null || data === void 0 ? void 0 : data.packageName) || null;
31478
- if (packageId) {
31479
- var scoped = makeScopedComponentId(packageId, component);
31480
- if (scoped in componentMap) return scoped;
31481
- }
31482
- var suffix = ".".concat(component);
31483
- var matches = Object.keys(componentMap).filter(function (k) {
31484
- return k.endsWith(suffix);
31485
- });
31486
- if (matches.length === 0) return null;
31487
- if (matches.length === 1) return matches[0];
31488
- if (packageId) {
31489
- var target = makeScopedComponentId(packageId, component);
31490
- if (matches.includes(target)) return target;
31491
- }
31492
- return matches[0];
31525
+ function canonicalScopedId(config, widgetKey) {
31526
+ var looksScoped = function looksScoped(s) {
31527
+ return typeof s === "string" && s.split(".").length === 3 && !s.includes("/");
31528
+ };
31529
+ if (looksScoped(config === null || config === void 0 ? void 0 : config.id)) return config.id;
31530
+ if (looksScoped(widgetKey)) return widgetKey;
31531
+ if (config !== null && config !== void 0 && config.scope && config !== null && config !== void 0 && config.packageName) {
31532
+ var _config$component, _config$component2;
31533
+ var componentName = config.name || ((_config$component = config.component) === null || _config$component === void 0 ? void 0 : _config$component.displayName) || ((_config$component2 = config.component) === null || _config$component2 === void 0 ? void 0 : _config$component2.name) || null;
31534
+ if (componentName) {
31535
+ return makeScopedComponentId("".concat(String(config.scope).replace(/^@/, ""), "/").concat(config.packageName), componentName);
31536
+ }
31537
+ }
31538
+ var dump = JSON.stringify({
31539
+ id: config === null || config === void 0 ? void 0 : config.id,
31540
+ scope: config === null || config === void 0 ? void 0 : config.scope,
31541
+ packageName: config === null || config === void 0 ? void 0 : config.packageName,
31542
+ name: config === null || config === void 0 ? void 0 : config.name,
31543
+ widgetKey: widgetKey
31544
+ });
31545
+ throw new Error("[ComponentManager] Cannot register widget \u2014 missing origin metadata. " + "Need either a scoped `id` (scope.package.Component) or " + "`scope` + `packageName` + `name`. Got: ".concat(dump));
31493
31546
  }
31494
-
31495
- var _componentMap = {};
31496
- var _containerComponent = null;
31497
- var _gridContainerComponent = null;
31498
31547
  var ComponentManager = {
31499
31548
  // _componentMap: {},
31500
31549
 
@@ -31529,39 +31578,50 @@ var ComponentManager = {
31529
31578
  return _componentMap;
31530
31579
  },
31531
31580
  /**
31532
- * Resolve a component name to its registered config — single source
31533
- * of truth for every render-path lookup. Routes through
31534
- * `resolveComponentKey` so legacy bare names (`"ProspectWorkspace"`)
31535
- * still find their registered scoped counterpart
31536
- * (`"ai-built.pipeline.ProspectWorkspace"`). Returns null when the
31537
- * widget isn't registered. Pass the layout item as `data` to use
31538
- * its `packageId` / `_sourcePackage` for disambiguation.
31581
+ * Resolve a component reference to its registered config. Strict
31582
+ * exact-match lookup against the registry. Layout items are
31583
+ * expected to carry the canonical scoped id
31584
+ * (`scope.package.Component`); `LayoutModel` migrates legacy bare
31585
+ * names to the scoped form on dashboard load.
31539
31586
  *
31540
- * @param {string} component
31541
- * @param {object} [data]
31587
+ * Returns null when the widget isn't registered — the renderer then
31588
+ * shows `WidgetNotFound`. There is no fallback.
31589
+ *
31590
+ * @param {string} component - The scoped widget id
31542
31591
  * @returns {object|null} the live registered config, or null
31543
31592
  */
31544
- resolve: function resolve(component, data) {
31593
+ resolve: function resolve(component) {
31545
31594
  var m = _componentMap;
31546
31595
  if (!m) return null;
31547
- var key = resolveComponentKey(m, component, data);
31596
+ var key = resolveComponentKey(m, component);
31548
31597
  return key ? m[key] || null : null;
31549
31598
  },
31550
31599
  /**
31551
- * The method for registering the widget into the Dashboard application
31552
- * This is a requirement for the widget to be included into the Dash
31600
+ * Register a widget config under its canonical scoped id.
31601
+ *
31602
+ * Every widget that enters the registry MUST have a scope.package
31603
+ * .Component id. The id is determined in this order:
31604
+ * 1. `config.id` already in scoped form → trust it.
31605
+ * 2. `config.scope` + `config.packageName` + `config.name` → derive.
31606
+ * 3. Otherwise → throw. Silent fallbacks here are how layouts end
31607
+ * up referencing widgets that were registered under the wrong
31608
+ * key, so we fail loudly at registration instead of producing
31609
+ * a corrupt registry.
31553
31610
  *
31554
- * @param {Object} widgetConfig the widget configuration script created by the developer
31555
- * @param {*} widgetKey the unique id for the widget
31611
+ * `widgetKey` is kept for backwards compatibility with callers that
31612
+ * pass a string key; it is consulted ONLY as a tiebreak when the
31613
+ * config is otherwise complete.
31614
+ *
31615
+ * @param {Object} widgetConfig the widget configuration script
31616
+ * @param {string} [widgetKey] legacy fallback key (informational only)
31617
+ * @throws if origin metadata is missing
31556
31618
  */
31557
31619
  registerWidget: function registerWidget(widgetConfig, widgetKey) {
31558
31620
  var tempComponentMap = this.componentMap();
31559
- // Handle both module exports (widgetConfig.default) and direct config objects
31560
31621
  var config = widgetConfig["default"] || widgetConfig;
31561
- // Register under a single canonical key: config.id (scoped widget ID) if
31562
- // available, otherwise the provided widgetKey. No aliases — one widget, one key.
31563
- var registrationKey = config.id || widgetKey;
31564
- tempComponentMap[registrationKey] = ComponentConfigModel(config);
31622
+ var id = canonicalScopedId(config, widgetKey);
31623
+ config.id = id;
31624
+ tempComponentMap[id] = ComponentConfigModel(config);
31565
31625
  this.setComponentMap(tempComponentMap);
31566
31626
  },
31567
31627
  /**
@@ -31615,15 +31675,14 @@ var ComponentManager = {
31615
31675
  * @returns {Widget} the Widget in the component map
31616
31676
  */
31617
31677
  getComponent: function getComponent(component) {
31618
- var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
31619
31678
  try {
31620
- // console.log("get component");
31621
31679
  if (component && this.componentMap()) {
31622
31680
  if (ComponentManager.isLayoutContainer(component) === false) {
31623
31681
  var m = this.componentMap();
31624
- // Resolve through the scoped/bare lookup pipeline so layouts
31625
- // authored under either format land at the same registry key.
31626
- var resolvedKey = resolveComponentKey(m, component, data);
31682
+ // Strict scoped-id lookup. If the layout item didn't carry
31683
+ // a scoped id, LayoutModel should have migrated it before
31684
+ // we get here.
31685
+ var resolvedKey = resolveComponentKey(m, component);
31627
31686
  var cmp = resolvedKey ? m[resolvedKey] : null;
31628
31687
  if (cmp !== null && cmp !== undefined) {
31629
31688
  cmp["componentName"] = resolvedKey;
@@ -31786,7 +31845,6 @@ var ComponentManager = {
31786
31845
  var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
31787
31846
  try {
31788
31847
  if (component) {
31789
- // console.log("config");
31790
31848
  var requiredFields = {
31791
31849
  type: {
31792
31850
  value: "text"
@@ -31801,35 +31859,19 @@ var ComponentManager = {
31801
31859
  value: ""
31802
31860
  }
31803
31861
  };
31804
-
31805
- // get the component configuration from the map
31806
31862
  var components = this.map();
31807
- var resolvedKey = resolveComponentKey(components, component, data);
31863
+ var resolvedKey = resolveComponentKey(components, component);
31808
31864
  if (resolvedKey && resolvedKey in components) {
31809
- // let c = deepCopy(components['component']);
31810
-
31811
- // we have to make sure that we remove the component if this is a context
31812
-
31813
31865
  var tempComponent = components[resolvedKey];
31814
31866
  delete tempComponent["component"];
31815
31867
  var c = JSON.parse(JSON.stringify(tempComponent));
31816
-
31817
- // Carry the canonical scoped id forward so callers (LayoutModel,
31818
- // ComponentManager.getComponent) can rewrite layout items'
31819
- // `component` to the scoped form on first load.
31820
31868
  c["component"] = resolvedKey;
31821
-
31822
- // if no userConfig key. let's add it for the next step
31823
31869
  if ("userConfig" in c === false) {
31824
31870
  c["userConfig"] = {};
31825
31871
  }
31826
-
31827
- // if (isLayout === false) {
31828
31872
  var userPrefs = {};
31829
- // now we can make sure the configuration is "complete"
31830
31873
  if ("userConfig" in c) {
31831
31874
  Object.keys(c["userConfig"]).forEach(function (key) {
31832
- // check the required fields!
31833
31875
  Object.keys(requiredFields).forEach(function (k) {
31834
31876
  if (k in c["userConfig"][key]) {
31835
31877
  if (k in c["userConfig"][key] === false) {
@@ -31837,16 +31879,21 @@ var ComponentManager = {
31837
31879
  }
31838
31880
  }
31839
31881
  });
31840
- // set the user preferences
31841
31882
  userPrefs[key] = ComponentManager.userPrefsForItem("userPrefs" in data ? data : c, key, c["userConfig"][key]);
31842
31883
  });
31843
31884
  }
31844
-
31845
- // set the user preferences here
31846
31885
  c["userPrefs"] = userPrefs;
31886
+
31887
+ // Identity fields (id/package/scope/...) are forwarded so
31888
+ // consumers can derive the package label without reading
31889
+ // the live registry directly. Without these, callers fall
31890
+ // back to `item.workspace` which is a category, not a
31891
+ // package, and produce labels like `@DashSamples-workspace`.
31847
31892
  return {
31893
+ id: resolvedKey,
31848
31894
  type: c["type"],
31849
31895
  name: c["name"],
31896
+ displayName: c["displayName"],
31850
31897
  workspace: c["workspace"],
31851
31898
  canHaveChildren: c["canHaveChildren"],
31852
31899
  userPrefs: c["userPrefs"],
@@ -31857,7 +31904,13 @@ var ComponentManager = {
31857
31904
  providers: "providers" in c ? c["providers"] : [],
31858
31905
  notifications: "notifications" in c ? c["notifications"] : [],
31859
31906
  scheduledTasks: "scheduledTasks" in c ? c["scheduledTasks"] : [],
31860
- icon: "icon" in c ? c["icon"] : null
31907
+ icon: "icon" in c ? c["icon"] : null,
31908
+ scope: c["scope"],
31909
+ packageName: c["packageName"],
31910
+ "package": c["package"],
31911
+ author: c["author"],
31912
+ version: c["version"],
31913
+ _sourcePackage: c["_sourcePackage"]
31861
31914
  };
31862
31915
  }
31863
31916
  return null;
@@ -55536,26 +55589,23 @@ var DashboardConfigModal = function DashboardConfigModal(_ref) {
55536
55589
  // footer so the same package label shows in every surface.
55537
55590
  var dependencies = useMemo(function () {
55538
55591
  var byPackage = new Map();
55539
- var stripTrailingComponent = function stripTrailingComponent(s) {
55540
- if (typeof s !== "string") return "";
55541
- var lastDot = s.lastIndexOf(".");
55542
- return lastDot > 0 ? s.slice(0, lastDot) : s;
55543
- };
55592
+ // Derive the @scope/package label from the layout item's scoped
55593
+ // component id. Layout items are always scoped post-v0.1.435
55594
+ // (LayoutModel migrates legacy bare names on load), so this is
55595
+ // the single source of truth — no config lookup, no workspace
55596
+ // fallback, no heuristics.
55544
55597
  var derivePackage = function derivePackage(item) {
55545
- // The layout item records the exact source package id when the
55546
- // widget was added. If present, trust it — no heuristics. This
55547
- // matches the publish flow's attribution, so the Dependencies
55548
- // tab and the Publish modal always agree.
55598
+ var scopedId = typeof (item === null || item === void 0 ? void 0 : item.component) === "string" ? item.component : "";
55599
+ var parts = scopedId.split(".");
55600
+ if (parts.length === 3) {
55601
+ var _parts = _slicedToArray(parts, 2),
55602
+ scope = _parts[0],
55603
+ pkg = _parts[1];
55604
+ if (scope && pkg) return "@".concat(scope, "/").concat(pkg);
55605
+ }
55606
+ // Defensive: an explicit packageId on the item still wins for
55607
+ // legacy items the migration couldn't auto-resolve.
55549
55608
  if (item !== null && item !== void 0 && item.packageId) return String(item.packageId);
55550
- var cfg = typeof getWidgetConfig === "function" ? getWidgetConfig(item.component) : null;
55551
- if (cfg !== null && cfg !== void 0 && cfg._sourcePackage) return String(cfg._sourcePackage);
55552
- var fromId = stripTrailingComponent((cfg === null || cfg === void 0 ? void 0 : cfg.id) || "");
55553
- if (fromId) return fromId;
55554
- if (cfg !== null && cfg !== void 0 && cfg["package"]) return String(cfg["package"]);
55555
- var ws = item === null || item === void 0 ? void 0 : item.workspace;
55556
- if (typeof ws === "string" && ws && ws !== "layout") {
55557
- return ws.startsWith("@") ? ws : "@".concat(ws);
55558
- }
55559
55609
  return "(unknown)";
55560
55610
  };
55561
55611