@trops/dash-core 0.1.27 → 0.1.28

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
@@ -7161,39 +7161,45 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7161
7161
  isCreatingProvider = _useState24[0],
7162
7162
  setIsCreatingProvider = _useState24[1];
7163
7163
 
7164
- // Registry state
7165
- var _useState25 = useState(false),
7164
+ // Installed widget grouping
7165
+ var _useState25 = useState(new Set()),
7166
7166
  _useState26 = _slicedToArray(_useState25, 2),
7167
- isLoadingRegistry = _useState26[0],
7168
- setIsLoadingRegistry = _useState26[1];
7169
- var _useState27 = useState(null),
7167
+ expandedGroups = _useState26[0],
7168
+ setExpandedGroups = _useState26[1];
7169
+
7170
+ // Registry state
7171
+ var _useState27 = useState(false),
7170
7172
  _useState28 = _slicedToArray(_useState27, 2),
7171
- registryError = _useState28[0],
7172
- setRegistryError = _useState28[1];
7173
- var _useState29 = useState([]),
7173
+ isLoadingRegistry = _useState28[0],
7174
+ setIsLoadingRegistry = _useState28[1];
7175
+ var _useState29 = useState(null),
7174
7176
  _useState30 = _slicedToArray(_useState29, 2),
7175
- registryPackages = _useState30[0],
7176
- setRegistryPackages = _useState30[1];
7177
- var _useState31 = useState("packages"),
7177
+ registryError = _useState30[0],
7178
+ setRegistryError = _useState30[1];
7179
+ var _useState31 = useState([]),
7178
7180
  _useState32 = _slicedToArray(_useState31, 2),
7179
- registryViewMode = _useState32[0],
7180
- setRegistryViewMode = _useState32[1]; // "packages" | "widgets"
7181
- var _useState33 = useState(new Set()),
7181
+ registryPackages = _useState32[0],
7182
+ setRegistryPackages = _useState32[1];
7183
+ var _useState33 = useState("packages"),
7182
7184
  _useState34 = _slicedToArray(_useState33, 2),
7183
- expandedPackages = _useState34[0],
7184
- setExpandedPackages = _useState34[1];
7185
- var _useState35 = useState(null),
7185
+ registryViewMode = _useState34[0],
7186
+ setRegistryViewMode = _useState34[1]; // "packages" | "widgets"
7187
+ var _useState35 = useState(new Set()),
7186
7188
  _useState36 = _slicedToArray(_useState35, 2),
7187
- selectedPackage = _useState36[0],
7188
- setSelectedPackage = _useState36[1];
7189
- var _useState37 = useState(false),
7189
+ expandedPackages = _useState36[0],
7190
+ setExpandedPackages = _useState36[1];
7191
+ var _useState37 = useState(null),
7190
7192
  _useState38 = _slicedToArray(_useState37, 2),
7191
- isInstalling = _useState38[0],
7192
- setIsInstalling = _useState38[1];
7193
- var _useState39 = useState(null),
7193
+ selectedPackage = _useState38[0],
7194
+ setSelectedPackage = _useState38[1];
7195
+ var _useState39 = useState(false),
7194
7196
  _useState40 = _slicedToArray(_useState39, 2),
7195
- installError = _useState40[0],
7196
- setInstallError = _useState40[1];
7197
+ isInstalling = _useState40[0],
7198
+ setIsInstalling = _useState40[1];
7199
+ var _useState41 = useState(null),
7200
+ _useState42 = _slicedToArray(_useState41, 2),
7201
+ installError = _useState42[0],
7202
+ setInstallError = _useState42[1];
7197
7203
 
7198
7204
  // Phase 3: Recent Widgets - localStorage functions
7199
7205
  var loadRecentWidgets = function loadRecentWidgets() {
@@ -7265,6 +7271,7 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7265
7271
  setSearchQuery("");
7266
7272
  setSelectedAuthor("all");
7267
7273
  setSelectedProvider("all");
7274
+ setExpandedGroups(new Set()); // Start with all groups collapsed
7268
7275
  }
7269
7276
  // eslint-disable-next-line react-hooks/exhaustive-deps
7270
7277
  }, [isOpen]);
@@ -7418,6 +7425,42 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7418
7425
  };
7419
7426
  var filteredWidgets = getFilteredWidgets();
7420
7427
 
7428
+ // Set of installed package names for "Installed" badge in Discover mode
7429
+ var installedPackageNames = useMemo(function () {
7430
+ var names = new Set();
7431
+ var map = ComponentManager.map();
7432
+ Object.values(map).forEach(function (widget) {
7433
+ if (widget._sourcePackage) names.add(widget._sourcePackage);
7434
+ });
7435
+ return names;
7436
+ }, [widgets]);
7437
+
7438
+ // Group installed widgets by package > author > "Other"
7439
+ var groupedInstalledWidgets = useMemo(function () {
7440
+ if (selectedSource !== "Installed") return {};
7441
+ var groups = {};
7442
+ filteredWidgets.forEach(function (widget) {
7443
+ var group = widget["package"] || widget.author || "Other";
7444
+ if (!groups[group]) groups[group] = [];
7445
+ groups[group].push(widget);
7446
+ });
7447
+ return groups;
7448
+ }, [filteredWidgets, selectedSource]);
7449
+ var installedGroupNames = useMemo(function () {
7450
+ return Object.keys(groupedInstalledWidgets).sort();
7451
+ }, [groupedInstalledWidgets]);
7452
+ var toggleGroup = function toggleGroup(groupName) {
7453
+ setExpandedGroups(function (prev) {
7454
+ var next = new Set(prev);
7455
+ if (next.has(groupName)) {
7456
+ next["delete"](groupName);
7457
+ } else {
7458
+ next.add(groupName);
7459
+ }
7460
+ return next;
7461
+ });
7462
+ };
7463
+
7421
7464
  // Group filtered widgets by package (for package view in Discover)
7422
7465
  var getGroupedByPackage = function getGroupedByPackage() {
7423
7466
  var groups = {};
@@ -7618,8 +7661,10 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7618
7661
  var isAddButtonEnabled = function isAddButtonEnabled() {
7619
7662
  if (!selectedWidget) return false;
7620
7663
 
7621
- // For registry widgets, always enabled (install action)
7622
- if (selectedWidget.isRegistry) return true;
7664
+ // For registry widgets, enabled unless already installed
7665
+ if (selectedWidget.isRegistry) {
7666
+ return !installedPackageNames.has(selectedWidget.packageName);
7667
+ }
7623
7668
 
7624
7669
  // Check providers: all required providers must be selected
7625
7670
  var hasRequiredProviders = selectedWidget.providers ? selectedWidget.providers.filter(function (p) {
@@ -7724,31 +7769,56 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7724
7769
  children: /*#__PURE__*/jsx("div", {
7725
7770
  className: "flex items-center justify-between w-full",
7726
7771
  children: /*#__PURE__*/jsxs("div", {
7727
- className: "flex items-center space-x-2 flex-1 min-w-0",
7772
+ className: "flex items-center gap-2 flex-1 min-w-0",
7728
7773
  children: [/*#__PURE__*/jsx("span", {
7729
7774
  className: "text-xs text-gray-500",
7730
7775
  children: expandedPackages.has(group.name) ? "\u25BC" : "\u25B6"
7731
7776
  }), /*#__PURE__*/jsxs("div", {
7732
7777
  className: "min-w-0 flex-1",
7733
7778
  children: [/*#__PURE__*/jsx("div", {
7734
- className: "text-base font-medium truncate",
7779
+ className: "text-sm font-medium truncate",
7735
7780
  children: group.displayName
7736
7781
  }), /*#__PURE__*/jsxs("div", {
7737
7782
  className: "text-xs text-gray-500",
7738
7783
  children: [group.widgets.length, " widget", group.widgets.length !== 1 ? "s" : "", " \xB7 v", group.version]
7739
7784
  })]
7785
+ }), installedPackageNames.has(group.name) && /*#__PURE__*/jsx("span", {
7786
+ className: "text-[10px] px-1.5 py-0.5 rounded bg-green-500/20 text-green-400 flex-shrink-0",
7787
+ children: "Installed"
7740
7788
  })]
7741
7789
  })
7742
7790
  })
7743
7791
  }), expandedPackages.has(group.name) && group.widgets.map(function (widget) {
7792
+ var _widget$providers;
7744
7793
  return /*#__PURE__*/jsx(MenuItem3, {
7745
7794
  onClick: function onClick() {
7746
7795
  return handleWidgetSelect(widget);
7747
7796
  },
7748
7797
  selected: (selectedWidget === null || selectedWidget === void 0 ? void 0 : selectedWidget.key) === widget.key,
7749
- children: /*#__PURE__*/jsx("div", {
7750
- className: "pl-6 text-sm",
7751
- children: widget.name
7798
+ children: /*#__PURE__*/jsxs("div", {
7799
+ className: "flex items-center gap-2 pl-6 w-full",
7800
+ children: [/*#__PURE__*/jsx(WidgetIcon, {
7801
+ icon: widget.icon,
7802
+ className: "h-4 w-4 opacity-60 flex-shrink-0",
7803
+ fallback: "puzzle-piece"
7804
+ }), /*#__PURE__*/jsxs("div", {
7805
+ className: "flex-1 min-w-0",
7806
+ children: [/*#__PURE__*/jsx("div", {
7807
+ className: "text-sm font-medium truncate",
7808
+ children: widget.name
7809
+ }), widget.description && /*#__PURE__*/jsx("div", {
7810
+ className: "text-xs opacity-50 truncate",
7811
+ children: widget.description
7812
+ }), ((_widget$providers = widget.providers) === null || _widget$providers === void 0 ? void 0 : _widget$providers.length) > 0 && /*#__PURE__*/jsx("div", {
7813
+ className: "flex flex-wrap gap-1 mt-0.5",
7814
+ children: widget.providers.map(function (p) {
7815
+ return /*#__PURE__*/jsx("span", {
7816
+ className: "text-[10px] px-1.5 py-0.5 rounded bg-blue-500/20 text-blue-300",
7817
+ children: p.type
7818
+ }, p.type);
7819
+ })
7820
+ })]
7821
+ })]
7752
7822
  })
7753
7823
  }, widget.key);
7754
7824
  })]
@@ -7763,19 +7833,44 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7763
7833
  padding: true,
7764
7834
  height: "h-full",
7765
7835
  children: filteredWidgets.map(function (widget) {
7836
+ var _widget$providers2;
7766
7837
  return /*#__PURE__*/jsx(MenuItem3, {
7767
7838
  onClick: function onClick() {
7768
7839
  return handleWidgetSelect(widget);
7769
7840
  },
7770
7841
  selected: (selectedWidget === null || selectedWidget === void 0 ? void 0 : selectedWidget.key) === widget.key,
7771
7842
  children: /*#__PURE__*/jsxs("div", {
7772
- className: "flex items-center justify-between w-full",
7773
- children: [/*#__PURE__*/jsx("div", {
7774
- className: "text-base font-medium",
7775
- children: widget.name
7776
- }), /*#__PURE__*/jsx("span", {
7777
- className: "text-xs text-gray-500",
7778
- children: widget.packageDisplayName
7843
+ className: "flex items-center gap-2 w-full",
7844
+ children: [/*#__PURE__*/jsx(WidgetIcon, {
7845
+ icon: widget.icon,
7846
+ className: "h-4 w-4 opacity-60 flex-shrink-0",
7847
+ fallback: "puzzle-piece"
7848
+ }), /*#__PURE__*/jsxs("div", {
7849
+ className: "flex-1 min-w-0",
7850
+ children: [/*#__PURE__*/jsx("div", {
7851
+ className: "text-sm font-medium truncate",
7852
+ children: widget.name
7853
+ }), widget.description && /*#__PURE__*/jsx("div", {
7854
+ className: "text-xs opacity-50 truncate",
7855
+ children: widget.description
7856
+ }), ((_widget$providers2 = widget.providers) === null || _widget$providers2 === void 0 ? void 0 : _widget$providers2.length) > 0 && /*#__PURE__*/jsx("div", {
7857
+ className: "flex flex-wrap gap-1 mt-0.5",
7858
+ children: widget.providers.map(function (p) {
7859
+ return /*#__PURE__*/jsx("span", {
7860
+ className: "text-[10px] px-1.5 py-0.5 rounded bg-blue-500/20 text-blue-300",
7861
+ children: p.type
7862
+ }, p.type);
7863
+ })
7864
+ })]
7865
+ }), /*#__PURE__*/jsxs("div", {
7866
+ className: "flex items-center gap-1.5 flex-shrink-0",
7867
+ children: [installedPackageNames.has(widget.packageName) && /*#__PURE__*/jsx("span", {
7868
+ className: "text-[10px] px-1.5 py-0.5 rounded bg-green-500/20 text-green-400",
7869
+ children: "Installed"
7870
+ }), /*#__PURE__*/jsx("span", {
7871
+ className: "text-xs text-gray-500",
7872
+ children: widget.packageDisplayName
7873
+ })]
7779
7874
  })]
7780
7875
  })
7781
7876
  }, widget.key);
@@ -7807,6 +7902,9 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7807
7902
  }), /*#__PURE__*/jsxs("span", {
7808
7903
  className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " text-gray-300"),
7809
7904
  children: ["v", selectedWidget.packageVersion]
7905
+ }), installedPackageNames.has(selectedWidget.packageName) && /*#__PURE__*/jsx("span", {
7906
+ className: "text-xs px-2 py-0.5 rounded bg-green-500/20 text-green-400",
7907
+ children: "Installed"
7810
7908
  })]
7811
7909
  })]
7812
7910
  }), /*#__PURE__*/jsx("hr", {
@@ -7900,70 +7998,78 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7900
7998
  }), /*#__PURE__*/jsxs("div", {
7901
7999
  className: "flex flex-col w-full lg:w-2/3 h-full overflow-hidden",
7902
8000
  children: [/*#__PURE__*/jsxs("div", {
7903
- className: "flex flex-row items-center space-x-3 mb-4 px-2",
7904
- children: [/*#__PURE__*/jsx("input", {
7905
- type: "text",
7906
- placeholder: selectedSource === "Discover" ? "Search packages and widgets..." : "Search widgets...",
7907
- value: searchQuery,
7908
- onChange: function onChange(e) {
7909
- return setSearchQuery(e.target.value);
7910
- },
7911
- 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")
7912
- }), /*#__PURE__*/jsxs("select", {
7913
- value: selectedAuthor,
7914
- onChange: function onChange(e) {
7915
- return setSelectedAuthor(e.target.value);
7916
- },
7917
- 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"),
7918
- children: [/*#__PURE__*/jsx("option", {
7919
- value: "all",
7920
- children: "All Authors"
7921
- }), getUniqueAuthors().map(function (author) {
7922
- return /*#__PURE__*/jsx("option", {
7923
- value: author,
7924
- children: author
7925
- }, author);
7926
- })]
7927
- }), selectedSource === "Installed" && /*#__PURE__*/jsxs("select", {
7928
- value: selectedProvider,
7929
- onChange: function onChange(e) {
7930
- return setSelectedProvider(e.target.value);
7931
- },
7932
- 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"),
7933
- children: [/*#__PURE__*/jsx("option", {
7934
- value: "all",
7935
- children: "All Providers"
7936
- }), getUniqueProviders().map(function (provider) {
7937
- return /*#__PURE__*/jsx("option", {
7938
- value: provider,
7939
- children: provider === "none" ? "No Providers" : provider
7940
- }, provider);
7941
- })]
7942
- }), selectedSource === "Discover" && /*#__PURE__*/jsxs("select", {
7943
- value: registryViewMode,
7944
- onChange: function onChange(e) {
7945
- return setRegistryViewMode(e.target.value);
7946
- },
7947
- 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"),
7948
- children: [/*#__PURE__*/jsx("option", {
7949
- value: "packages",
7950
- children: "Packages"
7951
- }), /*#__PURE__*/jsx("option", {
7952
- value: "widgets",
7953
- children: "Widgets"
8001
+ className: "flex flex-col gap-3 mb-4 px-2",
8002
+ children: [/*#__PURE__*/jsxs("div", {
8003
+ className: "flex flex-row items-center gap-3",
8004
+ children: [/*#__PURE__*/jsxs("div", {
8005
+ className: "flex bg-white/5 rounded-md p-0.5 flex-shrink-0",
8006
+ children: [/*#__PURE__*/jsx("button", {
8007
+ type: "button",
8008
+ onClick: function onClick() {
8009
+ return setSelectedSource("Installed");
8010
+ },
8011
+ 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"),
8012
+ children: "Installed"
8013
+ }), /*#__PURE__*/jsx("button", {
8014
+ type: "button",
8015
+ onClick: function onClick() {
8016
+ return setSelectedSource("Discover");
8017
+ },
8018
+ 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"),
8019
+ children: "Discover"
8020
+ })]
8021
+ }), /*#__PURE__*/jsx(SearchInput, {
8022
+ value: searchQuery,
8023
+ onChange: setSearchQuery,
8024
+ placeholder: selectedSource === "Discover" ? "Search packages and widgets..." : "Search widgets...",
8025
+ className: "flex-1",
8026
+ inputClassName: "py-1.5 text-sm"
7954
8027
  })]
7955
- }), /*#__PURE__*/jsxs("select", {
7956
- value: selectedSource,
7957
- onChange: function onChange(e) {
7958
- return setSelectedSource(e.target.value);
7959
- },
7960
- 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"),
7961
- children: [/*#__PURE__*/jsx("option", {
7962
- value: "Installed",
7963
- children: "Installed"
7964
- }), /*#__PURE__*/jsx("option", {
7965
- value: "Discover",
7966
- children: "Discover"
8028
+ }), /*#__PURE__*/jsxs("div", {
8029
+ className: "flex flex-row items-center gap-2",
8030
+ children: [/*#__PURE__*/jsxs("select", {
8031
+ value: selectedAuthor,
8032
+ onChange: function onChange(e) {
8033
+ return setSelectedAuthor(e.target.value);
8034
+ },
8035
+ 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"),
8036
+ children: [/*#__PURE__*/jsx("option", {
8037
+ value: "all",
8038
+ children: "All Authors"
8039
+ }), getUniqueAuthors().map(function (author) {
8040
+ return /*#__PURE__*/jsx("option", {
8041
+ value: author,
8042
+ children: author
8043
+ }, author);
8044
+ })]
8045
+ }), selectedSource === "Installed" && /*#__PURE__*/jsxs("select", {
8046
+ value: selectedProvider,
8047
+ onChange: function onChange(e) {
8048
+ return setSelectedProvider(e.target.value);
8049
+ },
8050
+ 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"),
8051
+ children: [/*#__PURE__*/jsx("option", {
8052
+ value: "all",
8053
+ children: "All Providers"
8054
+ }), getUniqueProviders().map(function (provider) {
8055
+ return /*#__PURE__*/jsx("option", {
8056
+ value: provider,
8057
+ children: provider === "none" ? "No Providers" : provider
8058
+ }, provider);
8059
+ })]
8060
+ }), selectedSource === "Discover" && /*#__PURE__*/jsxs("select", {
8061
+ value: registryViewMode,
8062
+ onChange: function onChange(e) {
8063
+ return setRegistryViewMode(e.target.value);
8064
+ },
8065
+ 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"),
8066
+ children: [/*#__PURE__*/jsx("option", {
8067
+ value: "packages",
8068
+ children: "Packages"
8069
+ }), /*#__PURE__*/jsx("option", {
8070
+ value: "widgets",
8071
+ children: "Widgets"
8072
+ })]
7967
8073
  })]
7968
8074
  })]
7969
8075
  }), /*#__PURE__*/jsxs("div", {
@@ -7994,7 +8100,7 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7994
8100
  className: "px-2 py-1 mb-2 border-b ".concat(currentTheme["border-primary-medium"]),
7995
8101
  children: /*#__PURE__*/jsx(Paragraph, {
7996
8102
  className: "text-xs font-semibold text-gray-400",
7997
- children: "RECENT WIDGETS"
8103
+ children: "RECENT"
7998
8104
  })
7999
8105
  }), recentWidgets.map(function (widget) {
8000
8106
  return /*#__PURE__*/jsx(MenuItem3, {
@@ -8003,28 +8109,75 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
8003
8109
  },
8004
8110
  selected: (selectedWidget === null || selectedWidget === void 0 ? void 0 : selectedWidget.key) === widget.key,
8005
8111
  children: /*#__PURE__*/jsxs("div", {
8006
- className: "flex items-center space-x-2 w-full",
8007
- children: [/*#__PURE__*/jsx("span", {
8008
- className: "text-xs",
8009
- children: "\uD83D\uDD52"
8010
- }), /*#__PURE__*/jsx("div", {
8011
- className: "text-base font-medium flex-1",
8012
- children: widget.name
8112
+ className: "flex items-center gap-2 w-full",
8113
+ children: [/*#__PURE__*/jsx(WidgetIcon, {
8114
+ icon: widget.icon,
8115
+ className: "h-4 w-4 opacity-60 flex-shrink-0",
8116
+ fallback: "puzzle-piece"
8117
+ }), /*#__PURE__*/jsxs("div", {
8118
+ className: "flex-1 min-w-0",
8119
+ children: [/*#__PURE__*/jsx("div", {
8120
+ className: "text-sm font-medium truncate",
8121
+ children: widget.name
8122
+ }), widget.description && /*#__PURE__*/jsx("div", {
8123
+ className: "text-xs opacity-50 truncate",
8124
+ children: widget.description
8125
+ })]
8013
8126
  })]
8014
8127
  })
8015
8128
  }, "recent-".concat(widget.key));
8016
8129
  })]
8017
- }), filteredWidgets.map(function (widget) {
8018
- return /*#__PURE__*/jsx(MenuItem3, {
8019
- onClick: function onClick() {
8020
- return handleWidgetSelect(widget);
8021
- },
8022
- selected: (selectedWidget === null || selectedWidget === void 0 ? void 0 : selectedWidget.key) === widget.key,
8023
- children: /*#__PURE__*/jsx("div", {
8024
- className: "text-base font-medium",
8025
- children: widget.name
8026
- })
8027
- }, widget.key);
8130
+ }), installedGroupNames.map(function (groupName) {
8131
+ return /*#__PURE__*/jsxs("div", {
8132
+ className: "mb-1",
8133
+ children: [/*#__PURE__*/jsxs("button", {
8134
+ type: "button",
8135
+ onClick: function onClick() {
8136
+ return toggleGroup(groupName);
8137
+ },
8138
+ 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",
8139
+ children: [/*#__PURE__*/jsx("span", {
8140
+ className: "text-[10px] opacity-60",
8141
+ children: expandedGroups.has(groupName) ? "\u25BC" : "\u25B6"
8142
+ }), groupName, /*#__PURE__*/jsx("span", {
8143
+ className: "opacity-40 ml-auto",
8144
+ children: groupedInstalledWidgets[groupName].length
8145
+ })]
8146
+ }), expandedGroups.has(groupName) && groupedInstalledWidgets[groupName].map(function (widget) {
8147
+ var _widget$providers3;
8148
+ return /*#__PURE__*/jsx(MenuItem3, {
8149
+ onClick: function onClick() {
8150
+ return handleWidgetSelect(widget);
8151
+ },
8152
+ selected: (selectedWidget === null || selectedWidget === void 0 ? void 0 : selectedWidget.key) === widget.key,
8153
+ children: /*#__PURE__*/jsxs("div", {
8154
+ className: "flex items-center gap-2 w-full",
8155
+ children: [/*#__PURE__*/jsx(WidgetIcon, {
8156
+ icon: widget.icon,
8157
+ className: "h-4 w-4 opacity-60 flex-shrink-0",
8158
+ fallback: "puzzle-piece"
8159
+ }), /*#__PURE__*/jsxs("div", {
8160
+ className: "flex-1 min-w-0",
8161
+ children: [/*#__PURE__*/jsx("div", {
8162
+ className: "text-sm font-medium truncate",
8163
+ children: widget.name
8164
+ }), widget.description && /*#__PURE__*/jsx("div", {
8165
+ className: "text-xs opacity-50 truncate",
8166
+ children: widget.description
8167
+ }), ((_widget$providers3 = widget.providers) === null || _widget$providers3 === void 0 ? void 0 : _widget$providers3.length) > 0 && /*#__PURE__*/jsx("div", {
8168
+ className: "flex flex-wrap gap-1 mt-0.5",
8169
+ children: widget.providers.map(function (p) {
8170
+ return /*#__PURE__*/jsx("span", {
8171
+ className: "text-[10px] px-1.5 py-0.5 rounded bg-blue-500/20 text-blue-300",
8172
+ children: p.type
8173
+ }, p.type);
8174
+ })
8175
+ })]
8176
+ })]
8177
+ })
8178
+ }, widget.key);
8179
+ })]
8180
+ }, groupName);
8028
8181
  })]
8029
8182
  })
8030
8183
  }), /*#__PURE__*/jsx("div", {
@@ -8213,7 +8366,7 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
8213
8366
  padding: "py-2 px-4",
8214
8367
  onClick: onClose
8215
8368
  }), /*#__PURE__*/jsx(Button, {
8216
- title: selectedWidget !== null && selectedWidget !== void 0 && selectedWidget.isRegistry ? isInstalling ? "Installing..." : "Install Package" : "Add to Dashboard",
8369
+ title: selectedWidget !== null && selectedWidget !== void 0 && selectedWidget.isRegistry ? isInstalling ? "Installing..." : installedPackageNames.has(selectedWidget.packageName) ? "Already Installed" : "Install Package" : "Add to Dashboard",
8217
8370
  bgColor: "bg-gray-800",
8218
8371
  hoverBackgroundColor: isAddButtonEnabled() && !isInstalling ? selectedWidget !== null && selectedWidget !== void 0 && selectedWidget.isRegistry ? "hover:bg-blue-700" : "hover:bg-green-700" : "",
8219
8372
  textSize: "text-lg",