@unctad-ai/voice-agent-ui 5.0.0 → 5.0.2
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/{VoiceSettingsView-AMFLQL3Z.js → VoiceSettingsView-GDVOO6A3.js} +2 -2
- package/dist/{chunk-SRZ6RHED.js → chunk-342HTDVN.js} +2 -2
- package/dist/index.js +93 -26
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- /package/dist/{VoiceSettingsView-AMFLQL3Z.js.map → VoiceSettingsView-GDVOO6A3.js.map} +0 -0
- /package/dist/{chunk-SRZ6RHED.js.map → chunk-342HTDVN.js.map} +0 -0
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
SliderSetting,
|
|
6
6
|
ToggleSetting,
|
|
7
7
|
VoiceSettingsView
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-342HTDVN.js";
|
|
9
9
|
export {
|
|
10
10
|
Divider,
|
|
11
11
|
SelectSetting,
|
|
@@ -14,4 +14,4 @@ export {
|
|
|
14
14
|
ToggleSetting,
|
|
15
15
|
VoiceSettingsView as default
|
|
16
16
|
};
|
|
17
|
-
//# sourceMappingURL=VoiceSettingsView-
|
|
17
|
+
//# sourceMappingURL=VoiceSettingsView-GDVOO6A3.js.map
|
|
@@ -1505,7 +1505,7 @@ function VoiceSettingsView({ onBack, onVolumeChange }) {
|
|
|
1505
1505
|
) : /* @__PURE__ */ jsx3("span", {}),
|
|
1506
1506
|
/* @__PURE__ */ jsxs2("span", { children: [
|
|
1507
1507
|
"Kit v",
|
|
1508
|
-
/* @__PURE__ */ jsx3("span", { style: { fontWeight: 500, color: "#6b7280" }, children: "5.0.
|
|
1508
|
+
/* @__PURE__ */ jsx3("span", { style: { fontWeight: 500, color: "#6b7280" }, children: "5.0.2" })
|
|
1509
1509
|
] })
|
|
1510
1510
|
] }) })
|
|
1511
1511
|
]
|
|
@@ -1597,4 +1597,4 @@ export {
|
|
|
1597
1597
|
SettingsSection,
|
|
1598
1598
|
Divider
|
|
1599
1599
|
};
|
|
1600
|
-
//# sourceMappingURL=chunk-
|
|
1600
|
+
//# sourceMappingURL=chunk-342HTDVN.js.map
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
VoiceSettingsProvider,
|
|
9
9
|
VoiceSettingsView,
|
|
10
10
|
useVoiceSettings
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-342HTDVN.js";
|
|
12
12
|
|
|
13
13
|
// src/VoiceAgentProvider.tsx
|
|
14
14
|
import { SiteConfigProvider } from "@unctad-ai/voice-agent-core";
|
|
@@ -1665,7 +1665,9 @@ function PipelineMetricsBar({
|
|
|
1665
1665
|
|
|
1666
1666
|
// src/components/GlassCopilotPanel.tsx
|
|
1667
1667
|
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1668
|
-
var VoiceSettingsView2 = lazy(() => import("./VoiceSettingsView-
|
|
1668
|
+
var VoiceSettingsView2 = lazy(() => import("./VoiceSettingsView-GDVOO6A3.js"));
|
|
1669
|
+
var RETRY_INITIAL_MS = 3e3;
|
|
1670
|
+
var RETRY_MAX_MS = 3e4;
|
|
1669
1671
|
var STATE_LABELS = {
|
|
1670
1672
|
IDLE: "Tap mic to speak",
|
|
1671
1673
|
LISTENING: "Listening...",
|
|
@@ -1680,7 +1682,7 @@ var ARIA_LIVE_LABELS = {
|
|
|
1680
1682
|
speaking: "Playing response",
|
|
1681
1683
|
error: "An error occurred"
|
|
1682
1684
|
};
|
|
1683
|
-
function CopilotFAB({ onClick, portraitSrc }) {
|
|
1685
|
+
function CopilotFAB({ onClick, portraitSrc, isOffline = false }) {
|
|
1684
1686
|
const { colors } = useSiteConfig4();
|
|
1685
1687
|
return /* @__PURE__ */ jsx9(
|
|
1686
1688
|
motion5.button,
|
|
@@ -1699,7 +1701,7 @@ function CopilotFAB({ onClick, portraitSrc }) {
|
|
|
1699
1701
|
},
|
|
1700
1702
|
"aria-label": "Open voice assistant",
|
|
1701
1703
|
"data-testid": "voice-agent-fab",
|
|
1702
|
-
children: /* @__PURE__ */ jsx9("div", { className: "agent-fab-border", style: { width: 54, height: 54, "--agent-primary": colors.primary }, children: /* @__PURE__ */ jsx9("div", { className: "agent-fab-border-inner", children: portraitSrc ? /* @__PURE__ */ jsx9(
|
|
1704
|
+
children: /* @__PURE__ */ jsx9("div", { className: "agent-fab-border", style: { width: 54, height: 54, "--agent-primary": isOffline ? "#9ca3af" : colors.primary, animation: isOffline ? "none" : void 0 }, children: /* @__PURE__ */ jsx9("div", { className: "agent-fab-border-inner", children: portraitSrc ? /* @__PURE__ */ jsx9(
|
|
1703
1705
|
"img",
|
|
1704
1706
|
{
|
|
1705
1707
|
src: portraitSrc,
|
|
@@ -1736,6 +1738,7 @@ function CollapsedBar({
|
|
|
1736
1738
|
onClose,
|
|
1737
1739
|
onRetry,
|
|
1738
1740
|
isRetrying = false,
|
|
1741
|
+
retryCountdown,
|
|
1739
1742
|
voiceError,
|
|
1740
1743
|
micPaused = false,
|
|
1741
1744
|
onMicToggle,
|
|
@@ -1807,8 +1810,8 @@ function CollapsedBar({
|
|
|
1807
1810
|
letterSpacing: "0.01em"
|
|
1808
1811
|
},
|
|
1809
1812
|
children: isOffline ? /* @__PURE__ */ jsxs8("span", { className: "inline-flex items-center gap-1", children: [
|
|
1810
|
-
"Offline",
|
|
1811
|
-
onRetry && /* @__PURE__ */ jsx9(
|
|
1813
|
+
retryCountdown ? `Retrying in ${retryCountdown}s` : "Offline",
|
|
1814
|
+
onRetry && !retryCountdown && /* @__PURE__ */ jsx9(
|
|
1812
1815
|
"button",
|
|
1813
1816
|
{
|
|
1814
1817
|
onClick: (e) => {
|
|
@@ -1931,15 +1934,17 @@ function ComposerBar({
|
|
|
1931
1934
|
}, [disabled]);
|
|
1932
1935
|
useEffect6(() => {
|
|
1933
1936
|
if (mode === "text") {
|
|
1934
|
-
|
|
1937
|
+
const timer = setTimeout(() => inputRef.current?.focus(), 200);
|
|
1938
|
+
return () => clearTimeout(timer);
|
|
1935
1939
|
}
|
|
1936
1940
|
}, [mode]);
|
|
1937
1941
|
const handleSubmit = () => {
|
|
1942
|
+
if (disabled) return;
|
|
1938
1943
|
const trimmed = text.trim();
|
|
1939
1944
|
if (!trimmed) return;
|
|
1940
1945
|
onTextSubmit(trimmed);
|
|
1941
1946
|
setText("");
|
|
1942
|
-
|
|
1947
|
+
requestAnimationFrame(() => inputRef.current?.focus());
|
|
1943
1948
|
};
|
|
1944
1949
|
const handleCancel = () => {
|
|
1945
1950
|
setText("");
|
|
@@ -2062,6 +2067,7 @@ function ComposerBar({
|
|
|
2062
2067
|
type: "text",
|
|
2063
2068
|
value: text,
|
|
2064
2069
|
onChange: (e) => setText(e.target.value),
|
|
2070
|
+
disabled,
|
|
2065
2071
|
onKeyDown: (e) => {
|
|
2066
2072
|
if (e.key === "Enter") handleSubmit();
|
|
2067
2073
|
if (e.key === "Escape") handleCancel();
|
|
@@ -2080,7 +2086,7 @@ function ComposerBar({
|
|
|
2080
2086
|
pill.style.boxShadow = "none";
|
|
2081
2087
|
}
|
|
2082
2088
|
},
|
|
2083
|
-
placeholder: "Ask about services...",
|
|
2089
|
+
placeholder: disabled ? "Reconnecting..." : "Ask about services...",
|
|
2084
2090
|
"aria-label": "Type your question",
|
|
2085
2091
|
"data-testid": "voice-agent-input",
|
|
2086
2092
|
className: "w-full",
|
|
@@ -2090,7 +2096,9 @@ function ComposerBar({
|
|
|
2090
2096
|
background: "transparent",
|
|
2091
2097
|
border: "none",
|
|
2092
2098
|
outline: "none",
|
|
2093
|
-
padding: 0
|
|
2099
|
+
padding: 0,
|
|
2100
|
+
opacity: disabled ? 0.5 : 1,
|
|
2101
|
+
cursor: disabled ? "not-allowed" : void 0
|
|
2094
2102
|
}
|
|
2095
2103
|
}
|
|
2096
2104
|
)
|
|
@@ -2161,6 +2169,7 @@ function ExpandedContent({
|
|
|
2161
2169
|
onInteraction,
|
|
2162
2170
|
onRetry,
|
|
2163
2171
|
isRetrying = false,
|
|
2172
|
+
retryCountdown,
|
|
2164
2173
|
lastTimings,
|
|
2165
2174
|
showPipelineMetrics,
|
|
2166
2175
|
pipelineMetricsAutoHideMs,
|
|
@@ -2256,7 +2265,7 @@ function ExpandedContent({
|
|
|
2256
2265
|
/* @__PURE__ */ jsx9(PipelineMetricsBar, { timings: lastTimings ?? null, show: showPipelineMetrics, autoHideMs: pipelineMetricsAutoHideMs }),
|
|
2257
2266
|
isOffline && onRetry && /* @__PURE__ */ jsx9("div", { style: { padding: "0 16px 8px", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsxs8(motion5.button, { whileHover: { scale: 1.04 }, whileTap: { scale: 0.96 }, onClick: onRetry, disabled: isRetrying, className: "inline-flex items-center gap-2 rounded-full cursor-pointer transition-colors", style: { padding: "8px 18px", fontSize: "13px", fontWeight: 500, color: isRetrying ? "rgba(0,0,0,0.35)" : "rgba(220,38,38,0.8)", backgroundColor: isRetrying ? "rgba(0,0,0,0.04)" : "rgba(220,38,38,0.08)", border: "1px solid", borderColor: isRetrying ? "rgba(0,0,0,0.06)" : "rgba(220,38,38,0.15)" }, "aria-label": "Retry connection", children: [
|
|
2258
2267
|
/* @__PURE__ */ jsx9(motion5.span, { animate: isRetrying ? { rotate: 360 } : { rotate: 0 }, transition: isRetrying ? { duration: 0.8, repeat: Infinity, ease: "linear" } : { duration: 0.3 }, style: { display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsx9(RotateCw, { style: { width: 14, height: 14 } }) }),
|
|
2259
|
-
isRetrying ? "Checking..." : "Retry connection"
|
|
2268
|
+
isRetrying ? "Checking..." : retryCountdown ? `Retrying in ${retryCountdown}s...` : "Retry connection"
|
|
2260
2269
|
] }) }),
|
|
2261
2270
|
voiceError !== "network_error" && /* @__PURE__ */ jsx9("div", { style: { padding: "0 16px 8px" }, children: /* @__PURE__ */ jsx9(VoiceErrorDisplay, { error: voiceError, onDismiss: dismissError }) }),
|
|
2262
2271
|
/* @__PURE__ */ jsx9("div", { style: { padding: "0 16px 8px" }, children: /* @__PURE__ */ jsx9(VoiceToolCard, { result: toolResult, onDismiss: onToolDismiss, variant: "capsule" }) })
|
|
@@ -2344,28 +2353,70 @@ function WiredPanelInner({
|
|
|
2344
2353
|
const autoStartedRef = useRef4(false);
|
|
2345
2354
|
const pollTimerRef = useRef4(null);
|
|
2346
2355
|
const cancelledRef = useRef4(false);
|
|
2356
|
+
const [retryCountdown, setRetryCountdown] = useState5(null);
|
|
2357
|
+
const backoffDelayRef = useRef4(RETRY_INITIAL_MS);
|
|
2358
|
+
const countdownTimerRef = useRef4(null);
|
|
2359
|
+
const dismissErrorRef = useRef4(dismissError);
|
|
2360
|
+
useEffect6(() => {
|
|
2361
|
+
dismissErrorRef.current = dismissError;
|
|
2362
|
+
}, [dismissError]);
|
|
2363
|
+
const autoListenRef = useRef4(settings.autoListen);
|
|
2364
|
+
useEffect6(() => {
|
|
2365
|
+
autoListenRef.current = settings.autoListen;
|
|
2366
|
+
}, [settings.autoListen]);
|
|
2367
|
+
const clearCountdown = useCallback3(() => {
|
|
2368
|
+
if (countdownTimerRef.current) {
|
|
2369
|
+
clearInterval(countdownTimerRef.current);
|
|
2370
|
+
countdownTimerRef.current = null;
|
|
2371
|
+
}
|
|
2372
|
+
setRetryCountdown(null);
|
|
2373
|
+
}, []);
|
|
2374
|
+
const runHealthCheckRef = useRef4(() => {
|
|
2375
|
+
});
|
|
2376
|
+
const scheduleRetry = useCallback3((delayMs) => {
|
|
2377
|
+
if (pollTimerRef.current) clearTimeout(pollTimerRef.current);
|
|
2378
|
+
clearCountdown();
|
|
2379
|
+
const seconds = Math.ceil(delayMs / 1e3);
|
|
2380
|
+
setRetryCountdown(seconds);
|
|
2381
|
+
let remaining = seconds;
|
|
2382
|
+
countdownTimerRef.current = setInterval(() => {
|
|
2383
|
+
remaining -= 1;
|
|
2384
|
+
if (remaining <= 0) {
|
|
2385
|
+
clearCountdown();
|
|
2386
|
+
return;
|
|
2387
|
+
}
|
|
2388
|
+
setRetryCountdown(remaining);
|
|
2389
|
+
}, 1e3);
|
|
2390
|
+
pollTimerRef.current = setTimeout(() => runHealthCheckRef.current(), delayMs);
|
|
2391
|
+
backoffDelayRef.current = Math.min(delayMs * 2, RETRY_MAX_MS);
|
|
2392
|
+
}, [clearCountdown]);
|
|
2347
2393
|
const runHealthCheck = useCallback3(() => {
|
|
2394
|
+
clearCountdown();
|
|
2348
2395
|
checkBackendHealth().then(({ available }) => {
|
|
2349
2396
|
if (cancelledRef.current) return;
|
|
2350
2397
|
setBackendDown(!available);
|
|
2351
2398
|
if (available) {
|
|
2352
|
-
|
|
2353
|
-
|
|
2399
|
+
backoffDelayRef.current = RETRY_INITIAL_MS;
|
|
2400
|
+
dismissErrorRef.current();
|
|
2401
|
+
if (!autoStartedRef.current && autoListenRef.current) {
|
|
2354
2402
|
autoStartedRef.current = true;
|
|
2355
2403
|
startRef.current();
|
|
2356
2404
|
}
|
|
2357
2405
|
} else {
|
|
2358
|
-
|
|
2359
|
-
pollTimerRef.current = setTimeout(runHealthCheck, RECOVERY_POLL_MS);
|
|
2406
|
+
scheduleRetry(backoffDelayRef.current);
|
|
2360
2407
|
}
|
|
2361
2408
|
});
|
|
2362
|
-
}, [
|
|
2409
|
+
}, [scheduleRetry, clearCountdown]);
|
|
2410
|
+
useEffect6(() => {
|
|
2411
|
+
runHealthCheckRef.current = runHealthCheck;
|
|
2412
|
+
}, [runHealthCheck]);
|
|
2363
2413
|
useEffect6(() => {
|
|
2364
2414
|
cancelledRef.current = false;
|
|
2365
2415
|
runHealthCheck();
|
|
2366
2416
|
return () => {
|
|
2367
2417
|
cancelledRef.current = true;
|
|
2368
2418
|
if (pollTimerRef.current) clearTimeout(pollTimerRef.current);
|
|
2419
|
+
if (countdownTimerRef.current) clearInterval(countdownTimerRef.current);
|
|
2369
2420
|
};
|
|
2370
2421
|
}, [runHealthCheck]);
|
|
2371
2422
|
const onStateChangeRef = useRef4(onStateChange);
|
|
@@ -2443,23 +2494,23 @@ function WiredPanelInner({
|
|
|
2443
2494
|
const handleRetryClick = useCallback3(() => {
|
|
2444
2495
|
if (isRetrying) return;
|
|
2445
2496
|
setIsRetrying(true);
|
|
2497
|
+
backoffDelayRef.current = RETRY_INITIAL_MS;
|
|
2498
|
+
clearCountdown();
|
|
2446
2499
|
checkBackendHealth().then(({ available }) => {
|
|
2447
2500
|
if (cancelledRef.current) return;
|
|
2448
2501
|
setIsRetrying(false);
|
|
2449
2502
|
setBackendDown(!available);
|
|
2450
2503
|
if (available) {
|
|
2451
|
-
|
|
2452
|
-
if (!autoStartedRef.current &&
|
|
2504
|
+
dismissErrorRef.current();
|
|
2505
|
+
if (!autoStartedRef.current && autoListenRef.current) {
|
|
2453
2506
|
autoStartedRef.current = true;
|
|
2454
2507
|
startRef.current();
|
|
2455
2508
|
}
|
|
2456
|
-
}
|
|
2457
|
-
|
|
2458
|
-
if (pollTimerRef.current) clearTimeout(pollTimerRef.current);
|
|
2459
|
-
pollTimerRef.current = setTimeout(runHealthCheck, RECOVERY_POLL_MS);
|
|
2509
|
+
} else {
|
|
2510
|
+
scheduleRetry(backoffDelayRef.current);
|
|
2460
2511
|
}
|
|
2461
2512
|
}).catch(() => setIsRetrying(false));
|
|
2462
|
-
}, [isRetrying,
|
|
2513
|
+
}, [isRetrying, clearCountdown, scheduleRetry]);
|
|
2463
2514
|
const onExpandRef = useRef4(onExpand);
|
|
2464
2515
|
useEffect6(() => {
|
|
2465
2516
|
onExpandRef.current = onExpand;
|
|
@@ -2476,10 +2527,10 @@ function WiredPanelInner({
|
|
|
2476
2527
|
const [showSettings, setShowSettings] = useState5(false);
|
|
2477
2528
|
const toggleSettings = useCallback3(() => setShowSettings((p) => !p), []);
|
|
2478
2529
|
if (panelState === "collapsed") {
|
|
2479
|
-
return /* @__PURE__ */ jsx9(CollapsedBar, { orbState, getAmplitude, analyser, voiceState: state, onExpand, onClose, onRetry: handleRetryClick, isRetrying, voiceError: effectiveError, micPaused, onMicToggle: handleMicToggle, ttsEnabled: settings.ttsEnabled, copilotName: config.copilotName, portraitSrc: resolvedPortrait });
|
|
2530
|
+
return /* @__PURE__ */ jsx9(CollapsedBar, { orbState, getAmplitude, analyser, voiceState: state, onExpand, onClose, onRetry: handleRetryClick, isRetrying, retryCountdown, voiceError: effectiveError, micPaused, onMicToggle: handleMicToggle, ttsEnabled: settings.ttsEnabled, copilotName: config.copilotName, portraitSrc: resolvedPortrait });
|
|
2480
2531
|
}
|
|
2481
2532
|
return /* @__PURE__ */ jsxs8("div", { className: "relative h-full", children: [
|
|
2482
|
-
/* @__PURE__ */ jsx9(ExpandedContent, { orbState, getAmplitude, analyser, voiceState: state, messages, isTyping, toolResult, voiceError: effectiveError, dismissError, onCollapse, onClose, onTextSubmit: handleTextSubmit, onMicToggle: handleMicToggle, micPaused, onToolDismiss: () => setToolResult(null), onInteraction: bumpActivity, onRetry: handleRetryClick, isRetrying, lastTimings, showPipelineMetrics: settings.showPipelineMetrics, pipelineMetricsAutoHideMs: settings.pipelineMetricsAutoHideMs, showSettings, onSettingsToggle: toggleSettings, ttsEnabled: settings.ttsEnabled, copilotName: config.copilotName, portraitSrc: resolvedPortrait, onStartMic: handleMicToggle, onSwitchToKeyboard: handleSwitchToKeyboard, switchToTextRef }),
|
|
2533
|
+
/* @__PURE__ */ jsx9(ExpandedContent, { orbState, getAmplitude, analyser, voiceState: state, messages, isTyping, toolResult, voiceError: effectiveError, dismissError, onCollapse, onClose, onTextSubmit: handleTextSubmit, onMicToggle: handleMicToggle, micPaused, onToolDismiss: () => setToolResult(null), onInteraction: bumpActivity, onRetry: handleRetryClick, isRetrying, retryCountdown, lastTimings, showPipelineMetrics: settings.showPipelineMetrics, pipelineMetricsAutoHideMs: settings.pipelineMetricsAutoHideMs, showSettings, onSettingsToggle: toggleSettings, ttsEnabled: settings.ttsEnabled, copilotName: config.copilotName, portraitSrc: resolvedPortrait, onStartMic: handleMicToggle, onSwitchToKeyboard: handleSwitchToKeyboard, switchToTextRef }),
|
|
2483
2534
|
/* @__PURE__ */ jsx9(AnimatePresence5, { children: showSettings && /* @__PURE__ */ jsx9(Suspense, { fallback: null, children: /* @__PURE__ */ jsx9(VoiceSettingsView2, { onBack: toggleSettings, onVolumeChange: applyVolume }) }) })
|
|
2484
2535
|
] });
|
|
2485
2536
|
}
|
|
@@ -2506,6 +2557,22 @@ function GlassCopilotPanel({ isOpen: isOpenProp, onOpen: onOpenProp, onClose: on
|
|
|
2506
2557
|
const handleExpand = useCallback3(() => {
|
|
2507
2558
|
setInternalState("expanded");
|
|
2508
2559
|
}, []);
|
|
2560
|
+
const [fabOffline, setFabOffline] = useState5(false);
|
|
2561
|
+
useEffect6(() => {
|
|
2562
|
+
if (isOpen) return;
|
|
2563
|
+
let cancelled = false;
|
|
2564
|
+
const check = () => {
|
|
2565
|
+
checkBackendHealth().then(({ available }) => {
|
|
2566
|
+
if (!cancelled) setFabOffline(!available);
|
|
2567
|
+
});
|
|
2568
|
+
};
|
|
2569
|
+
check();
|
|
2570
|
+
const timer = setInterval(check, RECOVERY_POLL_MS);
|
|
2571
|
+
return () => {
|
|
2572
|
+
cancelled = true;
|
|
2573
|
+
clearInterval(timer);
|
|
2574
|
+
};
|
|
2575
|
+
}, [isOpen]);
|
|
2509
2576
|
const isVisible = panelState !== "hidden";
|
|
2510
2577
|
const isExpanded = panelState === "expanded";
|
|
2511
2578
|
const targetHeight = isExpanded ? PANEL_EXPANDED_HEIGHT : PANEL_COLLAPSED_HEIGHT;
|
|
@@ -2537,7 +2604,7 @@ function GlassCopilotPanel({ isOpen: isOpenProp, onOpen: onOpenProp, onClose: on
|
|
|
2537
2604
|
] }) }) }),
|
|
2538
2605
|
/* @__PURE__ */ jsx9("span", { "aria-live": "polite", "aria-atomic": "true", style: { position: "absolute", width: 1, height: 1, padding: 0, margin: -1, overflow: "hidden", clip: "rect(0,0,0,0)", whiteSpace: "nowrap", borderWidth: 0 }, children: ariaAnnouncement }),
|
|
2539
2606
|
/* @__PURE__ */ jsxs8(AnimatePresence5, { children: [
|
|
2540
|
-
!isVisible && /* @__PURE__ */ jsx9(motion5.div, { ref: fabRef, initial: { scale: 0, opacity: 0 }, animate: { scale: 1, opacity: 1 }, exit: { scale: 0, opacity: 0 }, transition: { duration: 0.25, ease: "easeOut" }, className: "fixed", style: { bottom: PANEL_BOTTOM, right: PANEL_RIGHT, zIndex: PANEL_Z_INDEX }, children: /* @__PURE__ */ jsx9(CopilotFAB, { onClick: handleOpen, portraitSrc: resolvedPortrait }) }, "copilot-fab"),
|
|
2607
|
+
!isVisible && /* @__PURE__ */ jsx9(motion5.div, { ref: fabRef, initial: { scale: 0, opacity: 0 }, animate: { scale: 1, opacity: 1 }, exit: { scale: 0, opacity: 0 }, transition: { duration: 0.25, ease: "easeOut" }, className: "fixed", style: { bottom: PANEL_BOTTOM, right: PANEL_RIGHT, zIndex: PANEL_Z_INDEX }, children: /* @__PURE__ */ jsx9(CopilotFAB, { onClick: handleOpen, portraitSrc: resolvedPortrait, isOffline: fabOffline }) }, "copilot-fab"),
|
|
2541
2608
|
isVisible && /* @__PURE__ */ jsxs8(
|
|
2542
2609
|
motion5.div,
|
|
2543
2610
|
{
|