11import React , { useState , useEffect , useRef } from 'react'
22import { useVapiWidget } from '../hooks'
33
4- // Import extracted types
54import { VapiWidgetProps , ColorScheme , StyleConfig } from './types'
65
7- // Import extracted constants
86import { sizeClasses , radiusClasses , positionClasses } from './constants'
97
10- // Import extracted components
118import ConsentForm from './widget/ConsentForm'
129import FloatingButton from './widget/FloatingButton'
1310import WidgetHeader from './widget/WidgetHeader'
@@ -18,7 +15,6 @@ import VoiceControls from './widget/controls/VoiceControls'
1815import ChatControls from './widget/controls/ChatControls'
1916import HybridControls from './widget/controls/HybridControls'
2017
21- // Import animations
2218import '../styles/animations.css'
2319
2420const VapiWidget : React . FC < VapiWidgetProps > = ( {
@@ -54,13 +50,10 @@ const VapiWidget: React.FC<VapiWidgetProps> = ({
5450 const [ hasConsent , setHasConsent ] = useState ( false )
5551 const [ chatInput , setChatInput ] = useState ( '' )
5652
57- // Ref for auto-scrolling
5853 const conversationEndRef = useRef < HTMLDivElement > ( null )
5954
60- // Ref for input field focus
6155 const inputRef = useRef < HTMLInputElement > ( null )
6256
63- // Use the new combined hook
6457 const vapi = useVapiWidget ( {
6558 mode,
6659 publicKey,
@@ -72,7 +65,6 @@ const VapiWidget: React.FC<VapiWidgetProps> = ({
7265 onError
7366 } )
7467
75- // Create color scheme object
7668 const colors : ColorScheme = {
7769 baseColor : baseColor
7870 ? ( theme === 'dark' && baseColor === '#FFFFFF' ? '#000000' : baseColor )
@@ -82,17 +74,14 @@ const VapiWidget: React.FC<VapiWidgetProps> = ({
8274 buttonAccentColor : buttonAccentColor || '#FFFFFF'
8375 }
8476
85- // Adjust size for chat/hybrid modes - tiny behaves as medium
8677 const effectiveSize = mode !== 'voice' && size === 'tiny' ? 'compact' : size
8778
88- // Create style config object
8979 const styles : StyleConfig = {
9080 size : effectiveSize ,
9181 radius,
9282 theme
9383 }
9484
95- // Check consent on mount
9685 useEffect ( ( ) => {
9786 if ( requireConsent ) {
9887 const storedConsent = localStorage . getItem ( localStorageKey )
@@ -103,15 +92,12 @@ const VapiWidget: React.FC<VapiWidgetProps> = ({
10392 }
10493 } , [ requireConsent , localStorageKey ] )
10594
106- // Auto-scroll to bottom when new messages arrive or content streams
10795 useEffect ( ( ) => {
10896 conversationEndRef . current ?. scrollIntoView ( { behavior : 'smooth' } )
10997 } , [ vapi . conversation , vapi . chat . isTyping ] )
11098
111- // Auto-focus input when widget expands in chat or hybrid mode
11299 useEffect ( ( ) => {
113100 if ( isExpanded && ( mode === 'chat' || mode === 'hybrid' ) ) {
114- // Small delay to ensure the DOM is ready
115101 setTimeout ( ( ) => {
116102 inputRef . current ?. focus ( )
117103 } , 100 )
@@ -121,11 +107,9 @@ const VapiWidget: React.FC<VapiWidgetProps> = ({
121107 const handleConsentAgree = ( ) => {
122108 localStorage . setItem ( localStorageKey , 'true' )
123109 setHasConsent ( true )
124- // Widget will automatically show since isExpanded is already true
125110 }
126111
127112 const handleConsentCancel = ( ) => {
128- // Just close the expanded view
129113 setIsExpanded ( false )
130114 }
131115
@@ -136,14 +120,11 @@ const VapiWidget: React.FC<VapiWidgetProps> = ({
136120 const handleSendMessage = async ( ) => {
137121 if ( ! chatInput . trim ( ) ) return
138122
139- // Store the message and clear input immediately
140123 const message = chatInput . trim ( )
141124 setChatInput ( '' )
142125
143- // Then send the message
144126 await vapi . chat . sendMessage ( message )
145127
146- // Maintain focus on the input field
147128 inputRef . current ?. focus ( )
148129 }
149130
@@ -154,22 +135,18 @@ const VapiWidget: React.FC<VapiWidgetProps> = ({
154135 }
155136
156137 const handleReset = ( ) => {
157- // Clear all conversation history and session states
158138 vapi . clearConversation ( )
159139
160- // If there's an active call, end it
161140 if ( vapi . voice . isCallActive ) {
162141 vapi . voice . endCall ( )
163142 }
164143
165- // Clear the chat input
166144 setChatInput ( '' )
167145 }
168146
169147 // Don't allow expanded view for tiny voice mode
170148 const showExpandedView = isExpanded && ! ( mode === 'voice' && size === 'tiny' )
171149
172- // Handle floating button click
173150 const handleFloatingButtonClick = ( ) => {
174151 setIsExpanded ( true )
175152 }
@@ -178,7 +155,6 @@ const VapiWidget: React.FC<VapiWidgetProps> = ({
178155 < >
179156 < div className = { `fixed z-[50] ${ positionClasses [ position ] } ` } >
180157 { showExpandedView ? (
181- // Check if we need to show consent form or the actual widget
182158 requireConsent && ! hasConsent ? (
183159 < ConsentForm
184160 termsContent = { termsContent }
@@ -189,7 +165,6 @@ const VapiWidget: React.FC<VapiWidgetProps> = ({
189165 radius = { radius }
190166 />
191167 ) : (
192- // Expanded Widget
193168 < div
194169 className = { `${ sizeClasses [ size ] . expanded } ${ radiusClasses [ radius ] } border flex flex-col overflow-hidden ${
195170 styles . theme === 'dark'
@@ -230,7 +205,6 @@ const VapiWidget: React.FC<VapiWidgetProps> = ({
230205 : { } )
231206 } }
232207 >
233- { /* Show transcript when: showTranscript is true OR in chat mode OR in hybrid mode but voice is not active */ }
234208 { ( showTranscript || mode === 'chat' || ( mode === 'hybrid' && ! vapi . voice . isCallActive ) ) ? (
235209 < >
236210 { vapi . conversation . length === 0 ? (
@@ -268,7 +242,6 @@ const VapiWidget: React.FC<VapiWidgetProps> = ({
268242 ) }
269243 </ >
270244 ) : (
271- /* Show center volume indicator when transcript is hidden and voice call is active */
272245 vapi . voice . isCallActive ? (
273246 < VolumeIndicator
274247 volumeLevel = { vapi . voice . volumeLevel }
@@ -348,7 +321,6 @@ const VapiWidget: React.FC<VapiWidgetProps> = ({
348321 </ div >
349322 )
350323 ) : (
351- // Floating Button - Always visible
352324 < FloatingButton
353325 isCallActive = { vapi . voice . isCallActive }
354326 connectionStatus = { vapi . voice . connectionStatus }
0 commit comments