@supernal/interface-nextjs 1.0.22 → 1.0.24

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.mjs CHANGED
@@ -1,7 +1,13 @@
1
1
  "use client";
2
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
+ }) : x)(function(x) {
5
+ if (typeof require !== "undefined") return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
2
8
 
3
9
  // src/components/SupernalProvider.tsx
4
- import { useEffect as useEffect8 } from "react";
10
+ import { useEffect as useEffect14 } from "react";
5
11
 
6
12
  // src/contexts/ChatInputContext.tsx
7
13
  import { createContext, useContext, useCallback, useRef } from "react";
@@ -551,7 +557,8 @@ var InputField = ({
551
557
  voiceEnabled = false,
552
558
  isListening = false,
553
559
  onMicClick,
554
- modKey = "Ctrl"
560
+ modKey = "Ctrl",
561
+ onKeyDown
555
562
  }) => /* @__PURE__ */ jsx3("form", { onSubmit, className: compact ? "flex space-x-2" : THEME_CLASSES.bg.inputForm + " bg-transparent", children: /* @__PURE__ */ jsxs("div", { className: compact ? "flex space-x-2 flex-1" : "relative", children: [
556
563
  /* @__PURE__ */ jsx3(
557
564
  "input",
@@ -560,6 +567,7 @@ var InputField = ({
560
567
  type: "text",
561
568
  value: inputValue,
562
569
  onChange: (e) => onInputChange(e.target.value),
570
+ onKeyDown,
563
571
  placeholder,
564
572
  className: compact ? `flex-1 px-3 py-2 text-xs border rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all ${glassClasses}` : `w-full pl-4 ${inputValue.trim() ? "pr-12" : "pr-12"} py-3 text-sm text-gray-900 dark:text-white placeholder:text-gray-500 dark:placeholder:text-gray-300 rounded-3xl focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all shadow-sm ${glassClasses}`,
565
573
  style: INLINE_STYLES.input(theme === "dark"),
@@ -600,7 +608,7 @@ var Avatar = ({ avatar, size = "normal" }) => {
600
608
  };
601
609
 
602
610
  // src/components/ChatBubble/ChatBubble.tsx
603
- import React7, { useState as useState7, useRef as useRef6, useEffect as useEffect5, useMemo as useMemo2 } from "react";
611
+ import React8, { useState as useState8, useRef as useRef8, useEffect as useEffect7, useMemo as useMemo3 } from "react";
604
612
 
605
613
  // src/components/MessageRenderer.tsx
606
614
  import ReactMarkdown from "react-markdown";
@@ -845,7 +853,10 @@ function useTTS() {
845
853
  async (text, options = {}) => {
846
854
  if (Platform.isNative) {
847
855
  try {
848
- const { TextToSpeech } = await import("@capacitor/text-to-speech");
856
+ const { TextToSpeech } = await import(
857
+ /* webpackIgnore: true */
858
+ "@capacitor/text-to-speech"
859
+ );
849
860
  await TextToSpeech.speak({
850
861
  text,
851
862
  lang: "en-US",
@@ -1086,7 +1097,10 @@ function useSTT() {
1086
1097
  setIsListening(true);
1087
1098
  try {
1088
1099
  if (Platform2.isNative) {
1089
- const { SpeechRecognition: CapSpeech } = await import("@capacitor-community/speech-recognition");
1100
+ const { SpeechRecognition: CapSpeech } = await import(
1101
+ /* webpackIgnore: true */
1102
+ "@capacitor-community/speech-recognition"
1103
+ );
1090
1104
  await CapSpeech.requestPermissions();
1091
1105
  const { matches } = await CapSpeech.start({
1092
1106
  language: "en-US",
@@ -1294,10 +1308,10 @@ var TTSPlaylistMenu = ({
1294
1308
 
1295
1309
  // src/utils/pageContentParser.ts
1296
1310
  var GENERIC_SUGGESTIONS = [
1297
- { text: "Try: navigate to...", type: "generic" },
1298
- { text: "Ask: what can I do here?", type: "generic" },
1299
- { text: "Show me around", type: "generic" },
1300
- { text: "What's on this page?", type: "generic" }
1311
+ { text: "navigate to...", type: "generic" },
1312
+ { text: "what can I do here?", type: "generic" },
1313
+ { text: "show me around", type: "generic" },
1314
+ { text: "what's on this page?", type: "generic" }
1301
1315
  ];
1302
1316
  function extractPageSpecificSuggestions() {
1303
1317
  if (typeof window === "undefined") return [];
@@ -1307,7 +1321,7 @@ function extractPageSpecificSuggestions() {
1307
1321
  const text = heading.textContent?.trim();
1308
1322
  if (text && text.length > 0 && text.length < 50) {
1309
1323
  suggestions.push({
1310
- text: `Ask about: ${text}`,
1324
+ text: text.toLowerCase(),
1311
1325
  type: "page-specific"
1312
1326
  });
1313
1327
  }
@@ -1367,15 +1381,72 @@ function detectBackgroundContext() {
1367
1381
  }
1368
1382
 
1369
1383
  // src/utils/ttsDetection.ts
1370
- function detectTTSWidgets() {
1384
+ function waitForTTSReady(timeout = 5e3) {
1385
+ return new Promise((resolve) => {
1386
+ if (typeof window === "undefined") {
1387
+ resolve(false);
1388
+ return;
1389
+ }
1390
+ if (window.SupernalTTSStatus?.initialized || window.SupernalTTSInstance || document.querySelector(".supernal-tts-play")) {
1391
+ console.log("[TTS Detection] Widget already initialized");
1392
+ resolve(true);
1393
+ return;
1394
+ }
1395
+ let resolved = false;
1396
+ const done = (result) => {
1397
+ if (resolved) return;
1398
+ resolved = true;
1399
+ cleanup();
1400
+ resolve(result);
1401
+ };
1402
+ const handler = () => {
1403
+ console.log("[TTS Detection] Widget ready event received");
1404
+ done(true);
1405
+ };
1406
+ const pollId = setInterval(() => {
1407
+ if (window.SupernalTTSStatus?.initialized || window.SupernalTTSInstance || document.querySelector(".supernal-tts-play")) {
1408
+ console.log("[TTS Detection] Widget detected via polling");
1409
+ done(true);
1410
+ }
1411
+ }, 500);
1412
+ const timeoutId = setTimeout(() => {
1413
+ console.warn("[TTS Detection] Timeout waiting for widget initialization");
1414
+ done(false);
1415
+ }, timeout);
1416
+ const cleanup = () => {
1417
+ window.removeEventListener("supernal-tts-ready", handler);
1418
+ clearInterval(pollId);
1419
+ clearTimeout(timeoutId);
1420
+ };
1421
+ window.addEventListener("supernal-tts-ready", handler);
1422
+ });
1423
+ }
1424
+ var lastDetectionState = { count: 0, hasButtons: false };
1425
+ async function detectTTSWidgets() {
1371
1426
  if (typeof window === "undefined") return false;
1372
1427
  const widgetWrappers = document.querySelectorAll(".supernal-tts-widget[data-text]");
1373
- console.log("[TTS Detection] Found widget wrappers:", widgetWrappers.length);
1374
- if (widgetWrappers.length > 0) {
1375
- console.log("[TTS Detection] Wrapper visible?", widgetWrappers[0].offsetParent !== null);
1376
- console.log("[TTS Detection] Has play button?", !!widgetWrappers[0].querySelector(".supernal-tts-play"));
1428
+ if (widgetWrappers.length === 0) {
1429
+ if (lastDetectionState.count !== 0) {
1430
+ console.log("[TTS Detection] No widget wrappers found");
1431
+ lastDetectionState = { count: 0, hasButtons: false };
1432
+ }
1433
+ return false;
1434
+ }
1435
+ const ready = await waitForTTSReady(5e3);
1436
+ if (!ready) {
1437
+ console.warn("[TTS Detection] Widget not ready after 5s timeout");
1438
+ return false;
1439
+ }
1440
+ const hasPlayButtons = Array.from(widgetWrappers).some((wrapper) => {
1441
+ const hasButton = wrapper.querySelector(".supernal-tts-play") !== null;
1442
+ const isVisible = wrapper.offsetParent !== null;
1443
+ return hasButton && isVisible;
1444
+ });
1445
+ if (lastDetectionState.count !== widgetWrappers.length || lastDetectionState.hasButtons !== hasPlayButtons) {
1446
+ console.log(`[TTS Detection] Found ${widgetWrappers.length} widgets, ${hasPlayButtons ? "with" : "without"} play buttons`);
1447
+ lastDetectionState = { count: widgetWrappers.length, hasButtons: hasPlayButtons };
1377
1448
  }
1378
- return widgetWrappers.length > 0;
1449
+ return hasPlayButtons;
1379
1450
  }
1380
1451
  function extractWidgetLabel(element, fallbackIndex) {
1381
1452
  const ariaLabel = element.getAttribute("aria-label");
@@ -1409,6 +1480,7 @@ function extractWidgetLabel(element, fallbackIndex) {
1409
1480
  }
1410
1481
  return `Readable Section ${fallbackIndex}`;
1411
1482
  }
1483
+ var lastExtractionCount = 0;
1412
1484
  function extractTTSWidgets() {
1413
1485
  if (typeof window === "undefined") return [];
1414
1486
  const widgets = [];
@@ -1416,7 +1488,6 @@ function extractTTSWidgets() {
1416
1488
  ttsWidgets.forEach((wrapper, idx) => {
1417
1489
  const element = wrapper;
1418
1490
  if (element.offsetParent === null) {
1419
- console.log("[TTS Extract] Skipping hidden widget:", wrapper);
1420
1491
  return;
1421
1492
  }
1422
1493
  const label = extractWidgetLabel(wrapper, widgets.length + 1);
@@ -1428,14 +1499,6 @@ function extractTTSWidgets() {
1428
1499
  if (playButton && !playButton.hasAttribute("data-testid")) {
1429
1500
  playButton.setAttribute("data-testid", `${widgetId}-play`);
1430
1501
  }
1431
- console.log("[TTS Extract] Widget:", {
1432
- id: widgetId,
1433
- label,
1434
- hasButton: !!playButton,
1435
- wrapper: element,
1436
- playButton,
1437
- testId: element.getAttribute("data-testid")
1438
- });
1439
1502
  widgets.push({
1440
1503
  id: widgetId,
1441
1504
  element: wrapper,
@@ -1443,7 +1506,10 @@ function extractTTSWidgets() {
1443
1506
  label
1444
1507
  });
1445
1508
  });
1446
- console.log("[TTS Extract] Total widgets found:", widgets.length);
1509
+ if (widgets.length !== lastExtractionCount) {
1510
+ console.log(`[TTS Extract] Found ${widgets.length} visible widgets`);
1511
+ lastExtractionCount = widgets.length;
1512
+ }
1447
1513
  return widgets;
1448
1514
  }
1449
1515
 
@@ -1458,10 +1524,12 @@ var opacityStates = {
1458
1524
  speaking: 1
1459
1525
  },
1460
1526
  desktop: {
1461
- idle: 0.4,
1462
- // Increased from 0.1 for better visibility
1463
- listening: 0.7,
1464
- typing: 0.9,
1527
+ idle: 0.2,
1528
+ // Much less visible when inactive
1529
+ listening: 0.95,
1530
+ // Very visible when listening
1531
+ typing: 1,
1532
+ // Fully visible when typing
1465
1533
  speaking: 0.5
1466
1534
  }
1467
1535
  };
@@ -1487,14 +1555,21 @@ var SubtitleOverlay = ({
1487
1555
  theme,
1488
1556
  config,
1489
1557
  sttTranscript,
1490
- resetTranscript
1558
+ resetTranscript,
1559
+ onSwitchToFullMode
1491
1560
  }) => {
1492
1561
  const [overlayState, setOverlayState] = useState6("idle");
1493
1562
  const [opacity, setOpacity] = useState6(1);
1494
1563
  const [lastInputMethod, setLastInputMethod] = useState6(null);
1495
1564
  const [isMobile, setIsMobile] = useState6(false);
1496
1565
  const [messageOpacity, setMessageOpacity] = useState6(1);
1497
- const [expansionState, setExpansionState] = useState6("collapsed");
1566
+ const [expansionState, setExpansionState] = useState6(() => {
1567
+ if (typeof window !== "undefined") {
1568
+ const saved = localStorage.getItem("subtitle-overlay-expanded");
1569
+ return saved === "true" ? "expanded" : "collapsed";
1570
+ }
1571
+ return "collapsed";
1572
+ });
1498
1573
  const [touchStartY, setTouchStartY] = useState6(null);
1499
1574
  const lastInputTimeRef = useRef5(Date.now());
1500
1575
  const autoFadeTimerRef = useRef5(null);
@@ -1508,13 +1583,25 @@ var SubtitleOverlay = ({
1508
1583
  const [showPlaylist, setShowPlaylist] = useState6(false);
1509
1584
  const [ttsWidgets, setTTSWidgets] = useState6([]);
1510
1585
  const [touchStartYInput, setTouchStartYInput] = useState6(null);
1586
+ const [completedActions, setCompletedActions] = useState6([]);
1587
+ const [showCompletedActions, setShowCompletedActions] = useState6(false);
1588
+ const [shouldShowAiResponse, setShouldShowAiResponse] = useState6(false);
1589
+ const [latestActionOpacity, setLatestActionOpacity] = useState6(0);
1590
+ const latestActionFadeRef = useRef5(null);
1591
+ const lastUserMessageRef = useRef5("");
1592
+ const lastShownAiMessageRef = useRef5("");
1593
+ const justExpandedViaSlashRef = useRef5(false);
1594
+ const [isDragging, setIsDragging] = useState6(false);
1595
+ const [position, setPosition] = useState6({ x: 0, y: 0 });
1596
+ const [dragStart, setDragStart] = useState6({ x: 0, y: 0 });
1597
+ const dragRef = useRef5(null);
1598
+ const dragDistanceRef = useRef5(0);
1599
+ const lastEscapeTimeRef = useRef5(0);
1600
+ const DOUBLE_ESCAPE_THRESHOLD_MS = 500;
1511
1601
  useEffect4(() => {
1512
1602
  const checkMobile = () => {
1513
1603
  const mobile = window.innerWidth < 768;
1514
1604
  setIsMobile(mobile);
1515
- if (!mobile && expansionState === "collapsed") {
1516
- setExpansionState("expanded");
1517
- }
1518
1605
  };
1519
1606
  checkMobile();
1520
1607
  window.addEventListener("resize", checkMobile);
@@ -1527,7 +1614,7 @@ var SubtitleOverlay = ({
1527
1614
  }
1528
1615
  if (!isMobile && overlayState === "idle") {
1529
1616
  autoFadeTimerRef.current = setTimeout(() => {
1530
- setOpacity(0.4);
1617
+ setOpacity(0.2);
1531
1618
  }, 5e3);
1532
1619
  }
1533
1620
  return () => {
@@ -1541,23 +1628,52 @@ var SubtitleOverlay = ({
1541
1628
  clearTimeout(messageFadeTimerRef.current);
1542
1629
  messageFadeTimerRef.current = null;
1543
1630
  }
1631
+ const lastAiMsg = messages.filter((m) => m.type === "ai").slice(-1)[0];
1632
+ if (!shouldShowAiResponse || !lastAiMsg) {
1633
+ setMessageOpacity(0);
1634
+ return;
1635
+ }
1636
+ const messageKey = lastAiMsg.text?.substring(0, 100) || "";
1637
+ const shownMessages = JSON.parse(localStorage.getItem("subtitle-shown-messages") || "[]");
1638
+ if (shownMessages.includes(messageKey)) {
1639
+ setMessageOpacity(0);
1640
+ setShouldShowAiResponse(false);
1641
+ return;
1642
+ }
1643
+ lastShownAiMessageRef.current = messageKey;
1544
1644
  setMessageOpacity(1);
1545
1645
  messageFadeTimerRef.current = setTimeout(() => {
1546
1646
  setMessageOpacity(0);
1547
- }, 8e3);
1647
+ setShouldShowAiResponse(false);
1648
+ try {
1649
+ const shown = JSON.parse(localStorage.getItem("subtitle-shown-messages") || "[]");
1650
+ shown.push(messageKey);
1651
+ const trimmed = shown.slice(-50);
1652
+ localStorage.setItem("subtitle-shown-messages", JSON.stringify(trimmed));
1653
+ } catch {
1654
+ }
1655
+ }, 3e3);
1548
1656
  return () => {
1549
1657
  if (messageFadeTimerRef.current) {
1550
1658
  clearTimeout(messageFadeTimerRef.current);
1551
1659
  }
1552
1660
  };
1553
- }, [messages.filter((m) => m.type === "ai").slice(-1)[0]?.text]);
1661
+ }, [messages.filter((m) => m.type === "ai").slice(-1)[0]?.text, shouldShowAiResponse]);
1554
1662
  useEffect4(() => {
1555
1663
  if (sttTranscript && voiceEnabled && resetTranscript) {
1556
1664
  onSendMessage(sttTranscript);
1557
1665
  resetTranscript();
1558
- setExpansionState("expanded");
1559
1666
  setLastInputMethod("voice");
1560
1667
  lastInputTimeRef.current = Date.now();
1668
+ setShouldShowAiResponse(true);
1669
+ const newAction = {
1670
+ id: `action-${Date.now()}`,
1671
+ tool: "Voice Command",
1672
+ timestamp: Date.now(),
1673
+ description: sttTranscript.substring(0, 50) + (sttTranscript.length > 50 ? "..." : "")
1674
+ };
1675
+ setCompletedActions((prev) => [...prev, newAction]);
1676
+ triggerActionFade();
1561
1677
  }
1562
1678
  }, [sttTranscript, voiceEnabled, resetTranscript, onSendMessage]);
1563
1679
  useEffect4(() => {
@@ -1565,8 +1681,8 @@ var SubtitleOverlay = ({
1565
1681
  setSuggestions(pageSuggestions);
1566
1682
  }, []);
1567
1683
  useEffect4(() => {
1568
- const detectWidgets = () => {
1569
- const detected = detectTTSWidgets();
1684
+ const detectWidgets = async () => {
1685
+ const detected = await detectTTSWidgets();
1570
1686
  setHasTTSWidgets(detected);
1571
1687
  if (detected) {
1572
1688
  const widgets = extractTTSWidgets();
@@ -1583,11 +1699,20 @@ var SubtitleOverlay = ({
1583
1699
  });
1584
1700
  observer.observe(document.body, {
1585
1701
  childList: true,
1586
- subtree: true
1702
+ subtree: true,
1703
+ attributes: true,
1704
+ attributeFilter: ["data-tts-status"]
1705
+ // Watch for status changes
1587
1706
  });
1707
+ const handleReady = () => {
1708
+ console.log("[SubtitleOverlay] TTS ready event received");
1709
+ detectWidgets();
1710
+ };
1711
+ window.addEventListener("supernal-tts-ready", handleReady);
1588
1712
  return () => {
1589
1713
  observer.disconnect();
1590
1714
  clearTimeout(timeoutId);
1715
+ window.removeEventListener("supernal-tts-ready", handleReady);
1591
1716
  };
1592
1717
  }, []);
1593
1718
  useEffect4(() => {
@@ -1608,8 +1733,30 @@ var SubtitleOverlay = ({
1608
1733
  }, [glassTheme]);
1609
1734
  useEffect4(() => {
1610
1735
  const handleGlobalKeyDown = (e) => {
1736
+ if (e.key === "Escape") {
1737
+ const now = Date.now();
1738
+ const timeSinceLastEscape = now - lastEscapeTimeRef.current;
1739
+ if (expansionState === "expanded") {
1740
+ setExpansionState("collapsed");
1741
+ if (isListening && onMicClick) {
1742
+ onMicClick();
1743
+ }
1744
+ return;
1745
+ }
1746
+ if (expansionState === "collapsed" && timeSinceLastEscape < DOUBLE_ESCAPE_THRESHOLD_MS) {
1747
+ console.log("[SubtitleOverlay] Double-escape detected - switching to full mode");
1748
+ if (onSwitchToFullMode) {
1749
+ onSwitchToFullMode();
1750
+ }
1751
+ lastEscapeTimeRef.current = 0;
1752
+ return;
1753
+ }
1754
+ lastEscapeTimeRef.current = now;
1755
+ }
1611
1756
  if (e.key === "/" && expansionState === "collapsed" && !(e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement)) {
1612
1757
  e.preventDefault();
1758
+ e.stopImmediatePropagation();
1759
+ justExpandedViaSlashRef.current = true;
1613
1760
  setExpansionState("expanded");
1614
1761
  }
1615
1762
  if ((e.ctrlKey || e.metaKey) && e.key === "k") {
@@ -1620,17 +1767,60 @@ var SubtitleOverlay = ({
1620
1767
  inputRef.current?.focus();
1621
1768
  }
1622
1769
  }
1770
+ if ((e.ctrlKey || e.metaKey) && e.key === "/" && voiceEnabled) {
1771
+ e.preventDefault();
1772
+ if (expansionState === "collapsed") {
1773
+ setExpansionState("expanded");
1774
+ }
1775
+ onMicClick();
1776
+ }
1623
1777
  };
1624
1778
  window.addEventListener("keydown", handleGlobalKeyDown);
1625
1779
  return () => window.removeEventListener("keydown", handleGlobalKeyDown);
1780
+ }, [expansionState, onSwitchToFullMode, voiceEnabled, onMicClick]);
1781
+ useEffect4(() => {
1782
+ if (typeof window !== "undefined") {
1783
+ localStorage.setItem("subtitle-overlay-expanded", expansionState === "expanded" ? "true" : "false");
1784
+ }
1626
1785
  }, [expansionState]);
1627
1786
  useEffect4(() => {
1628
1787
  if (expansionState === "expanded" && inputRef.current) {
1629
1788
  setTimeout(() => {
1630
1789
  inputRef.current?.focus();
1790
+ if (justExpandedViaSlashRef.current) {
1791
+ justExpandedViaSlashRef.current = false;
1792
+ if (inputRef.current && inputRef.current.value.startsWith("/")) {
1793
+ const cleaned = inputRef.current.value.replace(/^\/+/, "");
1794
+ onInputChange(cleaned);
1795
+ }
1796
+ }
1631
1797
  }, 100);
1632
1798
  }
1633
1799
  }, [expansionState]);
1800
+ useEffect4(() => {
1801
+ if (isMobile) return;
1802
+ const handleMouseMove = (e) => {
1803
+ if (!isDragging) return;
1804
+ const deltaX = e.clientX - dragStart.x;
1805
+ const deltaY = e.clientY - dragStart.y;
1806
+ dragDistanceRef.current = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
1807
+ setPosition({ x: deltaX, y: deltaY });
1808
+ };
1809
+ const handleMouseUp = () => {
1810
+ setIsDragging(false);
1811
+ setTimeout(() => {
1812
+ dragDistanceRef.current = 0;
1813
+ }, 100);
1814
+ };
1815
+ if (isDragging) {
1816
+ window.addEventListener("mousemove", handleMouseMove);
1817
+ window.addEventListener("mouseup", handleMouseUp);
1818
+ }
1819
+ return () => {
1820
+ window.removeEventListener("mousemove", handleMouseMove);
1821
+ window.removeEventListener("mouseup", handleMouseUp);
1822
+ };
1823
+ }, [isDragging, dragStart, isMobile]);
1634
1824
  useEffect4(() => {
1635
1825
  const timeSinceLastInput = Date.now() - lastInputTimeRef.current;
1636
1826
  const context = {
@@ -1659,13 +1849,11 @@ var SubtitleOverlay = ({
1659
1849
  lastInputTimeRef.current = Date.now();
1660
1850
  };
1661
1851
  const handleIconClick = () => {
1852
+ if (dragDistanceRef.current > 5) {
1853
+ return;
1854
+ }
1662
1855
  if (expansionState === "collapsed") {
1663
1856
  setExpansionState("expanded");
1664
- if (!isListening && voiceEnabled) {
1665
- onMicClick();
1666
- setLastInputMethod("voice");
1667
- lastInputTimeRef.current = Date.now();
1668
- }
1669
1857
  } else {
1670
1858
  onMicClick();
1671
1859
  setLastInputMethod("voice");
@@ -1687,10 +1875,36 @@ var SubtitleOverlay = ({
1687
1875
  const handleTouchEnd = () => {
1688
1876
  setTouchStartY(null);
1689
1877
  };
1878
+ const triggerActionFade = () => {
1879
+ if (latestActionFadeRef.current) {
1880
+ clearTimeout(latestActionFadeRef.current);
1881
+ }
1882
+ setLatestActionOpacity(1);
1883
+ latestActionFadeRef.current = setTimeout(() => {
1884
+ setLatestActionOpacity(0);
1885
+ }, 2500);
1886
+ };
1690
1887
  const handleSend = () => {
1691
1888
  if (inputValue.trim()) {
1692
1889
  onSendMessage(inputValue);
1693
1890
  lastInputTimeRef.current = Date.now();
1891
+ setShouldShowAiResponse(true);
1892
+ lastUserMessageRef.current = inputValue;
1893
+ const newAction = {
1894
+ id: `action-${Date.now()}`,
1895
+ tool: "Message Sent",
1896
+ timestamp: Date.now(),
1897
+ description: inputValue.substring(0, 50) + (inputValue.length > 50 ? "..." : "")
1898
+ };
1899
+ setCompletedActions((prev) => [...prev, newAction]);
1900
+ triggerActionFade();
1901
+ }
1902
+ };
1903
+ const handleMouseDown = (e) => {
1904
+ if (isMobile) return;
1905
+ if (e.target === dragRef.current || e.target.classList.contains("drag-handle")) {
1906
+ setIsDragging(true);
1907
+ setDragStart({ x: e.clientX - position.x, y: e.clientY - position.y });
1694
1908
  }
1695
1909
  };
1696
1910
  const handleKeyDown = (e) => {
@@ -1698,13 +1912,12 @@ var SubtitleOverlay = ({
1698
1912
  e.preventDefault();
1699
1913
  handleSend();
1700
1914
  }
1701
- if (e.key === "Escape" && isListening) {
1702
- onMicClick();
1703
- }
1704
- };
1705
- const handleSuggestionTap = () => {
1706
- if (suggestions.length > 0 && !inputValue.trim()) {
1707
- onInputChange(suggestions[currentSuggestionIndex].text);
1915
+ if (e.key === "Escape") {
1916
+ if (isListening) {
1917
+ onMicClick();
1918
+ } else if (expansionState === "expanded") {
1919
+ setExpansionState("collapsed");
1920
+ }
1708
1921
  }
1709
1922
  };
1710
1923
  const handleInputTouchStart = (e) => {
@@ -1760,7 +1973,6 @@ var SubtitleOverlay = ({
1760
1973
  const lastAiMessage = messages.filter((m) => m.type === "ai").slice(-1)[0];
1761
1974
  const getIcon = () => {
1762
1975
  if (expansionState === "collapsed") return "@/";
1763
- if (isListening) return "~/";
1764
1976
  return "</";
1765
1977
  };
1766
1978
  const getIconTitle = () => {
@@ -1838,42 +2050,130 @@ var SubtitleOverlay = ({
1838
2050
  return /* @__PURE__ */ jsxs6(
1839
2051
  "div",
1840
2052
  {
1841
- className: `fixed bottom-0 left-0 right-0 transition-all duration-300 ease-in-out`,
2053
+ ref: dragRef,
2054
+ className: `fixed transition-all duration-300 ease-in-out ${!isMobile && (isDragging ? "cursor-grabbing" : "")}`,
1842
2055
  style: {
1843
2056
  opacity,
1844
2057
  bottom: isMobile ? "env(safe-area-inset-bottom, 0px)" : "0px",
2058
+ left: isMobile ? "0" : "50%",
2059
+ right: isMobile ? "0" : "auto",
1845
2060
  zIndex: 55,
2061
+ width: isMobile ? "100vw" : "650px",
1846
2062
  maxWidth: isMobile ? "100vw" : "650px",
1847
- marginLeft: isMobile ? "0" : "auto",
1848
- marginRight: isMobile ? "0" : "auto",
1849
- padding: isMobile ? "12px" : "16px"
2063
+ padding: isMobile ? "12px" : "16px",
2064
+ transform: isMobile ? "none" : `translate(calc(-50% + ${position.x}px), ${position.y}px)`,
2065
+ pointerEvents: "auto",
2066
+ userSelect: isDragging ? "none" : "auto"
1850
2067
  },
1851
2068
  onTouchStart: handleTouchStart,
1852
2069
  onTouchMove: handleTouchMove,
1853
2070
  onTouchEnd: handleTouchEnd,
2071
+ onMouseDown: !isMobile ? handleMouseDown : void 0,
1854
2072
  "data-testid": "subtitle-overlay",
1855
2073
  role: "complementary",
1856
2074
  "aria-label": "Chat overlay",
1857
2075
  children: [
1858
- lastAiMessage && messageOpacity > 0 && /* @__PURE__ */ jsxs6(
2076
+ !isMobile && /* @__PURE__ */ jsx10(
1859
2077
  "div",
1860
2078
  {
1861
- className: `mb-2 px-4 py-2 text-sm rounded-2xl transition-opacity duration-1000 ease-out animate-popup-in ${theme === "dark" ? "text-white" : "text-gray-900"}`,
2079
+ className: "drag-handle absolute -top-3 left-1/2 transform -translate-x-1/2 cursor-grab active:cursor-grabbing opacity-40 hover:opacity-70 transition-opacity",
2080
+ style: {
2081
+ width: "40px",
2082
+ height: "6px",
2083
+ background: theme === "dark" ? "rgba(255, 255, 255, 0.3)" : "rgba(0, 0, 0, 0.3)",
2084
+ borderRadius: "3px"
2085
+ },
2086
+ "aria-label": "Drag to reposition",
2087
+ "data-testid": "subtitle-overlay-drag-handle"
2088
+ }
2089
+ ),
2090
+ showCompletedActions && completedActions.length > 0 && /* @__PURE__ */ jsxs6(
2091
+ "div",
2092
+ {
2093
+ className: `mb-2 px-4 py-3 text-xs rounded-2xl animate-popup-in ${theme === "dark" ? "text-white" : "text-gray-900"}`,
1862
2094
  style: {
1863
- opacity: messageOpacity,
1864
- pointerEvents: messageOpacity === 0 ? "none" : "auto",
1865
2095
  ...theme === "dark" ? GLASS_RESPONSE_BUBBLE.dark : GLASS_RESPONSE_BUBBLE.light,
1866
- animation: messageOpacity === 0 ? "popupFadeOut 0.5s forwards" : void 0
2096
+ maxHeight: "200px",
2097
+ overflowY: "auto"
2098
+ },
2099
+ role: "log",
2100
+ "aria-label": "Completed actions",
2101
+ "data-testid": "completed-actions-list",
2102
+ children: [
2103
+ /* @__PURE__ */ jsxs6("div", { className: "font-medium opacity-70 mb-2 flex items-center justify-between", children: [
2104
+ /* @__PURE__ */ jsx10("span", { children: "Completed Actions" }),
2105
+ /* @__PURE__ */ jsx10(
2106
+ "button",
2107
+ {
2108
+ onClick: () => setShowCompletedActions(false),
2109
+ className: "opacity-50 hover:opacity-100",
2110
+ "aria-label": "Close completed actions",
2111
+ children: "\xD7"
2112
+ }
2113
+ )
2114
+ ] }),
2115
+ /* @__PURE__ */ jsx10("div", { className: "space-y-1", children: completedActions.map((action) => /* @__PURE__ */ jsxs6("div", { className: "text-xs opacity-80 border-l-2 border-green-500 pl-2", children: [
2116
+ /* @__PURE__ */ jsx10("div", { className: "font-medium", children: action.tool }),
2117
+ /* @__PURE__ */ jsx10("div", { className: "opacity-70", children: action.description })
2118
+ ] }, action.id)) })
2119
+ ]
2120
+ }
2121
+ ),
2122
+ !showCompletedActions && (latestActionOpacity > 0 || lastAiMessage && messageOpacity > 0) && /* @__PURE__ */ jsxs6(
2123
+ "div",
2124
+ {
2125
+ className: `mb-2 px-4 py-2 text-xs rounded-2xl ${theme === "dark" ? "text-white" : "text-gray-900"}`,
2126
+ style: {
2127
+ ...theme === "dark" ? GLASS_RESPONSE_BUBBLE.dark : GLASS_RESPONSE_BUBBLE.light,
2128
+ opacity: Math.max(latestActionOpacity, messageOpacity),
2129
+ transition: "opacity 0.6s ease-out",
2130
+ pointerEvents: latestActionOpacity === 0 && messageOpacity === 0 ? "none" : "auto"
1867
2131
  },
1868
2132
  role: "status",
1869
2133
  "aria-live": "polite",
2134
+ "data-testid": "subtitle-overlay-ai-message",
1870
2135
  children: [
1871
- /* @__PURE__ */ jsx10("span", { className: "font-medium opacity-70", children: "AI:" }),
1872
- " ",
1873
- lastAiMessage.text
2136
+ latestActionOpacity > 0 && completedActions.length > 0 && (() => {
2137
+ const latest = completedActions[completedActions.length - 1];
2138
+ return /* @__PURE__ */ jsxs6(
2139
+ "div",
2140
+ {
2141
+ className: "border-l-2 border-green-500 pl-2 mb-1",
2142
+ style: { opacity: latestActionOpacity, transition: "opacity 0.6s ease-out" },
2143
+ children: [
2144
+ /* @__PURE__ */ jsx10("span", { className: "font-medium", children: latest.tool }),
2145
+ /* @__PURE__ */ jsx10("span", { className: "opacity-70 ml-1", children: latest.description })
2146
+ ]
2147
+ }
2148
+ );
2149
+ })(),
2150
+ lastAiMessage && messageOpacity > 0 && /* @__PURE__ */ jsxs6("div", { style: { opacity: messageOpacity, transition: "opacity 0.8s ease-out" }, children: [
2151
+ /* @__PURE__ */ jsx10("span", { className: "font-medium opacity-70", children: "AI:" }),
2152
+ " ",
2153
+ /* @__PURE__ */ jsx10("span", { className: "text-sm", children: lastAiMessage.text })
2154
+ ] })
1874
2155
  ]
1875
2156
  }
1876
2157
  ),
2158
+ completedActions.length > 0 && !showCompletedActions && /* @__PURE__ */ jsx10("div", { className: "flex justify-center mb-1", children: /* @__PURE__ */ jsx10(
2159
+ "button",
2160
+ {
2161
+ type: "button",
2162
+ onClick: () => setShowCompletedActions(true),
2163
+ className: `transition-all flex items-center justify-center ${theme === "dark" ? "text-gray-500 hover:text-gray-300" : "text-gray-400 hover:text-gray-600"}`,
2164
+ style: {
2165
+ width: 28,
2166
+ height: 14,
2167
+ fontSize: 10,
2168
+ lineHeight: 1,
2169
+ opacity: 0.5
2170
+ },
2171
+ title: `${completedActions.length} previous actions`,
2172
+ "data-testid": "completed-actions-toggle",
2173
+ "aria-label": `Show ${completedActions.length} completed actions`,
2174
+ children: /* @__PURE__ */ jsx10("svg", { width: "16", height: "8", viewBox: "0 0 16 8", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx10("path", { d: "M2 6L8 2L14 6" }) })
2175
+ }
2176
+ ) }),
1877
2177
  /* @__PURE__ */ jsxs6("div", { className: "flex items-center space-x-2", children: [
1878
2178
  hasTTSWidgets && /* @__PURE__ */ jsx10(
1879
2179
  "button",
@@ -1913,8 +2213,7 @@ var SubtitleOverlay = ({
1913
2213
  onTouchStart: handleInputTouchStart,
1914
2214
  onTouchMove: handleInputTouchMove,
1915
2215
  onTouchEnd: handleInputTouchEnd,
1916
- onClick: handleSuggestionTap,
1917
- placeholder: suggestions.length > 0 && !inputValue.trim() ? `${suggestions[currentSuggestionIndex].text} (tap to use, swipe \u2195 to change)` : config.placeholder || "Type or speak...",
2216
+ placeholder: config.placeholder || "Type or speak...",
1918
2217
  className: "flex-1 px-3 py-2 text-sm bg-transparent focus:outline-none placeholder:opacity-60",
1919
2218
  style: {
1920
2219
  color: effectiveGlassTheme === "dark" ? "rgba(255, 255, 255, 0.95)" : "rgba(0, 0, 0, 0.9)"
@@ -1923,7 +2222,7 @@ var SubtitleOverlay = ({
1923
2222
  "aria-label": "Chat message input"
1924
2223
  }
1925
2224
  ),
1926
- isListening && /* @__PURE__ */ jsx10("div", { className: "flex space-x-1 items-center", "aria-hidden": "true", children: [...Array(5)].map((_, i) => /* @__PURE__ */ jsx10(
2225
+ isListening && /* @__PURE__ */ jsx10("div", { className: "flex space-x-1 items-center", "aria-hidden": "true", "data-testid": "subtitle-overlay-waveform", children: [...Array(5)].map((_, i) => /* @__PURE__ */ jsx10(
1927
2226
  "div",
1928
2227
  {
1929
2228
  className: "w-0.5 bg-red-500 rounded-full animate-pulse",
@@ -1934,7 +2233,7 @@ var SubtitleOverlay = ({
1934
2233
  },
1935
2234
  i
1936
2235
  )) }),
1937
- inputValue.trim() && !isListening && /* @__PURE__ */ jsx10(
2236
+ inputValue.trim() && /* @__PURE__ */ jsx10(
1938
2237
  "button",
1939
2238
  {
1940
2239
  type: "button",
@@ -2003,8 +2302,203 @@ var SubtitleOverlay = ({
2003
2302
  );
2004
2303
  };
2005
2304
 
2305
+ // src/components/SlashCommand/useSlashCommand.ts
2306
+ import { useState as useState7, useMemo as useMemo2, useCallback as useCallback5, useRef as useRef6, useEffect as useEffect5 } from "react";
2307
+ import { ToolRegistry } from "@supernal/interface/browser";
2308
+ function useSlashCommand(inputValue, onSelect) {
2309
+ const [selectedIndex, setSelectedIndex] = useState7(0);
2310
+ const prevOpenRef = useRef6(false);
2311
+ const isOpen = inputValue.startsWith("/");
2312
+ const query = isOpen ? inputValue.slice(1) : "";
2313
+ useEffect5(() => {
2314
+ if (isOpen && !prevOpenRef.current) {
2315
+ setSelectedIndex(0);
2316
+ }
2317
+ prevOpenRef.current = isOpen;
2318
+ }, [isOpen]);
2319
+ useEffect5(() => {
2320
+ setSelectedIndex(0);
2321
+ }, [query]);
2322
+ const filteredTools = useMemo2(() => {
2323
+ if (!isOpen) return [];
2324
+ const locationTools = ToolRegistry.getToolsByLocation();
2325
+ const aiTools = locationTools.filter((t) => t.aiEnabled);
2326
+ if (!query) return aiTools;
2327
+ const q = query.toLowerCase();
2328
+ return aiTools.filter((tool) => {
2329
+ const fields = [
2330
+ tool.name?.toLowerCase() ?? "",
2331
+ tool.description?.toLowerCase() ?? "",
2332
+ tool.toolId?.toLowerCase() ?? "",
2333
+ ...(tool.examples || []).map((ex) => ex?.toLowerCase() ?? ""),
2334
+ ...(tool.keywords || []).map((kw) => kw?.toLowerCase() ?? "")
2335
+ ];
2336
+ return fields.some((f) => f.includes(q));
2337
+ });
2338
+ }, [isOpen, query]);
2339
+ const close = useCallback5(() => {
2340
+ }, []);
2341
+ const selectTool = useCallback5((tool) => {
2342
+ const command = tool.examples?.[0] || tool.name?.toLowerCase() || tool.toolId;
2343
+ onSelect(command);
2344
+ }, [onSelect]);
2345
+ const onKeyDown = useCallback5((e) => {
2346
+ if (!isOpen || filteredTools.length === 0) return;
2347
+ if (e.key === "ArrowDown") {
2348
+ e.preventDefault();
2349
+ setSelectedIndex((prev) => (prev + 1) % filteredTools.length);
2350
+ } else if (e.key === "ArrowUp") {
2351
+ e.preventDefault();
2352
+ setSelectedIndex((prev) => (prev - 1 + filteredTools.length) % filteredTools.length);
2353
+ } else if (e.key === "Enter" && filteredTools[selectedIndex]) {
2354
+ e.preventDefault();
2355
+ selectTool(filteredTools[selectedIndex]);
2356
+ } else if (e.key === "Escape") {
2357
+ e.preventDefault();
2358
+ onSelect("");
2359
+ } else if (e.key === "Tab" && filteredTools[selectedIndex]) {
2360
+ e.preventDefault();
2361
+ selectTool(filteredTools[selectedIndex]);
2362
+ }
2363
+ }, [isOpen, filteredTools, selectedIndex, selectTool, onSelect]);
2364
+ return {
2365
+ isOpen,
2366
+ filteredTools,
2367
+ selectedIndex,
2368
+ onKeyDown,
2369
+ selectTool,
2370
+ close
2371
+ };
2372
+ }
2373
+
2374
+ // src/components/SlashCommand/SlashCommandPopup.tsx
2375
+ import { useEffect as useEffect6, useRef as useRef7 } from "react";
2376
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
2377
+ var MAX_VISIBLE_ITEMS = 8;
2378
+ var SlashCommandPopup = ({
2379
+ tools,
2380
+ selectedIndex,
2381
+ onSelect,
2382
+ onClose
2383
+ }) => {
2384
+ const listRef = useRef7(null);
2385
+ const selectedRef = useRef7(null);
2386
+ useEffect6(() => {
2387
+ selectedRef.current?.scrollIntoView({ block: "nearest" });
2388
+ }, [selectedIndex]);
2389
+ useEffect6(() => {
2390
+ const handleClickOutside = (e) => {
2391
+ if (listRef.current && !listRef.current.contains(e.target)) {
2392
+ onClose();
2393
+ }
2394
+ };
2395
+ document.addEventListener("mousedown", handleClickOutside);
2396
+ return () => document.removeEventListener("mousedown", handleClickOutside);
2397
+ }, [onClose]);
2398
+ if (tools.length === 0) return null;
2399
+ const itemHeight = 52;
2400
+ const maxHeight = MAX_VISIBLE_ITEMS * itemHeight;
2401
+ return /* @__PURE__ */ jsxs7(
2402
+ "div",
2403
+ {
2404
+ ref: listRef,
2405
+ style: {
2406
+ position: "absolute",
2407
+ bottom: "100%",
2408
+ left: 0,
2409
+ right: 0,
2410
+ marginBottom: 4,
2411
+ maxHeight,
2412
+ overflowY: tools.length > MAX_VISIBLE_ITEMS ? "auto" : "hidden",
2413
+ borderRadius: 12,
2414
+ ...GLASS_RESPONSE_BUBBLE.dark,
2415
+ zIndex: 999998
2416
+ },
2417
+ "data-slash-command-popup": true,
2418
+ children: [
2419
+ /* @__PURE__ */ jsxs7("div", { style: {
2420
+ padding: "8px 12px 4px",
2421
+ color: "rgba(255,255,255,0.45)",
2422
+ fontSize: 11,
2423
+ fontWeight: 500,
2424
+ letterSpacing: "0.02em"
2425
+ }, children: [
2426
+ "Commands \xB7 ",
2427
+ tools.length,
2428
+ " available"
2429
+ ] }),
2430
+ tools.map((tool, index) => {
2431
+ const isSelected = index === selectedIndex;
2432
+ return /* @__PURE__ */ jsxs7(
2433
+ "button",
2434
+ {
2435
+ ref: isSelected ? selectedRef : void 0,
2436
+ onClick: () => onSelect(tool),
2437
+ style: {
2438
+ width: "100%",
2439
+ display: "block",
2440
+ padding: "8px 12px",
2441
+ background: isSelected ? "rgba(59, 130, 246, 0.25)" : "none",
2442
+ border: "none",
2443
+ cursor: "pointer",
2444
+ textAlign: "left",
2445
+ color: "#fff",
2446
+ transition: "background 0.1s"
2447
+ },
2448
+ onMouseEnter: (e) => {
2449
+ if (!isSelected) {
2450
+ e.currentTarget.style.background = "rgba(255,255,255,0.06)";
2451
+ }
2452
+ },
2453
+ onMouseLeave: (e) => {
2454
+ if (!isSelected) {
2455
+ e.currentTarget.style.background = "none";
2456
+ }
2457
+ },
2458
+ children: [
2459
+ /* @__PURE__ */ jsxs7("div", { style: { fontSize: 13, fontWeight: 500 }, children: [
2460
+ /* @__PURE__ */ jsxs7("span", { style: { color: "rgba(147, 197, 253, 0.9)" }, children: [
2461
+ "/",
2462
+ tool.toolId
2463
+ ] }),
2464
+ /* @__PURE__ */ jsx11("span", { style: { color: "rgba(255,255,255,0.7)", fontWeight: 400, marginLeft: 8 }, children: tool.name })
2465
+ ] }),
2466
+ tool.description && /* @__PURE__ */ jsx11("div", { style: {
2467
+ fontSize: 11,
2468
+ color: "rgba(255,255,255,0.4)",
2469
+ marginTop: 2,
2470
+ lineHeight: 1.3,
2471
+ overflow: "hidden",
2472
+ textOverflow: "ellipsis",
2473
+ whiteSpace: "nowrap"
2474
+ }, children: tool.description })
2475
+ ]
2476
+ },
2477
+ tool.toolId
2478
+ );
2479
+ }),
2480
+ /* @__PURE__ */ jsxs7("div", { style: {
2481
+ padding: "6px 12px",
2482
+ borderTop: "1px solid rgba(255,255,255,0.06)",
2483
+ color: "rgba(255,255,255,0.3)",
2484
+ fontSize: 10
2485
+ }, children: [
2486
+ /* @__PURE__ */ jsx11("kbd", { style: { padding: "1px 3px", borderRadius: 3, border: "1px solid rgba(255,255,255,0.15)", fontSize: 9 }, children: "\u2191\u2193" }),
2487
+ " navigate",
2488
+ " ",
2489
+ /* @__PURE__ */ jsx11("kbd", { style: { padding: "1px 3px", borderRadius: 3, border: "1px solid rgba(255,255,255,0.15)", fontSize: 9 }, children: "Enter" }),
2490
+ " select",
2491
+ " ",
2492
+ /* @__PURE__ */ jsx11("kbd", { style: { padding: "1px 3px", borderRadius: 3, border: "1px solid rgba(255,255,255,0.15)", fontSize: 9 }, children: "Esc" }),
2493
+ " dismiss"
2494
+ ] })
2495
+ ]
2496
+ }
2497
+ );
2498
+ };
2499
+
2006
2500
  // src/components/ChatBubble/ChatBubble.tsx
2007
- import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
2501
+ import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
2008
2502
  var ChatBubble = ({
2009
2503
  messages,
2010
2504
  onSendMessage,
@@ -2019,56 +2513,65 @@ var ChatBubble = ({
2019
2513
  }) => {
2020
2514
  const mergedConfig = { ...DEFAULT_CONFIG, ...userConfig };
2021
2515
  if (userConfig?.logo && !userConfig?.avatar) {
2022
- mergedConfig.avatar = /* @__PURE__ */ jsx11("img", { src: userConfig.logo, alt: "Supernal", className: "w-6 h-6" });
2516
+ mergedConfig.avatar = /* @__PURE__ */ jsx12("img", { src: userConfig.logo, alt: "Supernal", className: "w-6 h-6" });
2023
2517
  }
2024
2518
  const config = mergedConfig;
2025
- const [isExpanded, setIsExpanded] = useState7(defaultExpanded);
2026
- const [isMinimized, setIsMinimized] = useState7(false);
2027
- const [inputValue, setInputValue] = useState7("");
2028
- const [lastReadMessageCount, setLastReadMessageCount] = useState7(0);
2029
- const [showWelcome, setShowWelcome] = useState7(
2519
+ const [isExpanded, setIsExpanded] = useState8(defaultExpanded);
2520
+ const [isMinimized, setIsMinimized] = useState8(false);
2521
+ const [inputValue, setInputValue] = useState8("");
2522
+ const [lastReadMessageCount, setLastReadMessageCount] = useState8(0);
2523
+ const [showWelcome, setShowWelcome] = useState8(
2030
2524
  config.welcome?.enabled && messages.length === 0
2031
2525
  );
2032
- const [isDragging, setIsDragging] = useState7(false);
2033
- const [dragInitiated, setDragInitiated] = useState7(false);
2034
- const [isDocked, setIsDocked] = useState7(true);
2035
- const [dockPosition, setDockPosition] = useState7(position);
2036
- const [panelPosition, setPanelPosition] = useState7({ x: 0, y: 0 });
2037
- const [theme, setTheme] = useState7("light");
2038
- const [showMoreMenu, setShowMoreMenu] = useState7(false);
2039
- const [, setTimestampTick] = useState7(0);
2040
- const [localGlassMode, setLocalGlassMode] = useState7(config.glassMode ?? true);
2041
- const [glassOpacity, setGlassOpacity] = useState7("medium");
2042
- const [notifications, setNotifications] = useState7(true);
2043
- const [voiceEnabled, setVoiceEnabled] = useState7(true);
2044
- const [usePremiumVoices, setUsePremiumVoices] = useState7(false);
2045
- const [autoReadResponses, setAutoReadResponses] = useState7(false);
2046
- const [ttsSpeed, setTtsSpeed] = useState7(1);
2047
- const [sttAutoRecordTimeout, setSttAutoRecordTimeout] = useState7(5e3);
2048
- const [sttAutoExecute, setSttAutoExecute] = useState7(true);
2049
- const sttAutoRecordTimeoutRef = useRef6(null);
2526
+ const [isDragging, setIsDragging] = useState8(false);
2527
+ const [dragInitiated, setDragInitiated] = useState8(false);
2528
+ const [isDocked, setIsDocked] = useState8(true);
2529
+ const [dockPosition, setDockPosition] = useState8(position);
2530
+ const [panelPosition, setPanelPosition] = useState8({ x: 0, y: 0 });
2531
+ const [theme, setTheme] = useState8("light");
2532
+ const [showMoreMenu, setShowMoreMenu] = useState8(false);
2533
+ const [, setTimestampTick] = useState8(0);
2534
+ const [localGlassMode, setLocalGlassMode] = useState8(config.glassMode ?? true);
2535
+ const [glassOpacity, setGlassOpacity] = useState8("medium");
2536
+ const [notifications, setNotifications] = useState8(true);
2537
+ const [voiceEnabled, setVoiceEnabled] = useState8(true);
2538
+ const [usePremiumVoices, setUsePremiumVoices] = useState8(false);
2539
+ const [autoReadResponses, setAutoReadResponses] = useState8(false);
2540
+ const [ttsSpeed, setTtsSpeed] = useState8(1);
2541
+ const [sttAutoRecordTimeout, setSttAutoRecordTimeout] = useState8(5e3);
2542
+ const [sttAutoExecute, setSttAutoExecute] = useState8(true);
2543
+ const sttAutoRecordTimeoutRef = useRef8(null);
2050
2544
  const { speak: speakTTS, stop: stopTTS, isPlaying: isTTSPlaying } = useTTS();
2051
2545
  const { startListening, stopListening, transcript: sttTranscript, isListening, resetTranscript } = useSTT();
2052
- const [displayMode, setDisplayMode] = useState7(propDisplayMode);
2053
- const [drawerSide, setDrawerSide] = useState7(propDrawerSide);
2054
- useEffect5(() => {
2055
- setDisplayMode(propDisplayMode);
2546
+ const slashCommand = useSlashCommand(inputValue, (command) => {
2547
+ setInputValue(command);
2548
+ setTimeout(() => inputRef.current?.focus(), 0);
2549
+ });
2550
+ const [displayMode, setDisplayMode] = useState8(propDisplayMode);
2551
+ const [drawerSide, setDrawerSide] = useState8(propDrawerSide);
2552
+ const displayModeLoadedFromStorage = useRef8(false);
2553
+ useEffect7(() => {
2554
+ if (!displayModeLoadedFromStorage.current) {
2555
+ setDisplayMode(propDisplayMode);
2556
+ }
2056
2557
  }, [propDisplayMode]);
2057
- const [drawerOpen, setDrawerOpen] = useState7(false);
2058
- const [touchStart, setTouchStart] = useState7(null);
2059
- const [swipeProgress, setSwipeProgress] = useState7(0);
2060
- const [isMobile, setIsMobile] = useState7(false);
2061
- const [isMac, setIsMac] = useState7(false);
2062
- const [currentHintIndex, setCurrentHintIndex] = useState7(0);
2063
- const [isHydrated, setIsHydrated] = useState7(false);
2064
- useEffect5(() => {
2558
+ const [drawerOpen, setDrawerOpen] = useState8(false);
2559
+ const [touchStart, setTouchStart] = useState8(null);
2560
+ const [swipeProgress, setSwipeProgress] = useState8(0);
2561
+ const [isMobile, setIsMobile] = useState8(false);
2562
+ const lastEscapeTimeRef = useRef8(0);
2563
+ const DOUBLE_ESCAPE_THRESHOLD_MS = 500;
2564
+ const [isMac, setIsMac] = useState8(false);
2565
+ const [currentHintIndex, setCurrentHintIndex] = useState8(0);
2566
+ const [isHydrated, setIsHydrated] = useState8(false);
2567
+ useEffect7(() => {
2065
2568
  if (typeof window !== "undefined") {
2066
2569
  const platform = window.navigator.platform.toLowerCase();
2067
2570
  const isMacPlatform = platform.includes("mac");
2068
2571
  setIsMac(isMacPlatform);
2069
2572
  }
2070
2573
  }, []);
2071
- const inputHints = useMemo2(() => {
2574
+ const inputHints = useMemo3(() => {
2072
2575
  const modKey = isMac ? "Cmd" : "Ctrl";
2073
2576
  return [
2074
2577
  `Press ${modKey}+/ to start voice recording`,
@@ -2077,14 +2580,14 @@ var ChatBubble = ({
2077
2580
  sttAutoExecute ? `Voice commands execute automatically` : "Voice commands fill this input"
2078
2581
  ];
2079
2582
  }, [isMac, sttAutoExecute]);
2080
- useEffect5(() => {
2583
+ useEffect7(() => {
2081
2584
  setCurrentHintIndex((prev) => (prev + 1) % inputHints.length);
2082
2585
  }, [messages.length, inputHints.length]);
2083
- const messagesEndRef = useRef6(null);
2084
- const inputRef = useRef6(null);
2085
- const panelRef = useRef6(null);
2086
- const dragRef = useRef6(null);
2087
- const rafRef = useRef6(null);
2586
+ const messagesEndRef = useRef8(null);
2587
+ const inputRef = useRef8(null);
2588
+ const panelRef = useRef8(null);
2589
+ const dragRef = useRef8(null);
2590
+ const rafRef = useRef8(null);
2088
2591
  const formatRelativeTime = (timestamp) => {
2089
2592
  const now = /* @__PURE__ */ new Date();
2090
2593
  const messageTime = new Date(timestamp);
@@ -2099,8 +2602,30 @@ var ChatBubble = ({
2099
2602
  if (diffDays < 7) return `${diffDays} ${diffDays === 1 ? "day" : "days"} ago`;
2100
2603
  return messageTime.toLocaleDateString();
2101
2604
  };
2102
- useEffect5(() => {
2103
- if (variant === "full") {
2605
+ useEffect7(() => {
2606
+ if (variant === "floating" && panelPosition.x === 0 && panelPosition.y === 0) {
2607
+ try {
2608
+ const stored = localStorage.getItem(storageKey);
2609
+ if (stored !== null) {
2610
+ const state = JSON.parse(stored);
2611
+ const pos = state.panelPosition;
2612
+ if (pos && typeof pos.x === "number" && typeof pos.y === "number") {
2613
+ setPanelPosition(pos);
2614
+ return;
2615
+ }
2616
+ }
2617
+ } catch (error) {
2618
+ console.error("ChatBubble: Error loading floating position from localStorage", error);
2619
+ }
2620
+ if (typeof window !== "undefined") {
2621
+ const centerX = (window.innerWidth - 300) / 2;
2622
+ const centerY = (window.innerHeight - 150) / 2;
2623
+ setPanelPosition({ x: centerX, y: centerY });
2624
+ }
2625
+ }
2626
+ }, [variant, storageKey, panelPosition.x, panelPosition.y]);
2627
+ useEffect7(() => {
2628
+ if (variant === "full" || variant === "drawer" || variant === "subtitle") {
2104
2629
  try {
2105
2630
  const stored = localStorage.getItem(storageKey);
2106
2631
  if (stored !== null) {
@@ -2141,6 +2666,7 @@ var ChatBubble = ({
2141
2666
  }
2142
2667
  if (state.displayMode !== void 0) {
2143
2668
  setDisplayMode(state.displayMode);
2669
+ displayModeLoadedFromStorage.current = true;
2144
2670
  }
2145
2671
  if (state.drawerSide !== void 0) {
2146
2672
  setDrawerSide(state.drawerSide);
@@ -2176,12 +2702,12 @@ var ChatBubble = ({
2176
2702
  }
2177
2703
  setIsHydrated(true);
2178
2704
  }, [storageKey, variant, defaultExpanded, position]);
2179
- useEffect5(() => {
2180
- if (variant !== "full") {
2705
+ useEffect7(() => {
2706
+ if (variant !== "full" && variant !== "drawer" && variant !== "subtitle") {
2181
2707
  setIsHydrated(true);
2182
2708
  }
2183
2709
  }, [variant]);
2184
- useEffect5(() => {
2710
+ useEffect7(() => {
2185
2711
  if (!isExpanded || isDocked || !panelRef.current) return;
2186
2712
  const checkBounds = () => {
2187
2713
  const rect = panelRef.current?.getBoundingClientRect();
@@ -2198,25 +2724,46 @@ var ChatBubble = ({
2198
2724
  const timeoutId = setTimeout(checkBounds, 100);
2199
2725
  return () => clearTimeout(timeoutId);
2200
2726
  }, [isExpanded, isDocked]);
2201
- useEffect5(() => {
2727
+ useEffect7(() => {
2728
+ const isSubtitleMode = displayMode === "subtitle" || displayMode === "auto" && variant === "subtitle";
2729
+ if (isSubtitleMode) return;
2202
2730
  const handleKeyDown = (e) => {
2203
- if (e.key === "Escape" && isExpanded && !isDocked) {
2731
+ if (e.key !== "Escape") return;
2732
+ const now = Date.now();
2733
+ const timeSinceLastEscape = now - lastEscapeTimeRef.current;
2734
+ const effectiveVariant = displayMode !== "auto" ? displayMode : isMobile ? "subtitle" : variant;
2735
+ if (timeSinceLastEscape < DOUBLE_ESCAPE_THRESHOLD_MS) {
2736
+ console.log("[ChatBubble] Double-escape detected - cycling variant from:", effectiveVariant);
2737
+ if (effectiveVariant === "full" || effectiveVariant === "floating" || effectiveVariant === "drawer") {
2738
+ setDisplayMode("subtitle");
2739
+ displayModeLoadedFromStorage.current = true;
2740
+ console.log("[ChatBubble] Switched to subtitle mode");
2741
+ } else if (effectiveVariant === "subtitle") {
2742
+ setDisplayMode("full");
2743
+ displayModeLoadedFromStorage.current = true;
2744
+ console.log("[ChatBubble] Switched to full mode");
2745
+ }
2746
+ lastEscapeTimeRef.current = 0;
2747
+ return;
2748
+ }
2749
+ if (isExpanded && !isDocked) {
2204
2750
  console.log("ChatBubble reset via Escape key");
2205
2751
  setIsDocked(true);
2206
2752
  setDockPosition(position);
2207
2753
  setPanelPosition({ x: 0, y: 0 });
2208
2754
  }
2755
+ lastEscapeTimeRef.current = now;
2209
2756
  };
2210
2757
  window.addEventListener("keydown", handleKeyDown);
2211
2758
  return () => window.removeEventListener("keydown", handleKeyDown);
2212
- }, [isExpanded, isDocked, position]);
2213
- useEffect5(() => {
2759
+ }, [isExpanded, isDocked, position, variant, displayMode, isMobile]);
2760
+ useEffect7(() => {
2214
2761
  if (typeof window !== "undefined") {
2215
2762
  const isDark = document.documentElement.getAttribute("data-theme") === "dark";
2216
2763
  setTheme(isDark ? "dark" : "light");
2217
2764
  }
2218
2765
  }, []);
2219
- useEffect5(() => {
2766
+ useEffect7(() => {
2220
2767
  if (typeof window === "undefined") return;
2221
2768
  const mediaQuery = window.matchMedia("(max-width: 767px)");
2222
2769
  const handleChange = (e) => {
@@ -2226,20 +2773,27 @@ var ChatBubble = ({
2226
2773
  mediaQuery.addEventListener("change", handleChange);
2227
2774
  return () => mediaQuery.removeEventListener("change", handleChange);
2228
2775
  }, []);
2229
- const currentVariant = React7.useMemo(() => {
2776
+ const currentVariant = React8.useMemo(() => {
2230
2777
  if (displayMode !== "auto") {
2231
2778
  return displayMode;
2232
2779
  }
2233
- return isMobile ? "drawer" : variant;
2780
+ return isMobile && variant === "full" ? "subtitle" : variant;
2234
2781
  }, [displayMode, isMobile, variant]);
2235
- useEffect5(() => {
2782
+ const prevVariantRef = React8.useRef(variant);
2783
+ useEffect7(() => {
2784
+ if (prevVariantRef.current !== variant && displayMode !== "auto") {
2785
+ setDisplayMode("auto");
2786
+ prevVariantRef.current = variant;
2787
+ }
2788
+ }, [variant, displayMode]);
2789
+ useEffect7(() => {
2236
2790
  const interval = setInterval(() => {
2237
2791
  setTimestampTick((tick) => tick + 1);
2238
2792
  }, 6e4);
2239
2793
  return () => clearInterval(interval);
2240
2794
  }, []);
2241
- useEffect5(() => {
2242
- if (variant === "full" || variant === "drawer") {
2795
+ useEffect7(() => {
2796
+ if (variant === "full" || variant === "drawer" || variant === "subtitle") {
2243
2797
  try {
2244
2798
  localStorage.setItem(
2245
2799
  storageKey,
@@ -2270,7 +2824,7 @@ var ChatBubble = ({
2270
2824
  }
2271
2825
  }, [isExpanded, isMinimized, isDocked, dockPosition, panelPosition, theme, localGlassMode, notifications, displayMode, drawerSide, drawerOpen, glassOpacity, voiceEnabled, usePremiumVoices, autoReadResponses, ttsSpeed, sttAutoRecordTimeout, sttAutoExecute, storageKey, variant]);
2272
2826
  const { registerInput } = useChatInput();
2273
- useEffect5(() => {
2827
+ useEffect7(() => {
2274
2828
  registerInput((text, submit = false) => {
2275
2829
  setInputValue(text);
2276
2830
  if (!isExpanded && variant === "full") {
@@ -2287,7 +2841,7 @@ var ChatBubble = ({
2287
2841
  }, [registerInput, onSendMessage]);
2288
2842
  const unreadCount = Math.max(0, messages.length - lastReadMessageCount);
2289
2843
  const hasUnread = unreadCount > 0 && !isExpanded && variant === "full";
2290
- useEffect5(() => {
2844
+ useEffect7(() => {
2291
2845
  if (isExpanded || variant === "floating") {
2292
2846
  messagesEndRef.current?.scrollIntoView({ behavior: "auto" });
2293
2847
  setLastReadMessageCount(messages.length);
@@ -2299,12 +2853,12 @@ var ChatBubble = ({
2299
2853
  }
2300
2854
  }
2301
2855
  }, [messages, isExpanded, variant]);
2302
- useEffect5(() => {
2856
+ useEffect7(() => {
2303
2857
  if (isExpanded && variant === "full") {
2304
2858
  inputRef.current?.focus();
2305
2859
  }
2306
2860
  }, [isExpanded, variant]);
2307
- useEffect5(() => {
2861
+ useEffect7(() => {
2308
2862
  if (!voiceEnabled || !autoReadResponses || messages.length === 0) return;
2309
2863
  const lastMessage = messages[messages.length - 1];
2310
2864
  if (lastMessage.type === "ai") {
@@ -2316,7 +2870,8 @@ var ChatBubble = ({
2316
2870
  });
2317
2871
  }
2318
2872
  }, [messages, voiceEnabled, autoReadResponses, ttsSpeed, usePremiumVoices, speakTTS]);
2319
- useEffect5(() => {
2873
+ useEffect7(() => {
2874
+ if (currentVariant === "subtitle") return;
2320
2875
  if (sttTranscript && voiceEnabled) {
2321
2876
  setInputValue(sttTranscript);
2322
2877
  resetTranscript();
@@ -2329,10 +2884,10 @@ var ChatBubble = ({
2329
2884
  sttAutoRecordTimeoutRef.current = null;
2330
2885
  }
2331
2886
  }
2332
- }, [sttTranscript, voiceEnabled, resetTranscript, sttAutoExecute, onSendMessage]);
2333
- useEffect5(() => {
2887
+ }, [sttTranscript, voiceEnabled, resetTranscript, sttAutoExecute, onSendMessage, currentVariant]);
2888
+ useEffect7(() => {
2889
+ if (currentVariant === "subtitle") return;
2334
2890
  const handleKeyDown = (e) => {
2335
- if (variant !== "full") return;
2336
2891
  if ((e.metaKey || e.ctrlKey) && e.key === "/" && voiceEnabled) {
2337
2892
  e.preventDefault();
2338
2893
  const wasExpanded = isExpanded;
@@ -2387,8 +2942,8 @@ var ChatBubble = ({
2387
2942
  clearTimeout(sttAutoRecordTimeoutRef.current);
2388
2943
  }
2389
2944
  };
2390
- }, [isExpanded, showMoreMenu, variant, voiceEnabled, isListening, startListening, stopListening, sttAutoRecordTimeout]);
2391
- useEffect5(() => {
2945
+ }, [currentVariant, isExpanded, showMoreMenu, voiceEnabled, isListening, startListening, stopListening, sttAutoRecordTimeout]);
2946
+ useEffect7(() => {
2392
2947
  if (currentVariant !== "drawer") return;
2393
2948
  const handleKeyDown = (e) => {
2394
2949
  if (e.key === "Escape" && drawerOpen) {
@@ -2398,7 +2953,7 @@ var ChatBubble = ({
2398
2953
  window.addEventListener("keydown", handleKeyDown);
2399
2954
  return () => window.removeEventListener("keydown", handleKeyDown);
2400
2955
  }, [currentVariant, drawerOpen]);
2401
- useEffect5(() => {
2956
+ useEffect7(() => {
2402
2957
  if (!showMoreMenu) return;
2403
2958
  const handleClickOutside = (e) => {
2404
2959
  const target = e.target;
@@ -2409,7 +2964,7 @@ var ChatBubble = ({
2409
2964
  document.addEventListener("mousedown", handleClickOutside);
2410
2965
  return () => document.removeEventListener("mousedown", handleClickOutside);
2411
2966
  }, [showMoreMenu]);
2412
- useEffect5(() => {
2967
+ useEffect7(() => {
2413
2968
  if (typeof window === "undefined" || currentVariant !== "drawer") return;
2414
2969
  const EDGE_ZONE_PX = 20;
2415
2970
  const SWIPE_THRESHOLD = 0.4;
@@ -2474,12 +3029,8 @@ var ChatBubble = ({
2474
3029
  const rect = panelRef.current?.getBoundingClientRect();
2475
3030
  if (!rect) return;
2476
3031
  if (isDocked) {
2477
- const currentCenterX = rect.left + rect.width / 2;
2478
- const currentCenterY = rect.top + rect.height / 2;
2479
- const viewportCenterX = window.innerWidth / 2;
2480
- const viewportCenterY = window.innerHeight / 2;
2481
- const targetX = currentCenterX - viewportCenterX;
2482
- const targetY = currentCenterY - viewportCenterY;
3032
+ const targetX = rect.left;
3033
+ const targetY = rect.top;
2483
3034
  setPanelPosition({ x: targetX, y: targetY });
2484
3035
  dragRef.current = {
2485
3036
  startX: e.clientX,
@@ -2498,7 +3049,7 @@ var ChatBubble = ({
2498
3049
  };
2499
3050
  }
2500
3051
  };
2501
- useEffect5(() => {
3052
+ useEffect7(() => {
2502
3053
  if (!dragInitiated || !dragRef.current) return;
2503
3054
  const dragThresholdPx = 5;
2504
3055
  const handleMouseMove = (e) => {
@@ -2642,55 +3193,11 @@ var ChatBubble = ({
2642
3193
  const glassClasses = glassMode ? glassOpacity === "low" ? "backdrop-blur-xl bg-white/90 dark:bg-gray-900/90 border border-white/20 dark:border-white/10" : glassOpacity === "high" ? "backdrop-blur-xl bg-white/50 dark:bg-gray-900/50 border border-white/20 dark:border-white/10" : "backdrop-blur-xl bg-white/70 dark:bg-gray-900/70 border border-white/20 dark:border-white/10" : "bg-white dark:bg-gray-900";
2643
3194
  const glassGradient = glassMode ? glassOpacity === "low" ? "bg-gradient-to-br from-white/95 via-white/85 to-white/70 dark:from-gray-900/90 dark:via-gray-900/80 dark:to-gray-900/70" : glassOpacity === "high" ? "bg-gradient-to-br from-white/70 via-white/50 to-white/30 dark:from-gray-900/60 dark:via-gray-900/50 dark:to-gray-900/40" : "bg-gradient-to-br from-white/90 via-white/70 to-white/50 dark:from-gray-900/80 dark:via-gray-900/70 dark:to-gray-900/60" : "bg-white dark:bg-gray-900";
2644
3195
  const getFloatingPositionStyle = () => {
2645
- if (dockPosition.includes("top") && dockPosition.includes("left")) {
2646
- return {
2647
- top: 0,
2648
- left: 0,
2649
- transform: `translate(${panelPosition.x}px, ${panelPosition.y}px)`
2650
- };
2651
- } else if (dockPosition.includes("top") && dockPosition.includes("right")) {
2652
- return {
2653
- top: 0,
2654
- right: 0,
2655
- transform: `translate(${-panelPosition.x}px, ${panelPosition.y}px)`
2656
- };
2657
- } else if (dockPosition.includes("bottom") && dockPosition.includes("left")) {
2658
- return {
2659
- bottom: 0,
2660
- left: 0,
2661
- transform: `translate(${panelPosition.x}px, ${-panelPosition.y}px)`
2662
- };
2663
- } else if (dockPosition.includes("bottom") && dockPosition.includes("right")) {
2664
- return {
2665
- bottom: 0,
2666
- right: 0,
2667
- transform: `translate(${-panelPosition.x}px, ${-panelPosition.y}px)`
2668
- };
2669
- } else if (dockPosition.includes("left-center")) {
2670
- return {
2671
- left: 0,
2672
- top: "50%",
2673
- transform: `translate(${panelPosition.x}px, calc(-50% + ${panelPosition.y}px))`
2674
- };
2675
- } else if (dockPosition.includes("right-center")) {
2676
- return {
2677
- right: 0,
2678
- top: "50%",
2679
- transform: `translate(${-panelPosition.x}px, calc(-50% + ${panelPosition.y}px))`
2680
- };
2681
- } else if (dockPosition.includes("bottom-center")) {
2682
- return {
2683
- bottom: 0,
2684
- left: "50%",
2685
- transform: `translate(calc(-50% + ${panelPosition.x}px), ${-panelPosition.y}px)`
2686
- };
2687
- } else {
2688
- return {
2689
- left: "50%",
2690
- top: "50%",
2691
- transform: `translate(calc(-50% + ${panelPosition.x}px), calc(-50% + ${panelPosition.y}px))`
2692
- };
2693
- }
3196
+ return {
3197
+ top: 0,
3198
+ left: 0,
3199
+ transform: `translate(${panelPosition.x}px, ${panelPosition.y}px)`
3200
+ };
2694
3201
  };
2695
3202
  const maxHeightVh = 80;
2696
3203
  const dynamicHeight = `min(${maxHeightVh}vh, 700px)`;
@@ -2705,7 +3212,7 @@ var ChatBubble = ({
2705
3212
  return null;
2706
3213
  }
2707
3214
  if (currentVariant === "subtitle") {
2708
- return /* @__PURE__ */ jsx11(
3215
+ return /* @__PURE__ */ jsx12(
2709
3216
  SubtitleOverlay,
2710
3217
  {
2711
3218
  messages,
@@ -2726,36 +3233,41 @@ var ChatBubble = ({
2726
3233
  theme,
2727
3234
  config,
2728
3235
  sttTranscript,
2729
- resetTranscript
3236
+ resetTranscript,
3237
+ onSwitchToFullMode: () => {
3238
+ console.log("[ChatBubble] Switching from subtitle to full mode");
3239
+ setDisplayMode("full");
3240
+ displayModeLoadedFromStorage.current = true;
3241
+ }
2730
3242
  }
2731
3243
  );
2732
3244
  }
2733
3245
  if (currentVariant === "drawer") {
2734
3246
  const drawerWidth = "100vw";
2735
- return /* @__PURE__ */ jsxs7(Fragment3, { children: [
2736
- (drawerOpen || swipeProgress > 0) && /* @__PURE__ */ jsx11(
3247
+ return /* @__PURE__ */ jsxs8(Fragment3, { children: [
3248
+ (drawerOpen || swipeProgress > 0) && /* @__PURE__ */ jsx12(
2737
3249
  "div",
2738
3250
  {
2739
- className: "fixed inset-0 bg-black z-[99998] transition-opacity duration-300",
3251
+ className: "fixed inset-0 bg-black z-[49998] transition-opacity duration-300",
2740
3252
  style: {
2741
3253
  opacity: touchStart && swipeProgress > 0 ? swipeProgress / 100 * 0.5 : 0.5,
2742
3254
  zIndex: 999998
2743
- // Force high z-index for overlay
3255
+ // Super high z-index for overlay backdrop
2744
3256
  },
2745
3257
  onClick: () => setDrawerOpen(false)
2746
3258
  }
2747
3259
  ),
2748
- /* @__PURE__ */ jsxs7(
3260
+ /* @__PURE__ */ jsxs8(
2749
3261
  "div",
2750
3262
  {
2751
- className: `fixed ${drawerSide === "right" ? "right-0" : "left-0"} top-0 h-full z-[99999] flex flex-col ${glassClasses} shadow-2xl`,
3263
+ className: `fixed ${drawerSide === "right" ? "right-0" : "left-0"} top-0 h-full z-[49999] flex flex-col ${glassClasses} shadow-2xl`,
2752
3264
  style: {
2753
3265
  width: drawerWidth,
2754
3266
  transform: getDrawerTransform(),
2755
3267
  transition: touchStart ? "none" : "transform 300ms cubic-bezier(0.4, 0, 0.2, 1)",
2756
3268
  willChange: "transform",
2757
3269
  zIndex: 999999
2758
- // Force extremely high z-index
3270
+ // Super high z-index for drawer
2759
3271
  },
2760
3272
  role: "dialog",
2761
3273
  "aria-modal": "true",
@@ -2764,31 +3276,31 @@ var ChatBubble = ({
2764
3276
  onTouchMove: handleDrawerTouchMove,
2765
3277
  onTouchEnd: handleDrawerTouchEnd,
2766
3278
  children: [
2767
- /* @__PURE__ */ jsxs7("div", { className: `${THEME_CLASSES.bg.header} ${glassMode ? THEME_CLASSES.bg.headerGradient : THEME_CLASSES.bg.headerLight}`, children: [
2768
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center space-x-3", children: [
2769
- config.avatar && /* @__PURE__ */ jsxs7("div", { className: "relative flex-shrink-0", children: [
2770
- /* @__PURE__ */ jsx11(Avatar, { avatar: config.avatar }),
2771
- /* @__PURE__ */ jsx11("div", { className: "absolute -bottom-1 -right-1 w-3 h-3 bg-green-500 rounded-full border-2 border-white" })
3279
+ /* @__PURE__ */ jsxs8("div", { className: `${THEME_CLASSES.bg.header} ${glassMode ? THEME_CLASSES.bg.headerGradient : THEME_CLASSES.bg.headerLight}`, children: [
3280
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center space-x-3", children: [
3281
+ config.avatar && /* @__PURE__ */ jsxs8("div", { className: "relative flex-shrink-0", children: [
3282
+ /* @__PURE__ */ jsx12(Avatar, { avatar: config.avatar }),
3283
+ /* @__PURE__ */ jsx12("div", { className: "absolute -bottom-1 -right-1 w-3 h-3 bg-green-500 rounded-full border-2 border-white" })
2772
3284
  ] }),
2773
- config.title && /* @__PURE__ */ jsx11("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx11("h3", { className: THEME_CLASSES.text.title, children: config.title }) })
3285
+ config.title && /* @__PURE__ */ jsx12("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx12("h3", { className: THEME_CLASSES.text.title, children: config.title }) })
2774
3286
  ] }),
2775
- /* @__PURE__ */ jsx11("button", { onClick: () => setDrawerOpen(false), className: THEME_CLASSES.button.close, title: "Close drawer", children: /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })
3287
+ /* @__PURE__ */ jsx12("button", { onClick: () => setDrawerOpen(false), className: THEME_CLASSES.button.close, title: "Close drawer", children: /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })
2776
3288
  ] }),
2777
- /* @__PURE__ */ jsxs7("div", { className: "flex-1 overflow-y-auto p-4 space-y-2", children: [
2778
- showWelcome && messages.length === 0 && config.welcome?.enabled && /* @__PURE__ */ jsxs7("div", { className: THEME_CLASSES.welcome.container, children: [
2779
- config.welcome.title && /* @__PURE__ */ jsx11("h4", { className: THEME_CLASSES.welcome.title, style: INLINE_STYLES.welcomeTitle(theme === "dark"), children: config.welcome.title }),
2780
- config.welcome.content && /* @__PURE__ */ jsx11("p", { className: THEME_CLASSES.welcome.content, style: INLINE_STYLES.welcomeContent(theme === "dark"), children: config.welcome.content })
3289
+ /* @__PURE__ */ jsxs8("div", { className: "flex-1 overflow-y-auto p-4 space-y-2", children: [
3290
+ showWelcome && messages.length === 0 && config.welcome?.enabled && /* @__PURE__ */ jsxs8("div", { className: THEME_CLASSES.welcome.container, children: [
3291
+ config.welcome.title && /* @__PURE__ */ jsx12("h4", { className: THEME_CLASSES.welcome.title, style: INLINE_STYLES.welcomeTitle(theme === "dark"), children: config.welcome.title }),
3292
+ config.welcome.content && /* @__PURE__ */ jsx12("p", { className: THEME_CLASSES.welcome.content, style: INLINE_STYLES.welcomeContent(theme === "dark"), children: config.welcome.content })
2781
3293
  ] }),
2782
- messages.map((message) => /* @__PURE__ */ jsxs7("div", { className: `group flex items-center gap-1 mb-2 ${message.type === "user" ? "flex-row-reverse" : "flex-row"}`, children: [
2783
- /* @__PURE__ */ jsx11(
3294
+ messages.map((message) => /* @__PURE__ */ jsxs8("div", { className: `group flex items-center gap-1 mb-2 ${message.type === "user" ? "flex-row-reverse" : "flex-row"}`, children: [
3295
+ /* @__PURE__ */ jsx12(
2784
3296
  "div",
2785
3297
  {
2786
3298
  className: `inline-block px-4 py-2.5 rounded-2xl max-w-[95%] text-sm shadow-sm transition-all ${message.type === "user" ? THEME_CLASSES.message.user : message.type === "ai" ? THEME_CLASSES.message.ai : THEME_CLASSES.message.system}`,
2787
3299
  style: message.type === "user" ? INLINE_STYLES.messageUser() : message.type === "ai" ? INLINE_STYLES.messageAI(theme === "dark") : INLINE_STYLES.messageSystem(theme === "dark"),
2788
- children: /* @__PURE__ */ jsx11(MessageRenderer, { content: message.text, theme })
3300
+ children: /* @__PURE__ */ jsx12(MessageRenderer, { content: message.text, theme })
2789
3301
  }
2790
3302
  ),
2791
- message.type === "ai" && voiceEnabled && /* @__PURE__ */ jsx11(
3303
+ message.type === "ai" && voiceEnabled && /* @__PURE__ */ jsx12(
2792
3304
  TTSButton,
2793
3305
  {
2794
3306
  text: message.text,
@@ -2798,7 +3310,7 @@ var ChatBubble = ({
2798
3310
  size: "small"
2799
3311
  }
2800
3312
  ),
2801
- /* @__PURE__ */ jsx11(
3313
+ /* @__PURE__ */ jsx12(
2802
3314
  "div",
2803
3315
  {
2804
3316
  className: `text-xs opacity-0 group-hover:opacity-70 transition-opacity whitespace-nowrap flex-shrink-0 ${message.type === "user" ? "text-gray-400 dark:text-gray-500 text-left" : "text-gray-600 dark:text-gray-400 text-right"}`,
@@ -2807,78 +3319,92 @@ var ChatBubble = ({
2807
3319
  }
2808
3320
  )
2809
3321
  ] }, message.id)),
2810
- /* @__PURE__ */ jsx11("div", { ref: messagesEndRef })
3322
+ /* @__PURE__ */ jsx12("div", { ref: messagesEndRef })
2811
3323
  ] }),
2812
- /* @__PURE__ */ jsx11(
2813
- InputField,
2814
- {
2815
- inputValue,
2816
- onInputChange: setInputValue,
2817
- onSubmit: handleSend,
2818
- placeholder: inputHints[currentHintIndex],
2819
- glassClasses: "",
2820
- theme,
2821
- inputRef,
2822
- sendButtonLabel: config.sendButtonLabel,
2823
- voiceEnabled,
2824
- isListening,
2825
- onMicClick: handleMicClick,
2826
- modKey: isMac ? "Cmd" : "Ctrl"
2827
- }
2828
- )
3324
+ /* @__PURE__ */ jsxs8("div", { style: { position: "relative" }, children: [
3325
+ slashCommand.isOpen && /* @__PURE__ */ jsx12(
3326
+ SlashCommandPopup,
3327
+ {
3328
+ tools: slashCommand.filteredTools,
3329
+ selectedIndex: slashCommand.selectedIndex,
3330
+ onSelect: slashCommand.selectTool,
3331
+ onClose: () => setInputValue("")
3332
+ }
3333
+ ),
3334
+ /* @__PURE__ */ jsx12(
3335
+ InputField,
3336
+ {
3337
+ inputValue,
3338
+ onInputChange: setInputValue,
3339
+ onSubmit: handleSend,
3340
+ placeholder: inputHints[currentHintIndex],
3341
+ glassClasses: "",
3342
+ theme,
3343
+ inputRef,
3344
+ sendButtonLabel: config.sendButtonLabel,
3345
+ voiceEnabled,
3346
+ isListening,
3347
+ onMicClick: handleMicClick,
3348
+ modKey: isMac ? "Cmd" : "Ctrl",
3349
+ onKeyDown: slashCommand.onKeyDown
3350
+ }
3351
+ )
3352
+ ] })
2829
3353
  ]
2830
3354
  }
2831
3355
  ),
2832
- !drawerOpen && /* @__PURE__ */ jsx11(
3356
+ !drawerOpen && /* @__PURE__ */ jsx12(
2833
3357
  "div",
2834
3358
  {
2835
- className: `fixed ${drawerSide === "right" ? "right-0" : "left-0"} bottom-20 opacity-30 hover:opacity-90 transition-opacity duration-300 z-[99999] cursor-pointer`,
3359
+ className: `fixed ${drawerSide === "right" ? "right-0" : "left-0"} bottom-20 opacity-70 hover:opacity-100 transition-opacity duration-300 z-[999999] cursor-pointer`,
2836
3360
  style: { zIndex: 999999 },
2837
3361
  onClick: () => setDrawerOpen(true),
2838
- children: /* @__PURE__ */ jsx11("div", { className: `${glassMode ? "backdrop-blur-md bg-white/50 dark:bg-gray-800/50" : "bg-white dark:bg-gray-800"} text-gray-700 dark:text-gray-200 px-3 py-3 ${drawerSide === "right" ? "rounded-l-xl" : "rounded-r-xl"} shadow-md hover:shadow-lg flex items-center justify-center transition-all`, children: voiceEnabled ? /* @__PURE__ */ jsx11("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z" }) }) : /* @__PURE__ */ jsx11("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" }) }) })
3362
+ children: /* @__PURE__ */ jsx12("div", { className: `${glassMode ? "backdrop-blur-md bg-white/50 dark:bg-gray-800/50" : "bg-white dark:bg-gray-800"} text-gray-700 dark:text-gray-200 px-3 py-3 ${drawerSide === "right" ? "rounded-l-xl" : "rounded-r-xl"} shadow-md hover:shadow-lg flex items-center justify-center transition-all`, children: voiceEnabled ? /* @__PURE__ */ jsx12("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z" }) }) : /* @__PURE__ */ jsx12("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" }) }) })
2839
3363
  }
2840
3364
  )
2841
3365
  ] });
2842
3366
  }
2843
- if (variant === "floating") {
3367
+ if (currentVariant === "floating") {
2844
3368
  const recentMessage = messages[messages.length - 1];
2845
- return /* @__PURE__ */ jsx11(
3369
+ return /* @__PURE__ */ jsx12(
2846
3370
  "div",
2847
3371
  {
2848
- className: `fixed z-[99999] ${isDragging ? "cursor-grabbing" : "cursor-grab"}`,
3372
+ className: `fixed z-[999999] ${isDragging ? "cursor-grabbing" : "cursor-grab"}`,
2849
3373
  style: {
3374
+ top: 0,
3375
+ left: 0,
2850
3376
  transform: `translate(${panelPosition.x}px, ${panelPosition.y}px)`,
2851
3377
  zIndex: 999999,
2852
- // Force extremely high z-index
3378
+ // Super high z-index for floating variant
2853
3379
  ...!isDragging && { transition: "transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)" }
2854
3380
  },
2855
3381
  onMouseDown: handlePanelMouseDown,
2856
- children: /* @__PURE__ */ jsxs7("div", { className: `${glassClasses} rounded-2xl shadow-2xl p-3 max-w-xs ${!glassMode && "border-gray-200 border"}`, children: [
2857
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between mb-2", children: [
2858
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center space-x-2", children: [
2859
- /* @__PURE__ */ jsx11(Avatar, { avatar: config.avatar, size: "small" }),
2860
- config.title && /* @__PURE__ */ jsx11("span", { className: THEME_CLASSES.text.floatingTitle, children: config.title })
3382
+ children: /* @__PURE__ */ jsxs8("div", { className: `${glassClasses} rounded-2xl shadow-2xl p-3 max-w-xs ${!glassMode && "border-gray-200 border"}`, children: [
3383
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between mb-2", children: [
3384
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center space-x-2", children: [
3385
+ /* @__PURE__ */ jsx12(Avatar, { avatar: config.avatar, size: "small" }),
3386
+ config.title && /* @__PURE__ */ jsx12("span", { className: THEME_CLASSES.text.floatingTitle, children: config.title })
2861
3387
  ] }),
2862
- onClearChat && /* @__PURE__ */ jsx11(
3388
+ onClearChat && /* @__PURE__ */ jsx12(
2863
3389
  "button",
2864
3390
  {
2865
3391
  onClick: onClearChat,
2866
3392
  className: THEME_CLASSES.button.floatingClear,
2867
3393
  title: "Clear chat",
2868
3394
  "data-testid": ChatNames.clearButton,
2869
- children: /* @__PURE__ */ jsx11("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
3395
+ children: /* @__PURE__ */ jsx12("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
2870
3396
  }
2871
3397
  )
2872
3398
  ] }),
2873
- recentMessage && /* @__PURE__ */ jsxs7("div", { className: `mb-2 group flex items-center gap-2 ${recentMessage.type === "user" ? "flex-row-reverse" : "flex-row"}`, children: [
2874
- /* @__PURE__ */ jsx11(
3399
+ recentMessage && /* @__PURE__ */ jsxs8("div", { className: `mb-2 group flex items-center gap-2 ${recentMessage.type === "user" ? "flex-row-reverse" : "flex-row"}`, children: [
3400
+ /* @__PURE__ */ jsx12(
2875
3401
  "div",
2876
3402
  {
2877
3403
  className: `text-xs px-3 py-2 rounded-xl transition-all ${recentMessage.type === "user" ? "bg-gradient-to-br from-blue-500 to-blue-600 text-white shadow-lg" : recentMessage.type === "ai" ? "bg-gradient-to-br from-gray-100 to-gray-200 dark:from-gray-700 dark:to-gray-800 text-gray-900 dark:text-white shadow-md" : "bg-gradient-to-br from-yellow-100 to-yellow-200 text-yellow-900 shadow-md"}`,
2878
3404
  children: recentMessage.text.length > 60 ? `${recentMessage.text.slice(0, 60)}...` : recentMessage.text
2879
3405
  }
2880
3406
  ),
2881
- /* @__PURE__ */ jsx11(
3407
+ /* @__PURE__ */ jsx12(
2882
3408
  "div",
2883
3409
  {
2884
3410
  className: `text-xs opacity-0 group-hover:opacity-70 transition-opacity whitespace-nowrap flex-shrink-0 ${recentMessage.type === "user" ? "text-gray-400 dark:text-gray-500 text-left" : "text-gray-600 dark:text-gray-400 text-right"}`,
@@ -2887,32 +3413,44 @@ var ChatBubble = ({
2887
3413
  }
2888
3414
  )
2889
3415
  ] }),
2890
- /* @__PURE__ */ jsx11(
2891
- InputField,
2892
- {
2893
- compact: true,
2894
- inputValue,
2895
- onInputChange: setInputValue,
2896
- onSubmit: handleSend,
2897
- placeholder: inputHints[currentHintIndex],
2898
- glassClasses: "",
2899
- theme,
2900
- sendButtonLabel: config.sendButtonLabel,
2901
- modKey: isMac ? "Cmd" : "Ctrl"
2902
- }
2903
- )
3416
+ /* @__PURE__ */ jsxs8("div", { style: { position: "relative" }, children: [
3417
+ slashCommand.isOpen && /* @__PURE__ */ jsx12(
3418
+ SlashCommandPopup,
3419
+ {
3420
+ tools: slashCommand.filteredTools,
3421
+ selectedIndex: slashCommand.selectedIndex,
3422
+ onSelect: slashCommand.selectTool,
3423
+ onClose: () => setInputValue("")
3424
+ }
3425
+ ),
3426
+ /* @__PURE__ */ jsx12(
3427
+ InputField,
3428
+ {
3429
+ compact: true,
3430
+ inputValue,
3431
+ onInputChange: setInputValue,
3432
+ onSubmit: handleSend,
3433
+ placeholder: inputHints[currentHintIndex],
3434
+ glassClasses: "",
3435
+ theme,
3436
+ sendButtonLabel: config.sendButtonLabel,
3437
+ modKey: isMac ? "Cmd" : "Ctrl",
3438
+ onKeyDown: slashCommand.onKeyDown
3439
+ }
3440
+ )
3441
+ ] })
2904
3442
  ] })
2905
3443
  }
2906
3444
  );
2907
3445
  }
2908
- return /* @__PURE__ */ jsx11(Fragment3, { children: /* @__PURE__ */ jsxs7(
3446
+ return /* @__PURE__ */ jsx12(Fragment3, { children: /* @__PURE__ */ jsxs8(
2909
3447
  "div",
2910
3448
  {
2911
3449
  className: "fixed",
2912
3450
  style: {
2913
3451
  ...dockClasses.container,
2914
- zIndex: 2147483647,
2915
- // Maximum z-index value
3452
+ zIndex: 999999,
3453
+ // Super high z-index for chat widget
2916
3454
  position: "fixed",
2917
3455
  ...isExpanded ? {
2918
3456
  width: panelWidth,
@@ -2923,16 +3461,16 @@ var ChatBubble = ({
2923
3461
  }
2924
3462
  },
2925
3463
  children: [
2926
- isExpanded && isMinimized && /* @__PURE__ */ jsxs7(
3464
+ isExpanded && isMinimized && /* @__PURE__ */ jsxs8(
2927
3465
  "div",
2928
3466
  {
2929
3467
  ref: panelRef,
2930
- className: `${isDocked ? "absolute" : "fixed z-[99999]"} ${glassGradient} rounded-3xl shadow-2xl border border-white/20 dark:border-white/10 ${!isDragging && "backdrop-blur-xl"} flex flex-col overflow-hidden ${!isDragging && "transition-all duration-300"}`,
3468
+ className: `${isDocked ? "absolute" : "fixed z-[999999]"} ${glassGradient} rounded-3xl shadow-2xl border border-white/20 dark:border-white/10 ${!isDragging && "backdrop-blur-xl"} flex flex-col overflow-hidden ${!isDragging && "transition-all duration-300"}`,
2931
3469
  style: {
2932
3470
  width: panelWidth,
2933
3471
  maxWidth: "400px",
2934
3472
  zIndex: 999999,
2935
- // Force extremely high z-index
3473
+ // Super high z-index for minimized panel
2936
3474
  ...isDocked ? {
2937
3475
  ...dockClasses.panel,
2938
3476
  // Only clear transform if dock position doesn't use transform
@@ -2941,7 +3479,7 @@ var ChatBubble = ({
2941
3479
  ...isDragging && { cursor: "grabbing" }
2942
3480
  },
2943
3481
  children: [
2944
- /* @__PURE__ */ jsxs7(
3482
+ /* @__PURE__ */ jsxs8(
2945
3483
  "div",
2946
3484
  {
2947
3485
  "data-drag-handle": true,
@@ -2957,15 +3495,15 @@ var ChatBubble = ({
2957
3495
  }
2958
3496
  },
2959
3497
  children: [
2960
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center space-x-3", children: [
2961
- config.avatar && /* @__PURE__ */ jsxs7("div", { className: "relative flex-shrink-0", children: [
2962
- /* @__PURE__ */ jsx11(Avatar, { avatar: config.avatar }),
2963
- /* @__PURE__ */ jsx11("div", { className: "absolute -bottom-1 -right-1 w-3 h-3 bg-green-500 rounded-full border-2 border-white" })
3498
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center space-x-3", children: [
3499
+ config.avatar && /* @__PURE__ */ jsxs8("div", { className: "relative flex-shrink-0", children: [
3500
+ /* @__PURE__ */ jsx12(Avatar, { avatar: config.avatar }),
3501
+ /* @__PURE__ */ jsx12("div", { className: "absolute -bottom-1 -right-1 w-3 h-3 bg-green-500 rounded-full border-2 border-white" })
2964
3502
  ] }),
2965
- config.title && /* @__PURE__ */ jsx11("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx11("h3", { className: THEME_CLASSES.text.title, children: config.title }) })
3503
+ config.title && /* @__PURE__ */ jsx12("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx12("h3", { className: THEME_CLASSES.text.title, children: config.title }) })
2966
3504
  ] }),
2967
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center space-x-1 flex-shrink-0", children: [
2968
- /* @__PURE__ */ jsx11(
3505
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center space-x-1 flex-shrink-0", children: [
3506
+ /* @__PURE__ */ jsx12(
2969
3507
  "button",
2970
3508
  {
2971
3509
  onClick: (e) => {
@@ -2974,10 +3512,10 @@ var ChatBubble = ({
2974
3512
  },
2975
3513
  className: THEME_CLASSES.button.minimize,
2976
3514
  title: "Minimize chat",
2977
- children: /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })
3515
+ children: /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })
2978
3516
  }
2979
3517
  ),
2980
- /* @__PURE__ */ jsx11(
3518
+ /* @__PURE__ */ jsx12(
2981
3519
  "button",
2982
3520
  {
2983
3521
  onClick: (e) => {
@@ -2986,46 +3524,58 @@ var ChatBubble = ({
2986
3524
  },
2987
3525
  className: THEME_CLASSES.button.close,
2988
3526
  title: "Close chat",
2989
- children: /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
3527
+ children: /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
2990
3528
  }
2991
3529
  )
2992
3530
  ] })
2993
3531
  ]
2994
3532
  }
2995
3533
  ),
2996
- /* @__PURE__ */ jsxs7("div", { className: "p-4", children: [
3534
+ /* @__PURE__ */ jsxs8("div", { className: "p-4", children: [
2997
3535
  (() => {
2998
3536
  const lastAiMessage = [...messages].reverse().find((m) => m.type === "ai");
2999
- return lastAiMessage ? /* @__PURE__ */ jsx11("div", { className: "mb-3", children: /* @__PURE__ */ jsx11("div", { className: `text-xs px-3 py-2 rounded-xl ${THEME_CLASSES.message.ai}`, style: INLINE_STYLES.messageAI(theme === "dark"), children: lastAiMessage.text.length > 100 ? `${lastAiMessage.text.slice(0, 100)}...` : lastAiMessage.text }) }) : /* @__PURE__ */ jsx11("div", { className: "mb-3", children: /* @__PURE__ */ jsx11("div", { className: THEME_CLASSES.text.minimizedMessage, style: INLINE_STYLES.minimizedMessage(theme === "dark"), children: "No AI responses yet" }) });
3537
+ return lastAiMessage ? /* @__PURE__ */ jsx12("div", { className: "mb-3", children: /* @__PURE__ */ jsx12("div", { className: `text-xs px-3 py-2 rounded-xl ${THEME_CLASSES.message.ai}`, style: INLINE_STYLES.messageAI(theme === "dark"), children: lastAiMessage.text.length > 100 ? `${lastAiMessage.text.slice(0, 100)}...` : lastAiMessage.text }) }) : /* @__PURE__ */ jsx12("div", { className: "mb-3", children: /* @__PURE__ */ jsx12("div", { className: THEME_CLASSES.text.minimizedMessage, style: INLINE_STYLES.minimizedMessage(theme === "dark"), children: "No AI responses yet" }) });
3000
3538
  })(),
3001
- /* @__PURE__ */ jsx11(
3002
- InputField,
3003
- {
3004
- compact: true,
3005
- inputValue,
3006
- onInputChange: setInputValue,
3007
- onSubmit: handleSend,
3008
- placeholder: inputHints[currentHintIndex],
3009
- glassClasses: "",
3010
- theme,
3011
- sendButtonLabel: config.sendButtonLabel,
3012
- modKey: isMac ? "Cmd" : "Ctrl"
3013
- }
3014
- )
3539
+ /* @__PURE__ */ jsxs8("div", { style: { position: "relative" }, children: [
3540
+ slashCommand.isOpen && /* @__PURE__ */ jsx12(
3541
+ SlashCommandPopup,
3542
+ {
3543
+ tools: slashCommand.filteredTools,
3544
+ selectedIndex: slashCommand.selectedIndex,
3545
+ onSelect: slashCommand.selectTool,
3546
+ onClose: () => setInputValue("")
3547
+ }
3548
+ ),
3549
+ /* @__PURE__ */ jsx12(
3550
+ InputField,
3551
+ {
3552
+ compact: true,
3553
+ inputValue,
3554
+ onInputChange: setInputValue,
3555
+ onSubmit: handleSend,
3556
+ placeholder: inputHints[currentHintIndex],
3557
+ glassClasses: "",
3558
+ theme,
3559
+ sendButtonLabel: config.sendButtonLabel,
3560
+ modKey: isMac ? "Cmd" : "Ctrl",
3561
+ onKeyDown: slashCommand.onKeyDown
3562
+ }
3563
+ )
3564
+ ] })
3015
3565
  ] })
3016
3566
  ]
3017
3567
  }
3018
3568
  ),
3019
- isExpanded && !isMinimized && /* @__PURE__ */ jsxs7(
3569
+ isExpanded && !isMinimized && /* @__PURE__ */ jsxs8(
3020
3570
  "div",
3021
3571
  {
3022
3572
  ref: panelRef,
3023
- className: `${isDocked ? "absolute" : "fixed z-[99999]"} ${glassGradient} rounded-3xl shadow-2xl border border-white/20 dark:border-white/10 ${!isDragging && "backdrop-blur-xl"} flex flex-col overflow-hidden ${!isDragging && "transition-all duration-300"}`,
3573
+ className: `${isDocked ? "absolute" : "fixed z-[999999]"} ${glassGradient} rounded-3xl shadow-2xl border border-white/20 dark:border-white/10 ${!isDragging && "backdrop-blur-xl"} flex flex-col overflow-hidden ${!isDragging && "transition-all duration-300"}`,
3024
3574
  style: {
3025
3575
  width: panelWidth,
3026
3576
  height: dynamicHeight,
3027
3577
  zIndex: 999999,
3028
- // Force extremely high z-index
3578
+ // Super high z-index for expanded panel
3029
3579
  ...isDocked ? {
3030
3580
  ...dockClasses.panel,
3031
3581
  // Only clear transform if dock position doesn't use transform
@@ -3034,22 +3584,22 @@ var ChatBubble = ({
3034
3584
  ...isDragging && { cursor: "grabbing" }
3035
3585
  },
3036
3586
  children: [
3037
- /* @__PURE__ */ jsxs7(
3587
+ /* @__PURE__ */ jsxs8(
3038
3588
  "div",
3039
3589
  {
3040
3590
  "data-drag-handle": true,
3041
3591
  className: `${THEME_CLASSES.bg.header} ${glassMode ? THEME_CLASSES.bg.headerGradient : THEME_CLASSES.bg.headerLight} cursor-move`,
3042
3592
  onMouseDown: handlePanelMouseDown,
3043
3593
  children: [
3044
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center space-x-3", children: [
3045
- config.avatar && /* @__PURE__ */ jsxs7("div", { className: "relative flex-shrink-0", children: [
3046
- /* @__PURE__ */ jsx11(Avatar, { avatar: config.avatar }),
3047
- /* @__PURE__ */ jsx11("div", { className: "absolute -bottom-1 -right-1 w-3 h-3 bg-green-500 rounded-full border-2 border-white" })
3594
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center space-x-3", children: [
3595
+ config.avatar && /* @__PURE__ */ jsxs8("div", { className: "relative flex-shrink-0", children: [
3596
+ /* @__PURE__ */ jsx12(Avatar, { avatar: config.avatar }),
3597
+ /* @__PURE__ */ jsx12("div", { className: "absolute -bottom-1 -right-1 w-3 h-3 bg-green-500 rounded-full border-2 border-white" })
3048
3598
  ] }),
3049
- config.title && /* @__PURE__ */ jsx11("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx11("h3", { className: THEME_CLASSES.text.title, children: config.title }) })
3599
+ config.title && /* @__PURE__ */ jsx12("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx12("h3", { className: THEME_CLASSES.text.title, children: config.title }) })
3050
3600
  ] }),
3051
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center space-x-1 flex-shrink-0 relative", "data-more-menu": true, children: [
3052
- /* @__PURE__ */ jsx11(
3601
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center space-x-1 flex-shrink-0 relative", "data-more-menu": true, children: [
3602
+ /* @__PURE__ */ jsx12(
3053
3603
  "a",
3054
3604
  {
3055
3605
  href: "https://www.interface.supernal.ai",
@@ -3057,30 +3607,30 @@ var ChatBubble = ({
3057
3607
  rel: "noopener noreferrer",
3058
3608
  className: "p-2 text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 transition-colors rounded-lg hover:bg-white/30",
3059
3609
  title: "Visit Supernal Interface Documentation",
3060
- children: /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" }) })
3610
+ children: /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" }) })
3061
3611
  }
3062
3612
  ),
3063
- /* @__PURE__ */ jsx11(
3613
+ /* @__PURE__ */ jsx12(
3064
3614
  "button",
3065
3615
  {
3066
3616
  onClick: () => setShowMoreMenu(!showMoreMenu),
3067
3617
  className: THEME_CLASSES.button.more,
3068
3618
  title: "More options",
3069
- children: /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" }) })
3619
+ children: /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" }) })
3070
3620
  }
3071
3621
  ),
3072
- showMoreMenu && /* @__PURE__ */ jsxs7("div", { className: "absolute right-0 top-10 bg-white dark:bg-gray-800 rounded-lg shadow-xl border border-gray-200 dark:border-gray-600 p-2 min-w-[220px] z-50", "data-more-menu": true, children: [
3073
- /* @__PURE__ */ jsx11("div", { className: "px-3 py-2 border-b border-gray-200 dark:border-gray-600 mb-2", children: /* @__PURE__ */ jsxs7("div", { className: "grid grid-cols-4 gap-1", children: [
3074
- /* @__PURE__ */ jsx11(
3622
+ showMoreMenu && /* @__PURE__ */ jsxs8("div", { className: "absolute right-0 top-10 bg-white dark:bg-gray-800 rounded-lg shadow-xl border border-gray-200 dark:border-gray-600 p-2 min-w-[220px] z-50", "data-more-menu": true, children: [
3623
+ /* @__PURE__ */ jsx12("div", { className: "px-3 py-2 border-b border-gray-200 dark:border-gray-600 mb-2", children: /* @__PURE__ */ jsxs8("div", { className: "grid grid-cols-4 gap-1", children: [
3624
+ /* @__PURE__ */ jsx12(
3075
3625
  "button",
3076
3626
  {
3077
3627
  onClick: () => setLocalGlassMode(false),
3078
3628
  className: `flex items-center justify-center p-2 rounded transition-all ${!localGlassMode ? "bg-blue-600 text-white shadow-sm" : "bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"}`,
3079
3629
  title: "Glass Off",
3080
- children: /* @__PURE__ */ jsx11("svg", { className: "w-5 h-5", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("rect", { x: "8", y: "8", width: "8", height: "8", rx: "1" }) })
3630
+ children: /* @__PURE__ */ jsx12("svg", { className: "w-5 h-5", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("rect", { x: "8", y: "8", width: "8", height: "8", rx: "1" }) })
3081
3631
  }
3082
3632
  ),
3083
- /* @__PURE__ */ jsx11(
3633
+ /* @__PURE__ */ jsx12(
3084
3634
  "button",
3085
3635
  {
3086
3636
  onClick: () => {
@@ -3089,10 +3639,10 @@ var ChatBubble = ({
3089
3639
  },
3090
3640
  className: `flex items-center justify-center p-2 rounded transition-all ${localGlassMode && glassOpacity === "low" ? "bg-blue-600 text-white shadow-sm" : "bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"}`,
3091
3641
  title: "Glass Low",
3092
- children: /* @__PURE__ */ jsx11("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("rect", { x: "9", y: "9", width: "6", height: "6", rx: "1", strokeWidth: "2" }) })
3642
+ children: /* @__PURE__ */ jsx12("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("rect", { x: "9", y: "9", width: "6", height: "6", rx: "1", strokeWidth: "2" }) })
3093
3643
  }
3094
3644
  ),
3095
- /* @__PURE__ */ jsx11(
3645
+ /* @__PURE__ */ jsx12(
3096
3646
  "button",
3097
3647
  {
3098
3648
  onClick: () => {
@@ -3101,13 +3651,13 @@ var ChatBubble = ({
3101
3651
  },
3102
3652
  className: `flex items-center justify-center p-2 rounded transition-all ${localGlassMode && glassOpacity === "medium" ? "bg-blue-600 text-white shadow-sm" : "bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"}`,
3103
3653
  title: "Glass Medium",
3104
- children: /* @__PURE__ */ jsxs7("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [
3105
- /* @__PURE__ */ jsx11("rect", { x: "8", y: "8", width: "8", height: "8", rx: "1", strokeWidth: "2" }),
3106
- /* @__PURE__ */ jsx11("rect", { x: "10", y: "10", width: "4", height: "4", rx: "0.5", strokeWidth: "1.5" })
3654
+ children: /* @__PURE__ */ jsxs8("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [
3655
+ /* @__PURE__ */ jsx12("rect", { x: "8", y: "8", width: "8", height: "8", rx: "1", strokeWidth: "2" }),
3656
+ /* @__PURE__ */ jsx12("rect", { x: "10", y: "10", width: "4", height: "4", rx: "0.5", strokeWidth: "1.5" })
3107
3657
  ] })
3108
3658
  }
3109
3659
  ),
3110
- /* @__PURE__ */ jsx11(
3660
+ /* @__PURE__ */ jsx12(
3111
3661
  "button",
3112
3662
  {
3113
3663
  onClick: () => {
@@ -3116,15 +3666,15 @@ var ChatBubble = ({
3116
3666
  },
3117
3667
  className: `flex items-center justify-center p-2 rounded transition-all ${localGlassMode && glassOpacity === "high" ? "bg-blue-600 text-white shadow-sm" : "bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600"}`,
3118
3668
  title: "Glass High",
3119
- children: /* @__PURE__ */ jsxs7("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [
3120
- /* @__PURE__ */ jsx11("rect", { x: "7", y: "7", width: "10", height: "10", rx: "1", strokeWidth: "2" }),
3121
- /* @__PURE__ */ jsx11("rect", { x: "9", y: "9", width: "6", height: "6", rx: "0.5", strokeWidth: "1.5" }),
3122
- /* @__PURE__ */ jsx11("rect", { x: "11", y: "11", width: "2", height: "2", rx: "0.5", strokeWidth: "1" })
3669
+ children: /* @__PURE__ */ jsxs8("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [
3670
+ /* @__PURE__ */ jsx12("rect", { x: "7", y: "7", width: "10", height: "10", rx: "1", strokeWidth: "2" }),
3671
+ /* @__PURE__ */ jsx12("rect", { x: "9", y: "9", width: "6", height: "6", rx: "0.5", strokeWidth: "1.5" }),
3672
+ /* @__PURE__ */ jsx12("rect", { x: "11", y: "11", width: "2", height: "2", rx: "0.5", strokeWidth: "1" })
3123
3673
  ] })
3124
3674
  }
3125
3675
  )
3126
3676
  ] }) }),
3127
- /* @__PURE__ */ jsxs7(
3677
+ /* @__PURE__ */ jsxs8(
3128
3678
  "button",
3129
3679
  {
3130
3680
  onClick: () => {
@@ -3136,15 +3686,15 @@ var ChatBubble = ({
3136
3686
  },
3137
3687
  className: "w-full flex items-center space-x-2 px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
3138
3688
  children: [
3139
- /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" }) }),
3140
- /* @__PURE__ */ jsxs7("span", { children: [
3689
+ /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" }) }),
3690
+ /* @__PURE__ */ jsxs8("span", { children: [
3141
3691
  theme === "light" ? "Dark" : "Light",
3142
3692
  " Mode"
3143
3693
  ] })
3144
3694
  ]
3145
3695
  }
3146
3696
  ),
3147
- /* @__PURE__ */ jsxs7(
3697
+ /* @__PURE__ */ jsxs8(
3148
3698
  "button",
3149
3699
  {
3150
3700
  onClick: () => {
@@ -3155,15 +3705,15 @@ var ChatBubble = ({
3155
3705
  },
3156
3706
  className: "w-full flex items-center space-x-2 px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
3157
3707
  children: [
3158
- /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z" }) }),
3159
- /* @__PURE__ */ jsxs7("span", { children: [
3708
+ /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z" }) }),
3709
+ /* @__PURE__ */ jsxs8("span", { children: [
3160
3710
  voiceEnabled ? "Disable" : "Enable",
3161
3711
  " Voice"
3162
3712
  ] })
3163
3713
  ]
3164
3714
  }
3165
3715
  ),
3166
- /* @__PURE__ */ jsxs7(
3716
+ /* @__PURE__ */ jsxs8(
3167
3717
  "button",
3168
3718
  {
3169
3719
  onClick: () => {
@@ -3172,12 +3722,12 @@ var ChatBubble = ({
3172
3722
  },
3173
3723
  className: "w-full flex items-center space-x-2 px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
3174
3724
  children: [
3175
- /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" }) }),
3176
- /* @__PURE__ */ jsx11("span", { children: "Reset position" })
3725
+ /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" }) }),
3726
+ /* @__PURE__ */ jsx12("span", { children: "Reset position" })
3177
3727
  ]
3178
3728
  }
3179
3729
  ),
3180
- /* @__PURE__ */ jsxs7(
3730
+ /* @__PURE__ */ jsxs8(
3181
3731
  "button",
3182
3732
  {
3183
3733
  onClick: () => {
@@ -3193,12 +3743,12 @@ var ChatBubble = ({
3193
3743
  },
3194
3744
  className: "w-full flex items-center space-x-2 px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
3195
3745
  children: [
3196
- /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
3197
- /* @__PURE__ */ jsx11("span", { children: "How to use" })
3746
+ /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
3747
+ /* @__PURE__ */ jsx12("span", { children: "How to use" })
3198
3748
  ]
3199
3749
  }
3200
3750
  ),
3201
- onClearChat && /* @__PURE__ */ jsxs7(
3751
+ onClearChat && /* @__PURE__ */ jsxs8(
3202
3752
  "button",
3203
3753
  {
3204
3754
  onClick: () => {
@@ -3207,41 +3757,41 @@ var ChatBubble = ({
3207
3757
  },
3208
3758
  className: "w-full flex items-center space-x-2 px-3 py-2 text-sm text-red-600 dark:text-red-400 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
3209
3759
  children: [
3210
- /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }),
3211
- /* @__PURE__ */ jsx11("span", { children: "Clear chat" })
3760
+ /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }),
3761
+ /* @__PURE__ */ jsx12("span", { children: "Clear chat" })
3212
3762
  ]
3213
3763
  }
3214
3764
  )
3215
3765
  ] }),
3216
- /* @__PURE__ */ jsx11(
3766
+ /* @__PURE__ */ jsx12(
3217
3767
  "button",
3218
3768
  {
3219
3769
  onClick: () => setIsMinimized(true),
3220
3770
  className: THEME_CLASSES.button.minimize,
3221
3771
  title: "Minimize",
3222
- children: /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M20 12H4" }) })
3772
+ children: /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M20 12H4" }) })
3223
3773
  }
3224
3774
  ),
3225
- /* @__PURE__ */ jsx11(
3775
+ /* @__PURE__ */ jsx12(
3226
3776
  "button",
3227
3777
  {
3228
3778
  onClick: handleToggle,
3229
3779
  className: THEME_CLASSES.button.close,
3230
3780
  title: "Close",
3231
- children: /* @__PURE__ */ jsx11("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
3781
+ children: /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
3232
3782
  }
3233
3783
  )
3234
3784
  ] })
3235
3785
  ]
3236
3786
  }
3237
3787
  ),
3238
- /* @__PURE__ */ jsxs7("div", { className: "flex-1 overflow-y-auto p-4 space-y-2", children: [
3239
- showWelcome && messages.length === 0 && config.welcome?.enabled && /* @__PURE__ */ jsxs7("div", { className: THEME_CLASSES.welcome.container, children: [
3240
- config.welcome.title && /* @__PURE__ */ jsx11("h4", { className: THEME_CLASSES.welcome.title, style: INLINE_STYLES.welcomeTitle(theme === "dark"), children: config.welcome.title }),
3241
- config.welcome.content && /* @__PURE__ */ jsx11("p", { className: THEME_CLASSES.welcome.content, style: INLINE_STYLES.welcomeContent(theme === "dark"), children: config.welcome.content }),
3242
- config.welcome.suggestedCommands && config.welcome.suggestedCommands.length > 0 && /* @__PURE__ */ jsxs7("div", { className: THEME_CLASSES.welcome.commandsContainer, children: [
3243
- /* @__PURE__ */ jsx11("p", { className: THEME_CLASSES.welcome.commandsHeader, children: "Try these commands:" }),
3244
- /* @__PURE__ */ jsx11("div", { className: "space-y-1", children: config.welcome.suggestedCommands.map((cmd, idx) => /* @__PURE__ */ jsxs7(
3788
+ /* @__PURE__ */ jsxs8("div", { className: "flex-1 overflow-y-auto p-4 space-y-2", children: [
3789
+ showWelcome && messages.length === 0 && config.welcome?.enabled && /* @__PURE__ */ jsxs8("div", { className: THEME_CLASSES.welcome.container, children: [
3790
+ config.welcome.title && /* @__PURE__ */ jsx12("h4", { className: THEME_CLASSES.welcome.title, style: INLINE_STYLES.welcomeTitle(theme === "dark"), children: config.welcome.title }),
3791
+ config.welcome.content && /* @__PURE__ */ jsx12("p", { className: THEME_CLASSES.welcome.content, style: INLINE_STYLES.welcomeContent(theme === "dark"), children: config.welcome.content }),
3792
+ config.welcome.suggestedCommands && config.welcome.suggestedCommands.length > 0 && /* @__PURE__ */ jsxs8("div", { className: THEME_CLASSES.welcome.commandsContainer, children: [
3793
+ /* @__PURE__ */ jsx12("p", { className: THEME_CLASSES.welcome.commandsHeader, children: "Try these commands:" }),
3794
+ /* @__PURE__ */ jsx12("div", { className: "space-y-1", children: config.welcome.suggestedCommands.map((cmd, idx) => /* @__PURE__ */ jsxs8(
3245
3795
  "button",
3246
3796
  {
3247
3797
  onClick: () => {
@@ -3251,29 +3801,29 @@ var ChatBubble = ({
3251
3801
  },
3252
3802
  className: THEME_CLASSES.welcome.commandButton,
3253
3803
  children: [
3254
- /* @__PURE__ */ jsxs7("div", { className: THEME_CLASSES.welcome.commandText, style: INLINE_STYLES.commandText(theme === "dark"), children: [
3804
+ /* @__PURE__ */ jsxs8("div", { className: THEME_CLASSES.welcome.commandText, style: INLINE_STYLES.commandText(theme === "dark"), children: [
3255
3805
  '"',
3256
3806
  cmd.text,
3257
3807
  '"'
3258
3808
  ] }),
3259
- cmd.desc && /* @__PURE__ */ jsx11("div", { className: THEME_CLASSES.welcome.commandDesc, style: INLINE_STYLES.commandDesc(theme === "dark"), children: cmd.desc })
3809
+ cmd.desc && /* @__PURE__ */ jsx12("div", { className: THEME_CLASSES.welcome.commandDesc, style: INLINE_STYLES.commandDesc(theme === "dark"), children: cmd.desc })
3260
3810
  ]
3261
3811
  },
3262
3812
  idx
3263
3813
  )) })
3264
3814
  ] })
3265
3815
  ] }),
3266
- messages.map((message) => /* @__PURE__ */ jsxs7("div", { className: `group flex items-center gap-2 mb-2 ${message.type === "user" ? "flex-row-reverse" : "flex-row"}`, children: [
3267
- /* @__PURE__ */ jsx11(
3816
+ messages.map((message) => /* @__PURE__ */ jsxs8("div", { className: `group flex items-center gap-2 mb-2 ${message.type === "user" ? "flex-row-reverse" : "flex-row"}`, children: [
3817
+ /* @__PURE__ */ jsx12(
3268
3818
  "div",
3269
3819
  {
3270
3820
  className: `inline-block px-4 py-2.5 rounded-2xl max-w-[80%] text-sm shadow-sm transition-all ${message.type === "user" ? THEME_CLASSES.message.user : message.type === "ai" ? THEME_CLASSES.message.ai : THEME_CLASSES.message.system}`,
3271
3821
  style: message.type === "user" ? INLINE_STYLES.messageUser() : message.type === "ai" ? INLINE_STYLES.messageAI(theme === "dark") : INLINE_STYLES.messageSystem(theme === "dark"),
3272
3822
  "data-testid": `chat-message-${message.type}`,
3273
- children: /* @__PURE__ */ jsx11(MessageRenderer, { content: message.text, theme })
3823
+ children: /* @__PURE__ */ jsx12(MessageRenderer, { content: message.text, theme })
3274
3824
  }
3275
3825
  ),
3276
- message.type === "ai" && voiceEnabled && /* @__PURE__ */ jsx11(
3826
+ message.type === "ai" && voiceEnabled && /* @__PURE__ */ jsx12(
3277
3827
  TTSButton,
3278
3828
  {
3279
3829
  text: message.text,
@@ -3283,7 +3833,7 @@ var ChatBubble = ({
3283
3833
  size: "small"
3284
3834
  }
3285
3835
  ),
3286
- /* @__PURE__ */ jsx11(
3836
+ /* @__PURE__ */ jsx12(
3287
3837
  "div",
3288
3838
  {
3289
3839
  className: `text-xs opacity-0 group-hover:opacity-70 transition-opacity whitespace-nowrap flex-shrink-0 ${message.type === "user" ? "text-gray-400 dark:text-gray-500 text-left" : "text-gray-600 dark:text-gray-400 text-right"}`,
@@ -3292,29 +3842,41 @@ var ChatBubble = ({
3292
3842
  }
3293
3843
  )
3294
3844
  ] }, message.id)),
3295
- /* @__PURE__ */ jsx11("div", { ref: messagesEndRef })
3845
+ /* @__PURE__ */ jsx12("div", { ref: messagesEndRef })
3296
3846
  ] }),
3297
- /* @__PURE__ */ jsx11(
3298
- InputField,
3299
- {
3300
- inputValue,
3301
- onInputChange: setInputValue,
3302
- onSubmit: handleSend,
3303
- placeholder: inputHints[currentHintIndex],
3304
- glassClasses: "",
3305
- theme,
3306
- inputRef,
3307
- sendButtonLabel: config.sendButtonLabel,
3308
- voiceEnabled,
3309
- isListening,
3310
- onMicClick: handleMicClick,
3311
- modKey: isMac ? "Cmd" : "Ctrl"
3312
- }
3313
- )
3847
+ /* @__PURE__ */ jsxs8("div", { style: { position: "relative" }, children: [
3848
+ slashCommand.isOpen && /* @__PURE__ */ jsx12(
3849
+ SlashCommandPopup,
3850
+ {
3851
+ tools: slashCommand.filteredTools,
3852
+ selectedIndex: slashCommand.selectedIndex,
3853
+ onSelect: slashCommand.selectTool,
3854
+ onClose: () => setInputValue("")
3855
+ }
3856
+ ),
3857
+ /* @__PURE__ */ jsx12(
3858
+ InputField,
3859
+ {
3860
+ inputValue,
3861
+ onInputChange: setInputValue,
3862
+ onSubmit: handleSend,
3863
+ placeholder: inputHints[currentHintIndex],
3864
+ glassClasses: "",
3865
+ theme,
3866
+ inputRef,
3867
+ sendButtonLabel: config.sendButtonLabel,
3868
+ voiceEnabled,
3869
+ isListening,
3870
+ onMicClick: handleMicClick,
3871
+ modKey: isMac ? "Cmd" : "Ctrl",
3872
+ onKeyDown: slashCommand.onKeyDown
3873
+ }
3874
+ )
3875
+ ] })
3314
3876
  ]
3315
3877
  }
3316
3878
  ),
3317
- !isExpanded && /* @__PURE__ */ jsxs7(
3879
+ !isExpanded && /* @__PURE__ */ jsxs8(
3318
3880
  "button",
3319
3881
  {
3320
3882
  onClick: handleToggle,
@@ -3322,8 +3884,8 @@ var ChatBubble = ({
3322
3884
  "data-testid": ChatNames.bubble,
3323
3885
  title: `Open chat (press ${isMac ? "Cmd" : "Ctrl"}+/ for voice recording)`,
3324
3886
  children: [
3325
- /* @__PURE__ */ jsx11("img", { src: config.logo, alt: "Supernal", className: "w-8 h-8" }),
3326
- hasUnread && notifications && /* @__PURE__ */ jsx11("div", { className: "absolute -top-1 -right-1 w-5 h-5 bg-red-500 rounded-full flex items-center justify-center animate-pulse shadow-lg", "data-testid": "unread-indicator", children: /* @__PURE__ */ jsx11("span", { className: "text-xs text-white font-bold", children: unreadCount > 9 ? "9+" : unreadCount }) })
3887
+ /* @__PURE__ */ jsx12("img", { src: config.logo, alt: "Supernal", className: "w-8 h-8" }),
3888
+ hasUnread && notifications && /* @__PURE__ */ jsx12("div", { className: "absolute -top-1 -right-1 w-5 h-5 bg-red-500 rounded-full flex items-center justify-center animate-pulse shadow-lg", "data-testid": "unread-indicator", children: /* @__PURE__ */ jsx12("span", { className: "text-xs text-white font-bold", children: unreadCount > 9 ? "9+" : unreadCount }) })
3327
3889
  ]
3328
3890
  }
3329
3891
  )
@@ -3333,24 +3895,24 @@ var ChatBubble = ({
3333
3895
  };
3334
3896
 
3335
3897
  // src/components/AutoNavigationContext.tsx
3336
- import { useEffect as useEffect7, useState as useState9 } from "react";
3898
+ import { useEffect as useEffect9, useState as useState10 } from "react";
3337
3899
 
3338
3900
  // src/hooks/useNavigationGraph.tsx
3339
- import { useEffect as useEffect6, useState as useState8, useCallback as useCallback5, createContext as createContext3, useContext as useContext3 } from "react";
3901
+ import { useEffect as useEffect8, useState as useState9, useCallback as useCallback6, createContext as createContext3, useContext as useContext3 } from "react";
3340
3902
  import {
3341
3903
  NavigationGraph
3342
3904
  } from "@supernal/interface/browser";
3343
- import { jsx as jsx12 } from "react/jsx-runtime";
3905
+ import { jsx as jsx13 } from "react/jsx-runtime";
3344
3906
  var NavigationContextContext = createContext3("global");
3345
3907
  function NavigationContextProvider({
3346
3908
  value,
3347
3909
  children
3348
3910
  }) {
3349
3911
  const graph = useNavigationGraph();
3350
- useEffect6(() => {
3912
+ useEffect8(() => {
3351
3913
  graph.setCurrentContext(value);
3352
3914
  }, [value, graph]);
3353
- return /* @__PURE__ */ jsx12(NavigationContextContext.Provider, { value, children });
3915
+ return /* @__PURE__ */ jsx13(NavigationContextContext.Provider, { value, children });
3354
3916
  }
3355
3917
  function useNavigationGraph() {
3356
3918
  return NavigationGraph.getInstance();
@@ -3358,8 +3920,8 @@ function useNavigationGraph() {
3358
3920
  function useCurrentContext() {
3359
3921
  const contextFromProvider = useContext3(NavigationContextContext);
3360
3922
  const graph = useNavigationGraph();
3361
- const [graphContext, setGraphContext] = useState8("");
3362
- useEffect6(() => {
3923
+ const [graphContext, setGraphContext] = useState9("");
3924
+ useEffect8(() => {
3363
3925
  const interval = setInterval(() => {
3364
3926
  const current = graph.getCurrentContext?.() || "";
3365
3927
  if (current !== graphContext) {
@@ -3373,7 +3935,7 @@ function useCurrentContext() {
3373
3935
  function useRegisterTool(toolId, contextId, metadata) {
3374
3936
  const graph = useNavigationGraph();
3375
3937
  const currentContext = useCurrentContext();
3376
- useEffect6(() => {
3938
+ useEffect8(() => {
3377
3939
  let targetContext = contextId || currentContext;
3378
3940
  if (!contextId && metadata) {
3379
3941
  const detection = graph.detectToolContext?.(toolId, metadata);
@@ -3387,10 +3949,10 @@ function useRegisterTool(toolId, contextId, metadata) {
3387
3949
  function useNavigationPath(targetContextOrToolId, isToolId = false) {
3388
3950
  const graph = useNavigationGraph();
3389
3951
  const currentContext = useCurrentContext();
3390
- const [path, setPath] = useState8(null);
3391
- const [loading, setLoading] = useState8(true);
3392
- const [error, setError] = useState8();
3393
- useEffect6(() => {
3952
+ const [path, setPath] = useState9(null);
3953
+ const [loading, setLoading] = useState9(true);
3954
+ const [error, setError] = useState9();
3955
+ useEffect8(() => {
3394
3956
  try {
3395
3957
  let targetContext = targetContextOrToolId;
3396
3958
  if (isToolId) {
@@ -3418,9 +3980,9 @@ function useNavigationPath(targetContextOrToolId, isToolId = false) {
3418
3980
  function useNavigate() {
3419
3981
  const graph = useNavigationGraph();
3420
3982
  const currentContext = useCurrentContext();
3421
- const [navigating, setNavigating] = useState8(false);
3422
- const [error, setError] = useState8();
3423
- const navigateTo = useCallback5(async (targetContextOrToolId, isToolId = false, executeNavigation) => {
3983
+ const [navigating, setNavigating] = useState9(false);
3984
+ const [error, setError] = useState9();
3985
+ const navigateTo = useCallback6(async (targetContextOrToolId, isToolId = false, executeNavigation) => {
3424
3986
  setNavigating(true);
3425
3987
  setError(void 0);
3426
3988
  try {
@@ -3462,8 +4024,8 @@ function useNavigate() {
3462
4024
  }
3463
4025
  function useAllContexts() {
3464
4026
  const graph = useNavigationGraph();
3465
- const [contexts, setContexts] = useState8(graph.getAllContexts?.());
3466
- useEffect6(() => {
4027
+ const [contexts, setContexts] = useState9(graph.getAllContexts?.());
4028
+ useEffect8(() => {
3467
4029
  const interval = setInterval(() => {
3468
4030
  setContexts(graph.getAllContexts?.());
3469
4031
  }, 1e3);
@@ -3473,28 +4035,28 @@ function useAllContexts() {
3473
4035
  }
3474
4036
 
3475
4037
  // src/components/AutoNavigationContext.tsx
3476
- import { Fragment as Fragment4, jsx as jsx13 } from "react/jsx-runtime";
4038
+ import { Fragment as Fragment4, jsx as jsx14 } from "react/jsx-runtime";
3477
4039
  function AutoNavigationContext({
3478
4040
  children,
3479
4041
  routes,
3480
4042
  onNavigate
3481
4043
  }) {
3482
- const [pathname, setPathname] = useState9("/");
3483
- useEffect7(() => {
4044
+ const [pathname, setPathname] = useState10("/");
4045
+ useEffect9(() => {
3484
4046
  if (typeof window !== "undefined") {
3485
4047
  setPathname(window.location.pathname);
3486
4048
  }
3487
4049
  }, []);
3488
4050
  const context = routes ? inferContextFromPath(pathname, routes) : null;
3489
- useEffect7(() => {
4051
+ useEffect9(() => {
3490
4052
  if (onNavigate && context) {
3491
4053
  onNavigate(context);
3492
4054
  }
3493
4055
  }, [context, onNavigate]);
3494
4056
  if (!context) {
3495
- return /* @__PURE__ */ jsx13(Fragment4, { children });
4057
+ return /* @__PURE__ */ jsx14(Fragment4, { children });
3496
4058
  }
3497
- return /* @__PURE__ */ jsx13(NavigationContextProvider, { value: context, children });
4059
+ return /* @__PURE__ */ jsx14(NavigationContextProvider, { value: context, children });
3498
4060
  }
3499
4061
  function inferContextFromPath(path, customRoutes) {
3500
4062
  if (customRoutes) {
@@ -3524,8 +4086,438 @@ function inferContextFromPath(path, customRoutes) {
3524
4086
  }
3525
4087
 
3526
4088
  // src/components/SupernalProvider.tsx
3527
- import { ExposureCollector, ToolRegistry } from "@supernal/interface/browser";
3528
- import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
4089
+ import { ExposureCollector, ToolRegistry as ToolRegistry3 } from "@supernal/interface/browser";
4090
+
4091
+ // src/hooks/useLocationTracking.ts
4092
+ import { useEffect as useEffect10, useRef as useRef9 } from "react";
4093
+ import { useRouter } from "next/router";
4094
+ import { LocationContext } from "@supernal/interface/browser";
4095
+ function getVisibleElements() {
4096
+ if (typeof document === "undefined") return [];
4097
+ const elements = document.querySelectorAll("[data-testid]");
4098
+ return Array.from(elements).map((el) => el.getAttribute("data-testid")).filter(Boolean);
4099
+ }
4100
+ function arraysEqual(a, b) {
4101
+ if (a.length !== b.length) return false;
4102
+ const sortedA = [...a].sort();
4103
+ const sortedB = [...b].sort();
4104
+ return sortedA.every((val, idx) => val === sortedB[idx]);
4105
+ }
4106
+ function useLocationTracking() {
4107
+ const router = useRouter();
4108
+ const lastLocationRef = useRef9("");
4109
+ const lastElementsRef = useRef9([]);
4110
+ useEffect10(() => {
4111
+ const updateLocation = () => {
4112
+ const visibleElements = getVisibleElements();
4113
+ const locationChanged = lastLocationRef.current !== router.pathname;
4114
+ const elementsChanged = !arraysEqual(lastElementsRef.current, visibleElements);
4115
+ if (locationChanged || elementsChanged) {
4116
+ LocationContext.setCurrent({
4117
+ page: router.pathname,
4118
+ route: router.route,
4119
+ elements: visibleElements,
4120
+ metadata: {
4121
+ query: router.query,
4122
+ asPath: router.asPath
4123
+ }
4124
+ });
4125
+ if (locationChanged) {
4126
+ console.log(`[LocationTracking] Updated location: ${router.pathname}`);
4127
+ }
4128
+ if (elementsChanged) {
4129
+ console.log(`[LocationTracking] Visible elements changed: ${visibleElements.length} elements`);
4130
+ }
4131
+ lastLocationRef.current = router.pathname;
4132
+ lastElementsRef.current = visibleElements;
4133
+ }
4134
+ };
4135
+ const initialTimer = setTimeout(updateLocation, 100);
4136
+ const intervalId = setInterval(updateLocation, 1e3);
4137
+ const handleRouteChange = () => {
4138
+ setTimeout(updateLocation, 100);
4139
+ };
4140
+ router.events.on("routeChangeComplete", handleRouteChange);
4141
+ return () => {
4142
+ clearTimeout(initialTimer);
4143
+ clearInterval(intervalId);
4144
+ router.events.off("routeChangeComplete", handleRouteChange);
4145
+ };
4146
+ }, [router.pathname, router.route, router.asPath]);
4147
+ }
4148
+
4149
+ // src/hooks/useNavigationGraphSetup.ts
4150
+ import { useEffect as useEffect11, useState as useState11 } from "react";
4151
+ import { useRouter as useRouter2 } from "next/router";
4152
+ function useNavigationGraphSetup() {
4153
+ const router = useRouter2();
4154
+ const [isInitialized, setIsInitialized] = useState11(false);
4155
+ useEffect11(() => {
4156
+ import("@supernal/interface/browser").then(({ NavigationGraph: NavigationGraph2 }) => {
4157
+ const graph = NavigationGraph2.getInstance();
4158
+ const handler = (path) => {
4159
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
4160
+ router.push(normalizedPath);
4161
+ };
4162
+ graph.setNavigationHandler(handler);
4163
+ graph.setRouter(router);
4164
+ graph.setCurrentContext(router.asPath);
4165
+ setIsInitialized(true);
4166
+ console.log("[NavigationGraphSetup] Auto-configured with Next.js router");
4167
+ });
4168
+ }, [router]);
4169
+ useEffect11(() => {
4170
+ if (!isInitialized) return;
4171
+ import("@supernal/interface/browser").then(({ NavigationGraph: NavigationGraph2 }) => {
4172
+ const graph = NavigationGraph2.getInstance();
4173
+ graph.setCurrentContext(router.asPath);
4174
+ console.log(`[NavigationGraphSetup] Context updated: ${router.asPath}`);
4175
+ });
4176
+ }, [router.asPath, isInitialized]);
4177
+ }
4178
+
4179
+ // src/components/ToolMenuPopup/ToolMenuPopup.tsx
4180
+ import { useEffect as useEffect12, useRef as useRef10, useState as useState12 } from "react";
4181
+ import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
4182
+ var ToolMenuPopup = ({
4183
+ isOpen,
4184
+ onClose,
4185
+ categories,
4186
+ totalTools,
4187
+ contextLabel
4188
+ }) => {
4189
+ const [collapsedCategories, setCollapsedCategories] = useState12(/* @__PURE__ */ new Set());
4190
+ const [isHydrated, setIsHydrated] = useState12(false);
4191
+ const [isMobile, setIsMobile] = useState12(false);
4192
+ const popupRef = useRef10(null);
4193
+ const { insertText } = useChatInput();
4194
+ useEffect12(() => {
4195
+ setIsHydrated(true);
4196
+ setIsMobile(window.matchMedia("(max-width: 767px)").matches);
4197
+ }, []);
4198
+ useEffect12(() => {
4199
+ if (!isOpen) return;
4200
+ const handleClickOutside = (e) => {
4201
+ const target = e.target;
4202
+ if (popupRef.current && !popupRef.current.contains(target)) {
4203
+ onClose();
4204
+ }
4205
+ };
4206
+ document.addEventListener("mousedown", handleClickOutside);
4207
+ return () => document.removeEventListener("mousedown", handleClickOutside);
4208
+ }, [isOpen, onClose]);
4209
+ useEffect12(() => {
4210
+ if (!isOpen) return;
4211
+ const handleKey = (e) => {
4212
+ if (e.key === "Escape") {
4213
+ onClose();
4214
+ }
4215
+ };
4216
+ document.addEventListener("keydown", handleKey);
4217
+ return () => document.removeEventListener("keydown", handleKey);
4218
+ }, [isOpen, onClose]);
4219
+ if (!isHydrated || !isOpen) return null;
4220
+ const toggleCategory = (key) => {
4221
+ setCollapsedCategories((prev) => {
4222
+ const next = new Set(prev);
4223
+ if (next.has(key)) {
4224
+ next.delete(key);
4225
+ } else {
4226
+ next.add(key);
4227
+ }
4228
+ return next;
4229
+ });
4230
+ };
4231
+ const handleToolClick = (tool) => {
4232
+ const command = tool.examples?.[0] || tool.name.toLowerCase();
4233
+ insertText(command, false);
4234
+ onClose();
4235
+ };
4236
+ const glassStyle = {
4237
+ ...GLASS_RESPONSE_BUBBLE.dark,
4238
+ zIndex: 999998
4239
+ };
4240
+ const positionStyle = isMobile ? {
4241
+ position: "fixed",
4242
+ bottom: 0,
4243
+ left: 0,
4244
+ right: 0,
4245
+ maxHeight: "80vh",
4246
+ borderRadius: "16px 16px 0 0"
4247
+ } : {
4248
+ position: "fixed",
4249
+ top: "50%",
4250
+ left: "50%",
4251
+ transform: "translate(-50%, -50%)",
4252
+ maxWidth: 480,
4253
+ width: "90vw",
4254
+ maxHeight: "70vh",
4255
+ borderRadius: 16
4256
+ };
4257
+ return /* @__PURE__ */ jsxs9(
4258
+ "div",
4259
+ {
4260
+ ref: popupRef,
4261
+ "data-tool-menu": true,
4262
+ style: { ...glassStyle, ...positionStyle, overflowY: "auto" },
4263
+ children: [
4264
+ /* @__PURE__ */ jsxs9("div", { style: {
4265
+ padding: "16px 20px",
4266
+ borderBottom: "1px solid rgba(255, 255, 255, 0.1)",
4267
+ display: "flex",
4268
+ justifyContent: "space-between",
4269
+ alignItems: "center"
4270
+ }, children: [
4271
+ /* @__PURE__ */ jsxs9("div", { children: [
4272
+ /* @__PURE__ */ jsx15("h3", { style: { margin: 0, color: "#fff", fontSize: 16, fontWeight: 600 }, children: "Available Actions" }),
4273
+ /* @__PURE__ */ jsxs9("p", { style: { margin: "4px 0 0", color: "rgba(255,255,255,0.6)", fontSize: 12 }, children: [
4274
+ contextLabel,
4275
+ " \xB7 ",
4276
+ totalTools,
4277
+ " tool",
4278
+ totalTools !== 1 ? "s" : ""
4279
+ ] })
4280
+ ] }),
4281
+ /* @__PURE__ */ jsx15(
4282
+ "button",
4283
+ {
4284
+ onClick: onClose,
4285
+ style: {
4286
+ background: "none",
4287
+ border: "none",
4288
+ color: "rgba(255,255,255,0.5)",
4289
+ fontSize: 20,
4290
+ cursor: "pointer",
4291
+ padding: "4px 8px",
4292
+ lineHeight: 1
4293
+ },
4294
+ "aria-label": "Close tool menu",
4295
+ children: "\xD7"
4296
+ }
4297
+ )
4298
+ ] }),
4299
+ /* @__PURE__ */ jsxs9("div", { style: { padding: "8px 12px 16px" }, children: [
4300
+ categories.length === 0 && /* @__PURE__ */ jsx15("p", { style: { color: "rgba(255,255,255,0.5)", textAlign: "center", padding: "24px 0", fontSize: 14 }, children: "No tools available on this page." }),
4301
+ categories.map((category) => {
4302
+ const isCollapsed = collapsedCategories.has(category.key);
4303
+ return /* @__PURE__ */ jsxs9("div", { style: { marginBottom: 4 }, children: [
4304
+ /* @__PURE__ */ jsxs9(
4305
+ "button",
4306
+ {
4307
+ onClick: () => toggleCategory(category.key),
4308
+ style: {
4309
+ width: "100%",
4310
+ display: "flex",
4311
+ alignItems: "center",
4312
+ justifyContent: "space-between",
4313
+ padding: "10px 8px",
4314
+ background: "none",
4315
+ border: "none",
4316
+ cursor: "pointer",
4317
+ borderRadius: 8,
4318
+ color: "#fff",
4319
+ transition: "background 0.15s"
4320
+ },
4321
+ onMouseEnter: (e) => {
4322
+ e.currentTarget.style.background = "rgba(255,255,255,0.05)";
4323
+ },
4324
+ onMouseLeave: (e) => {
4325
+ e.currentTarget.style.background = "none";
4326
+ },
4327
+ children: [
4328
+ /* @__PURE__ */ jsxs9("span", { style: { fontSize: 14, fontWeight: 500 }, children: [
4329
+ category.displayName,
4330
+ /* @__PURE__ */ jsx15("span", { style: { color: "rgba(255,255,255,0.4)", fontWeight: 400, marginLeft: 8, fontSize: 12 }, children: category.tools.length })
4331
+ ] }),
4332
+ /* @__PURE__ */ jsx15("span", { style: { color: "rgba(255,255,255,0.4)", fontSize: 12 }, children: isCollapsed ? "\u25B6" : "\u25BC" })
4333
+ ]
4334
+ }
4335
+ ),
4336
+ !isCollapsed && /* @__PURE__ */ jsx15("div", { style: { paddingLeft: 8, paddingRight: 8 }, children: category.tools.map((tool, idx) => /* @__PURE__ */ jsxs9(
4337
+ "button",
4338
+ {
4339
+ onClick: () => handleToolClick(tool),
4340
+ style: {
4341
+ width: "100%",
4342
+ display: "block",
4343
+ padding: "8px 10px",
4344
+ background: "none",
4345
+ border: "none",
4346
+ cursor: "pointer",
4347
+ borderRadius: 6,
4348
+ textAlign: "left",
4349
+ color: "#fff",
4350
+ transition: "background 0.15s"
4351
+ },
4352
+ onMouseEnter: (e) => {
4353
+ e.currentTarget.style.background = "rgba(255,255,255,0.08)";
4354
+ },
4355
+ onMouseLeave: (e) => {
4356
+ e.currentTarget.style.background = "none";
4357
+ },
4358
+ children: [
4359
+ /* @__PURE__ */ jsx15("div", { style: { fontSize: 13, fontWeight: 500 }, children: tool.name }),
4360
+ tool.description && /* @__PURE__ */ jsx15("div", { style: {
4361
+ fontSize: 11,
4362
+ color: "rgba(255,255,255,0.5)",
4363
+ marginTop: 2,
4364
+ lineHeight: 1.3,
4365
+ overflow: "hidden",
4366
+ textOverflow: "ellipsis",
4367
+ whiteSpace: "nowrap"
4368
+ }, children: tool.description })
4369
+ ]
4370
+ },
4371
+ tool.toolId || `${category.key}-${idx}`
4372
+ )) })
4373
+ ] }, category.key);
4374
+ })
4375
+ ] }),
4376
+ /* @__PURE__ */ jsxs9("div", { style: {
4377
+ padding: "10px 20px",
4378
+ borderTop: "1px solid rgba(255, 255, 255, 0.08)",
4379
+ textAlign: "center",
4380
+ color: "rgba(255,255,255,0.35)",
4381
+ fontSize: 11
4382
+ }, children: [
4383
+ "Click a tool to insert its command \xB7 Type ",
4384
+ /* @__PURE__ */ jsx15("kbd", { style: {
4385
+ padding: "1px 4px",
4386
+ borderRadius: 3,
4387
+ border: "1px solid rgba(255,255,255,0.2)",
4388
+ fontSize: 10
4389
+ }, children: "/" }),
4390
+ " in chat for quick commands \xB7 ",
4391
+ /* @__PURE__ */ jsx15("kbd", { style: {
4392
+ padding: "1px 4px",
4393
+ borderRadius: 3,
4394
+ border: "1px solid rgba(255,255,255,0.2)",
4395
+ fontSize: 10
4396
+ }, children: "Esc" }),
4397
+ " to close"
4398
+ ] })
4399
+ ]
4400
+ }
4401
+ );
4402
+ };
4403
+
4404
+ // src/components/ToolMenuPopup/ToolMenuPopupTrigger.tsx
4405
+ import { useEffect as useEffect13 } from "react";
4406
+
4407
+ // src/components/ToolMenuPopup/useToolMenu.ts
4408
+ import { useState as useState13, useMemo as useMemo4, useCallback as useCallback7 } from "react";
4409
+ import { ToolRegistry as ToolRegistry2 } from "@supernal/interface/browser";
4410
+ var CATEGORY_DISPLAY = {
4411
+ navigation: "Navigation",
4412
+ user_interaction: "Controls",
4413
+ data_manipulation: "Data",
4414
+ content_creation: "Content",
4415
+ content_retrieval: "Content",
4416
+ external_service: "Services",
4417
+ system: "System",
4418
+ memory: "Memory",
4419
+ data: "Data",
4420
+ search: "Search",
4421
+ utility: "Utility",
4422
+ dom: "DOM",
4423
+ api: "API",
4424
+ communication: "Communication",
4425
+ "context-app": "App Context",
4426
+ workflow: "Workflow"
4427
+ };
4428
+ function useToolMenu() {
4429
+ const [isOpen, setIsOpen] = useState13(false);
4430
+ const open = useCallback7(() => setIsOpen(true), []);
4431
+ const close = useCallback7(() => setIsOpen(false), []);
4432
+ const toggle = useCallback7(() => setIsOpen((prev) => !prev), []);
4433
+ const { categories, totalTools, contextLabel } = useMemo4(() => {
4434
+ if (!isOpen) {
4435
+ return { categories: [], totalTools: 0, contextLabel: "" };
4436
+ }
4437
+ const tools = ToolRegistry2.getToolsByLocation();
4438
+ const aiTools = tools.filter((t) => t.aiEnabled);
4439
+ const grouped = {};
4440
+ for (const tool of aiTools) {
4441
+ const cat = tool.category || "uncategorized";
4442
+ if (!grouped[cat]) grouped[cat] = [];
4443
+ grouped[cat].push(tool);
4444
+ }
4445
+ const cats = Object.entries(grouped).map(([key, catTools]) => ({
4446
+ key,
4447
+ displayName: CATEGORY_DISPLAY[key] || key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
4448
+ tools: catTools
4449
+ })).sort((a, b) => a.displayName.localeCompare(b.displayName));
4450
+ let label = "All Pages";
4451
+ try {
4452
+ const { LocationContext: LocationContext2 } = __require("@supernal/interface/browser");
4453
+ const current = LocationContext2.getCurrent();
4454
+ if (current?.page) {
4455
+ label = current.page;
4456
+ }
4457
+ } catch {
4458
+ }
4459
+ return { categories: cats, totalTools: aiTools.length, contextLabel: label };
4460
+ }, [isOpen]);
4461
+ return { isOpen, open, close, toggle, categories, totalTools, contextLabel };
4462
+ }
4463
+
4464
+ // src/components/ToolMenuPopup/ToolMenuPopupTrigger.tsx
4465
+ import { jsx as jsx16 } from "react/jsx-runtime";
4466
+ var ToolMenuPopupTrigger = () => {
4467
+ const toolMenu = useToolMenu();
4468
+ useEffect13(() => {
4469
+ const handleKeyDown = (e) => {
4470
+ if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key === "/") {
4471
+ e.preventDefault();
4472
+ toolMenu.toggle();
4473
+ return;
4474
+ }
4475
+ if (e.key === "?" && !e.metaKey && !e.ctrlKey && !e.altKey) {
4476
+ const target = e.target;
4477
+ const tag = target.tagName?.toLowerCase();
4478
+ const isEditable = target.isContentEditable;
4479
+ if (tag === "input" || tag === "textarea" || isEditable) {
4480
+ const value = target.value;
4481
+ if (value && value.trim().length > 0) {
4482
+ return;
4483
+ }
4484
+ }
4485
+ e.preventDefault();
4486
+ toolMenu.toggle();
4487
+ return;
4488
+ }
4489
+ if (e.key === "/" && !e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey) {
4490
+ const target = e.target;
4491
+ const tag = target.tagName?.toLowerCase();
4492
+ const isEditable = target.isContentEditable;
4493
+ if (tag === "input" || tag === "textarea" || isEditable) {
4494
+ const value = target.value;
4495
+ if (!value || value.trim().length === 0) {
4496
+ e.preventDefault();
4497
+ e.stopPropagation();
4498
+ toolMenu.toggle();
4499
+ }
4500
+ }
4501
+ }
4502
+ };
4503
+ document.addEventListener("keydown", handleKeyDown);
4504
+ return () => document.removeEventListener("keydown", handleKeyDown);
4505
+ }, [toolMenu]);
4506
+ if (!toolMenu.isOpen) return null;
4507
+ return /* @__PURE__ */ jsx16(
4508
+ ToolMenuPopup,
4509
+ {
4510
+ isOpen: toolMenu.isOpen,
4511
+ onClose: toolMenu.close,
4512
+ categories: toolMenu.categories,
4513
+ totalTools: toolMenu.totalTools,
4514
+ contextLabel: toolMenu.contextLabel
4515
+ }
4516
+ );
4517
+ };
4518
+
4519
+ // src/components/SupernalProvider.tsx
4520
+ import { jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
3529
4521
  function ChatBubbleConnector({
3530
4522
  theme,
3531
4523
  position,
@@ -3542,7 +4534,7 @@ function ChatBubbleConnector({
3542
4534
  glassMode,
3543
4535
  ...logo ? { logo } : {}
3544
4536
  };
3545
- return /* @__PURE__ */ jsx14(
4537
+ return /* @__PURE__ */ jsx17(
3546
4538
  ChatBubble,
3547
4539
  {
3548
4540
  messages,
@@ -3579,12 +4571,14 @@ function SupernalProvider({
3579
4571
  console.log("[SupernalProvider] disabled:", disabled, "type:", typeof disabled);
3580
4572
  console.log("[SupernalProvider] shouldRenderChatBubble:", shouldRenderChatBubble);
3581
4573
  console.log("[SupernalProvider] variant:", variant, "effectiveDisplayMode:", effectiveDisplayMode);
3582
- useEffect8(() => {
4574
+ useLocationTracking();
4575
+ useNavigationGraphSetup();
4576
+ useEffect14(() => {
3583
4577
  if (typeof window === "undefined") return;
3584
4578
  const collector = ExposureCollector.getInstance();
3585
4579
  const registeredToolIds = /* @__PURE__ */ new Set();
3586
4580
  const registerTools = () => {
3587
- const allTools = ToolRegistry.getAllTools();
4581
+ const allTools = ToolRegistry3.getAllTools();
3588
4582
  allTools.forEach((tool) => {
3589
4583
  if (tool.elementId && !registeredToolIds.has(tool.toolId)) {
3590
4584
  const element = document.querySelector(`[data-testid="${tool.elementId}"]`);
@@ -3611,9 +4605,9 @@ function SupernalProvider({
3611
4605
  collector.destroy();
3612
4606
  };
3613
4607
  }, []);
3614
- return /* @__PURE__ */ jsx14(ChatInputProvider, { children: /* @__PURE__ */ jsxs8(ChatProvider, { mode, apiKey, onToolExecute, children: [
3615
- /* @__PURE__ */ jsx14(AutoNavigationContext, { routes, onNavigate, children }),
3616
- shouldRenderChatBubble ? /* @__PURE__ */ jsx14(
4608
+ return /* @__PURE__ */ jsx17(ChatInputProvider, { children: /* @__PURE__ */ jsxs10(ChatProvider, { mode, apiKey, onToolExecute, children: [
4609
+ /* @__PURE__ */ jsx17(AutoNavigationContext, { routes, onNavigate, children }),
4610
+ shouldRenderChatBubble ? /* @__PURE__ */ jsx17(
3617
4611
  ChatBubbleConnector,
3618
4612
  {
3619
4613
  theme,
@@ -3625,26 +4619,27 @@ function SupernalProvider({
3625
4619
  displayMode: effectiveDisplayMode,
3626
4620
  drawerSide
3627
4621
  }
3628
- ) : null
4622
+ ) : null,
4623
+ !disabled && /* @__PURE__ */ jsx17(ToolMenuPopupTrigger, {})
3629
4624
  ] }) });
3630
4625
  }
3631
4626
 
3632
4627
  // src/components/ChatBubbleSettingsModal.tsx
3633
- import React11, { useEffect as useEffect9 } from "react";
3634
- import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
4628
+ import React14, { useEffect as useEffect15 } from "react";
4629
+ import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
3635
4630
  function ChatBubbleSettingsModal({
3636
4631
  isOpen,
3637
4632
  onClose,
3638
4633
  settings,
3639
4634
  onSettingsChange
3640
4635
  }) {
3641
- const [localSettings, setLocalSettings] = React11.useState(settings);
3642
- useEffect9(() => {
4636
+ const [localSettings, setLocalSettings] = React14.useState(settings);
4637
+ useEffect15(() => {
3643
4638
  if (isOpen) {
3644
4639
  setLocalSettings(settings);
3645
4640
  }
3646
4641
  }, [isOpen, settings]);
3647
- useEffect9(() => {
4642
+ useEffect15(() => {
3648
4643
  const handleEscape = (e) => {
3649
4644
  if (e.key === "Escape" && isOpen) {
3650
4645
  onClose();
@@ -3665,8 +4660,8 @@ function ChatBubbleSettingsModal({
3665
4660
  onClose();
3666
4661
  };
3667
4662
  const isDark = localSettings.theme === "dark";
3668
- return /* @__PURE__ */ jsxs9(Fragment5, { children: [
3669
- /* @__PURE__ */ jsx15(
4663
+ return /* @__PURE__ */ jsxs11(Fragment5, { children: [
4664
+ /* @__PURE__ */ jsx18(
3670
4665
  "div",
3671
4666
  {
3672
4667
  className: "fixed inset-0 bg-black bg-opacity-50 z-[60] backdrop-blur-sm",
@@ -3674,12 +4669,12 @@ function ChatBubbleSettingsModal({
3674
4669
  "aria-hidden": "true"
3675
4670
  }
3676
4671
  ),
3677
- /* @__PURE__ */ jsx15(
4672
+ /* @__PURE__ */ jsx18(
3678
4673
  "div",
3679
4674
  {
3680
4675
  className: "fixed inset-0 z-[70] flex items-center justify-center p-4",
3681
4676
  "data-testid": "chat-settings-modal",
3682
- children: /* @__PURE__ */ jsxs9(
4677
+ children: /* @__PURE__ */ jsxs11(
3683
4678
  "div",
3684
4679
  {
3685
4680
  className: `${isDark ? "bg-gray-800 text-white" : "bg-white text-gray-900"} rounded-2xl shadow-2xl max-w-md w-full p-6 border ${isDark ? "border-gray-700" : "border-gray-200"}`,
@@ -3688,8 +4683,8 @@ function ChatBubbleSettingsModal({
3688
4683
  "aria-labelledby": "settings-modal-title",
3689
4684
  onClick: (e) => e.stopPropagation(),
3690
4685
  children: [
3691
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between mb-6", children: [
3692
- /* @__PURE__ */ jsx15(
4686
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between mb-6", children: [
4687
+ /* @__PURE__ */ jsx18(
3693
4688
  "h2",
3694
4689
  {
3695
4690
  id: "settings-modal-title",
@@ -3697,56 +4692,56 @@ function ChatBubbleSettingsModal({
3697
4692
  children: "Chat Settings"
3698
4693
  }
3699
4694
  ),
3700
- /* @__PURE__ */ jsx15(
4695
+ /* @__PURE__ */ jsx18(
3701
4696
  "button",
3702
4697
  {
3703
4698
  onClick: handleCancel,
3704
4699
  className: `${isDark ? "text-gray-400 hover:text-gray-200" : "text-gray-400 hover:text-gray-600"} transition-colors p-1 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700`,
3705
4700
  "aria-label": "Close modal",
3706
- children: /* @__PURE__ */ jsx15("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx15("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
4701
+ children: /* @__PURE__ */ jsx18("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx18("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
3707
4702
  }
3708
4703
  )
3709
4704
  ] }),
3710
- /* @__PURE__ */ jsxs9("div", { className: "space-y-5 mb-6", children: [
3711
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
3712
- /* @__PURE__ */ jsxs9("div", { children: [
3713
- /* @__PURE__ */ jsx15("label", { className: "block text-base font-medium mb-1", children: "Theme" }),
3714
- /* @__PURE__ */ jsx15("p", { className: `text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Switch between light and dark modes" })
4705
+ /* @__PURE__ */ jsxs11("div", { className: "space-y-5 mb-6", children: [
4706
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
4707
+ /* @__PURE__ */ jsxs11("div", { children: [
4708
+ /* @__PURE__ */ jsx18("label", { className: "block text-base font-medium mb-1", children: "Theme" }),
4709
+ /* @__PURE__ */ jsx18("p", { className: `text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Switch between light and dark modes" })
3715
4710
  ] }),
3716
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center space-x-2", children: [
3717
- /* @__PURE__ */ jsx15(
4711
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center space-x-2", children: [
4712
+ /* @__PURE__ */ jsx18(
3718
4713
  "button",
3719
4714
  {
3720
4715
  onClick: () => setLocalSettings({ ...localSettings, theme: "light" }),
3721
4716
  className: `p-2 rounded-lg transition-all ${localSettings.theme === "light" ? "bg-blue-600 text-white shadow-lg" : isDark ? "bg-gray-700 text-gray-300 hover:bg-gray-600" : "bg-gray-100 text-gray-600 hover:bg-gray-200"}`,
3722
4717
  title: "Light mode",
3723
- children: /* @__PURE__ */ jsx15("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx15("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" }) })
4718
+ children: /* @__PURE__ */ jsx18("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx18("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" }) })
3724
4719
  }
3725
4720
  ),
3726
- /* @__PURE__ */ jsx15(
4721
+ /* @__PURE__ */ jsx18(
3727
4722
  "button",
3728
4723
  {
3729
4724
  onClick: () => setLocalSettings({ ...localSettings, theme: "dark" }),
3730
4725
  className: `p-2 rounded-lg transition-all ${localSettings.theme === "dark" ? "bg-blue-600 text-white shadow-lg" : isDark ? "bg-gray-700 text-gray-300 hover:bg-gray-600" : "bg-gray-100 text-gray-600 hover:bg-gray-200"}`,
3731
4726
  title: "Dark mode",
3732
- children: /* @__PURE__ */ jsx15("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx15("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" }) })
4727
+ children: /* @__PURE__ */ jsx18("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx18("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" }) })
3733
4728
  }
3734
4729
  )
3735
4730
  ] })
3736
4731
  ] }),
3737
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
3738
- /* @__PURE__ */ jsxs9("div", { children: [
3739
- /* @__PURE__ */ jsx15("label", { className: "block text-base font-medium mb-1", children: "Glass Mode" }),
3740
- /* @__PURE__ */ jsx15("p", { className: `text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Enable glassmorphism transparency effect" })
4732
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
4733
+ /* @__PURE__ */ jsxs11("div", { children: [
4734
+ /* @__PURE__ */ jsx18("label", { className: "block text-base font-medium mb-1", children: "Glass Mode" }),
4735
+ /* @__PURE__ */ jsx18("p", { className: `text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Enable glassmorphism transparency effect" })
3741
4736
  ] }),
3742
- /* @__PURE__ */ jsx15(
4737
+ /* @__PURE__ */ jsx18(
3743
4738
  "button",
3744
4739
  {
3745
4740
  onClick: () => setLocalSettings({ ...localSettings, glassMode: !localSettings.glassMode }),
3746
4741
  className: `relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${localSettings.glassMode ? "bg-blue-600" : isDark ? "bg-gray-700" : "bg-gray-300"}`,
3747
4742
  role: "switch",
3748
4743
  "aria-checked": localSettings.glassMode,
3749
- children: /* @__PURE__ */ jsx15(
4744
+ children: /* @__PURE__ */ jsx18(
3750
4745
  "span",
3751
4746
  {
3752
4747
  className: `inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${localSettings.glassMode ? "translate-x-6" : "translate-x-1"}`
@@ -3755,19 +4750,19 @@ function ChatBubbleSettingsModal({
3755
4750
  }
3756
4751
  )
3757
4752
  ] }),
3758
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
3759
- /* @__PURE__ */ jsxs9("div", { children: [
3760
- /* @__PURE__ */ jsx15("label", { className: "block text-base font-medium mb-1", children: "Notifications" }),
3761
- /* @__PURE__ */ jsx15("p", { className: `text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Show unread message indicators" })
4753
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
4754
+ /* @__PURE__ */ jsxs11("div", { children: [
4755
+ /* @__PURE__ */ jsx18("label", { className: "block text-base font-medium mb-1", children: "Notifications" }),
4756
+ /* @__PURE__ */ jsx18("p", { className: `text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Show unread message indicators" })
3762
4757
  ] }),
3763
- /* @__PURE__ */ jsx15(
4758
+ /* @__PURE__ */ jsx18(
3764
4759
  "button",
3765
4760
  {
3766
4761
  onClick: () => setLocalSettings({ ...localSettings, notifications: !localSettings.notifications }),
3767
4762
  className: `relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${localSettings.notifications ? "bg-blue-600" : isDark ? "bg-gray-700" : "bg-gray-300"}`,
3768
4763
  role: "switch",
3769
4764
  "aria-checked": localSettings.notifications,
3770
- children: /* @__PURE__ */ jsx15(
4765
+ children: /* @__PURE__ */ jsx18(
3771
4766
  "span",
3772
4767
  {
3773
4768
  className: `inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${localSettings.notifications ? "translate-x-6" : "translate-x-1"}`
@@ -3776,16 +4771,16 @@ function ChatBubbleSettingsModal({
3776
4771
  }
3777
4772
  )
3778
4773
  ] }),
3779
- /* @__PURE__ */ jsx15("div", { className: `border-t ${isDark ? "border-gray-700" : "border-gray-200"} my-2` }),
3780
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
3781
- /* @__PURE__ */ jsxs9("div", { children: [
3782
- /* @__PURE__ */ jsxs9("label", { className: "block text-base font-medium mb-1 flex items-center space-x-2", children: [
3783
- /* @__PURE__ */ jsx15("span", { children: "Subtitle Overlay" }),
3784
- /* @__PURE__ */ jsx15("span", { className: "inline-block px-2 py-0.5 text-xs font-semibold rounded-full bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200", children: "BETA" })
4774
+ /* @__PURE__ */ jsx18("div", { className: `border-t ${isDark ? "border-gray-700" : "border-gray-200"} my-2` }),
4775
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
4776
+ /* @__PURE__ */ jsxs11("div", { children: [
4777
+ /* @__PURE__ */ jsxs11("label", { className: "block text-base font-medium mb-1 flex items-center space-x-2", children: [
4778
+ /* @__PURE__ */ jsx18("span", { children: "Subtitle Overlay" }),
4779
+ /* @__PURE__ */ jsx18("span", { className: "inline-block px-2 py-0.5 text-xs font-semibold rounded-full bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200", children: "BETA" })
3785
4780
  ] }),
3786
- /* @__PURE__ */ jsx15("p", { className: `text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Minimalist voice-first overlay with @/ icon" })
4781
+ /* @__PURE__ */ jsx18("p", { className: `text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Minimalist voice-first overlay with @/ icon" })
3787
4782
  ] }),
3788
- /* @__PURE__ */ jsx15(
4783
+ /* @__PURE__ */ jsx18(
3789
4784
  "button",
3790
4785
  {
3791
4786
  onClick: () => setLocalSettings({
@@ -3797,7 +4792,7 @@ function ChatBubbleSettingsModal({
3797
4792
  className: `relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${localSettings.subtitleOverlayEnabled ? "bg-blue-600" : isDark ? "bg-gray-700" : "bg-gray-300"}`,
3798
4793
  role: "switch",
3799
4794
  "aria-checked": localSettings.subtitleOverlayEnabled,
3800
- children: /* @__PURE__ */ jsx15(
4795
+ children: /* @__PURE__ */ jsx18(
3801
4796
  "span",
3802
4797
  {
3803
4798
  className: `inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${localSettings.subtitleOverlayEnabled ? "translate-x-6" : "translate-x-1"}`
@@ -3806,12 +4801,12 @@ function ChatBubbleSettingsModal({
3806
4801
  }
3807
4802
  )
3808
4803
  ] }),
3809
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
3810
- /* @__PURE__ */ jsxs9("div", { children: [
3811
- /* @__PURE__ */ jsx15("label", { className: "block text-base font-medium mb-1", children: "Display Mode" }),
3812
- /* @__PURE__ */ jsx15("p", { className: `text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Auto switches drawer on mobile, panel on desktop" })
4804
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
4805
+ /* @__PURE__ */ jsxs11("div", { children: [
4806
+ /* @__PURE__ */ jsx18("label", { className: "block text-base font-medium mb-1", children: "Display Mode" }),
4807
+ /* @__PURE__ */ jsx18("p", { className: `text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Auto switches drawer on mobile, panel on desktop" })
3813
4808
  ] }),
3814
- /* @__PURE__ */ jsxs9(
4809
+ /* @__PURE__ */ jsxs11(
3815
4810
  "select",
3816
4811
  {
3817
4812
  value: localSettings.displayMode || "auto",
@@ -3821,22 +4816,22 @@ function ChatBubbleSettingsModal({
3821
4816
  }),
3822
4817
  className: `px-3 py-2 rounded-lg border ${isDark ? "bg-gray-700 border-gray-600 text-white" : "bg-white border-gray-300 text-gray-900"} focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all`,
3823
4818
  children: [
3824
- /* @__PURE__ */ jsx15("option", { value: "auto", children: "Auto (Recommended)" }),
3825
- /* @__PURE__ */ jsx15("option", { value: "drawer", children: "Always Drawer" }),
3826
- /* @__PURE__ */ jsx15("option", { value: "full", children: "Always Panel" }),
3827
- /* @__PURE__ */ jsx15("option", { value: "floating", children: "Always Floating" }),
3828
- /* @__PURE__ */ jsx15("option", { value: "subtitle", children: "Subtitle Overlay (Beta)" })
4819
+ /* @__PURE__ */ jsx18("option", { value: "auto", children: "Auto (Recommended)" }),
4820
+ /* @__PURE__ */ jsx18("option", { value: "drawer", children: "Always Drawer" }),
4821
+ /* @__PURE__ */ jsx18("option", { value: "full", children: "Always Panel" }),
4822
+ /* @__PURE__ */ jsx18("option", { value: "floating", children: "Always Floating" }),
4823
+ /* @__PURE__ */ jsx18("option", { value: "subtitle", children: "Subtitle Overlay (Beta)" })
3829
4824
  ]
3830
4825
  }
3831
4826
  )
3832
4827
  ] }),
3833
- (localSettings.displayMode === "auto" || localSettings.displayMode === "drawer") && /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
3834
- /* @__PURE__ */ jsxs9("div", { children: [
3835
- /* @__PURE__ */ jsx15("label", { className: "block text-base font-medium mb-1", children: "Drawer Side" }),
3836
- /* @__PURE__ */ jsx15("p", { className: `text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Which edge drawer slides from" })
4828
+ (localSettings.displayMode === "auto" || localSettings.displayMode === "drawer") && /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
4829
+ /* @__PURE__ */ jsxs11("div", { children: [
4830
+ /* @__PURE__ */ jsx18("label", { className: "block text-base font-medium mb-1", children: "Drawer Side" }),
4831
+ /* @__PURE__ */ jsx18("p", { className: `text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Which edge drawer slides from" })
3837
4832
  ] }),
3838
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center space-x-2", children: [
3839
- /* @__PURE__ */ jsx15(
4833
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center space-x-2", children: [
4834
+ /* @__PURE__ */ jsx18(
3840
4835
  "button",
3841
4836
  {
3842
4837
  onClick: () => setLocalSettings({ ...localSettings, drawerSide: "left" }),
@@ -3844,7 +4839,7 @@ function ChatBubbleSettingsModal({
3844
4839
  children: "Left"
3845
4840
  }
3846
4841
  ),
3847
- /* @__PURE__ */ jsx15(
4842
+ /* @__PURE__ */ jsx18(
3848
4843
  "button",
3849
4844
  {
3850
4845
  onClick: () => setLocalSettings({ ...localSettings, drawerSide: "right" }),
@@ -3854,24 +4849,24 @@ function ChatBubbleSettingsModal({
3854
4849
  )
3855
4850
  ] })
3856
4851
  ] }),
3857
- /* @__PURE__ */ jsx15("div", { className: `border-t ${isDark ? "border-gray-700" : "border-gray-200"} my-2` }),
3858
- /* @__PURE__ */ jsxs9("div", { className: "mb-3", children: [
3859
- /* @__PURE__ */ jsx15("h3", { className: "text-lg font-semibold mb-1", children: "Voice Control" }),
3860
- /* @__PURE__ */ jsx15("p", { className: `text-xs ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Enable voice input and audio feedback" })
4852
+ /* @__PURE__ */ jsx18("div", { className: `border-t ${isDark ? "border-gray-700" : "border-gray-200"} my-2` }),
4853
+ /* @__PURE__ */ jsxs11("div", { className: "mb-3", children: [
4854
+ /* @__PURE__ */ jsx18("h3", { className: "text-lg font-semibold mb-1", children: "Voice Control" }),
4855
+ /* @__PURE__ */ jsx18("p", { className: `text-xs ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Enable voice input and audio feedback" })
3861
4856
  ] }),
3862
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
3863
- /* @__PURE__ */ jsxs9("div", { children: [
3864
- /* @__PURE__ */ jsx15("label", { className: "block text-base font-medium mb-1", children: "Voice Control" }),
3865
- /* @__PURE__ */ jsx15("p", { className: `text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Enable voice input and TTS responses" })
4857
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
4858
+ /* @__PURE__ */ jsxs11("div", { children: [
4859
+ /* @__PURE__ */ jsx18("label", { className: "block text-base font-medium mb-1", children: "Voice Control" }),
4860
+ /* @__PURE__ */ jsx18("p", { className: `text-sm ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Enable voice input and TTS responses" })
3866
4861
  ] }),
3867
- /* @__PURE__ */ jsx15(
4862
+ /* @__PURE__ */ jsx18(
3868
4863
  "button",
3869
4864
  {
3870
4865
  onClick: () => setLocalSettings({ ...localSettings, voiceEnabled: !localSettings.voiceEnabled }),
3871
4866
  className: `relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${localSettings.voiceEnabled ? "bg-blue-600" : isDark ? "bg-gray-700" : "bg-gray-300"}`,
3872
4867
  role: "switch",
3873
4868
  "aria-checked": localSettings.voiceEnabled,
3874
- children: /* @__PURE__ */ jsx15(
4869
+ children: /* @__PURE__ */ jsx18(
3875
4870
  "span",
3876
4871
  {
3877
4872
  className: `inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${localSettings.voiceEnabled ? "translate-x-6" : "translate-x-1"}`
@@ -3880,20 +4875,20 @@ function ChatBubbleSettingsModal({
3880
4875
  }
3881
4876
  )
3882
4877
  ] }),
3883
- localSettings.voiceEnabled && /* @__PURE__ */ jsxs9(Fragment5, { children: [
3884
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between pl-4 border-l-2 border-blue-500/30", children: [
3885
- /* @__PURE__ */ jsxs9("div", { children: [
3886
- /* @__PURE__ */ jsx15("label", { className: "block text-sm font-medium mb-1", children: "Auto-read AI Responses" }),
3887
- /* @__PURE__ */ jsx15("p", { className: `text-xs ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Automatically read AI messages aloud" })
4878
+ localSettings.voiceEnabled && /* @__PURE__ */ jsxs11(Fragment5, { children: [
4879
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between pl-4 border-l-2 border-blue-500/30", children: [
4880
+ /* @__PURE__ */ jsxs11("div", { children: [
4881
+ /* @__PURE__ */ jsx18("label", { className: "block text-sm font-medium mb-1", children: "Auto-read AI Responses" }),
4882
+ /* @__PURE__ */ jsx18("p", { className: `text-xs ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Automatically read AI messages aloud" })
3888
4883
  ] }),
3889
- /* @__PURE__ */ jsx15(
4884
+ /* @__PURE__ */ jsx18(
3890
4885
  "button",
3891
4886
  {
3892
4887
  onClick: () => setLocalSettings({ ...localSettings, autoReadResponses: !localSettings.autoReadResponses }),
3893
4888
  className: `relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${localSettings.autoReadResponses ? "bg-blue-600" : isDark ? "bg-gray-700" : "bg-gray-300"}`,
3894
4889
  role: "switch",
3895
4890
  "aria-checked": localSettings.autoReadResponses,
3896
- children: /* @__PURE__ */ jsx15(
4891
+ children: /* @__PURE__ */ jsx18(
3897
4892
  "span",
3898
4893
  {
3899
4894
  className: `inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${localSettings.autoReadResponses ? "translate-x-6" : "translate-x-1"}`
@@ -3902,19 +4897,19 @@ function ChatBubbleSettingsModal({
3902
4897
  }
3903
4898
  )
3904
4899
  ] }),
3905
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between pl-4 border-l-2 border-blue-500/30", children: [
3906
- /* @__PURE__ */ jsxs9("div", { children: [
3907
- /* @__PURE__ */ jsx15("label", { className: "block text-sm font-medium mb-1", children: "Premium Voices \u{1F48E}" }),
3908
- /* @__PURE__ */ jsx15("p", { className: `text-xs ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Use high-quality OpenAI voices (requires network)" })
4900
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between pl-4 border-l-2 border-blue-500/30", children: [
4901
+ /* @__PURE__ */ jsxs11("div", { children: [
4902
+ /* @__PURE__ */ jsx18("label", { className: "block text-sm font-medium mb-1", children: "Premium Voices \u{1F48E}" }),
4903
+ /* @__PURE__ */ jsx18("p", { className: `text-xs ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Use high-quality OpenAI voices (requires network)" })
3909
4904
  ] }),
3910
- /* @__PURE__ */ jsx15(
4905
+ /* @__PURE__ */ jsx18(
3911
4906
  "button",
3912
4907
  {
3913
4908
  onClick: () => setLocalSettings({ ...localSettings, usePremiumVoices: !localSettings.usePremiumVoices }),
3914
4909
  className: `relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${localSettings.usePremiumVoices ? "bg-blue-600" : isDark ? "bg-gray-700" : "bg-gray-300"}`,
3915
4910
  role: "switch",
3916
4911
  "aria-checked": localSettings.usePremiumVoices,
3917
- children: /* @__PURE__ */ jsx15(
4912
+ children: /* @__PURE__ */ jsx18(
3918
4913
  "span",
3919
4914
  {
3920
4915
  className: `inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${localSettings.usePremiumVoices ? "translate-x-6" : "translate-x-1"}`
@@ -3923,13 +4918,13 @@ function ChatBubbleSettingsModal({
3923
4918
  }
3924
4919
  )
3925
4920
  ] }),
3926
- /* @__PURE__ */ jsxs9("div", { className: "pl-4 border-l-2 border-blue-500/30", children: [
3927
- /* @__PURE__ */ jsxs9("label", { className: "block text-sm font-medium mb-2", children: [
4921
+ /* @__PURE__ */ jsxs11("div", { className: "pl-4 border-l-2 border-blue-500/30", children: [
4922
+ /* @__PURE__ */ jsxs11("label", { className: "block text-sm font-medium mb-2", children: [
3928
4923
  "Voice Speed: ",
3929
4924
  localSettings.ttsSpeed.toFixed(1),
3930
4925
  "x"
3931
4926
  ] }),
3932
- /* @__PURE__ */ jsx15(
4927
+ /* @__PURE__ */ jsx18(
3933
4928
  "input",
3934
4929
  {
3935
4930
  type: "range",
@@ -3941,30 +4936,30 @@ function ChatBubbleSettingsModal({
3941
4936
  className: "w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer accent-blue-600"
3942
4937
  }
3943
4938
  ),
3944
- /* @__PURE__ */ jsxs9("div", { className: "flex justify-between text-xs text-gray-400 mt-1", children: [
3945
- /* @__PURE__ */ jsx15("span", { children: "0.5x (Slow)" }),
3946
- /* @__PURE__ */ jsx15("span", { children: "1.0x (Normal)" }),
3947
- /* @__PURE__ */ jsx15("span", { children: "2.0x (Fast)" })
4939
+ /* @__PURE__ */ jsxs11("div", { className: "flex justify-between text-xs text-gray-400 mt-1", children: [
4940
+ /* @__PURE__ */ jsx18("span", { children: "0.5x (Slow)" }),
4941
+ /* @__PURE__ */ jsx18("span", { children: "1.0x (Normal)" }),
4942
+ /* @__PURE__ */ jsx18("span", { children: "2.0x (Fast)" })
3948
4943
  ] })
3949
4944
  ] }),
3950
- /* @__PURE__ */ jsx15("div", { className: `border-t ${isDark ? "border-gray-700" : "border-gray-200"} my-2` }),
3951
- /* @__PURE__ */ jsxs9("div", { className: "mb-3", children: [
3952
- /* @__PURE__ */ jsx15("h4", { className: "text-sm font-semibold mb-1", children: "Voice Quick Record (Ctrl+/)" }),
3953
- /* @__PURE__ */ jsx15("p", { className: `text-xs ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Press Ctrl+/ (or Cmd+/ on Mac) to auto-record and execute voice commands" })
4945
+ /* @__PURE__ */ jsx18("div", { className: `border-t ${isDark ? "border-gray-700" : "border-gray-200"} my-2` }),
4946
+ /* @__PURE__ */ jsxs11("div", { className: "mb-3", children: [
4947
+ /* @__PURE__ */ jsx18("h4", { className: "text-sm font-semibold mb-1", children: "Voice Quick Record (Ctrl+/)" }),
4948
+ /* @__PURE__ */ jsx18("p", { className: `text-xs ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Press Ctrl+/ (or Cmd+/ on Mac) to auto-record and execute voice commands" })
3954
4949
  ] }),
3955
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between pl-4 border-l-2 border-purple-500/30", children: [
3956
- /* @__PURE__ */ jsxs9("div", { children: [
3957
- /* @__PURE__ */ jsx15("label", { className: "block text-sm font-medium mb-1", children: "Auto-Execute Commands" }),
3958
- /* @__PURE__ */ jsx15("p", { className: `text-xs ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Automatically run recognized voice commands" })
4950
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between pl-4 border-l-2 border-purple-500/30", children: [
4951
+ /* @__PURE__ */ jsxs11("div", { children: [
4952
+ /* @__PURE__ */ jsx18("label", { className: "block text-sm font-medium mb-1", children: "Auto-Execute Commands" }),
4953
+ /* @__PURE__ */ jsx18("p", { className: `text-xs ${isDark ? "text-gray-400" : "text-gray-500"}`, children: "Automatically run recognized voice commands" })
3959
4954
  ] }),
3960
- /* @__PURE__ */ jsx15(
4955
+ /* @__PURE__ */ jsx18(
3961
4956
  "button",
3962
4957
  {
3963
4958
  onClick: () => setLocalSettings({ ...localSettings, sttAutoExecute: !localSettings.sttAutoExecute }),
3964
4959
  className: `relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${localSettings.sttAutoExecute ? "bg-purple-600" : isDark ? "bg-gray-700" : "bg-gray-300"}`,
3965
4960
  role: "switch",
3966
4961
  "aria-checked": localSettings.sttAutoExecute,
3967
- children: /* @__PURE__ */ jsx15(
4962
+ children: /* @__PURE__ */ jsx18(
3968
4963
  "span",
3969
4964
  {
3970
4965
  className: `inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${localSettings.sttAutoExecute ? "translate-x-6" : "translate-x-1"}`
@@ -3973,13 +4968,13 @@ function ChatBubbleSettingsModal({
3973
4968
  }
3974
4969
  )
3975
4970
  ] }),
3976
- /* @__PURE__ */ jsxs9("div", { className: "pl-4 border-l-2 border-purple-500/30", children: [
3977
- /* @__PURE__ */ jsxs9("label", { className: "block text-sm font-medium mb-2", children: [
4971
+ /* @__PURE__ */ jsxs11("div", { className: "pl-4 border-l-2 border-purple-500/30", children: [
4972
+ /* @__PURE__ */ jsxs11("label", { className: "block text-sm font-medium mb-2", children: [
3978
4973
  "Recording Timeout: ",
3979
4974
  (localSettings.sttAutoRecordTimeout / 1e3).toFixed(1),
3980
4975
  "s"
3981
4976
  ] }),
3982
- /* @__PURE__ */ jsx15(
4977
+ /* @__PURE__ */ jsx18(
3983
4978
  "input",
3984
4979
  {
3985
4980
  type: "range",
@@ -3991,22 +4986,22 @@ function ChatBubbleSettingsModal({
3991
4986
  className: "w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer accent-purple-600"
3992
4987
  }
3993
4988
  ),
3994
- /* @__PURE__ */ jsxs9("div", { className: "flex justify-between text-xs text-gray-400 mt-1", children: [
3995
- /* @__PURE__ */ jsx15("span", { children: "2s" }),
3996
- /* @__PURE__ */ jsx15("span", { children: "8s" }),
3997
- /* @__PURE__ */ jsx15("span", { children: "15s" })
4989
+ /* @__PURE__ */ jsxs11("div", { className: "flex justify-between text-xs text-gray-400 mt-1", children: [
4990
+ /* @__PURE__ */ jsx18("span", { children: "2s" }),
4991
+ /* @__PURE__ */ jsx18("span", { children: "8s" }),
4992
+ /* @__PURE__ */ jsx18("span", { children: "15s" })
3998
4993
  ] })
3999
4994
  ] }),
4000
- /* @__PURE__ */ jsxs9("div", { className: `p-3 rounded-lg ${isDark ? "bg-purple-900/20 border border-purple-500/30" : "bg-purple-50 border border-purple-200"}`, children: [
4001
- /* @__PURE__ */ jsx15("p", { className: `text-xs ${isDark ? "text-purple-300" : "text-purple-800"} mb-1 font-medium`, children: "\u26A1 Quick Tip: Press Ctrl+/ anywhere (even while typing!)" }),
4002
- /* @__PURE__ */ jsx15("p", { className: `text-xs ${isDark ? "text-purple-400" : "text-purple-700"}`, children: localSettings.sttAutoExecute ? "Recording auto-stops and executes your command" : "Recording auto-stops and fills the input (press Enter to send)" })
4995
+ /* @__PURE__ */ jsxs11("div", { className: `p-3 rounded-lg ${isDark ? "bg-purple-900/20 border border-purple-500/30" : "bg-purple-50 border border-purple-200"}`, children: [
4996
+ /* @__PURE__ */ jsx18("p", { className: `text-xs ${isDark ? "text-purple-300" : "text-purple-800"} mb-1 font-medium`, children: "\u26A1 Quick Tip: Press Ctrl+/ anywhere (even while typing!)" }),
4997
+ /* @__PURE__ */ jsx18("p", { className: `text-xs ${isDark ? "text-purple-400" : "text-purple-700"}`, children: localSettings.sttAutoExecute ? "Recording auto-stops and executes your command" : "Recording auto-stops and fills the input (press Enter to send)" })
4003
4998
  ] }),
4004
- !localSettings.usePremiumVoices && /* @__PURE__ */ jsx15("div", { className: `p-3 rounded-lg ${isDark ? "bg-green-900/20 border border-green-500/30" : "bg-green-50 border border-green-200"}`, children: /* @__PURE__ */ jsx15("p", { className: `text-xs ${isDark ? "text-green-300" : "text-green-800"}`, children: "\u{1F49A} Using free device voices (works offline, zero cost)" }) }),
4005
- localSettings.usePremiumVoices && /* @__PURE__ */ jsx15("div", { className: `p-3 rounded-lg ${isDark ? "bg-purple-900/20 border border-purple-500/30" : "bg-purple-50 border border-purple-200"}`, children: /* @__PURE__ */ jsx15("p", { className: `text-xs ${isDark ? "text-purple-300" : "text-purple-800"}`, children: "\u{1F48E} Using premium OpenAI voices (requires internet connection)" }) })
4999
+ !localSettings.usePremiumVoices && /* @__PURE__ */ jsx18("div", { className: `p-3 rounded-lg ${isDark ? "bg-green-900/20 border border-green-500/30" : "bg-green-50 border border-green-200"}`, children: /* @__PURE__ */ jsx18("p", { className: `text-xs ${isDark ? "text-green-300" : "text-green-800"}`, children: "\u{1F49A} Using free device voices (works offline, zero cost)" }) }),
5000
+ localSettings.usePremiumVoices && /* @__PURE__ */ jsx18("div", { className: `p-3 rounded-lg ${isDark ? "bg-purple-900/20 border border-purple-500/30" : "bg-purple-50 border border-purple-200"}`, children: /* @__PURE__ */ jsx18("p", { className: `text-xs ${isDark ? "text-purple-300" : "text-purple-800"}`, children: "\u{1F48E} Using premium OpenAI voices (requires internet connection)" }) })
4006
5001
  ] })
4007
5002
  ] }),
4008
- /* @__PURE__ */ jsxs9("div", { className: "flex justify-end space-x-3 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
4009
- /* @__PURE__ */ jsx15(
5003
+ /* @__PURE__ */ jsxs11("div", { className: "flex justify-end space-x-3 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
5004
+ /* @__PURE__ */ jsx18(
4010
5005
  "button",
4011
5006
  {
4012
5007
  onClick: handleCancel,
@@ -4014,7 +5009,7 @@ function ChatBubbleSettingsModal({
4014
5009
  children: "Cancel"
4015
5010
  }
4016
5011
  ),
4017
- /* @__PURE__ */ jsx15(
5012
+ /* @__PURE__ */ jsx18(
4018
5013
  "button",
4019
5014
  {
4020
5015
  onClick: handleSave,
@@ -4167,6 +5162,8 @@ export {
4167
5162
  SubtitleOverlay,
4168
5163
  SupernalProvider,
4169
5164
  ToolManager,
5165
+ ToolMenuPopup,
5166
+ ToolMenuPopupTrigger,
4170
5167
  findBestMatch,
4171
5168
  scoreToolMatch,
4172
5169
  useAllContexts,
@@ -4176,5 +5173,6 @@ export {
4176
5173
  useNavigate,
4177
5174
  useNavigationGraph,
4178
5175
  useNavigationPath,
4179
- useRegisterTool
5176
+ useRegisterTool,
5177
+ useToolMenu
4180
5178
  };