@trops/dash-core 0.1.432 → 0.1.434

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
@@ -18036,7 +18036,6 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
18036
18036
  padding: true,
18037
18037
  height: "h-full",
18038
18038
  children: filteredWidgets.map(function (widget) {
18039
- var _widget$providers;
18040
18039
  return /*#__PURE__*/jsx(MenuItem3, {
18041
18040
  onClick: function onClick() {
18042
18041
  return handleWidgetSelect(widget);
@@ -18056,15 +18055,22 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
18056
18055
  }), widget.description && /*#__PURE__*/jsx("div", {
18057
18056
  className: "text-xs opacity-50 truncate",
18058
18057
  children: widget.description
18059
- }), ((_widget$providers = widget.providers) === null || _widget$providers === void 0 ? void 0 : _widget$providers.length) > 0 && /*#__PURE__*/jsx("div", {
18060
- className: "flex flex-wrap gap-1 mt-0.5",
18061
- children: widget.providers.map(function (p) {
18062
- return /*#__PURE__*/jsx("span", {
18063
- className: "text-[10px] px-1.5 py-0.5 rounded bg-blue-500/20 text-blue-300",
18064
- children: p.type
18065
- }, p.type);
18066
- })
18067
- })]
18058
+ }), function () {
18059
+ // Same defensive null-safe iteration as WidgetSidebar:
18060
+ // a sparse `providers` array (null entries from a
18061
+ // malformed `.dash.js`) used to crash the chip render.
18062
+ var provs = getUserConfigurableProviders(widget.providers);
18063
+ if (provs.length === 0) return null;
18064
+ return /*#__PURE__*/jsx("div", {
18065
+ className: "flex flex-wrap gap-1 mt-0.5",
18066
+ children: provs.map(function (p) {
18067
+ return /*#__PURE__*/jsx("span", {
18068
+ className: "text-[10px] px-1.5 py-0.5 rounded bg-blue-500/20 text-blue-300",
18069
+ children: p.type
18070
+ }, p.type);
18071
+ })
18072
+ });
18073
+ }()]
18068
18074
  }), /*#__PURE__*/jsxs("div", {
18069
18075
  className: "flex items-center gap-1.5 flex-shrink-0",
18070
18076
  children: [installedPackageNames.has(widget.packageName) && /*#__PURE__*/jsx("span", {
@@ -26668,7 +26674,11 @@ function renderComponent(component, id) {
26668
26674
  // Check if widget exists before attempting render —
26669
26675
  // WidgetFactory.render() always returns a React element (truthy),
26670
26676
  // so the old ternary fallback could never fire.
26671
- if (!isWidgetResolvable(component)) {
26677
+ // Pass `params` (the layout item) so `packageId` /
26678
+ // `_sourcePackage` can disambiguate when a legacy layout
26679
+ // references a bare component name and multiple installed
26680
+ // packages register a widget with the same trailing name.
26681
+ if (!isWidgetResolvable(component, params)) {
26672
26682
  return /*#__PURE__*/jsx(WidgetNotFound, {
26673
26683
  component: component
26674
26684
  });
@@ -27473,20 +27483,25 @@ function addChildToLayoutItem(childComponent, layoutItem, workspace) {
27473
27483
  }
27474
27484
 
27475
27485
  /**
27476
- * Check if a widget component key is resolvable in ComponentManager
27486
+ * Check if a widget component key is resolvable in ComponentManager.
27487
+ * Routes through `ComponentManager.resolve` so a legacy bare component
27488
+ * key (e.g. `"ProspectWorkspace"`) finds its registered scoped form
27489
+ * (`"ai-built.pipeline.ProspectWorkspace"`). Without this routing the
27490
+ * function would return false for every legacy-layout widget after the
27491
+ * scoped-IDs migration, and the renderer would show `WidgetNotFound`
27492
+ * for working dashboards.
27493
+ *
27477
27494
  * @param {string} componentKey the component key to check
27495
+ * @param {object} [data] the layout item — used for `packageId`
27496
+ * disambiguation when multiple registered
27497
+ * widgets share the same bare name
27478
27498
  * @returns {boolean} true if the widget can be rendered
27479
27499
  */
27480
- function isWidgetResolvable(componentKey) {
27500
+ function isWidgetResolvable(componentKey, data) {
27481
27501
  // Layout containers are always resolvable (handled specially by WidgetFactory)
27482
27502
  if (ComponentManager.isLayoutContainer(componentKey)) return true;
27483
- var m = ComponentManager.componentMap();
27484
- if (!m) return false;
27485
- // Exact key match (scoped id)
27486
- if (m[componentKey] && typeof m[componentKey].component === "function") {
27487
- return true;
27488
- }
27489
- return false;
27503
+ var config = ComponentManager.resolve(componentKey, data);
27504
+ return !!(config && typeof config.component === "function");
27490
27505
  }
27491
27506
 
27492
27507
  // export {
@@ -31429,31 +31444,33 @@ function bareComponentName(idOrName) {
31429
31444
  return parts[parts.length - 1] || "";
31430
31445
  }
31431
31446
 
31432
- var _componentMap = {};
31433
-
31434
31447
  /**
31435
- * Resolve the registry key for a component lookup. Returns null if no
31448
+ * Resolve a component name to a registry key. Returns null if no
31436
31449
  * match exists.
31437
31450
  *
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).
31455
+ *
31438
31456
  * Lookup order (the LAYOUT ITEM is the source of truth):
31439
31457
  * 1. EXACT match on `component` — covers the new scoped form
31440
- * (`scope.package.X`) and any legacy `.dash.js` that already set
31441
- * `config.id` to a scoped value.
31458
+ * (`scope.package.X`) and any legacy `.dash.js` that already
31459
+ * set `config.id` to a scoped value.
31442
31460
  * 2. If `component` is bare (no dots) AND we have a packageId hint
31443
31461
  * on the layout item, build the scoped id and try that.
31444
31462
  * 3. Bare-name fallback: scan the map for any key ending in
31445
31463
  * `.${component}`. If exactly one matches, use it. If multiple
31446
- * match (the collision case), prefer the one matching the layout
31447
- * item's `packageId` / `_sourcePackage`; otherwise fall through
31448
- * to the first match (deterministic, but also logs a warning so
31449
- * callers can spot the ambiguity).
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).
31450
31468
  *
31451
- * Step (3) is the back-compat path for layouts authored before scoped
31452
- * registration landed. New layouts ALWAYS resolve via step (1) — the
31453
- * `component` field is already scoped.
31469
+ * Step (3) is the back-compat path for layouts authored before
31470
+ * scoped registration landed. New layouts ALWAYS resolve via step (1).
31454
31471
  */
31455
31472
  function resolveComponentKey(componentMap, component, data) {
31456
- if (!component) return null;
31473
+ if (!componentMap || !component) return null;
31457
31474
  if (component in componentMap) return component;
31458
31475
  if (typeof component !== "string") return null;
31459
31476
  if (component.includes(".")) return null;
@@ -31474,6 +31491,8 @@ function resolveComponentKey(componentMap, component, data) {
31474
31491
  }
31475
31492
  return matches[0];
31476
31493
  }
31494
+
31495
+ var _componentMap = {};
31477
31496
  var _containerComponent = null;
31478
31497
  var _gridContainerComponent = null;
31479
31498
  var ComponentManager = {
@@ -31509,6 +31528,25 @@ var ComponentManager = {
31509
31528
  componentMap: function componentMap() {
31510
31529
  return _componentMap;
31511
31530
  },
31531
+ /**
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.
31539
+ *
31540
+ * @param {string} component
31541
+ * @param {object} [data]
31542
+ * @returns {object|null} the live registered config, or null
31543
+ */
31544
+ resolve: function resolve(component, data) {
31545
+ var m = _componentMap;
31546
+ if (!m) return null;
31547
+ var key = resolveComponentKey(m, component, data);
31548
+ return key ? m[key] || null : null;
31549
+ },
31512
31550
  /**
31513
31551
  * The method for registering the widget into the Dashboard application
31514
31552
  * This is a requirement for the widget to be included into the Dash
@@ -51415,14 +51453,17 @@ var NotificationsSection = function NotificationsSection(_ref) {
51415
51453
  });
51416
51454
  }, []);
51417
51455
 
51418
- // Collect all widget instances with notifications from workspaces
51456
+ // Collect all widget instances with notifications from workspaces.
51457
+ // Route through `ComponentManager.resolve` so a legacy layout
51458
+ // referencing a bare component name still finds its registered
51459
+ // scoped form (post-v0.1.432). Direct `componentMap[item.component]`
51460
+ // returns undefined for bare names after the migration.
51419
51461
  var widgetInstances = [];
51420
- var componentMap = ComponentManager.componentMap() || {};
51421
51462
  workspaces.forEach(function (ws) {
51422
51463
  var items = flattenLayout(ws.layout);
51423
51464
  items.forEach(function (item) {
51424
51465
  var _config$notifications;
51425
- var config = componentMap[item.component];
51466
+ var config = ComponentManager.resolve(item.component, item);
51426
51467
  if ((config === null || config === void 0 || (_config$notifications = config.notifications) === null || _config$notifications === void 0 ? void 0 : _config$notifications.length) > 0) {
51427
51468
  var _item$userPrefs;
51428
51469
  widgetInstances.push({
@@ -53639,7 +53680,13 @@ var DraggableWidgetItem = function DraggableWidgetItem(_ref) {
53639
53680
  _useDrag2 = _slicedToArray(_useDrag, 2),
53640
53681
  isDragging = _useDrag2[0].isDragging,
53641
53682
  drag = _useDrag2[1];
53642
- var providerTypes = (widget.providers || []).map(function (p) {
53683
+
53684
+ // Route through getUserConfigurableProviders — drops the `api`
53685
+ // class AND null/undefined entries that occasionally appear in
53686
+ // sparse `widget.providers` arrays. Without this, a single null
53687
+ // slot crashes the whole sidebar with `Cannot read properties of
53688
+ // null (reading 'type')`.
53689
+ var providerTypes = getUserConfigurableProviders(widget.providers).map(function (p) {
53643
53690
  return p.type;
53644
53691
  });
53645
53692
  var eventCount = (widget.events || []).length;
@@ -54213,12 +54260,18 @@ var WidgetSidebar = function WidgetSidebar(_ref4) {
54213
54260
  }))).sort();
54214
54261
  }, [allWidgets]);
54215
54262
 
54216
- // Derive unique provider types for dropdown
54263
+ // Derive unique provider types for the filter dropdown. Route
54264
+ // through getUserConfigurableProviders so a single null entry in
54265
+ // any widget's `providers` array doesn't crash the whole sidebar
54266
+ // (it filters non-objects AND drops the `api` provider class that
54267
+ // isn't user-configurable). Observed prod crash:
54268
+ // `TypeError: Cannot read properties of null (reading 'type')` →
54269
+ // unmounted WidgetSidebar via React error boundary.
54217
54270
  var uniqueProviders = useMemo(function () {
54218
54271
  var types = new Set();
54219
54272
  allWidgets.forEach(function (_ref7) {
54220
54273
  var widget = _ref7.widget;
54221
- return (widget.providers || []).forEach(function (p) {
54274
+ return getUserConfigurableProviders(widget === null || widget === void 0 ? void 0 : widget.providers).forEach(function (p) {
54222
54275
  return types.add(p.type);
54223
54276
  });
54224
54277
  });
@@ -54240,12 +54293,13 @@ var WidgetSidebar = function WidgetSidebar(_ref4) {
54240
54293
  if (filterAuthor !== "all") {
54241
54294
  if ((widget["package"] || widget.author || "Other") !== filterAuthor) return false;
54242
54295
  }
54243
- // Provider filter
54296
+ // Provider filter — same null-safety as `uniqueProviders` above.
54244
54297
  if (filterProvider !== "all") {
54298
+ var configurable = getUserConfigurableProviders(widget === null || widget === void 0 ? void 0 : widget.providers);
54245
54299
  if (filterProvider === "none") {
54246
- if (widget.providers && widget.providers.length > 0) return false;
54300
+ if (configurable.length > 0) return false;
54247
54301
  } else {
54248
- if (!widget.providers || !widget.providers.some(function (p) {
54302
+ if (!configurable.some(function (p) {
54249
54303
  return p.type === filterProvider;
54250
54304
  })) return false;
54251
54305
  }
@@ -57823,9 +57877,13 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
57823
57877
  return getUnresolvedProviders({
57824
57878
  workspace: workspaceSelected,
57825
57879
  appProviders: (appContext === null || appContext === void 0 ? void 0 : appContext.providers) || {},
57880
+ // Use ComponentManager.config so a legacy layout referencing
57881
+ // a bare component name (`"PipelineKanban"`) still resolves
57882
+ // to its scoped registration. Direct `componentMap[name]`
57883
+ // returns undefined after the v0.1.432 scoped-IDs migration.
57826
57884
  getWidgetRequirements: function getWidgetRequirements(name) {
57827
- var _ComponentManager$com;
57828
- return name && ((_ComponentManager$com = ComponentManager.componentMap()[name]) === null || _ComponentManager$com === void 0 ? void 0 : _ComponentManager$com.providers) || [];
57885
+ var _ComponentManager$con;
57886
+ return name && ((_ComponentManager$con = ComponentManager.config(name)) === null || _ComponentManager$con === void 0 ? void 0 : _ComponentManager$con.providers) || [];
57829
57887
  }
57830
57888
  });
57831
57889
  }, [workspaceSelected, appContext === null || appContext === void 0 ? void 0 : appContext.providers]);
@@ -58827,13 +58885,18 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
58827
58885
  isOpen: isConfigModalOpen,
58828
58886
  setIsOpen: setIsConfigModalOpen,
58829
58887
  workspace: workspaceSelected,
58830
- appProviders: (appContext === null || appContext === void 0 ? void 0 : appContext.providers) || {},
58888
+ appProviders: (appContext === null || appContext === void 0 ? void 0 : appContext.providers) || {}
58889
+ // Use ComponentManager.config so legacy bare component
58890
+ // refs in `workspaceSelected.layout` still resolve to
58891
+ // their registered scoped form (post-v0.1.432). Direct
58892
+ // `componentMap[name]` returns undefined for those.
58893
+ ,
58831
58894
  getWidgetRequirements: function getWidgetRequirements(name) {
58832
- var _ComponentManager$com2;
58833
- return name && ((_ComponentManager$com2 = ComponentManager.componentMap()[name]) === null || _ComponentManager$com2 === void 0 ? void 0 : _ComponentManager$com2.providers) || [];
58895
+ var _ComponentManager$con2;
58896
+ return name && ((_ComponentManager$con2 = ComponentManager.config(name)) === null || _ComponentManager$con2 === void 0 ? void 0 : _ComponentManager$con2.providers) || [];
58834
58897
  },
58835
58898
  getWidgetConfig: function getWidgetConfig(name) {
58836
- return name && ComponentManager.componentMap()[name] || null;
58899
+ return name && ComponentManager.config(name) || null;
58837
58900
  },
58838
58901
  onSaveBindings: handleBulkProviderBindings,
58839
58902
  onSaveListeners: handleBulkListenerBindings,