@unctad-ai/voice-agent-ui 0.1.1

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.
Files changed (81) hide show
  1. package/dist/VoiceAgentProvider.d.ts +6 -0
  2. package/dist/VoiceAgentProvider.d.ts.map +1 -0
  3. package/dist/VoiceAgentProvider.js +8 -0
  4. package/dist/VoiceAgentProvider.js.map +1 -0
  5. package/dist/components/AgentAvatar.d.ts +16 -0
  6. package/dist/components/AgentAvatar.d.ts.map +1 -0
  7. package/dist/components/AgentAvatar.js +186 -0
  8. package/dist/components/AgentAvatar.js.map +1 -0
  9. package/dist/components/GlassCopilotPanel.d.ts +13 -0
  10. package/dist/components/GlassCopilotPanel.d.ts.map +1 -0
  11. package/dist/components/GlassCopilotPanel.js +438 -0
  12. package/dist/components/GlassCopilotPanel.js.map +1 -0
  13. package/dist/components/PipelineMetricsBar.d.ts +7 -0
  14. package/dist/components/PipelineMetricsBar.d.ts.map +1 -0
  15. package/dist/components/PipelineMetricsBar.js +62 -0
  16. package/dist/components/PipelineMetricsBar.js.map +1 -0
  17. package/dist/components/VoiceA11yAnnouncer.d.ts +8 -0
  18. package/dist/components/VoiceA11yAnnouncer.d.ts.map +1 -0
  19. package/dist/components/VoiceA11yAnnouncer.js +32 -0
  20. package/dist/components/VoiceA11yAnnouncer.js.map +1 -0
  21. package/dist/components/VoiceControls.d.ts +9 -0
  22. package/dist/components/VoiceControls.d.ts.map +1 -0
  23. package/dist/components/VoiceControls.js +60 -0
  24. package/dist/components/VoiceControls.js.map +1 -0
  25. package/dist/components/VoiceCopilotFAB.d.ts +9 -0
  26. package/dist/components/VoiceCopilotFAB.d.ts.map +1 -0
  27. package/dist/components/VoiceCopilotFAB.js +12 -0
  28. package/dist/components/VoiceCopilotFAB.js.map +1 -0
  29. package/dist/components/VoiceDotRing.d.ts +9 -0
  30. package/dist/components/VoiceDotRing.d.ts.map +1 -0
  31. package/dist/components/VoiceDotRing.js +64 -0
  32. package/dist/components/VoiceDotRing.js.map +1 -0
  33. package/dist/components/VoiceErrorBoundary.d.ts +19 -0
  34. package/dist/components/VoiceErrorBoundary.d.ts.map +1 -0
  35. package/dist/components/VoiceErrorBoundary.js +24 -0
  36. package/dist/components/VoiceErrorBoundary.js.map +1 -0
  37. package/dist/components/VoiceErrorDisplay.d.ts +8 -0
  38. package/dist/components/VoiceErrorDisplay.d.ts.map +1 -0
  39. package/dist/components/VoiceErrorDisplay.js +94 -0
  40. package/dist/components/VoiceErrorDisplay.js.map +1 -0
  41. package/dist/components/VoiceOnboarding.d.ts +8 -0
  42. package/dist/components/VoiceOnboarding.d.ts.map +1 -0
  43. package/dist/components/VoiceOnboarding.js +28 -0
  44. package/dist/components/VoiceOnboarding.js.map +1 -0
  45. package/dist/components/VoiceOrb.d.ts +10 -0
  46. package/dist/components/VoiceOrb.d.ts.map +1 -0
  47. package/dist/components/VoiceOrb.js +236 -0
  48. package/dist/components/VoiceOrb.js.map +1 -0
  49. package/dist/components/VoiceOverlay.d.ts +9 -0
  50. package/dist/components/VoiceOverlay.d.ts.map +1 -0
  51. package/dist/components/VoiceOverlay.js +199 -0
  52. package/dist/components/VoiceOverlay.js.map +1 -0
  53. package/dist/components/VoiceSettingsView.d.ts +7 -0
  54. package/dist/components/VoiceSettingsView.d.ts.map +1 -0
  55. package/dist/components/VoiceSettingsView.js +109 -0
  56. package/dist/components/VoiceSettingsView.js.map +1 -0
  57. package/dist/components/VoiceToolCard.d.ts +11 -0
  58. package/dist/components/VoiceToolCard.d.ts.map +1 -0
  59. package/dist/components/VoiceToolCard.js +37 -0
  60. package/dist/components/VoiceToolCard.js.map +1 -0
  61. package/dist/components/VoiceTranscript.d.ts +13 -0
  62. package/dist/components/VoiceTranscript.d.ts.map +1 -0
  63. package/dist/components/VoiceTranscript.js +313 -0
  64. package/dist/components/VoiceTranscript.js.map +1 -0
  65. package/dist/components/VoiceWaveformCanvas.d.ts +9 -0
  66. package/dist/components/VoiceWaveformCanvas.d.ts.map +1 -0
  67. package/dist/components/VoiceWaveformCanvas.js +91 -0
  68. package/dist/components/VoiceWaveformCanvas.js.map +1 -0
  69. package/dist/contexts/VoiceSettingsContext.d.ts +37 -0
  70. package/dist/contexts/VoiceSettingsContext.d.ts.map +1 -0
  71. package/dist/contexts/VoiceSettingsContext.js +89 -0
  72. package/dist/contexts/VoiceSettingsContext.js.map +1 -0
  73. package/dist/index.d.ts +22 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +22 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/utils.d.ts +3 -0
  78. package/dist/utils.d.ts.map +1 -0
  79. package/dist/utils.js +6 -0
  80. package/dist/utils.js.map +1 -0
  81. package/package.json +53 -0
@@ -0,0 +1,8 @@
1
+ import type { OrbState } from '@unctad-ai/voice-agent-core';
2
+ interface VoiceA11yAnnouncerProps {
3
+ isOpen: boolean;
4
+ orbState: OrbState;
5
+ }
6
+ export default function VoiceA11yAnnouncer({ isOpen, orbState }: VoiceA11yAnnouncerProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=VoiceA11yAnnouncer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceA11yAnnouncer.d.ts","sourceRoot":"","sources":["../../src/components/VoiceA11yAnnouncer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE5D,UAAU,uBAAuB;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAUD,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,uBAAuB,2CA8BvF"}
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from 'react';
3
+ const STATE_ANNOUNCEMENTS = {
4
+ idle: 'Voice assistant ready',
5
+ listening: 'Listening for your question',
6
+ processing: 'Processing your request',
7
+ speaking: 'Assistant is responding',
8
+ error: 'An error occurred',
9
+ };
10
+ export default function VoiceA11yAnnouncer({ isOpen, orbState }) {
11
+ const prevOpen = useRef(isOpen);
12
+ const prevState = useRef(orbState);
13
+ const announceRef = useRef(null);
14
+ useEffect(() => {
15
+ if (!announceRef.current)
16
+ return;
17
+ if (isOpen && !prevOpen.current) {
18
+ announceRef.current.textContent =
19
+ 'Voice assistant opened. Press Escape to close. Use Ctrl+Shift+V to toggle.';
20
+ }
21
+ else if (!isOpen && prevOpen.current) {
22
+ announceRef.current.textContent = 'Voice assistant closed';
23
+ }
24
+ else if (isOpen && orbState !== prevState.current) {
25
+ announceRef.current.textContent = STATE_ANNOUNCEMENTS[orbState];
26
+ }
27
+ prevOpen.current = isOpen;
28
+ prevState.current = orbState;
29
+ }, [isOpen, orbState]);
30
+ return (_jsx("div", { ref: announceRef, "aria-live": "polite", "aria-atomic": "true", className: "sr-only", role: "status" }));
31
+ }
32
+ //# sourceMappingURL=VoiceA11yAnnouncer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceA11yAnnouncer.js","sourceRoot":"","sources":["../../src/components/VoiceA11yAnnouncer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAQ1C,MAAM,mBAAmB,GAA6B;IACpD,IAAI,EAAE,uBAAuB;IAC7B,SAAS,EAAE,6BAA6B;IACxC,UAAU,EAAE,yBAAyB;IACrC,QAAQ,EAAE,yBAAyB;IACnC,KAAK,EAAE,mBAAmB;CAC3B,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAA2B;IACtF,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAChC,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,WAAW,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAEjD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,WAAW,CAAC,OAAO;YAAE,OAAO;QAEjC,IAAI,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAChC,WAAW,CAAC,OAAO,CAAC,WAAW;gBAC7B,4EAA4E,CAAC;QACjF,CAAC;aAAM,IAAI,CAAC,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACvC,WAAW,CAAC,OAAO,CAAC,WAAW,GAAG,wBAAwB,CAAC;QAC7D,CAAC;aAAM,IAAI,MAAM,IAAI,QAAQ,KAAK,SAAS,CAAC,OAAO,EAAE,CAAC;YACpD,WAAW,CAAC,OAAO,CAAC,WAAW,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAClE,CAAC;QAED,QAAQ,CAAC,OAAO,GAAG,MAAM,CAAC;QAC1B,SAAS,CAAC,OAAO,GAAG,QAAQ,CAAC;IAC/B,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEvB,OAAO,CACL,cACE,GAAG,EAAE,WAAW,eACN,QAAQ,iBACN,MAAM,EAClB,SAAS,EAAC,SAAS,EACnB,IAAI,EAAC,QAAQ,GACb,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { VoiceState } from '@unctad-ai/voice-agent-core';
2
+ interface VoiceControlsProps {
3
+ state: VoiceState;
4
+ onTextSubmit: (text: string) => void;
5
+ isListening: boolean;
6
+ }
7
+ export default function VoiceControls({ state, onTextSubmit, isListening }: VoiceControlsProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
9
+ //# sourceMappingURL=VoiceControls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceControls.d.ts","sourceRoot":"","sources":["../../src/components/VoiceControls.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,UAAU,kBAAkB;IAC1B,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,WAAW,EAAE,OAAO,CAAC;CACtB;AAmBD,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,EAAE,kBAAkB,2CA4J7F"}
@@ -0,0 +1,60 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useRef, useEffect } from 'react';
3
+ import { motion, AnimatePresence } from 'motion/react';
4
+ import { Keyboard, Send, X } from 'lucide-react';
5
+ import { cn } from '../utils';
6
+ import { useSiteConfig } from '@unctad-ai/voice-agent-core';
7
+ const STATE_LABELS = {
8
+ IDLE: 'How can I help you?',
9
+ LISTENING: "I'm listening...",
10
+ USER_SPEAKING: 'Go ahead...',
11
+ PROCESSING: 'Let me look into that...',
12
+ AI_SPEAKING: "Here's what I found...",
13
+ };
14
+ /** Shared glass-pill style for control buttons */
15
+ const GLASS_PILL_BASE = cn('backdrop-blur-xl rounded-full', 'flex items-center justify-center', 'border border-white/15', 'transition-all duration-200 cursor-pointer', 'hover:border-white/30 hover:shadow-[0_0_16px_rgba(255,255,255,0.08)]');
16
+ export default function VoiceControls({ state, onTextSubmit, isListening }) {
17
+ const { colors } = useSiteConfig();
18
+ const [showTextInput, setShowTextInput] = useState(false);
19
+ const [text, setText] = useState('');
20
+ const inputRef = useRef(null);
21
+ useEffect(() => {
22
+ if (showTextInput)
23
+ inputRef.current?.focus();
24
+ }, [showTextInput]);
25
+ const handleSubmit = () => {
26
+ const trimmed = text.trim();
27
+ if (!trimmed)
28
+ return;
29
+ onTextSubmit(trimmed);
30
+ setText('');
31
+ setShowTextInput(false);
32
+ };
33
+ return (_jsx("div", { className: "w-full max-w-2xl mx-auto mt-auto pb-8 px-4", children: _jsx(AnimatePresence, { mode: "wait", children: showTextInput ? (_jsxs(motion.div, { initial: { opacity: 0, y: 16, scale: 0.95 }, animate: { opacity: 1, y: 0, scale: 1 }, exit: { opacity: 0, y: 16, scale: 0.95 }, transition: { duration: 0.25, ease: [0.22, 1, 0.36, 1] }, className: cn('rounded-full', 'flex items-center gap-4', 'border border-white/20', 'px-8 py-3'), style: {
34
+ backgroundColor: 'rgba(0, 0, 0, 0.4)',
35
+ backdropFilter: 'blur(16px) saturate(1.2)',
36
+ WebkitBackdropFilter: 'blur(16px) saturate(1.2)',
37
+ }, children: [_jsx("input", { ref: inputRef, type: "text", value: text, onChange: (e) => setText(e.target.value), onKeyDown: (e) => e.key === 'Enter' && handleSubmit(), placeholder: "Ask a question...", className: "flex-1 text-sm placeholder:text-white/40 min-w-0", style: {
38
+ color: 'white',
39
+ background: 'none',
40
+ border: 'none',
41
+ outline: 'none',
42
+ boxShadow: 'none',
43
+ WebkitAppearance: 'none',
44
+ padding: 0,
45
+ } }), _jsx(motion.button, { onClick: handleSubmit, whileTap: { scale: 0.9 }, className: "rounded-full p-2 text-white transition-colors cursor-pointer", style: { backgroundColor: colors.primary }, "aria-label": "Send message", children: _jsx(Send, { className: "h-4 w-4" }) }), _jsx("button", { onClick: () => {
46
+ setShowTextInput(false);
47
+ setText('');
48
+ }, className: "rounded-full p-2 text-white/60 hover:text-white hover:bg-white/10 transition-all cursor-pointer", "aria-label": "Cancel text input", children: _jsx(X, { className: "h-4 w-4" }) })] }, "text-input")) : (_jsx(motion.div, { initial: { opacity: 0, y: 16, scale: 0.95 }, animate: { opacity: 1, y: 0, scale: 1 }, exit: { opacity: 0, y: 16, scale: 0.95 }, transition: { duration: 0.25, ease: [0.22, 1, 0.36, 1] }, className: "flex items-center justify-center gap-3", children: _jsxs("div", { className: cn('rounded-full', 'text-white text-sm font-medium', 'flex items-center gap-6', 'border border-white/20', 'pl-8 pr-4 py-1.5'), style: {
49
+ backgroundColor: 'rgba(0, 0, 0, 0.4)',
50
+ backdropFilter: 'blur(16px) saturate(1.2)',
51
+ WebkitBackdropFilter: 'blur(16px) saturate(1.2)',
52
+ color: 'white',
53
+ }, children: [_jsxs("span", { className: "relative flex items-center justify-center w-3 h-3 ml-0.5", children: [isListening && (_jsx("span", { className: "absolute inset-0 rounded-full animate-ping", style: { backgroundColor: `${colors.primary}80` } })), _jsx("span", { className: cn('relative h-2.5 w-2.5 rounded-full transition-colors duration-300'), style: isListening ? {
54
+ backgroundColor: colors.primary,
55
+ boxShadow: `0 0 8px ${colors.primary}99`,
56
+ } : {
57
+ backgroundColor: 'rgba(255,255,255,0.3)',
58
+ } })] }), _jsx(AnimatePresence, { mode: "wait", children: _jsx(motion.span, { initial: { opacity: 0, y: 4 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -4 }, transition: { duration: 0.2 }, className: "pr-1", children: STATE_LABELS[state] }, state) }), _jsx("button", { onClick: () => setShowTextInput(true), className: cn('rounded-full p-2', 'text-white/60 hover:text-white', 'hover:bg-white/10', 'transition-all duration-200 cursor-pointer'), "aria-label": "Type a message", children: _jsx(Keyboard, { className: "h-4 w-4" }) })] }) }, "controls")) }) }));
59
+ }
60
+ //# sourceMappingURL=VoiceControls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceControls.js","sourceRoot":"","sources":["../../src/components/VoiceControls.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ interface VoiceCopilotFABProps {
2
+ onClick: () => void;
3
+ isActive?: boolean;
4
+ isOverlayOpen?: boolean;
5
+ onMouseEnter?: () => void;
6
+ }
7
+ export default function VoiceCopilotFAB({ onClick, isActive, isOverlayOpen, onMouseEnter, }: VoiceCopilotFABProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
9
+ //# sourceMappingURL=VoiceCopilotFAB.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceCopilotFAB.d.ts","sourceRoot":"","sources":["../../src/components/VoiceCopilotFAB.tsx"],"names":[],"mappings":"AAIA,UAAU,oBAAoB;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EACtC,OAAO,EACP,QAAQ,EACR,aAAa,EACb,YAAY,GACb,EAAE,oBAAoB,2CAwCtB"}
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { motion, AnimatePresence, useReducedMotion } from 'motion/react';
3
+ import { Mic } from 'lucide-react';
4
+ import { useSiteConfig } from '@unctad-ai/voice-agent-core';
5
+ export default function VoiceCopilotFAB({ onClick, isActive, isOverlayOpen, onMouseEnter, }) {
6
+ const prefersReduced = useReducedMotion();
7
+ const { colors } = useSiteConfig();
8
+ return (_jsx(AnimatePresence, { children: !isOverlayOpen && (_jsx(motion.div, { initial: { scale: 0, opacity: 0 }, animate: { scale: 1, opacity: 1 }, exit: { scale: 0, opacity: 0 }, transition: { duration: 0.25, ease: 'easeOut' }, className: "fixed bottom-6 right-6 z-50", children: _jsx(motion.button, { onClick: onClick, onMouseEnter: onMouseEnter, animate: prefersReduced ? {} : { scale: [1, 1.15, 1] }, transition: prefersReduced
9
+ ? {}
10
+ : { scale: { duration: 1.5, repeat: Infinity, ease: 'easeInOut' } }, whileHover: { scale: 1.1 }, whileTap: { scale: 0.95 }, className: "relative rounded-full p-3 shadow-lg text-white transition-all cursor-pointer", style: { backgroundColor: colors.primary }, "aria-label": "Open voice assistant", children: isActive ? (_jsx("span", { className: "h-3 w-3 rounded-full bg-white animate-pulse" })) : (_jsx(Mic, { className: "w-6 h-6" })) }) }, "voice-fab-wrapper")) }));
11
+ }
12
+ //# sourceMappingURL=VoiceCopilotFAB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceCopilotFAB.js","sourceRoot":"","sources":["../../src/components/VoiceCopilotFAB.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAS5D,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EACtC,OAAO,EACP,QAAQ,EACR,aAAa,EACb,YAAY,GACS;IACrB,MAAM,cAAc,GAAG,gBAAgB,EAAE,CAAC;IAC1C,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAAC;IAEnC,OAAO,CACL,KAAC,eAAe,cACb,CAAC,aAAa,IAAI,CACjB,KAAC,MAAM,CAAC,GAAG,IAET,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EACjC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EACjC,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EAC9B,UAAU,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,EAC/C,SAAS,EAAC,6BAA6B,YAEvC,KAAC,MAAM,CAAC,MAAM,IACZ,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EACtD,UAAU,EACR,cAAc;oBACZ,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAEvE,UAAU,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,EAC1B,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EACzB,SAAS,EAAC,8EAA8E,EACxF,KAAK,EAAE,EAAE,eAAe,EAAE,MAAM,CAAC,OAAO,EAAE,gBAC/B,sBAAsB,YAEhC,QAAQ,CAAC,CAAC,CAAC,CACV,eAAM,SAAS,EAAC,6CAA6C,GAAG,CACjE,CAAC,CAAC,CAAC,CACF,KAAC,GAAG,IAAC,SAAS,EAAC,SAAS,GAAG,CAC5B,GACa,IA3BZ,mBAAmB,CA4BZ,CACd,GACe,CACnB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { OrbState } from '@unctad-ai/voice-agent-core';
2
+ interface VoiceDotRingProps {
3
+ analyserNode: AnalyserNode | null;
4
+ state: OrbState;
5
+ orbRadius: number;
6
+ }
7
+ export default function VoiceDotRing({ analyserNode, state, orbRadius }: VoiceDotRingProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
9
+ //# sourceMappingURL=VoiceDotRing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceDotRing.d.ts","sourceRoot":"","sources":["../../src/components/VoiceDotRing.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE5D,UAAU,iBAAiB;IACzB,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,KAAK,EAAE,QAAQ,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAUD,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,iBAAiB,2CAuFzF"}
@@ -0,0 +1,64 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useRef, useEffect, useState } from 'react';
3
+ import { DOT_RING_COUNT, DOT_RING_GAP, DOT_RING_BASE_RADIUS, DOT_RING_PEAK_RADIUS, DOT_RING_SMOOTHING, } from '@unctad-ai/voice-agent-core';
4
+ const STATE_COLORS = {
5
+ idle: 'rgba(59,130,246,0.6)',
6
+ listening: 'rgba(219,33,41,0.8)',
7
+ processing: 'rgba(245,158,11,0.7)',
8
+ speaking: 'rgba(34,197,94,0.7)',
9
+ error: 'rgba(220,38,38,0.6)',
10
+ };
11
+ export default function VoiceDotRing({ analyserNode, state, orbRadius }) {
12
+ const dotsRef = useRef([]);
13
+ const barsRef = useRef(new Float32Array(DOT_RING_COUNT));
14
+ const rafRef = useRef(0);
15
+ const colorRef = useRef(STATE_COLORS.idle);
16
+ const [reducedMotion] = useState(() => window.matchMedia('(prefers-reduced-motion: reduce)').matches);
17
+ const ringRadius = orbRadius + DOT_RING_GAP;
18
+ const svgSize = (ringRadius + DOT_RING_PEAK_RADIUS + 2) * 2;
19
+ const cx = svgSize / 2;
20
+ const cy = svgSize / 2;
21
+ useEffect(() => {
22
+ const freqData = analyserNode ? new Uint8Array(analyserNode.frequencyBinCount) : null;
23
+ const tick = () => {
24
+ // Lerp color toward target
25
+ colorRef.current = STATE_COLORS[state];
26
+ if (analyserNode && freqData) {
27
+ analyserNode.getByteFrequencyData(freqData);
28
+ }
29
+ for (let i = 0; i < DOT_RING_COUNT; i++) {
30
+ const dot = dotsRef.current[i];
31
+ if (!dot)
32
+ continue;
33
+ let targetVal = 0;
34
+ if (freqData && freqData.length > 0) {
35
+ const binIndex = Math.floor((i / DOT_RING_COUNT) * freqData.length);
36
+ targetVal = freqData[binIndex] / 255;
37
+ }
38
+ barsRef.current[i] += (targetVal - barsRef.current[i]) * DOT_RING_SMOOTHING;
39
+ const val = reducedMotion ? 0 : barsRef.current[i];
40
+ const r = DOT_RING_BASE_RADIUS + val * (DOT_RING_PEAK_RADIUS - DOT_RING_BASE_RADIUS);
41
+ const opacity = 0.3 + val * 0.5;
42
+ dot.setAttribute('r', String(r));
43
+ dot.setAttribute('opacity', String(opacity));
44
+ dot.setAttribute('fill', colorRef.current);
45
+ }
46
+ rafRef.current = requestAnimationFrame(tick);
47
+ };
48
+ rafRef.current = requestAnimationFrame(tick);
49
+ return () => cancelAnimationFrame(rafRef.current);
50
+ }, [analyserNode, state, reducedMotion, ringRadius]);
51
+ return (_jsx("svg", { width: svgSize, height: svgSize, viewBox: `0 0 ${svgSize} ${svgSize}`, className: "absolute pointer-events-none", style: {
52
+ top: '50%',
53
+ left: '50%',
54
+ transform: 'translate(-50%, -50%)',
55
+ }, "aria-hidden": "true", children: Array.from({ length: DOT_RING_COUNT }, (_, i) => {
56
+ const angle = (i / DOT_RING_COUNT) * Math.PI * 2 - Math.PI / 2;
57
+ const x = cx + Math.cos(angle) * ringRadius;
58
+ const y = cy + Math.sin(angle) * ringRadius;
59
+ return (_jsx("circle", { ref: (el) => {
60
+ dotsRef.current[i] = el;
61
+ }, cx: x, cy: y, r: DOT_RING_BASE_RADIUS, fill: STATE_COLORS.idle, opacity: 0.3 }, i));
62
+ }) }));
63
+ }
64
+ //# sourceMappingURL=VoiceDotRing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceDotRing.js","sourceRoot":"","sources":["../../src/components/VoiceDotRing.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { Component } from 'react';
2
+ import type { ReactNode, ErrorInfo } from 'react';
3
+ interface Props {
4
+ children: ReactNode;
5
+ onReset?: () => void;
6
+ }
7
+ interface State {
8
+ hasError: boolean;
9
+ error: Error | null;
10
+ }
11
+ export default class VoiceErrorBoundary extends Component<Props, State> {
12
+ state: State;
13
+ static getDerivedStateFromError(error: Error): State;
14
+ componentDidCatch(error: Error, info: ErrorInfo): void;
15
+ handleReset: () => void;
16
+ render(): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
17
+ }
18
+ export {};
19
+ //# sourceMappingURL=VoiceErrorBoundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceErrorBoundary.d.ts","sourceRoot":"","sources":["../../src/components/VoiceErrorBoundary.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIlD,UAAU,KAAK;IACb,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,UAAU,KAAK;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,CAAC,OAAO,OAAO,kBAAmB,SAAQ,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC;IACrE,KAAK,EAAE,KAAK,CAAoC;IAEhD,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK;IAIpD,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS;IAI/C,WAAW,aAGT;IAEF,MAAM;CA0BP"}
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Component } from 'react';
3
+ import { cn } from '../utils';
4
+ import { AlertTriangle, RefreshCw } from 'lucide-react';
5
+ export default class VoiceErrorBoundary extends Component {
6
+ state = { hasError: false, error: null };
7
+ static getDerivedStateFromError(error) {
8
+ return { hasError: true, error };
9
+ }
10
+ componentDidCatch(error, info) {
11
+ console.error('Voice component error:', error, info.componentStack);
12
+ }
13
+ handleReset = () => {
14
+ this.setState({ hasError: false, error: null });
15
+ this.props.onReset?.();
16
+ };
17
+ render() {
18
+ if (this.state.hasError) {
19
+ return (_jsxs("div", { className: "flex flex-col items-center justify-center gap-4 p-8 text-center", children: [_jsx(AlertTriangle, { className: "h-10 w-10 text-red-400" }), _jsx("p", { className: "text-white text-lg", children: "Something went wrong with the voice assistant." }), _jsx("p", { className: "text-white/50 text-sm max-w-sm", children: this.state.error?.message || 'An unexpected error occurred.' }), _jsxs("button", { onClick: this.handleReset, className: cn('flex items-center gap-2 px-4 py-2', 'bg-white/10 backdrop-blur-md rounded-full', 'text-white text-sm hover:bg-white/20 transition-colors cursor-pointer'), children: [_jsx(RefreshCw, { className: "h-4 w-4" }), "Try again"] })] }));
20
+ }
21
+ return this.props.children;
22
+ }
23
+ }
24
+ //# sourceMappingURL=VoiceErrorBoundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceErrorBoundary.js","sourceRoot":"","sources":["../../src/components/VoiceErrorBoundary.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAYxD,MAAM,CAAC,OAAO,OAAO,kBAAmB,SAAQ,SAAuB;IACrE,KAAK,GAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAEhD,MAAM,CAAC,wBAAwB,CAAC,KAAY;QAC1C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACnC,CAAC;IAED,iBAAiB,CAAC,KAAY,EAAE,IAAe;QAC7C,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IACtE,CAAC;IAED,WAAW,GAAG,GAAG,EAAE;QACjB,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;IACzB,CAAC,CAAC;IAEF,MAAM;QACJ,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACxB,OAAO,CACL,eAAK,SAAS,EAAC,iEAAiE,aAC9E,KAAC,aAAa,IAAC,SAAS,EAAC,wBAAwB,GAAG,EACpD,YAAG,SAAS,EAAC,oBAAoB,+DAAmD,EACpF,YAAG,SAAS,EAAC,gCAAgC,YAC1C,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,IAAI,+BAA+B,GAC3D,EACJ,kBACE,OAAO,EAAE,IAAI,CAAC,WAAW,EACzB,SAAS,EAAE,EAAE,CACX,mCAAmC,EACnC,2CAA2C,EAC3C,uEAAuE,CACxE,aAED,KAAC,SAAS,IAAC,SAAS,EAAC,SAAS,GAAG,iBAE1B,IACL,CACP,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ export type VoiceErrorType = 'mic_denied' | 'mic_unavailable' | 'vad_load_failed' | 'stt_failed' | 'tts_failed' | 'network_error' | 'llm_failed' | 'speech_too_short' | 'not_addressed' | 'processing' | null;
2
+ interface VoiceErrorDisplayProps {
3
+ error: VoiceErrorType;
4
+ onDismiss: () => void;
5
+ }
6
+ export default function VoiceErrorDisplay({ error, onDismiss }: VoiceErrorDisplayProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=VoiceErrorDisplay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceErrorDisplay.d.ts","sourceRoot":"","sources":["../../src/components/VoiceErrorDisplay.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,cAAc,GACtB,YAAY,GACZ,iBAAiB,GACjB,iBAAiB,GACjB,YAAY,GACZ,YAAY,GACZ,eAAe,GACf,YAAY,GACZ,kBAAkB,GAClB,eAAe,GACf,YAAY,GACZ,IAAI,CAAC;AAET,UAAU,sBAAsB;IAC9B,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAuFD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,sBAAsB,2CAuCrF"}
@@ -0,0 +1,94 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { motion, AnimatePresence } from 'motion/react';
3
+ import { AlertTriangle, Hourglass, Mic, MicOff, VolumeX, Wifi, WifiOff } from 'lucide-react';
4
+ import { cn } from '../utils';
5
+ const SEVERITY_STYLES = {
6
+ error: {
7
+ bg: 'rgba(220, 38, 38, 0.08)',
8
+ border: 'rgba(220, 38, 38, 0.15)',
9
+ icon: 'text-red-500',
10
+ text: 'text-red-700',
11
+ dismiss: 'text-red-400 hover:text-red-600',
12
+ },
13
+ warning: {
14
+ bg: 'rgba(217, 119, 6, 0.08)',
15
+ border: 'rgba(217, 119, 6, 0.15)',
16
+ icon: 'text-amber-500',
17
+ text: 'text-amber-700',
18
+ dismiss: 'text-amber-400 hover:text-amber-600',
19
+ },
20
+ info: {
21
+ bg: 'rgba(0, 0, 0, 0.04)',
22
+ border: 'rgba(0, 0, 0, 0.08)',
23
+ icon: 'text-neutral-500',
24
+ text: 'text-neutral-600',
25
+ dismiss: 'text-neutral-400 hover:text-neutral-600',
26
+ },
27
+ };
28
+ const ERROR_CONFIG = {
29
+ mic_denied: {
30
+ icon: MicOff,
31
+ title: 'Microphone access denied',
32
+ severity: 'error',
33
+ },
34
+ mic_unavailable: {
35
+ icon: MicOff,
36
+ title: 'No microphone found',
37
+ severity: 'error',
38
+ },
39
+ vad_load_failed: {
40
+ icon: AlertTriangle,
41
+ title: 'Voice detection unavailable',
42
+ severity: 'warning',
43
+ },
44
+ stt_failed: {
45
+ icon: Mic,
46
+ title: "Didn't catch that",
47
+ severity: 'info',
48
+ },
49
+ tts_failed: {
50
+ icon: AlertTriangle,
51
+ title: 'Voice response unavailable',
52
+ severity: 'warning',
53
+ },
54
+ network_error: {
55
+ icon: WifiOff,
56
+ title: 'Connection lost',
57
+ severity: 'error',
58
+ },
59
+ llm_failed: {
60
+ icon: Wifi,
61
+ title: 'AI service unavailable',
62
+ severity: 'error',
63
+ },
64
+ speech_too_short: {
65
+ icon: Mic,
66
+ title: "Didn't catch that",
67
+ severity: 'info',
68
+ },
69
+ not_addressed: {
70
+ icon: VolumeX,
71
+ title: 'Not addressed to me',
72
+ severity: 'info',
73
+ },
74
+ processing: {
75
+ icon: Hourglass,
76
+ title: 'Still processing...',
77
+ severity: 'info',
78
+ },
79
+ };
80
+ export default function VoiceErrorDisplay({ error, onDismiss }) {
81
+ return (_jsx(AnimatePresence, { children: error && (_jsx(motion.div, { initial: { opacity: 0, y: 16, scale: 0.95 }, animate: { opacity: 1, y: 0, scale: 1 }, exit: { opacity: 0, y: -8, scale: 0.95 }, transition: { duration: 0.25 }, className: cn('max-w-xs mx-auto', 'rounded-xl', 'px-4 py-2'), style: {
82
+ backgroundColor: SEVERITY_STYLES[ERROR_CONFIG[error].severity].bg,
83
+ border: `1px solid ${SEVERITY_STYLES[ERROR_CONFIG[error].severity].border}`,
84
+ backdropFilter: 'blur(12px)',
85
+ WebkitBackdropFilter: 'blur(12px)',
86
+ pointerEvents: 'auto',
87
+ }, children: (() => {
88
+ const config = ERROR_CONFIG[error];
89
+ const styles = SEVERITY_STYLES[config.severity];
90
+ const Icon = config.icon;
91
+ return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Icon, { className: cn('h-4 w-4 shrink-0', styles.icon) }), _jsx("span", { className: cn('text-xs flex-1', styles.text), children: config.title }), _jsx("button", { onClick: onDismiss, className: cn('text-xs transition-colors cursor-pointer', styles.dismiss), children: "\u00D7" })] }));
92
+ })() })) }));
93
+ }
94
+ //# sourceMappingURL=VoiceErrorDisplay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceErrorDisplay.js","sourceRoot":"","sources":["../../src/components/VoiceErrorDisplay.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ interface VoiceOnboardingProps {
2
+ onTryNow: () => void;
3
+ /** Custom description text shown in the onboarding tooltip */
4
+ description?: string;
5
+ }
6
+ export default function VoiceOnboarding({ onTryNow, description }: VoiceOnboardingProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=VoiceOnboarding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceOnboarding.d.ts","sourceRoot":"","sources":["../../src/components/VoiceOnboarding.tsx"],"names":[],"mappings":"AAOA,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,oBAAoB,2CA0EtF"}
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from 'react';
3
+ import { motion, AnimatePresence } from 'motion/react';
4
+ import { cn } from '../utils';
5
+ import { useSiteConfig } from '@unctad-ai/voice-agent-core';
6
+ const STORAGE_KEY = 'voice-onboarding-dismissed';
7
+ export default function VoiceOnboarding({ onTryNow, description }) {
8
+ const { colors } = useSiteConfig();
9
+ const [show, setShow] = useState(false);
10
+ useEffect(() => {
11
+ const dismissed = localStorage.getItem(STORAGE_KEY);
12
+ if (!dismissed) {
13
+ // Small delay so FAB renders first
14
+ const timer = setTimeout(() => setShow(true), 1500);
15
+ return () => clearTimeout(timer);
16
+ }
17
+ }, []);
18
+ const dismiss = () => {
19
+ setShow(false);
20
+ localStorage.setItem(STORAGE_KEY, 'true');
21
+ };
22
+ const handleTryNow = () => {
23
+ dismiss();
24
+ onTryNow();
25
+ };
26
+ return (_jsx(AnimatePresence, { children: show && (_jsxs(motion.div, { initial: { opacity: 0, y: 8, scale: 0.95 }, animate: { opacity: 1, y: 0, scale: 1 }, exit: { opacity: 0, y: 8, scale: 0.95 }, transition: { duration: 0.25, ease: 'easeOut' }, className: cn('fixed bottom-24 right-6 z-50', 'md:bottom-[104px] md:right-6', 'bg-white rounded-xl shadow-xl', 'border border-neutral-200', 'p-4 max-w-[280px]'), role: "tooltip", children: [_jsx("div", { className: "absolute -bottom-2 right-6 w-4 h-4 bg-white border-b border-r border-neutral-200 rotate-45" }), _jsx("p", { className: "text-sm text-neutral-700 leading-relaxed mb-3", children: description ?? 'Meet your AI assistant. Ask about services, permits, or opportunities.' }), _jsxs("div", { className: "flex gap-2", children: [_jsx("button", { onClick: handleTryNow, className: cn('text-white text-sm font-medium', 'rounded-lg px-3 py-1.5', 'transition-colors cursor-pointer'), style: { backgroundColor: colors.primary }, children: "Try it now" }), _jsx("button", { onClick: dismiss, className: cn('text-neutral-500 text-sm', 'rounded-lg px-3 py-1.5', 'hover:text-neutral-700 hover:bg-neutral-100', 'transition-colors cursor-pointer'), children: "Maybe later" })] })] })) }));
27
+ }
28
+ //# sourceMappingURL=VoiceOnboarding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceOnboarding.js","sourceRoot":"","sources":["../../src/components/VoiceOnboarding.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,WAAW,GAAG,4BAA4B,CAAC;AAQjD,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAwB;IACrF,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExC,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACpD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,mCAAmC;YACnC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;YACpD,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,OAAO,CAAC,KAAK,CAAC,CAAC;QACf,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE,CAAC;IACb,CAAC,CAAC;IAEF,OAAO,CACL,KAAC,eAAe,cACb,IAAI,IAAI,CACP,MAAC,MAAM,CAAC,GAAG,IACT,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAC1C,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EACvC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EACvC,UAAU,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,EAC/C,SAAS,EAAE,EAAE,CACX,8BAA8B,EAC9B,8BAA8B,EAC9B,+BAA+B,EAC/B,2BAA2B,EAC3B,mBAAmB,CACpB,EACD,IAAI,EAAC,SAAS,aAGd,cAAK,SAAS,EAAC,4FAA4F,GAAG,EAE9G,YAAG,SAAS,EAAC,+CAA+C,YACzD,WAAW,IAAI,wEAAwE,GACtF,EACJ,eAAK,SAAS,EAAC,YAAY,aACzB,iBACE,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,EAAE,CACX,gCAAgC,EAChC,wBAAwB,EACxB,kCAAkC,CACnC,EACD,KAAK,EAAE,EAAE,eAAe,EAAE,MAAM,CAAC,OAAO,EAAE,2BAGnC,EACT,iBACE,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,EAAE,CACX,0BAA0B,EAC1B,wBAAwB,EACxB,6CAA6C,EAC7C,kCAAkC,CACnC,4BAGM,IACL,IACK,CACd,GACe,CACnB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { OrbState } from '@unctad-ai/voice-agent-core';
2
+ interface VoiceOrbProps {
3
+ state: OrbState;
4
+ /** Getter function called each animation frame — avoids 60fps React re-renders */
5
+ getAmplitude: () => number;
6
+ size?: number;
7
+ }
8
+ export default function VoiceOrb({ state, getAmplitude, size }: VoiceOrbProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=VoiceOrb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceOrb.d.ts","sourceRoot":"","sources":["../../src/components/VoiceOrb.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE5D,UAAU,aAAa;IACrB,KAAK,EAAE,QAAQ,CAAC;IAChB,kFAAkF;IAClF,YAAY,EAAE,MAAM,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAiHD,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,IAAU,EAAE,EAAE,aAAa,2CAyNlF"}