@trops/dash-core 0.1.383 → 0.1.385

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -51607,6 +51607,8 @@ var FooterPopover = function FooterPopover(_ref3) {
51607
51607
  _useState2 = _slicedToArray(_useState, 2),
51608
51608
  doNotDisturb = _useState2[0],
51609
51609
  setDoNotDisturb = _useState2[1];
51610
+ var _ref4 = useContext(ThemeContext) || {},
51611
+ currentTheme = _ref4.currentTheme;
51610
51612
  var displayName = authStatus === "authenticated" && authProfile ? authProfile.displayName || authProfile.username : "Account";
51611
51613
 
51612
51614
  // Load initial DND state
@@ -51645,10 +51647,10 @@ var FooterPopover = function FooterPopover(_ref3) {
51645
51647
  }
51646
51648
  return /*#__PURE__*/jsx(Popover, {
51647
51649
  className: "relative",
51648
- children: function children(_ref4) {
51650
+ children: function children(_ref5) {
51649
51651
  var _rect$left;
51650
- var open = _ref4.open,
51651
- close = _ref4.close;
51652
+ var open = _ref5.open,
51653
+ close = _ref5.close;
51652
51654
  var rect = open && buttonRef.current ? buttonRef.current.getBoundingClientRect() : null;
51653
51655
  return /*#__PURE__*/jsxs(Fragment, {
51654
51656
  children: [/*#__PURE__*/jsxs(Popover.Button, {
@@ -51678,7 +51680,7 @@ var FooterPopover = function FooterPopover(_ref3) {
51678
51680
  onClick: close
51679
51681
  }), /*#__PURE__*/jsx(Popover.Panel, {
51680
51682
  "static": true,
51681
- className: "fixed w-52 rounded-lg border border-white/10 bg-neutral-900 shadow-xl",
51683
+ className: "fixed w-52 rounded-lg border border-white/10 ".concat((currentTheme === null || currentTheme === void 0 ? void 0 : currentTheme["bg-primary-dark"]) || "bg-neutral-900", " shadow-xl"),
51682
51684
  style: {
51683
51685
  zIndex: 9999,
51684
51686
  left: (_rect$left = rect === null || rect === void 0 ? void 0 : rect.left) !== null && _rect$left !== void 0 ? _rect$left : 0,
@@ -51729,12 +51731,12 @@ var FooterPopover = function FooterPopover(_ref3) {
51729
51731
  }
51730
51732
  });
51731
51733
  };
51732
- var PopoverItem = function PopoverItem(_ref5) {
51733
- var icon = _ref5.icon,
51734
- label = _ref5.label,
51735
- onClick = _ref5.onClick,
51736
- _ref5$active = _ref5.active,
51737
- active = _ref5$active === void 0 ? false : _ref5$active;
51734
+ var PopoverItem = function PopoverItem(_ref6) {
51735
+ var icon = _ref6.icon,
51736
+ label = _ref6.label,
51737
+ onClick = _ref6.onClick,
51738
+ _ref6$active = _ref6.active,
51739
+ active = _ref6$active === void 0 ? false : _ref6$active;
51738
51740
  return /*#__PURE__*/jsxs("button", {
51739
51741
  type: "button",
51740
51742
  onClick: onClick,
@@ -53405,6 +53407,61 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
53405
53407
  // eslint-disable-next-line react-hooks/exhaustive-deps
53406
53408
  }, []);
53407
53409
 
53410
+ // ─── Listen for external "apply theme" requests ─────────────────
53411
+ // MCP-driven apply_theme updates settings in the main process; this
53412
+ // listener pulls the new theme into ThemeContext without a remount.
53413
+ useEffect(function () {
53414
+ var handler = function handler(e) {
53415
+ var _e$detail;
53416
+ var themeKey = e === null || e === void 0 || (_e$detail = e.detail) === null || _e$detail === void 0 ? void 0 : _e$detail.themeKey;
53417
+ if (themeKey && typeof changeCurrentTheme === "function") {
53418
+ changeCurrentTheme(themeKey);
53419
+ }
53420
+ };
53421
+ window.addEventListener("dash:apply-theme", handler);
53422
+ return function () {
53423
+ return window.removeEventListener("dash:apply-theme", handler);
53424
+ };
53425
+ }, [changeCurrentTheme]);
53426
+
53427
+ // ─── Listen for external "open workspace" requests ──────────────
53428
+ // Fired by: Dash.js notification click, MCP state-changed for
53429
+ // create_dashboard, etc. Any code that wants to switch the active
53430
+ // dashboard from outside this component dispatches
53431
+ // window.dispatchEvent(new CustomEvent("dash:navigate-workspace",
53432
+ // { detail: { workspaceId: <number> } }))
53433
+ // We record the requested ID and open it once it appears in
53434
+ // workspaceConfig — handles the case where the workspace was just
53435
+ // created and the config reload is still in flight.
53436
+ var _useState49 = useState(null),
53437
+ _useState50 = _slicedToArray(_useState49, 2),
53438
+ pendingOpenWorkspaceId = _useState50[0],
53439
+ setPendingOpenWorkspaceId = _useState50[1];
53440
+ useEffect(function () {
53441
+ var handler = function handler(e) {
53442
+ var _e$detail2;
53443
+ var id = e === null || e === void 0 || (_e$detail2 = e.detail) === null || _e$detail2 === void 0 ? void 0 : _e$detail2.workspaceId;
53444
+ if (id != null) setPendingOpenWorkspaceId(Number(id));
53445
+ };
53446
+ window.addEventListener("dash:navigate-workspace", handler);
53447
+ return function () {
53448
+ return window.removeEventListener("dash:navigate-workspace", handler);
53449
+ };
53450
+ }, []);
53451
+ useEffect(function () {
53452
+ if (pendingOpenWorkspaceId == null) return;
53453
+ var ws = workspaceConfig.find(function (w) {
53454
+ return Number(w.id) === Number(pendingOpenWorkspaceId);
53455
+ });
53456
+ if (ws) {
53457
+ handleOpenTab(ws);
53458
+ setPendingOpenWorkspaceId(null);
53459
+ }
53460
+ // If not found yet, keep the pending ID and wait for the next
53461
+ // workspaceConfig update (workspace:saved triggers a reload).
53462
+ // eslint-disable-next-line react-hooks/exhaustive-deps
53463
+ }, [pendingOpenWorkspaceId, workspaceConfig]);
53464
+
53408
53465
  // ─── Load recents on mount ───────────────────────────────────────
53409
53466
  useEffect(function () {
53410
53467
  var _window$mainApi4;
@@ -53656,6 +53713,22 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
53656
53713
  setWorkspaceConfig(function () {
53657
53714
  return workspacesTemp;
53658
53715
  });
53716
+ // Also sync fresh workspace data into any open tabs. Without this,
53717
+ // MCP-driven mutations (update_layout, add_widget, etc.) update the
53718
+ // config but the active tab keeps its stale snapshot — users only
53719
+ // see the change after closing and reopening the tab.
53720
+ setOpenTabs(function (prevTabs) {
53721
+ return prevTabs.map(function (tab) {
53722
+ var fresh = workspacesTemp.find(function (w) {
53723
+ return Number(w.id) === Number(tab.id);
53724
+ });
53725
+ if (!fresh) return tab; // workspace was deleted; leave tab for handleCloseTab to reap
53726
+ return _objectSpread$6(_objectSpread$6({}, tab), {}, {
53727
+ name: fresh.name || tab.name,
53728
+ workspace: fresh
53729
+ });
53730
+ });
53731
+ });
53659
53732
  setIsLoadingWorkspaces(false);
53660
53733
  } catch (e) {
53661
53734
  }
@@ -53729,10 +53802,10 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
53729
53802
  }
53730
53803
 
53731
53804
  // ─── Page State ──────────────────────────────────────────────────
53732
- var _useState49 = useState(null),
53733
- _useState50 = _slicedToArray(_useState49, 2),
53734
- activePageId = _useState50[0],
53735
- setActivePageId = _useState50[1];
53805
+ var _useState51 = useState(null),
53806
+ _useState52 = _slicedToArray(_useState51, 2),
53807
+ activePageId = _useState52[0],
53808
+ setActivePageId = _useState52[1];
53736
53809
 
53737
53810
  // Page history stack for goBack() — pushes the previous page id
53738
53811
  // whenever a navigation happens through navigateToPage().
@@ -53792,8 +53865,8 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
53792
53865
  if (prev) setActivePageId(prev); // bypass history recording
53793
53866
  }
53794
53867
  function onSetNavSidebar(e) {
53795
- var _e$detail;
53796
- setSidebarCollapsed(!!((_e$detail = e.detail) !== null && _e$detail !== void 0 && _e$detail.collapsed));
53868
+ var _e$detail3;
53869
+ setSidebarCollapsed(!!((_e$detail3 = e.detail) !== null && _e$detail3 !== void 0 && _e$detail3.collapsed));
53797
53870
  }
53798
53871
  function onToggleNavSidebar() {
53799
53872
  setSidebarCollapsed(function (c) {
@@ -53829,16 +53902,18 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
53829
53902
  }, []);
53830
53903
  var workspacePages = (workspaceSelected === null || workspaceSelected === void 0 ? void 0 : workspaceSelected.pages) || [];
53831
53904
 
53832
- // Memoize sorted pages so page object references stay stable across re-renders
53905
+ // Memoize sorted pages so page object references stay stable across re-renders.
53906
+ // Depend on `workspaceSelected` so the memo invalidates whenever the workspace
53907
+ // is refreshed (e.g. after an MCP-driven layout/widget change). Without this,
53908
+ // PageLayoutBuilder's React.memo would see the same page reference and skip
53909
+ // re-rendering even though the page's layout array changed underneath.
53833
53910
  var sortedPagesForRender = useMemo(function () {
53834
53911
  return _toConsumableArray(workspacePages).sort(function (a, b) {
53835
53912
  return (a.order || 0) - (b.order || 0);
53836
53913
  });
53837
53914
  },
53838
53915
  // eslint-disable-next-line react-hooks/exhaustive-deps
53839
- [workspacePages.length,
53840
- // Re-sort when page names/order change but not on every parent render
53841
- workspacePages.map(function (p) {
53916
+ [workspaceSelected, workspacePages.length, workspacePages.map(function (p) {
53842
53917
  return "".concat(p.id, ":").concat(p.order, ":").concat(p.name);
53843
53918
  }).join(",")]);
53844
53919
  var currentActivePageId = activePageId || (workspaceSelected === null || workspaceSelected === void 0 ? void 0 : workspaceSelected.activePageId) || ((_workspacePages$0$id = (_workspacePages$ = workspacePages[0]) === null || _workspacePages$ === void 0 ? void 0 : _workspacePages$.id) !== null && _workspacePages$0$id !== void 0 ? _workspacePages$0$id : null);
@@ -53859,8 +53934,8 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
53859
53934
  // Listen for open/close dashboard actions via DashboardActionsApi
53860
53935
  useEffect(function () {
53861
53936
  function onOpen(e) {
53862
- var _e$detail2;
53863
- var name = (_e$detail2 = e.detail) === null || _e$detail2 === void 0 ? void 0 : _e$detail2.name;
53937
+ var _e$detail4;
53938
+ var name = (_e$detail4 = e.detail) === null || _e$detail4 === void 0 ? void 0 : _e$detail4.name;
53864
53939
  if (!name) return;
53865
53940
  var ws = (workspaceConfigRef.current || []).find(function (w) {
53866
53941
  return (w.name || "").toLowerCase() === name.toLowerCase();
@@ -53868,8 +53943,8 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
53868
53943
  if (ws && handleOpenTabRef.current) handleOpenTabRef.current(ws);
53869
53944
  }
53870
53945
  function onClose(e) {
53871
- var _e$detail3;
53872
- var name = (_e$detail3 = e.detail) === null || _e$detail3 === void 0 ? void 0 : _e$detail3.name;
53946
+ var _e$detail5;
53947
+ var name = (_e$detail5 = e.detail) === null || _e$detail5 === void 0 ? void 0 : _e$detail5.name;
53873
53948
  if (name) {
53874
53949
  var tab = (openTabsRef.current || []).find(function (t) {
53875
53950
  return (t.name || "").toLowerCase() === name.toLowerCase();
@@ -56542,6 +56617,13 @@ var MessageBubble = function MessageBubble(_ref2) {
56542
56617
  content = message.content,
56543
56618
  toolCalls = message.toolCalls,
56544
56619
  hidden = message.hidden;
56620
+ var _ref3 = useContext(ThemeContext) || {},
56621
+ currentTheme = _ref3.currentTheme;
56622
+ // Prefer theme-provided panel colors so assistant chrome follows the
56623
+ // active app theme. Fall back to the original muted neutral if no
56624
+ // theme is in scope.
56625
+ var bubbleBg = (currentTheme === null || currentTheme === void 0 ? void 0 : currentTheme["bg-secondary-dark"]) || (currentTheme === null || currentTheme === void 0 ? void 0 : currentTheme["bg-primary-dark"]) || "bg-gray-800/40";
56626
+ var userBubbleBg = (currentTheme === null || currentTheme === void 0 ? void 0 : currentTheme["bg-primary-bright"]) || (currentTheme === null || currentTheme === void 0 ? void 0 : currentTheme["bg-primary"]) || "bg-indigo-700/40";
56545
56627
 
56546
56628
  // App-injected priming messages (e.g. widget-builder "Hello…" seed)
56547
56629
  // are kept in state for conversation continuity but suppressed from
@@ -56561,7 +56643,7 @@ var MessageBubble = function MessageBubble(_ref2) {
56561
56643
  className: "text-[10px] font-semibold uppercase tracking-wider text-indigo-400 mb-1 text-right",
56562
56644
  children: "You"
56563
56645
  }), /*#__PURE__*/jsx("div", {
56564
- className: "px-3 py-2 rounded-lg bg-indigo-700/40 text-sm text-gray-100 whitespace-pre-wrap break-words leading-relaxed",
56646
+ className: "px-3 py-2 rounded-lg text-sm text-gray-100 whitespace-pre-wrap break-words leading-relaxed ".concat(userBubbleBg),
56565
56647
  children: text
56566
56648
  })]
56567
56649
  })
@@ -56641,7 +56723,7 @@ var MessageBubble = function MessageBubble(_ref2) {
56641
56723
  className: "text-[10px] font-semibold uppercase tracking-wider text-gray-500 mb-1",
56642
56724
  children: "Assistant"
56643
56725
  }), /*#__PURE__*/jsx("div", {
56644
- className: "text-sm leading-relaxed px-3 py-2 rounded-lg bg-gray-800/40 text-gray-500 italic",
56726
+ className: "text-sm leading-relaxed px-3 py-2 rounded-lg text-gray-500 italic ".concat(bubbleBg),
56645
56727
  children: "Thinking..."
56646
56728
  })]
56647
56729
  });
@@ -56654,7 +56736,7 @@ var MessageBubble = function MessageBubble(_ref2) {
56654
56736
  className: "text-[10px] font-semibold uppercase tracking-wider text-gray-500 mb-1",
56655
56737
  children: "Assistant"
56656
56738
  }), /*#__PURE__*/jsxs("div", {
56657
- className: "text-sm leading-relaxed px-3 py-2 rounded-lg bg-gray-800/40",
56739
+ className: "text-sm leading-relaxed px-3 py-2 rounded-lg ".concat(bubbleBg),
56658
56740
  children: [isStreaming && /*#__PURE__*/jsx("div", {
56659
56741
  className: "text-gray-200",
56660
56742
  children: /*#__PURE__*/jsx(StreamingText, {
@@ -57326,6 +57408,10 @@ function ChatCore(_ref) {
57326
57408
  setStreamingText("");
57327
57409
  setSessionActive(false);
57328
57410
  saveConversation([]);
57411
+ // Allow the initial-message auto-send to re-fire on the fresh
57412
+ // empty conversation. Without this reset, the greeting only ever
57413
+ // appears once per mount, and New Chat leaves the panel blank.
57414
+ initialMessageFiredRef.current = false;
57329
57415
  if (isCliBackend && mainApi !== null && mainApi !== void 0 && (_mainApi$llm3 = mainApi.llm) !== null && _mainApi$llm3 !== void 0 && _mainApi$llm3.clearCliSession) {
57330
57416
  mainApi.llm.clearCliSession(uuid || persistKey || sessionKey);
57331
57417
  }