@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.d.mts +38 -1
- package/dist/index.d.ts +38 -1
- package/dist/index.js +1538 -543
- package/dist/index.mjs +1535 -537
- package/package.json +1 -1
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
|
|
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
|
|
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(
|
|
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(
|
|
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: "
|
|
1298
|
-
{ text: "
|
|
1299
|
-
{ text: "
|
|
1300
|
-
{ text: "
|
|
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:
|
|
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
|
|
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
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
1462
|
-
//
|
|
1463
|
-
listening: 0.
|
|
1464
|
-
|
|
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(
|
|
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.
|
|
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
|
-
|
|
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"
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
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
|
-
|
|
2076
|
+
!isMobile && /* @__PURE__ */ jsx10(
|
|
1859
2077
|
"div",
|
|
1860
2078
|
{
|
|
1861
|
-
className:
|
|
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
|
-
|
|
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
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
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
|
-
|
|
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() &&
|
|
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
|
|
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__ */
|
|
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] =
|
|
2026
|
-
const [isMinimized, setIsMinimized] =
|
|
2027
|
-
const [inputValue, setInputValue] =
|
|
2028
|
-
const [lastReadMessageCount, setLastReadMessageCount] =
|
|
2029
|
-
const [showWelcome, setShowWelcome] =
|
|
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] =
|
|
2033
|
-
const [dragInitiated, setDragInitiated] =
|
|
2034
|
-
const [isDocked, setIsDocked] =
|
|
2035
|
-
const [dockPosition, setDockPosition] =
|
|
2036
|
-
const [panelPosition, setPanelPosition] =
|
|
2037
|
-
const [theme, setTheme] =
|
|
2038
|
-
const [showMoreMenu, setShowMoreMenu] =
|
|
2039
|
-
const [, setTimestampTick] =
|
|
2040
|
-
const [localGlassMode, setLocalGlassMode] =
|
|
2041
|
-
const [glassOpacity, setGlassOpacity] =
|
|
2042
|
-
const [notifications, setNotifications] =
|
|
2043
|
-
const [voiceEnabled, setVoiceEnabled] =
|
|
2044
|
-
const [usePremiumVoices, setUsePremiumVoices] =
|
|
2045
|
-
const [autoReadResponses, setAutoReadResponses] =
|
|
2046
|
-
const [ttsSpeed, setTtsSpeed] =
|
|
2047
|
-
const [sttAutoRecordTimeout, setSttAutoRecordTimeout] =
|
|
2048
|
-
const [sttAutoExecute, setSttAutoExecute] =
|
|
2049
|
-
const sttAutoRecordTimeoutRef =
|
|
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
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
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] =
|
|
2058
|
-
const [touchStart, setTouchStart] =
|
|
2059
|
-
const [swipeProgress, setSwipeProgress] =
|
|
2060
|
-
const [isMobile, setIsMobile] =
|
|
2061
|
-
const
|
|
2062
|
-
const
|
|
2063
|
-
const [
|
|
2064
|
-
|
|
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 =
|
|
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
|
-
|
|
2583
|
+
useEffect7(() => {
|
|
2081
2584
|
setCurrentHintIndex((prev) => (prev + 1) % inputHints.length);
|
|
2082
2585
|
}, [messages.length, inputHints.length]);
|
|
2083
|
-
const messagesEndRef =
|
|
2084
|
-
const inputRef =
|
|
2085
|
-
const panelRef =
|
|
2086
|
-
const dragRef =
|
|
2087
|
-
const rafRef =
|
|
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
|
-
|
|
2103
|
-
if (variant === "
|
|
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
|
-
|
|
2180
|
-
if (variant !== "full") {
|
|
2705
|
+
useEffect7(() => {
|
|
2706
|
+
if (variant !== "full" && variant !== "drawer" && variant !== "subtitle") {
|
|
2181
2707
|
setIsHydrated(true);
|
|
2182
2708
|
}
|
|
2183
2709
|
}, [variant]);
|
|
2184
|
-
|
|
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
|
-
|
|
2727
|
+
useEffect7(() => {
|
|
2728
|
+
const isSubtitleMode = displayMode === "subtitle" || displayMode === "auto" && variant === "subtitle";
|
|
2729
|
+
if (isSubtitleMode) return;
|
|
2202
2730
|
const handleKeyDown = (e) => {
|
|
2203
|
-
if (e.key
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
2776
|
+
const currentVariant = React8.useMemo(() => {
|
|
2230
2777
|
if (displayMode !== "auto") {
|
|
2231
2778
|
return displayMode;
|
|
2232
2779
|
}
|
|
2233
|
-
return isMobile ? "
|
|
2780
|
+
return isMobile && variant === "full" ? "subtitle" : variant;
|
|
2234
2781
|
}, [displayMode, isMobile, variant]);
|
|
2235
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2856
|
+
useEffect7(() => {
|
|
2303
2857
|
if (isExpanded && variant === "full") {
|
|
2304
2858
|
inputRef.current?.focus();
|
|
2305
2859
|
}
|
|
2306
2860
|
}, [isExpanded, variant]);
|
|
2307
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
2391
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
2478
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
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__ */
|
|
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__ */
|
|
2736
|
-
(drawerOpen || swipeProgress > 0) && /* @__PURE__ */
|
|
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-[
|
|
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
|
-
//
|
|
3255
|
+
// Super high z-index for overlay backdrop
|
|
2744
3256
|
},
|
|
2745
3257
|
onClick: () => setDrawerOpen(false)
|
|
2746
3258
|
}
|
|
2747
3259
|
),
|
|
2748
|
-
/* @__PURE__ */
|
|
3260
|
+
/* @__PURE__ */ jsxs8(
|
|
2749
3261
|
"div",
|
|
2750
3262
|
{
|
|
2751
|
-
className: `fixed ${drawerSide === "right" ? "right-0" : "left-0"} top-0 h-full z-[
|
|
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
|
-
//
|
|
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__ */
|
|
2768
|
-
/* @__PURE__ */
|
|
2769
|
-
config.avatar && /* @__PURE__ */
|
|
2770
|
-
/* @__PURE__ */
|
|
2771
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2778
|
-
showWelcome && messages.length === 0 && config.welcome?.enabled && /* @__PURE__ */
|
|
2779
|
-
config.welcome.title && /* @__PURE__ */
|
|
2780
|
-
config.welcome.content && /* @__PURE__ */
|
|
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__ */
|
|
2783
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3300
|
+
children: /* @__PURE__ */ jsx12(MessageRenderer, { content: message.text, theme })
|
|
2789
3301
|
}
|
|
2790
3302
|
),
|
|
2791
|
-
message.type === "ai" && voiceEnabled && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3322
|
+
/* @__PURE__ */ jsx12("div", { ref: messagesEndRef })
|
|
2811
3323
|
] }),
|
|
2812
|
-
/* @__PURE__ */
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
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__ */
|
|
3356
|
+
!drawerOpen && /* @__PURE__ */ jsx12(
|
|
2833
3357
|
"div",
|
|
2834
3358
|
{
|
|
2835
|
-
className: `fixed ${drawerSide === "right" ? "right-0" : "left-0"} bottom-20 opacity-
|
|
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__ */
|
|
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 (
|
|
3367
|
+
if (currentVariant === "floating") {
|
|
2844
3368
|
const recentMessage = messages[messages.length - 1];
|
|
2845
|
-
return /* @__PURE__ */
|
|
3369
|
+
return /* @__PURE__ */ jsx12(
|
|
2846
3370
|
"div",
|
|
2847
3371
|
{
|
|
2848
|
-
className: `fixed z-[
|
|
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
|
-
//
|
|
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__ */
|
|
2857
|
-
/* @__PURE__ */
|
|
2858
|
-
/* @__PURE__ */
|
|
2859
|
-
/* @__PURE__ */
|
|
2860
|
-
config.title && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2874
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
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__ */
|
|
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:
|
|
2915
|
-
//
|
|
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__ */
|
|
3464
|
+
isExpanded && isMinimized && /* @__PURE__ */ jsxs8(
|
|
2927
3465
|
"div",
|
|
2928
3466
|
{
|
|
2929
3467
|
ref: panelRef,
|
|
2930
|
-
className: `${isDocked ? "absolute" : "fixed z-[
|
|
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
|
-
//
|
|
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__ */
|
|
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__ */
|
|
2961
|
-
config.avatar && /* @__PURE__ */
|
|
2962
|
-
/* @__PURE__ */
|
|
2963
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2968
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
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__ */
|
|
3569
|
+
isExpanded && !isMinimized && /* @__PURE__ */ jsxs8(
|
|
3020
3570
|
"div",
|
|
3021
3571
|
{
|
|
3022
3572
|
ref: panelRef,
|
|
3023
|
-
className: `${isDocked ? "absolute" : "fixed z-[
|
|
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
|
-
//
|
|
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__ */
|
|
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__ */
|
|
3045
|
-
config.avatar && /* @__PURE__ */
|
|
3046
|
-
/* @__PURE__ */
|
|
3047
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3052
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3073
|
-
/* @__PURE__ */
|
|
3074
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3105
|
-
/* @__PURE__ */
|
|
3106
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3120
|
-
/* @__PURE__ */
|
|
3121
|
-
/* @__PURE__ */
|
|
3122
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3140
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3159
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3176
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3197
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3211
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3239
|
-
showWelcome && messages.length === 0 && config.welcome?.enabled && /* @__PURE__ */
|
|
3240
|
-
config.welcome.title && /* @__PURE__ */
|
|
3241
|
-
config.welcome.content && /* @__PURE__ */
|
|
3242
|
-
config.welcome.suggestedCommands && config.welcome.suggestedCommands.length > 0 && /* @__PURE__ */
|
|
3243
|
-
/* @__PURE__ */
|
|
3244
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3267
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3823
|
+
children: /* @__PURE__ */ jsx12(MessageRenderer, { content: message.text, theme })
|
|
3274
3824
|
}
|
|
3275
3825
|
),
|
|
3276
|
-
message.type === "ai" && voiceEnabled && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3845
|
+
/* @__PURE__ */ jsx12("div", { ref: messagesEndRef })
|
|
3296
3846
|
] }),
|
|
3297
|
-
/* @__PURE__ */
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
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__ */
|
|
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__ */
|
|
3326
|
-
hasUnread && notifications && /* @__PURE__ */
|
|
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
|
|
3898
|
+
import { useEffect as useEffect9, useState as useState10 } from "react";
|
|
3337
3899
|
|
|
3338
3900
|
// src/hooks/useNavigationGraph.tsx
|
|
3339
|
-
import { useEffect as
|
|
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
|
|
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
|
-
|
|
3912
|
+
useEffect8(() => {
|
|
3351
3913
|
graph.setCurrentContext(value);
|
|
3352
3914
|
}, [value, graph]);
|
|
3353
|
-
return /* @__PURE__ */
|
|
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] =
|
|
3362
|
-
|
|
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
|
-
|
|
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] =
|
|
3391
|
-
const [loading, setLoading] =
|
|
3392
|
-
const [error, setError] =
|
|
3393
|
-
|
|
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] =
|
|
3422
|
-
const [error, setError] =
|
|
3423
|
-
const navigateTo =
|
|
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] =
|
|
3466
|
-
|
|
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
|
|
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] =
|
|
3483
|
-
|
|
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
|
-
|
|
4051
|
+
useEffect9(() => {
|
|
3490
4052
|
if (onNavigate && context) {
|
|
3491
4053
|
onNavigate(context);
|
|
3492
4054
|
}
|
|
3493
4055
|
}, [context, onNavigate]);
|
|
3494
4056
|
if (!context) {
|
|
3495
|
-
return /* @__PURE__ */
|
|
4057
|
+
return /* @__PURE__ */ jsx14(Fragment4, { children });
|
|
3496
4058
|
}
|
|
3497
|
-
return /* @__PURE__ */
|
|
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
|
-
|
|
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__ */
|
|
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
|
-
|
|
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 =
|
|
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__ */
|
|
3615
|
-
/* @__PURE__ */
|
|
3616
|
-
shouldRenderChatBubble ? /* @__PURE__ */
|
|
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
|
|
3634
|
-
import { Fragment as Fragment5, jsx as
|
|
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] =
|
|
3642
|
-
|
|
4636
|
+
const [localSettings, setLocalSettings] = React14.useState(settings);
|
|
4637
|
+
useEffect15(() => {
|
|
3643
4638
|
if (isOpen) {
|
|
3644
4639
|
setLocalSettings(settings);
|
|
3645
4640
|
}
|
|
3646
4641
|
}, [isOpen, settings]);
|
|
3647
|
-
|
|
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__ */
|
|
3669
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3692
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3711
|
-
/* @__PURE__ */
|
|
3712
|
-
/* @__PURE__ */
|
|
3713
|
-
/* @__PURE__ */
|
|
3714
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3717
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3738
|
-
/* @__PURE__ */
|
|
3739
|
-
/* @__PURE__ */
|
|
3740
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3759
|
-
/* @__PURE__ */
|
|
3760
|
-
/* @__PURE__ */
|
|
3761
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3780
|
-
/* @__PURE__ */
|
|
3781
|
-
/* @__PURE__ */
|
|
3782
|
-
/* @__PURE__ */
|
|
3783
|
-
/* @__PURE__ */
|
|
3784
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3810
|
-
/* @__PURE__ */
|
|
3811
|
-
/* @__PURE__ */
|
|
3812
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3825
|
-
/* @__PURE__ */
|
|
3826
|
-
/* @__PURE__ */
|
|
3827
|
-
/* @__PURE__ */
|
|
3828
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3834
|
-
/* @__PURE__ */
|
|
3835
|
-
/* @__PURE__ */
|
|
3836
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3839
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3858
|
-
/* @__PURE__ */
|
|
3859
|
-
/* @__PURE__ */
|
|
3860
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3863
|
-
/* @__PURE__ */
|
|
3864
|
-
/* @__PURE__ */
|
|
3865
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3884
|
-
/* @__PURE__ */
|
|
3885
|
-
/* @__PURE__ */
|
|
3886
|
-
/* @__PURE__ */
|
|
3887
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3906
|
-
/* @__PURE__ */
|
|
3907
|
-
/* @__PURE__ */
|
|
3908
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3927
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3945
|
-
/* @__PURE__ */
|
|
3946
|
-
/* @__PURE__ */
|
|
3947
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3951
|
-
/* @__PURE__ */
|
|
3952
|
-
/* @__PURE__ */
|
|
3953
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3956
|
-
/* @__PURE__ */
|
|
3957
|
-
/* @__PURE__ */
|
|
3958
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3977
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3995
|
-
/* @__PURE__ */
|
|
3996
|
-
/* @__PURE__ */
|
|
3997
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4001
|
-
/* @__PURE__ */
|
|
4002
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4005
|
-
localSettings.usePremiumVoices && /* @__PURE__ */
|
|
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__ */
|
|
4009
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
};
|