@trops/dash-core 0.1.139 → 0.1.141

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
@@ -31258,7 +31258,8 @@ var GENERATE_MODES = {
31258
31258
  NONE: null,
31259
31259
  PRESETS: "presets",
31260
31260
  COLOR: "color",
31261
- WIZARD: "wizard"
31261
+ WIZARD: "wizard",
31262
+ CHOOSER: "chooser"
31262
31263
  };
31263
31264
 
31264
31265
  // ─── Preset Gallery ──────────────────────────────────────────────────────
@@ -31552,7 +31553,7 @@ var ThemeQuickCreate = function ThemeQuickCreate(_ref8) {
31552
31553
  className: "text-sm font-semibold opacity-50",
31553
31554
  children: "Generation Method"
31554
31555
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
31555
- className: "grid grid-cols-2 gap-2",
31556
+ className: "flex flex-col gap-2",
31556
31557
  children: [/*#__PURE__*/jsxRuntime.jsx(MethodCard, {
31557
31558
  icon: "swatchbook",
31558
31559
  title: "Presets",
@@ -31569,15 +31570,15 @@ var ThemeQuickCreate = function ThemeQuickCreate(_ref8) {
31569
31570
  onClick: function onClick() {
31570
31571
  return handleMethodSelect("random");
31571
31572
  }
31573
+ }), /*#__PURE__*/jsxRuntime.jsx(MethodCard, {
31574
+ icon: "droplet",
31575
+ title: "From Color",
31576
+ subtitle: "Build from a base color with harmony rules",
31577
+ selected: wizardMethod === "color",
31578
+ onClick: function onClick() {
31579
+ return handleMethodSelect("color");
31580
+ }
31572
31581
  })]
31573
- }), /*#__PURE__*/jsxRuntime.jsx(MethodCard, {
31574
- icon: "droplet",
31575
- title: "From Color",
31576
- subtitle: "Build from a base color with harmony rules",
31577
- selected: wizardMethod === "color",
31578
- onClick: function onClick() {
31579
- return handleMethodSelect("color");
31580
- }
31581
31582
  })]
31582
31583
  }), wizardMethod === "presets" && /*#__PURE__*/jsxRuntime.jsx(PresetGallery, {
31583
31584
  onSelect: function onSelect(preset) {
@@ -31604,126 +31605,836 @@ var ThemeQuickCreate = function ThemeQuickCreate(_ref8) {
31604
31605
  });
31605
31606
  };
31606
31607
 
31607
- 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; }
31608
- 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; }
31609
- var ThemeManagerModal = function ThemeManagerModal(_ref) {
31610
- var open = _ref.open,
31611
- setIsOpen = _ref.setIsOpen;
31608
+ var ChooserCard = function ChooserCard(_ref) {
31609
+ var icon = _ref.icon,
31610
+ title = _ref.title,
31611
+ subtitle = _ref.subtitle,
31612
+ onClick = _ref.onClick;
31613
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
31614
+ className: "flex flex-col gap-1.5 p-4 rounded-lg cursor-pointer transition-all bg-white/5 hover:bg-white/10 hover:ring-1 hover:ring-white/20",
31615
+ onClick: onClick,
31616
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
31617
+ className: "flex flex-row items-center gap-2",
31618
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
31619
+ icon: icon,
31620
+ className: "h-3.5 w-3.5 opacity-50"
31621
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
31622
+ className: "text-sm font-medium",
31623
+ children: title
31624
+ })]
31625
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
31626
+ className: "text-xs opacity-40",
31627
+ children: subtitle
31628
+ })]
31629
+ });
31630
+ };
31631
+ var ThemeNewChooser = function ThemeNewChooser(_ref2) {
31632
+ var onSearchThemes = _ref2.onSearchThemes,
31633
+ onCreateNew = _ref2.onCreateNew;
31634
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
31635
+ className: "flex flex-col gap-6 p-6 overflow-y-auto flex-1 min-h-0",
31636
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
31637
+ className: "text-sm font-semibold opacity-50",
31638
+ children: "Add a Theme"
31639
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
31640
+ className: "grid grid-cols-2 gap-3",
31641
+ children: [/*#__PURE__*/jsxRuntime.jsx(ChooserCard, {
31642
+ icon: "magnifying-glass",
31643
+ title: "Search for Themes",
31644
+ subtitle: "Browse the theme marketplace",
31645
+ onClick: onSearchThemes
31646
+ }), /*#__PURE__*/jsxRuntime.jsx(ChooserCard, {
31647
+ icon: "wand-magic-sparkles",
31648
+ title: "Create New",
31649
+ subtitle: "Build from presets, random palettes, or color harmony rules",
31650
+ onClick: onCreateNew
31651
+ })]
31652
+ })]
31653
+ });
31654
+ };
31655
+
31656
+ /**
31657
+ * Shared Tailwind color utilities.
31658
+ *
31659
+ * Single source of truth for mapping Tailwind color family names to hex values.
31660
+ * Used by both renderer components (theme detail/discovery) and electron
31661
+ * controllers (theme publish/install).
31662
+ */
31663
+
31664
+ // Tailwind color family name → representative hex (500 shade)
31665
+ var TAILWIND_COLORS = {
31666
+ slate: "#64748b",
31667
+ gray: "#6b7280",
31668
+ zinc: "#71717a",
31669
+ neutral: "#737373",
31670
+ stone: "#78716c",
31671
+ red: "#ef4444",
31672
+ orange: "#f97316",
31673
+ amber: "#f59e0b",
31674
+ yellow: "#eab308",
31675
+ lime: "#84cc16",
31676
+ green: "#22c55e",
31677
+ emerald: "#10b981",
31678
+ teal: "#14b8a6",
31679
+ cyan: "#06b6d4",
31680
+ sky: "#0ea5e9",
31681
+ blue: "#3b82f6",
31682
+ indigo: "#6366f1",
31683
+ violet: "#8b5cf6",
31684
+ purple: "#a855f7",
31685
+ fuchsia: "#d946ef",
31686
+ pink: "#ec4899",
31687
+ rose: "#f43f5e"
31688
+ };
31689
+
31690
+ /**
31691
+ * Convert a color value to a CSS-usable color.
31692
+ * If it's a Tailwind family name, map to its hex 500 shade.
31693
+ * If it already looks like a hex/rgb/hsl value, return as-is.
31694
+ */
31695
+ function toDisplayColor(value) {
31696
+ if (!value) return "";
31697
+ var lower = value.toLowerCase().trim();
31698
+ return TAILWIND_COLORS[lower] || value;
31699
+ }
31700
+
31701
+ function adjustColor(hex, amount) {
31702
+ if (!hex || !hex.startsWith("#")) return hex;
31703
+ var num = parseInt(hex.slice(1), 16);
31704
+ var r = Math.min(255, Math.max(0, (num >> 16 & 0xff) + Math.round(255 * amount)));
31705
+ var g = Math.min(255, Math.max(0, (num >> 8 & 0xff) + Math.round(255 * amount)));
31706
+ var b = Math.min(255, Math.max(0, (num & 0xff) + Math.round(255 * amount)));
31707
+ return "#".concat((r << 16 | g << 8 | b).toString(16).padStart(6, "0"));
31708
+ }
31709
+
31710
+ /**
31711
+ * ThemePreviewMockup — renders a mini dashboard mockup using theme colors.
31712
+ */
31713
+ var ThemePreviewMockup = function ThemePreviewMockup(_ref) {
31714
+ var colors = _ref.colors;
31715
+ var primary = colors.primary,
31716
+ secondary = colors.secondary,
31717
+ tertiary = colors.tertiary,
31718
+ neutral = colors.neutral;
31719
+ var bg = neutral || adjustColor(primary, -0.6);
31720
+ var sidebar = adjustColor(primary, -0.5);
31721
+ var header = adjustColor(primary, -0.4);
31722
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
31723
+ className: "flex flex-col gap-2",
31724
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
31725
+ className: "text-xs font-semibold opacity-50",
31726
+ children: "PREVIEW"
31727
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
31728
+ className: "rounded-lg overflow-hidden border border-white/10",
31729
+ style: {
31730
+ backgroundColor: bg,
31731
+ minHeight: 160
31732
+ },
31733
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
31734
+ className: "flex flex-row h-full",
31735
+ style: {
31736
+ minHeight: 160
31737
+ },
31738
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
31739
+ className: "flex flex-col gap-1.5 p-2 w-24 flex-shrink-0",
31740
+ style: {
31741
+ backgroundColor: sidebar
31742
+ },
31743
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
31744
+ className: "h-2 w-12 rounded-sm opacity-60",
31745
+ style: {
31746
+ backgroundColor: primary
31747
+ }
31748
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
31749
+ className: "h-2 w-16 rounded-sm opacity-30",
31750
+ style: {
31751
+ backgroundColor: secondary
31752
+ }
31753
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
31754
+ className: "h-2 w-10 rounded-sm opacity-30",
31755
+ style: {
31756
+ backgroundColor: secondary
31757
+ }
31758
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
31759
+ className: "h-2 w-14 rounded-sm opacity-30",
31760
+ style: {
31761
+ backgroundColor: secondary
31762
+ }
31763
+ })]
31764
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
31765
+ className: "flex flex-col flex-1 min-w-0",
31766
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
31767
+ className: "flex items-center gap-2 px-3 py-2",
31768
+ style: {
31769
+ backgroundColor: header
31770
+ },
31771
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
31772
+ className: "h-2 w-20 rounded-sm opacity-70",
31773
+ style: {
31774
+ backgroundColor: primary
31775
+ }
31776
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
31777
+ className: "flex-1"
31778
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
31779
+ className: "h-2 w-8 rounded-sm opacity-40",
31780
+ style: {
31781
+ backgroundColor: tertiary || secondary
31782
+ }
31783
+ })]
31784
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
31785
+ className: "grid grid-cols-3 gap-2 p-3 flex-1",
31786
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
31787
+ className: "rounded p-2 flex flex-col gap-1.5",
31788
+ style: {
31789
+ backgroundColor: adjustColor(primary, -0.35)
31790
+ },
31791
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
31792
+ className: "h-1.5 w-10 rounded-sm",
31793
+ style: {
31794
+ backgroundColor: primary,
31795
+ opacity: 0.7
31796
+ }
31797
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
31798
+ className: "h-8 w-full rounded-sm",
31799
+ style: {
31800
+ backgroundColor: secondary,
31801
+ opacity: 0.3
31802
+ }
31803
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
31804
+ className: "h-1.5 w-12 rounded-sm",
31805
+ style: {
31806
+ backgroundColor: tertiary || secondary,
31807
+ opacity: 0.4
31808
+ }
31809
+ })]
31810
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
31811
+ className: "rounded p-2 flex flex-col gap-1.5",
31812
+ style: {
31813
+ backgroundColor: adjustColor(primary, -0.35)
31814
+ },
31815
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
31816
+ className: "h-1.5 w-8 rounded-sm",
31817
+ style: {
31818
+ backgroundColor: secondary,
31819
+ opacity: 0.7
31820
+ }
31821
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
31822
+ className: "flex flex-row gap-1 flex-1",
31823
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
31824
+ className: "flex-1 rounded-sm",
31825
+ style: {
31826
+ backgroundColor: primary,
31827
+ opacity: 0.25
31828
+ }
31829
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
31830
+ className: "flex-1 rounded-sm",
31831
+ style: {
31832
+ backgroundColor: tertiary || secondary,
31833
+ opacity: 0.25
31834
+ }
31835
+ })]
31836
+ })]
31837
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
31838
+ className: "rounded p-2 flex flex-col gap-1.5",
31839
+ style: {
31840
+ backgroundColor: adjustColor(primary, -0.35)
31841
+ },
31842
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
31843
+ className: "h-1.5 w-12 rounded-sm",
31844
+ style: {
31845
+ backgroundColor: tertiary || primary,
31846
+ opacity: 0.7
31847
+ }
31848
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
31849
+ className: "h-4 w-full rounded-sm",
31850
+ style: {
31851
+ backgroundColor: primary,
31852
+ opacity: 0.2
31853
+ }
31854
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
31855
+ className: "h-4 w-full rounded-sm",
31856
+ style: {
31857
+ backgroundColor: secondary,
31858
+ opacity: 0.2
31859
+ }
31860
+ })]
31861
+ })]
31862
+ })]
31863
+ })]
31864
+ })
31865
+ })]
31866
+ });
31867
+ };
31868
+
31869
+ /**
31870
+ * RegistryThemeDetail — detail panel for a registry theme package.
31871
+ *
31872
+ * Shows package header, color preview swatches, description, tags, and install button.
31873
+ */
31874
+ var RegistryThemeDetail = function RegistryThemeDetail(_ref2) {
31875
+ var themePackage = _ref2.themePackage,
31876
+ appId = _ref2.appId,
31877
+ onInstallComplete = _ref2.onInstallComplete;
31612
31878
  var _useContext = React.useContext(DashReact.ThemeContext),
31613
- changeThemesForApplication = _useContext.changeThemesForApplication,
31614
- rawThemes = _useContext.rawThemes,
31615
- themes = _useContext.themes,
31616
- changeCurrentTheme = _useContext.changeCurrentTheme,
31617
- changeThemeVariant = _useContext.changeThemeVariant,
31618
- currentTheme = _useContext.currentTheme;
31619
- var _useContext2 = React.useContext(AppContext),
31620
- dashApi = _useContext2.dashApi,
31621
- credentials = _useContext2.credentials,
31622
- settings = _useContext2.settings;
31623
- var _useState = React.useState(null),
31879
+ currentTheme = _useContext.currentTheme,
31880
+ changeThemesForApplication = _useContext.changeThemesForApplication;
31881
+ var panelStyles = DashReact.getStylesForItem(DashReact.themeObjects.PANEL, currentTheme, {
31882
+ grow: false
31883
+ });
31884
+ var _useState = React.useState(false),
31624
31885
  _useState2 = _slicedToArray(_useState, 2),
31625
- themeSelected = _useState2[0],
31626
- setThemeSelected = _useState2[1];
31886
+ isInstalling = _useState2[0],
31887
+ setIsInstalling = _useState2[1];
31627
31888
  var _useState3 = React.useState(null),
31628
31889
  _useState4 = _slicedToArray(_useState3, 2),
31629
- rawThemeSelected = _useState4[0],
31630
- setRawThemeSelected = _useState4[1];
31631
- var _useState5 = React.useState(null),
31632
- _useState6 = _slicedToArray(_useState5, 2),
31633
- themeKeySelected = _useState6[0],
31634
- setThemeKeySelected = _useState6[1];
31635
- var _useState7 = React.useState(false),
31636
- _useState8 = _slicedToArray(_useState7, 2),
31637
- isEditing = _useState8[0],
31638
- setIsEditing = _useState8[1];
31639
- var _useState9 = React.useState(false),
31640
- _useState0 = _slicedToArray(_useState9, 2),
31641
- isCreating = _useState0[0],
31642
- setIsCreating = _useState0[1];
31643
- var _useState1 = React.useState(""),
31644
- _useState10 = _slicedToArray(_useState1, 2),
31645
- wizardName = _useState10[0],
31646
- setWizardName = _useState10[1];
31647
- var _useState11 = React.useState(null),
31648
- _useState12 = _slicedToArray(_useState11, 2),
31649
- wizardMethod = _useState12[0],
31650
- setWizardMethod = _useState12[1];
31651
- var _useState13 = React.useState(null),
31652
- _useState14 = _slicedToArray(_useState13, 2),
31653
- wizardTheme = _useState14[0],
31654
- setWizardTheme = _useState14[1];
31655
- var _React$useState = React.useState(),
31656
- _React$useState2 = _slicedToArray(_React$useState, 2),
31657
- updateState = _React$useState2[1];
31658
- var forceUpdate = React.useCallback(function () {
31659
- return updateState({});
31660
- }, []);
31661
- var footerStyles = DashReact.getStylesForItem(DashReact.themeObjects.PANEL_FOOTER, currentTheme, {});
31662
- React.useEffect(function () {
31663
- if (open === false) {
31664
- setThemeSelected(null);
31665
- setRawThemeSelected(null);
31666
- setThemeKeySelected(null);
31667
- setIsCreating(false);
31668
- } else {
31669
- if (themeKeySelected === null && themes) {
31670
- var themeKeyTemp = settings && "theme" in settings ? settings["theme"] in themes ? settings["theme"] : Object.keys(themes)[0] : Object.keys(themes)[0];
31671
- var themeModel = ThemeModel(rawThemes[themeKeyTemp]);
31672
- setThemeKeySelected(function () {
31673
- return themeKeyTemp;
31674
- });
31675
- setThemeSelected(function () {
31676
- return themeModel;
31677
- });
31678
- setRawThemeSelected(function () {
31679
- return rawThemes[themeKeyTemp];
31680
- });
31681
- }
31682
- }
31683
- }, [open, themes, rawThemes, settings, themeKeySelected]);
31684
- function handleThemeSelected(themeUpdated, themeKey) {
31685
- var newRawThemeSelected = DashReact.deepCopy(rawThemeSelected);
31686
- if (newRawThemeSelected !== null) {
31687
- Object.keys(themeUpdated).forEach(function (k) {
31688
- newRawThemeSelected[k] = themeUpdated[k];
31689
- });
31690
- } else {
31691
- newRawThemeSelected = DashReact.deepCopy(themeUpdated);
31692
- }
31693
- setRawThemeSelected(function () {
31694
- return newRawThemeSelected;
31695
- });
31696
- var newTheme = ThemeModel(DashReact.deepCopy(newRawThemeSelected));
31697
- setThemeKeySelected(function () {
31698
- return themeKey;
31699
- });
31700
- setThemeSelected(function () {
31701
- return newTheme;
31702
- });
31703
- forceUpdate();
31704
- }
31705
- function handleStartCreateTheme() {
31706
- setIsCreating(true);
31707
- setIsEditing(false);
31708
- setWizardName("");
31709
- setWizardMethod(null);
31710
- setWizardTheme(null);
31890
+ installResult = _useState4[0],
31891
+ setInstallResult = _useState4[1];
31892
+ var pkg = themePackage;
31893
+ if (!pkg) return null;
31894
+ var rawColors = pkg.colors || {};
31895
+ // Also check top-level fields for themes that store colors directly
31896
+ var colors = {
31897
+ primary: toDisplayColor(rawColors.primary || pkg.primary || ""),
31898
+ secondary: toDisplayColor(rawColors.secondary || pkg.secondary || ""),
31899
+ tertiary: toDisplayColor(rawColors.tertiary || pkg.tertiary || ""),
31900
+ neutral: toDisplayColor(rawColors.neutral || pkg.neutral || "")
31901
+ };
31902
+ function handleInstall() {
31903
+ return _handleInstall.apply(this, arguments);
31711
31904
  }
31712
- function handleWizardComplete() {
31713
- if (!wizardTheme || !wizardName.trim()) return;
31714
- var key = wizardTheme.id || "theme-".concat(Date.now());
31715
- var finalTheme = _objectSpread$b(_objectSpread$b({}, wizardTheme), {}, {
31716
- id: key,
31717
- name: wizardName.trim()
31718
- });
31719
- if (dashApi) {
31720
- dashApi.saveTheme(credentials.appId, key, finalTheme, function (e, message) {
31721
- changeThemesForApplication(message["themes"]);
31722
- setIsCreating(false);
31723
- setIsEditing(false);
31724
- var newThemes = message["themes"];
31725
- if (newThemes && newThemes[key]) {
31726
- setThemeKeySelected(key);
31905
+ function _handleInstall() {
31906
+ _handleInstall = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
31907
+ var result, _t;
31908
+ return _regeneratorRuntime.wrap(function (_context) {
31909
+ while (1) switch (_context.prev = _context.next) {
31910
+ case 0:
31911
+ if (!(!appId || !pkg.name)) {
31912
+ _context.next = 1;
31913
+ break;
31914
+ }
31915
+ return _context.abrupt("return");
31916
+ case 1:
31917
+ setIsInstalling(true);
31918
+ setInstallResult(null);
31919
+ _context.prev = 2;
31920
+ _context.next = 3;
31921
+ return window.mainApi.themes.installThemeFromRegistry(appId, pkg.name);
31922
+ case 3:
31923
+ result = _context.sent;
31924
+ setInstallResult({
31925
+ status: result !== null && result !== void 0 && result.success ? "success" : "error",
31926
+ message: result !== null && result !== void 0 && result.success ? "Theme \"".concat(result.themeKey || pkg.displayName || pkg.name, "\" installed successfully.") : (result === null || result === void 0 ? void 0 : result.error) || "Installation failed."
31927
+ });
31928
+ if (result !== null && result !== void 0 && result.success) {
31929
+ // Refresh ThemeContext with updated themes
31930
+ if (result.themes) {
31931
+ changeThemesForApplication(result.themes);
31932
+ }
31933
+ if (onInstallComplete) {
31934
+ onInstallComplete(result);
31935
+ }
31936
+ }
31937
+ _context.next = 5;
31938
+ break;
31939
+ case 4:
31940
+ _context.prev = 4;
31941
+ _t = _context["catch"](2);
31942
+ setInstallResult({
31943
+ status: "error",
31944
+ message: _t.message || "Failed to install theme."
31945
+ });
31946
+ case 5:
31947
+ _context.prev = 5;
31948
+ setIsInstalling(false);
31949
+ return _context.finish(5);
31950
+ case 6:
31951
+ case "end":
31952
+ return _context.stop();
31953
+ }
31954
+ }, _callee, null, [[2, 4, 5, 6]]);
31955
+ }));
31956
+ return _handleInstall.apply(this, arguments);
31957
+ }
31958
+ var colorEntries = [{
31959
+ label: "Primary",
31960
+ value: colors.primary
31961
+ }, {
31962
+ label: "Secondary",
31963
+ value: colors.secondary
31964
+ }, {
31965
+ label: "Tertiary",
31966
+ value: colors.tertiary
31967
+ }, {
31968
+ label: "Neutral",
31969
+ value: colors.neutral
31970
+ }].filter(function (c) {
31971
+ return c.value;
31972
+ });
31973
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
31974
+ className: "flex flex-col flex-1 min-h-0",
31975
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
31976
+ className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-6 ".concat(panelStyles.textColor || "text-gray-200"),
31977
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
31978
+ className: "flex flex-row items-center gap-3",
31979
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
31980
+ className: "h-5 w-5 flex-shrink-0 flex items-center justify-center",
31981
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
31982
+ icon: "palette",
31983
+ className: "h-5 w-5"
31984
+ })
31985
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
31986
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading3, {
31987
+ title: pkg.displayName || pkg.name,
31988
+ padding: false
31989
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
31990
+ className: "flex items-center gap-2 mt-0.5",
31991
+ children: [/*#__PURE__*/jsxRuntime.jsxs("span", {
31992
+ className: "text-sm opacity-60",
31993
+ children: ["by ", pkg.author || "Unknown"]
31994
+ }), pkg.version && /*#__PURE__*/jsxRuntime.jsxs("span", {
31995
+ className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " opacity-70"),
31996
+ children: ["v", pkg.version]
31997
+ })]
31998
+ })]
31999
+ })]
32000
+ }), /*#__PURE__*/jsxRuntime.jsx("hr", {
32001
+ className: currentTheme["border-primary-medium"]
32002
+ }), colorEntries.length > 0 && /*#__PURE__*/jsxRuntime.jsx(ThemePreviewMockup, {
32003
+ colors: colors
32004
+ }), colorEntries.length > 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
32005
+ className: "flex flex-row gap-3",
32006
+ children: colorEntries.map(function (_ref3) {
32007
+ var label = _ref3.label,
32008
+ value = _ref3.value;
32009
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
32010
+ className: "flex flex-col items-center gap-1 flex-1",
32011
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
32012
+ className: "h-8 w-8 rounded border-2 border-white/20",
32013
+ style: {
32014
+ backgroundColor: value
32015
+ }
32016
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
32017
+ className: "text-[10px] opacity-50",
32018
+ children: label
32019
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
32020
+ className: "text-[10px] opacity-30 font-mono",
32021
+ children: value
32022
+ })]
32023
+ }, label);
32024
+ })
32025
+ }), pkg.description && /*#__PURE__*/jsxRuntime.jsx("p", {
32026
+ className: "text-sm",
32027
+ children: pkg.description
32028
+ }), pkg.tags && pkg.tags.length > 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
32029
+ className: "flex flex-wrap gap-1",
32030
+ children: pkg.tags.map(function (tag) {
32031
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
32032
+ className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " opacity-60"),
32033
+ children: tag
32034
+ }, tag);
32035
+ })
32036
+ }), installResult && /*#__PURE__*/jsxRuntime.jsx("div", {
32037
+ className: "p-2 rounded border ".concat(installResult.status === "success" ? "bg-green-900/20 border-green-700" : "bg-red-900/30 border-red-700"),
32038
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
32039
+ className: "flex items-center gap-2",
32040
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
32041
+ icon: installResult.status === "success" ? "circle-check" : "circle-xmark",
32042
+ className: "h-4 w-4 ".concat(installResult.status === "success" ? "text-green-400" : "text-red-400")
32043
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
32044
+ className: "text-sm ".concat(installResult.status === "error" ? "text-red-400" : ""),
32045
+ children: installResult.message
32046
+ })]
32047
+ })
32048
+ })]
32049
+ }), (installResult === null || installResult === void 0 ? void 0 : installResult.status) !== "success" && /*#__PURE__*/jsxRuntime.jsx("div", {
32050
+ className: "flex items-center justify-end px-6 py-3 border-t ".concat(currentTheme["border-primary-medium"]),
32051
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
32052
+ title: isInstalling ? "Installing..." : "Install Theme",
32053
+ bgColor: "bg-blue-600",
32054
+ hoverBackgroundColor: isInstalling ? "" : "hover:bg-blue-700",
32055
+ textSize: "text-sm",
32056
+ padding: "py-1.5 px-4",
32057
+ onClick: handleInstall,
32058
+ disabled: isInstalling
32059
+ })
32060
+ })]
32061
+ });
32062
+ };
32063
+
32064
+ var ThemeColorDots = function ThemeColorDots(_ref) {
32065
+ var theme = _ref.theme,
32066
+ colors = _ref.colors,
32067
+ _ref$size = _ref.size,
32068
+ size = _ref$size === void 0 ? "h-2.5 w-2.5" : _ref$size;
32069
+ var c = colors || {};
32070
+ var values = [toDisplayColor(c.primary || (theme === null || theme === void 0 ? void 0 : theme.primary) || ""), toDisplayColor(c.secondary || (theme === null || theme === void 0 ? void 0 : theme.secondary) || ""), toDisplayColor(c.tertiary || (theme === null || theme === void 0 ? void 0 : theme.tertiary) || "")].filter(Boolean);
32071
+ if (values.length === 0) return null;
32072
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
32073
+ className: "flex items-center gap-0.5",
32074
+ children: values.map(function (color, i) {
32075
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
32076
+ className: "".concat(size, " rounded-sm border border-white/20 flex-shrink-0"),
32077
+ style: {
32078
+ backgroundColor: color
32079
+ }
32080
+ }, i);
32081
+ })
32082
+ });
32083
+ };
32084
+
32085
+ var DiscoverThemesDetail = function DiscoverThemesDetail(_ref) {
32086
+ var onBack = _ref.onBack,
32087
+ appId = _ref.appId,
32088
+ onInstallComplete = _ref.onInstallComplete;
32089
+ var _useContext = React.useContext(DashReact.ThemeContext),
32090
+ currentTheme = _useContext.currentTheme;
32091
+ var panelStyles = DashReact.getStylesForItem(DashReact.themeObjects.PANEL, currentTheme, {
32092
+ grow: false
32093
+ });
32094
+ var _useState = React.useState([]),
32095
+ _useState2 = _slicedToArray(_useState, 2),
32096
+ packages = _useState2[0],
32097
+ setPackages = _useState2[1];
32098
+ var _useState3 = React.useState(false),
32099
+ _useState4 = _slicedToArray(_useState3, 2),
32100
+ isLoading = _useState4[0],
32101
+ setIsLoading = _useState4[1];
32102
+ var _useState5 = React.useState(null),
32103
+ _useState6 = _slicedToArray(_useState5, 2),
32104
+ error = _useState6[0],
32105
+ setError = _useState6[1];
32106
+ var _useState7 = React.useState(""),
32107
+ _useState8 = _slicedToArray(_useState7, 2),
32108
+ searchQuery = _useState8[0],
32109
+ setSearchQuery = _useState8[1];
32110
+ var _useState9 = React.useState(null),
32111
+ _useState0 = _slicedToArray(_useState9, 2),
32112
+ selectedPackageName = _useState0[0],
32113
+ setSelectedPackageName = _useState0[1];
32114
+ var search = React.useCallback(/*#__PURE__*/function () {
32115
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(query) {
32116
+ var _window$mainApi;
32117
+ var result, _t;
32118
+ return _regeneratorRuntime.wrap(function (_context) {
32119
+ while (1) switch (_context.prev = _context.next) {
32120
+ case 0:
32121
+ if ((_window$mainApi = window.mainApi) !== null && _window$mainApi !== void 0 && (_window$mainApi = _window$mainApi.registry) !== null && _window$mainApi !== void 0 && _window$mainApi.searchThemes) {
32122
+ _context.next = 1;
32123
+ break;
32124
+ }
32125
+ setPackages([]);
32126
+ return _context.abrupt("return");
32127
+ case 1:
32128
+ setIsLoading(true);
32129
+ setError(null);
32130
+ _context.prev = 2;
32131
+ _context.next = 3;
32132
+ return window.mainApi.registry.searchThemes(query || "", {});
32133
+ case 3:
32134
+ result = _context.sent;
32135
+ setPackages((result === null || result === void 0 ? void 0 : result.packages) || []);
32136
+ _context.next = 5;
32137
+ break;
32138
+ case 4:
32139
+ _context.prev = 4;
32140
+ _t = _context["catch"](2);
32141
+ setError(_t.message || "Failed to search theme registry");
32142
+ setPackages([]);
32143
+ case 5:
32144
+ _context.prev = 5;
32145
+ setIsLoading(false);
32146
+ return _context.finish(5);
32147
+ case 6:
32148
+ case "end":
32149
+ return _context.stop();
32150
+ }
32151
+ }, _callee, null, [[2, 4, 5, 6]]);
32152
+ }));
32153
+ return function (_x) {
32154
+ return _ref2.apply(this, arguments);
32155
+ };
32156
+ }(), []);
32157
+
32158
+ // Debounce search on query changes
32159
+ React.useEffect(function () {
32160
+ var timer = setTimeout(function () {
32161
+ search(searchQuery);
32162
+ }, 300);
32163
+ return function () {
32164
+ return clearTimeout(timer);
32165
+ };
32166
+ // eslint-disable-next-line react-hooks/exhaustive-deps
32167
+ }, [searchQuery]);
32168
+ var retry = function retry() {
32169
+ return search(searchQuery);
32170
+ };
32171
+ var selectedPackage = selectedPackageName ? packages.find(function (p) {
32172
+ return p.name === selectedPackageName;
32173
+ }) : null;
32174
+
32175
+ // If a package is selected, show its detail inline
32176
+ if (selectedPackage) {
32177
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
32178
+ className: "flex flex-col flex-1 min-h-0",
32179
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
32180
+ className: "flex-shrink-0 px-4 pt-4",
32181
+ children: /*#__PURE__*/jsxRuntime.jsxs("button", {
32182
+ type: "button",
32183
+ onClick: function onClick() {
32184
+ return setSelectedPackageName(null);
32185
+ },
32186
+ className: "flex items-center gap-1.5 text-sm opacity-60 hover:opacity-100 transition-opacity",
32187
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
32188
+ icon: "arrow-left",
32189
+ className: "h-3 w-3"
32190
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
32191
+ children: "Back"
32192
+ })]
32193
+ })
32194
+ }), /*#__PURE__*/jsxRuntime.jsx(RegistryThemeDetail, {
32195
+ themePackage: selectedPackage,
32196
+ appId: appId,
32197
+ onInstallComplete: onInstallComplete
32198
+ })]
32199
+ });
32200
+ }
32201
+
32202
+ // Package list view
32203
+ var listBody;
32204
+ if (isLoading) {
32205
+ listBody = /*#__PURE__*/jsxRuntime.jsx("div", {
32206
+ className: "flex items-center justify-center py-12",
32207
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
32208
+ className: "text-center",
32209
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
32210
+ className: "animate-spin rounded-full h-6 w-6 border-b-2 border-blue-500 mx-auto mb-3"
32211
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Paragraph, {
32212
+ className: "text-sm opacity-50",
32213
+ children: "Loading themes..."
32214
+ })]
32215
+ })
32216
+ });
32217
+ } else if (error) {
32218
+ listBody = /*#__PURE__*/jsxRuntime.jsxs("div", {
32219
+ className: "px-4 py-8 text-center",
32220
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Paragraph, {
32221
+ className: "text-sm text-red-400 mb-3",
32222
+ children: error
32223
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
32224
+ title: "Retry",
32225
+ bgColor: "bg-gray-700",
32226
+ hoverBackgroundColor: "hover:bg-gray-600",
32227
+ textSize: "text-sm",
32228
+ padding: "py-1 px-3",
32229
+ onClick: retry
32230
+ })]
32231
+ });
32232
+ } else if (packages.length === 0) {
32233
+ listBody = /*#__PURE__*/jsxRuntime.jsx("div", {
32234
+ className: "px-4 py-8 text-center",
32235
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Paragraph, {
32236
+ className: "text-sm opacity-50",
32237
+ children: searchQuery ? "No themes match your search." : "No theme packages available."
32238
+ })
32239
+ });
32240
+ } else {
32241
+ listBody = /*#__PURE__*/jsxRuntime.jsx("div", {
32242
+ className: "space-y-1",
32243
+ children: packages.map(function (pkg) {
32244
+ return /*#__PURE__*/jsxRuntime.jsx(DashReact.Sidebar.Item, {
32245
+ icon: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
32246
+ icon: "palette",
32247
+ className: "h-3.5 w-3.5"
32248
+ }),
32249
+ badge: /*#__PURE__*/jsxRuntime.jsx(ThemeColorDots, {
32250
+ colors: pkg.colors,
32251
+ theme: pkg
32252
+ }),
32253
+ onClick: function onClick() {
32254
+ return setSelectedPackageName(pkg.name);
32255
+ },
32256
+ children: pkg.displayName || pkg.name
32257
+ }, pkg.name);
32258
+ })
32259
+ });
32260
+ }
32261
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
32262
+ className: "flex flex-col flex-1 min-h-0 ".concat(panelStyles.textColor || "text-gray-200"),
32263
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
32264
+ className: "flex-shrink-0 px-4 pt-4",
32265
+ children: /*#__PURE__*/jsxRuntime.jsxs("button", {
32266
+ type: "button",
32267
+ onClick: onBack,
32268
+ className: "flex items-center gap-1.5 text-sm opacity-60 hover:opacity-100 transition-opacity",
32269
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
32270
+ icon: "arrow-left",
32271
+ className: "h-3 w-3"
32272
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
32273
+ children: "Back"
32274
+ })]
32275
+ })
32276
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
32277
+ className: "flex-shrink-0 px-4 py-3",
32278
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.SearchInput, {
32279
+ value: searchQuery,
32280
+ onChange: setSearchQuery,
32281
+ placeholder: "Search themes...",
32282
+ inputClassName: "py-1.5 text-xs"
32283
+ })
32284
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
32285
+ className: "flex-1 min-h-0 overflow-y-auto px-2",
32286
+ children: listBody
32287
+ }), !isLoading && !error && packages.length > 0 && /*#__PURE__*/jsxRuntime.jsxs("div", {
32288
+ className: "flex-shrink-0 px-4 py-2 text-[10px] opacity-40 border-t border-white/10",
32289
+ children: [packages.length, " theme", packages.length !== 1 ? "s" : ""]
32290
+ })]
32291
+ });
32292
+ };
32293
+
32294
+ 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; }
32295
+ 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; }
32296
+ var ThemeManagerModal = function ThemeManagerModal(_ref) {
32297
+ var open = _ref.open,
32298
+ setIsOpen = _ref.setIsOpen;
32299
+ var _useContext = React.useContext(DashReact.ThemeContext),
32300
+ changeThemesForApplication = _useContext.changeThemesForApplication,
32301
+ rawThemes = _useContext.rawThemes,
32302
+ themes = _useContext.themes,
32303
+ changeCurrentTheme = _useContext.changeCurrentTheme,
32304
+ changeThemeVariant = _useContext.changeThemeVariant,
32305
+ currentTheme = _useContext.currentTheme;
32306
+ var _useContext2 = React.useContext(AppContext),
32307
+ dashApi = _useContext2.dashApi,
32308
+ credentials = _useContext2.credentials,
32309
+ settings = _useContext2.settings;
32310
+ var _useState = React.useState(null),
32311
+ _useState2 = _slicedToArray(_useState, 2),
32312
+ themeSelected = _useState2[0],
32313
+ setThemeSelected = _useState2[1];
32314
+ var _useState3 = React.useState(null),
32315
+ _useState4 = _slicedToArray(_useState3, 2),
32316
+ rawThemeSelected = _useState4[0],
32317
+ setRawThemeSelected = _useState4[1];
32318
+ var _useState5 = React.useState(null),
32319
+ _useState6 = _slicedToArray(_useState5, 2),
32320
+ themeKeySelected = _useState6[0],
32321
+ setThemeKeySelected = _useState6[1];
32322
+ var _useState7 = React.useState(false),
32323
+ _useState8 = _slicedToArray(_useState7, 2),
32324
+ isEditing = _useState8[0],
32325
+ setIsEditing = _useState8[1];
32326
+ var _useState9 = React.useState(false),
32327
+ _useState0 = _slicedToArray(_useState9, 2),
32328
+ isCreating = _useState0[0],
32329
+ setIsCreating = _useState0[1];
32330
+ var _useState1 = React.useState(false),
32331
+ _useState10 = _slicedToArray(_useState1, 2),
32332
+ isChoosingMode = _useState10[0],
32333
+ setIsChoosingMode = _useState10[1];
32334
+ var _useState11 = React.useState(false),
32335
+ _useState12 = _slicedToArray(_useState11, 2),
32336
+ isSearching = _useState12[0],
32337
+ setIsSearching = _useState12[1];
32338
+ var _useState13 = React.useState(""),
32339
+ _useState14 = _slicedToArray(_useState13, 2),
32340
+ wizardName = _useState14[0],
32341
+ setWizardName = _useState14[1];
32342
+ var _useState15 = React.useState(null),
32343
+ _useState16 = _slicedToArray(_useState15, 2),
32344
+ wizardMethod = _useState16[0],
32345
+ setWizardMethod = _useState16[1];
32346
+ var _useState17 = React.useState(null),
32347
+ _useState18 = _slicedToArray(_useState17, 2),
32348
+ wizardTheme = _useState18[0],
32349
+ setWizardTheme = _useState18[1];
32350
+ var _React$useState = React.useState(),
32351
+ _React$useState2 = _slicedToArray(_React$useState, 2),
32352
+ updateState = _React$useState2[1];
32353
+ var forceUpdate = React.useCallback(function () {
32354
+ return updateState({});
32355
+ }, []);
32356
+ var footerStyles = DashReact.getStylesForItem(DashReact.themeObjects.PANEL_FOOTER, currentTheme, {});
32357
+ React.useEffect(function () {
32358
+ if (open === false) {
32359
+ setThemeSelected(null);
32360
+ setRawThemeSelected(null);
32361
+ setThemeKeySelected(null);
32362
+ setIsCreating(false);
32363
+ setIsChoosingMode(false);
32364
+ setIsSearching(false);
32365
+ } else {
32366
+ if (themeKeySelected === null && themes) {
32367
+ var themeKeyTemp = settings && "theme" in settings ? settings["theme"] in themes ? settings["theme"] : Object.keys(themes)[0] : Object.keys(themes)[0];
32368
+ var themeModel = ThemeModel(rawThemes[themeKeyTemp]);
32369
+ setThemeKeySelected(function () {
32370
+ return themeKeyTemp;
32371
+ });
32372
+ setThemeSelected(function () {
32373
+ return themeModel;
32374
+ });
32375
+ setRawThemeSelected(function () {
32376
+ return rawThemes[themeKeyTemp];
32377
+ });
32378
+ }
32379
+ }
32380
+ }, [open, themes, rawThemes, settings, themeKeySelected]);
32381
+ function handleThemeSelected(themeUpdated, themeKey) {
32382
+ var newRawThemeSelected = DashReact.deepCopy(rawThemeSelected);
32383
+ if (newRawThemeSelected !== null) {
32384
+ Object.keys(themeUpdated).forEach(function (k) {
32385
+ newRawThemeSelected[k] = themeUpdated[k];
32386
+ });
32387
+ } else {
32388
+ newRawThemeSelected = DashReact.deepCopy(themeUpdated);
32389
+ }
32390
+ setRawThemeSelected(function () {
32391
+ return newRawThemeSelected;
32392
+ });
32393
+ var newTheme = ThemeModel(DashReact.deepCopy(newRawThemeSelected));
32394
+ setThemeKeySelected(function () {
32395
+ return themeKey;
32396
+ });
32397
+ setThemeSelected(function () {
32398
+ return newTheme;
32399
+ });
32400
+ forceUpdate();
32401
+ }
32402
+ function handleStartCreateTheme() {
32403
+ setIsChoosingMode(true);
32404
+ setIsCreating(false);
32405
+ setIsSearching(false);
32406
+ setIsEditing(false);
32407
+ }
32408
+ function handleChooseCreate() {
32409
+ setIsChoosingMode(false);
32410
+ setIsCreating(true);
32411
+ setWizardName("");
32412
+ setWizardMethod(null);
32413
+ setWizardTheme(null);
32414
+ }
32415
+ function handleChooseSearch() {
32416
+ setIsChoosingMode(false);
32417
+ setIsSearching(true);
32418
+ }
32419
+ function handleBackFromSearch() {
32420
+ setIsSearching(false);
32421
+ setIsChoosingMode(true);
32422
+ }
32423
+ function handleWizardComplete() {
32424
+ if (!wizardTheme || !wizardName.trim()) return;
32425
+ var key = wizardTheme.id || "theme-".concat(Date.now());
32426
+ var finalTheme = _objectSpread$b(_objectSpread$b({}, wizardTheme), {}, {
32427
+ id: key,
32428
+ name: wizardName.trim()
32429
+ });
32430
+ if (dashApi) {
32431
+ dashApi.saveTheme(credentials.appId, key, finalTheme, function (e, message) {
32432
+ changeThemesForApplication(message["themes"]);
32433
+ setIsCreating(false);
32434
+ setIsEditing(false);
32435
+ var newThemes = message["themes"];
32436
+ if (newThemes && newThemes[key]) {
32437
+ setThemeKeySelected(key);
31727
32438
  setThemeSelected(newThemes[key]);
31728
32439
  setRawThemeSelected(finalTheme);
31729
32440
  }
@@ -31732,6 +32443,8 @@ var ThemeManagerModal = function ThemeManagerModal(_ref) {
31732
32443
  }
31733
32444
  function handleCancelCreate() {
31734
32445
  setIsCreating(false);
32446
+ setIsChoosingMode(false);
32447
+ setIsSearching(false);
31735
32448
  }
31736
32449
  function handleSaveTheme() {
31737
32450
  if (themeKeySelected !== null && rawThemeSelected !== null) {
@@ -31808,7 +32521,22 @@ var ThemeManagerModal = function ThemeManagerModal(_ref) {
31808
32521
  onChooseTheme: handleChooseTheme,
31809
32522
  onChangeVariant: changeThemeVariant,
31810
32523
  rawTheme: rawThemeSelected,
31811
- wizardContent: isCreating ? /*#__PURE__*/jsxRuntime.jsx(ThemeQuickCreate, {
32524
+ wizardContent: isChoosingMode ? /*#__PURE__*/jsxRuntime.jsx(ThemeNewChooser, {
32525
+ onSearchThemes: handleChooseSearch,
32526
+ onCreateNew: handleChooseCreate
32527
+ }) : isSearching ? /*#__PURE__*/jsxRuntime.jsx(DiscoverThemesDetail, {
32528
+ onBack: handleBackFromSearch,
32529
+ appId: credentials === null || credentials === void 0 ? void 0 : credentials.appId,
32530
+ onInstallComplete: function onInstallComplete() {
32531
+ if (dashApi && credentials !== null && credentials !== void 0 && credentials.appId) {
32532
+ dashApi.listThemes(credentials.appId, function (e, message) {
32533
+ if (message && message.themes) {
32534
+ changeThemesForApplication(message.themes);
32535
+ }
32536
+ });
32537
+ }
32538
+ }
32539
+ }) : isCreating ? /*#__PURE__*/jsxRuntime.jsx(ThemeQuickCreate, {
31812
32540
  wizardName: wizardName,
31813
32541
  setWizardName: setWizardName,
31814
32542
  wizardMethod: wizardMethod,
@@ -31836,13 +32564,13 @@ var ThemeManagerModal = function ThemeManagerModal(_ref) {
31836
32564
  children: themeKeySelected
31837
32565
  })]
31838
32566
  })
31839
- }), isCreating && /*#__PURE__*/jsxRuntime.jsx("div", {
32567
+ }), (isCreating || isChoosingMode || isSearching) && /*#__PURE__*/jsxRuntime.jsx("div", {
31840
32568
  className: "flex flex-row space-x-2",
31841
32569
  children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
31842
32570
  onClick: handleCancelCreate,
31843
32571
  title: "Cancel"
31844
32572
  })
31845
- }), !isCreating && isEditing === false && /*#__PURE__*/jsxRuntime.jsxs("div", {
32573
+ }), !isCreating && !isChoosingMode && !isSearching && isEditing === false && /*#__PURE__*/jsxRuntime.jsxs("div", {
31846
32574
  className: "flex flex-row space-x-2",
31847
32575
  children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
31848
32576
  onClick: function onClick() {
@@ -31861,7 +32589,7 @@ var ThemeManagerModal = function ThemeManagerModal(_ref) {
31861
32589
  onClick: handleActivateTheme,
31862
32590
  title: "Activate"
31863
32591
  })]
31864
- }), !isCreating && isEditing === true && /*#__PURE__*/jsxRuntime.jsxs("div", {
32592
+ }), !isCreating && !isChoosingMode && !isSearching && isEditing === true && /*#__PURE__*/jsxRuntime.jsxs("div", {
31865
32593
  className: "flex flex-row space-x-2",
31866
32594
  children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
31867
32595
  onClick: function onClick() {
@@ -32808,7 +33536,11 @@ var DashboardDetail = function DashboardDetail(_ref2) {
32808
33536
  t = _ref8[1];
32809
33537
  return {
32810
33538
  label: t.name || key,
32811
- value: key
33539
+ value: key,
33540
+ icon: "palette",
33541
+ badge: /*#__PURE__*/jsxRuntime.jsx(ThemeColorDots, {
33542
+ theme: t
33543
+ })
32812
33544
  };
32813
33545
  }));
32814
33546
  function handleChangeFolder(val) {
@@ -37055,545 +37787,146 @@ var ComponentStyleRow = function ComponentStyleRow(_ref3) {
37055
37787
  title: "".concat(key, ": ").concat(value)
37056
37788
  }, key);
37057
37789
  }
37058
- return /*#__PURE__*/jsxRuntime.jsx("div", {
37059
- className: "h-5 w-5 rounded-sm ".concat(value),
37060
- title: "".concat(key, ": ").concat(value)
37061
- }, key);
37062
- })
37063
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
37064
- className: "flex flex-row items-center gap-2 flex-1 overflow-hidden",
37065
- children: nonColorEntries.map(function (_ref5) {
37066
- var key = _ref5.key,
37067
- value = _ref5.value;
37068
- return /*#__PURE__*/jsxRuntime.jsx("span", {
37069
- className: "text-[10px] opacity-40 whitespace-nowrap",
37070
- title: key,
37071
- children: value
37072
- }, key);
37073
- })
37074
- })]
37075
- });
37076
- };
37077
-
37078
- // --- Main Component ---
37079
-
37080
- var ThemeDetail = function ThemeDetail(_ref6) {
37081
- var themeKey = _ref6.themeKey,
37082
- themes = _ref6.themes,
37083
- currentThemeKey = _ref6.currentThemeKey,
37084
- themeVariant = _ref6.themeVariant,
37085
- onActivate = _ref6.onActivate,
37086
- onOpenThemeEditor = _ref6.onOpenThemeEditor,
37087
- _ref6$onDelete = _ref6.onDelete,
37088
- onDelete = _ref6$onDelete === void 0 ? null : _ref6$onDelete,
37089
- _ref6$appId = _ref6.appId,
37090
- appId = _ref6$appId === void 0 ? null : _ref6$appId;
37091
- var theme = themeKey && themes ? themes[themeKey] : null;
37092
- var _useState = React.useState(false),
37093
- _useState2 = _slicedToArray(_useState, 2),
37094
- publishOpen = _useState2[0],
37095
- setPublishOpen = _useState2[1];
37096
- var canPublish = theme && !theme._registryMeta;
37097
- var displayTheme = React.useMemo(function () {
37098
- return theme ? theme[themeVariant] || {} : {};
37099
- }, [theme, themeVariant]);
37100
- var isActive = themeKey === currentThemeKey;
37101
-
37102
- // Memoize all component styles
37103
- var allStyles = React.useMemo(function () {
37104
- var result = {};
37105
- Object.values(DashReact.themeObjects).forEach(function (key) {
37106
- result[key] = DashReact.getStylesForItem(key, displayTheme, {});
37107
- });
37108
- return result;
37109
- }, [displayTheme]);
37110
- if (!theme) return null;
37111
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
37112
- className: "flex flex-col flex-1 min-h-0",
37113
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
37114
- className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-6",
37115
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
37116
- className: "flex flex-row items-center gap-3",
37117
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading, {
37118
- title: theme.name || themeKey,
37119
- padding: false
37120
- }), isActive && /*#__PURE__*/jsxRuntime.jsx("span", {
37121
- className: "text-xs opacity-40",
37122
- children: "active"
37123
- })]
37124
- }), /*#__PURE__*/jsxRuntime.jsx(ColorSwatchGrid, {
37125
- displayTheme: displayTheme
37126
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
37127
- className: "flex flex-col space-y-2",
37128
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
37129
- className: "text-xs font-semibold opacity-50",
37130
- children: "Component Styles"
37131
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Accordion2, {
37132
- type: "multiple",
37133
- children: COMPONENT_GROUPS.map(function (group) {
37134
- // Only show groups that have valid theme objects
37135
- var validKeys = group.keys.filter(function (k) {
37136
- return DashReact.themeObjects[k];
37137
- });
37138
- if (validKeys.length === 0) return null;
37139
- return /*#__PURE__*/jsxRuntime.jsxs(DashReact.Accordion2.Item, {
37140
- value: group.label,
37141
- children: [/*#__PURE__*/jsxRuntime.jsxs(DashReact.Accordion2.Trigger, {
37142
- value: group.label,
37143
- children: [group.label, " (", validKeys.length, ")"]
37144
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Accordion2.Content, {
37145
- value: group.label,
37146
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
37147
- className: "flex flex-col",
37148
- children: validKeys.map(function (k) {
37149
- var objectValue = DashReact.themeObjects[k];
37150
- return /*#__PURE__*/jsxRuntime.jsx(ComponentStyleRow, {
37151
- objectKey: objectValue,
37152
- styles: allStyles[objectValue]
37153
- }, k);
37154
- })
37155
- })
37156
- })]
37157
- }, group.label);
37158
- })
37159
- })]
37160
- })]
37161
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
37162
- className: "flex-shrink-0 flex flex-row justify-between px-6 py-4 border-t border-white/10",
37163
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
37164
- className: "flex flex-row gap-2",
37165
- children: [!isActive && onDelete && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
37166
- title: "Delete",
37167
- onClick: function onClick() {
37168
- return onDelete(themeKey);
37169
- },
37170
- size: "sm"
37171
- }), canPublish && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
37172
- title: "Publish",
37173
- onClick: function onClick() {
37174
- return setPublishOpen(true);
37175
- },
37176
- size: "sm"
37177
- })]
37178
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
37179
- className: "flex flex-row gap-2",
37180
- children: [!isActive && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
37181
- title: "Activate",
37182
- onClick: function onClick() {
37183
- return onActivate(themeKey);
37184
- },
37185
- size: "sm"
37186
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
37187
- title: "Edit",
37188
- onClick: onOpenThemeEditor,
37189
- size: "sm"
37190
- })]
37191
- })]
37192
- }), canPublish && /*#__PURE__*/jsxRuntime.jsx(PublishThemeModal, {
37193
- isOpen: publishOpen,
37194
- setIsOpen: setPublishOpen,
37195
- appId: appId,
37196
- themeKey: themeKey,
37197
- themeName: theme.name || themeKey
37198
- })]
37199
- });
37200
- };
37201
-
37202
- var RegistryThemeDetail = function RegistryThemeDetail(_ref) {
37203
- var themePackage = _ref.themePackage,
37204
- appId = _ref.appId,
37205
- onInstallComplete = _ref.onInstallComplete;
37206
- var _useContext = React.useContext(DashReact.ThemeContext),
37207
- currentTheme = _useContext.currentTheme,
37208
- changeThemesForApplication = _useContext.changeThemesForApplication;
37209
- var panelStyles = DashReact.getStylesForItem(DashReact.themeObjects.PANEL, currentTheme, {
37210
- grow: false
37211
- });
37212
- var _useState = React.useState(false),
37213
- _useState2 = _slicedToArray(_useState, 2),
37214
- isInstalling = _useState2[0],
37215
- setIsInstalling = _useState2[1];
37216
- var _useState3 = React.useState(null),
37217
- _useState4 = _slicedToArray(_useState3, 2),
37218
- installResult = _useState4[0],
37219
- setInstallResult = _useState4[1];
37220
- var pkg = themePackage;
37221
- if (!pkg) return null;
37222
- var colors = pkg.colors || {};
37223
- function handleInstall() {
37224
- return _handleInstall.apply(this, arguments);
37225
- }
37226
- function _handleInstall() {
37227
- _handleInstall = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
37228
- var result, _t;
37229
- return _regeneratorRuntime.wrap(function (_context) {
37230
- while (1) switch (_context.prev = _context.next) {
37231
- case 0:
37232
- if (!(!appId || !pkg.name)) {
37233
- _context.next = 1;
37234
- break;
37235
- }
37236
- return _context.abrupt("return");
37237
- case 1:
37238
- setIsInstalling(true);
37239
- setInstallResult(null);
37240
- _context.prev = 2;
37241
- _context.next = 3;
37242
- return window.mainApi.themes.installThemeFromRegistry(appId, pkg.name);
37243
- case 3:
37244
- result = _context.sent;
37245
- setInstallResult({
37246
- status: result !== null && result !== void 0 && result.success ? "success" : "error",
37247
- message: result !== null && result !== void 0 && result.success ? "Theme \"".concat(result.themeKey || pkg.displayName || pkg.name, "\" installed successfully.") : (result === null || result === void 0 ? void 0 : result.error) || "Installation failed."
37248
- });
37249
- if (result !== null && result !== void 0 && result.success) {
37250
- // Refresh ThemeContext with updated themes
37251
- if (result.themes) {
37252
- changeThemesForApplication(result.themes);
37253
- }
37254
- if (onInstallComplete) {
37255
- onInstallComplete(result);
37256
- }
37257
- }
37258
- _context.next = 5;
37259
- break;
37260
- case 4:
37261
- _context.prev = 4;
37262
- _t = _context["catch"](2);
37263
- setInstallResult({
37264
- status: "error",
37265
- message: _t.message || "Failed to install theme."
37266
- });
37267
- case 5:
37268
- _context.prev = 5;
37269
- setIsInstalling(false);
37270
- return _context.finish(5);
37271
- case 6:
37272
- case "end":
37273
- return _context.stop();
37274
- }
37275
- }, _callee, null, [[2, 4, 5, 6]]);
37276
- }));
37277
- return _handleInstall.apply(this, arguments);
37278
- }
37279
- var colorEntries = [{
37280
- label: "Primary",
37281
- value: colors.primary
37282
- }, {
37283
- label: "Secondary",
37284
- value: colors.secondary
37285
- }, {
37286
- label: "Tertiary",
37287
- value: colors.tertiary
37288
- }, {
37289
- label: "Neutral",
37290
- value: colors.neutral
37291
- }].filter(function (c) {
37292
- return c.value;
37790
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
37791
+ className: "h-5 w-5 rounded-sm ".concat(value),
37792
+ title: "".concat(key, ": ").concat(value)
37793
+ }, key);
37794
+ })
37795
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
37796
+ className: "flex flex-row items-center gap-2 flex-1 overflow-hidden",
37797
+ children: nonColorEntries.map(function (_ref5) {
37798
+ var key = _ref5.key,
37799
+ value = _ref5.value;
37800
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
37801
+ className: "text-[10px] opacity-40 whitespace-nowrap",
37802
+ title: key,
37803
+ children: value
37804
+ }, key);
37805
+ })
37806
+ })]
37293
37807
  });
37808
+ };
37809
+
37810
+ // --- Main Component ---
37811
+
37812
+ var ThemeDetail = function ThemeDetail(_ref6) {
37813
+ var themeKey = _ref6.themeKey,
37814
+ themes = _ref6.themes,
37815
+ currentThemeKey = _ref6.currentThemeKey,
37816
+ themeVariant = _ref6.themeVariant,
37817
+ onActivate = _ref6.onActivate,
37818
+ onOpenThemeEditor = _ref6.onOpenThemeEditor,
37819
+ _ref6$onDelete = _ref6.onDelete,
37820
+ onDelete = _ref6$onDelete === void 0 ? null : _ref6$onDelete,
37821
+ _ref6$appId = _ref6.appId,
37822
+ appId = _ref6$appId === void 0 ? null : _ref6$appId;
37823
+ var theme = themeKey && themes ? themes[themeKey] : null;
37824
+ var _useState = React.useState(false),
37825
+ _useState2 = _slicedToArray(_useState, 2),
37826
+ publishOpen = _useState2[0],
37827
+ setPublishOpen = _useState2[1];
37828
+ var canPublish = theme && !theme._registryMeta;
37829
+ var displayTheme = React.useMemo(function () {
37830
+ return theme ? theme[themeVariant] || {} : {};
37831
+ }, [theme, themeVariant]);
37832
+ var isActive = themeKey === currentThemeKey;
37833
+
37834
+ // Memoize all component styles
37835
+ var allStyles = React.useMemo(function () {
37836
+ var result = {};
37837
+ Object.values(DashReact.themeObjects).forEach(function (key) {
37838
+ result[key] = DashReact.getStylesForItem(key, displayTheme, {});
37839
+ });
37840
+ return result;
37841
+ }, [displayTheme]);
37842
+ if (!theme) return null;
37294
37843
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
37295
37844
  className: "flex flex-col flex-1 min-h-0",
37296
37845
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
37297
- className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-6 ".concat(panelStyles.textColor || "text-gray-200"),
37846
+ className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-6",
37298
37847
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
37299
37848
  className: "flex flex-row items-center gap-3",
37300
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
37301
- className: "h-5 w-5 flex-shrink-0 flex items-center justify-center",
37302
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
37303
- icon: "palette",
37304
- className: "h-5 w-5"
37305
- })
37306
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
37307
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading3, {
37308
- title: pkg.displayName || pkg.name,
37309
- padding: false
37310
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
37311
- className: "flex items-center gap-2 mt-0.5",
37312
- children: [/*#__PURE__*/jsxRuntime.jsxs("span", {
37313
- className: "text-sm opacity-60",
37314
- children: ["by ", pkg.author || "Unknown"]
37315
- }), pkg.version && /*#__PURE__*/jsxRuntime.jsxs("span", {
37316
- className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " opacity-70"),
37317
- children: ["v", pkg.version]
37318
- })]
37319
- })]
37849
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading, {
37850
+ title: theme.name || themeKey,
37851
+ padding: false
37852
+ }), isActive && /*#__PURE__*/jsxRuntime.jsx("span", {
37853
+ className: "text-xs opacity-40",
37854
+ children: "active"
37320
37855
  })]
37321
- }), /*#__PURE__*/jsxRuntime.jsx("hr", {
37322
- className: currentTheme["border-primary-medium"]
37323
- }), colorEntries.length > 0 && /*#__PURE__*/jsxRuntime.jsxs("div", {
37856
+ }), /*#__PURE__*/jsxRuntime.jsx(ColorSwatchGrid, {
37857
+ displayTheme: displayTheme
37858
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
37859
+ className: "flex flex-col space-y-2",
37324
37860
  children: [/*#__PURE__*/jsxRuntime.jsx("span", {
37325
- className: "text-xs font-semibold opacity-50 mb-2 block",
37326
- children: "COLORS"
37327
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
37328
- className: "flex flex-row gap-3",
37329
- children: colorEntries.map(function (_ref2) {
37330
- var label = _ref2.label,
37331
- value = _ref2.value;
37332
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
37333
- className: "flex flex-col items-center gap-1",
37334
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
37335
- className: "h-10 w-10 rounded-full border-2 border-white/20",
37336
- style: {
37337
- backgroundColor: value
37338
- }
37339
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
37340
- className: "text-[10px] opacity-50",
37341
- children: label
37342
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
37343
- className: "text-[10px] opacity-30 font-mono",
37344
- children: value
37345
- })]
37346
- }, label);
37347
- })
37348
- })]
37349
- }), pkg.description && /*#__PURE__*/jsxRuntime.jsx("p", {
37350
- className: "text-sm",
37351
- children: pkg.description
37352
- }), pkg.tags && pkg.tags.length > 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
37353
- className: "flex flex-wrap gap-1",
37354
- children: pkg.tags.map(function (tag) {
37355
- return /*#__PURE__*/jsxRuntime.jsx("span", {
37356
- className: "text-xs px-2 py-0.5 rounded ".concat(currentTheme["bg-primary-medium"], " opacity-60"),
37357
- children: tag
37358
- }, tag);
37359
- })
37360
- }), installResult && /*#__PURE__*/jsxRuntime.jsx("div", {
37361
- className: "p-2 rounded border ".concat(installResult.status === "success" ? "bg-green-900/20 border-green-700" : "bg-red-900/30 border-red-700"),
37362
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
37363
- className: "flex items-center gap-2",
37364
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
37365
- icon: installResult.status === "success" ? "circle-check" : "circle-xmark",
37366
- className: "h-4 w-4 ".concat(installResult.status === "success" ? "text-green-400" : "text-red-400")
37367
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
37368
- className: "text-sm ".concat(installResult.status === "error" ? "text-red-400" : ""),
37369
- children: installResult.message
37370
- })]
37371
- })
37372
- })]
37373
- }), (installResult === null || installResult === void 0 ? void 0 : installResult.status) !== "success" && /*#__PURE__*/jsxRuntime.jsx("div", {
37374
- className: "flex items-center justify-end px-6 py-3 border-t ".concat(currentTheme["border-primary-medium"]),
37375
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
37376
- title: isInstalling ? "Installing..." : "Install Theme",
37377
- bgColor: "bg-blue-600",
37378
- hoverBackgroundColor: isInstalling ? "" : "hover:bg-blue-700",
37379
- textSize: "text-sm",
37380
- padding: "py-1.5 px-4",
37381
- onClick: handleInstall,
37382
- disabled: isInstalling
37383
- })
37384
- })]
37385
- });
37386
- };
37387
-
37388
- var DiscoverThemesDetail = function DiscoverThemesDetail(_ref) {
37389
- var onBack = _ref.onBack,
37390
- appId = _ref.appId,
37391
- onInstallComplete = _ref.onInstallComplete;
37392
- var _useContext = React.useContext(DashReact.ThemeContext),
37393
- currentTheme = _useContext.currentTheme;
37394
- var panelStyles = DashReact.getStylesForItem(DashReact.themeObjects.PANEL, currentTheme, {
37395
- grow: false
37396
- });
37397
- var _useState = React.useState([]),
37398
- _useState2 = _slicedToArray(_useState, 2),
37399
- packages = _useState2[0],
37400
- setPackages = _useState2[1];
37401
- var _useState3 = React.useState(false),
37402
- _useState4 = _slicedToArray(_useState3, 2),
37403
- isLoading = _useState4[0],
37404
- setIsLoading = _useState4[1];
37405
- var _useState5 = React.useState(null),
37406
- _useState6 = _slicedToArray(_useState5, 2),
37407
- error = _useState6[0],
37408
- setError = _useState6[1];
37409
- var _useState7 = React.useState(""),
37410
- _useState8 = _slicedToArray(_useState7, 2),
37411
- searchQuery = _useState8[0],
37412
- setSearchQuery = _useState8[1];
37413
- var _useState9 = React.useState(null),
37414
- _useState0 = _slicedToArray(_useState9, 2),
37415
- selectedPackageName = _useState0[0],
37416
- setSelectedPackageName = _useState0[1];
37417
- var search = React.useCallback(/*#__PURE__*/function () {
37418
- var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(query) {
37419
- var _window$mainApi;
37420
- var result, _t;
37421
- return _regeneratorRuntime.wrap(function (_context) {
37422
- while (1) switch (_context.prev = _context.next) {
37423
- case 0:
37424
- if ((_window$mainApi = window.mainApi) !== null && _window$mainApi !== void 0 && (_window$mainApi = _window$mainApi.registry) !== null && _window$mainApi !== void 0 && _window$mainApi.searchThemes) {
37425
- _context.next = 1;
37426
- break;
37427
- }
37428
- setPackages([]);
37429
- return _context.abrupt("return");
37430
- case 1:
37431
- setIsLoading(true);
37432
- setError(null);
37433
- _context.prev = 2;
37434
- _context.next = 3;
37435
- return window.mainApi.registry.searchThemes(query || "", {});
37436
- case 3:
37437
- result = _context.sent;
37438
- setPackages((result === null || result === void 0 ? void 0 : result.packages) || []);
37439
- _context.next = 5;
37440
- break;
37441
- case 4:
37442
- _context.prev = 4;
37443
- _t = _context["catch"](2);
37444
- setError(_t.message || "Failed to search theme registry");
37445
- setPackages([]);
37446
- case 5:
37447
- _context.prev = 5;
37448
- setIsLoading(false);
37449
- return _context.finish(5);
37450
- case 6:
37451
- case "end":
37452
- return _context.stop();
37453
- }
37454
- }, _callee, null, [[2, 4, 5, 6]]);
37455
- }));
37456
- return function (_x) {
37457
- return _ref2.apply(this, arguments);
37458
- };
37459
- }(), []);
37460
-
37461
- // Debounce search on query changes
37462
- React.useEffect(function () {
37463
- var timer = setTimeout(function () {
37464
- search(searchQuery);
37465
- }, 300);
37466
- return function () {
37467
- return clearTimeout(timer);
37468
- };
37469
- // eslint-disable-next-line react-hooks/exhaustive-deps
37470
- }, [searchQuery]);
37471
- var retry = function retry() {
37472
- return search(searchQuery);
37473
- };
37474
- var selectedPackage = selectedPackageName ? packages.find(function (p) {
37475
- return p.name === selectedPackageName;
37476
- }) : null;
37477
-
37478
- // If a package is selected, show its detail inline
37479
- if (selectedPackage) {
37480
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
37481
- className: "flex flex-col flex-1 min-h-0",
37482
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
37483
- className: "flex-shrink-0 px-4 pt-4",
37484
- children: /*#__PURE__*/jsxRuntime.jsxs("button", {
37485
- type: "button",
37861
+ className: "text-xs font-semibold opacity-50",
37862
+ children: "Component Styles"
37863
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Accordion2, {
37864
+ type: "multiple",
37865
+ children: COMPONENT_GROUPS.map(function (group) {
37866
+ // Only show groups that have valid theme objects
37867
+ var validKeys = group.keys.filter(function (k) {
37868
+ return DashReact.themeObjects[k];
37869
+ });
37870
+ if (validKeys.length === 0) return null;
37871
+ return /*#__PURE__*/jsxRuntime.jsxs(DashReact.Accordion2.Item, {
37872
+ value: group.label,
37873
+ children: [/*#__PURE__*/jsxRuntime.jsxs(DashReact.Accordion2.Trigger, {
37874
+ value: group.label,
37875
+ children: [group.label, " (", validKeys.length, ")"]
37876
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Accordion2.Content, {
37877
+ value: group.label,
37878
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
37879
+ className: "flex flex-col",
37880
+ children: validKeys.map(function (k) {
37881
+ var objectValue = DashReact.themeObjects[k];
37882
+ return /*#__PURE__*/jsxRuntime.jsx(ComponentStyleRow, {
37883
+ objectKey: objectValue,
37884
+ styles: allStyles[objectValue]
37885
+ }, k);
37886
+ })
37887
+ })
37888
+ })]
37889
+ }, group.label);
37890
+ })
37891
+ })]
37892
+ })]
37893
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
37894
+ className: "flex-shrink-0 flex flex-row justify-between px-6 py-4 border-t border-white/10",
37895
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
37896
+ className: "flex flex-row gap-2",
37897
+ children: [!isActive && onDelete && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
37898
+ title: "Delete",
37486
37899
  onClick: function onClick() {
37487
- return setSelectedPackageName(null);
37900
+ return onDelete(themeKey);
37488
37901
  },
37489
- className: "flex items-center gap-1.5 text-sm opacity-60 hover:opacity-100 transition-opacity",
37490
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
37491
- icon: "arrow-left",
37492
- className: "h-3 w-3"
37493
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
37494
- children: "Back"
37495
- })]
37496
- })
37497
- }), /*#__PURE__*/jsxRuntime.jsx(RegistryThemeDetail, {
37498
- themePackage: selectedPackage,
37499
- appId: appId,
37500
- onInstallComplete: onInstallComplete
37501
- })]
37502
- });
37503
- }
37504
-
37505
- // Package list view
37506
- var listBody;
37507
- if (isLoading) {
37508
- listBody = /*#__PURE__*/jsxRuntime.jsx("div", {
37509
- className: "flex items-center justify-center py-12",
37510
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
37511
- className: "text-center",
37512
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
37513
- className: "animate-spin rounded-full h-6 w-6 border-b-2 border-blue-500 mx-auto mb-3"
37514
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Paragraph, {
37515
- className: "text-sm opacity-50",
37516
- children: "Loading themes..."
37902
+ size: "sm"
37903
+ }), canPublish && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
37904
+ title: "Publish",
37905
+ onClick: function onClick() {
37906
+ return setPublishOpen(true);
37907
+ },
37908
+ size: "sm"
37517
37909
  })]
37518
- })
37519
- });
37520
- } else if (error) {
37521
- listBody = /*#__PURE__*/jsxRuntime.jsxs("div", {
37522
- className: "px-4 py-8 text-center",
37523
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Paragraph, {
37524
- className: "text-sm text-red-400 mb-3",
37525
- children: error
37526
- }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
37527
- title: "Retry",
37528
- bgColor: "bg-gray-700",
37529
- hoverBackgroundColor: "hover:bg-gray-600",
37530
- textSize: "text-sm",
37531
- padding: "py-1 px-3",
37532
- onClick: retry
37533
- })]
37534
- });
37535
- } else if (packages.length === 0) {
37536
- listBody = /*#__PURE__*/jsxRuntime.jsx("div", {
37537
- className: "px-4 py-8 text-center",
37538
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Paragraph, {
37539
- className: "text-sm opacity-50",
37540
- children: searchQuery ? "No themes match your search." : "No theme packages available."
37541
- })
37542
- });
37543
- } else {
37544
- listBody = /*#__PURE__*/jsxRuntime.jsx("div", {
37545
- className: "space-y-1",
37546
- children: packages.map(function (pkg) {
37547
- var colors = pkg.colors || {};
37548
- return /*#__PURE__*/jsxRuntime.jsx(DashReact.Sidebar.Item, {
37549
- icon: /*#__PURE__*/jsxRuntime.jsx("div", {
37550
- className: "flex items-center gap-0.5",
37551
- children: [colors.primary, colors.secondary, colors.tertiary].filter(Boolean).map(function (color, i) {
37552
- return /*#__PURE__*/jsxRuntime.jsx("div", {
37553
- className: "h-3 w-3 rounded-full border border-white/20",
37554
- style: {
37555
- backgroundColor: color
37556
- }
37557
- }, i);
37558
- })
37559
- }),
37910
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
37911
+ className: "flex flex-row gap-2",
37912
+ children: [!isActive && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
37913
+ title: "Activate",
37560
37914
  onClick: function onClick() {
37561
- return setSelectedPackageName(pkg.name);
37915
+ return onActivate(themeKey);
37562
37916
  },
37563
- children: pkg.displayName || pkg.name
37564
- }, pkg.name);
37565
- })
37566
- });
37567
- }
37568
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
37569
- className: "flex flex-col flex-1 min-h-0 ".concat(panelStyles.textColor || "text-gray-200"),
37570
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
37571
- className: "flex-shrink-0 px-4 pt-4",
37572
- children: /*#__PURE__*/jsxRuntime.jsxs("button", {
37573
- type: "button",
37574
- onClick: onBack,
37575
- className: "flex items-center gap-1.5 text-sm opacity-60 hover:opacity-100 transition-opacity",
37576
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
37577
- icon: "arrow-left",
37578
- className: "h-3 w-3"
37579
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
37580
- children: "Back"
37917
+ size: "sm"
37918
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
37919
+ title: "Edit",
37920
+ onClick: onOpenThemeEditor,
37921
+ size: "sm"
37581
37922
  })]
37582
- })
37583
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
37584
- className: "flex-shrink-0 px-4 py-3",
37585
- children: /*#__PURE__*/jsxRuntime.jsx(DashReact.SearchInput, {
37586
- value: searchQuery,
37587
- onChange: setSearchQuery,
37588
- placeholder: "Search themes...",
37589
- inputClassName: "py-1.5 text-xs"
37590
- })
37591
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
37592
- className: "flex-1 min-h-0 overflow-y-auto px-2",
37593
- children: listBody
37594
- }), !isLoading && !error && packages.length > 0 && /*#__PURE__*/jsxRuntime.jsxs("div", {
37595
- className: "flex-shrink-0 px-4 py-2 text-[10px] opacity-40 border-t border-white/10",
37596
- children: [packages.length, " theme", packages.length !== 1 ? "s" : ""]
37923
+ })]
37924
+ }), canPublish && /*#__PURE__*/jsxRuntime.jsx(PublishThemeModal, {
37925
+ isOpen: publishOpen,
37926
+ setIsOpen: setPublishOpen,
37927
+ appId: appId,
37928
+ themeKey: themeKey,
37929
+ themeName: theme.name || themeKey
37597
37930
  })]
37598
37931
  });
37599
37932
  };
@@ -37644,6 +37977,10 @@ var ThemesSection = function ThemesSection(_ref) {
37644
37977
  _useState10 = _slicedToArray(_useState1, 2),
37645
37978
  installMode = _useState10[0],
37646
37979
  setInstallMode = _useState10[1];
37980
+ var _useState11 = React.useState(false),
37981
+ _useState12 = _slicedToArray(_useState11, 2),
37982
+ enteredViaChooser = _useState12[0],
37983
+ setEnteredViaChooser = _useState12[1];
37647
37984
  var themeEntries = themes ? Object.entries(themes) : [];
37648
37985
  var appId = credentials === null || credentials === void 0 ? void 0 : credentials.appId;
37649
37986
  var rowStyles = DashReact.getStylesForItem(DashReact.themeObjects.PANEL_HEADER, currentTheme, {
@@ -37654,7 +37991,7 @@ var ThemesSection = function ThemesSection(_ref) {
37654
37991
  var prevCreateRequested = React.useRef(false);
37655
37992
  React.useEffect(function () {
37656
37993
  if (createRequested && !prevCreateRequested.current) {
37657
- setGenerateMode(GENERATE_MODES.WIZARD);
37994
+ setGenerateMode(GENERATE_MODES.CHOOSER);
37658
37995
  setWizardName("");
37659
37996
  setWizardMethod(null);
37660
37997
  setWizardTheme(null);
@@ -37736,9 +38073,9 @@ var ThemesSection = function ThemesSection(_ref) {
37736
38073
  }
37737
38074
  var listContent = /*#__PURE__*/jsxRuntime.jsxs("div", {
37738
38075
  className: "flex flex-col h-full",
37739
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
38076
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
37740
38077
  className: "flex-shrink-0 flex flex-col gap-2 px-3 py-2 ".concat(rowStyles.backgroundColor || ""),
37741
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
38078
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
37742
38079
  className: "flex flex-row items-center justify-between",
37743
38080
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
37744
38081
  className: "flex flex-row items-center gap-2",
@@ -37756,32 +38093,7 @@ var ThemesSection = function ThemesSection(_ref) {
37756
38093
  className: "text-xs opacity-50",
37757
38094
  children: themeVariant === "dark" ? "Dark" : "Light"
37758
38095
  })]
37759
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
37760
- className: "flex bg-white/5 rounded-md p-0.5",
37761
- children: [{
37762
- key: "themes",
37763
- label: "My Themes"
37764
- }, {
37765
- key: "marketplace",
37766
- label: "Marketplace"
37767
- }].map(function (tab) {
37768
- var currentTab = installMode === "marketplace" ? "marketplace" : "themes";
37769
- return /*#__PURE__*/jsxRuntime.jsx("button", {
37770
- type: "button",
37771
- onClick: function onClick() {
37772
- if (tab.key === "marketplace") {
37773
- setInstallMode("marketplace");
37774
- setSelectedThemeKey(null);
37775
- setGenerateMode(GENERATE_MODES.NONE);
37776
- } else {
37777
- setInstallMode(null);
37778
- }
37779
- },
37780
- className: "flex-1 px-2 py-0.5 rounded text-[11px] transition-colors ".concat(currentTab === tab.key ? "bg-white/10 font-medium opacity-90" : "opacity-50 hover:opacity-70"),
37781
- children: tab.label
37782
- }, tab.key);
37783
- })
37784
- })]
38096
+ })
37785
38097
  }), /*#__PURE__*/jsxRuntime.jsx("div", {
37786
38098
  className: "flex-1 overflow-y-auto min-h-0",
37787
38099
  children: /*#__PURE__*/jsxRuntime.jsxs(DashReact.Sidebar.Content, {
@@ -37805,7 +38117,9 @@ var ThemesSection = function ThemesSection(_ref) {
37805
38117
  setGenerateMode(GENERATE_MODES.NONE);
37806
38118
  setInstallMode(null);
37807
38119
  },
37808
- badge: isActive ? "active" : null,
38120
+ badge: /*#__PURE__*/jsxRuntime.jsx(ThemeColorDots, {
38121
+ theme: theme
38122
+ }),
37809
38123
  className: isSelected ? "bg-white/10 opacity-100" : "",
37810
38124
  children: theme.name || key
37811
38125
  }, key);
@@ -37823,6 +38137,10 @@ var ThemesSection = function ThemesSection(_ref) {
37823
38137
  detailContent = /*#__PURE__*/jsxRuntime.jsx(DiscoverThemesDetail, {
37824
38138
  onBack: function onBack() {
37825
38139
  setInstallMode(null);
38140
+ if (enteredViaChooser) {
38141
+ setGenerateMode(GENERATE_MODES.CHOOSER);
38142
+ setEnteredViaChooser(false);
38143
+ }
37826
38144
  },
37827
38145
  appId: appId,
37828
38146
  onInstallComplete: function onInstallComplete() {
@@ -37836,6 +38154,17 @@ var ThemesSection = function ThemesSection(_ref) {
37836
38154
  }
37837
38155
  }
37838
38156
  });
38157
+ } else if (generateMode === GENERATE_MODES.CHOOSER) {
38158
+ detailContent = /*#__PURE__*/jsxRuntime.jsx(ThemeNewChooser, {
38159
+ onSearchThemes: function onSearchThemes() {
38160
+ setGenerateMode(GENERATE_MODES.NONE);
38161
+ setInstallMode("marketplace");
38162
+ setEnteredViaChooser(true);
38163
+ },
38164
+ onCreateNew: function onCreateNew() {
38165
+ setGenerateMode(GENERATE_MODES.WIZARD);
38166
+ }
38167
+ });
37839
38168
  } else if (generateMode === GENERATE_MODES.WIZARD) {
37840
38169
  detailContent = /*#__PURE__*/jsxRuntime.jsx(ThemeQuickCreate, {
37841
38170
  wizardName: wizardName,
@@ -38186,7 +38515,9 @@ var RegistryPackageDetail = function RegistryPackageDetail(_ref) {
38186
38515
  _ref$isInstalling = _ref.isInstalling,
38187
38516
  isInstalling = _ref$isInstalling === void 0 ? false : _ref$isInstalling,
38188
38517
  _ref$installError = _ref.installError,
38189
- installError = _ref$installError === void 0 ? null : _ref$installError;
38518
+ installError = _ref$installError === void 0 ? null : _ref$installError,
38519
+ _ref$isInstalled = _ref.isInstalled,
38520
+ isInstalled = _ref$isInstalled === void 0 ? false : _ref$isInstalled;
38190
38521
  var _useContext = React.useContext(DashReact.ThemeContext),
38191
38522
  currentTheme = _useContext.currentTheme;
38192
38523
  var panelStyles = DashReact.getStylesForItem(DashReact.themeObjects.PANEL, currentTheme, {
@@ -38206,9 +38537,15 @@ var RegistryPackageDetail = function RegistryPackageDetail(_ref) {
38206
38537
  className: "h-5 w-5"
38207
38538
  })
38208
38539
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
38209
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading3, {
38210
- title: widget.packageDisplayName,
38211
- padding: false
38540
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
38541
+ className: "flex items-center gap-2",
38542
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading3, {
38543
+ title: widget.packageDisplayName,
38544
+ padding: false
38545
+ }), isInstalled && /*#__PURE__*/jsxRuntime.jsx("span", {
38546
+ className: "text-[10px] px-1.5 py-0.5 rounded bg-emerald-500/20 text-emerald-400 flex-shrink-0",
38547
+ children: "Installed"
38548
+ })]
38212
38549
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
38213
38550
  className: "flex items-center gap-2 mt-0.5",
38214
38551
  children: [/*#__PURE__*/jsxRuntime.jsxs("span", {
@@ -38319,13 +38656,13 @@ var RegistryPackageDetail = function RegistryPackageDetail(_ref) {
38319
38656
  }), /*#__PURE__*/jsxRuntime.jsx("div", {
38320
38657
  className: "flex items-center justify-end px-6 py-3 border-t ".concat(currentTheme["border-primary-medium"]),
38321
38658
  children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
38322
- title: isInstalling ? "Installing..." : "Install Package",
38323
- bgColor: "bg-blue-600",
38324
- hoverBackgroundColor: isInstalling ? "" : "hover:bg-blue-700",
38659
+ title: isInstalled ? "Installed" : isInstalling ? "Installing..." : "Install Package",
38660
+ bgColor: isInstalled ? "bg-emerald-600/50" : "bg-blue-600",
38661
+ hoverBackgroundColor: isInstalled || isInstalling ? "" : "hover:bg-blue-700",
38325
38662
  textSize: "text-sm",
38326
38663
  padding: "py-1.5 px-4",
38327
38664
  onClick: onInstall,
38328
- disabled: isInstalling
38665
+ disabled: isInstalling || isInstalled
38329
38666
  })
38330
38667
  })]
38331
38668
  });
@@ -38428,7 +38765,11 @@ var useRegistrySearch = function useRegistrySearch() {
38428
38765
  return window.mainApi.registry.search(query !== null && query !== void 0 ? query : searchQuery, filters);
38429
38766
  case 3:
38430
38767
  result = _context.sent;
38431
- pkgs = result.packages || [];
38768
+ // Only include packages that contain at least one widget
38769
+ // (filters out theme-only packages, etc.)
38770
+ pkgs = (result.packages || []).filter(function (pkg) {
38771
+ return pkg.widgets && pkg.widgets.length > 0;
38772
+ });
38432
38773
  setPackages(pkgs);
38433
38774
 
38434
38775
  // Flatten packages into widget entries
@@ -38647,6 +38988,83 @@ var DiscoverWidgetsDetail = function DiscoverWidgetsDetail(_ref) {
38647
38988
  _useState4 = _slicedToArray(_useState3, 2),
38648
38989
  toolConflictWarning = _useState4[0],
38649
38990
  setToolConflictWarning = _useState4[1];
38991
+
38992
+ // Track installed package names (same pattern as WidgetSidebar)
38993
+ var _useState5 = React.useState(new Set()),
38994
+ _useState6 = _slicedToArray(_useState5, 2),
38995
+ installedPackageNames = _useState6[0],
38996
+ setInstalledPackageNames = _useState6[1];
38997
+ var loadInstalledPackages = React.useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
38998
+ var widgets, names, _iterator, _step, w, folderName, _folderName;
38999
+ return _regeneratorRuntime.wrap(function (_context) {
39000
+ while (1) switch (_context.prev = _context.next) {
39001
+ case 0:
39002
+ _context.prev = 0;
39003
+ _context.next = 1;
39004
+ return window.mainApi.widgets.list();
39005
+ case 1:
39006
+ widgets = _context.sent;
39007
+ names = new Set();
39008
+ _iterator = _createForOfIteratorHelper$2(widgets);
39009
+ try {
39010
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
39011
+ w = _step.value;
39012
+ if (w.name) names.add(w.name);
39013
+ if (w.path) {
39014
+ folderName = w.path.split("/").pop();
39015
+ if (folderName) names.add(folderName);
39016
+ }
39017
+ if (w.author && w.name) {
39018
+ names.add("".concat(w.author, "/").concat(w.name));
39019
+ }
39020
+ if (w.author && w.path) {
39021
+ _folderName = w.path.split("/").pop();
39022
+ if (_folderName) names.add("".concat(w.author, "/").concat(_folderName));
39023
+ }
39024
+ }
39025
+ } catch (err) {
39026
+ _iterator.e(err);
39027
+ } finally {
39028
+ _iterator.f();
39029
+ }
39030
+ setInstalledPackageNames(names);
39031
+ _context.next = 3;
39032
+ break;
39033
+ case 2:
39034
+ _context.prev = 2;
39035
+ _context["catch"](0);
39036
+ case 3:
39037
+ case "end":
39038
+ return _context.stop();
39039
+ }
39040
+ }, _callee, null, [[0, 2]]);
39041
+ })), []);
39042
+ React.useEffect(function () {
39043
+ loadInstalledPackages();
39044
+ var handleWidgetsUpdated = function handleWidgetsUpdated() {
39045
+ return loadInstalledPackages();
39046
+ };
39047
+ window.addEventListener("dash:widgets-updated", handleWidgetsUpdated);
39048
+ return function () {
39049
+ return window.removeEventListener("dash:widgets-updated", handleWidgetsUpdated);
39050
+ };
39051
+ }, [loadInstalledPackages]);
39052
+ var isPackageInstalled = React.useCallback(function (pkg) {
39053
+ if (installedPackageNames.has(pkg.name) || pkg.scope && installedPackageNames.has("".concat(pkg.scope, "/").concat(pkg.name))) {
39054
+ return true;
39055
+ }
39056
+ var packageWidgets = pkg.widgets || [];
39057
+ if (packageWidgets.length > 0) {
39058
+ var cMap = ComponentManager.componentMap();
39059
+ var cMapKeys = Object.keys(cMap);
39060
+ return packageWidgets.some(function (w) {
39061
+ return w.name in cMap || cMapKeys.some(function (k) {
39062
+ return k === w.name || k.endsWith("_".concat(w.name));
39063
+ });
39064
+ });
39065
+ }
39066
+ return false;
39067
+ }, [installedPackageNames]);
38650
39068
  var selectedWidget = selectedPackageName ? flatWidgets.find(function (w) {
38651
39069
  return w.packageName === selectedPackageName;
38652
39070
  }) : null;
@@ -38655,31 +39073,31 @@ var DiscoverWidgetsDetail = function DiscoverWidgetsDetail(_ref) {
38655
39073
  var checkToolConflicts = function checkToolConflicts(widget) {
38656
39074
  var conflicts = [];
38657
39075
  var packageWidgets = widget.packageWidgets || [];
38658
- var _iterator = _createForOfIteratorHelper$2(packageWidgets),
38659
- _step;
39076
+ var _iterator2 = _createForOfIteratorHelper$2(packageWidgets),
39077
+ _step2;
38660
39078
  try {
38661
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
38662
- var w = _step.value;
38663
- var _iterator2 = _createForOfIteratorHelper$2(w.providers || []),
38664
- _step2;
39079
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
39080
+ var w = _step2.value;
39081
+ var _iterator3 = _createForOfIteratorHelper$2(w.providers || []),
39082
+ _step3;
38665
39083
  try {
38666
39084
  var _loop = function _loop() {
38667
39085
  var _p$requiredTools;
38668
- var p = _step2.value;
39086
+ var p = _step3.value;
38669
39087
  if (!((_p$requiredTools = p.requiredTools) !== null && _p$requiredTools !== void 0 && _p$requiredTools.length) || p.providerClass !== "mcp") return 1; // continue
38670
39088
  // Find matching user provider
38671
- var matchingProviders = Object.entries(providers).filter(function (_ref2) {
38672
- var _ref3 = _slicedToArray(_ref2, 2),
38673
- prov = _ref3[1];
39089
+ var matchingProviders = Object.entries(providers).filter(function (_ref3) {
39090
+ var _ref4 = _slicedToArray(_ref3, 2),
39091
+ prov = _ref4[1];
38674
39092
  return prov.type === p.type && prov.providerClass === "mcp" && prov.allowedTools;
38675
39093
  });
38676
- var _iterator3 = _createForOfIteratorHelper$2(matchingProviders),
38677
- _step3;
39094
+ var _iterator4 = _createForOfIteratorHelper$2(matchingProviders),
39095
+ _step4;
38678
39096
  try {
38679
39097
  var _loop2 = function _loop2() {
38680
- var _step3$value = _slicedToArray(_step3.value, 2),
38681
- provName = _step3$value[0],
38682
- prov = _step3$value[1];
39098
+ var _step4$value = _slicedToArray(_step4.value, 2),
39099
+ provName = _step4$value[0],
39100
+ prov = _step4$value[1];
38683
39101
  var blocked = p.requiredTools.filter(function (t) {
38684
39102
  return !prov.allowedTools.includes(t);
38685
39103
  });
@@ -38691,28 +39109,28 @@ var DiscoverWidgetsDetail = function DiscoverWidgetsDetail(_ref) {
38691
39109
  });
38692
39110
  }
38693
39111
  };
38694
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
39112
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
38695
39113
  _loop2();
38696
39114
  }
38697
39115
  } catch (err) {
38698
- _iterator3.e(err);
39116
+ _iterator4.e(err);
38699
39117
  } finally {
38700
- _iterator3.f();
39118
+ _iterator4.f();
38701
39119
  }
38702
39120
  };
38703
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
39121
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
38704
39122
  if (_loop()) continue;
38705
39123
  }
38706
39124
  } catch (err) {
38707
- _iterator2.e(err);
39125
+ _iterator3.e(err);
38708
39126
  } finally {
38709
- _iterator2.f();
39127
+ _iterator3.f();
38710
39128
  }
38711
39129
  }
38712
39130
  } catch (err) {
38713
- _iterator.e(err);
39131
+ _iterator2.e(err);
38714
39132
  } finally {
38715
- _iterator.f();
39133
+ _iterator2.f();
38716
39134
  }
38717
39135
  return conflicts;
38718
39136
  };
@@ -38755,7 +39173,10 @@ var DiscoverWidgetsDetail = function DiscoverWidgetsDetail(_ref) {
38755
39173
  widget: selectedWidget,
38756
39174
  onInstall: handleInstall,
38757
39175
  isInstalling: isInstalling,
38758
- installError: installError
39176
+ installError: installError,
39177
+ isInstalled: selectedWidget ? isPackageInstalled(packages.find(function (p) {
39178
+ return p.name === selectedPackageName;
39179
+ }) || {}) : false
38759
39180
  })]
38760
39181
  });
38761
39182
  }
@@ -38808,6 +39229,7 @@ var DiscoverWidgetsDetail = function DiscoverWidgetsDetail(_ref) {
38808
39229
  return w.packageName === pkg.name;
38809
39230
  });
38810
39231
  var hasIncompatible = (pkgWidget === null || pkgWidget === void 0 ? void 0 : pkgWidget.missingApis) && pkgWidget.missingApis.length > 0;
39232
+ var isInstalled = isPackageInstalled(pkg);
38811
39233
  return /*#__PURE__*/jsxRuntime.jsx(DashReact.Sidebar.Item, {
38812
39234
  icon: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
38813
39235
  icon: hasIncompatible ? "triangle-exclamation" : "cube",
@@ -38817,7 +39239,14 @@ var DiscoverWidgetsDetail = function DiscoverWidgetsDetail(_ref) {
38817
39239
  return setSelectedPackageName(pkg.name);
38818
39240
  },
38819
39241
  badge: "".concat(widgetCount),
38820
- children: pkg.displayName || pkg.name
39242
+ className: isInstalled ? "opacity-50" : "",
39243
+ children: /*#__PURE__*/jsxRuntime.jsxs("span", {
39244
+ className: "flex items-center gap-1.5",
39245
+ children: [pkg.displayName || pkg.name, isInstalled && /*#__PURE__*/jsxRuntime.jsx("span", {
39246
+ className: "text-[10px] text-emerald-400",
39247
+ children: "Installed"
39248
+ })]
39249
+ })
38821
39250
  }, pkg.name);
38822
39251
  })
38823
39252
  });
@@ -44897,6 +45326,7 @@ exports.THEME_SAVE = THEME_SAVE;
44897
45326
  exports.THEME_SAVE_COMPLETE = THEME_SAVE_COMPLETE;
44898
45327
  exports.THEME_SAVE_ERROR = THEME_SAVE_ERROR;
44899
45328
  exports.ThemeApi = ThemeApi;
45329
+ exports.ThemeColorDots = ThemeColorDots;
44900
45330
  exports.ThemeManagerModal = ThemeManagerModal;
44901
45331
  exports.ThemeModel = ThemeModel;
44902
45332
  exports.ThemeWrapper = ThemeWrapper;