@trops/dash-core 0.1.27 → 0.1.29

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
@@ -7180,39 +7180,45 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7180
7180
  isCreatingProvider = _useState24[0],
7181
7181
  setIsCreatingProvider = _useState24[1];
7182
7182
 
7183
- // Registry state
7184
- var _useState25 = React.useState(false),
7183
+ // Installed widget grouping
7184
+ var _useState25 = React.useState(new Set()),
7185
7185
  _useState26 = _slicedToArray(_useState25, 2),
7186
- isLoadingRegistry = _useState26[0],
7187
- setIsLoadingRegistry = _useState26[1];
7188
- var _useState27 = React.useState(null),
7186
+ expandedGroups = _useState26[0],
7187
+ setExpandedGroups = _useState26[1];
7188
+
7189
+ // Registry state
7190
+ var _useState27 = React.useState(false),
7189
7191
  _useState28 = _slicedToArray(_useState27, 2),
7190
- registryError = _useState28[0],
7191
- setRegistryError = _useState28[1];
7192
- var _useState29 = React.useState([]),
7192
+ isLoadingRegistry = _useState28[0],
7193
+ setIsLoadingRegistry = _useState28[1];
7194
+ var _useState29 = React.useState(null),
7193
7195
  _useState30 = _slicedToArray(_useState29, 2),
7194
- registryPackages = _useState30[0],
7195
- setRegistryPackages = _useState30[1];
7196
- var _useState31 = React.useState("packages"),
7196
+ registryError = _useState30[0],
7197
+ setRegistryError = _useState30[1];
7198
+ var _useState31 = React.useState([]),
7197
7199
  _useState32 = _slicedToArray(_useState31, 2),
7198
- registryViewMode = _useState32[0],
7199
- setRegistryViewMode = _useState32[1]; // "packages" | "widgets"
7200
- var _useState33 = React.useState(new Set()),
7200
+ registryPackages = _useState32[0],
7201
+ setRegistryPackages = _useState32[1];
7202
+ var _useState33 = React.useState("packages"),
7201
7203
  _useState34 = _slicedToArray(_useState33, 2),
7202
- expandedPackages = _useState34[0],
7203
- setExpandedPackages = _useState34[1];
7204
- var _useState35 = React.useState(null),
7204
+ registryViewMode = _useState34[0],
7205
+ setRegistryViewMode = _useState34[1]; // "packages" | "widgets"
7206
+ var _useState35 = React.useState(new Set()),
7205
7207
  _useState36 = _slicedToArray(_useState35, 2),
7206
- selectedPackage = _useState36[0],
7207
- setSelectedPackage = _useState36[1];
7208
- var _useState37 = React.useState(false),
7208
+ expandedPackages = _useState36[0],
7209
+ setExpandedPackages = _useState36[1];
7210
+ var _useState37 = React.useState(null),
7209
7211
  _useState38 = _slicedToArray(_useState37, 2),
7210
- isInstalling = _useState38[0],
7211
- setIsInstalling = _useState38[1];
7212
- var _useState39 = React.useState(null),
7212
+ selectedPackage = _useState38[0],
7213
+ setSelectedPackage = _useState38[1];
7214
+ var _useState39 = React.useState(false),
7213
7215
  _useState40 = _slicedToArray(_useState39, 2),
7214
- installError = _useState40[0],
7215
- setInstallError = _useState40[1];
7216
+ isInstalling = _useState40[0],
7217
+ setIsInstalling = _useState40[1];
7218
+ var _useState41 = React.useState(null),
7219
+ _useState42 = _slicedToArray(_useState41, 2),
7220
+ installError = _useState42[0],
7221
+ setInstallError = _useState42[1];
7216
7222
 
7217
7223
  // Phase 3: Recent Widgets - localStorage functions
7218
7224
  var loadRecentWidgets = function loadRecentWidgets() {
@@ -7284,6 +7290,7 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7284
7290
  setSearchQuery("");
7285
7291
  setSelectedAuthor("all");
7286
7292
  setSelectedProvider("all");
7293
+ setExpandedGroups(new Set()); // Start with all groups collapsed
7287
7294
  }
7288
7295
  // eslint-disable-next-line react-hooks/exhaustive-deps
7289
7296
  }, [isOpen]);
@@ -7437,6 +7444,42 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7437
7444
  };
7438
7445
  var filteredWidgets = getFilteredWidgets();
7439
7446
 
7447
+ // Set of installed package names for "Installed" badge in Discover mode
7448
+ var installedPackageNames = React.useMemo(function () {
7449
+ var names = new Set();
7450
+ var map = ComponentManager.map();
7451
+ Object.values(map).forEach(function (widget) {
7452
+ if (widget._sourcePackage) names.add(widget._sourcePackage);
7453
+ });
7454
+ return names;
7455
+ }, [widgets]);
7456
+
7457
+ // Group installed widgets by package > author > "Other"
7458
+ var groupedInstalledWidgets = React.useMemo(function () {
7459
+ if (selectedSource !== "Installed") return {};
7460
+ var groups = {};
7461
+ filteredWidgets.forEach(function (widget) {
7462
+ var group = widget["package"] || widget.author || "Other";
7463
+ if (!groups[group]) groups[group] = [];
7464
+ groups[group].push(widget);
7465
+ });
7466
+ return groups;
7467
+ }, [filteredWidgets, selectedSource]);
7468
+ var installedGroupNames = React.useMemo(function () {
7469
+ return Object.keys(groupedInstalledWidgets).sort();
7470
+ }, [groupedInstalledWidgets]);
7471
+ var toggleGroup = function toggleGroup(groupName) {
7472
+ setExpandedGroups(function (prev) {
7473
+ var next = new Set(prev);
7474
+ if (next.has(groupName)) {
7475
+ next["delete"](groupName);
7476
+ } else {
7477
+ next.add(groupName);
7478
+ }
7479
+ return next;
7480
+ });
7481
+ };
7482
+
7440
7483
  // Group filtered widgets by package (for package view in Discover)
7441
7484
  var getGroupedByPackage = function getGroupedByPackage() {
7442
7485
  var groups = {};
@@ -7637,8 +7680,10 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7637
7680
  var isAddButtonEnabled = function isAddButtonEnabled() {
7638
7681
  if (!selectedWidget) return false;
7639
7682
 
7640
- // For registry widgets, always enabled (install action)
7641
- if (selectedWidget.isRegistry) return true;
7683
+ // For registry widgets, enabled unless already installed
7684
+ if (selectedWidget.isRegistry) {
7685
+ return !installedPackageNames.has(selectedWidget.packageName);
7686
+ }
7642
7687
 
7643
7688
  // Check providers: all required providers must be selected
7644
7689
  var hasRequiredProviders = selectedWidget.providers ? selectedWidget.providers.filter(function (p) {
@@ -7743,31 +7788,56 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7743
7788
  children: /*#__PURE__*/jsxRuntime.jsx("div", {
7744
7789
  className: "flex items-center justify-between w-full",
7745
7790
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
7746
- className: "flex items-center space-x-2 flex-1 min-w-0",
7791
+ className: "flex items-center gap-2 flex-1 min-w-0",
7747
7792
  children: [/*#__PURE__*/jsxRuntime.jsx("span", {
7748
7793
  className: "text-xs text-gray-500",
7749
7794
  children: expandedPackages.has(group.name) ? "\u25BC" : "\u25B6"
7750
7795
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
7751
7796
  className: "min-w-0 flex-1",
7752
7797
  children: [/*#__PURE__*/jsxRuntime.jsx("div", {
7753
- className: "text-base font-medium truncate",
7798
+ className: "text-sm font-medium truncate",
7754
7799
  children: group.displayName
7755
7800
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
7756
7801
  className: "text-xs text-gray-500",
7757
7802
  children: [group.widgets.length, " widget", group.widgets.length !== 1 ? "s" : "", " \xB7 v", group.version]
7758
7803
  })]
7804
+ }), installedPackageNames.has(group.name) && /*#__PURE__*/jsxRuntime.jsx("span", {
7805
+ className: "text-[10px] px-1.5 py-0.5 rounded bg-green-500/20 text-green-400 flex-shrink-0",
7806
+ children: "Installed"
7759
7807
  })]
7760
7808
  })
7761
7809
  })
7762
7810
  }), expandedPackages.has(group.name) && group.widgets.map(function (widget) {
7811
+ var _widget$providers;
7763
7812
  return /*#__PURE__*/jsxRuntime.jsx(DashReact.MenuItem3, {
7764
7813
  onClick: function onClick() {
7765
7814
  return handleWidgetSelect(widget);
7766
7815
  },
7767
7816
  selected: (selectedWidget === null || selectedWidget === void 0 ? void 0 : selectedWidget.key) === widget.key,
7768
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
7769
- className: "pl-6 text-sm",
7770
- children: widget.name
7817
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
7818
+ className: "flex items-center gap-2 pl-6 w-full",
7819
+ children: [/*#__PURE__*/jsxRuntime.jsx(WidgetIcon, {
7820
+ icon: widget.icon,
7821
+ className: "h-4 w-4 opacity-60 flex-shrink-0",
7822
+ fallback: "puzzle-piece"
7823
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
7824
+ className: "flex-1 min-w-0",
7825
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
7826
+ className: "text-sm font-medium truncate",
7827
+ children: widget.name
7828
+ }), widget.description && /*#__PURE__*/jsxRuntime.jsx("div", {
7829
+ className: "text-xs opacity-50 truncate",
7830
+ children: widget.description
7831
+ }), ((_widget$providers = widget.providers) === null || _widget$providers === void 0 ? void 0 : _widget$providers.length) > 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
7832
+ className: "flex flex-wrap gap-1 mt-0.5",
7833
+ children: widget.providers.map(function (p) {
7834
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
7835
+ className: "text-[10px] px-1.5 py-0.5 rounded bg-blue-500/20 text-blue-300",
7836
+ children: p.type
7837
+ }, p.type);
7838
+ })
7839
+ })]
7840
+ })]
7771
7841
  })
7772
7842
  }, widget.key);
7773
7843
  })]
@@ -7782,19 +7852,44 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7782
7852
  padding: true,
7783
7853
  height: "h-full",
7784
7854
  children: filteredWidgets.map(function (widget) {
7855
+ var _widget$providers2;
7785
7856
  return /*#__PURE__*/jsxRuntime.jsx(DashReact.MenuItem3, {
7786
7857
  onClick: function onClick() {
7787
7858
  return handleWidgetSelect(widget);
7788
7859
  },
7789
7860
  selected: (selectedWidget === null || selectedWidget === void 0 ? void 0 : selectedWidget.key) === widget.key,
7790
7861
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
7791
- className: "flex items-center justify-between w-full",
7792
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
7793
- className: "text-base font-medium",
7794
- children: widget.name
7795
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
7796
- className: "text-xs text-gray-500",
7797
- children: widget.packageDisplayName
7862
+ className: "flex items-center gap-2 w-full",
7863
+ children: [/*#__PURE__*/jsxRuntime.jsx(WidgetIcon, {
7864
+ icon: widget.icon,
7865
+ className: "h-4 w-4 opacity-60 flex-shrink-0",
7866
+ fallback: "puzzle-piece"
7867
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
7868
+ className: "flex-1 min-w-0",
7869
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
7870
+ className: "text-sm font-medium truncate",
7871
+ children: widget.name
7872
+ }), widget.description && /*#__PURE__*/jsxRuntime.jsx("div", {
7873
+ className: "text-xs opacity-50 truncate",
7874
+ children: widget.description
7875
+ }), ((_widget$providers2 = widget.providers) === null || _widget$providers2 === void 0 ? void 0 : _widget$providers2.length) > 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
7876
+ className: "flex flex-wrap gap-1 mt-0.5",
7877
+ children: widget.providers.map(function (p) {
7878
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
7879
+ className: "text-[10px] px-1.5 py-0.5 rounded bg-blue-500/20 text-blue-300",
7880
+ children: p.type
7881
+ }, p.type);
7882
+ })
7883
+ })]
7884
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
7885
+ className: "flex items-center gap-1.5 flex-shrink-0",
7886
+ children: [installedPackageNames.has(widget.packageName) && /*#__PURE__*/jsxRuntime.jsx("span", {
7887
+ className: "text-[10px] px-1.5 py-0.5 rounded bg-green-500/20 text-green-400",
7888
+ children: "Installed"
7889
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
7890
+ className: "text-xs text-gray-500",
7891
+ children: widget.packageDisplayName
7892
+ })]
7798
7893
  })]
7799
7894
  })
7800
7895
  }, widget.key);
@@ -7826,6 +7921,9 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7826
7921
  }), /*#__PURE__*/jsxRuntime.jsxs("span", {
7827
7922
  className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " text-gray-300"),
7828
7923
  children: ["v", selectedWidget.packageVersion]
7924
+ }), installedPackageNames.has(selectedWidget.packageName) && /*#__PURE__*/jsxRuntime.jsx("span", {
7925
+ className: "text-xs px-2 py-0.5 rounded bg-green-500/20 text-green-400",
7926
+ children: "Installed"
7829
7927
  })]
7830
7928
  })]
7831
7929
  }), /*#__PURE__*/jsxRuntime.jsx("hr", {
@@ -7903,7 +8001,7 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7903
8001
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
7904
8002
  className: "flex flex-col w-full h-full overflow-clip",
7905
8003
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
7906
- className: "flex flex-row w-full h-full space-x-4 overflow-clip p-6",
8004
+ className: "flex flex-row w-full flex-1 min-h-0 space-x-4 overflow-clip p-6",
7907
8005
  children: [/*#__PURE__*/jsxRuntime.jsx("div", {
7908
8006
  className: "hidden lg:flex flex-col flex-shrink h-full rounded font-medium text-gray-400 w-1/3",
7909
8007
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
@@ -7919,70 +8017,78 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7919
8017
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
7920
8018
  className: "flex flex-col w-full lg:w-2/3 h-full overflow-hidden",
7921
8019
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
7922
- className: "flex flex-row items-center space-x-3 mb-4 px-2",
7923
- children: [/*#__PURE__*/jsxRuntime.jsx("input", {
7924
- type: "text",
7925
- placeholder: selectedSource === "Discover" ? "Search packages and widgets..." : "Search widgets...",
7926
- value: searchQuery,
7927
- onChange: function onChange(e) {
7928
- return setSearchQuery(e.target.value);
7929
- },
7930
- className: "flex-1 px-3 py-2 rounded text-sm ".concat(currentTheme["bg-primary-medium"], " ").concat(currentTheme["text-primary-light"], " ").concat(currentTheme["border-primary-medium"], " border focus:outline-none focus:ring-2 focus:ring-blue-500")
7931
- }), /*#__PURE__*/jsxRuntime.jsxs("select", {
7932
- value: selectedAuthor,
7933
- onChange: function onChange(e) {
7934
- return setSelectedAuthor(e.target.value);
7935
- },
7936
- className: "px-3 py-2 rounded text-sm ".concat(currentTheme["bg-primary-medium"], " ").concat(currentTheme["text-primary-light"], " ").concat(currentTheme["border-primary-medium"], " border focus:outline-none focus:ring-2 focus:ring-blue-500"),
7937
- children: [/*#__PURE__*/jsxRuntime.jsx("option", {
7938
- value: "all",
7939
- children: "All Authors"
7940
- }), getUniqueAuthors().map(function (author) {
7941
- return /*#__PURE__*/jsxRuntime.jsx("option", {
7942
- value: author,
7943
- children: author
7944
- }, author);
7945
- })]
7946
- }), selectedSource === "Installed" && /*#__PURE__*/jsxRuntime.jsxs("select", {
7947
- value: selectedProvider,
7948
- onChange: function onChange(e) {
7949
- return setSelectedProvider(e.target.value);
7950
- },
7951
- className: "px-3 py-2 rounded text-sm ".concat(currentTheme["bg-primary-medium"], " ").concat(currentTheme["text-primary-light"], " ").concat(currentTheme["border-primary-medium"], " border focus:outline-none focus:ring-2 focus:ring-blue-500"),
7952
- children: [/*#__PURE__*/jsxRuntime.jsx("option", {
7953
- value: "all",
7954
- children: "All Providers"
7955
- }), getUniqueProviders().map(function (provider) {
7956
- return /*#__PURE__*/jsxRuntime.jsx("option", {
7957
- value: provider,
7958
- children: provider === "none" ? "No Providers" : provider
7959
- }, provider);
7960
- })]
7961
- }), selectedSource === "Discover" && /*#__PURE__*/jsxRuntime.jsxs("select", {
7962
- value: registryViewMode,
7963
- onChange: function onChange(e) {
7964
- return setRegistryViewMode(e.target.value);
7965
- },
7966
- className: "px-3 py-2 rounded text-sm ".concat(currentTheme["bg-primary-medium"], " ").concat(currentTheme["text-primary-light"], " ").concat(currentTheme["border-primary-medium"], " border focus:outline-none focus:ring-2 focus:ring-blue-500"),
7967
- children: [/*#__PURE__*/jsxRuntime.jsx("option", {
7968
- value: "packages",
7969
- children: "Packages"
7970
- }), /*#__PURE__*/jsxRuntime.jsx("option", {
7971
- value: "widgets",
7972
- children: "Widgets"
8020
+ className: "flex flex-col gap-3 mb-4 px-2",
8021
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
8022
+ className: "flex flex-row items-center gap-3",
8023
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
8024
+ className: "flex bg-white/5 rounded-md p-0.5 flex-shrink-0",
8025
+ children: [/*#__PURE__*/jsxRuntime.jsx("button", {
8026
+ type: "button",
8027
+ onClick: function onClick() {
8028
+ return setSelectedSource("Installed");
8029
+ },
8030
+ className: "px-3 py-1.5 rounded text-sm transition-colors ".concat(selectedSource === "Installed" ? "bg-white/10 font-medium opacity-90" : "opacity-50 hover:opacity-70"),
8031
+ children: "Installed"
8032
+ }), /*#__PURE__*/jsxRuntime.jsx("button", {
8033
+ type: "button",
8034
+ onClick: function onClick() {
8035
+ return setSelectedSource("Discover");
8036
+ },
8037
+ className: "px-3 py-1.5 rounded text-sm transition-colors ".concat(selectedSource === "Discover" ? "bg-white/10 font-medium opacity-90" : "opacity-50 hover:opacity-70"),
8038
+ children: "Discover"
8039
+ })]
8040
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.SearchInput, {
8041
+ value: searchQuery,
8042
+ onChange: setSearchQuery,
8043
+ placeholder: selectedSource === "Discover" ? "Search packages and widgets..." : "Search widgets...",
8044
+ className: "flex-1",
8045
+ inputClassName: "py-1.5 text-sm"
7973
8046
  })]
7974
- }), /*#__PURE__*/jsxRuntime.jsxs("select", {
7975
- value: selectedSource,
7976
- onChange: function onChange(e) {
7977
- return setSelectedSource(e.target.value);
7978
- },
7979
- className: "px-3 py-2 rounded text-sm ".concat(currentTheme["bg-primary-medium"], " ").concat(currentTheme["text-primary-light"], " ").concat(currentTheme["border-primary-medium"], " border focus:outline-none focus:ring-2 focus:ring-blue-500"),
7980
- children: [/*#__PURE__*/jsxRuntime.jsx("option", {
7981
- value: "Installed",
7982
- children: "Installed"
7983
- }), /*#__PURE__*/jsxRuntime.jsx("option", {
7984
- value: "Discover",
7985
- children: "Discover"
8047
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
8048
+ className: "flex flex-row items-center gap-2",
8049
+ children: [/*#__PURE__*/jsxRuntime.jsxs("select", {
8050
+ value: selectedAuthor,
8051
+ onChange: function onChange(e) {
8052
+ return setSelectedAuthor(e.target.value);
8053
+ },
8054
+ className: "px-2 py-1 rounded text-xs bg-transparent border ".concat(currentTheme["border-primary-medium"] || "border-gray-700", " ").concat(currentTheme["text-primary-light"] || "text-gray-300", " focus:outline-none appearance-none cursor-pointer"),
8055
+ children: [/*#__PURE__*/jsxRuntime.jsx("option", {
8056
+ value: "all",
8057
+ children: "All Authors"
8058
+ }), getUniqueAuthors().map(function (author) {
8059
+ return /*#__PURE__*/jsxRuntime.jsx("option", {
8060
+ value: author,
8061
+ children: author
8062
+ }, author);
8063
+ })]
8064
+ }), selectedSource === "Installed" && /*#__PURE__*/jsxRuntime.jsxs("select", {
8065
+ value: selectedProvider,
8066
+ onChange: function onChange(e) {
8067
+ return setSelectedProvider(e.target.value);
8068
+ },
8069
+ className: "px-2 py-1 rounded text-xs bg-transparent border ".concat(currentTheme["border-primary-medium"] || "border-gray-700", " ").concat(currentTheme["text-primary-light"] || "text-gray-300", " focus:outline-none appearance-none cursor-pointer"),
8070
+ children: [/*#__PURE__*/jsxRuntime.jsx("option", {
8071
+ value: "all",
8072
+ children: "All Providers"
8073
+ }), getUniqueProviders().map(function (provider) {
8074
+ return /*#__PURE__*/jsxRuntime.jsx("option", {
8075
+ value: provider,
8076
+ children: provider === "none" ? "No Providers" : provider
8077
+ }, provider);
8078
+ })]
8079
+ }), selectedSource === "Discover" && /*#__PURE__*/jsxRuntime.jsxs("select", {
8080
+ value: registryViewMode,
8081
+ onChange: function onChange(e) {
8082
+ return setRegistryViewMode(e.target.value);
8083
+ },
8084
+ className: "px-2 py-1 rounded text-xs bg-transparent border ".concat(currentTheme["border-primary-medium"] || "border-gray-700", " ").concat(currentTheme["text-primary-light"] || "text-gray-300", " focus:outline-none appearance-none cursor-pointer"),
8085
+ children: [/*#__PURE__*/jsxRuntime.jsx("option", {
8086
+ value: "packages",
8087
+ children: "Packages"
8088
+ }), /*#__PURE__*/jsxRuntime.jsx("option", {
8089
+ value: "widgets",
8090
+ children: "Widgets"
8091
+ })]
7986
8092
  })]
7987
8093
  })]
7988
8094
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
@@ -8013,7 +8119,7 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
8013
8119
  className: "px-2 py-1 mb-2 border-b ".concat(currentTheme["border-primary-medium"]),
8014
8120
  children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Paragraph, {
8015
8121
  className: "text-xs font-semibold text-gray-400",
8016
- children: "RECENT WIDGETS"
8122
+ children: "RECENT"
8017
8123
  })
8018
8124
  }), recentWidgets.map(function (widget) {
8019
8125
  return /*#__PURE__*/jsxRuntime.jsx(DashReact.MenuItem3, {
@@ -8022,28 +8128,75 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
8022
8128
  },
8023
8129
  selected: (selectedWidget === null || selectedWidget === void 0 ? void 0 : selectedWidget.key) === widget.key,
8024
8130
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
8025
- className: "flex items-center space-x-2 w-full",
8026
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
8027
- className: "text-xs",
8028
- children: "\uD83D\uDD52"
8029
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
8030
- className: "text-base font-medium flex-1",
8031
- children: widget.name
8131
+ className: "flex items-center gap-2 w-full",
8132
+ children: [/*#__PURE__*/jsxRuntime.jsx(WidgetIcon, {
8133
+ icon: widget.icon,
8134
+ className: "h-4 w-4 opacity-60 flex-shrink-0",
8135
+ fallback: "puzzle-piece"
8136
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
8137
+ className: "flex-1 min-w-0",
8138
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
8139
+ className: "text-sm font-medium truncate",
8140
+ children: widget.name
8141
+ }), widget.description && /*#__PURE__*/jsxRuntime.jsx("div", {
8142
+ className: "text-xs opacity-50 truncate",
8143
+ children: widget.description
8144
+ })]
8032
8145
  })]
8033
8146
  })
8034
8147
  }, "recent-".concat(widget.key));
8035
8148
  })]
8036
- }), filteredWidgets.map(function (widget) {
8037
- return /*#__PURE__*/jsxRuntime.jsx(DashReact.MenuItem3, {
8038
- onClick: function onClick() {
8039
- return handleWidgetSelect(widget);
8040
- },
8041
- selected: (selectedWidget === null || selectedWidget === void 0 ? void 0 : selectedWidget.key) === widget.key,
8042
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
8043
- className: "text-base font-medium",
8044
- children: widget.name
8045
- })
8046
- }, widget.key);
8149
+ }), installedGroupNames.map(function (groupName) {
8150
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
8151
+ className: "mb-1",
8152
+ children: [/*#__PURE__*/jsxRuntime.jsxs("button", {
8153
+ type: "button",
8154
+ onClick: function onClick() {
8155
+ return toggleGroup(groupName);
8156
+ },
8157
+ className: "flex items-center gap-1.5 w-full px-2 py-1.5 text-xs font-semibold text-gray-400 hover:text-gray-300 transition-colors",
8158
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
8159
+ className: "text-[10px] opacity-60",
8160
+ children: expandedGroups.has(groupName) ? "\u25BC" : "\u25B6"
8161
+ }), groupName, /*#__PURE__*/jsxRuntime.jsx("span", {
8162
+ className: "opacity-40 ml-auto",
8163
+ children: groupedInstalledWidgets[groupName].length
8164
+ })]
8165
+ }), expandedGroups.has(groupName) && groupedInstalledWidgets[groupName].map(function (widget) {
8166
+ var _widget$providers3;
8167
+ return /*#__PURE__*/jsxRuntime.jsx(DashReact.MenuItem3, {
8168
+ onClick: function onClick() {
8169
+ return handleWidgetSelect(widget);
8170
+ },
8171
+ selected: (selectedWidget === null || selectedWidget === void 0 ? void 0 : selectedWidget.key) === widget.key,
8172
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
8173
+ className: "flex items-center gap-2 w-full",
8174
+ children: [/*#__PURE__*/jsxRuntime.jsx(WidgetIcon, {
8175
+ icon: widget.icon,
8176
+ className: "h-4 w-4 opacity-60 flex-shrink-0",
8177
+ fallback: "puzzle-piece"
8178
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
8179
+ className: "flex-1 min-w-0",
8180
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
8181
+ className: "text-sm font-medium truncate",
8182
+ children: widget.name
8183
+ }), widget.description && /*#__PURE__*/jsxRuntime.jsx("div", {
8184
+ className: "text-xs opacity-50 truncate",
8185
+ children: widget.description
8186
+ }), ((_widget$providers3 = widget.providers) === null || _widget$providers3 === void 0 ? void 0 : _widget$providers3.length) > 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
8187
+ className: "flex flex-wrap gap-1 mt-0.5",
8188
+ children: widget.providers.map(function (p) {
8189
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
8190
+ className: "text-[10px] px-1.5 py-0.5 rounded bg-blue-500/20 text-blue-300",
8191
+ children: p.type
8192
+ }, p.type);
8193
+ })
8194
+ })]
8195
+ })]
8196
+ })
8197
+ }, widget.key);
8198
+ })]
8199
+ }, groupName);
8047
8200
  })]
8048
8201
  })
8049
8202
  }), /*#__PURE__*/jsxRuntime.jsx("div", {
@@ -8185,10 +8338,12 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
8185
8338
  },
8186
8339
  className: "w-full px-3 py-2 rounded text-sm ".concat(currentTheme["bg-primary-medium"], " ").concat(currentTheme["text-primary-light"], " ").concat(currentTheme["border-primary-medium"], " border"),
8187
8340
  children: config.options && config.options.map(function (opt) {
8341
+ var optValue = _typeof(opt) === "object" ? opt.value : opt;
8342
+ var optLabel = _typeof(opt) === "object" ? opt.displayName || opt.value : opt;
8188
8343
  return /*#__PURE__*/jsxRuntime.jsx("option", {
8189
- value: opt,
8190
- children: opt
8191
- }, opt);
8344
+ value: optValue,
8345
+ children: optLabel
8346
+ }, optValue);
8192
8347
  })
8193
8348
  }), config.instructions && /*#__PURE__*/jsxRuntime.jsx("p", {
8194
8349
  className: "text-xs text-gray-400",
@@ -8232,7 +8387,7 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
8232
8387
  padding: "py-2 px-4",
8233
8388
  onClick: onClose
8234
8389
  }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
8235
- title: selectedWidget !== null && selectedWidget !== void 0 && selectedWidget.isRegistry ? isInstalling ? "Installing..." : "Install Package" : "Add to Dashboard",
8390
+ title: selectedWidget !== null && selectedWidget !== void 0 && selectedWidget.isRegistry ? isInstalling ? "Installing..." : installedPackageNames.has(selectedWidget.packageName) ? "Already Installed" : "Install Package" : "Add to Dashboard",
8236
8391
  bgColor: "bg-gray-800",
8237
8392
  hoverBackgroundColor: isAddButtonEnabled() && !isInstalling ? selectedWidget !== null && selectedWidget !== void 0 && selectedWidget.isRegistry ? "hover:bg-blue-700" : "hover:bg-green-700" : "",
8238
8393
  textSize: "text-lg",