@trops/dash-core 0.1.453 → 0.1.455

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
@@ -3711,7 +3711,7 @@ var FolderDetail = function FolderDetail(_ref) {
3711
3711
  });
3712
3712
  };
3713
3713
 
3714
- var OptionCard$1 = function OptionCard(_ref) {
3714
+ var OptionCard$2 = function OptionCard(_ref) {
3715
3715
  var icon = _ref.icon,
3716
3716
  title = _ref.title,
3717
3717
  description = _ref.description,
@@ -3760,28 +3760,28 @@ var CreationMethodPicker = function CreationMethodPicker(_ref2) {
3760
3760
  })]
3761
3761
  }), /*#__PURE__*/jsxs("div", {
3762
3762
  className: "flex flex-col w-2/3 p-6 pt-10 space-y-3",
3763
- children: [/*#__PURE__*/jsx(OptionCard$1, {
3763
+ children: [/*#__PURE__*/jsx(OptionCard$2, {
3764
3764
  icon: "plus",
3765
3765
  title: "New Dashboard",
3766
3766
  description: "Start from a blank template and customize your layout",
3767
3767
  onClick: function onClick() {
3768
3768
  return onSelect("template");
3769
3769
  }
3770
- }), /*#__PURE__*/jsx(OptionCard$1, {
3770
+ }), /*#__PURE__*/jsx(OptionCard$2, {
3771
3771
  icon: "file-zipper",
3772
3772
  title: "Import from File",
3773
3773
  description: "Import a dashboard from a .zip file on your computer",
3774
3774
  onClick: function onClick() {
3775
3775
  return onSelect("import");
3776
3776
  }
3777
- }), /*#__PURE__*/jsx(OptionCard$1, {
3777
+ }), /*#__PURE__*/jsx(OptionCard$2, {
3778
3778
  icon: "compass",
3779
3779
  title: "Search Registry",
3780
3780
  description: "Browse and install dashboards from the online registry",
3781
3781
  onClick: function onClick() {
3782
3782
  return onSelect("registry");
3783
3783
  }
3784
- }), /*#__PURE__*/jsx(OptionCard$1, {
3784
+ }), /*#__PURE__*/jsx(OptionCard$2, {
3785
3785
  icon: "wand-magic-sparkles",
3786
3786
  title: "Dashboard Wizard",
3787
3787
  description: "Guided setup \u2014 pick categories, providers, and widgets step by step",
@@ -43913,7 +43913,9 @@ var ProviderDetail = function ProviderDetail(_ref) {
43913
43913
  _ref$catalogAuthComma = _ref.catalogAuthCommand,
43914
43914
  catalogAuthCommand = _ref$catalogAuthComma === void 0 ? null : _ref$catalogAuthComma,
43915
43915
  _ref$catalogCredentia = _ref.catalogCredentialSchema,
43916
- catalogCredentialSchema = _ref$catalogCredentia === void 0 ? {} : _ref$catalogCredentia;
43916
+ catalogCredentialSchema = _ref$catalogCredentia === void 0 ? {} : _ref$catalogCredentia,
43917
+ _ref$onBack = _ref.onBack,
43918
+ onBack = _ref$onBack === void 0 ? null : _ref$onBack;
43917
43919
  var appContext = useContext(AppContext);
43918
43920
  var dashApi = appContext === null || appContext === void 0 ? void 0 : appContext.dashApi;
43919
43921
  var isMcp = (provider === null || provider === void 0 ? void 0 : provider.providerClass) === "mcp";
@@ -44242,7 +44244,15 @@ var ProviderDetail = function ProviderDetail(_ref) {
44242
44244
  className: "flex flex-col flex-1 min-h-0",
44243
44245
  children: [/*#__PURE__*/jsxs("div", {
44244
44246
  className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-5",
44245
- children: [/*#__PURE__*/jsx(SubHeading3, {
44247
+ children: [onBack && /*#__PURE__*/jsxs("button", {
44248
+ type: "button",
44249
+ onClick: onBack,
44250
+ className: "flex items-center gap-2 text-sm opacity-60 hover:opacity-100 transition-opacity",
44251
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
44252
+ icon: "chevron-left",
44253
+ className: "h-3 w-3"
44254
+ }), "Back"]
44255
+ }), /*#__PURE__*/jsx(SubHeading3, {
44246
44256
  title: isCreating ? "New Provider" : "Edit Provider",
44247
44257
  padding: false
44248
44258
  }), /*#__PURE__*/jsxs("div", {
@@ -45836,7 +45846,9 @@ var McpCatalogDetail = function McpCatalogDetail(_ref) {
45836
45846
  var onSave = _ref.onSave,
45837
45847
  onCancel = _ref.onCancel,
45838
45848
  _ref$initialSelectedI = _ref.initialSelectedId,
45839
- initialSelectedId = _ref$initialSelectedI === void 0 ? null : _ref$initialSelectedI;
45849
+ initialSelectedId = _ref$initialSelectedI === void 0 ? null : _ref$initialSelectedI,
45850
+ _ref$onBack = _ref.onBack,
45851
+ onBack = _ref$onBack === void 0 ? null : _ref$onBack;
45840
45852
  var appContext = useContext(AppContext);
45841
45853
  var dashApi = appContext === null || appContext === void 0 ? void 0 : appContext.dashApi;
45842
45854
  var _useState = useState([]),
@@ -46487,7 +46499,15 @@ var McpCatalogDetail = function McpCatalogDetail(_ref) {
46487
46499
  className: "flex flex-col flex-1 min-h-0",
46488
46500
  children: /*#__PURE__*/jsxs("div", {
46489
46501
  className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-4",
46490
- children: [/*#__PURE__*/jsxs("div", {
46502
+ children: [onBack && /*#__PURE__*/jsxs("button", {
46503
+ type: "button",
46504
+ onClick: onBack,
46505
+ className: "flex items-center gap-2 text-sm opacity-60 hover:opacity-100 transition-opacity",
46506
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
46507
+ icon: "chevron-left",
46508
+ className: "h-3 w-3"
46509
+ }), "Back"]
46510
+ }), /*#__PURE__*/jsxs("div", {
46491
46511
  className: "flex items-center justify-between",
46492
46512
  children: [/*#__PURE__*/jsx(SubHeading3, {
46493
46513
  title: "Add MCP Server",
@@ -46664,7 +46684,9 @@ var WebSocketProviderForm = function WebSocketProviderForm(_ref) {
46664
46684
  _ref$initialCredentia = _ref.initialCredentials,
46665
46685
  initialCredentials = _ref$initialCredentia === void 0 ? {} : _ref$initialCredentia,
46666
46686
  onSave = _ref.onSave,
46667
- onCancel = _ref.onCancel;
46687
+ onCancel = _ref.onCancel,
46688
+ _ref$onBack = _ref.onBack,
46689
+ onBack = _ref$onBack === void 0 ? null : _ref$onBack;
46668
46690
  var _useState = useState(initialName),
46669
46691
  _useState2 = _slicedToArray(_useState, 2),
46670
46692
  name = _useState2[0],
@@ -46878,7 +46900,15 @@ var WebSocketProviderForm = function WebSocketProviderForm(_ref) {
46878
46900
  className: "flex flex-col flex-1 min-h-0",
46879
46901
  children: [/*#__PURE__*/jsxs("div", {
46880
46902
  className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-5",
46881
- children: [/*#__PURE__*/jsx(SubHeading3, {
46903
+ children: [onBack && /*#__PURE__*/jsxs("button", {
46904
+ type: "button",
46905
+ onClick: onBack,
46906
+ className: "flex items-center gap-2 text-sm opacity-60 hover:opacity-100 transition-opacity",
46907
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
46908
+ icon: "chevron-left",
46909
+ className: "h-3 w-3"
46910
+ }), "Back"]
46911
+ }), /*#__PURE__*/jsx(SubHeading3, {
46882
46912
  title: isEditMode ? "Edit WebSocket Provider" : "New WebSocket Provider",
46883
46913
  padding: false
46884
46914
  }), /*#__PURE__*/jsxs("div", {
@@ -47054,6 +47084,103 @@ var WebSocketProviderForm = function WebSocketProviderForm(_ref) {
47054
47084
  });
47055
47085
  };
47056
47086
 
47087
+ var OptionCard$1 = function OptionCard(_ref) {
47088
+ var icon = _ref.icon,
47089
+ title = _ref.title,
47090
+ description = _ref.description,
47091
+ onClick = _ref.onClick,
47092
+ currentTheme = _ref.currentTheme;
47093
+ return /*#__PURE__*/jsxs("button", {
47094
+ type: "button",
47095
+ onClick: onClick,
47096
+ className: "w-full flex flex-row items-center gap-4 p-4 rounded-lg text-left transition-opacity ".concat(currentTheme["bg-primary-medium"] || "bg-white/5", " hover:opacity-80"),
47097
+ children: [/*#__PURE__*/jsx("div", {
47098
+ className: "flex-shrink-0 h-8 w-8 flex items-center justify-center opacity-60",
47099
+ children: /*#__PURE__*/jsx(FontAwesomeIcon, {
47100
+ icon: icon,
47101
+ className: "h-5 w-5"
47102
+ })
47103
+ }), /*#__PURE__*/jsxs("div", {
47104
+ className: "flex flex-col min-w-0",
47105
+ children: [/*#__PURE__*/jsx("span", {
47106
+ className: "text-sm font-medium",
47107
+ children: title
47108
+ }), /*#__PURE__*/jsx("span", {
47109
+ className: "text-xs opacity-50 mt-0.5",
47110
+ children: description
47111
+ })]
47112
+ }), /*#__PURE__*/jsx("div", {
47113
+ className: "flex-shrink-0 ml-auto opacity-30",
47114
+ children: /*#__PURE__*/jsx(FontAwesomeIcon, {
47115
+ icon: "chevron-right",
47116
+ className: "h-3 w-3"
47117
+ })
47118
+ })]
47119
+ });
47120
+ };
47121
+
47122
+ /**
47123
+ * NewProviderPicker — the 3-option chooser shown when the user clicks
47124
+ * "+ New Provider" from the Settings → Providers header without a
47125
+ * specific class pre-selected. Mirrors InstallWidgetPicker's pattern
47126
+ * so the UI feels consistent across "+ New ..." entry points in
47127
+ * Settings.
47128
+ *
47129
+ * Calls `onSelect(class)` with the literal class string ("credential",
47130
+ * "mcp", or "websocket"). The parent (ProvidersSection) then routes
47131
+ * to the appropriate create flow:
47132
+ *
47133
+ * credential → ProviderDetail (credential create form)
47134
+ * mcp → McpCatalogDetail (catalog browser)
47135
+ * websocket → WsProviderDetail (WebSocket add form)
47136
+ *
47137
+ * The Widget Builder's existing deep-link path (which always passes
47138
+ * an explicit class) bypasses this chooser and goes straight to the
47139
+ * matching form.
47140
+ */
47141
+ var NewProviderPicker = function NewProviderPicker(_ref2) {
47142
+ var onSelect = _ref2.onSelect;
47143
+ var _useContext = useContext(ThemeContext),
47144
+ currentTheme = _useContext.currentTheme;
47145
+ var panelStyles = getStylesForItem(themeObjects.PANEL, currentTheme, {
47146
+ grow: false
47147
+ });
47148
+ return /*#__PURE__*/jsx("div", {
47149
+ className: "flex flex-col flex-1 min-h-0",
47150
+ children: /*#__PURE__*/jsxs("div", {
47151
+ className: "flex-1 overflow-y-auto p-6 space-y-3 ".concat(panelStyles.textColor || "text-gray-200"),
47152
+ children: [/*#__PURE__*/jsx("span", {
47153
+ className: "text-xs font-semibold opacity-50 block mb-4",
47154
+ children: "ADD A NEW PROVIDER"
47155
+ }), /*#__PURE__*/jsx(OptionCard$1, {
47156
+ icon: "key",
47157
+ title: "Credential",
47158
+ description: "API key or token credentials for services like Algolia, Anthropic, or any HTTP API",
47159
+ onClick: function onClick() {
47160
+ return onSelect("credential");
47161
+ },
47162
+ currentTheme: currentTheme
47163
+ }), /*#__PURE__*/jsx(OptionCard$1, {
47164
+ icon: "plug",
47165
+ title: "MCP",
47166
+ description: "Model Context Protocol server \u2014 pick from a curated catalog (Slack, Filesystem, Notion, etc.)",
47167
+ onClick: function onClick() {
47168
+ return onSelect("mcp");
47169
+ },
47170
+ currentTheme: currentTheme
47171
+ }), /*#__PURE__*/jsx(OptionCard$1, {
47172
+ icon: "diagram-project",
47173
+ title: "WebSocket",
47174
+ description: "Real-time WebSocket connection to a streaming endpoint",
47175
+ onClick: function onClick() {
47176
+ return onSelect("websocket");
47177
+ },
47178
+ currentTheme: currentTheme
47179
+ })]
47180
+ })
47181
+ });
47182
+ };
47183
+
47057
47184
  var ProvidersSection = function ProvidersSection(_ref) {
47058
47185
  var _ref$dashApi = _ref.dashApi,
47059
47186
  dashApi = _ref$dashApi === void 0 ? null : _ref$dashApi,
@@ -47094,42 +47221,59 @@ var ProvidersSection = function ProvidersSection(_ref) {
47094
47221
  _useState8 = _slicedToArray(_useState7, 2),
47095
47222
  isCreating = _useState8[0],
47096
47223
  setIsCreating = _useState8[1];
47224
+ // When the user clicks "+ New Provider" without a pre-selected
47225
+ // class (Settings header button), show the class chooser
47226
+ // (Credential / MCP / WebSocket) instead of defaulting to the
47227
+ // credential form. Widget Builder's deep-link path passes a class
47228
+ // explicitly and bypasses this chooser.
47097
47229
  var _useState9 = useState(false),
47098
47230
  _useState0 = _slicedToArray(_useState9, 2),
47099
- isEditing = _useState0[0],
47100
- setIsEditing = _useState0[1];
47101
- var _useState1 = useState(""),
47231
+ isShowingClassChooser = _useState0[0],
47232
+ setIsShowingClassChooser = _useState0[1];
47233
+ // Tracks whether the current create-flow detail was reached via the
47234
+ // chooser (vs. the Widget Builder deep-link or list-edit). Only the
47235
+ // chooser-entry path renders the "← Back" affordance, since that's
47236
+ // the only path that has somewhere to go back to.
47237
+ var _useState1 = useState(false),
47102
47238
  _useState10 = _slicedToArray(_useState1, 2),
47103
- formName = _useState10[0],
47104
- setFormName = _useState10[1];
47105
- var _useState11 = useState(""),
47239
+ cameFromClassChooser = _useState10[0],
47240
+ setCameFromClassChooser = _useState10[1];
47241
+ var _useState11 = useState(false),
47106
47242
  _useState12 = _slicedToArray(_useState11, 2),
47107
- formType = _useState12[0],
47108
- setFormType = _useState12[1];
47109
- var _useState13 = useState({}),
47243
+ isEditing = _useState12[0],
47244
+ setIsEditing = _useState12[1];
47245
+ var _useState13 = useState(""),
47110
47246
  _useState14 = _slicedToArray(_useState13, 2),
47111
- formCredentials = _useState14[0],
47112
- setFormCredentials = _useState14[1];
47113
- var _useState15 = useState(null),
47247
+ formName = _useState14[0],
47248
+ setFormName = _useState14[1];
47249
+ var _useState15 = useState(""),
47114
47250
  _useState16 = _slicedToArray(_useState15, 2),
47115
- deleteTarget = _useState16[0],
47116
- setDeleteTarget = _useState16[1];
47117
- var _useState17 = useState(false),
47251
+ formType = _useState16[0],
47252
+ setFormType = _useState16[1];
47253
+ var _useState17 = useState({}),
47118
47254
  _useState18 = _slicedToArray(_useState17, 2),
47119
- isAddingMcp = _useState18[0],
47120
- setIsAddingMcp = _useState18[1];
47121
- var _useState19 = useState(false),
47255
+ formCredentials = _useState18[0],
47256
+ setFormCredentials = _useState18[1];
47257
+ var _useState19 = useState(null),
47122
47258
  _useState20 = _slicedToArray(_useState19, 2),
47123
- isEditingMcp = _useState20[0],
47124
- setIsEditingMcp = _useState20[1];
47259
+ deleteTarget = _useState20[0],
47260
+ setDeleteTarget = _useState20[1];
47125
47261
  var _useState21 = useState(false),
47126
47262
  _useState22 = _slicedToArray(_useState21, 2),
47127
- isAddingWs = _useState22[0],
47128
- setIsAddingWs = _useState22[1];
47263
+ isAddingMcp = _useState22[0],
47264
+ setIsAddingMcp = _useState22[1];
47129
47265
  var _useState23 = useState(false),
47130
47266
  _useState24 = _slicedToArray(_useState23, 2),
47131
- isEditingWs = _useState24[0],
47132
- setIsEditingWs = _useState24[1];
47267
+ isEditingMcp = _useState24[0],
47268
+ setIsEditingMcp = _useState24[1];
47269
+ var _useState25 = useState(false),
47270
+ _useState26 = _slicedToArray(_useState25, 2),
47271
+ isAddingWs = _useState26[0],
47272
+ setIsAddingWs = _useState26[1];
47273
+ var _useState27 = useState(false),
47274
+ _useState28 = _slicedToArray(_useState27, 2),
47275
+ isEditingWs = _useState28[0],
47276
+ setIsEditingWs = _useState28[1];
47133
47277
 
47134
47278
  // Row ID counter for env/header rows in MCP edit mode
47135
47279
  var nextRowIdRef = useRef(0);
@@ -47411,19 +47555,39 @@ var ProvidersSection = function ProvidersSection(_ref) {
47411
47555
  if (createRequested && !prevCreateRequested.current) {
47412
47556
  resetForm();
47413
47557
  setSelectedName(null);
47558
+ setIsShowingClassChooser(false);
47559
+ // External create requests (deep-link or header button) do NOT
47560
+ // come via the chooser, so any leftover "came from chooser" state
47561
+ // from a prior session must be cleared before routing.
47562
+ setCameFromClassChooser(false);
47414
47563
  if (initialProviderClass === "mcp") {
47415
47564
  // MCP class: open the catalog detail. Pre-select happens in
47416
47565
  // McpCatalogDetail via the initialSelectedId prop passed below.
47417
47566
  setIsCreating(false);
47418
47567
  setIsAddingMcp(true);
47419
- } else {
47420
- // Credential class (default): open the credential create form
47421
- // and pre-fill the type field if provided.
47568
+ } else if (initialProviderClass === "websocket") {
47569
+ // WebSocket class: open the WebSocket add form. Reachable via
47570
+ // a future Widget Builder deep-link for ws-typed widgets.
47571
+ setIsCreating(false);
47572
+ setIsAddingMcp(false);
47573
+ setIsAddingWs(true);
47574
+ } else if (initialProviderClass === "credential") {
47575
+ // Credential class: open the credential create form and
47576
+ // pre-fill the type field if provided.
47422
47577
  setIsAddingMcp(false);
47423
47578
  setIsCreating(true);
47424
47579
  if (initialProviderType) {
47425
47580
  setFormType(initialProviderType);
47426
47581
  }
47582
+ } else {
47583
+ // No class specified — Settings header "+ New Provider"
47584
+ // button hits this branch. Show the chooser so the user
47585
+ // picks Credential / MCP / WebSocket explicitly instead of
47586
+ // landing on the credential form by default.
47587
+ setIsAddingMcp(false);
47588
+ setIsCreating(false);
47589
+ setIsAddingWs(false);
47590
+ setIsShowingClassChooser(true);
47427
47591
  }
47428
47592
  }
47429
47593
  prevCreateRequested.current = createRequested;
@@ -47523,13 +47687,26 @@ var ProvidersSection = function ProvidersSection(_ref) {
47523
47687
  })]
47524
47688
  })]
47525
47689
  });
47690
+
47691
+ // Closes whichever create-flow detail is open and re-opens the
47692
+ // class chooser. Only attached to the detail's onBack prop when
47693
+ // the user reached it via the chooser (cameFromClassChooser).
47694
+ var goBackToClassChooser = function goBackToClassChooser() {
47695
+ resetForm();
47696
+ setIsAddingWs(false);
47697
+ setIsAddingMcp(false);
47698
+ setIsCreating(false);
47699
+ setCameFromClassChooser(false);
47700
+ setIsShowingClassChooser(true);
47701
+ };
47526
47702
  var detailContent = null;
47527
47703
  if (isAddingWs) {
47528
47704
  detailContent = /*#__PURE__*/jsx(WebSocketProviderForm, {
47529
47705
  onSave: handleWsSave,
47530
47706
  onCancel: function onCancel() {
47531
47707
  return setIsAddingWs(false);
47532
- }
47708
+ },
47709
+ onBack: cameFromClassChooser ? goBackToClassChooser : null
47533
47710
  });
47534
47711
  } else if (isEditingWs && selectedName && selectedProvider) {
47535
47712
  var wc = selectedProvider.wsConfig || {};
@@ -47555,13 +47732,28 @@ var ProvidersSection = function ProvidersSection(_ref) {
47555
47732
  return setIsEditingWs(false);
47556
47733
  }
47557
47734
  }, selectedName);
47735
+ } else if (isShowingClassChooser) {
47736
+ detailContent = /*#__PURE__*/jsx(NewProviderPicker, {
47737
+ onSelect: function onSelect(cls) {
47738
+ setIsShowingClassChooser(false);
47739
+ setCameFromClassChooser(true);
47740
+ if (cls === "mcp") {
47741
+ setIsAddingMcp(true);
47742
+ } else if (cls === "websocket") {
47743
+ setIsAddingWs(true);
47744
+ } else {
47745
+ setIsCreating(true);
47746
+ }
47747
+ }
47748
+ });
47558
47749
  } else if (isAddingMcp) {
47559
47750
  detailContent = /*#__PURE__*/jsx(McpCatalogDetail, {
47560
47751
  onSave: handleMcpSave,
47561
47752
  onCancel: function onCancel() {
47562
47753
  return setIsAddingMcp(false);
47563
47754
  },
47564
- initialSelectedId: initialProviderType
47755
+ initialSelectedId: initialProviderType,
47756
+ onBack: cameFromClassChooser ? goBackToClassChooser : null
47565
47757
  });
47566
47758
  } else if (isCreating) {
47567
47759
  detailContent = /*#__PURE__*/jsx(ProviderDetail, {
@@ -47576,7 +47768,8 @@ var ProvidersSection = function ProvidersSection(_ref) {
47576
47768
  onCancelEdit: function onCancelEdit() {
47577
47769
  resetForm();
47578
47770
  setIsCreating(false);
47579
- }
47771
+ },
47772
+ onBack: cameFromClassChooser ? goBackToClassChooser : null
47580
47773
  });
47581
47774
  } else if (isEditingMcp && selectedName && selectedProvider) {
47582
47775
  var mc = selectedProvider.mcpConfig || {};