@trops/dash-core 0.1.26 → 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.js CHANGED
@@ -23,7 +23,6 @@ var _getPrototypeOf = require('@babel/runtime/helpers/getPrototypeOf');
23
23
  var _inherits = require('@babel/runtime/helpers/inherits');
24
24
  var colors = require('tailwindcss/colors');
25
25
  var ReactDOM = require('react-dom');
26
- var dashCore = require('@trops/dash-core');
27
26
  var fontawesomeSvgCore = require('@fortawesome/fontawesome-svg-core');
28
27
  var algoliasearch = require('algoliasearch');
29
28
  var reactInstantsearchHooksWeb = require('react-instantsearch-hooks-web');
@@ -50,7 +49,6 @@ var DashReact__namespace = /*#__PURE__*/_interopNamespaceDefault(DashReact);
50
49
  var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
51
50
  var jsxRuntime__namespace = /*#__PURE__*/_interopNamespaceDefault(jsxRuntime);
52
51
  var ReactDOM__namespace = /*#__PURE__*/_interopNamespaceDefault(ReactDOM);
53
- var dashCore__namespace = /*#__PURE__*/_interopNamespaceDefault(dashCore);
54
52
 
55
53
  function ownKeys$w(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
56
54
  function _objectSpread$w(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$w(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$w(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -7182,39 +7180,45 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7182
7180
  isCreatingProvider = _useState24[0],
7183
7181
  setIsCreatingProvider = _useState24[1];
7184
7182
 
7185
- // Registry state
7186
- var _useState25 = React.useState(false),
7183
+ // Installed widget grouping
7184
+ var _useState25 = React.useState(new Set()),
7187
7185
  _useState26 = _slicedToArray(_useState25, 2),
7188
- isLoadingRegistry = _useState26[0],
7189
- setIsLoadingRegistry = _useState26[1];
7190
- var _useState27 = React.useState(null),
7186
+ expandedGroups = _useState26[0],
7187
+ setExpandedGroups = _useState26[1];
7188
+
7189
+ // Registry state
7190
+ var _useState27 = React.useState(false),
7191
7191
  _useState28 = _slicedToArray(_useState27, 2),
7192
- registryError = _useState28[0],
7193
- setRegistryError = _useState28[1];
7194
- var _useState29 = React.useState([]),
7192
+ isLoadingRegistry = _useState28[0],
7193
+ setIsLoadingRegistry = _useState28[1];
7194
+ var _useState29 = React.useState(null),
7195
7195
  _useState30 = _slicedToArray(_useState29, 2),
7196
- registryPackages = _useState30[0],
7197
- setRegistryPackages = _useState30[1];
7198
- var _useState31 = React.useState("packages"),
7196
+ registryError = _useState30[0],
7197
+ setRegistryError = _useState30[1];
7198
+ var _useState31 = React.useState([]),
7199
7199
  _useState32 = _slicedToArray(_useState31, 2),
7200
- registryViewMode = _useState32[0],
7201
- setRegistryViewMode = _useState32[1]; // "packages" | "widgets"
7202
- var _useState33 = React.useState(new Set()),
7200
+ registryPackages = _useState32[0],
7201
+ setRegistryPackages = _useState32[1];
7202
+ var _useState33 = React.useState("packages"),
7203
7203
  _useState34 = _slicedToArray(_useState33, 2),
7204
- expandedPackages = _useState34[0],
7205
- setExpandedPackages = _useState34[1];
7206
- var _useState35 = React.useState(null),
7204
+ registryViewMode = _useState34[0],
7205
+ setRegistryViewMode = _useState34[1]; // "packages" | "widgets"
7206
+ var _useState35 = React.useState(new Set()),
7207
7207
  _useState36 = _slicedToArray(_useState35, 2),
7208
- selectedPackage = _useState36[0],
7209
- setSelectedPackage = _useState36[1];
7210
- var _useState37 = React.useState(false),
7208
+ expandedPackages = _useState36[0],
7209
+ setExpandedPackages = _useState36[1];
7210
+ var _useState37 = React.useState(null),
7211
7211
  _useState38 = _slicedToArray(_useState37, 2),
7212
- isInstalling = _useState38[0],
7213
- setIsInstalling = _useState38[1];
7214
- var _useState39 = React.useState(null),
7212
+ selectedPackage = _useState38[0],
7213
+ setSelectedPackage = _useState38[1];
7214
+ var _useState39 = React.useState(false),
7215
7215
  _useState40 = _slicedToArray(_useState39, 2),
7216
- installError = _useState40[0],
7217
- 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];
7218
7222
 
7219
7223
  // Phase 3: Recent Widgets - localStorage functions
7220
7224
  var loadRecentWidgets = function loadRecentWidgets() {
@@ -7286,6 +7290,7 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7286
7290
  setSearchQuery("");
7287
7291
  setSelectedAuthor("all");
7288
7292
  setSelectedProvider("all");
7293
+ setExpandedGroups(new Set()); // Start with all groups collapsed
7289
7294
  }
7290
7295
  // eslint-disable-next-line react-hooks/exhaustive-deps
7291
7296
  }, [isOpen]);
@@ -7439,6 +7444,42 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7439
7444
  };
7440
7445
  var filteredWidgets = getFilteredWidgets();
7441
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
+
7442
7483
  // Group filtered widgets by package (for package view in Discover)
7443
7484
  var getGroupedByPackage = function getGroupedByPackage() {
7444
7485
  var groups = {};
@@ -7639,8 +7680,10 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7639
7680
  var isAddButtonEnabled = function isAddButtonEnabled() {
7640
7681
  if (!selectedWidget) return false;
7641
7682
 
7642
- // For registry widgets, always enabled (install action)
7643
- if (selectedWidget.isRegistry) return true;
7683
+ // For registry widgets, enabled unless already installed
7684
+ if (selectedWidget.isRegistry) {
7685
+ return !installedPackageNames.has(selectedWidget.packageName);
7686
+ }
7644
7687
 
7645
7688
  // Check providers: all required providers must be selected
7646
7689
  var hasRequiredProviders = selectedWidget.providers ? selectedWidget.providers.filter(function (p) {
@@ -7745,31 +7788,56 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7745
7788
  children: /*#__PURE__*/jsxRuntime.jsx("div", {
7746
7789
  className: "flex items-center justify-between w-full",
7747
7790
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
7748
- className: "flex items-center space-x-2 flex-1 min-w-0",
7791
+ className: "flex items-center gap-2 flex-1 min-w-0",
7749
7792
  children: [/*#__PURE__*/jsxRuntime.jsx("span", {
7750
7793
  className: "text-xs text-gray-500",
7751
7794
  children: expandedPackages.has(group.name) ? "\u25BC" : "\u25B6"
7752
7795
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
7753
7796
  className: "min-w-0 flex-1",
7754
7797
  children: [/*#__PURE__*/jsxRuntime.jsx("div", {
7755
- className: "text-base font-medium truncate",
7798
+ className: "text-sm font-medium truncate",
7756
7799
  children: group.displayName
7757
7800
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
7758
7801
  className: "text-xs text-gray-500",
7759
7802
  children: [group.widgets.length, " widget", group.widgets.length !== 1 ? "s" : "", " \xB7 v", group.version]
7760
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"
7761
7807
  })]
7762
7808
  })
7763
7809
  })
7764
7810
  }), expandedPackages.has(group.name) && group.widgets.map(function (widget) {
7811
+ var _widget$providers;
7765
7812
  return /*#__PURE__*/jsxRuntime.jsx(DashReact.MenuItem3, {
7766
7813
  onClick: function onClick() {
7767
7814
  return handleWidgetSelect(widget);
7768
7815
  },
7769
7816
  selected: (selectedWidget === null || selectedWidget === void 0 ? void 0 : selectedWidget.key) === widget.key,
7770
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
7771
- className: "pl-6 text-sm",
7772
- 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
+ })]
7773
7841
  })
7774
7842
  }, widget.key);
7775
7843
  })]
@@ -7784,19 +7852,44 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7784
7852
  padding: true,
7785
7853
  height: "h-full",
7786
7854
  children: filteredWidgets.map(function (widget) {
7855
+ var _widget$providers2;
7787
7856
  return /*#__PURE__*/jsxRuntime.jsx(DashReact.MenuItem3, {
7788
7857
  onClick: function onClick() {
7789
7858
  return handleWidgetSelect(widget);
7790
7859
  },
7791
7860
  selected: (selectedWidget === null || selectedWidget === void 0 ? void 0 : selectedWidget.key) === widget.key,
7792
7861
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
7793
- className: "flex items-center justify-between w-full",
7794
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
7795
- className: "text-base font-medium",
7796
- children: widget.name
7797
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
7798
- className: "text-xs text-gray-500",
7799
- 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
+ })]
7800
7893
  })]
7801
7894
  })
7802
7895
  }, widget.key);
@@ -7828,6 +7921,9 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7828
7921
  }), /*#__PURE__*/jsxRuntime.jsxs("span", {
7829
7922
  className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " text-gray-300"),
7830
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"
7831
7927
  })]
7832
7928
  })]
7833
7929
  }), /*#__PURE__*/jsxRuntime.jsx("hr", {
@@ -7921,70 +8017,78 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
7921
8017
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
7922
8018
  className: "flex flex-col w-full lg:w-2/3 h-full overflow-hidden",
7923
8019
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
7924
- className: "flex flex-row items-center space-x-3 mb-4 px-2",
7925
- children: [/*#__PURE__*/jsxRuntime.jsx("input", {
7926
- type: "text",
7927
- placeholder: selectedSource === "Discover" ? "Search packages and widgets..." : "Search widgets...",
7928
- value: searchQuery,
7929
- onChange: function onChange(e) {
7930
- return setSearchQuery(e.target.value);
7931
- },
7932
- 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")
7933
- }), /*#__PURE__*/jsxRuntime.jsxs("select", {
7934
- value: selectedAuthor,
7935
- onChange: function onChange(e) {
7936
- return setSelectedAuthor(e.target.value);
7937
- },
7938
- 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"),
7939
- children: [/*#__PURE__*/jsxRuntime.jsx("option", {
7940
- value: "all",
7941
- children: "All Authors"
7942
- }), getUniqueAuthors().map(function (author) {
7943
- return /*#__PURE__*/jsxRuntime.jsx("option", {
7944
- value: author,
7945
- children: author
7946
- }, author);
7947
- })]
7948
- }), selectedSource === "Installed" && /*#__PURE__*/jsxRuntime.jsxs("select", {
7949
- value: selectedProvider,
7950
- onChange: function onChange(e) {
7951
- return setSelectedProvider(e.target.value);
7952
- },
7953
- 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"),
7954
- children: [/*#__PURE__*/jsxRuntime.jsx("option", {
7955
- value: "all",
7956
- children: "All Providers"
7957
- }), getUniqueProviders().map(function (provider) {
7958
- return /*#__PURE__*/jsxRuntime.jsx("option", {
7959
- value: provider,
7960
- children: provider === "none" ? "No Providers" : provider
7961
- }, provider);
7962
- })]
7963
- }), selectedSource === "Discover" && /*#__PURE__*/jsxRuntime.jsxs("select", {
7964
- value: registryViewMode,
7965
- onChange: function onChange(e) {
7966
- return setRegistryViewMode(e.target.value);
7967
- },
7968
- 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"),
7969
- children: [/*#__PURE__*/jsxRuntime.jsx("option", {
7970
- value: "packages",
7971
- children: "Packages"
7972
- }), /*#__PURE__*/jsxRuntime.jsx("option", {
7973
- value: "widgets",
7974
- 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"
7975
8046
  })]
7976
- }), /*#__PURE__*/jsxRuntime.jsxs("select", {
7977
- value: selectedSource,
7978
- onChange: function onChange(e) {
7979
- return setSelectedSource(e.target.value);
7980
- },
7981
- 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"),
7982
- children: [/*#__PURE__*/jsxRuntime.jsx("option", {
7983
- value: "Installed",
7984
- children: "Installed"
7985
- }), /*#__PURE__*/jsxRuntime.jsx("option", {
7986
- value: "Discover",
7987
- 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
+ })]
7988
8092
  })]
7989
8093
  })]
7990
8094
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
@@ -8015,7 +8119,7 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
8015
8119
  className: "px-2 py-1 mb-2 border-b ".concat(currentTheme["border-primary-medium"]),
8016
8120
  children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Paragraph, {
8017
8121
  className: "text-xs font-semibold text-gray-400",
8018
- children: "RECENT WIDGETS"
8122
+ children: "RECENT"
8019
8123
  })
8020
8124
  }), recentWidgets.map(function (widget) {
8021
8125
  return /*#__PURE__*/jsxRuntime.jsx(DashReact.MenuItem3, {
@@ -8024,28 +8128,75 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
8024
8128
  },
8025
8129
  selected: (selectedWidget === null || selectedWidget === void 0 ? void 0 : selectedWidget.key) === widget.key,
8026
8130
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
8027
- className: "flex items-center space-x-2 w-full",
8028
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
8029
- className: "text-xs",
8030
- children: "\uD83D\uDD52"
8031
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
8032
- className: "text-base font-medium flex-1",
8033
- 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
+ })]
8034
8145
  })]
8035
8146
  })
8036
8147
  }, "recent-".concat(widget.key));
8037
8148
  })]
8038
- }), filteredWidgets.map(function (widget) {
8039
- return /*#__PURE__*/jsxRuntime.jsx(DashReact.MenuItem3, {
8040
- onClick: function onClick() {
8041
- return handleWidgetSelect(widget);
8042
- },
8043
- selected: (selectedWidget === null || selectedWidget === void 0 ? void 0 : selectedWidget.key) === widget.key,
8044
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
8045
- className: "text-base font-medium",
8046
- children: widget.name
8047
- })
8048
- }, 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);
8049
8200
  })]
8050
8201
  })
8051
8202
  }), /*#__PURE__*/jsxRuntime.jsx("div", {
@@ -8234,7 +8385,7 @@ var EnhancedWidgetDropdown = function EnhancedWidgetDropdown(_ref) {
8234
8385
  padding: "py-2 px-4",
8235
8386
  onClick: onClose
8236
8387
  }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
8237
- title: selectedWidget !== null && selectedWidget !== void 0 && selectedWidget.isRegistry ? isInstalling ? "Installing..." : "Install Package" : "Add to Dashboard",
8388
+ title: selectedWidget !== null && selectedWidget !== void 0 && selectedWidget.isRegistry ? isInstalling ? "Installing..." : installedPackageNames.has(selectedWidget.packageName) ? "Already Installed" : "Install Package" : "Add to Dashboard",
8238
8389
  bgColor: "bg-gray-800",
8239
8390
  hoverBackgroundColor: isAddButtonEnabled() && !isInstalling ? selectedWidget !== null && selectedWidget !== void 0 && selectedWidget.isRegistry ? "hover:bg-blue-700" : "hover:bg-green-700" : "",
8240
8391
  textSize: "text-lg",
@@ -21353,14 +21504,26 @@ var PropTypes = /*@__PURE__*/getDefaultExportFromCjs(propTypesExports);
21353
21504
  function ownKeys$b(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
21354
21505
  function _objectSpread$b(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$b(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$b(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
21355
21506
 
21356
- // Map of package names to the host app's module instances.
21357
- // When the CJS bundle calls require("react"), it receives the
21358
- // exact same React singleton the host app uses.
21359
- var MODULE_MAP = {
21507
+ // Host-injected module references (e.g., "@trops/dash-core").
21508
+ // Set by the host app via setHostModules() after all modules are fully loaded,
21509
+ // avoiding the self-referential import that breaks under webpack scope hoisting.
21510
+ var _hostModules = {};
21511
+
21512
+ /**
21513
+ * Allow the host app to inject module references for the require shim.
21514
+ * Called from Dash.js after importing dash-core, so the full namespace is available.
21515
+ *
21516
+ * @param {object} modules - Map of package names to module namespaces
21517
+ */
21518
+ function setHostModules(modules) {
21519
+ _hostModules = modules;
21520
+ }
21521
+
21522
+ // Base modules that can be statically imported without circular issues.
21523
+ var BASE_MODULE_MAP = {
21360
21524
  react: React__namespace,
21361
21525
  "react-dom": ReactDOM__namespace,
21362
21526
  "@trops/dash-react": DashReact__namespace,
21363
- "@trops/dash-core": dashCore__namespace,
21364
21527
  "react/jsx-runtime": jsxRuntime__namespace,
21365
21528
  "prop-types": PropTypes
21366
21529
  };
@@ -21373,13 +21536,16 @@ var MODULE_MAP = {
21373
21536
  * @returns {object} The module.exports from the evaluated bundle
21374
21537
  */
21375
21538
  function evaluateBundle(source, widgetName) {
21539
+ // Merge base modules with host-provided modules (e.g., "@trops/dash-core")
21540
+ // at call time so _hostModules is populated by the time widgets load.
21541
+ var moduleMap = _objectSpread$b(_objectSpread$b({}, BASE_MODULE_MAP), _hostModules);
21376
21542
  var module = {
21377
21543
  exports: {}
21378
21544
  };
21379
21545
  var exports = module.exports;
21380
21546
  var require = function require(name) {
21381
- if (MODULE_MAP[name]) {
21382
- var mod = MODULE_MAP[name];
21547
+ if (moduleMap[name]) {
21548
+ var mod = moduleMap[name];
21383
21549
  // CJS interop: `import * as X` creates an ES module namespace where
21384
21550
  // named exports may live under `.default` (e.g. @trops/dash-react).
21385
21551
  // CJS bundles expect `require("pkg").Widget` to work, so merge
@@ -32666,6 +32832,7 @@ exports.renderLayout = _renderLayout;
32666
32832
  exports.renderLayoutMenu = renderLayoutMenu;
32667
32833
  exports.replaceItemInLayout = replaceItemInLayout;
32668
32834
  exports.resolveIcon = resolveIcon;
32835
+ exports.setHostModules = setHostModules;
32669
32836
  exports.traverseParentTree = traverseParentTree;
32670
32837
  exports.updateLayoutItem = updateLayoutItem;
32671
32838
  exports.updateParentForItem = updateParentForItem;