@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.js CHANGED
@@ -18054,7 +18054,6 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
18054
18054
  padding: true,
18055
18055
  height: "h-full",
18056
18056
  children: filteredWidgets.map(function (widget) {
18057
- var _widget$providers;
18058
18057
  return /*#__PURE__*/jsxRuntime.jsx(DashReact.MenuItem3, {
18059
18058
  onClick: function onClick() {
18060
18059
  return handleWidgetSelect(widget);
@@ -18074,15 +18073,22 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
18074
18073
  }), widget.description && /*#__PURE__*/jsxRuntime.jsx("div", {
18075
18074
  className: "text-xs opacity-50 truncate",
18076
18075
  children: widget.description
18077
- }), ((_widget$providers = widget.providers) === null || _widget$providers === void 0 ? void 0 : _widget$providers.length) > 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
18078
- className: "flex flex-wrap gap-1 mt-0.5",
18079
- children: widget.providers.map(function (p) {
18080
- return /*#__PURE__*/jsxRuntime.jsx("span", {
18081
- className: "text-[10px] px-1.5 py-0.5 rounded bg-blue-500/20 text-blue-300",
18082
- children: p.type
18083
- }, p.type);
18084
- })
18085
- })]
18076
+ }), function () {
18077
+ // Same defensive null-safe iteration as WidgetSidebar:
18078
+ // a sparse `providers` array (null entries from a
18079
+ // malformed `.dash.js`) used to crash the chip render.
18080
+ var provs = getUserConfigurableProviders(widget.providers);
18081
+ if (provs.length === 0) return null;
18082
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
18083
+ className: "flex flex-wrap gap-1 mt-0.5",
18084
+ children: provs.map(function (p) {
18085
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
18086
+ className: "text-[10px] px-1.5 py-0.5 rounded bg-blue-500/20 text-blue-300",
18087
+ children: p.type
18088
+ }, p.type);
18089
+ })
18090
+ });
18091
+ }()]
18086
18092
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
18087
18093
  className: "flex items-center gap-1.5 flex-shrink-0",
18088
18094
  children: [installedPackageNames.has(widget.packageName) && /*#__PURE__*/jsxRuntime.jsx("span", {
@@ -26686,7 +26692,11 @@ function renderComponent(component, id) {
26686
26692
  // Check if widget exists before attempting render —
26687
26693
  // WidgetFactory.render() always returns a React element (truthy),
26688
26694
  // so the old ternary fallback could never fire.
26689
- if (!isWidgetResolvable(component)) {
26695
+ // Pass `params` (the layout item) so `packageId` /
26696
+ // `_sourcePackage` can disambiguate when a legacy layout
26697
+ // references a bare component name and multiple installed
26698
+ // packages register a widget with the same trailing name.
26699
+ if (!isWidgetResolvable(component, params)) {
26690
26700
  return /*#__PURE__*/jsxRuntime.jsx(WidgetNotFound, {
26691
26701
  component: component
26692
26702
  });
@@ -27491,20 +27501,25 @@ function addChildToLayoutItem(childComponent, layoutItem, workspace) {
27491
27501
  }
27492
27502
 
27493
27503
  /**
27494
- * Check if a widget component key is resolvable in ComponentManager
27504
+ * Check if a widget component key is resolvable in ComponentManager.
27505
+ * Routes through `ComponentManager.resolve` so a legacy bare component
27506
+ * key (e.g. `"ProspectWorkspace"`) finds its registered scoped form
27507
+ * (`"ai-built.pipeline.ProspectWorkspace"`). Without this routing the
27508
+ * function would return false for every legacy-layout widget after the
27509
+ * scoped-IDs migration, and the renderer would show `WidgetNotFound`
27510
+ * for working dashboards.
27511
+ *
27495
27512
  * @param {string} componentKey the component key to check
27513
+ * @param {object} [data] the layout item — used for `packageId`
27514
+ * disambiguation when multiple registered
27515
+ * widgets share the same bare name
27496
27516
  * @returns {boolean} true if the widget can be rendered
27497
27517
  */
27498
- function isWidgetResolvable(componentKey) {
27518
+ function isWidgetResolvable(componentKey, data) {
27499
27519
  // Layout containers are always resolvable (handled specially by WidgetFactory)
27500
27520
  if (ComponentManager.isLayoutContainer(componentKey)) return true;
27501
- var m = ComponentManager.componentMap();
27502
- if (!m) return false;
27503
- // Exact key match (scoped id)
27504
- if (m[componentKey] && typeof m[componentKey].component === "function") {
27505
- return true;
27506
- }
27507
- return false;
27521
+ var config = ComponentManager.resolve(componentKey, data);
27522
+ return !!(config && typeof config.component === "function");
27508
27523
  }
27509
27524
 
27510
27525
  // export {
@@ -31447,31 +31462,33 @@ function bareComponentName(idOrName) {
31447
31462
  return parts[parts.length - 1] || "";
31448
31463
  }
31449
31464
 
31450
- var _componentMap = {};
31451
-
31452
31465
  /**
31453
- * Resolve the registry key for a component lookup. Returns null if no
31466
+ * Resolve a component name to a registry key. Returns null if no
31454
31467
  * match exists.
31455
31468
  *
31469
+ * Pure function — depends only on the passed-in `componentMap` and
31470
+ * `data`. Lives outside ComponentManager so it can be tested without
31471
+ * pulling in the full Component/Layout import chain (and so other
31472
+ * call sites can route through it without circular deps).
31473
+ *
31456
31474
  * Lookup order (the LAYOUT ITEM is the source of truth):
31457
31475
  * 1. EXACT match on `component` — covers the new scoped form
31458
- * (`scope.package.X`) and any legacy `.dash.js` that already set
31459
- * `config.id` to a scoped value.
31476
+ * (`scope.package.X`) and any legacy `.dash.js` that already
31477
+ * set `config.id` to a scoped value.
31460
31478
  * 2. If `component` is bare (no dots) AND we have a packageId hint
31461
31479
  * on the layout item, build the scoped id and try that.
31462
31480
  * 3. Bare-name fallback: scan the map for any key ending in
31463
31481
  * `.${component}`. If exactly one matches, use it. If multiple
31464
- * match (the collision case), prefer the one matching the layout
31465
- * item's `packageId` / `_sourcePackage`; otherwise fall through
31466
- * to the first match (deterministic, but also logs a warning so
31467
- * callers can spot the ambiguity).
31482
+ * match (the collision case), prefer the one matching the
31483
+ * layout item's `packageId` / `_sourcePackage`; otherwise fall
31484
+ * through to the first match (deterministic, but also logs a
31485
+ * warning so callers can spot the ambiguity).
31468
31486
  *
31469
- * Step (3) is the back-compat path for layouts authored before scoped
31470
- * registration landed. New layouts ALWAYS resolve via step (1) — the
31471
- * `component` field is already scoped.
31487
+ * Step (3) is the back-compat path for layouts authored before
31488
+ * scoped registration landed. New layouts ALWAYS resolve via step (1).
31472
31489
  */
31473
31490
  function resolveComponentKey(componentMap, component, data) {
31474
- if (!component) return null;
31491
+ if (!componentMap || !component) return null;
31475
31492
  if (component in componentMap) return component;
31476
31493
  if (typeof component !== "string") return null;
31477
31494
  if (component.includes(".")) return null;
@@ -31492,6 +31509,8 @@ function resolveComponentKey(componentMap, component, data) {
31492
31509
  }
31493
31510
  return matches[0];
31494
31511
  }
31512
+
31513
+ var _componentMap = {};
31495
31514
  var _containerComponent = null;
31496
31515
  var _gridContainerComponent = null;
31497
31516
  var ComponentManager = {
@@ -31527,6 +31546,25 @@ var ComponentManager = {
31527
31546
  componentMap: function componentMap() {
31528
31547
  return _componentMap;
31529
31548
  },
31549
+ /**
31550
+ * Resolve a component name to its registered config — single source
31551
+ * of truth for every render-path lookup. Routes through
31552
+ * `resolveComponentKey` so legacy bare names (`"ProspectWorkspace"`)
31553
+ * still find their registered scoped counterpart
31554
+ * (`"ai-built.pipeline.ProspectWorkspace"`). Returns null when the
31555
+ * widget isn't registered. Pass the layout item as `data` to use
31556
+ * its `packageId` / `_sourcePackage` for disambiguation.
31557
+ *
31558
+ * @param {string} component
31559
+ * @param {object} [data]
31560
+ * @returns {object|null} the live registered config, or null
31561
+ */
31562
+ resolve: function resolve(component, data) {
31563
+ var m = _componentMap;
31564
+ if (!m) return null;
31565
+ var key = resolveComponentKey(m, component, data);
31566
+ return key ? m[key] || null : null;
31567
+ },
31530
31568
  /**
31531
31569
  * The method for registering the widget into the Dashboard application
31532
31570
  * This is a requirement for the widget to be included into the Dash
@@ -51433,14 +51471,17 @@ var NotificationsSection = function NotificationsSection(_ref) {
51433
51471
  });
51434
51472
  }, []);
51435
51473
 
51436
- // Collect all widget instances with notifications from workspaces
51474
+ // Collect all widget instances with notifications from workspaces.
51475
+ // Route through `ComponentManager.resolve` so a legacy layout
51476
+ // referencing a bare component name still finds its registered
51477
+ // scoped form (post-v0.1.432). Direct `componentMap[item.component]`
51478
+ // returns undefined for bare names after the migration.
51437
51479
  var widgetInstances = [];
51438
- var componentMap = ComponentManager.componentMap() || {};
51439
51480
  workspaces.forEach(function (ws) {
51440
51481
  var items = flattenLayout(ws.layout);
51441
51482
  items.forEach(function (item) {
51442
51483
  var _config$notifications;
51443
- var config = componentMap[item.component];
51484
+ var config = ComponentManager.resolve(item.component, item);
51444
51485
  if ((config === null || config === void 0 || (_config$notifications = config.notifications) === null || _config$notifications === void 0 ? void 0 : _config$notifications.length) > 0) {
51445
51486
  var _item$userPrefs;
51446
51487
  widgetInstances.push({
@@ -53657,7 +53698,13 @@ var DraggableWidgetItem = function DraggableWidgetItem(_ref) {
53657
53698
  _useDrag2 = _slicedToArray(_useDrag, 2),
53658
53699
  isDragging = _useDrag2[0].isDragging,
53659
53700
  drag = _useDrag2[1];
53660
- var providerTypes = (widget.providers || []).map(function (p) {
53701
+
53702
+ // Route through getUserConfigurableProviders — drops the `api`
53703
+ // class AND null/undefined entries that occasionally appear in
53704
+ // sparse `widget.providers` arrays. Without this, a single null
53705
+ // slot crashes the whole sidebar with `Cannot read properties of
53706
+ // null (reading 'type')`.
53707
+ var providerTypes = getUserConfigurableProviders(widget.providers).map(function (p) {
53661
53708
  return p.type;
53662
53709
  });
53663
53710
  var eventCount = (widget.events || []).length;
@@ -54231,12 +54278,18 @@ var WidgetSidebar = function WidgetSidebar(_ref4) {
54231
54278
  }))).sort();
54232
54279
  }, [allWidgets]);
54233
54280
 
54234
- // Derive unique provider types for dropdown
54281
+ // Derive unique provider types for the filter dropdown. Route
54282
+ // through getUserConfigurableProviders so a single null entry in
54283
+ // any widget's `providers` array doesn't crash the whole sidebar
54284
+ // (it filters non-objects AND drops the `api` provider class that
54285
+ // isn't user-configurable). Observed prod crash:
54286
+ // `TypeError: Cannot read properties of null (reading 'type')` →
54287
+ // unmounted WidgetSidebar via React error boundary.
54235
54288
  var uniqueProviders = React.useMemo(function () {
54236
54289
  var types = new Set();
54237
54290
  allWidgets.forEach(function (_ref7) {
54238
54291
  var widget = _ref7.widget;
54239
- return (widget.providers || []).forEach(function (p) {
54292
+ return getUserConfigurableProviders(widget === null || widget === void 0 ? void 0 : widget.providers).forEach(function (p) {
54240
54293
  return types.add(p.type);
54241
54294
  });
54242
54295
  });
@@ -54258,12 +54311,13 @@ var WidgetSidebar = function WidgetSidebar(_ref4) {
54258
54311
  if (filterAuthor !== "all") {
54259
54312
  if ((widget["package"] || widget.author || "Other") !== filterAuthor) return false;
54260
54313
  }
54261
- // Provider filter
54314
+ // Provider filter — same null-safety as `uniqueProviders` above.
54262
54315
  if (filterProvider !== "all") {
54316
+ var configurable = getUserConfigurableProviders(widget === null || widget === void 0 ? void 0 : widget.providers);
54263
54317
  if (filterProvider === "none") {
54264
- if (widget.providers && widget.providers.length > 0) return false;
54318
+ if (configurable.length > 0) return false;
54265
54319
  } else {
54266
- if (!widget.providers || !widget.providers.some(function (p) {
54320
+ if (!configurable.some(function (p) {
54267
54321
  return p.type === filterProvider;
54268
54322
  })) return false;
54269
54323
  }
@@ -57841,9 +57895,13 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
57841
57895
  return getUnresolvedProviders({
57842
57896
  workspace: workspaceSelected,
57843
57897
  appProviders: (appContext === null || appContext === void 0 ? void 0 : appContext.providers) || {},
57898
+ // Use ComponentManager.config so a legacy layout referencing
57899
+ // a bare component name (`"PipelineKanban"`) still resolves
57900
+ // to its scoped registration. Direct `componentMap[name]`
57901
+ // returns undefined after the v0.1.432 scoped-IDs migration.
57844
57902
  getWidgetRequirements: function getWidgetRequirements(name) {
57845
- var _ComponentManager$com;
57846
- return name && ((_ComponentManager$com = ComponentManager.componentMap()[name]) === null || _ComponentManager$com === void 0 ? void 0 : _ComponentManager$com.providers) || [];
57903
+ var _ComponentManager$con;
57904
+ return name && ((_ComponentManager$con = ComponentManager.config(name)) === null || _ComponentManager$con === void 0 ? void 0 : _ComponentManager$con.providers) || [];
57847
57905
  }
57848
57906
  });
57849
57907
  }, [workspaceSelected, appContext === null || appContext === void 0 ? void 0 : appContext.providers]);
@@ -58845,13 +58903,18 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
58845
58903
  isOpen: isConfigModalOpen,
58846
58904
  setIsOpen: setIsConfigModalOpen,
58847
58905
  workspace: workspaceSelected,
58848
- appProviders: (appContext === null || appContext === void 0 ? void 0 : appContext.providers) || {},
58906
+ appProviders: (appContext === null || appContext === void 0 ? void 0 : appContext.providers) || {}
58907
+ // Use ComponentManager.config so legacy bare component
58908
+ // refs in `workspaceSelected.layout` still resolve to
58909
+ // their registered scoped form (post-v0.1.432). Direct
58910
+ // `componentMap[name]` returns undefined for those.
58911
+ ,
58849
58912
  getWidgetRequirements: function getWidgetRequirements(name) {
58850
- var _ComponentManager$com2;
58851
- return name && ((_ComponentManager$com2 = ComponentManager.componentMap()[name]) === null || _ComponentManager$com2 === void 0 ? void 0 : _ComponentManager$com2.providers) || [];
58913
+ var _ComponentManager$con2;
58914
+ return name && ((_ComponentManager$con2 = ComponentManager.config(name)) === null || _ComponentManager$con2 === void 0 ? void 0 : _ComponentManager$con2.providers) || [];
58852
58915
  },
58853
58916
  getWidgetConfig: function getWidgetConfig(name) {
58854
- return name && ComponentManager.componentMap()[name] || null;
58917
+ return name && ComponentManager.config(name) || null;
58855
58918
  },
58856
58919
  onSaveBindings: handleBulkProviderBindings,
58857
58920
  onSaveListeners: handleBulkListenerBindings,