@trops/dash-core 0.1.451 → 0.1.453

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
@@ -25461,6 +25461,7 @@ var WidgetErrorBoundary = /*#__PURE__*/function (_Component) {
25461
25461
  }, {
25462
25462
  key: "render",
25463
25463
  value: function render() {
25464
+ var _this2 = this;
25464
25465
  if (this.state.hasError) {
25465
25466
  var _this$state$error;
25466
25467
  var widgetName = this.props.widgetName;
@@ -25468,33 +25469,64 @@ var WidgetErrorBoundary = /*#__PURE__*/function (_Component) {
25468
25469
 
25469
25470
  // Check if it's a WidgetContext error
25470
25471
  var isContextError = errorMessage.includes("Widget ID not found in Context") || errorMessage.includes("WidgetContext");
25472
+
25473
+ // AI-built widgets live under @ai-built/* — they get an "Open
25474
+ // in AI Builder" recovery button that dispatches the existing
25475
+ // dash:edit-widget-with-ai event (dash-electron's Dash.js
25476
+ // listens for it and reopens the failing widget in remix mode).
25477
+ var isAiBuilt = typeof widgetName === "string" && /(^|[./])ai-built\b/i.test(widgetName);
25478
+ var openInBuilder = function openInBuilder() {
25479
+ try {
25480
+ window.dispatchEvent(new CustomEvent("dash:edit-widget-with-ai", {
25481
+ detail: {
25482
+ widgetComponentName: widgetName
25483
+ }
25484
+ }));
25485
+ } catch (err) {
25486
+ }
25487
+ };
25471
25488
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
25472
- className: "flex flex-col h-full w-full bg-red-900 border-2 border-red-600 rounded p-4 text-red-100",
25489
+ className: "flex flex-col h-full w-full bg-amber-950 border border-amber-700 rounded p-4 text-amber-100",
25473
25490
  children: [/*#__PURE__*/jsxRuntime.jsx("div", {
25474
- className: "text-xl font-bold mb-2",
25475
- children: "\u26A0\uFE0F Widget Error"
25476
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
25477
- className: "text-sm mb-3",
25478
- children: [/*#__PURE__*/jsxRuntime.jsx("strong", {
25479
- children: "Widget:"
25480
- }), " ", widgetName]
25491
+ className: "text-base font-semibold mb-2 text-amber-200",
25492
+ children: "Widget couldn't render"
25481
25493
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
25482
- className: "text-sm mb-3",
25483
- children: [/*#__PURE__*/jsxRuntime.jsx("strong", {
25484
- children: "Error:"
25485
- }), " ", errorMessage]
25494
+ className: "text-xs mb-2 break-words",
25495
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
25496
+ className: "text-amber-300",
25497
+ children: widgetName
25498
+ }), " threw", " ", /*#__PURE__*/jsxRuntime.jsx("span", {
25499
+ className: "font-mono",
25500
+ children: errorMessage
25501
+ })]
25486
25502
  }), isContextError && /*#__PURE__*/jsxRuntime.jsxs("div", {
25487
- className: "text-sm bg-red-800 border border-red-700 rounded p-3 mt-2",
25503
+ className: "text-xs bg-amber-900 border border-amber-700 rounded p-2 mt-2 mb-2",
25488
25504
  children: [/*#__PURE__*/jsxRuntime.jsx("strong", {
25489
25505
  children: "Fix:"
25490
25506
  }), " This widget uses ", /*#__PURE__*/jsxRuntime.jsx("code", {
25491
25507
  children: "WidgetContext"
25492
25508
  }), " ", "but is missing the ", /*#__PURE__*/jsxRuntime.jsx("code", {
25493
25509
  children: "<Widget>"
25494
- }), " wrapper.", /*#__PURE__*/jsxRuntime.jsx("br", {}), /*#__PURE__*/jsxRuntime.jsx("br", {}), "Add the wrapper in your widget component:", /*#__PURE__*/jsxRuntime.jsx("pre", {
25510
+ }), " wrapper.", /*#__PURE__*/jsxRuntime.jsx("br", {}), "Add the wrapper in your widget component:", /*#__PURE__*/jsxRuntime.jsx("pre", {
25495
25511
  className: "bg-gray-900 p-2 rounded mt-2 text-xs overflow-auto",
25496
25512
  children: "import { Widget } from \"@trops/dash-react\";\n\nexport const ".concat(widgetName, " = (props) => {\n return (\n <Widget {...props}>\n {/* Your widget content */}\n </Widget>\n );\n};")
25497
25513
  })]
25514
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
25515
+ className: "flex items-center gap-2 mt-2",
25516
+ children: [/*#__PURE__*/jsxRuntime.jsx("button", {
25517
+ onClick: function onClick() {
25518
+ return _this2.setState({
25519
+ hasError: false,
25520
+ error: null
25521
+ });
25522
+ },
25523
+ className: "px-3 py-1 rounded text-xs bg-amber-700 hover:bg-amber-600 text-amber-100 transition-colors",
25524
+ children: "Retry"
25525
+ }), isAiBuilt && /*#__PURE__*/jsxRuntime.jsx("button", {
25526
+ onClick: openInBuilder,
25527
+ className: "px-3 py-1 rounded text-xs bg-indigo-600 hover:bg-indigo-500 text-white transition-colors",
25528
+ children: "Open in AI Builder"
25529
+ })]
25498
25530
  })]
25499
25531
  });
25500
25532
  }
@@ -45820,7 +45852,9 @@ var getIconForServer = function getIconForServer(server) {
45820
45852
  */
45821
45853
  var McpCatalogDetail = function McpCatalogDetail(_ref) {
45822
45854
  var onSave = _ref.onSave,
45823
- onCancel = _ref.onCancel;
45855
+ onCancel = _ref.onCancel,
45856
+ _ref$initialSelectedI = _ref.initialSelectedId,
45857
+ initialSelectedId = _ref$initialSelectedI === void 0 ? null : _ref$initialSelectedI;
45824
45858
  var appContext = React.useContext(AppContext);
45825
45859
  var dashApi = appContext === null || appContext === void 0 ? void 0 : appContext.dashApi;
45826
45860
  var _useState = React.useState([]),
@@ -45957,6 +45991,22 @@ var McpCatalogDetail = function McpCatalogDetail(_ref) {
45957
45991
  // eslint-disable-next-line react-hooks/exhaustive-deps
45958
45992
  }, [dashApi]);
45959
45993
 
45994
+ // Pre-select a catalog entry when initialSelectedId is provided
45995
+ // (used by the cross-modal "Add new <type>" CTA from the Widget
45996
+ // Builder). Fires once the catalog finishes loading; if no entry
45997
+ // matches the id (e.g. type isn't in the catalog), silently no-ops
45998
+ // and the user lands on the catalog grid to pick manually.
45999
+ React.useEffect(function () {
46000
+ if (!initialSelectedId || selectedServer || catalog.length === 0) return;
46001
+ var match = catalog.find(function (s) {
46002
+ return s && s.id === initialSelectedId;
46003
+ });
46004
+ if (match) {
46005
+ setSelectedServer(match);
46006
+ }
46007
+ // eslint-disable-next-line react-hooks/exhaustive-deps
46008
+ }, [catalog, initialSelectedId]);
46009
+
45960
46010
  // Filter catalog by search, then sort alphabetically by display name.
45961
46011
  // Built-in and known-external entries are interleaved alphabetically —
45962
46012
  // the per-card "external" badge keeps the source obvious without
@@ -47030,7 +47080,11 @@ var ProvidersSection = function ProvidersSection(_ref) {
47030
47080
  _ref$createRequested = _ref.createRequested,
47031
47081
  createRequested = _ref$createRequested === void 0 ? false : _ref$createRequested,
47032
47082
  _ref$onCreateAcknowle = _ref.onCreateAcknowledged,
47033
- onCreateAcknowledged = _ref$onCreateAcknowle === void 0 ? null : _ref$onCreateAcknowle;
47083
+ onCreateAcknowledged = _ref$onCreateAcknowle === void 0 ? null : _ref$onCreateAcknowle,
47084
+ _ref$initialProviderT = _ref.initialProviderType,
47085
+ initialProviderType = _ref$initialProviderT === void 0 ? null : _ref$initialProviderT,
47086
+ _ref$initialProviderC = _ref.initialProviderClass,
47087
+ initialProviderClass = _ref$initialProviderC === void 0 ? null : _ref$initialProviderC;
47034
47088
  var appContext = React.useContext(AppContext);
47035
47089
  var providers = (appContext === null || appContext === void 0 ? void 0 : appContext.providers) || {};
47036
47090
  var refreshProviders = appContext === null || appContext === void 0 ? void 0 : appContext.refreshProviders;
@@ -47366,14 +47420,29 @@ var ProvidersSection = function ProvidersSection(_ref) {
47366
47420
  });
47367
47421
  }
47368
47422
 
47369
- // Respond to external create trigger from header
47423
+ // Respond to external create trigger from header (or from the
47424
+ // cross-modal "Add new <type>" event dispatched by the Widget
47425
+ // Builder, with optional initialProviderType/initialProviderClass
47426
+ // for type pre-fill / catalog pre-select).
47370
47427
  var prevCreateRequested = React.useRef(false);
47371
47428
  React.useEffect(function () {
47372
47429
  if (createRequested && !prevCreateRequested.current) {
47373
47430
  resetForm();
47374
47431
  setSelectedName(null);
47375
- setIsAddingMcp(false);
47376
- setIsCreating(true);
47432
+ if (initialProviderClass === "mcp") {
47433
+ // MCP class: open the catalog detail. Pre-select happens in
47434
+ // McpCatalogDetail via the initialSelectedId prop passed below.
47435
+ setIsCreating(false);
47436
+ setIsAddingMcp(true);
47437
+ } else {
47438
+ // Credential class (default): open the credential create form
47439
+ // and pre-fill the type field if provided.
47440
+ setIsAddingMcp(false);
47441
+ setIsCreating(true);
47442
+ if (initialProviderType) {
47443
+ setFormType(initialProviderType);
47444
+ }
47445
+ }
47377
47446
  }
47378
47447
  prevCreateRequested.current = createRequested;
47379
47448
  if (createRequested && onCreateAcknowledged) {
@@ -47509,7 +47578,8 @@ var ProvidersSection = function ProvidersSection(_ref) {
47509
47578
  onSave: handleMcpSave,
47510
47579
  onCancel: function onCancel() {
47511
47580
  return setIsAddingMcp(false);
47512
- }
47581
+ },
47582
+ initialSelectedId: initialProviderType
47513
47583
  });
47514
47584
  } else if (isCreating) {
47515
47585
  detailContent = /*#__PURE__*/jsxRuntime.jsx(ProviderDetail, {
@@ -53291,6 +53361,10 @@ var AppSettingsModal = function AppSettingsModal(_ref) {
53291
53361
  initialProviderName = _ref$initialProviderN === void 0 ? null : _ref$initialProviderN,
53292
53362
  _ref$initialCreatePro = _ref.initialCreateProvider,
53293
53363
  initialCreateProvider = _ref$initialCreatePro === void 0 ? false : _ref$initialCreatePro,
53364
+ _ref$initialProviderT = _ref.initialProviderType,
53365
+ initialProviderType = _ref$initialProviderT === void 0 ? null : _ref$initialProviderT,
53366
+ _ref$initialProviderC = _ref.initialProviderClass,
53367
+ initialProviderClass = _ref$initialProviderC === void 0 ? null : _ref$initialProviderC,
53294
53368
  _ref$workspaces = _ref.workspaces,
53295
53369
  workspaces = _ref$workspaces === void 0 ? [] : _ref$workspaces,
53296
53370
  _ref$menuItems = _ref.menuItems,
@@ -53426,7 +53500,9 @@ var AppSettingsModal = function AppSettingsModal(_ref) {
53426
53500
  return setCreateRequested(false);
53427
53501
  },
53428
53502
  initialProviderName: initialProviderName,
53429
- initialCreateRequested: initialCreateProvider
53503
+ initialCreateRequested: initialCreateProvider,
53504
+ initialProviderType: initialProviderType,
53505
+ initialProviderClass: initialProviderClass
53430
53506
  }), activeSection === "themes" && /*#__PURE__*/jsxRuntime.jsx(ThemesSection, {
53431
53507
  onOpenThemeEditor: onOpenThemeEditor,
53432
53508
  dashApi: dashApi,
@@ -58278,13 +58354,31 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
58278
58354
  _useState52 = _slicedToArray(_useState51, 2),
58279
58355
  appSettingsCreateProvider = _useState52[0],
58280
58356
  setAppSettingsCreateProvider = _useState52[1];
58357
+ // Optional pre-fills used by the cross-modal "Add new <type>"
58358
+ // flow dispatched from dash-electron's WidgetBuilderModal.
58359
+ // initialProviderType is the type id (e.g. "filesystem", "slack").
58360
+ // initialProviderClass routes the create flow: "mcp" opens the
58361
+ // catalog detail with that type pre-selected; otherwise opens
58362
+ // the credential create form with formType pre-filled.
58363
+ var _useState53 = React.useState(null),
58364
+ _useState54 = _slicedToArray(_useState53, 2),
58365
+ appSettingsInitialProviderType = _useState54[0],
58366
+ setAppSettingsInitialProviderType = _useState54[1];
58367
+ var _useState55 = React.useState(null),
58368
+ _useState56 = _slicedToArray(_useState55, 2),
58369
+ appSettingsInitialProviderClass = _useState56[0],
58370
+ setAppSettingsInitialProviderClass = _useState56[1];
58281
58371
  function openAppSettings() {
58282
58372
  var section = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "general";
58283
58373
  var providerName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
58284
58374
  var createProvider = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
58375
+ var providerType = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
58376
+ var providerClass = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
58285
58377
  setAppSettingsInitialSection(section);
58286
58378
  setAppSettingsInitialProvider(providerName);
58287
58379
  setAppSettingsCreateProvider(createProvider);
58380
+ setAppSettingsInitialProviderType(providerType);
58381
+ setAppSettingsInitialProviderClass(providerClass);
58288
58382
  setIsAppSettingsOpen(true);
58289
58383
  }
58290
58384
  function handleProfileUpdated() {
@@ -58376,6 +58470,27 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
58376
58470
  };
58377
58471
  }, [changeCurrentTheme]);
58378
58472
 
58473
+ // ─── Listen for "open Settings to create a provider of type X" ──
58474
+ // Dispatched by dash-electron's Widget Builder PreviewProviderPicker
58475
+ // when the user clicks "Add new <type>" because no instances of the
58476
+ // chosen type exist yet. Detail: { type, providerClass }. The
58477
+ // Widget Builder's own listener (in dash-electron/Dash.js) handles
58478
+ // closing the builder modal — this listener only opens Settings.
58479
+ React.useEffect(function () {
58480
+ var handler = function handler(e) {
58481
+ var _ref4 = (e === null || e === void 0 ? void 0 : e.detail) || {},
58482
+ type = _ref4.type,
58483
+ providerClass = _ref4.providerClass;
58484
+ if (!type) return;
58485
+ openAppSettings("providers", null, true, type, providerClass || null);
58486
+ };
58487
+ window.addEventListener("dash:open-settings-create-provider", handler);
58488
+ return function () {
58489
+ return window.removeEventListener("dash:open-settings-create-provider", handler);
58490
+ };
58491
+ // eslint-disable-next-line react-hooks/exhaustive-deps
58492
+ }, []);
58493
+
58379
58494
  // ─── Listen for external "open workspace" requests ──────────────
58380
58495
  // Fired by: Dash.js notification click, MCP state-changed for
58381
58496
  // create_dashboard, etc. Any code that wants to switch the active
@@ -58385,10 +58500,10 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
58385
58500
  // We record the requested ID and open it once it appears in
58386
58501
  // workspaceConfig — handles the case where the workspace was just
58387
58502
  // created and the config reload is still in flight.
58388
- var _useState53 = React.useState(null),
58389
- _useState54 = _slicedToArray(_useState53, 2),
58390
- pendingOpenWorkspaceId = _useState54[0],
58391
- setPendingOpenWorkspaceId = _useState54[1];
58503
+ var _useState57 = React.useState(null),
58504
+ _useState58 = _slicedToArray(_useState57, 2),
58505
+ pendingOpenWorkspaceId = _useState58[0],
58506
+ setPendingOpenWorkspaceId = _useState58[1];
58392
58507
  React.useEffect(function () {
58393
58508
  var handler = function handler(e) {
58394
58509
  var _e$detail2;
@@ -59010,10 +59125,10 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
59010
59125
  }
59011
59126
 
59012
59127
  // ─── Page State ──────────────────────────────────────────────────
59013
- var _useState55 = React.useState(null),
59014
- _useState56 = _slicedToArray(_useState55, 2),
59015
- activePageId = _useState56[0],
59016
- setActivePageId = _useState56[1];
59128
+ var _useState59 = React.useState(null),
59129
+ _useState60 = _slicedToArray(_useState59, 2),
59130
+ activePageId = _useState60[0],
59131
+ setActivePageId = _useState60[1];
59017
59132
 
59018
59133
  // Page history stack for goBack() — pushes the previous page id
59019
59134
  // whenever a navigation happens through navigateToPage().
@@ -59047,9 +59162,9 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
59047
59162
  // Listen for programmatic page switches via DashboardActionsApi
59048
59163
  React.useEffect(function () {
59049
59164
  function onSwitchPage(e) {
59050
- var _ref4 = e.detail || {},
59051
- pageId = _ref4.pageId,
59052
- pageName = _ref4.pageName;
59165
+ var _ref5 = e.detail || {},
59166
+ pageId = _ref5.pageId,
59167
+ pageName = _ref5.pageName;
59053
59168
  if (pageId) {
59054
59169
  navigateToPage(pageId);
59055
59170
  } else if (pageName) {
@@ -59904,11 +60019,15 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
59904
60019
  if (!open) {
59905
60020
  setAppSettingsInitialProvider(null);
59906
60021
  setAppSettingsCreateProvider(false);
60022
+ setAppSettingsInitialProviderType(null);
60023
+ setAppSettingsInitialProviderClass(null);
59907
60024
  }
59908
60025
  },
59909
60026
  initialSection: appSettingsInitialSection,
59910
60027
  initialProviderName: appSettingsInitialProvider,
59911
60028
  initialCreateProvider: appSettingsCreateProvider,
60029
+ initialProviderType: appSettingsInitialProviderType,
60030
+ initialProviderClass: appSettingsInitialProviderClass,
59912
60031
  workspaces: workspaceConfig,
59913
60032
  menuItems: menuItems,
59914
60033
  dashApi: dashApi,