reactbridge-sdk 0.1.12 → 0.1.14
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/README.md +76 -0
- package/dist/components/ReactBridgeChatbox.d.ts +5 -1
- package/dist/components/ReactBridgeChatbox.d.ts.map +1 -1
- package/dist/components/ReactBridgeSearch.d.ts +5 -1
- package/dist/components/ReactBridgeSearch.d.ts.map +1 -1
- package/dist/hooks/useReactBridge.d.ts +1 -1
- package/dist/hooks/useReactBridge.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +195 -13
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +195 -11
- package/dist/index.js.map +1 -1
- package/dist/provider/ReactBridgeProvider.d.ts +8 -2
- package/dist/provider/ReactBridgeProvider.d.ts.map +1 -1
- package/dist/types/index.d.ts +17 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/voice.d.ts +15 -0
- package/dist/utils/voice.d.ts.map +1 -0
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -126,8 +126,73 @@ const lightTheme = {
|
|
|
126
126
|
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
|
|
127
127
|
};
|
|
128
128
|
|
|
129
|
+
// Default STT Provider using Web Speech API
|
|
130
|
+
class WebSpeechSTTProvider {
|
|
131
|
+
constructor() {
|
|
132
|
+
if (typeof window !== 'undefined') {
|
|
133
|
+
const SpeechRecognitionCtor = window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
134
|
+
if (SpeechRecognitionCtor) {
|
|
135
|
+
this.recognition = new SpeechRecognitionCtor();
|
|
136
|
+
if (!this.recognition) {
|
|
137
|
+
throw new Error('Failed to initialize SpeechRecognition');
|
|
138
|
+
}
|
|
139
|
+
this.recognition.continuous = false;
|
|
140
|
+
this.recognition.interimResults = false;
|
|
141
|
+
this.recognition.lang = 'en-US';
|
|
142
|
+
this.recognition.onresult = (event) => {
|
|
143
|
+
var _a;
|
|
144
|
+
const transcript = event.results[0][0].transcript;
|
|
145
|
+
(_a = this.onResultCallback) === null || _a === void 0 ? void 0 : _a.call(this, transcript);
|
|
146
|
+
};
|
|
147
|
+
this.recognition.onerror = (event) => {
|
|
148
|
+
var _a;
|
|
149
|
+
(_a = this.onErrorCallback) === null || _a === void 0 ? void 0 : _a.call(this, new Error(`Speech recognition error: ${event.error}`));
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
console.warn('SpeechRecognition API not supported in this browser.');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
startRecognition() {
|
|
158
|
+
if (this.recognition) {
|
|
159
|
+
this.recognition.start();
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
throw new Error('Speech recognition not supported');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
stopRecognition() {
|
|
166
|
+
var _a;
|
|
167
|
+
(_a = this.recognition) === null || _a === void 0 ? void 0 : _a.stop();
|
|
168
|
+
}
|
|
169
|
+
onResult(callback) {
|
|
170
|
+
this.onResultCallback = callback;
|
|
171
|
+
}
|
|
172
|
+
onError(callback) {
|
|
173
|
+
this.onErrorCallback = callback;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// Default TTS Provider using Web Speech API
|
|
177
|
+
class WebSpeechTTSProvider {
|
|
178
|
+
speak(text) {
|
|
179
|
+
if (typeof window !== 'undefined' && 'speechSynthesis' in window) {
|
|
180
|
+
const utterance = new SpeechSynthesisUtterance(text);
|
|
181
|
+
window.speechSynthesis.speak(utterance);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
console.warn('Text-to-speech not supported');
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
stop() {
|
|
188
|
+
if (typeof window !== 'undefined' && 'speechSynthesis' in window) {
|
|
189
|
+
window.speechSynthesis.cancel();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
129
194
|
const ReactBridgeContext = React.createContext(null);
|
|
130
|
-
function ReactBridgeProvider({ apiKey, config = {}, theme = lightTheme, children, }) {
|
|
195
|
+
function ReactBridgeProvider({ apiKey, config = {}, theme = lightTheme, sttProvider: initialSTTProvider, ttsProvider: initialTTSProvider, children, }) {
|
|
131
196
|
const fullConfig = {
|
|
132
197
|
apiKey,
|
|
133
198
|
baseURL: config.baseURL,
|
|
@@ -140,10 +205,16 @@ function ReactBridgeProvider({ apiKey, config = {}, theme = lightTheme, children
|
|
|
140
205
|
fullConfig.baseURL,
|
|
141
206
|
fullConfig.timeout,
|
|
142
207
|
]);
|
|
208
|
+
const [sttProvider, setSTTProvider] = React.useState(initialSTTProvider || new WebSpeechSTTProvider());
|
|
209
|
+
const [ttsProvider, setTTSProvider] = React.useState(initialTTSProvider || new WebSpeechTTSProvider());
|
|
143
210
|
const value = {
|
|
144
211
|
api,
|
|
145
212
|
config: fullConfig,
|
|
146
213
|
theme,
|
|
214
|
+
sttProvider,
|
|
215
|
+
ttsProvider,
|
|
216
|
+
setSTTProvider,
|
|
217
|
+
setTTSProvider,
|
|
147
218
|
};
|
|
148
219
|
return (React.createElement(ReactBridgeContext.Provider, { value: value }, children));
|
|
149
220
|
}
|
|
@@ -189,12 +260,13 @@ function getContextSummary(context) {
|
|
|
189
260
|
return parts.join('\n');
|
|
190
261
|
}
|
|
191
262
|
|
|
192
|
-
function useReactBridge({ onIntentDetected, currentContext, onError, }) {
|
|
193
|
-
const { api } = useReactBridgeContext();
|
|
263
|
+
function useReactBridge({ onIntentDetected, currentContext, onError, onSpeechStart, onSpeechEnd, onTranscript, onAgentResponse, }) {
|
|
264
|
+
const { api, sttProvider, ttsProvider } = useReactBridgeContext();
|
|
194
265
|
const [messages, setMessages] = React.useState([]);
|
|
195
266
|
const [isLoading, setIsLoading] = React.useState(false);
|
|
196
267
|
const [error, setError] = React.useState(null);
|
|
197
268
|
const [sessionId, setSessionId] = React.useState(null);
|
|
269
|
+
const [isListening, setIsListening] = React.useState(false);
|
|
198
270
|
const previousContextRef = React.useRef(null);
|
|
199
271
|
const lastRequestRef = React.useRef(null);
|
|
200
272
|
// Inject context changes as system messages
|
|
@@ -254,6 +326,11 @@ function useReactBridge({ onIntentDetected, currentContext, onError, }) {
|
|
|
254
326
|
toolCall: response.toolCall,
|
|
255
327
|
};
|
|
256
328
|
setMessages(prev => [...prev, assistantMessage]);
|
|
329
|
+
// Trigger TTS and callback
|
|
330
|
+
ttsProvider.speak(response.message);
|
|
331
|
+
if (onAgentResponse) {
|
|
332
|
+
onAgentResponse(response.message);
|
|
333
|
+
}
|
|
257
334
|
// Step 2: If there's a tool call, execute it
|
|
258
335
|
if (response.toolCall && onIntentDetected) {
|
|
259
336
|
try {
|
|
@@ -269,6 +346,11 @@ function useReactBridge({ onIntentDetected, currentContext, onError, }) {
|
|
|
269
346
|
timestamp: new Date(),
|
|
270
347
|
};
|
|
271
348
|
setMessages(prev => [...prev, finalMessage]);
|
|
349
|
+
// Trigger TTS for final response
|
|
350
|
+
ttsProvider.speak(resultResponse.message);
|
|
351
|
+
if (onAgentResponse) {
|
|
352
|
+
onAgentResponse(resultResponse.message);
|
|
353
|
+
}
|
|
272
354
|
}
|
|
273
355
|
}
|
|
274
356
|
catch (toolError) {
|
|
@@ -311,12 +393,50 @@ function useReactBridge({ onIntentDetected, currentContext, onError, }) {
|
|
|
311
393
|
setSessionId(null);
|
|
312
394
|
setError(null);
|
|
313
395
|
}, []);
|
|
396
|
+
const startVoiceInput = React.useCallback(() => {
|
|
397
|
+
setIsListening(true);
|
|
398
|
+
if (onSpeechStart) {
|
|
399
|
+
onSpeechStart();
|
|
400
|
+
}
|
|
401
|
+
sttProvider.onResult((text) => {
|
|
402
|
+
if (onTranscript) {
|
|
403
|
+
onTranscript(text);
|
|
404
|
+
}
|
|
405
|
+
sendChatQuery(text);
|
|
406
|
+
setIsListening(false);
|
|
407
|
+
if (onSpeechEnd) {
|
|
408
|
+
onSpeechEnd();
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
if (sttProvider.onError) {
|
|
412
|
+
sttProvider.onError((error) => {
|
|
413
|
+
setIsListening(false);
|
|
414
|
+
if (onError) {
|
|
415
|
+
onError(error);
|
|
416
|
+
}
|
|
417
|
+
if (onSpeechEnd) {
|
|
418
|
+
onSpeechEnd();
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
sttProvider.startRecognition();
|
|
423
|
+
}, [sttProvider, sendChatQuery, onSpeechStart, onSpeechEnd, onTranscript, onError]);
|
|
424
|
+
const stopVoiceInput = React.useCallback(() => {
|
|
425
|
+
setIsListening(false);
|
|
426
|
+
sttProvider.stopRecognition();
|
|
427
|
+
if (onSpeechEnd) {
|
|
428
|
+
onSpeechEnd();
|
|
429
|
+
}
|
|
430
|
+
}, [sttProvider, onSpeechEnd]);
|
|
314
431
|
return {
|
|
315
432
|
messages,
|
|
316
433
|
isLoading,
|
|
317
434
|
sendChatQuery,
|
|
318
435
|
clearMessages,
|
|
319
436
|
error,
|
|
437
|
+
isListening,
|
|
438
|
+
startVoiceInput,
|
|
439
|
+
stopVoiceInput,
|
|
320
440
|
};
|
|
321
441
|
}
|
|
322
442
|
|
|
@@ -325,9 +445,14 @@ const MESSAGE_ICON_SVG = (React.createElement("svg", { xmlns: "http://www.w3.org
|
|
|
325
445
|
, height: "1em", fill: "currentColor" },
|
|
326
446
|
React.createElement("path", { d: "M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z" })));
|
|
327
447
|
// --- END: Dependency-Free SVG Message Icon ---
|
|
448
|
+
// Microphone Icon SVG
|
|
449
|
+
const MIC_ICON_SVG$1 = (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "currentColor" },
|
|
450
|
+
React.createElement("path", { d: "M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z" })));
|
|
328
451
|
// Default styling constants for the widget wrapper
|
|
329
452
|
const defaultToggleButtonClass = "fixed bottom-6 right-6 z-40 w-14 h-14 rounded-full shadow-lg text-white bg-blue-600 hover:bg-blue-700 transition-all flex justify-center items-center cursor-pointer text-2xl";
|
|
330
453
|
function ReactBridgeChatbox({ onIntentDetected, currentContext, placeholder = "Type your message...", height = "500px", width = "100%", theme: themeOverride, renderMessage, onError,
|
|
454
|
+
// Voice Event Props
|
|
455
|
+
onSpeechStart, onSpeechEnd, onTranscript, onAgentResponse,
|
|
331
456
|
// NEW Widget Props
|
|
332
457
|
renderMode = "basic", // Default to 'basic' (original behavior)
|
|
333
458
|
defaultOpen = false, boxLocation = "bottom-right", titleText = "AI Assistant", titleIcon = null, titleTextColor, // Will use theme.colors.text or default white based on headerBgColor
|
|
@@ -336,10 +461,14 @@ toggleIcon = MESSAGE_ICON_SVG, // <<< NOW USES THE PURE SVG CONSTANT
|
|
|
336
461
|
toggleButtonClass = defaultToggleButtonClass, toggleButtonTitle = "Open chat assistant", }) {
|
|
337
462
|
const { theme: contextTheme } = useReactBridgeContext();
|
|
338
463
|
const theme = Object.assign(Object.assign({}, contextTheme), themeOverride);
|
|
339
|
-
const { messages, isLoading, sendChatQuery } = useReactBridge({
|
|
464
|
+
const { messages, isLoading, sendChatQuery, isListening, startVoiceInput, stopVoiceInput } = useReactBridge({
|
|
340
465
|
onIntentDetected,
|
|
341
466
|
currentContext,
|
|
342
467
|
onError,
|
|
468
|
+
onSpeechStart,
|
|
469
|
+
onSpeechEnd,
|
|
470
|
+
onTranscript,
|
|
471
|
+
onAgentResponse,
|
|
343
472
|
});
|
|
344
473
|
const [inputValue, setInputValue] = React.useState("");
|
|
345
474
|
// New: Manage widget open/closed state
|
|
@@ -410,7 +539,7 @@ toggleButtonClass = defaultToggleButtonClass, toggleButtonTitle = "Open chat ass
|
|
|
410
539
|
borderTop: `1px solid ${theme.colors.border}`,
|
|
411
540
|
backgroundColor: theme.colors.surface,
|
|
412
541
|
} },
|
|
413
|
-
React.createElement("div", { style: { display: "flex", gap: theme.spacing.sm } },
|
|
542
|
+
React.createElement("div", { style: { display: "flex", gap: theme.spacing.sm, alignItems: "center" } },
|
|
414
543
|
React.createElement("input", { type: "text", value: inputValue, onChange: (e) => setInputValue(e.target.value), placeholder: placeholder, disabled: isLoading, style: {
|
|
415
544
|
flex: 1,
|
|
416
545
|
padding: theme.spacing.sm,
|
|
@@ -421,6 +550,20 @@ toggleButtonClass = defaultToggleButtonClass, toggleButtonTitle = "Open chat ass
|
|
|
421
550
|
color: theme.colors.text,
|
|
422
551
|
outline: "none",
|
|
423
552
|
} }),
|
|
553
|
+
React.createElement("button", { type: "button", onClick: isListening ? stopVoiceInput : startVoiceInput, disabled: isLoading, title: isListening ? "Stop recording" : "Start voice input", style: {
|
|
554
|
+
padding: theme.spacing.sm,
|
|
555
|
+
backgroundColor: isListening ? theme.colors.error : theme.colors.secondary,
|
|
556
|
+
color: "#ffffff",
|
|
557
|
+
border: "none",
|
|
558
|
+
borderRadius: theme.borderRadius,
|
|
559
|
+
cursor: isLoading ? "not-allowed" : "pointer",
|
|
560
|
+
opacity: isLoading ? 0.5 : 1,
|
|
561
|
+
display: "flex",
|
|
562
|
+
alignItems: "center",
|
|
563
|
+
justifyContent: "center",
|
|
564
|
+
width: "40px",
|
|
565
|
+
height: "40px",
|
|
566
|
+
} }, MIC_ICON_SVG$1),
|
|
424
567
|
React.createElement("button", { type: "submit", disabled: isLoading || !inputValue.trim(), style: {
|
|
425
568
|
padding: `${theme.spacing.sm} ${theme.spacing.md}`,
|
|
426
569
|
fontSize: theme.fontSizes.md,
|
|
@@ -489,7 +632,7 @@ toggleButtonClass = defaultToggleButtonClass, toggleButtonTitle = "Open chat ass
|
|
|
489
632
|
borderTop: `1px solid ${theme.colors.border}`,
|
|
490
633
|
backgroundColor: theme.colors.surface,
|
|
491
634
|
} },
|
|
492
|
-
React.createElement("div", { style: { display: "flex", gap: theme.spacing.sm } },
|
|
635
|
+
React.createElement("div", { style: { display: "flex", gap: theme.spacing.sm, alignItems: "center" } },
|
|
493
636
|
React.createElement("input", { type: "text", value: inputValue, onChange: (e) => setInputValue(e.target.value), placeholder: placeholder, disabled: isLoading, style: {
|
|
494
637
|
flex: 1,
|
|
495
638
|
padding: theme.spacing.sm,
|
|
@@ -500,11 +643,25 @@ toggleButtonClass = defaultToggleButtonClass, toggleButtonTitle = "Open chat ass
|
|
|
500
643
|
color: theme.colors.text,
|
|
501
644
|
outline: "none",
|
|
502
645
|
} }),
|
|
646
|
+
React.createElement("button", { type: "button", onClick: isListening ? stopVoiceInput : startVoiceInput, disabled: isLoading, title: isListening ? "Stop recording" : "Start voice input", style: {
|
|
647
|
+
padding: theme.spacing.sm,
|
|
648
|
+
backgroundColor: isListening ? theme.colors.error : theme.colors.primary,
|
|
649
|
+
color: theme.colors.background,
|
|
650
|
+
border: "none",
|
|
651
|
+
borderRadius: theme.borderRadius,
|
|
652
|
+
cursor: isLoading ? "not-allowed" : "pointer",
|
|
653
|
+
opacity: isLoading ? 0.5 : 1,
|
|
654
|
+
display: "flex",
|
|
655
|
+
alignItems: "center",
|
|
656
|
+
justifyContent: "center",
|
|
657
|
+
width: "40px",
|
|
658
|
+
height: "40px",
|
|
659
|
+
} }, MIC_ICON_SVG$1),
|
|
503
660
|
React.createElement("button", { type: "submit", disabled: isLoading || !inputValue.trim(), style: {
|
|
504
661
|
padding: `${theme.spacing.sm} ${theme.spacing.md}`,
|
|
505
662
|
fontSize: theme.fontSizes.md,
|
|
506
663
|
backgroundColor: theme.colors.primary,
|
|
507
|
-
color:
|
|
664
|
+
color: theme.colors.background,
|
|
508
665
|
border: "none",
|
|
509
666
|
borderRadius: theme.borderRadius,
|
|
510
667
|
cursor: isLoading || !inputValue.trim() ? "not-allowed" : "pointer",
|
|
@@ -512,13 +669,20 @@ toggleButtonClass = defaultToggleButtonClass, toggleButtonTitle = "Open chat ass
|
|
|
512
669
|
} }, isLoading ? "Sending..." : "Send")))));
|
|
513
670
|
}
|
|
514
671
|
|
|
515
|
-
|
|
672
|
+
// Microphone Icon SVG
|
|
673
|
+
const MIC_ICON_SVG = (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "currentColor" },
|
|
674
|
+
React.createElement("path", { d: "M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z" })));
|
|
675
|
+
function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Search...', width = '100%', maxResults = 5, theme: themeOverride, onError, onSpeechStart, onSpeechEnd, onTranscript, onAgentResponse, }) {
|
|
516
676
|
const { theme: contextTheme } = useReactBridgeContext();
|
|
517
677
|
const theme = Object.assign(Object.assign({}, contextTheme), themeOverride);
|
|
518
|
-
const { messages, isLoading, sendChatQuery } = useReactBridge({
|
|
678
|
+
const { messages, isLoading, sendChatQuery, isListening, startVoiceInput, stopVoiceInput } = useReactBridge({
|
|
519
679
|
onIntentDetected,
|
|
520
680
|
currentContext,
|
|
521
681
|
onError,
|
|
682
|
+
onSpeechStart,
|
|
683
|
+
onSpeechEnd,
|
|
684
|
+
onTranscript,
|
|
685
|
+
onAgentResponse,
|
|
522
686
|
});
|
|
523
687
|
const [inputValue, setInputValue] = React.useState('');
|
|
524
688
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
@@ -560,7 +724,7 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
|
|
|
560
724
|
React.createElement("input", { type: "text", value: inputValue, onChange: (e) => setInputValue(e.target.value), onFocus: () => displayMessages.length > 0 && setIsOpen(true), placeholder: placeholder, disabled: isLoading, style: {
|
|
561
725
|
width: '100%',
|
|
562
726
|
padding: theme.spacing.md,
|
|
563
|
-
paddingRight: '
|
|
727
|
+
paddingRight: '140px', // Increased to make room for both mic and search buttons
|
|
564
728
|
fontSize: theme.fontSizes.md,
|
|
565
729
|
border: `1px solid ${theme.colors.border}`,
|
|
566
730
|
borderRadius: theme.borderRadius,
|
|
@@ -569,6 +733,24 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
|
|
|
569
733
|
outline: 'none',
|
|
570
734
|
boxSizing: 'border-box',
|
|
571
735
|
} }),
|
|
736
|
+
React.createElement("button", { type: "button", onClick: isListening ? stopVoiceInput : startVoiceInput, disabled: isLoading, title: isListening ? "Stop recording" : "Start voice input", style: {
|
|
737
|
+
position: 'absolute',
|
|
738
|
+
right: '70px', // Position before the search button
|
|
739
|
+
top: '50%',
|
|
740
|
+
transform: 'translateY(-50%)',
|
|
741
|
+
padding: theme.spacing.sm,
|
|
742
|
+
backgroundColor: isListening ? theme.colors.error : theme.colors.primary,
|
|
743
|
+
color: theme.colors.background,
|
|
744
|
+
border: "none",
|
|
745
|
+
borderRadius: theme.borderRadius,
|
|
746
|
+
cursor: isLoading ? "not-allowed" : "pointer",
|
|
747
|
+
opacity: isLoading ? 0.5 : 1,
|
|
748
|
+
display: "flex",
|
|
749
|
+
alignItems: "center",
|
|
750
|
+
justifyContent: "center",
|
|
751
|
+
width: "32px",
|
|
752
|
+
height: "32px",
|
|
753
|
+
} }, MIC_ICON_SVG),
|
|
572
754
|
React.createElement("button", { type: "submit", disabled: isLoading || !inputValue.trim(), style: {
|
|
573
755
|
position: 'absolute',
|
|
574
756
|
right: theme.spacing.sm,
|
|
@@ -577,7 +759,7 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
|
|
|
577
759
|
padding: `${theme.spacing.xs} ${theme.spacing.md}`,
|
|
578
760
|
fontSize: theme.fontSizes.sm,
|
|
579
761
|
backgroundColor: theme.colors.primary,
|
|
580
|
-
color:
|
|
762
|
+
color: theme.colors.background,
|
|
581
763
|
border: 'none',
|
|
582
764
|
borderRadius: theme.borderRadius,
|
|
583
765
|
cursor: isLoading || !inputValue.trim() ? 'not-allowed' : 'pointer',
|
|
@@ -654,6 +836,8 @@ exports.ReactBridgeAPI = ReactBridgeAPI;
|
|
|
654
836
|
exports.ReactBridgeChatbox = ReactBridgeChatbox;
|
|
655
837
|
exports.ReactBridgeProvider = ReactBridgeProvider;
|
|
656
838
|
exports.ReactBridgeSearch = ReactBridgeSearch;
|
|
839
|
+
exports.WebSpeechSTTProvider = WebSpeechSTTProvider;
|
|
840
|
+
exports.WebSpeechTTSProvider = WebSpeechTTSProvider;
|
|
657
841
|
exports.createCustomTheme = createCustomTheme;
|
|
658
842
|
exports.darkTheme = darkTheme;
|
|
659
843
|
exports.getTheme = getTheme;
|