@eshal-bot/chat-widget 0.1.2 → 0.1.4
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/chat-widget.css +1 -1
- package/dist/chat-widget.esm.css +1 -1
- package/dist/chat-widget.esm.js +4 -4
- package/dist/chat-widget.js +1623 -688
- package/dist/chat-widget.min.js +6 -6
- package/dist/chat-widget.standalone.css +1 -1
- package/dist/chat-widget.umd.js +4 -4
- package/dist/index.css +1 -1
- package/dist/index.d.ts +16 -0
- package/package.json +1 -1
package/dist/chat-widget.js
CHANGED
|
@@ -644,19 +644,145 @@
|
|
|
644
644
|
return null;
|
|
645
645
|
};
|
|
646
646
|
|
|
647
|
+
/**
|
|
648
|
+
* Initializes the PCM audio player worklet that streams inline PCM chunks
|
|
649
|
+
* coming from the ADK websocket events.
|
|
650
|
+
*/
|
|
651
|
+
async function startAudioPlayerWorklet() {
|
|
652
|
+
if (typeof window === 'undefined') {
|
|
653
|
+
throw new Error('Audio player can only be initialized in the browser');
|
|
654
|
+
}
|
|
655
|
+
const audioContext = new AudioContext({
|
|
656
|
+
sampleRate: 24000
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
// For webpack/vite, we need to use a different approach
|
|
660
|
+
// We'll inline the worklet code or use a blob URL
|
|
661
|
+
const workletCode = "\n class PCMPlayerProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this.bufferSize = 24000 * 180;\n this.buffer = new Float32Array(this.bufferSize);\n this.writeIndex = 0;\n this.readIndex = 0;\n this.port.onmessage = (event) => {\n if (event.data?.command === 'endOfAudio') {\n this.readIndex = this.writeIndex;\n return;\n }\n const int16Samples = new Int16Array(event.data);\n this.enqueue(int16Samples);\n };\n }\n\n enqueue(samples) {\n for (let i = 0; i < samples.length; i += 1) {\n const floatVal = samples[i] / 32768;\n this.buffer[this.writeIndex] = floatVal;\n this.writeIndex = (this.writeIndex + 1) % this.bufferSize;\n if (this.writeIndex === this.readIndex) {\n this.readIndex = (this.readIndex + 1) % this.bufferSize;\n }\n }\n }\n\n process(inputs, outputs) {\n const output = outputs[0];\n const framesPerBlock = output[0].length;\n for (let frame = 0; frame < framesPerBlock; frame += 1) {\n output[0][frame] = this.buffer[this.readIndex];\n if (output.length > 1) {\n output[1][frame] = this.buffer[this.readIndex];\n }\n if (this.readIndex !== this.writeIndex) {\n this.readIndex = (this.readIndex + 1) % this.bufferSize;\n }\n }\n return true;\n }\n }\n\n registerProcessor('pcm-player-processor', PCMPlayerProcessor);\n ";
|
|
662
|
+
const blob = new Blob([workletCode], {
|
|
663
|
+
type: 'application/javascript'
|
|
664
|
+
});
|
|
665
|
+
const workletUrl = URL.createObjectURL(blob);
|
|
666
|
+
await audioContext.audioWorklet.addModule(workletUrl);
|
|
667
|
+
const audioPlayerNode = new AudioWorkletNode(audioContext, 'pcm-player-processor');
|
|
668
|
+
audioPlayerNode.connect(audioContext.destination);
|
|
669
|
+
URL.revokeObjectURL(workletUrl);
|
|
670
|
+
return [audioPlayerNode, audioContext];
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Bootstraps the PCM recorder audio worklet, captures mic audio at 16kHz
|
|
675
|
+
* mono, and forwards buffers through the provided handler.
|
|
676
|
+
*/
|
|
677
|
+
async function startAudioRecorderWorklet(onPcmChunk) {
|
|
678
|
+
if (typeof window === 'undefined') {
|
|
679
|
+
throw new Error('Audio recorder can only run in the browser');
|
|
680
|
+
}
|
|
681
|
+
const audioRecorderContext = new AudioContext({
|
|
682
|
+
sampleRate: 16000
|
|
683
|
+
});
|
|
684
|
+
const workletCode = "\n class PCMRecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n if (!inputs.length || !inputs[0].length) {\n return true;\n }\n const inputChannel = inputs[0][0];\n this.port.postMessage(new Float32Array(inputChannel));\n return true;\n }\n }\n\n registerProcessor('pcm-recorder-processor', PCMRecorderProcessor);\n ";
|
|
685
|
+
const blob = new Blob([workletCode], {
|
|
686
|
+
type: 'application/javascript'
|
|
687
|
+
});
|
|
688
|
+
const workletUrl = URL.createObjectURL(blob);
|
|
689
|
+
await audioRecorderContext.audioWorklet.addModule(workletUrl);
|
|
690
|
+
const micStream = await navigator.mediaDevices.getUserMedia({
|
|
691
|
+
audio: {
|
|
692
|
+
channelCount: 1
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
const source = audioRecorderContext.createMediaStreamSource(micStream);
|
|
696
|
+
const audioRecorderNode = new AudioWorkletNode(audioRecorderContext, 'pcm-recorder-processor');
|
|
697
|
+
audioRecorderNode.port.onmessage = event => {
|
|
698
|
+
const pcmData = convertFloat32ToPCM(event.data);
|
|
699
|
+
onPcmChunk(pcmData);
|
|
700
|
+
};
|
|
701
|
+
source.connect(audioRecorderNode);
|
|
702
|
+
URL.revokeObjectURL(workletUrl);
|
|
703
|
+
return [audioRecorderNode, audioRecorderContext, micStream];
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Stops all microphone tracks.
|
|
708
|
+
*/
|
|
709
|
+
function stopMicrophone(stream) {
|
|
710
|
+
if (!stream) {
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
stream.getTracks().forEach(track => track.stop());
|
|
714
|
+
}
|
|
715
|
+
const INT16_MAX = 0x7fff;
|
|
716
|
+
function convertFloat32ToPCM(float32Array) {
|
|
717
|
+
const pcm16Array = new Int16Array(float32Array.length);
|
|
718
|
+
for (let i = 0; i < float32Array.length; i += 1) {
|
|
719
|
+
pcm16Array[i] = Math.max(-1, Math.min(1, float32Array[i])) * INT16_MAX;
|
|
720
|
+
}
|
|
721
|
+
return pcm16Array.buffer;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
var _process$env;
|
|
725
|
+
|
|
726
|
+
// BIDI WebSocket base URL - can be overridden via config
|
|
727
|
+
const BIDI_WS_BASE = typeof process !== 'undefined' && (_process$env = process.env) !== null && _process$env !== void 0 && _process$env.NEXT_PUBLIC_BIDI_WS_BASE ? process.env.NEXT_PUBLIC_BIDI_WS_BASE : 'wss://dev.eshal.ai/knowledge-api/ws';
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Clean CJK (Chinese, Japanese, Korean) spaces
|
|
731
|
+
*/
|
|
732
|
+
const cleanCJKSpaces = value => {
|
|
733
|
+
return value.replace(/([\u3000-\u303f\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uff00-\uffef])\s+([\u3000-\u303f\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uff00-\uffef])/g, '$1$2');
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Convert base64 to ArrayBuffer
|
|
738
|
+
*/
|
|
739
|
+
const base64ToArrayBuffer = base64 => {
|
|
740
|
+
if (typeof window === 'undefined') {
|
|
741
|
+
return new ArrayBuffer(0);
|
|
742
|
+
}
|
|
743
|
+
let normalized = base64.replace(/-/g, '+').replace(/_/g, '/');
|
|
744
|
+
while (normalized.length % 4 !== 0) {
|
|
745
|
+
normalized += '=';
|
|
746
|
+
}
|
|
747
|
+
const binary = window.atob(normalized);
|
|
748
|
+
const len = binary.length;
|
|
749
|
+
const bytes = new Uint8Array(len);
|
|
750
|
+
for (let i = 0; i < len; i += 1) {
|
|
751
|
+
bytes[i] = binary.charCodeAt(i);
|
|
752
|
+
}
|
|
753
|
+
return bytes.buffer;
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Sanitize WebSocket base URL
|
|
758
|
+
*/
|
|
759
|
+
const sanitizeWsBase = value => value.replace(/\/$/, '');
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* CN utility for conditional class names
|
|
763
|
+
*/
|
|
764
|
+
const cn = function () {
|
|
765
|
+
for (var _len = arguments.length, classes = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
766
|
+
classes[_key] = arguments[_key];
|
|
767
|
+
}
|
|
768
|
+
return classes.filter(Boolean).join(' ');
|
|
769
|
+
};
|
|
770
|
+
|
|
647
771
|
const createMessage = _ref => {
|
|
648
772
|
let {
|
|
649
773
|
id,
|
|
650
774
|
role,
|
|
651
775
|
content,
|
|
652
|
-
isProcessing = false
|
|
776
|
+
isProcessing = false,
|
|
777
|
+
metadata
|
|
653
778
|
} = _ref;
|
|
654
779
|
return {
|
|
655
780
|
id,
|
|
656
781
|
role,
|
|
657
782
|
content,
|
|
658
783
|
timestamp: new Date(),
|
|
659
|
-
isProcessing
|
|
784
|
+
isProcessing,
|
|
785
|
+
metadata
|
|
660
786
|
};
|
|
661
787
|
};
|
|
662
788
|
const useChatState = _ref2 => {
|
|
@@ -668,7 +794,8 @@
|
|
|
668
794
|
organizationId,
|
|
669
795
|
autoOpen,
|
|
670
796
|
openDelay,
|
|
671
|
-
darkMode
|
|
797
|
+
darkMode,
|
|
798
|
+
enableVoiceInteraction = false
|
|
672
799
|
} = _ref2;
|
|
673
800
|
const [isOpen, setIsOpen] = reactExports.useState(autoOpen);
|
|
674
801
|
const [isMinimized, setIsMinimized] = reactExports.useState(false);
|
|
@@ -689,6 +816,31 @@
|
|
|
689
816
|
const [isLoading, setIsLoading] = reactExports.useState(false);
|
|
690
817
|
const widgetRef = reactExports.useRef(null);
|
|
691
818
|
const messageIdRef = reactExports.useRef(1);
|
|
819
|
+
|
|
820
|
+
// Bidi/Voice state
|
|
821
|
+
const [isVoiceSessionActive, setIsVoiceSessionActive] = reactExports.useState(false);
|
|
822
|
+
const [bidiMessages, setBidiMessages] = reactExports.useState([]);
|
|
823
|
+
const [voiceStatus, setVoiceStatus] = reactExports.useState("idle"); // 'idle' | 'connecting' | 'connected' | 'error'
|
|
824
|
+
const [voiceError, setVoiceError] = reactExports.useState(null);
|
|
825
|
+
const [bidiSessionId] = reactExports.useState(() => "widget-session-".concat(Math.random().toString(36).slice(2, 9)));
|
|
826
|
+
|
|
827
|
+
// Bidi refs
|
|
828
|
+
const websocketRef = reactExports.useRef(null);
|
|
829
|
+
const audioPlayerNodeRef = reactExports.useRef(null);
|
|
830
|
+
const audioPlayerContextRef = reactExports.useRef(null);
|
|
831
|
+
const audioRecorderNodeRef = reactExports.useRef(null);
|
|
832
|
+
const audioRecorderContextRef = reactExports.useRef(null);
|
|
833
|
+
const micStreamRef = reactExports.useRef(null);
|
|
834
|
+
const currentInputMessageIdRef = reactExports.useRef(null);
|
|
835
|
+
const currentAssistantMessageIdRef = reactExports.useRef(null);
|
|
836
|
+
const isAudioReadyRef = reactExports.useRef(false);
|
|
837
|
+
const isVoiceSessionActiveRef = reactExports.useRef(false);
|
|
838
|
+
reactExports.useRef(null);
|
|
839
|
+
const websocketUrl = reactExports.useMemo(() => {
|
|
840
|
+
if (!organizationId) return null;
|
|
841
|
+
const normalizedBase = sanitizeWsBase(BIDI_WS_BASE);
|
|
842
|
+
return "".concat(normalizedBase, "/").concat(organizationId, "/").concat(bidiSessionId);
|
|
843
|
+
}, [organizationId, bidiSessionId]);
|
|
692
844
|
const getNextMessageId = reactExports.useCallback(() => {
|
|
693
845
|
const id = "msg-".concat(messageIdRef.current);
|
|
694
846
|
messageIdRef.current += 1;
|
|
@@ -840,17 +992,386 @@
|
|
|
840
992
|
const handleQuickQuestion = question => {
|
|
841
993
|
void sendMessage(question);
|
|
842
994
|
};
|
|
995
|
+
|
|
996
|
+
/**
|
|
997
|
+
* Handle user decision for HITL (Human-in-the-Loop)
|
|
998
|
+
*/
|
|
999
|
+
const handleDecision = reactExports.useCallback(async (decisionId, optionId, optionValue) => {
|
|
1000
|
+
// Remove the decision message from the list
|
|
1001
|
+
setMessages(prev => prev.filter(msg => {
|
|
1002
|
+
var _msg$decisionData;
|
|
1003
|
+
return ((_msg$decisionData = msg.decisionData) === null || _msg$decisionData === void 0 ? void 0 : _msg$decisionData.decisionId) !== decisionId;
|
|
1004
|
+
}));
|
|
1005
|
+
|
|
1006
|
+
// Handle the decision based on the selected option
|
|
1007
|
+
if (optionValue === "connect_agent") {
|
|
1008
|
+
// User wants to connect with a human agent
|
|
1009
|
+
const responseMessage = createMessage({
|
|
1010
|
+
id: getNextMessageId(),
|
|
1011
|
+
role: "assistant",
|
|
1012
|
+
content: "Great! I'm setting up a connection with a live customer service agent. Please hold on for a moment while I transfer you."
|
|
1013
|
+
});
|
|
1014
|
+
setMessages(prev => [...prev, responseMessage]);
|
|
1015
|
+
} else if (optionValue === "decline") {
|
|
1016
|
+
// User declined to connect with a human agent
|
|
1017
|
+
const responseMessage = createMessage({
|
|
1018
|
+
id: getNextMessageId(),
|
|
1019
|
+
role: "assistant",
|
|
1020
|
+
content: "I understand. I apologize that I don't have specific information about your query in my knowledge base. Is there anything else I can help you with?"
|
|
1021
|
+
});
|
|
1022
|
+
setMessages(prev => [...prev, responseMessage]);
|
|
1023
|
+
}
|
|
1024
|
+
}, [getNextMessageId]);
|
|
1025
|
+
|
|
1026
|
+
// Bidi/Voice functions
|
|
1027
|
+
const finalizePendingInputMessage = reactExports.useCallback(() => {
|
|
1028
|
+
if (!currentInputMessageIdRef.current) {
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
setBidiMessages(prev => prev.map(message => message.id === currentInputMessageIdRef.current ? _objectSpread2(_objectSpread2({}, message), {}, {
|
|
1032
|
+
isProcessing: false
|
|
1033
|
+
}) : message));
|
|
1034
|
+
currentInputMessageIdRef.current = null;
|
|
1035
|
+
}, []);
|
|
1036
|
+
const appendUserTranscription = reactExports.useCallback(function (text) {
|
|
1037
|
+
let finished = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
1038
|
+
if (!text) {
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
const chunk = cleanCJKSpaces(text);
|
|
1042
|
+
setBidiMessages(prev => {
|
|
1043
|
+
if (!currentInputMessageIdRef.current) {
|
|
1044
|
+
const newId = "bidi-input-".concat(Date.now());
|
|
1045
|
+
currentInputMessageIdRef.current = newId;
|
|
1046
|
+
const userMessage = createMessage({
|
|
1047
|
+
id: newId,
|
|
1048
|
+
role: "user",
|
|
1049
|
+
content: chunk,
|
|
1050
|
+
isProcessing: !finished,
|
|
1051
|
+
metadata: {
|
|
1052
|
+
source: "bidi",
|
|
1053
|
+
transcriptionType: "input"
|
|
1054
|
+
}
|
|
1055
|
+
});
|
|
1056
|
+
return [...prev, userMessage];
|
|
1057
|
+
}
|
|
1058
|
+
return prev.map(message => {
|
|
1059
|
+
if (message.id !== currentInputMessageIdRef.current) {
|
|
1060
|
+
return message;
|
|
1061
|
+
}
|
|
1062
|
+
const combined = cleanCJKSpaces("".concat(message.content || "").concat(chunk));
|
|
1063
|
+
return _objectSpread2(_objectSpread2({}, message), {}, {
|
|
1064
|
+
content: combined,
|
|
1065
|
+
timestamp: new Date(),
|
|
1066
|
+
isProcessing: !finished,
|
|
1067
|
+
metadata: _objectSpread2(_objectSpread2({}, message.metadata), {}, {
|
|
1068
|
+
transcriptionType: "input"
|
|
1069
|
+
})
|
|
1070
|
+
});
|
|
1071
|
+
});
|
|
1072
|
+
});
|
|
1073
|
+
if (finished) {
|
|
1074
|
+
currentInputMessageIdRef.current = null;
|
|
1075
|
+
}
|
|
1076
|
+
}, []);
|
|
1077
|
+
const appendAssistantContent = reactExports.useCallback(function (text) {
|
|
1078
|
+
let finished = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
1079
|
+
if (!text) {
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
finalizePendingInputMessage();
|
|
1083
|
+
setBidiMessages(prev => {
|
|
1084
|
+
if (!currentAssistantMessageIdRef.current) {
|
|
1085
|
+
const newId = "bidi-assistant-".concat(Date.now());
|
|
1086
|
+
currentAssistantMessageIdRef.current = newId;
|
|
1087
|
+
const assistantMessage = createMessage({
|
|
1088
|
+
id: newId,
|
|
1089
|
+
role: "assistant",
|
|
1090
|
+
content: text,
|
|
1091
|
+
isProcessing: !finished,
|
|
1092
|
+
metadata: {
|
|
1093
|
+
source: "bidi"
|
|
1094
|
+
}
|
|
1095
|
+
});
|
|
1096
|
+
return [...prev, assistantMessage];
|
|
1097
|
+
}
|
|
1098
|
+
return prev.map(message => {
|
|
1099
|
+
if (message.id !== currentAssistantMessageIdRef.current) {
|
|
1100
|
+
return message;
|
|
1101
|
+
}
|
|
1102
|
+
return _objectSpread2(_objectSpread2({}, message), {}, {
|
|
1103
|
+
content: "".concat(message.content || "").concat(text),
|
|
1104
|
+
timestamp: new Date(),
|
|
1105
|
+
isProcessing: !finished
|
|
1106
|
+
});
|
|
1107
|
+
});
|
|
1108
|
+
});
|
|
1109
|
+
if (finished) {
|
|
1110
|
+
currentAssistantMessageIdRef.current = null;
|
|
1111
|
+
}
|
|
1112
|
+
}, [finalizePendingInputMessage]);
|
|
1113
|
+
const handleContentParts = reactExports.useCallback(parts => {
|
|
1114
|
+
parts.forEach(part => {
|
|
1115
|
+
var _part$inlineData, _part$inlineData$mime;
|
|
1116
|
+
if ((_part$inlineData = part.inlineData) !== null && _part$inlineData !== void 0 && _part$inlineData.data && (_part$inlineData$mime = part.inlineData.mimeType) !== null && _part$inlineData$mime !== void 0 && _part$inlineData$mime.startsWith("audio/pcm")) {
|
|
1117
|
+
if (audioPlayerNodeRef.current) {
|
|
1118
|
+
audioPlayerNodeRef.current.port.postMessage(base64ToArrayBuffer(part.inlineData.data));
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
if (part.text) {
|
|
1122
|
+
appendAssistantContent(part.text, false);
|
|
1123
|
+
}
|
|
1124
|
+
});
|
|
1125
|
+
}, [appendAssistantContent]);
|
|
1126
|
+
const handleTurnComplete = reactExports.useCallback(() => {
|
|
1127
|
+
currentAssistantMessageIdRef.current = null;
|
|
1128
|
+
currentInputMessageIdRef.current = null;
|
|
1129
|
+
setBidiMessages(prev => prev.map(message => {
|
|
1130
|
+
var _message$metadata;
|
|
1131
|
+
return ((_message$metadata = message.metadata) === null || _message$metadata === void 0 ? void 0 : _message$metadata.source) === "bidi" && message.isProcessing ? _objectSpread2(_objectSpread2({}, message), {}, {
|
|
1132
|
+
isProcessing: false
|
|
1133
|
+
}) : message;
|
|
1134
|
+
}));
|
|
1135
|
+
}, []);
|
|
1136
|
+
const handleInterrupted = reactExports.useCallback(() => {
|
|
1137
|
+
if (audioPlayerNodeRef.current) {
|
|
1138
|
+
audioPlayerNodeRef.current.port.postMessage({
|
|
1139
|
+
command: "endOfAudio"
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
currentAssistantMessageIdRef.current = null;
|
|
1143
|
+
currentInputMessageIdRef.current = null;
|
|
1144
|
+
setBidiMessages(prev => prev.map(message => {
|
|
1145
|
+
var _message$metadata2;
|
|
1146
|
+
return ((_message$metadata2 = message.metadata) === null || _message$metadata2 === void 0 ? void 0 : _message$metadata2.source) === "bidi" ? _objectSpread2(_objectSpread2({}, message), {}, {
|
|
1147
|
+
isProcessing: false,
|
|
1148
|
+
metadata: _objectSpread2(_objectSpread2({}, message.metadata), {}, {
|
|
1149
|
+
interrupted: true
|
|
1150
|
+
})
|
|
1151
|
+
}) : message;
|
|
1152
|
+
}));
|
|
1153
|
+
}, []);
|
|
1154
|
+
const handleBidiEvent = reactExports.useCallback(event => {
|
|
1155
|
+
var _event$inputTranscrip, _event$outputTranscri, _event$content;
|
|
1156
|
+
if (!event) {
|
|
1157
|
+
return;
|
|
1158
|
+
}
|
|
1159
|
+
if (event.turnComplete) {
|
|
1160
|
+
handleTurnComplete();
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
if (event.interrupted) {
|
|
1164
|
+
handleInterrupted();
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
if ((_event$inputTranscrip = event.inputTranscription) !== null && _event$inputTranscrip !== void 0 && _event$inputTranscrip.text) {
|
|
1168
|
+
appendUserTranscription(event.inputTranscription.text, Boolean(event.inputTranscription.finished));
|
|
1169
|
+
}
|
|
1170
|
+
if ((_event$outputTranscri = event.outputTranscription) !== null && _event$outputTranscri !== void 0 && _event$outputTranscri.text) {
|
|
1171
|
+
appendAssistantContent(event.outputTranscription.text, Boolean(event.outputTranscription.finished));
|
|
1172
|
+
}
|
|
1173
|
+
if ((_event$content = event.content) !== null && _event$content !== void 0 && _event$content.parts) {
|
|
1174
|
+
handleContentParts(event.content.parts);
|
|
1175
|
+
}
|
|
1176
|
+
}, [appendAssistantContent, appendUserTranscription, handleContentParts, handleInterrupted, handleTurnComplete]);
|
|
1177
|
+
const handleRecorderAudio = reactExports.useCallback(pcmData => {
|
|
1178
|
+
const ws = websocketRef.current;
|
|
1179
|
+
if (!isVoiceSessionActiveRef.current || !ws || ws.readyState !== WebSocket.OPEN) {
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
ws.send(pcmData);
|
|
1183
|
+
}, []);
|
|
1184
|
+
const initializeAudioPipeline = reactExports.useCallback(async () => {
|
|
1185
|
+
if (isAudioReadyRef.current || typeof window === "undefined") {
|
|
1186
|
+
return;
|
|
1187
|
+
}
|
|
1188
|
+
try {
|
|
1189
|
+
const [playerNode, playerContext] = await startAudioPlayerWorklet();
|
|
1190
|
+
audioPlayerNodeRef.current = playerNode;
|
|
1191
|
+
audioPlayerContextRef.current = playerContext;
|
|
1192
|
+
await playerContext.resume();
|
|
1193
|
+
const [recorderNode, recorderContext, micStream] = await startAudioRecorderWorklet(handleRecorderAudio);
|
|
1194
|
+
audioRecorderNodeRef.current = recorderNode;
|
|
1195
|
+
audioRecorderContextRef.current = recorderContext;
|
|
1196
|
+
micStreamRef.current = micStream;
|
|
1197
|
+
await recorderContext.resume();
|
|
1198
|
+
isAudioReadyRef.current = true;
|
|
1199
|
+
} catch (error) {
|
|
1200
|
+
console.error("Failed to initialize audio pipeline", error);
|
|
1201
|
+
throw error;
|
|
1202
|
+
}
|
|
1203
|
+
}, [handleRecorderAudio]);
|
|
1204
|
+
const connectWebsocket = reactExports.useCallback(() => {
|
|
1205
|
+
if (typeof window === "undefined" || !websocketUrl) {
|
|
1206
|
+
return;
|
|
1207
|
+
}
|
|
1208
|
+
if (websocketRef.current && websocketRef.current.readyState === WebSocket.OPEN) {
|
|
1209
|
+
return;
|
|
1210
|
+
}
|
|
1211
|
+
setVoiceStatus("connecting");
|
|
1212
|
+
setVoiceError(null);
|
|
1213
|
+
try {
|
|
1214
|
+
const ws = new WebSocket(websocketUrl);
|
|
1215
|
+
websocketRef.current = ws;
|
|
1216
|
+
ws.onopen = () => {
|
|
1217
|
+
setVoiceStatus("connected");
|
|
1218
|
+
};
|
|
1219
|
+
ws.onmessage = event => {
|
|
1220
|
+
try {
|
|
1221
|
+
const payload = JSON.parse(event.data);
|
|
1222
|
+
handleBidiEvent(payload);
|
|
1223
|
+
} catch (error) {
|
|
1224
|
+
console.error("Failed to parse ADK event", error);
|
|
1225
|
+
}
|
|
1226
|
+
};
|
|
1227
|
+
ws.onerror = () => {
|
|
1228
|
+
setVoiceStatus("error");
|
|
1229
|
+
setVoiceError("Voice session connection error");
|
|
1230
|
+
};
|
|
1231
|
+
ws.onclose = () => {
|
|
1232
|
+
websocketRef.current = null;
|
|
1233
|
+
setVoiceStatus("idle");
|
|
1234
|
+
if (isVoiceSessionActiveRef.current) {
|
|
1235
|
+
setTimeout(() => {
|
|
1236
|
+
connectWebsocket();
|
|
1237
|
+
}, 5000);
|
|
1238
|
+
}
|
|
1239
|
+
};
|
|
1240
|
+
} catch (error) {
|
|
1241
|
+
console.error("Failed to open voice websocket", error);
|
|
1242
|
+
setVoiceStatus("error");
|
|
1243
|
+
setVoiceError(error instanceof Error ? error.message : "Unable to start voice session");
|
|
1244
|
+
}
|
|
1245
|
+
}, [handleBidiEvent, websocketUrl]);
|
|
1246
|
+
const startVoiceSession = reactExports.useCallback(async () => {
|
|
1247
|
+
if (!enableVoiceInteraction || !organizationId) {
|
|
1248
|
+
return;
|
|
1249
|
+
}
|
|
1250
|
+
setVoiceError(null);
|
|
1251
|
+
setVoiceStatus(prev => prev === "connected" ? prev : "connecting");
|
|
1252
|
+
setIsVoiceSessionActive(true);
|
|
1253
|
+
isVoiceSessionActiveRef.current = true;
|
|
1254
|
+
setBidiMessages(prev => {
|
|
1255
|
+
if (prev.length > 0) {
|
|
1256
|
+
return prev;
|
|
1257
|
+
}
|
|
1258
|
+
if (!welcomeMessage || welcomeMessage.trim() === "") {
|
|
1259
|
+
return [];
|
|
1260
|
+
}
|
|
1261
|
+
const welcomeMsg = createMessage({
|
|
1262
|
+
id: "bidi-welcome-".concat(Date.now()),
|
|
1263
|
+
role: "assistant",
|
|
1264
|
+
content: welcomeMessage,
|
|
1265
|
+
metadata: {
|
|
1266
|
+
source: "bidi"
|
|
1267
|
+
}
|
|
1268
|
+
});
|
|
1269
|
+
return [welcomeMsg];
|
|
1270
|
+
});
|
|
1271
|
+
connectWebsocket();
|
|
1272
|
+
try {
|
|
1273
|
+
await initializeAudioPipeline();
|
|
1274
|
+
} catch (error) {
|
|
1275
|
+
console.error("Failed to start audio pipeline", error);
|
|
1276
|
+
setVoiceError(error instanceof Error ? error.message : "Unable to access microphone");
|
|
1277
|
+
setVoiceStatus("error");
|
|
1278
|
+
}
|
|
1279
|
+
}, [enableVoiceInteraction, organizationId, welcomeMessage, connectWebsocket, initializeAudioPipeline]);
|
|
1280
|
+
const stopVoiceSession = reactExports.useCallback(() => {
|
|
1281
|
+
var _audioPlayerNodeRef$c, _audioPlayerContextRe, _audioRecorderNodeRef, _audioRecorderContext;
|
|
1282
|
+
setIsVoiceSessionActive(false);
|
|
1283
|
+
isVoiceSessionActiveRef.current = false;
|
|
1284
|
+
setVoiceStatus("idle");
|
|
1285
|
+
setVoiceError(null);
|
|
1286
|
+
if (websocketRef.current && websocketRef.current.readyState === WebSocket.OPEN) {
|
|
1287
|
+
websocketRef.current.close();
|
|
1288
|
+
}
|
|
1289
|
+
websocketRef.current = null;
|
|
1290
|
+
(_audioPlayerNodeRef$c = audioPlayerNodeRef.current) === null || _audioPlayerNodeRef$c === void 0 || _audioPlayerNodeRef$c.disconnect();
|
|
1291
|
+
(_audioPlayerContextRe = audioPlayerContextRef.current) === null || _audioPlayerContextRe === void 0 || _audioPlayerContextRe.close();
|
|
1292
|
+
audioPlayerNodeRef.current = null;
|
|
1293
|
+
audioPlayerContextRef.current = null;
|
|
1294
|
+
(_audioRecorderNodeRef = audioRecorderNodeRef.current) === null || _audioRecorderNodeRef === void 0 || _audioRecorderNodeRef.disconnect();
|
|
1295
|
+
(_audioRecorderContext = audioRecorderContextRef.current) === null || _audioRecorderContext === void 0 || _audioRecorderContext.close();
|
|
1296
|
+
audioRecorderNodeRef.current = null;
|
|
1297
|
+
audioRecorderContextRef.current = null;
|
|
1298
|
+
stopMicrophone(micStreamRef.current);
|
|
1299
|
+
micStreamRef.current = null;
|
|
1300
|
+
isAudioReadyRef.current = false;
|
|
1301
|
+
}, []);
|
|
1302
|
+
const handleVoiceToggle = reactExports.useCallback(() => {
|
|
1303
|
+
if (isVoiceSessionActive) {
|
|
1304
|
+
stopVoiceSession();
|
|
1305
|
+
return;
|
|
1306
|
+
}
|
|
1307
|
+
if (voiceStatus === "connecting") {
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
void startVoiceSession();
|
|
1311
|
+
}, [isVoiceSessionActive, startVoiceSession, stopVoiceSession, voiceStatus]);
|
|
1312
|
+
const sendBidiTextMessage = reactExports.useCallback(text => {
|
|
1313
|
+
const trimmed = text.trim();
|
|
1314
|
+
if (!trimmed) {
|
|
1315
|
+
return;
|
|
1316
|
+
}
|
|
1317
|
+
const ws = websocketRef.current;
|
|
1318
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
1319
|
+
setVoiceError("Voice session is not connected yet");
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
ws.send(JSON.stringify({
|
|
1323
|
+
type: "text",
|
|
1324
|
+
text: trimmed
|
|
1325
|
+
}));
|
|
1326
|
+
const userMessage = createMessage({
|
|
1327
|
+
id: "bidi-user-".concat(Date.now()),
|
|
1328
|
+
role: "user",
|
|
1329
|
+
content: trimmed,
|
|
1330
|
+
metadata: {
|
|
1331
|
+
source: "bidi"
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1334
|
+
setBidiMessages(prev => [...prev, userMessage]);
|
|
1335
|
+
setInputValue("");
|
|
1336
|
+
}, []);
|
|
1337
|
+
|
|
1338
|
+
// Cleanup on unmount
|
|
1339
|
+
reactExports.useEffect(() => {
|
|
1340
|
+
isVoiceSessionActiveRef.current = isVoiceSessionActive;
|
|
1341
|
+
}, [isVoiceSessionActive]);
|
|
1342
|
+
reactExports.useEffect(() => {
|
|
1343
|
+
return () => {
|
|
1344
|
+
var _audioPlayerNodeRef$c2, _audioPlayerContextRe2, _audioRecorderNodeRef2, _audioRecorderContext2;
|
|
1345
|
+
if (websocketRef.current && websocketRef.current.readyState === WebSocket.OPEN) {
|
|
1346
|
+
websocketRef.current.close();
|
|
1347
|
+
}
|
|
1348
|
+
(_audioPlayerNodeRef$c2 = audioPlayerNodeRef.current) === null || _audioPlayerNodeRef$c2 === void 0 || _audioPlayerNodeRef$c2.disconnect();
|
|
1349
|
+
(_audioPlayerContextRe2 = audioPlayerContextRef.current) === null || _audioPlayerContextRe2 === void 0 || _audioPlayerContextRe2.close();
|
|
1350
|
+
(_audioRecorderNodeRef2 = audioRecorderNodeRef.current) === null || _audioRecorderNodeRef2 === void 0 || _audioRecorderNodeRef2.disconnect();
|
|
1351
|
+
(_audioRecorderContext2 = audioRecorderContextRef.current) === null || _audioRecorderContext2 === void 0 || _audioRecorderContext2.close();
|
|
1352
|
+
stopMicrophone(micStreamRef.current);
|
|
1353
|
+
micStreamRef.current = null;
|
|
1354
|
+
isAudioReadyRef.current = false;
|
|
1355
|
+
};
|
|
1356
|
+
}, []);
|
|
843
1357
|
const memoizedQuickQuestions = reactExports.useMemo(() => quickQuestions, [quickQuestions]);
|
|
1358
|
+
|
|
1359
|
+
// Determine which messages to use
|
|
1360
|
+
const activeMessages = isVoiceSessionActive ? bidiMessages : messages;
|
|
844
1361
|
return {
|
|
845
1362
|
// State
|
|
846
1363
|
isOpen,
|
|
847
1364
|
isMinimized,
|
|
848
1365
|
isDark,
|
|
849
|
-
messages,
|
|
1366
|
+
messages: activeMessages,
|
|
850
1367
|
inputValue,
|
|
851
1368
|
isLoading,
|
|
852
1369
|
widgetRef,
|
|
853
1370
|
quickQuestions: memoizedQuickQuestions,
|
|
1371
|
+
// Bidi/Voice state
|
|
1372
|
+
isVoiceSessionActive,
|
|
1373
|
+
voiceStatus,
|
|
1374
|
+
voiceError,
|
|
854
1375
|
// Actions
|
|
855
1376
|
setInputValue,
|
|
856
1377
|
handleSend,
|
|
@@ -859,7 +1380,11 @@
|
|
|
859
1380
|
toggleChat,
|
|
860
1381
|
toggleTheme,
|
|
861
1382
|
toggleMinimize,
|
|
862
|
-
closeChat
|
|
1383
|
+
closeChat,
|
|
1384
|
+
handleDecision,
|
|
1385
|
+
// Bidi/Voice actions
|
|
1386
|
+
handleVoiceToggle,
|
|
1387
|
+
sendBidiTextMessage
|
|
863
1388
|
};
|
|
864
1389
|
};
|
|
865
1390
|
|
|
@@ -923,13 +1448,13 @@
|
|
|
923
1448
|
*/
|
|
924
1449
|
|
|
925
1450
|
|
|
926
|
-
const
|
|
927
|
-
["path", { d: "
|
|
928
|
-
["
|
|
929
|
-
["path", { d: "
|
|
930
|
-
["path", { d: "
|
|
931
|
-
["path", { d: "
|
|
932
|
-
["path", { d: "
|
|
1451
|
+
const AudioLines = createLucideIcon("AudioLines", [
|
|
1452
|
+
["path", { d: "M2 10v3", key: "1fnikh" }],
|
|
1453
|
+
["path", { d: "M6 6v11", key: "11sgs0" }],
|
|
1454
|
+
["path", { d: "M10 3v18", key: "yhl04a" }],
|
|
1455
|
+
["path", { d: "M14 8v7", key: "3a1oy3" }],
|
|
1456
|
+
["path", { d: "M18 5v13", key: "123xd1" }],
|
|
1457
|
+
["path", { d: "M22 10v3", key: "154ddg" }]
|
|
933
1458
|
]);
|
|
934
1459
|
|
|
935
1460
|
/**
|
|
@@ -940,11 +1465,8 @@
|
|
|
940
1465
|
*/
|
|
941
1466
|
|
|
942
1467
|
|
|
943
|
-
const
|
|
944
|
-
["
|
|
945
|
-
["polyline", { points: "9 21 3 21 3 15", key: "1avn1i" }],
|
|
946
|
-
["line", { x1: "21", x2: "14", y1: "3", y2: "10", key: "ota7mn" }],
|
|
947
|
-
["line", { x1: "3", x2: "10", y1: "21", y2: "14", key: "1atl0r" }]
|
|
1468
|
+
const Loader2 = createLucideIcon("Loader2", [
|
|
1469
|
+
["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]
|
|
948
1470
|
]);
|
|
949
1471
|
|
|
950
1472
|
/**
|
|
@@ -955,10 +1477,11 @@
|
|
|
955
1477
|
*/
|
|
956
1478
|
|
|
957
1479
|
|
|
958
|
-
const
|
|
959
|
-
["
|
|
960
|
-
["
|
|
961
|
-
["
|
|
1480
|
+
const Maximize2 = createLucideIcon("Maximize2", [
|
|
1481
|
+
["polyline", { points: "15 3 21 3 21 9", key: "mznyad" }],
|
|
1482
|
+
["polyline", { points: "9 21 3 21 3 15", key: "1avn1i" }],
|
|
1483
|
+
["line", { x1: "21", x2: "14", y1: "3", y2: "10", key: "ota7mn" }],
|
|
1484
|
+
["line", { x1: "3", x2: "10", y1: "21", y2: "14", key: "1atl0r" }]
|
|
962
1485
|
]);
|
|
963
1486
|
|
|
964
1487
|
/**
|
|
@@ -1059,322 +1582,6 @@
|
|
|
1059
1582
|
["path", { d: "m6 6 12 12", key: "d8bk6v" }]
|
|
1060
1583
|
]);
|
|
1061
1584
|
|
|
1062
|
-
var jsxRuntime = {exports: {}};
|
|
1063
|
-
|
|
1064
|
-
var reactJsxRuntime_production_min = {};
|
|
1065
|
-
|
|
1066
|
-
/**
|
|
1067
|
-
* @license React
|
|
1068
|
-
* react-jsx-runtime.production.min.js
|
|
1069
|
-
*
|
|
1070
|
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
1071
|
-
*
|
|
1072
|
-
* This source code is licensed under the MIT license found in the
|
|
1073
|
-
* LICENSE file in the root directory of this source tree.
|
|
1074
|
-
*/
|
|
1075
|
-
var f=reactExports,k=Symbol.for("react.element"),l=Symbol.for("react.fragment"),m=Object.prototype.hasOwnProperty,n=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,p={key:!0,ref:!0,__self:!0,__source:!0};
|
|
1076
|
-
function q(c,a,g){var b,d={},e=null,h=null;void 0!==g&&(e=""+g);void 0!==a.key&&(e=""+a.key);void 0!==a.ref&&(h=a.ref);for(b in a)m.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return {$$typeof:k,type:c,key:e,ref:h,props:d,_owner:n.current}}reactJsxRuntime_production_min.Fragment=l;reactJsxRuntime_production_min.jsx=q;reactJsxRuntime_production_min.jsxs=q;
|
|
1077
|
-
|
|
1078
|
-
{
|
|
1079
|
-
jsxRuntime.exports = reactJsxRuntime_production_min;
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
var jsxRuntimeExports = jsxRuntime.exports;
|
|
1083
|
-
|
|
1084
|
-
const LOGO_MAX_HEIGHT = "3.5rem";
|
|
1085
|
-
const LOGO_MAX_HEIGHT_COMPACT = "2.5rem";
|
|
1086
|
-
const LOGO_MAX_WIDTH_DEFAULT = "4.5rem";
|
|
1087
|
-
const LOGO_MAX_WIDTH_DEFAULT_COMPACT = "3rem";
|
|
1088
|
-
const LOGO_MAX_WIDTH_WIDE = "9rem";
|
|
1089
|
-
const LOGO_MAX_WIDTH_WIDE_COMPACT = "5.5rem";
|
|
1090
|
-
const STATUS_DOT_SIZE = "0.8rem";
|
|
1091
|
-
const STATUS_DOT_SIZE_COMPACT = "0.65rem";
|
|
1092
|
-
const STATUS_DOT_BORDER_WIDTH = "2px";
|
|
1093
|
-
const STATUS_DOT_BORDER_WIDTH_COMPACT = "1.5px";
|
|
1094
|
-
const STATUS_DOT_DEFAULT_COLOR = "#34d399";
|
|
1095
|
-
const STATUS_DOT_OFFSET = "38%";
|
|
1096
|
-
const STATUS_DOT_OFFSET_COMPACT = "22%";
|
|
1097
|
-
const LogoImage = _ref => {
|
|
1098
|
-
let {
|
|
1099
|
-
src,
|
|
1100
|
-
showStatusDot = false,
|
|
1101
|
-
statusColor = STATUS_DOT_DEFAULT_COLOR,
|
|
1102
|
-
size = "default"
|
|
1103
|
-
} = _ref;
|
|
1104
|
-
const [aspect, setAspect] = reactExports.useState("square");
|
|
1105
|
-
const isCompact = size === "compact";
|
|
1106
|
-
reactExports.useEffect(() => {
|
|
1107
|
-
if (typeof window === "undefined" || !src) {
|
|
1108
|
-
return;
|
|
1109
|
-
}
|
|
1110
|
-
const img = new Image();
|
|
1111
|
-
img.src = src;
|
|
1112
|
-
img.onload = () => {
|
|
1113
|
-
if (img.width > img.height) {
|
|
1114
|
-
setAspect("wide");
|
|
1115
|
-
} else if (img.height > img.width) {
|
|
1116
|
-
setAspect("tall");
|
|
1117
|
-
} else {
|
|
1118
|
-
setAspect("square");
|
|
1119
|
-
}
|
|
1120
|
-
};
|
|
1121
|
-
}, [src]);
|
|
1122
|
-
const containerStyle = {
|
|
1123
|
-
position: "relative",
|
|
1124
|
-
display: "inline-flex"
|
|
1125
|
-
};
|
|
1126
|
-
const imageStyle = {
|
|
1127
|
-
display: "block",
|
|
1128
|
-
objectFit: "contain",
|
|
1129
|
-
height: "auto",
|
|
1130
|
-
width: "auto",
|
|
1131
|
-
maxHeight: isCompact ? LOGO_MAX_HEIGHT_COMPACT : LOGO_MAX_HEIGHT,
|
|
1132
|
-
maxWidth: isCompact ? LOGO_MAX_WIDTH_DEFAULT_COMPACT : LOGO_MAX_WIDTH_DEFAULT
|
|
1133
|
-
};
|
|
1134
|
-
if (aspect === "wide") {
|
|
1135
|
-
imageStyle.maxWidth = isCompact ? LOGO_MAX_WIDTH_WIDE_COMPACT : LOGO_MAX_WIDTH_WIDE;
|
|
1136
|
-
}
|
|
1137
|
-
if (aspect === "tall") {
|
|
1138
|
-
imageStyle.maxHeight = isCompact ? "3rem" : "4rem";
|
|
1139
|
-
imageStyle.maxWidth = isCompact ? "3rem" : "4rem";
|
|
1140
|
-
}
|
|
1141
|
-
return /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
1142
|
-
style: containerStyle,
|
|
1143
|
-
children: [/*#__PURE__*/jsxRuntimeExports.jsx("img", {
|
|
1144
|
-
src: src,
|
|
1145
|
-
alt: "Logo",
|
|
1146
|
-
style: imageStyle,
|
|
1147
|
-
loading: "lazy"
|
|
1148
|
-
}), showStatusDot && /*#__PURE__*/jsxRuntimeExports.jsx("span", {
|
|
1149
|
-
style: {
|
|
1150
|
-
position: "absolute",
|
|
1151
|
-
bottom: 0,
|
|
1152
|
-
right: 0,
|
|
1153
|
-
width: isCompact ? STATUS_DOT_SIZE_COMPACT : STATUS_DOT_SIZE,
|
|
1154
|
-
height: isCompact ? STATUS_DOT_SIZE_COMPACT : STATUS_DOT_SIZE,
|
|
1155
|
-
borderRadius: "9999px",
|
|
1156
|
-
backgroundColor: statusColor,
|
|
1157
|
-
border: "".concat(isCompact ? STATUS_DOT_BORDER_WIDTH_COMPACT : STATUS_DOT_BORDER_WIDTH, " solid #ffffff"),
|
|
1158
|
-
transform: "translate(".concat(isCompact ? STATUS_DOT_OFFSET_COMPACT : STATUS_DOT_OFFSET, ", ").concat(isCompact ? STATUS_DOT_OFFSET_COMPACT : STATUS_DOT_OFFSET, ")"),
|
|
1159
|
-
pointerEvents: "none"
|
|
1160
|
-
}
|
|
1161
|
-
})]
|
|
1162
|
-
});
|
|
1163
|
-
};
|
|
1164
|
-
|
|
1165
|
-
const IS_BROWSER = typeof window !== "undefined";
|
|
1166
|
-
const SYSTEM_FONT_FAMILIES = new Set(["Arial", "Helvetica", "Times New Roman", "Georgia", "Courier New", "Verdana", "Trebuchet MS", "Palatino", "Garamond", "Tahoma", "Lucida Sans", "Lucida Grande", "Lucida Console", "Gill Sans", "Impact", "Comic Sans MS", "system-ui"].map(font => font.toLowerCase()));
|
|
1167
|
-
const GENERIC_FONT_KEYWORDS = ["sans-serif", "serif", "monospace", "cursive", "fantasy"];
|
|
1168
|
-
const GOOGLE_FONT_WEIGHTS = "300,400,500,600,700";
|
|
1169
|
-
const loadedFonts = new Set();
|
|
1170
|
-
let webFontLoaderPromise = null;
|
|
1171
|
-
const shouldSkipLoading = fontFamily => {
|
|
1172
|
-
const normalized = fontFamily.trim().toLowerCase();
|
|
1173
|
-
if (!normalized) return true;
|
|
1174
|
-
if (SYSTEM_FONT_FAMILIES.has(normalized)) return true;
|
|
1175
|
-
return GENERIC_FONT_KEYWORDS.some(keyword => normalized.includes(keyword));
|
|
1176
|
-
};
|
|
1177
|
-
const toGoogleFontQuery = fontFamily => fontFamily.trim().replace(/\s+/g, "+");
|
|
1178
|
-
function useGoogleFont(fontFamily) {
|
|
1179
|
-
reactExports.useEffect(() => {
|
|
1180
|
-
var _fontFamily$split$;
|
|
1181
|
-
if (!IS_BROWSER || !fontFamily) {
|
|
1182
|
-
return;
|
|
1183
|
-
}
|
|
1184
|
-
const baseFont = (_fontFamily$split$ = fontFamily.split(",")[0]) === null || _fontFamily$split$ === void 0 ? void 0 : _fontFamily$split$.trim();
|
|
1185
|
-
if (!baseFont || loadedFonts.has(baseFont)) {
|
|
1186
|
-
return;
|
|
1187
|
-
}
|
|
1188
|
-
if (shouldSkipLoading(baseFont)) {
|
|
1189
|
-
loadedFonts.add(baseFont);
|
|
1190
|
-
return;
|
|
1191
|
-
}
|
|
1192
|
-
let isMounted = true;
|
|
1193
|
-
const loadFont = async () => {
|
|
1194
|
-
try {
|
|
1195
|
-
if (!webFontLoaderPromise) {
|
|
1196
|
-
webFontLoaderPromise = Promise.resolve().then(function () { return webfontloader; });
|
|
1197
|
-
}
|
|
1198
|
-
const webFontModule = await webFontLoaderPromise;
|
|
1199
|
-
const WebFont = webFontModule && "default" in webFontModule ? webFontModule.default : webFontModule;
|
|
1200
|
-
const googleQuery = toGoogleFontQuery(baseFont);
|
|
1201
|
-
WebFont.load({
|
|
1202
|
-
google: {
|
|
1203
|
-
families: ["".concat(googleQuery, ":").concat(GOOGLE_FONT_WEIGHTS)]
|
|
1204
|
-
},
|
|
1205
|
-
fontactive: family => {
|
|
1206
|
-
if (isMounted) {
|
|
1207
|
-
loadedFonts.add(family);
|
|
1208
|
-
}
|
|
1209
|
-
},
|
|
1210
|
-
fontinactive: family => {
|
|
1211
|
-
if (isMounted) {
|
|
1212
|
-
loadedFonts.add(family);
|
|
1213
|
-
}
|
|
1214
|
-
console.warn("Warning: failed to load Google Font: ".concat(family));
|
|
1215
|
-
}
|
|
1216
|
-
});
|
|
1217
|
-
} catch (error) {
|
|
1218
|
-
console.error("Warning: WebFont loader error:", error);
|
|
1219
|
-
}
|
|
1220
|
-
};
|
|
1221
|
-
void loadFont();
|
|
1222
|
-
return () => {
|
|
1223
|
-
isMounted = false;
|
|
1224
|
-
};
|
|
1225
|
-
}, [fontFamily]);
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
|
-
const lightenColor = function (color) {
|
|
1229
|
-
let amount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.12;
|
|
1230
|
-
if (!color) {
|
|
1231
|
-
return color;
|
|
1232
|
-
}
|
|
1233
|
-
const hexMatch = color.trim().match(/^#([0-9a-f]{3,8})$/i);
|
|
1234
|
-
if (!hexMatch) {
|
|
1235
|
-
return color;
|
|
1236
|
-
}
|
|
1237
|
-
let hex = hexMatch[1];
|
|
1238
|
-
if (hex.length === 3) {
|
|
1239
|
-
hex = hex.split("").map(char => char + char).join("");
|
|
1240
|
-
}
|
|
1241
|
-
if (hex.length === 8) {
|
|
1242
|
-
hex = hex.slice(0, 6);
|
|
1243
|
-
}
|
|
1244
|
-
if (hex.length !== 6) {
|
|
1245
|
-
return color;
|
|
1246
|
-
}
|
|
1247
|
-
const num = parseInt(hex, 16);
|
|
1248
|
-
const r = num >> 16 & 255;
|
|
1249
|
-
const g = num >> 8 & 255;
|
|
1250
|
-
const b = num & 255;
|
|
1251
|
-
const mix = channel => {
|
|
1252
|
-
const mixed = Math.round(channel + (255 - channel) * amount);
|
|
1253
|
-
return Math.min(255, Math.max(0, mixed));
|
|
1254
|
-
};
|
|
1255
|
-
const [lr, lg, lb] = [mix(r), mix(g), mix(b)];
|
|
1256
|
-
const toHex = channel => channel.toString(16).padStart(2, "0");
|
|
1257
|
-
return "#".concat(toHex(lr)).concat(toHex(lg)).concat(toHex(lb));
|
|
1258
|
-
};
|
|
1259
|
-
const ChatHeader = _ref => {
|
|
1260
|
-
let {
|
|
1261
|
-
companyName,
|
|
1262
|
-
companyLogo,
|
|
1263
|
-
primaryColor,
|
|
1264
|
-
isDark,
|
|
1265
|
-
isMinimized = false,
|
|
1266
|
-
textColor,
|
|
1267
|
-
fontFamily,
|
|
1268
|
-
fontSize,
|
|
1269
|
-
onToggleTheme,
|
|
1270
|
-
onMinimize,
|
|
1271
|
-
onClose
|
|
1272
|
-
} = _ref;
|
|
1273
|
-
useGoogleFont(fontFamily);
|
|
1274
|
-
return /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
1275
|
-
className: "text-white ".concat(isMinimized ? "px-4 py-2.5" : "px-5 py-4", " flex items-center justify-between relative overflow-hidden rounded-t-2xl"),
|
|
1276
|
-
style: {
|
|
1277
|
-
background: "linear-gradient(135deg, ".concat(primaryColor, " 0%, ").concat(lightenColor(primaryColor, 0.2), " 100%)"),
|
|
1278
|
-
fontFamily
|
|
1279
|
-
},
|
|
1280
|
-
children: [/*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
1281
|
-
className: "absolute inset-0 pointer-events-none transition-opacity duration-200 ".concat(isMinimized ? "opacity-0" : "opacity-100", " bg-gradient-to-br from-white/10 to-transparent")
|
|
1282
|
-
}), /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
1283
|
-
className: "flex items-center ".concat(isMinimized ? "gap-1.5" : "gap-3", " relative z-10 min-w-0"),
|
|
1284
|
-
children: [companyLogo ? /*#__PURE__*/jsxRuntimeExports.jsx(LogoImage, {
|
|
1285
|
-
src: companyLogo,
|
|
1286
|
-
showStatusDot: true,
|
|
1287
|
-
statusColor: "#34d399",
|
|
1288
|
-
size: isMinimized ? "compact" : "default"
|
|
1289
|
-
}) : /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
1290
|
-
className: "relative",
|
|
1291
|
-
children: [/*#__PURE__*/jsxRuntimeExports.jsx(MessageCircle, {
|
|
1292
|
-
className: "transition-all ".concat(isMinimized ? "w-8 h-8" : "w-10 h-10")
|
|
1293
|
-
}), /*#__PURE__*/jsxRuntimeExports.jsx("span", {
|
|
1294
|
-
className: "absolute rounded-full",
|
|
1295
|
-
style: {
|
|
1296
|
-
bottom: 0,
|
|
1297
|
-
right: 0,
|
|
1298
|
-
width: isMinimized ? "0.65rem" : "0.8rem",
|
|
1299
|
-
height: isMinimized ? "0.65rem" : "0.8rem",
|
|
1300
|
-
backgroundColor: "#34d399",
|
|
1301
|
-
border: isMinimized ? "1.5px solid #ffffff" : "2px solid #ffffff",
|
|
1302
|
-
transform: "translate(".concat(isMinimized ? "22%" : "38%", ", ").concat(isMinimized ? "22%" : "38%", ")"),
|
|
1303
|
-
pointerEvents: "none"
|
|
1304
|
-
}
|
|
1305
|
-
})]
|
|
1306
|
-
}), /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
1307
|
-
className: "flex items-center gap-2 min-w-0",
|
|
1308
|
-
children: /*#__PURE__*/jsxRuntimeExports.jsx("h3", {
|
|
1309
|
-
className: "font-semibold leading-tight truncate",
|
|
1310
|
-
style: {
|
|
1311
|
-
fontSize: fontSize ? "calc(".concat(fontSize, " + ").concat(isMinimized ? "6px" : "10px", ")") : isMinimized ? "13px" : "15px",
|
|
1312
|
-
color: textColor || "#FFFFFF"
|
|
1313
|
-
},
|
|
1314
|
-
children: companyName
|
|
1315
|
-
})
|
|
1316
|
-
})]
|
|
1317
|
-
}), /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
1318
|
-
className: "flex items-center ".concat(isMinimized ? "gap-3" : "gap-4", " relative z-10 text-white"),
|
|
1319
|
-
children: [/*#__PURE__*/jsxRuntimeExports.jsx("span", {
|
|
1320
|
-
role: "button",
|
|
1321
|
-
tabIndex: 0,
|
|
1322
|
-
"aria-label": "Toggle theme",
|
|
1323
|
-
onClick: onToggleTheme,
|
|
1324
|
-
onKeyDown: event => {
|
|
1325
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
1326
|
-
event.preventDefault();
|
|
1327
|
-
onToggleTheme === null || onToggleTheme === void 0 || onToggleTheme(event);
|
|
1328
|
-
}
|
|
1329
|
-
},
|
|
1330
|
-
className: "inline-flex h-8 w-8 items-center justify-center cursor-pointer transition-opacity duration-200 hover:opacity-80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/40 rounded-full",
|
|
1331
|
-
children: isDark ? /*#__PURE__*/jsxRuntimeExports.jsx(Sun, {
|
|
1332
|
-
className: "w-4 h-4",
|
|
1333
|
-
strokeWidth: 1.6
|
|
1334
|
-
}) : /*#__PURE__*/jsxRuntimeExports.jsx(Moon, {
|
|
1335
|
-
className: "w-4 h-4",
|
|
1336
|
-
strokeWidth: 1.6
|
|
1337
|
-
})
|
|
1338
|
-
}), onMinimize && /*#__PURE__*/jsxRuntimeExports.jsx("span", {
|
|
1339
|
-
role: "button",
|
|
1340
|
-
tabIndex: 0,
|
|
1341
|
-
"aria-label": isMinimized ? "Expand" : "Minimize",
|
|
1342
|
-
onClick: onMinimize,
|
|
1343
|
-
onKeyDown: event => {
|
|
1344
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
1345
|
-
event.preventDefault();
|
|
1346
|
-
onMinimize === null || onMinimize === void 0 || onMinimize(event);
|
|
1347
|
-
}
|
|
1348
|
-
},
|
|
1349
|
-
className: "inline-flex h-8 w-8 items-center justify-center cursor-pointer transition-opacity duration-200 hover:opacity-80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/40 rounded-full",
|
|
1350
|
-
children: isMinimized ? /*#__PURE__*/jsxRuntimeExports.jsx(Maximize2, {
|
|
1351
|
-
className: "w-4 h-4",
|
|
1352
|
-
strokeWidth: 1.6
|
|
1353
|
-
}) : /*#__PURE__*/jsxRuntimeExports.jsx(Minimize2, {
|
|
1354
|
-
className: "w-4 h-4",
|
|
1355
|
-
strokeWidth: 1.6
|
|
1356
|
-
})
|
|
1357
|
-
}), /*#__PURE__*/jsxRuntimeExports.jsx("span", {
|
|
1358
|
-
role: "button",
|
|
1359
|
-
tabIndex: 0,
|
|
1360
|
-
"aria-label": "Close",
|
|
1361
|
-
onClick: onClose,
|
|
1362
|
-
onKeyDown: event => {
|
|
1363
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
1364
|
-
event.preventDefault();
|
|
1365
|
-
onClose === null || onClose === void 0 || onClose(event);
|
|
1366
|
-
}
|
|
1367
|
-
},
|
|
1368
|
-
className: "inline-flex h-8 w-8 items-center justify-center cursor-pointer transition-opacity duration-200 hover:opacity-80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/40 rounded-full",
|
|
1369
|
-
children: /*#__PURE__*/jsxRuntimeExports.jsx(X, {
|
|
1370
|
-
className: "w-4 h-4",
|
|
1371
|
-
strokeWidth: 1.6
|
|
1372
|
-
})
|
|
1373
|
-
})]
|
|
1374
|
-
})]
|
|
1375
|
-
});
|
|
1376
|
-
};
|
|
1377
|
-
|
|
1378
1585
|
function ok$2() {}
|
|
1379
1586
|
|
|
1380
1587
|
function unreachable() {}
|
|
@@ -4507,6 +4714,28 @@
|
|
|
4507
4714
|
]
|
|
4508
4715
|
};
|
|
4509
4716
|
|
|
4717
|
+
var jsxRuntime = {exports: {}};
|
|
4718
|
+
|
|
4719
|
+
var reactJsxRuntime_production_min = {};
|
|
4720
|
+
|
|
4721
|
+
/**
|
|
4722
|
+
* @license React
|
|
4723
|
+
* react-jsx-runtime.production.min.js
|
|
4724
|
+
*
|
|
4725
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4726
|
+
*
|
|
4727
|
+
* This source code is licensed under the MIT license found in the
|
|
4728
|
+
* LICENSE file in the root directory of this source tree.
|
|
4729
|
+
*/
|
|
4730
|
+
var f=reactExports,k=Symbol.for("react.element"),l=Symbol.for("react.fragment"),m=Object.prototype.hasOwnProperty,n=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,p={key:!0,ref:!0,__self:!0,__source:!0};
|
|
4731
|
+
function q(c,a,g){var b,d={},e=null,h=null;void 0!==g&&(e=""+g);void 0!==a.key&&(e=""+a.key);void 0!==a.ref&&(h=a.ref);for(b in a)m.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return {$$typeof:k,type:c,key:e,ref:h,props:d,_owner:n.current}}reactJsxRuntime_production_min.Fragment=l;reactJsxRuntime_production_min.jsx=q;reactJsxRuntime_production_min.jsxs=q;
|
|
4732
|
+
|
|
4733
|
+
{
|
|
4734
|
+
jsxRuntime.exports = reactJsxRuntime_production_min;
|
|
4735
|
+
}
|
|
4736
|
+
|
|
4737
|
+
var jsxRuntimeExports = jsxRuntime.exports;
|
|
4738
|
+
|
|
4510
4739
|
/**
|
|
4511
4740
|
* @typedef {import('mdast').Nodes} Nodes
|
|
4512
4741
|
*
|
|
@@ -55073,24 +55302,91 @@
|
|
|
55073
55302
|
}
|
|
55074
55303
|
};
|
|
55075
55304
|
|
|
55305
|
+
const IS_BROWSER = typeof window !== "undefined";
|
|
55306
|
+
const SYSTEM_FONT_FAMILIES = new Set(["Arial", "Helvetica", "Times New Roman", "Georgia", "Courier New", "Verdana", "Trebuchet MS", "Palatino", "Garamond", "Tahoma", "Lucida Sans", "Lucida Grande", "Lucida Console", "Gill Sans", "Impact", "Comic Sans MS", "system-ui"].map(font => font.toLowerCase()));
|
|
55307
|
+
const GENERIC_FONT_KEYWORDS = ["sans-serif", "serif", "monospace", "cursive", "fantasy"];
|
|
55308
|
+
const GOOGLE_FONT_WEIGHTS = "300,400,500,600,700";
|
|
55309
|
+
const loadedFonts = new Set();
|
|
55310
|
+
let webFontLoaderPromise = null;
|
|
55311
|
+
const shouldSkipLoading = fontFamily => {
|
|
55312
|
+
const normalized = fontFamily.trim().toLowerCase();
|
|
55313
|
+
if (!normalized) return true;
|
|
55314
|
+
if (SYSTEM_FONT_FAMILIES.has(normalized)) return true;
|
|
55315
|
+
return GENERIC_FONT_KEYWORDS.some(keyword => normalized.includes(keyword));
|
|
55316
|
+
};
|
|
55317
|
+
const toGoogleFontQuery = fontFamily => fontFamily.trim().replace(/\s+/g, "+");
|
|
55318
|
+
function useGoogleFont(fontFamily) {
|
|
55319
|
+
reactExports.useEffect(() => {
|
|
55320
|
+
var _fontFamily$split$;
|
|
55321
|
+
if (!IS_BROWSER || !fontFamily) {
|
|
55322
|
+
return;
|
|
55323
|
+
}
|
|
55324
|
+
const baseFont = (_fontFamily$split$ = fontFamily.split(",")[0]) === null || _fontFamily$split$ === void 0 ? void 0 : _fontFamily$split$.trim();
|
|
55325
|
+
if (!baseFont || loadedFonts.has(baseFont)) {
|
|
55326
|
+
return;
|
|
55327
|
+
}
|
|
55328
|
+
if (shouldSkipLoading(baseFont)) {
|
|
55329
|
+
loadedFonts.add(baseFont);
|
|
55330
|
+
return;
|
|
55331
|
+
}
|
|
55332
|
+
let isMounted = true;
|
|
55333
|
+
const loadFont = async () => {
|
|
55334
|
+
try {
|
|
55335
|
+
if (!webFontLoaderPromise) {
|
|
55336
|
+
webFontLoaderPromise = Promise.resolve().then(function () { return webfontloader; });
|
|
55337
|
+
}
|
|
55338
|
+
const webFontModule = await webFontLoaderPromise;
|
|
55339
|
+
const WebFont = webFontModule && "default" in webFontModule ? webFontModule.default : webFontModule;
|
|
55340
|
+
const googleQuery = toGoogleFontQuery(baseFont);
|
|
55341
|
+
WebFont.load({
|
|
55342
|
+
google: {
|
|
55343
|
+
families: ["".concat(googleQuery, ":").concat(GOOGLE_FONT_WEIGHTS)]
|
|
55344
|
+
},
|
|
55345
|
+
fontactive: family => {
|
|
55346
|
+
if (isMounted) {
|
|
55347
|
+
loadedFonts.add(family);
|
|
55348
|
+
}
|
|
55349
|
+
},
|
|
55350
|
+
fontinactive: family => {
|
|
55351
|
+
if (isMounted) {
|
|
55352
|
+
loadedFonts.add(family);
|
|
55353
|
+
}
|
|
55354
|
+
console.warn("Warning: failed to load Google Font: ".concat(family));
|
|
55355
|
+
}
|
|
55356
|
+
});
|
|
55357
|
+
} catch (error) {
|
|
55358
|
+
console.error("Warning: WebFont loader error:", error);
|
|
55359
|
+
}
|
|
55360
|
+
};
|
|
55361
|
+
void loadFont();
|
|
55362
|
+
return () => {
|
|
55363
|
+
isMounted = false;
|
|
55364
|
+
};
|
|
55365
|
+
}, [fontFamily]);
|
|
55366
|
+
}
|
|
55367
|
+
|
|
55076
55368
|
const _excluded = ["node", "children"],
|
|
55077
55369
|
_excluded2 = ["node", "children"],
|
|
55078
55370
|
_excluded3 = ["node", "children"],
|
|
55079
55371
|
_excluded4 = ["node", "children"],
|
|
55080
|
-
_excluded5 = ["
|
|
55372
|
+
_excluded5 = ["node", "children"],
|
|
55081
55373
|
_excluded6 = ["node", "children"],
|
|
55082
55374
|
_excluded7 = ["node", "children"],
|
|
55083
55375
|
_excluded8 = ["node", "children"],
|
|
55084
55376
|
_excluded9 = ["node", "children"],
|
|
55085
55377
|
_excluded0 = ["node", "children"],
|
|
55086
55378
|
_excluded1 = ["node", "children"],
|
|
55087
|
-
_excluded10 = ["node", "children"]
|
|
55379
|
+
_excluded10 = ["node", "children"],
|
|
55380
|
+
_excluded11 = ["className", "children"];
|
|
55088
55381
|
const StreamingMarkdown = _ref => {
|
|
55089
55382
|
let {
|
|
55090
55383
|
content,
|
|
55091
55384
|
isStreaming,
|
|
55092
55385
|
isDark = false,
|
|
55093
|
-
isRtl = false
|
|
55386
|
+
isRtl = false,
|
|
55387
|
+
textColor,
|
|
55388
|
+
fontFamily,
|
|
55389
|
+
fontSize
|
|
55094
55390
|
} = _ref;
|
|
55095
55391
|
const [displayedContent, setDisplayedContent] = reactExports.useState("");
|
|
55096
55392
|
const [showCursor, setShowCursor] = reactExports.useState(false);
|
|
@@ -55099,19 +55395,23 @@
|
|
|
55099
55395
|
const animationFrameRef = reactExports.useRef(null);
|
|
55100
55396
|
const lastUpdateRef = reactExports.useRef(0);
|
|
55101
55397
|
reactExports.useEffect(() => {
|
|
55398
|
+
// Reset if content changes significantly
|
|
55102
55399
|
if (content !== contentRef.current) {
|
|
55103
55400
|
contentRef.current = content;
|
|
55401
|
+
// If we're already past the new content length, show it all
|
|
55104
55402
|
if (indexRef.current >= content.length) {
|
|
55105
55403
|
setDisplayedContent(content);
|
|
55106
55404
|
setShowCursor(false);
|
|
55107
55405
|
return;
|
|
55108
55406
|
}
|
|
55407
|
+
// If new content is shorter, reset
|
|
55109
55408
|
if (content.length < displayedContent.length) {
|
|
55110
55409
|
indexRef.current = 0;
|
|
55111
55410
|
setDisplayedContent("");
|
|
55112
55411
|
}
|
|
55113
55412
|
}
|
|
55114
55413
|
if (!isStreaming) {
|
|
55414
|
+
// Not streaming - show full content immediately
|
|
55115
55415
|
setDisplayedContent(content);
|
|
55116
55416
|
setShowCursor(false);
|
|
55117
55417
|
if (animationFrameRef.current) {
|
|
@@ -55119,20 +55419,25 @@
|
|
|
55119
55419
|
}
|
|
55120
55420
|
return;
|
|
55121
55421
|
}
|
|
55422
|
+
|
|
55423
|
+
// Streaming mode - animate character by character
|
|
55122
55424
|
setShowCursor(true);
|
|
55123
55425
|
const animate = timestamp => {
|
|
55426
|
+
// Throttle updates for smooth 60fps animation
|
|
55124
55427
|
if (timestamp - lastUpdateRef.current < 16) {
|
|
55125
55428
|
animationFrameRef.current = requestAnimationFrame(animate);
|
|
55126
55429
|
return;
|
|
55127
55430
|
}
|
|
55128
55431
|
lastUpdateRef.current = timestamp;
|
|
55129
55432
|
if (indexRef.current < content.length) {
|
|
55433
|
+
// Add 2-5 characters per frame for natural speed
|
|
55130
55434
|
const charsToAdd = Math.max(2, Math.floor(Math.random() * 4));
|
|
55131
55435
|
const newIndex = Math.min(indexRef.current + charsToAdd, content.length);
|
|
55132
55436
|
setDisplayedContent(content.slice(0, newIndex));
|
|
55133
55437
|
indexRef.current = newIndex;
|
|
55134
55438
|
animationFrameRef.current = requestAnimationFrame(animate);
|
|
55135
55439
|
} else {
|
|
55440
|
+
// Finished streaming
|
|
55136
55441
|
setShowCursor(false);
|
|
55137
55442
|
}
|
|
55138
55443
|
};
|
|
@@ -55142,7 +55447,7 @@
|
|
|
55142
55447
|
cancelAnimationFrame(animationFrameRef.current);
|
|
55143
55448
|
}
|
|
55144
55449
|
};
|
|
55145
|
-
}, [content,
|
|
55450
|
+
}, [content, isStreaming]);
|
|
55146
55451
|
return /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
55147
55452
|
className: "relative",
|
|
55148
55453
|
style: {
|
|
@@ -55151,113 +55456,143 @@
|
|
|
55151
55456
|
},
|
|
55152
55457
|
children: [/*#__PURE__*/jsxRuntimeExports.jsx(Markdown, {
|
|
55153
55458
|
remarkPlugins: [remarkGfm],
|
|
55154
|
-
className: "
|
|
55459
|
+
className: "prose prose-sm max-w-none [&>*:last-child]:!mb-0 [&>*:first-child]:!mt-0",
|
|
55460
|
+
style: {
|
|
55461
|
+
color: textColor || (isDark ? "#f3f4f6" : "#1A1A1A"),
|
|
55462
|
+
fontFamily: fontFamily || "Inter",
|
|
55463
|
+
fontSize: fontSize || "14px",
|
|
55464
|
+
margin: 0,
|
|
55465
|
+
padding: 0
|
|
55466
|
+
},
|
|
55155
55467
|
components: {
|
|
55156
|
-
|
|
55468
|
+
a(_ref2) {
|
|
55157
55469
|
let {
|
|
55158
55470
|
node,
|
|
55159
55471
|
children
|
|
55160
55472
|
} = _ref2,
|
|
55161
55473
|
props = _objectWithoutProperties$1(_ref2, _excluded);
|
|
55162
|
-
return /*#__PURE__*/jsxRuntimeExports.jsx("
|
|
55163
|
-
className:
|
|
55474
|
+
return /*#__PURE__*/jsxRuntimeExports.jsx("a", _objectSpread2(_objectSpread2({
|
|
55475
|
+
className: isDark ? "text-blue-400 hover:text-blue-300 hover:underline" : "text-blue-600 hover:underline",
|
|
55476
|
+
target: "_blank",
|
|
55477
|
+
rel: "noopener noreferrer"
|
|
55164
55478
|
}, props), {}, {
|
|
55165
55479
|
children: children
|
|
55166
55480
|
}));
|
|
55167
55481
|
},
|
|
55168
|
-
|
|
55482
|
+
p(_ref3) {
|
|
55169
55483
|
let {
|
|
55170
55484
|
node,
|
|
55171
55485
|
children
|
|
55172
55486
|
} = _ref3,
|
|
55173
55487
|
props = _objectWithoutProperties$1(_ref3, _excluded2);
|
|
55174
|
-
return /*#__PURE__*/jsxRuntimeExports.jsx("
|
|
55175
|
-
className: "
|
|
55488
|
+
return /*#__PURE__*/jsxRuntimeExports.jsx("p", _objectSpread2(_objectSpread2({
|
|
55489
|
+
className: "leading-relaxed [&:not(:last-child)]:mb-2 [&:first-child]:!mt-0",
|
|
55490
|
+
style: {
|
|
55491
|
+
color: textColor || (isDark ? "#f3f4f6" : "#1A1A1A"),
|
|
55492
|
+
fontFamily: fontFamily || "Inter",
|
|
55493
|
+
fontSize: fontSize || "14px",
|
|
55494
|
+
margin: 0,
|
|
55495
|
+
marginTop: 0,
|
|
55496
|
+
padding: 0
|
|
55497
|
+
}
|
|
55176
55498
|
}, props), {}, {
|
|
55177
55499
|
children: children
|
|
55178
55500
|
}));
|
|
55179
55501
|
},
|
|
55180
|
-
|
|
55502
|
+
ul(_ref4) {
|
|
55181
55503
|
let {
|
|
55182
55504
|
node,
|
|
55183
55505
|
children
|
|
55184
55506
|
} = _ref4,
|
|
55185
55507
|
props = _objectWithoutProperties$1(_ref4, _excluded3);
|
|
55186
|
-
return /*#__PURE__*/jsxRuntimeExports.jsx("
|
|
55187
|
-
className: "
|
|
55508
|
+
return /*#__PURE__*/jsxRuntimeExports.jsx("ul", _objectSpread2(_objectSpread2({
|
|
55509
|
+
className: "list-disc pl-5 space-y-1 [&:first-child]:!mt-0",
|
|
55510
|
+
style: {
|
|
55511
|
+
marginTop: 0
|
|
55512
|
+
}
|
|
55188
55513
|
}, props), {}, {
|
|
55189
55514
|
children: children
|
|
55190
55515
|
}));
|
|
55191
55516
|
},
|
|
55192
|
-
|
|
55517
|
+
ol(_ref5) {
|
|
55193
55518
|
let {
|
|
55194
55519
|
node,
|
|
55195
55520
|
children
|
|
55196
55521
|
} = _ref5,
|
|
55197
55522
|
props = _objectWithoutProperties$1(_ref5, _excluded4);
|
|
55198
|
-
return /*#__PURE__*/jsxRuntimeExports.jsx("
|
|
55199
|
-
className: "
|
|
55523
|
+
return /*#__PURE__*/jsxRuntimeExports.jsx("ol", _objectSpread2(_objectSpread2({
|
|
55524
|
+
className: "list-decimal pl-5 space-y-1 [&:first-child]:!mt-0",
|
|
55525
|
+
style: {
|
|
55526
|
+
marginTop: 0
|
|
55527
|
+
}
|
|
55200
55528
|
}, props), {}, {
|
|
55201
55529
|
children: children
|
|
55202
55530
|
}));
|
|
55203
55531
|
},
|
|
55204
|
-
|
|
55532
|
+
li(_ref6) {
|
|
55205
55533
|
let {
|
|
55206
|
-
|
|
55534
|
+
node,
|
|
55207
55535
|
children
|
|
55208
55536
|
} = _ref6,
|
|
55209
55537
|
props = _objectWithoutProperties$1(_ref6, _excluded5);
|
|
55210
|
-
|
|
55211
|
-
|
|
55212
|
-
|
|
55213
|
-
|
|
55214
|
-
|
|
55215
|
-
|
|
55216
|
-
|
|
55217
|
-
}, props), {}, {
|
|
55218
|
-
children: String(children).replace(/\n$/, "")
|
|
55219
|
-
}));
|
|
55220
|
-
}
|
|
55221
|
-
return /*#__PURE__*/jsxRuntimeExports.jsx("code", _objectSpread2(_objectSpread2({
|
|
55222
|
-
className: className
|
|
55538
|
+
return /*#__PURE__*/jsxRuntimeExports.jsx("li", _objectSpread2(_objectSpread2({
|
|
55539
|
+
className: "mb-1",
|
|
55540
|
+
style: {
|
|
55541
|
+
color: textColor || (isDark ? "#f3f4f6" : "#1A1A1A"),
|
|
55542
|
+
fontFamily: fontFamily || "Inter",
|
|
55543
|
+
fontSize: fontSize || "14px"
|
|
55544
|
+
}
|
|
55223
55545
|
}, props), {}, {
|
|
55224
55546
|
children: children
|
|
55225
55547
|
}));
|
|
55226
55548
|
},
|
|
55227
|
-
|
|
55549
|
+
h1(_ref7) {
|
|
55228
55550
|
let {
|
|
55229
55551
|
node,
|
|
55230
55552
|
children
|
|
55231
55553
|
} = _ref7,
|
|
55232
55554
|
props = _objectWithoutProperties$1(_ref7, _excluded6);
|
|
55233
|
-
return /*#__PURE__*/jsxRuntimeExports.jsx("
|
|
55234
|
-
className:
|
|
55235
|
-
|
|
55236
|
-
|
|
55555
|
+
return /*#__PURE__*/jsxRuntimeExports.jsx("h1", _objectSpread2(_objectSpread2({
|
|
55556
|
+
className: "text-xl font-bold mb-2 [&:first-child]:!mt-0",
|
|
55557
|
+
style: {
|
|
55558
|
+
color: textColor || (isDark ? "#f3f4f6" : "#1A1A1A"),
|
|
55559
|
+
fontFamily: fontFamily || "Inter",
|
|
55560
|
+
marginTop: "0.75rem"
|
|
55561
|
+
}
|
|
55237
55562
|
}, props), {}, {
|
|
55238
55563
|
children: children
|
|
55239
55564
|
}));
|
|
55240
55565
|
},
|
|
55241
|
-
|
|
55566
|
+
h2(_ref8) {
|
|
55242
55567
|
let {
|
|
55243
55568
|
node,
|
|
55244
55569
|
children
|
|
55245
55570
|
} = _ref8,
|
|
55246
55571
|
props = _objectWithoutProperties$1(_ref8, _excluded7);
|
|
55247
|
-
return /*#__PURE__*/jsxRuntimeExports.jsx("
|
|
55248
|
-
className: "
|
|
55572
|
+
return /*#__PURE__*/jsxRuntimeExports.jsx("h2", _objectSpread2(_objectSpread2({
|
|
55573
|
+
className: "text-lg font-semibold mb-2 [&:first-child]:!mt-0",
|
|
55574
|
+
style: {
|
|
55575
|
+
color: textColor || (isDark ? "#f3f4f6" : "#1A1A1A"),
|
|
55576
|
+
fontFamily: fontFamily || "Inter",
|
|
55577
|
+
marginTop: "0.75rem"
|
|
55578
|
+
}
|
|
55249
55579
|
}, props), {}, {
|
|
55250
55580
|
children: children
|
|
55251
55581
|
}));
|
|
55252
55582
|
},
|
|
55253
|
-
|
|
55583
|
+
h3(_ref9) {
|
|
55254
55584
|
let {
|
|
55255
55585
|
node,
|
|
55256
55586
|
children
|
|
55257
55587
|
} = _ref9,
|
|
55258
55588
|
props = _objectWithoutProperties$1(_ref9, _excluded8);
|
|
55259
|
-
return /*#__PURE__*/jsxRuntimeExports.jsx("
|
|
55260
|
-
className: "
|
|
55589
|
+
return /*#__PURE__*/jsxRuntimeExports.jsx("h3", _objectSpread2(_objectSpread2({
|
|
55590
|
+
className: "text-base font-semibold mb-2 [&:first-child]:!mt-0",
|
|
55591
|
+
style: {
|
|
55592
|
+
color: textColor || (isDark ? "#f3f4f6" : "#1A1A1A"),
|
|
55593
|
+
fontFamily: fontFamily || "Inter",
|
|
55594
|
+
marginTop: "0.75rem"
|
|
55595
|
+
}
|
|
55261
55596
|
}, props), {}, {
|
|
55262
55597
|
children: children
|
|
55263
55598
|
}));
|
|
@@ -55312,6 +55647,29 @@
|
|
|
55312
55647
|
}, props), {}, {
|
|
55313
55648
|
children: children
|
|
55314
55649
|
}));
|
|
55650
|
+
},
|
|
55651
|
+
code(_ref12) {
|
|
55652
|
+
let {
|
|
55653
|
+
className,
|
|
55654
|
+
children
|
|
55655
|
+
} = _ref12,
|
|
55656
|
+
props = _objectWithoutProperties$1(_ref12, _excluded11);
|
|
55657
|
+
const match = /language-(\w+)/.exec(className || "");
|
|
55658
|
+
if (match) {
|
|
55659
|
+
return /*#__PURE__*/jsxRuntimeExports.jsx(SyntaxHighlighter, _objectSpread2(_objectSpread2({
|
|
55660
|
+
style: oneDark,
|
|
55661
|
+
language: match[1],
|
|
55662
|
+
PreTag: "div",
|
|
55663
|
+
wrapLines: true
|
|
55664
|
+
}, props), {}, {
|
|
55665
|
+
children: String(children).replace(/\n$/, "")
|
|
55666
|
+
}));
|
|
55667
|
+
}
|
|
55668
|
+
return /*#__PURE__*/jsxRuntimeExports.jsx("code", _objectSpread2(_objectSpread2({
|
|
55669
|
+
className: className
|
|
55670
|
+
}, props), {}, {
|
|
55671
|
+
children: children
|
|
55672
|
+
}));
|
|
55315
55673
|
}
|
|
55316
55674
|
},
|
|
55317
55675
|
children: displayedContent
|
|
@@ -55323,34 +55681,54 @@
|
|
|
55323
55681
|
})]
|
|
55324
55682
|
});
|
|
55325
55683
|
};
|
|
55326
|
-
const TypingIndicator =
|
|
55327
|
-
let {
|
|
55328
|
-
isDark
|
|
55329
|
-
} = _ref12;
|
|
55684
|
+
const TypingIndicator = _ref13 => {
|
|
55330
55685
|
return /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
55331
55686
|
className: "flex gap-1.5",
|
|
55332
55687
|
children: [/*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
55333
55688
|
className: "w-2 h-2 rounded-full bg-gray-400 animate-bounce",
|
|
55334
55689
|
style: {
|
|
55335
|
-
animationDelay: "0ms"
|
|
55336
|
-
backgroundColor: isDark ? "#9CA3AF" : "#9CA3AF"
|
|
55690
|
+
animationDelay: "0ms"
|
|
55337
55691
|
}
|
|
55338
55692
|
}), /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
55339
55693
|
className: "w-2 h-2 rounded-full bg-gray-400 animate-bounce",
|
|
55340
55694
|
style: {
|
|
55341
|
-
animationDelay: "150ms"
|
|
55342
|
-
backgroundColor: isDark ? "#9CA3AF" : "#9CA3AF"
|
|
55695
|
+
animationDelay: "150ms"
|
|
55343
55696
|
}
|
|
55344
55697
|
}), /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
55345
55698
|
className: "w-2 h-2 rounded-full bg-gray-400 animate-bounce",
|
|
55346
55699
|
style: {
|
|
55347
|
-
animationDelay: "300ms"
|
|
55348
|
-
backgroundColor: isDark ? "#9CA3AF" : "#9CA3AF"
|
|
55700
|
+
animationDelay: "300ms"
|
|
55349
55701
|
}
|
|
55350
55702
|
})]
|
|
55351
55703
|
});
|
|
55352
55704
|
};
|
|
55353
|
-
|
|
55705
|
+
|
|
55706
|
+
// Decision widget component for HITL (Human-in-the-Loop)
|
|
55707
|
+
const DecisionWidget = _ref14 => {
|
|
55708
|
+
let {
|
|
55709
|
+
question,
|
|
55710
|
+
options,
|
|
55711
|
+
onDecision,
|
|
55712
|
+
disabled,
|
|
55713
|
+
isDark = false
|
|
55714
|
+
} = _ref14;
|
|
55715
|
+
return /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
55716
|
+
className: "mt-3 p-3 rounded-lg border ".concat(isDark ? "bg-blue-900/30 border-blue-700/50" : "bg-blue-50 border-blue-200"),
|
|
55717
|
+
children: [/*#__PURE__*/jsxRuntimeExports.jsx("p", {
|
|
55718
|
+
className: "text-sm font-medium mb-2 ".concat(isDark ? "text-gray-100" : "text-gray-900"),
|
|
55719
|
+
children: question
|
|
55720
|
+
}), /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
55721
|
+
className: "space-y-2",
|
|
55722
|
+
children: options.map(option => /*#__PURE__*/jsxRuntimeExports.jsx("button", {
|
|
55723
|
+
onClick: () => onDecision(option.id, option.label),
|
|
55724
|
+
disabled: disabled,
|
|
55725
|
+
className: "w-full text-left px-3 py-2 text-sm rounded transition-all ".concat(isDark ? "bg-gray-800 border border-gray-700 hover:bg-blue-900/50 hover:border-blue-600 disabled:opacity-50 disabled:cursor-not-allowed" : "bg-white border border-gray-300 hover:bg-blue-50 hover:border-blue-400 disabled:opacity-50 disabled:cursor-not-allowed"),
|
|
55726
|
+
children: option.label
|
|
55727
|
+
}, option.id))
|
|
55728
|
+
})]
|
|
55729
|
+
});
|
|
55730
|
+
};
|
|
55731
|
+
const AssistantMessage = _ref15 => {
|
|
55354
55732
|
let {
|
|
55355
55733
|
message,
|
|
55356
55734
|
formatTime,
|
|
@@ -55358,28 +55736,47 @@
|
|
|
55358
55736
|
primaryColor,
|
|
55359
55737
|
agentMessageBubbleColor,
|
|
55360
55738
|
textColor,
|
|
55739
|
+
assistantTextColor,
|
|
55361
55740
|
fontFamily,
|
|
55362
55741
|
fontSize,
|
|
55363
|
-
isRtl
|
|
55364
|
-
|
|
55742
|
+
isRtl,
|
|
55743
|
+
onDecision,
|
|
55744
|
+
companyLogo,
|
|
55745
|
+
conciergeName,
|
|
55746
|
+
companyName
|
|
55747
|
+
} = _ref15;
|
|
55365
55748
|
const displayContent = typeof message.content === "string" ? message.content : "";
|
|
55366
55749
|
const isTypingMessage = message.isProcessing && (!displayContent || displayContent.length === 0);
|
|
55367
|
-
const bubbleColor = agentMessageBubbleColor
|
|
55368
|
-
const messageTextColor = textColor
|
|
55369
|
-
const messageFontFamily = fontFamily
|
|
55370
|
-
const messageFontSize = fontSize
|
|
55750
|
+
const bubbleColor = agentMessageBubbleColor !== undefined && agentMessageBubbleColor !== null ? agentMessageBubbleColor : isDark ? "#1f2937" : "#FFFFFF";
|
|
55751
|
+
const messageTextColor = assistantTextColor !== undefined && assistantTextColor !== null ? assistantTextColor : textColor !== undefined && textColor !== null ? textColor : isDark ? "#f3f4f6" : "#1A1A1A";
|
|
55752
|
+
const messageFontFamily = fontFamily !== undefined && fontFamily !== null ? fontFamily : "Inter";
|
|
55753
|
+
const messageFontSize = fontSize !== undefined && fontSize !== null ? fontSize : "14px";
|
|
55371
55754
|
useGoogleFont(messageFontFamily);
|
|
55372
55755
|
return /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
55373
55756
|
className: "flex gap-3 flex-row animate-in",
|
|
55374
55757
|
children: [/*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
55375
55758
|
className: "flex-shrink-0 mt-1",
|
|
55376
55759
|
children: /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
55377
|
-
className: "w-8 h-8 rounded-full flex items-center justify-center ".concat(isDark ? "bg-gray-700" : "bg-gray-200"),
|
|
55378
|
-
children: /*#__PURE__*/jsxRuntimeExports.jsx(
|
|
55379
|
-
className: "w-
|
|
55760
|
+
className: "w-8 h-8 rounded-full flex items-center justify-center overflow-hidden ".concat(isDark ? "bg-gray-700" : "bg-gray-200"),
|
|
55761
|
+
children: companyLogo ? /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
55762
|
+
className: "w-full h-full flex items-center justify-center",
|
|
55763
|
+
children: /*#__PURE__*/jsxRuntimeExports.jsx("img", {
|
|
55764
|
+
src: companyLogo,
|
|
55765
|
+
alt: "Company logo",
|
|
55766
|
+
className: "w-full h-full object-cover rounded-full",
|
|
55767
|
+
style: {
|
|
55768
|
+
maxWidth: "100%",
|
|
55769
|
+
maxHeight: "100%"
|
|
55770
|
+
}
|
|
55771
|
+
})
|
|
55772
|
+
}) : /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
55773
|
+
className: "w-full h-full flex items-center justify-center text-white font-semibold",
|
|
55380
55774
|
style: {
|
|
55381
|
-
|
|
55382
|
-
|
|
55775
|
+
backgroundColor: primaryColor,
|
|
55776
|
+
fontSize: "14px",
|
|
55777
|
+
fontFamily: fontFamily || "Inter"
|
|
55778
|
+
},
|
|
55779
|
+
children: (conciergeName || companyName || "A").charAt(0).toUpperCase()
|
|
55383
55780
|
})
|
|
55384
55781
|
})
|
|
55385
55782
|
}), /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
@@ -55396,35 +55793,64 @@
|
|
|
55396
55793
|
},
|
|
55397
55794
|
children: isTypingMessage ? /*#__PURE__*/jsxRuntimeExports.jsx(TypingIndicator, {
|
|
55398
55795
|
isDark: isDark
|
|
55399
|
-
}) :
|
|
55400
|
-
|
|
55401
|
-
|
|
55402
|
-
|
|
55403
|
-
|
|
55404
|
-
|
|
55796
|
+
}) : /*#__PURE__*/jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, {
|
|
55797
|
+
children: message.requiresDecision && message.decisionData && onDecision ? /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
55798
|
+
children: [displayContent && /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
55799
|
+
className: "mb-3",
|
|
55800
|
+
children: /*#__PURE__*/jsxRuntimeExports.jsx(StreamingMarkdown, {
|
|
55801
|
+
content: displayContent,
|
|
55802
|
+
isStreaming: message.isProcessing,
|
|
55803
|
+
isDark: isDark,
|
|
55804
|
+
isRtl: isRtl,
|
|
55805
|
+
textColor: messageTextColor,
|
|
55806
|
+
fontFamily: messageFontFamily,
|
|
55807
|
+
fontSize: messageFontSize
|
|
55808
|
+
})
|
|
55809
|
+
}), /*#__PURE__*/jsxRuntimeExports.jsx(DecisionWidget, {
|
|
55810
|
+
question: message.decisionData.question,
|
|
55811
|
+
options: message.decisionData.options,
|
|
55812
|
+
onDecision: (optionId, optionValue) => onDecision(message.decisionData.decisionId, optionId, optionValue),
|
|
55813
|
+
disabled: !!message.decisionResponse,
|
|
55814
|
+
isDark: isDark
|
|
55815
|
+
}), message.decisionResponse && /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
55816
|
+
className: "mt-2 text-xs ".concat(isDark ? "text-gray-400" : "text-gray-500"),
|
|
55817
|
+
children: ["Selected: ", message.decisionResponse.selectedOption]
|
|
55818
|
+
})]
|
|
55819
|
+
}) : displayContent ? /*#__PURE__*/jsxRuntimeExports.jsx(StreamingMarkdown, {
|
|
55820
|
+
content: displayContent,
|
|
55821
|
+
isStreaming: message.isProcessing,
|
|
55822
|
+
isDark: isDark,
|
|
55823
|
+
isRtl: isRtl,
|
|
55824
|
+
textColor: messageTextColor,
|
|
55825
|
+
fontFamily: messageFontFamily,
|
|
55826
|
+
fontSize: messageFontSize
|
|
55827
|
+
}) : null
|
|
55828
|
+
})
|
|
55405
55829
|
}), /*#__PURE__*/jsxRuntimeExports.jsx("p", {
|
|
55406
55830
|
className: "text-[11px] mt-1.5 px-1 ".concat(isDark ? "text-gray-500" : "text-gray-400"),
|
|
55831
|
+
dir: "ltr",
|
|
55407
55832
|
children: formatTime(message.timestamp)
|
|
55408
55833
|
})]
|
|
55409
55834
|
})]
|
|
55410
55835
|
});
|
|
55411
55836
|
};
|
|
55412
|
-
const UserMessage =
|
|
55837
|
+
const UserMessage = _ref16 => {
|
|
55413
55838
|
let {
|
|
55414
55839
|
message,
|
|
55415
55840
|
formatTime,
|
|
55416
55841
|
userMessageBoxColor,
|
|
55417
55842
|
primaryColor,
|
|
55418
55843
|
textColor,
|
|
55844
|
+
userTextColor,
|
|
55419
55845
|
fontFamily,
|
|
55420
55846
|
fontSize,
|
|
55421
55847
|
isDark,
|
|
55422
55848
|
isRtl
|
|
55423
|
-
} =
|
|
55424
|
-
const primary = userMessageBoxColor
|
|
55425
|
-
const messageTextColor = textColor
|
|
55426
|
-
const messageFontFamily = fontFamily
|
|
55427
|
-
const messageFontSize = fontSize
|
|
55849
|
+
} = _ref16;
|
|
55850
|
+
const primary = userMessageBoxColor !== undefined && userMessageBoxColor !== null ? userMessageBoxColor : primaryColor !== undefined && primaryColor !== null ? primaryColor : "#2563eb";
|
|
55851
|
+
const messageTextColor = userTextColor !== undefined && userTextColor !== null ? userTextColor : textColor !== undefined && textColor !== null ? textColor : "#FFFFFF";
|
|
55852
|
+
const messageFontFamily = fontFamily !== undefined && fontFamily !== null ? fontFamily : "Inter";
|
|
55853
|
+
const messageFontSize = fontSize !== undefined && fontSize !== null ? fontSize : "14px";
|
|
55428
55854
|
useGoogleFont(messageFontFamily);
|
|
55429
55855
|
return /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
55430
55856
|
className: "flex gap-3 flex-row-reverse animate-in",
|
|
@@ -55443,26 +55869,31 @@
|
|
|
55443
55869
|
style: {
|
|
55444
55870
|
background: "linear-gradient(135deg, ".concat(primary, " 0%, ").concat(primary, "dd 100%)"),
|
|
55445
55871
|
fontFamily: messageFontFamily,
|
|
55446
|
-
fontSize: messageFontSize,
|
|
55447
55872
|
textAlign: isRtl ? "right" : "left",
|
|
55448
55873
|
direction: isRtl ? "rtl" : "ltr"
|
|
55449
55874
|
},
|
|
55450
55875
|
children: /*#__PURE__*/jsxRuntimeExports.jsx("p", {
|
|
55451
|
-
className: "
|
|
55876
|
+
className: "whitespace-pre-wrap break-words",
|
|
55452
55877
|
style: {
|
|
55453
55878
|
color: messageTextColor,
|
|
55454
|
-
|
|
55879
|
+
fontFamily: messageFontFamily,
|
|
55880
|
+
fontSize: messageFontSize,
|
|
55881
|
+
lineHeight: "1.5",
|
|
55882
|
+
textAlign: isRtl ? "right" : "left",
|
|
55883
|
+
margin: 0,
|
|
55884
|
+
padding: 0
|
|
55455
55885
|
},
|
|
55456
55886
|
children: message.content
|
|
55457
55887
|
})
|
|
55458
55888
|
}), /*#__PURE__*/jsxRuntimeExports.jsx("p", {
|
|
55459
55889
|
className: "text-[11px] mt-1.5 px-1 ".concat(isDark ? "text-gray-500" : "text-gray-400"),
|
|
55890
|
+
dir: "ltr",
|
|
55460
55891
|
children: formatTime(message.timestamp)
|
|
55461
55892
|
})]
|
|
55462
55893
|
})]
|
|
55463
55894
|
});
|
|
55464
55895
|
};
|
|
55465
|
-
const MessageBubble =
|
|
55896
|
+
const MessageBubble = _ref17 => {
|
|
55466
55897
|
let {
|
|
55467
55898
|
message,
|
|
55468
55899
|
isDark,
|
|
@@ -55470,11 +55901,17 @@
|
|
|
55470
55901
|
agentMessageBubbleColor,
|
|
55471
55902
|
userMessageBoxColor,
|
|
55472
55903
|
textColor,
|
|
55904
|
+
assistantTextColor,
|
|
55905
|
+
userTextColor,
|
|
55473
55906
|
fontFamily,
|
|
55474
55907
|
fontSize,
|
|
55475
55908
|
formatTime,
|
|
55476
|
-
isRtl
|
|
55477
|
-
|
|
55909
|
+
isRtl,
|
|
55910
|
+
onDecision,
|
|
55911
|
+
companyLogo,
|
|
55912
|
+
conciergeName,
|
|
55913
|
+
companyName
|
|
55914
|
+
} = _ref17;
|
|
55478
55915
|
if (!message) {
|
|
55479
55916
|
return null;
|
|
55480
55917
|
}
|
|
@@ -55485,6 +55922,7 @@
|
|
|
55485
55922
|
userMessageBoxColor: userMessageBoxColor,
|
|
55486
55923
|
primaryColor: primaryColor,
|
|
55487
55924
|
textColor: textColor,
|
|
55925
|
+
userTextColor: userTextColor,
|
|
55488
55926
|
fontFamily: fontFamily,
|
|
55489
55927
|
fontSize: fontSize,
|
|
55490
55928
|
isDark: isDark,
|
|
@@ -55498,184 +55936,14 @@
|
|
|
55498
55936
|
primaryColor: primaryColor,
|
|
55499
55937
|
agentMessageBubbleColor: agentMessageBubbleColor,
|
|
55500
55938
|
textColor: textColor,
|
|
55939
|
+
assistantTextColor: assistantTextColor,
|
|
55501
55940
|
fontFamily: fontFamily,
|
|
55502
55941
|
fontSize: fontSize,
|
|
55503
|
-
isRtl: isRtl
|
|
55504
|
-
|
|
55505
|
-
|
|
55506
|
-
|
|
55507
|
-
|
|
55508
|
-
let {
|
|
55509
|
-
messages = [],
|
|
55510
|
-
isDark,
|
|
55511
|
-
primaryColor,
|
|
55512
|
-
isLoading,
|
|
55513
|
-
agentMessageBubbleColor,
|
|
55514
|
-
userMessageBoxColor,
|
|
55515
|
-
textColor,
|
|
55516
|
-
fontFamily,
|
|
55517
|
-
fontSize,
|
|
55518
|
-
formatTime,
|
|
55519
|
-
isRtl = false
|
|
55520
|
-
} = _ref;
|
|
55521
|
-
const containerRef = reactExports.useRef(null);
|
|
55522
|
-
const messagesEndRef = reactExports.useRef(null);
|
|
55523
|
-
const shouldAutoScrollRef = reactExports.useRef(true);
|
|
55524
|
-
const autoScrollKey = reactExports.useMemo(() => messages.map(message => {
|
|
55525
|
-
var _message$content$leng, _message$content;
|
|
55526
|
-
return "".concat(message.id, ":").concat((_message$content$leng = (_message$content = message.content) === null || _message$content === void 0 ? void 0 : _message$content.length) !== null && _message$content$leng !== void 0 ? _message$content$leng : 0, ":").concat(message.isProcessing ? 1 : 0);
|
|
55527
|
-
}).join("|"), [messages]);
|
|
55528
|
-
const updateAutoScrollIntent = reactExports.useCallback(() => {
|
|
55529
|
-
const container = containerRef.current;
|
|
55530
|
-
if (!container) {
|
|
55531
|
-
return;
|
|
55532
|
-
}
|
|
55533
|
-
const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight;
|
|
55534
|
-
shouldAutoScrollRef.current = distanceFromBottom < 160;
|
|
55535
|
-
}, []);
|
|
55536
|
-
reactExports.useEffect(() => {
|
|
55537
|
-
const container = containerRef.current;
|
|
55538
|
-
if (!container) {
|
|
55539
|
-
return undefined;
|
|
55540
|
-
}
|
|
55541
|
-
container.addEventListener("scroll", updateAutoScrollIntent, {
|
|
55542
|
-
passive: true
|
|
55543
|
-
});
|
|
55544
|
-
updateAutoScrollIntent();
|
|
55545
|
-
return () => {
|
|
55546
|
-
container.removeEventListener("scroll", updateAutoScrollIntent);
|
|
55547
|
-
};
|
|
55548
|
-
}, [updateAutoScrollIntent]);
|
|
55549
|
-
reactExports.useEffect(() => {
|
|
55550
|
-
if (!shouldAutoScrollRef.current) {
|
|
55551
|
-
return undefined;
|
|
55552
|
-
}
|
|
55553
|
-
if (typeof window === "undefined") {
|
|
55554
|
-
return undefined;
|
|
55555
|
-
}
|
|
55556
|
-
const frame = window.requestAnimationFrame(() => {
|
|
55557
|
-
var _messagesEndRef$curre;
|
|
55558
|
-
(_messagesEndRef$curre = messagesEndRef.current) === null || _messagesEndRef$curre === void 0 || _messagesEndRef$curre.scrollIntoView({
|
|
55559
|
-
behavior: "smooth",
|
|
55560
|
-
block: "end"
|
|
55561
|
-
});
|
|
55562
|
-
});
|
|
55563
|
-
return () => {
|
|
55564
|
-
window.cancelAnimationFrame(frame);
|
|
55565
|
-
};
|
|
55566
|
-
}, [autoScrollKey, isLoading]);
|
|
55567
|
-
return /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
55568
|
-
ref: containerRef,
|
|
55569
|
-
className: "chat-messages flex-1 overflow-y-auto px-5 py-4 space-y-4 min-h-0 ".concat(isDark ? "bg-gray-900" : "bg-gradient-to-b from-gray-50/50 to-white", " break-words"),
|
|
55570
|
-
children: [messages.map(message => /*#__PURE__*/jsxRuntimeExports.jsx(MessageBubble, {
|
|
55571
|
-
message: message,
|
|
55572
|
-
isDark: isDark,
|
|
55573
|
-
primaryColor: primaryColor,
|
|
55574
|
-
agentMessageBubbleColor: agentMessageBubbleColor,
|
|
55575
|
-
userMessageBoxColor: userMessageBoxColor,
|
|
55576
|
-
textColor: textColor,
|
|
55577
|
-
fontFamily: fontFamily,
|
|
55578
|
-
fontSize: fontSize,
|
|
55579
|
-
formatTime: formatTime,
|
|
55580
|
-
isRtl: isRtl
|
|
55581
|
-
}, message.id)), /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
55582
|
-
ref: messagesEndRef,
|
|
55583
|
-
className: "h-px"
|
|
55584
|
-
})]
|
|
55585
|
-
});
|
|
55586
|
-
};
|
|
55587
|
-
|
|
55588
|
-
const ChatInput = _ref => {
|
|
55589
|
-
let {
|
|
55590
|
-
inputValue,
|
|
55591
|
-
setInputValue,
|
|
55592
|
-
onSend,
|
|
55593
|
-
isDark,
|
|
55594
|
-
primaryColor,
|
|
55595
|
-
isOpen,
|
|
55596
|
-
isMinimized,
|
|
55597
|
-
isLoading,
|
|
55598
|
-
placeholder,
|
|
55599
|
-
textColor,
|
|
55600
|
-
fontFamily,
|
|
55601
|
-
fontSize,
|
|
55602
|
-
isRtl = false
|
|
55603
|
-
} = _ref;
|
|
55604
|
-
const textareaRef = reactExports.useRef(null);
|
|
55605
|
-
useGoogleFont(fontFamily);
|
|
55606
|
-
reactExports.useEffect(() => {
|
|
55607
|
-
if (isOpen && !isMinimized) {
|
|
55608
|
-
var _textareaRef$current;
|
|
55609
|
-
(_textareaRef$current = textareaRef.current) === null || _textareaRef$current === void 0 || _textareaRef$current.focus();
|
|
55610
|
-
}
|
|
55611
|
-
}, [isOpen, isMinimized]);
|
|
55612
|
-
reactExports.useEffect(() => {
|
|
55613
|
-
const textarea = textareaRef.current;
|
|
55614
|
-
if (textarea) {
|
|
55615
|
-
textarea.style.height = "auto";
|
|
55616
|
-
textarea.style.height = "".concat(Math.min(textarea.scrollHeight, 120), "px");
|
|
55617
|
-
}
|
|
55618
|
-
}, [inputValue]);
|
|
55619
|
-
const handleKeyPress = event => {
|
|
55620
|
-
if (event.key === "Enter" && !event.shiftKey) {
|
|
55621
|
-
event.preventDefault();
|
|
55622
|
-
onSend();
|
|
55623
|
-
}
|
|
55624
|
-
};
|
|
55625
|
-
const handleChange = event => {
|
|
55626
|
-
setInputValue(event.target.value);
|
|
55627
|
-
};
|
|
55628
|
-
const isDisabled = !inputValue.trim() || isLoading;
|
|
55629
|
-
const separatorColor = isDark ? "#374151" : "#e5e7eb";
|
|
55630
|
-
return /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
55631
|
-
className: "px-5 py-4 border-t flex-shrink-0 ".concat(isDark ? "border-gray-700 bg-gray-900" : "border-gray-200 bg-white"),
|
|
55632
|
-
style: {
|
|
55633
|
-
borderTopColor: separatorColor,
|
|
55634
|
-
borderTopWidth: "1px",
|
|
55635
|
-
borderTopStyle: "solid"
|
|
55636
|
-
},
|
|
55637
|
-
children: /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
55638
|
-
className: "flex gap-2.5 items-end",
|
|
55639
|
-
children: [/*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
55640
|
-
className: "flex-1 flex items-center min-h-[48px] ".concat(isDark ? "bg-gray-800" : "bg-gray-50", " rounded-2xl border transition-all duration-200"),
|
|
55641
|
-
style: {
|
|
55642
|
-
borderColor: inputValue ? primaryColor : isDark ? "#374151" : "#e5e7eb",
|
|
55643
|
-
borderWidth: inputValue ? "2px" : "1px"
|
|
55644
|
-
},
|
|
55645
|
-
children: /*#__PURE__*/jsxRuntimeExports.jsx("textarea", {
|
|
55646
|
-
id: "chat-widget-input",
|
|
55647
|
-
ref: textareaRef,
|
|
55648
|
-
value: inputValue,
|
|
55649
|
-
onChange: handleChange,
|
|
55650
|
-
onKeyDown: handleKeyPress,
|
|
55651
|
-
placeholder: placeholder || "Type your message...",
|
|
55652
|
-
rows: 1,
|
|
55653
|
-
disabled: isLoading,
|
|
55654
|
-
dir: isRtl ? "rtl" : "ltr",
|
|
55655
|
-
className: "w-full px-4 py-0 bg-transparent rounded-xl leading-normal ".concat(isDark ? "text-gray-100" : "text-gray-900", " placeholder-gray-400 resize-none outline-none scrollbar-hide"),
|
|
55656
|
-
style: {
|
|
55657
|
-
maxHeight: "120px",
|
|
55658
|
-
lineHeight: "48px",
|
|
55659
|
-
fontFamily: fontFamily || "Inter",
|
|
55660
|
-
fontSize: fontSize || "14px",
|
|
55661
|
-
color: textColor || (isDark ? "#f3f4f6" : "#111827"),
|
|
55662
|
-
textAlign: isRtl ? "right" : "left"
|
|
55663
|
-
}
|
|
55664
|
-
})
|
|
55665
|
-
}), /*#__PURE__*/jsxRuntimeExports.jsx("button", {
|
|
55666
|
-
onClick: onSend,
|
|
55667
|
-
disabled: isDisabled,
|
|
55668
|
-
className: "h-12 w-12 p-0 rounded-xl transition-all duration-200 flex items-center justify-center shadow-lg disabled:opacity-40 disabled:cursor-not-allowed disabled:shadow-none ".concat(!isDisabled ? "scale-100" : "scale-95"),
|
|
55669
|
-
style: {
|
|
55670
|
-
backgroundColor: !isDisabled ? primaryColor : isDark ? "#374151" : "#e5e7eb",
|
|
55671
|
-
color: !isDisabled ? "white" : "#9ca3af"
|
|
55672
|
-
},
|
|
55673
|
-
"aria-label": "Send message",
|
|
55674
|
-
children: /*#__PURE__*/jsxRuntimeExports.jsx(Send, {
|
|
55675
|
-
className: "w-5 h-5"
|
|
55676
|
-
})
|
|
55677
|
-
})]
|
|
55678
|
-
})
|
|
55942
|
+
isRtl: isRtl,
|
|
55943
|
+
onDecision: onDecision,
|
|
55944
|
+
companyLogo: companyLogo,
|
|
55945
|
+
conciergeName: conciergeName,
|
|
55946
|
+
companyName: companyName
|
|
55679
55947
|
});
|
|
55680
55948
|
};
|
|
55681
55949
|
|
|
@@ -55856,6 +56124,7 @@
|
|
|
55856
56124
|
};
|
|
55857
56125
|
};
|
|
55858
56126
|
const QuickQuestions = _ref3 => {
|
|
56127
|
+
var _ref4;
|
|
55859
56128
|
let {
|
|
55860
56129
|
questions = [],
|
|
55861
56130
|
isDark = false,
|
|
@@ -55866,12 +56135,15 @@
|
|
|
55866
56135
|
fontFamily = "Inter",
|
|
55867
56136
|
fontSize = "14px",
|
|
55868
56137
|
textColor,
|
|
55869
|
-
isRtl = false
|
|
56138
|
+
isRtl = false,
|
|
56139
|
+
questionTextColor,
|
|
56140
|
+
questionBoxColor
|
|
55870
56141
|
} = _ref3;
|
|
55871
56142
|
if (!questions.length || isTyping) {
|
|
55872
56143
|
return null;
|
|
55873
56144
|
}
|
|
55874
|
-
const resolvedTextColor =
|
|
56145
|
+
const resolvedTextColor = (_ref4 = questionTextColor !== null && questionTextColor !== void 0 ? questionTextColor : textColor) !== null && _ref4 !== void 0 ? _ref4 : isDark ? "#f3f4f6" : "#111827";
|
|
56146
|
+
const resolvedQuestionBoxColor = questionBoxColor !== null && questionBoxColor !== void 0 ? questionBoxColor : isDark ? "#374151" : "#e5e7eb";
|
|
55875
56147
|
const palette = reactExports.useMemo(() => getQuickQuestionPalette(resolvedTextColor, isDark), [resolvedTextColor, isDark]);
|
|
55876
56148
|
const applyHoverState = (element, isHover) => {
|
|
55877
56149
|
element.style.backgroundColor = isHover ? palette.hoverBackground : palette.background;
|
|
@@ -55920,11 +56192,19 @@
|
|
|
55920
56192
|
})]
|
|
55921
56193
|
});
|
|
55922
56194
|
}
|
|
55923
|
-
|
|
55924
|
-
|
|
56195
|
+
|
|
56196
|
+
// Vertical layout (default)
|
|
56197
|
+
return /*#__PURE__*/jsxRuntimeExports.jsx("div", _objectSpread2(_objectSpread2({
|
|
56198
|
+
className: "space-y-3 flex flex-col items-start pl-[50px]"
|
|
56199
|
+
}, isRtl && {
|
|
56200
|
+
style: {
|
|
56201
|
+
paddingLeft: "0",
|
|
56202
|
+
paddingRight: "50px"
|
|
56203
|
+
}
|
|
56204
|
+
}), {}, {
|
|
55925
56205
|
children: questions.map((question, index) => /*#__PURE__*/jsxRuntimeExports.jsxs("button", {
|
|
55926
56206
|
onClick: () => onQuestionClick === null || onQuestionClick === void 0 ? void 0 : onQuestionClick(question),
|
|
55927
|
-
className: "group relative text-sm px-
|
|
56207
|
+
className: "group relative text-sm px-3 py-3 rounded-2xl font-medium transition-all duration-300 hover:scale-[1.02] active:scale-[0.98] whitespace-normal max-w-[85%] overflow-hidden backdrop-blur-sm ".concat(isRtl ? "text-right" : "text-left"),
|
|
55928
56208
|
style: {
|
|
55929
56209
|
direction: isRtl ? "rtl" : "ltr",
|
|
55930
56210
|
backgroundColor: palette.background,
|
|
@@ -55938,29 +56218,608 @@
|
|
|
55938
56218
|
applyHoverState(e.currentTarget, false);
|
|
55939
56219
|
},
|
|
55940
56220
|
children: [/*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
55941
|
-
|
|
55942
|
-
|
|
56221
|
+
style: {
|
|
56222
|
+
backgroundColor: "#F5F5F5",
|
|
56223
|
+
border: "1px solid ".concat(resolvedQuestionBoxColor)
|
|
56224
|
+
},
|
|
56225
|
+
className: "absolute inset-0 transition-opacity duration-300 rounded-2xl"
|
|
56226
|
+
}), /*#__PURE__*/jsxRuntimeExports.jsx("span", {
|
|
55943
56227
|
className: "relative z-10 flex items-center gap-2.5 text-left",
|
|
55944
|
-
children:
|
|
55945
|
-
className: "h-4 w-4 opacity-60 group-hover:opacity-100 transition-opacity duration-300 flex-shrink-0",
|
|
55946
|
-
style: {
|
|
55947
|
-
color: primaryColor
|
|
55948
|
-
}
|
|
55949
|
-
}), /*#__PURE__*/jsxRuntimeExports.jsx("span", {
|
|
56228
|
+
children: /*#__PURE__*/jsxRuntimeExports.jsx("span", {
|
|
55950
56229
|
className: "flex-1 leading-snug ".concat(isRtl ? "text-right" : "text-left"),
|
|
55951
56230
|
style: {
|
|
55952
56231
|
direction: isRtl ? "rtl" : "ltr",
|
|
55953
|
-
color:
|
|
56232
|
+
color: "#1A1A1A",
|
|
55954
56233
|
fontFamily,
|
|
55955
56234
|
fontSize
|
|
55956
56235
|
},
|
|
55957
56236
|
children: question
|
|
55958
|
-
})
|
|
56237
|
+
})
|
|
55959
56238
|
})]
|
|
55960
56239
|
}, index))
|
|
56240
|
+
}));
|
|
56241
|
+
};
|
|
56242
|
+
|
|
56243
|
+
const LoadingState = _ref => {
|
|
56244
|
+
let {
|
|
56245
|
+
title,
|
|
56246
|
+
description,
|
|
56247
|
+
isAnimated = false
|
|
56248
|
+
} = _ref;
|
|
56249
|
+
return /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
56250
|
+
className: "flex flex-col items-center justify-center py-12 px-4",
|
|
56251
|
+
children: [isAnimated && /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
56252
|
+
className: "flex gap-1.5 mb-4",
|
|
56253
|
+
children: [/*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56254
|
+
className: "w-2 h-2 rounded-full bg-gray-400 animate-bounce",
|
|
56255
|
+
style: {
|
|
56256
|
+
animationDelay: "0ms"
|
|
56257
|
+
}
|
|
56258
|
+
}), /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56259
|
+
className: "w-2 h-2 rounded-full bg-gray-400 animate-bounce",
|
|
56260
|
+
style: {
|
|
56261
|
+
animationDelay: "150ms"
|
|
56262
|
+
}
|
|
56263
|
+
}), /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56264
|
+
className: "w-2 h-2 rounded-full bg-gray-400 animate-bounce",
|
|
56265
|
+
style: {
|
|
56266
|
+
animationDelay: "300ms"
|
|
56267
|
+
}
|
|
56268
|
+
})]
|
|
56269
|
+
}), title && /*#__PURE__*/jsxRuntimeExports.jsx("h3", {
|
|
56270
|
+
className: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-1",
|
|
56271
|
+
children: title
|
|
56272
|
+
}), description && /*#__PURE__*/jsxRuntimeExports.jsx("p", {
|
|
56273
|
+
className: "text-xs text-gray-500 dark:text-gray-400 text-center max-w-xs",
|
|
56274
|
+
children: description
|
|
56275
|
+
})]
|
|
55961
56276
|
});
|
|
55962
56277
|
};
|
|
55963
56278
|
|
|
56279
|
+
const MessageList = _ref => {
|
|
56280
|
+
let {
|
|
56281
|
+
messages = [],
|
|
56282
|
+
isDark,
|
|
56283
|
+
primaryColor,
|
|
56284
|
+
isLoading,
|
|
56285
|
+
agentMessageBubbleColor,
|
|
56286
|
+
userMessageBoxColor,
|
|
56287
|
+
textColor,
|
|
56288
|
+
assistantTextColor,
|
|
56289
|
+
userTextColor,
|
|
56290
|
+
fontFamily,
|
|
56291
|
+
fontSize,
|
|
56292
|
+
formatTime,
|
|
56293
|
+
isRtl = false,
|
|
56294
|
+
quickQuestions = [],
|
|
56295
|
+
shouldShowQuickQuestions = false,
|
|
56296
|
+
onQuickQuestion,
|
|
56297
|
+
quickQuestionsLayout = "vertical",
|
|
56298
|
+
onDecision,
|
|
56299
|
+
disclaimerText,
|
|
56300
|
+
disclaimerPosition = "top",
|
|
56301
|
+
resolvedAgentBubbleColor,
|
|
56302
|
+
resolvedUserMessageColor,
|
|
56303
|
+
resolvedTextColor,
|
|
56304
|
+
isVoiceSessionActive = false,
|
|
56305
|
+
voiceStatus = "idle",
|
|
56306
|
+
messagesContainerRef,
|
|
56307
|
+
companyLogo,
|
|
56308
|
+
conciergeName,
|
|
56309
|
+
companyName
|
|
56310
|
+
} = _ref;
|
|
56311
|
+
const messagesEndRef = reactExports.useRef(null);
|
|
56312
|
+
const shouldAutoScrollRef = reactExports.useRef(true);
|
|
56313
|
+
const autoScrollKey = reactExports.useMemo(() => messages.map(message => {
|
|
56314
|
+
var _message$content$leng, _message$content;
|
|
56315
|
+
return "".concat(message.id, ":").concat((_message$content$leng = (_message$content = message.content) === null || _message$content === void 0 ? void 0 : _message$content.length) !== null && _message$content$leng !== void 0 ? _message$content$leng : 0, ":").concat(message.isProcessing ? 1 : 0);
|
|
56316
|
+
}).join("|"), [messages]);
|
|
56317
|
+
const updateAutoScrollIntent = reactExports.useCallback(() => {
|
|
56318
|
+
const container = messagesContainerRef === null || messagesContainerRef === void 0 ? void 0 : messagesContainerRef.current;
|
|
56319
|
+
if (!container) {
|
|
56320
|
+
return;
|
|
56321
|
+
}
|
|
56322
|
+
const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight;
|
|
56323
|
+
shouldAutoScrollRef.current = distanceFromBottom < 160;
|
|
56324
|
+
}, [messagesContainerRef]);
|
|
56325
|
+
reactExports.useEffect(() => {
|
|
56326
|
+
const container = messagesContainerRef === null || messagesContainerRef === void 0 ? void 0 : messagesContainerRef.current;
|
|
56327
|
+
if (!container) {
|
|
56328
|
+
return undefined;
|
|
56329
|
+
}
|
|
56330
|
+
container.addEventListener("scroll", updateAutoScrollIntent, {
|
|
56331
|
+
passive: true
|
|
56332
|
+
});
|
|
56333
|
+
updateAutoScrollIntent();
|
|
56334
|
+
return () => {
|
|
56335
|
+
container.removeEventListener("scroll", updateAutoScrollIntent);
|
|
56336
|
+
};
|
|
56337
|
+
}, [updateAutoScrollIntent, messagesContainerRef]);
|
|
56338
|
+
reactExports.useEffect(() => {
|
|
56339
|
+
if (!shouldAutoScrollRef.current) {
|
|
56340
|
+
return undefined;
|
|
56341
|
+
}
|
|
56342
|
+
if (typeof window === "undefined") {
|
|
56343
|
+
return undefined;
|
|
56344
|
+
}
|
|
56345
|
+
const frame = window.requestAnimationFrame(() => {
|
|
56346
|
+
var _messagesEndRef$curre;
|
|
56347
|
+
(_messagesEndRef$curre = messagesEndRef.current) === null || _messagesEndRef$curre === void 0 || _messagesEndRef$curre.scrollIntoView({
|
|
56348
|
+
behavior: "smooth",
|
|
56349
|
+
block: "end"
|
|
56350
|
+
});
|
|
56351
|
+
});
|
|
56352
|
+
return () => {
|
|
56353
|
+
window.cancelAnimationFrame(frame);
|
|
56354
|
+
};
|
|
56355
|
+
}, [autoScrollKey, isLoading]);
|
|
56356
|
+
return /*#__PURE__*/jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, {
|
|
56357
|
+
children: [isVoiceSessionActive && messages.length === 0 && /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56358
|
+
className: "flex flex-col items-center justify-center h-full",
|
|
56359
|
+
children: /*#__PURE__*/jsxRuntimeExports.jsx(LoadingState, {
|
|
56360
|
+
title: "Starting voice session...",
|
|
56361
|
+
description: "Allow microphone access or begin speaking to continue.",
|
|
56362
|
+
isAnimated: true
|
|
56363
|
+
})
|
|
56364
|
+
}), disclaimerText && disclaimerPosition === "top" && /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56365
|
+
className: "flex justify-center",
|
|
56366
|
+
children: /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56367
|
+
className: "rounded-lg px-2 py-1 max-w-[85%] border",
|
|
56368
|
+
style: {
|
|
56369
|
+
backgroundColor: agentMessageBubbleColor !== undefined && agentMessageBubbleColor !== null ? agentMessageBubbleColor : resolvedAgentBubbleColor || "#F5F5F5",
|
|
56370
|
+
color: assistantTextColor !== undefined && assistantTextColor !== null ? assistantTextColor : "#1A1A1A",
|
|
56371
|
+
fontFamily: fontFamily !== undefined && fontFamily !== null ? fontFamily : "Inter",
|
|
56372
|
+
fontSize: fontSize !== undefined && fontSize !== null ? "calc(".concat(fontSize, " - 2px)") : "12px",
|
|
56373
|
+
direction: isRtl ? "rtl" : "ltr",
|
|
56374
|
+
textAlign: "center",
|
|
56375
|
+
borderColor: isDark ? "#374151" : "#e5e7eb"
|
|
56376
|
+
},
|
|
56377
|
+
children: /*#__PURE__*/jsxRuntimeExports.jsx("p", {
|
|
56378
|
+
className: "leading-relaxed whitespace-pre-wrap break-words",
|
|
56379
|
+
dir: isRtl ? "rtl" : "ltr",
|
|
56380
|
+
style: {
|
|
56381
|
+
color: assistantTextColor !== undefined && assistantTextColor !== null ? assistantTextColor : "#1A1A1A",
|
|
56382
|
+
fontFamily: fontFamily !== undefined && fontFamily !== null ? fontFamily : "Inter",
|
|
56383
|
+
fontSize: fontSize !== undefined && fontSize !== null ? "calc(".concat(fontSize, " - 2px)") : "12px"
|
|
56384
|
+
},
|
|
56385
|
+
children: disclaimerText
|
|
56386
|
+
})
|
|
56387
|
+
})
|
|
56388
|
+
}), messages.map(message => /*#__PURE__*/jsxRuntimeExports.jsx(MessageBubble, {
|
|
56389
|
+
message: message,
|
|
56390
|
+
isDark: isDark,
|
|
56391
|
+
primaryColor: primaryColor,
|
|
56392
|
+
agentMessageBubbleColor: agentMessageBubbleColor,
|
|
56393
|
+
userMessageBoxColor: userMessageBoxColor,
|
|
56394
|
+
textColor: textColor,
|
|
56395
|
+
assistantTextColor: assistantTextColor,
|
|
56396
|
+
userTextColor: userTextColor,
|
|
56397
|
+
fontFamily: fontFamily,
|
|
56398
|
+
fontSize: fontSize,
|
|
56399
|
+
formatTime: formatTime,
|
|
56400
|
+
isRtl: isRtl,
|
|
56401
|
+
onDecision: onDecision,
|
|
56402
|
+
companyLogo: companyLogo,
|
|
56403
|
+
conciergeName: conciergeName,
|
|
56404
|
+
companyName: companyName
|
|
56405
|
+
}, message.id)), shouldShowQuickQuestions && quickQuestions.length > 0 && /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56406
|
+
className: "pt-1",
|
|
56407
|
+
children: /*#__PURE__*/jsxRuntimeExports.jsx(QuickQuestions, {
|
|
56408
|
+
questions: quickQuestions,
|
|
56409
|
+
isDark: isDark,
|
|
56410
|
+
primaryColor: primaryColor,
|
|
56411
|
+
onQuestionClick: onQuickQuestion,
|
|
56412
|
+
isTyping: isLoading,
|
|
56413
|
+
layout: quickQuestionsLayout,
|
|
56414
|
+
fontFamily: fontFamily,
|
|
56415
|
+
fontSize: fontSize,
|
|
56416
|
+
textColor: textColor,
|
|
56417
|
+
isRtl: isRtl,
|
|
56418
|
+
questionTextColor: assistantTextColor,
|
|
56419
|
+
questionBoxColor: agentMessageBubbleColor
|
|
56420
|
+
})
|
|
56421
|
+
}), /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56422
|
+
ref: messagesEndRef,
|
|
56423
|
+
className: "h-px"
|
|
56424
|
+
})]
|
|
56425
|
+
});
|
|
56426
|
+
};
|
|
56427
|
+
|
|
56428
|
+
const ChatInput = _ref => {
|
|
56429
|
+
let {
|
|
56430
|
+
inputValue,
|
|
56431
|
+
setInputValue,
|
|
56432
|
+
onSend,
|
|
56433
|
+
isDark,
|
|
56434
|
+
primaryColor,
|
|
56435
|
+
isOpen,
|
|
56436
|
+
isMinimized,
|
|
56437
|
+
isLoading,
|
|
56438
|
+
placeholder,
|
|
56439
|
+
textColor,
|
|
56440
|
+
fontFamily,
|
|
56441
|
+
fontSize,
|
|
56442
|
+
isRtl = false,
|
|
56443
|
+
enableVoiceInteraction = false,
|
|
56444
|
+
isVoiceSessionActive = false,
|
|
56445
|
+
voiceStatus = "idle",
|
|
56446
|
+
voiceError = null,
|
|
56447
|
+
onVoiceToggle,
|
|
56448
|
+
onBidiSubmit,
|
|
56449
|
+
disclaimerText,
|
|
56450
|
+
disclaimerPosition = "top"
|
|
56451
|
+
} = _ref;
|
|
56452
|
+
const textareaRef = reactExports.useRef(null);
|
|
56453
|
+
useGoogleFont(fontFamily);
|
|
56454
|
+
reactExports.useEffect(() => {
|
|
56455
|
+
if (isOpen && !isMinimized) {
|
|
56456
|
+
var _textareaRef$current;
|
|
56457
|
+
(_textareaRef$current = textareaRef.current) === null || _textareaRef$current === void 0 || _textareaRef$current.focus();
|
|
56458
|
+
}
|
|
56459
|
+
}, [isOpen, isMinimized]);
|
|
56460
|
+
|
|
56461
|
+
// Auto-resize textarea
|
|
56462
|
+
reactExports.useEffect(() => {
|
|
56463
|
+
const textarea = textareaRef.current;
|
|
56464
|
+
if (textarea) {
|
|
56465
|
+
// Reset height to auto to get accurate scrollHeight
|
|
56466
|
+
textarea.style.height = "auto";
|
|
56467
|
+
// Calculate new height based on scrollHeight
|
|
56468
|
+
const scrollHeight = textarea.scrollHeight;
|
|
56469
|
+
// Ensure minimum height when there's text (lineHeight 1.4 means we need at least ~20px per line)
|
|
56470
|
+
const minHeightWithText = inputValue.trim().length > 0 ? 20 : 48;
|
|
56471
|
+
const newHeight = Math.max(minHeightWithText, Math.min(scrollHeight, 120));
|
|
56472
|
+
textarea.style.height = "".concat(newHeight, "px");
|
|
56473
|
+
}
|
|
56474
|
+
}, [inputValue]);
|
|
56475
|
+
const handleKeyPress = event => {
|
|
56476
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
56477
|
+
event.preventDefault();
|
|
56478
|
+
if (isVoiceSessionActive && onBidiSubmit) {
|
|
56479
|
+
onBidiSubmit();
|
|
56480
|
+
} else {
|
|
56481
|
+
onSend();
|
|
56482
|
+
}
|
|
56483
|
+
}
|
|
56484
|
+
};
|
|
56485
|
+
const handleChange = event => {
|
|
56486
|
+
setInputValue(event.target.value);
|
|
56487
|
+
};
|
|
56488
|
+
const isDisabled = !inputValue.trim() || isLoading;
|
|
56489
|
+
const separatorColor = isDark ? "#374151" : "#e5e7eb";
|
|
56490
|
+
return /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
56491
|
+
className: "px-5 py-4 border-t flex-shrink-0 ".concat(isDark ? "border-gray-700 bg-gray-900" : "border-gray-200 bg-white"),
|
|
56492
|
+
style: {
|
|
56493
|
+
borderTopColor: separatorColor,
|
|
56494
|
+
borderTopWidth: "1px",
|
|
56495
|
+
borderTopStyle: "solid"
|
|
56496
|
+
},
|
|
56497
|
+
children: [/*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
56498
|
+
className: "flex items-center gap-1.5",
|
|
56499
|
+
children: [/*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56500
|
+
className: "flex-1 flex items-center min-h-[48px] ".concat(isDark ? "bg-gray-800" : "bg-gray-50", " rounded-2xl border transition-all duration-200"),
|
|
56501
|
+
style: {
|
|
56502
|
+
borderColor: inputValue ? primaryColor : isDark ? "#374151" : "#e5e7eb",
|
|
56503
|
+
borderWidth: inputValue ? "2px" : "1px"
|
|
56504
|
+
},
|
|
56505
|
+
children: /*#__PURE__*/jsxRuntimeExports.jsx("textarea", {
|
|
56506
|
+
id: "chat-widget-input",
|
|
56507
|
+
ref: textareaRef,
|
|
56508
|
+
value: inputValue,
|
|
56509
|
+
onChange: handleChange,
|
|
56510
|
+
onKeyDown: handleKeyPress,
|
|
56511
|
+
placeholder: placeholder || "Type your message...",
|
|
56512
|
+
rows: 1,
|
|
56513
|
+
disabled: isLoading || isVoiceSessionActive && voiceStatus !== "connected",
|
|
56514
|
+
dir: isRtl ? "rtl" : "ltr",
|
|
56515
|
+
className: "w-full px-4 bg-transparent rounded-xl leading-normal ".concat(isDark ? "text-gray-100" : "text-gray-900", " placeholder-gray-400 resize-none outline-none scrollbar-hide"),
|
|
56516
|
+
style: {
|
|
56517
|
+
height: "auto",
|
|
56518
|
+
maxHeight: "120px",
|
|
56519
|
+
minHeight: "48px",
|
|
56520
|
+
paddingTop: inputValue.trim().length > 0 ? "12px" : "0px",
|
|
56521
|
+
paddingBottom: inputValue.trim().length > 0 ? "12px" : "0px",
|
|
56522
|
+
lineHeight: inputValue.trim().length > 0 ? "1.4" : "48px",
|
|
56523
|
+
fontFamily: fontFamily || "Inter",
|
|
56524
|
+
fontSize: fontSize || "14px",
|
|
56525
|
+
color: textColor || (isDark ? "#F5F5F5" : "#1A1A1A"),
|
|
56526
|
+
textAlign: isRtl ? "right" : "left",
|
|
56527
|
+
direction: isRtl ? "rtl" : "ltr",
|
|
56528
|
+
wordSpacing: "0",
|
|
56529
|
+
letterSpacing: "0"
|
|
56530
|
+
}
|
|
56531
|
+
})
|
|
56532
|
+
}), enableVoiceInteraction && /*#__PURE__*/jsxRuntimeExports.jsx("button", {
|
|
56533
|
+
type: "button",
|
|
56534
|
+
onClick: onVoiceToggle,
|
|
56535
|
+
className: "h-10 w-10 rounded-xl flex items-center justify-center transition-all duration-200 shadow-md ".concat(isVoiceSessionActive ? "bg-red-500 text-white hover:bg-red-600" : isDark ? "bg-gray-800 text-gray-200 hover:bg-gray-700" : "bg-white text-gray-600 hover:bg-gray-100", " ").concat(voiceStatus === "connecting" ? "opacity-60 cursor-not-allowed shadow-none" : ""),
|
|
56536
|
+
disabled: voiceStatus === "connecting",
|
|
56537
|
+
children: voiceStatus === "connecting" ? /*#__PURE__*/jsxRuntimeExports.jsx(Loader2, {
|
|
56538
|
+
className: "w-4 h-4 animate-spin"
|
|
56539
|
+
}) : /*#__PURE__*/jsxRuntimeExports.jsx(AudioLines, {
|
|
56540
|
+
className: "w-4 h-4"
|
|
56541
|
+
})
|
|
56542
|
+
}), /*#__PURE__*/jsxRuntimeExports.jsx("button", {
|
|
56543
|
+
onClick: isVoiceSessionActive && onBidiSubmit ? onBidiSubmit : onSend,
|
|
56544
|
+
disabled: isDisabled || isVoiceSessionActive && voiceStatus !== "connected",
|
|
56545
|
+
className: "h-10 w-10 rounded-xl transition-all duration-200 flex items-center justify-center shadow-md disabled:opacity-40 disabled:cursor-not-allowed disabled:shadow-none ".concat(inputValue.trim() ? "scale-100" : "scale-95"),
|
|
56546
|
+
style: {
|
|
56547
|
+
backgroundColor: inputValue.trim() ? primaryColor : isDark ? "#374151" : "#e5e7eb",
|
|
56548
|
+
color: inputValue.trim() ? "white" : "#9ca3af"
|
|
56549
|
+
},
|
|
56550
|
+
"aria-label": "Send message",
|
|
56551
|
+
children: /*#__PURE__*/jsxRuntimeExports.jsx(Send, {
|
|
56552
|
+
className: "w-4 h-4 transition-transform",
|
|
56553
|
+
style: isRtl ? {
|
|
56554
|
+
transform: "rotate(-90deg)"
|
|
56555
|
+
} : undefined
|
|
56556
|
+
})
|
|
56557
|
+
})]
|
|
56558
|
+
}), isVoiceSessionActive && /*#__PURE__*/jsxRuntimeExports.jsxs("p", {
|
|
56559
|
+
className: "text-[11px] mt-2 px-1 ".concat(voiceStatus === "connected" ? "text-green-500" : "text-gray-500", " flex items-center gap-1"),
|
|
56560
|
+
children: [/*#__PURE__*/jsxRuntimeExports.jsx("span", {
|
|
56561
|
+
className: "w-1.5 h-1.5 rounded-full bg-current inline-flex"
|
|
56562
|
+
}), voiceStatus === "connected" ? "Voice session live — speak or type to converse." : "Connecting to voice session..."]
|
|
56563
|
+
}), voiceError && /*#__PURE__*/jsxRuntimeExports.jsx("p", {
|
|
56564
|
+
className: "text-[11px] mt-1 px-1 text-red-500",
|
|
56565
|
+
children: voiceError
|
|
56566
|
+
}), disclaimerText && disclaimerPosition === "footer" && /*#__PURE__*/jsxRuntimeExports.jsx("p", {
|
|
56567
|
+
className: "text-xs mt-2 text-center",
|
|
56568
|
+
style: {
|
|
56569
|
+
color: isDark ? "#FFFFFF" : "#000000",
|
|
56570
|
+
fontFamily: fontFamily || "Inter",
|
|
56571
|
+
fontSize: fontSize ? "calc(".concat(fontSize, " - 2px)") : "12px",
|
|
56572
|
+
direction: isRtl ? "rtl" : "ltr"
|
|
56573
|
+
},
|
|
56574
|
+
dir: isRtl ? "rtl" : "ltr",
|
|
56575
|
+
children: disclaimerText
|
|
56576
|
+
})]
|
|
56577
|
+
});
|
|
56578
|
+
};
|
|
56579
|
+
|
|
56580
|
+
const LOGO_MAX_HEIGHT = "3.5rem";
|
|
56581
|
+
const LOGO_MAX_HEIGHT_COMPACT = "2.5rem";
|
|
56582
|
+
const LOGO_MAX_WIDTH_DEFAULT = "4.5rem";
|
|
56583
|
+
const LOGO_MAX_WIDTH_DEFAULT_COMPACT = "3rem";
|
|
56584
|
+
const LOGO_MAX_WIDTH_WIDE = "9rem";
|
|
56585
|
+
const LOGO_MAX_WIDTH_WIDE_COMPACT = "5.5rem";
|
|
56586
|
+
const STATUS_DOT_SIZE = "0.8rem";
|
|
56587
|
+
const STATUS_DOT_SIZE_COMPACT = "0.65rem";
|
|
56588
|
+
const STATUS_DOT_BORDER_WIDTH = "2px";
|
|
56589
|
+
const STATUS_DOT_BORDER_WIDTH_COMPACT = "1.5px";
|
|
56590
|
+
const STATUS_DOT_DEFAULT_COLOR = "#34d399";
|
|
56591
|
+
const STATUS_DOT_OFFSET = "38%";
|
|
56592
|
+
const STATUS_DOT_OFFSET_COMPACT = "22%";
|
|
56593
|
+
const LogoImage = _ref => {
|
|
56594
|
+
let {
|
|
56595
|
+
src,
|
|
56596
|
+
showStatusDot = false,
|
|
56597
|
+
statusColor = STATUS_DOT_DEFAULT_COLOR,
|
|
56598
|
+
size = "default"
|
|
56599
|
+
} = _ref;
|
|
56600
|
+
const [aspect, setAspect] = reactExports.useState("square");
|
|
56601
|
+
const isCompact = size === "compact";
|
|
56602
|
+
reactExports.useEffect(() => {
|
|
56603
|
+
if (typeof window === "undefined" || !src) {
|
|
56604
|
+
return;
|
|
56605
|
+
}
|
|
56606
|
+
const img = new Image();
|
|
56607
|
+
img.src = src;
|
|
56608
|
+
img.onload = () => {
|
|
56609
|
+
if (img.width > img.height) {
|
|
56610
|
+
setAspect("wide");
|
|
56611
|
+
} else if (img.height > img.width) {
|
|
56612
|
+
setAspect("tall");
|
|
56613
|
+
} else {
|
|
56614
|
+
setAspect("square");
|
|
56615
|
+
}
|
|
56616
|
+
};
|
|
56617
|
+
}, [src]);
|
|
56618
|
+
const containerStyle = {
|
|
56619
|
+
position: "relative",
|
|
56620
|
+
display: "inline-flex"
|
|
56621
|
+
};
|
|
56622
|
+
const imageStyle = {
|
|
56623
|
+
display: "block",
|
|
56624
|
+
objectFit: "cover",
|
|
56625
|
+
height: "100%",
|
|
56626
|
+
width: "100%",
|
|
56627
|
+
// borderRadius:'50%',
|
|
56628
|
+
maxHeight: isCompact ? LOGO_MAX_HEIGHT_COMPACT : LOGO_MAX_HEIGHT,
|
|
56629
|
+
maxWidth: isCompact ? LOGO_MAX_WIDTH_DEFAULT_COMPACT : LOGO_MAX_WIDTH_DEFAULT
|
|
56630
|
+
};
|
|
56631
|
+
if (aspect === "wide") {
|
|
56632
|
+
imageStyle.maxWidth = isCompact ? LOGO_MAX_WIDTH_WIDE_COMPACT : LOGO_MAX_WIDTH_WIDE;
|
|
56633
|
+
}
|
|
56634
|
+
if (aspect === "tall") {
|
|
56635
|
+
imageStyle.maxHeight = isCompact ? "3rem" : "4rem";
|
|
56636
|
+
imageStyle.maxWidth = isCompact ? "3rem" : "4rem";
|
|
56637
|
+
}
|
|
56638
|
+
return /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
56639
|
+
style: containerStyle,
|
|
56640
|
+
children: [/*#__PURE__*/jsxRuntimeExports.jsx("img", {
|
|
56641
|
+
src: src,
|
|
56642
|
+
alt: "Logo",
|
|
56643
|
+
style: imageStyle,
|
|
56644
|
+
loading: "lazy"
|
|
56645
|
+
}), showStatusDot && /*#__PURE__*/jsxRuntimeExports.jsx("span", {
|
|
56646
|
+
style: {
|
|
56647
|
+
position: "absolute",
|
|
56648
|
+
bottom: 0,
|
|
56649
|
+
right: 0,
|
|
56650
|
+
width: isCompact ? STATUS_DOT_SIZE_COMPACT : STATUS_DOT_SIZE,
|
|
56651
|
+
height: isCompact ? STATUS_DOT_SIZE_COMPACT : STATUS_DOT_SIZE,
|
|
56652
|
+
borderRadius: "9999px",
|
|
56653
|
+
backgroundColor: statusColor,
|
|
56654
|
+
border: "".concat(isCompact ? STATUS_DOT_BORDER_WIDTH_COMPACT : STATUS_DOT_BORDER_WIDTH, " solid #ffffff"),
|
|
56655
|
+
transform: "translate(".concat(isCompact ? STATUS_DOT_OFFSET_COMPACT : STATUS_DOT_OFFSET, ", ").concat(isCompact ? STATUS_DOT_OFFSET_COMPACT : STATUS_DOT_OFFSET, ")"),
|
|
56656
|
+
pointerEvents: "none"
|
|
56657
|
+
}
|
|
56658
|
+
})]
|
|
56659
|
+
});
|
|
56660
|
+
};
|
|
56661
|
+
|
|
56662
|
+
const ChatHeader = _ref => {
|
|
56663
|
+
let {
|
|
56664
|
+
conciergeName,
|
|
56665
|
+
companyName,
|
|
56666
|
+
companyLogo,
|
|
56667
|
+
primaryColor,
|
|
56668
|
+
isDark,
|
|
56669
|
+
isMinimized = false,
|
|
56670
|
+
textColor,
|
|
56671
|
+
fontFamily,
|
|
56672
|
+
fontSize,
|
|
56673
|
+
onToggleTheme,
|
|
56674
|
+
onMinimize,
|
|
56675
|
+
onClose,
|
|
56676
|
+
headerTextBold = false,
|
|
56677
|
+
headerTextItalic = false
|
|
56678
|
+
} = _ref;
|
|
56679
|
+
useGoogleFont(fontFamily);
|
|
56680
|
+
const agentData = {
|
|
56681
|
+
fontFamily,
|
|
56682
|
+
fontSize,
|
|
56683
|
+
headerTextBold,
|
|
56684
|
+
headerTextItalic,
|
|
56685
|
+
textColor
|
|
56686
|
+
};
|
|
56687
|
+
return /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
56688
|
+
className: "text-white ".concat(isMinimized ? "px-4 py-2.5" : "px-5 py-4", " flex items-center justify-between relative overflow-hidden rounded-t-2xl"),
|
|
56689
|
+
style: {
|
|
56690
|
+
background: "linear-gradient(135deg, ".concat(primaryColor, " 0%, ").concat(primaryColor, "dd 100%)"),
|
|
56691
|
+
fontFamily
|
|
56692
|
+
},
|
|
56693
|
+
children: [/*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
56694
|
+
className: "flex gap-2 w-96",
|
|
56695
|
+
children: [/*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56696
|
+
className: "absolute inset-0 bg-gradient-to-br from-white/10 to-transparent pointer-events-none"
|
|
56697
|
+
}), companyLogo && /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56698
|
+
className: "w-[48px] h-[48px] rounded-full overflow-hidden flex items-center justify-center bg-white/10",
|
|
56699
|
+
children: /*#__PURE__*/jsxRuntimeExports.jsx(LogoImage, {
|
|
56700
|
+
src: companyLogo
|
|
56701
|
+
})
|
|
56702
|
+
}), /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56703
|
+
className: "flex items-center gap-2 ".concat(!companyLogo ? "px-3" : ""),
|
|
56704
|
+
style: {
|
|
56705
|
+
fontFamily: (agentData === null || agentData === void 0 ? void 0 : agentData.fontFamily) || "Inter"
|
|
56706
|
+
},
|
|
56707
|
+
children: /*#__PURE__*/jsxRuntimeExports.jsx("h3", {
|
|
56708
|
+
className: cn("font-semibold leading-tight", (agentData === null || agentData === void 0 ? void 0 : agentData.headerTextBold) && "font-bold", (agentData === null || agentData === void 0 ? void 0 : agentData.headerTextItalic) && "italic"),
|
|
56709
|
+
style: {
|
|
56710
|
+
fontSize: agentData !== null && agentData !== void 0 && agentData.fontSize ? "calc(".concat(agentData.fontSize, " + 2px)") : "15px",
|
|
56711
|
+
color: (agentData === null || agentData === void 0 ? void 0 : agentData.textColor) || "#FFFFFF"
|
|
56712
|
+
},
|
|
56713
|
+
children: companyName
|
|
56714
|
+
})
|
|
56715
|
+
})]
|
|
56716
|
+
}), /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
56717
|
+
className: "flex items-center gap-0 relative z-10 text-white flex-shrink-0 ml-1",
|
|
56718
|
+
children: [/*#__PURE__*/jsxRuntimeExports.jsx("span", {
|
|
56719
|
+
role: "button",
|
|
56720
|
+
tabIndex: 0,
|
|
56721
|
+
"aria-label": "Toggle theme",
|
|
56722
|
+
onClick: onToggleTheme,
|
|
56723
|
+
onKeyDown: event => {
|
|
56724
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
56725
|
+
event.preventDefault();
|
|
56726
|
+
onToggleTheme === null || onToggleTheme === void 0 || onToggleTheme(event);
|
|
56727
|
+
}
|
|
56728
|
+
},
|
|
56729
|
+
className: "inline-flex h-7 w-7 items-center justify-center cursor-pointer transition-opacity duration-200 hover:opacity-80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/40 rounded-full",
|
|
56730
|
+
children: isDark ? /*#__PURE__*/jsxRuntimeExports.jsx(Sun, {
|
|
56731
|
+
className: "w-3.5 h-3.5",
|
|
56732
|
+
strokeWidth: 1.6
|
|
56733
|
+
}) : /*#__PURE__*/jsxRuntimeExports.jsx(Moon, {
|
|
56734
|
+
className: "w-3.5 h-3.5",
|
|
56735
|
+
strokeWidth: 1.6
|
|
56736
|
+
})
|
|
56737
|
+
}), onMinimize && /*#__PURE__*/jsxRuntimeExports.jsx("span", {
|
|
56738
|
+
role: "button",
|
|
56739
|
+
tabIndex: 0,
|
|
56740
|
+
"aria-label": isMinimized ? "Expand" : "Minimize",
|
|
56741
|
+
onClick: onMinimize,
|
|
56742
|
+
onKeyDown: event => {
|
|
56743
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
56744
|
+
event.preventDefault();
|
|
56745
|
+
onMinimize === null || onMinimize === void 0 || onMinimize(event);
|
|
56746
|
+
}
|
|
56747
|
+
},
|
|
56748
|
+
className: "inline-flex h-7 w-7 items-center justify-center cursor-pointer transition-opacity duration-200 hover:opacity-80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/40 rounded-full",
|
|
56749
|
+
children: isMinimized ? /*#__PURE__*/jsxRuntimeExports.jsx(Maximize2, {
|
|
56750
|
+
className: "w-3.5 h-3.5",
|
|
56751
|
+
strokeWidth: 1.6
|
|
56752
|
+
}) : /*#__PURE__*/jsxRuntimeExports.jsx(Minimize2, {
|
|
56753
|
+
className: "w-3.5 h-3.5",
|
|
56754
|
+
strokeWidth: 1.6
|
|
56755
|
+
})
|
|
56756
|
+
}), /*#__PURE__*/jsxRuntimeExports.jsx("span", {
|
|
56757
|
+
role: "button",
|
|
56758
|
+
tabIndex: 0,
|
|
56759
|
+
"aria-label": "Close",
|
|
56760
|
+
onClick: onClose,
|
|
56761
|
+
onKeyDown: event => {
|
|
56762
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
56763
|
+
event.preventDefault();
|
|
56764
|
+
onClose === null || onClose === void 0 || onClose(event);
|
|
56765
|
+
}
|
|
56766
|
+
},
|
|
56767
|
+
className: "inline-flex h-7 w-7 items-center justify-center cursor-pointer transition-opacity duration-200 hover:opacity-80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/40 rounded-full",
|
|
56768
|
+
children: /*#__PURE__*/jsxRuntimeExports.jsx(X, {
|
|
56769
|
+
className: "w-3.5 h-3.5",
|
|
56770
|
+
strokeWidth: 1.6
|
|
56771
|
+
})
|
|
56772
|
+
})]
|
|
56773
|
+
})]
|
|
56774
|
+
});
|
|
56775
|
+
};
|
|
56776
|
+
|
|
56777
|
+
/**
|
|
56778
|
+
* Auto-scroll hook that scrolls to bottom when dependencies change
|
|
56779
|
+
*/
|
|
56780
|
+
function useAutoScroll(containerRef) {
|
|
56781
|
+
let dependencies = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
56782
|
+
let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
56783
|
+
const {
|
|
56784
|
+
enabled = true,
|
|
56785
|
+
threshold = 30,
|
|
56786
|
+
behavior = "smooth",
|
|
56787
|
+
delay = 0
|
|
56788
|
+
} = options;
|
|
56789
|
+
const shouldScrollRef = reactExports.useRef(true);
|
|
56790
|
+
reactExports.useRef(0);
|
|
56791
|
+
reactExports.useEffect(() => {
|
|
56792
|
+
if (!enabled || !containerRef.current) {
|
|
56793
|
+
return;
|
|
56794
|
+
}
|
|
56795
|
+
const container = containerRef.current;
|
|
56796
|
+
const checkScrollPosition = () => {
|
|
56797
|
+
const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight;
|
|
56798
|
+
shouldScrollRef.current = distanceFromBottom < threshold;
|
|
56799
|
+
};
|
|
56800
|
+
const handleScroll = () => {
|
|
56801
|
+
checkScrollPosition();
|
|
56802
|
+
};
|
|
56803
|
+
container.addEventListener("scroll", handleScroll, {
|
|
56804
|
+
passive: true
|
|
56805
|
+
});
|
|
56806
|
+
checkScrollPosition();
|
|
56807
|
+
const scrollToBottom = () => {
|
|
56808
|
+
if (shouldScrollRef.current && container) {
|
|
56809
|
+
container.scrollTo({
|
|
56810
|
+
top: container.scrollHeight,
|
|
56811
|
+
behavior
|
|
56812
|
+
});
|
|
56813
|
+
}
|
|
56814
|
+
};
|
|
56815
|
+
const timeoutId = setTimeout(scrollToBottom, delay);
|
|
56816
|
+
return () => {
|
|
56817
|
+
container.removeEventListener("scroll", handleScroll);
|
|
56818
|
+
clearTimeout(timeoutId);
|
|
56819
|
+
};
|
|
56820
|
+
}, [containerRef, enabled, threshold, behavior, delay, ...dependencies]);
|
|
56821
|
+
}
|
|
56822
|
+
|
|
55964
56823
|
const DEFAULT_AGENT_BUBBLE_COLOR = "#ffffff";
|
|
55965
56824
|
const DEFAULT_USER_MESSAGE_COLOR = "#f5f5f5";
|
|
55966
56825
|
const DEFAULT_TEXT_COLOR = "#000000";
|
|
@@ -55989,6 +56848,7 @@
|
|
|
55989
56848
|
isDark,
|
|
55990
56849
|
primaryColor,
|
|
55991
56850
|
textColor,
|
|
56851
|
+
conciergeName,
|
|
55992
56852
|
companyName,
|
|
55993
56853
|
companyLogo,
|
|
55994
56854
|
messages,
|
|
@@ -56005,23 +56865,38 @@
|
|
|
56005
56865
|
quickQuestionsLayout = "vertical",
|
|
56006
56866
|
agentMessageBubbleColor,
|
|
56007
56867
|
userMessageBoxColor,
|
|
56868
|
+
assistantTextColor,
|
|
56869
|
+
userTextColor,
|
|
56008
56870
|
fontFamily = "Inter",
|
|
56009
56871
|
fontSize = "14px",
|
|
56010
|
-
defaultLanguage = "en"
|
|
56872
|
+
defaultLanguage = "en",
|
|
56873
|
+
onDecision,
|
|
56874
|
+
headerTextBold = false,
|
|
56875
|
+
headerTextItalic = false,
|
|
56876
|
+
enableVoiceInteraction = false,
|
|
56877
|
+
isVoiceSessionActive = false,
|
|
56878
|
+
voiceStatus = "idle",
|
|
56879
|
+
voiceError = null,
|
|
56880
|
+
onVoiceToggle,
|
|
56881
|
+
onBidiSubmit,
|
|
56882
|
+
disclaimerText,
|
|
56883
|
+
disclaimerPosition = "top",
|
|
56884
|
+
apiBaseUrl,
|
|
56885
|
+
apiKey,
|
|
56886
|
+
organizationId
|
|
56011
56887
|
} = _ref;
|
|
56012
56888
|
useGoogleFont(fontFamily);
|
|
56889
|
+
const messagesContainerRef = reactExports.useRef(null);
|
|
56890
|
+
|
|
56891
|
+
// Auto-scroll hook
|
|
56892
|
+
useAutoScroll(messagesContainerRef, [messages, isLoading], {
|
|
56893
|
+
enabled: true,
|
|
56894
|
+
threshold: 30,
|
|
56895
|
+
behavior: "smooth",
|
|
56896
|
+
delay: 0
|
|
56897
|
+
});
|
|
56013
56898
|
const defaultLanguageCode = defaultLanguage === null || defaultLanguage === void 0 || (_defaultLanguage$toLo = defaultLanguage.toLowerCase) === null || _defaultLanguage$toLo === void 0 ? void 0 : _defaultLanguage$toLo.call(defaultLanguage);
|
|
56014
56899
|
const isRtlLanguage = Boolean(defaultLanguageCode && defaultLanguageCode.startsWith("ar"));
|
|
56015
|
-
const basePrimaryColor = primaryColor || "#2563eb";
|
|
56016
|
-
const containerStyle = reactExports.useMemo(() => {
|
|
56017
|
-
if (isDark) {
|
|
56018
|
-
return undefined;
|
|
56019
|
-
}
|
|
56020
|
-
return {
|
|
56021
|
-
backgroundColor: basePrimaryColor,
|
|
56022
|
-
borderColor: basePrimaryColor
|
|
56023
|
-
};
|
|
56024
|
-
}, [basePrimaryColor, isDark]);
|
|
56025
56900
|
const resolvedAgentBubbleColor = reactExports.useMemo(() => {
|
|
56026
56901
|
if (isDark) {
|
|
56027
56902
|
if (isDefaultColor(agentMessageBubbleColor, DEFAULT_AGENT_BUBBLE_COLOR)) {
|
|
@@ -56056,50 +56931,56 @@
|
|
|
56056
56931
|
return null;
|
|
56057
56932
|
}
|
|
56058
56933
|
return /*#__PURE__*/jsxRuntimeExports.jsxs("div", {
|
|
56059
|
-
className: "
|
|
56060
|
-
|
|
56061
|
-
|
|
56062
|
-
|
|
56063
|
-
|
|
56064
|
-
|
|
56065
|
-
|
|
56066
|
-
|
|
56067
|
-
|
|
56068
|
-
|
|
56069
|
-
|
|
56070
|
-
|
|
56071
|
-
|
|
56072
|
-
|
|
56073
|
-
|
|
56074
|
-
|
|
56075
|
-
|
|
56076
|
-
|
|
56077
|
-
|
|
56078
|
-
|
|
56079
|
-
|
|
56080
|
-
|
|
56081
|
-
primaryColor: primaryColor,
|
|
56082
|
-
isLoading: isLoading,
|
|
56083
|
-
agentMessageBubbleColor: resolvedAgentBubbleColor,
|
|
56084
|
-
userMessageBoxColor: resolvedUserMessageColor,
|
|
56085
|
-
textColor: resolvedTextColor,
|
|
56086
|
-
fontFamily: fontFamily,
|
|
56087
|
-
fontSize: fontSize,
|
|
56088
|
-
formatTime: formatTime,
|
|
56089
|
-
isRtl: isRtlLanguage
|
|
56090
|
-
}), shouldShowQuickQuestions && /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56091
|
-
className: "px-5 pb-4 flex-shrink-0",
|
|
56092
|
-
children: /*#__PURE__*/jsxRuntimeExports.jsx(QuickQuestions, {
|
|
56093
|
-
questions: quickQuestions,
|
|
56934
|
+
className: "".concat(isMinimized ? "w-80" : "w-[380px]", " max-w-[92vw] flex-shrink-0 border rounded-2xl shadow-2xl bg-white border-gray-200 flex flex-col ").concat(isMinimized ? "h-auto" : "h-[650px] max-h-[85vh]", " overflow-hidden z-50 ").concat(isDark ? "bg-gray-900 border-gray-700" : ""),
|
|
56935
|
+
children: [/*#__PURE__*/jsxRuntimeExports.jsx(ChatHeader, {
|
|
56936
|
+
conciergeName: conciergeName,
|
|
56937
|
+
companyName: companyName,
|
|
56938
|
+
companyLogo: companyLogo,
|
|
56939
|
+
primaryColor: primaryColor,
|
|
56940
|
+
isDark: isDark,
|
|
56941
|
+
isMinimized: isMinimized,
|
|
56942
|
+
textColor: resolvedTextColor,
|
|
56943
|
+
fontFamily: fontFamily,
|
|
56944
|
+
fontSize: fontSize,
|
|
56945
|
+
onToggleTheme: onToggleTheme,
|
|
56946
|
+
onMinimize: onMinimize,
|
|
56947
|
+
onClose: onClose,
|
|
56948
|
+
headerTextBold: headerTextBold,
|
|
56949
|
+
headerTextItalic: headerTextItalic
|
|
56950
|
+
}), !isMinimized && /*#__PURE__*/jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, {
|
|
56951
|
+
children: [/*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56952
|
+
ref: messagesContainerRef,
|
|
56953
|
+
className: "chat-messages flex-1 overflow-y-auto px-5 py-4 space-y-4 ".concat(isDark ? "bg-gray-900" : "bg-gradient-to-b from-gray-50/50 to-white", " break-words"),
|
|
56954
|
+
children: /*#__PURE__*/jsxRuntimeExports.jsx(MessageList, {
|
|
56955
|
+
messages: messages,
|
|
56094
56956
|
isDark: isDark,
|
|
56095
56957
|
primaryColor: primaryColor,
|
|
56096
|
-
|
|
56097
|
-
|
|
56098
|
-
|
|
56958
|
+
isLoading: isLoading,
|
|
56959
|
+
agentMessageBubbleColor: agentMessageBubbleColor,
|
|
56960
|
+
userMessageBoxColor: userMessageBoxColor,
|
|
56961
|
+
textColor: textColor,
|
|
56962
|
+
assistantTextColor: assistantTextColor,
|
|
56963
|
+
userTextColor: userTextColor,
|
|
56099
56964
|
fontFamily: fontFamily,
|
|
56100
56965
|
fontSize: fontSize,
|
|
56101
|
-
|
|
56102
|
-
isRtl: isRtlLanguage
|
|
56966
|
+
formatTime: formatTime,
|
|
56967
|
+
isRtl: isRtlLanguage,
|
|
56968
|
+
quickQuestions: quickQuestions,
|
|
56969
|
+
shouldShowQuickQuestions: shouldShowQuickQuestions,
|
|
56970
|
+
onQuickQuestion: onQuickQuestion !== null && onQuickQuestion !== void 0 ? onQuickQuestion : onDirectSend,
|
|
56971
|
+
quickQuestionsLayout: quickQuestionsLayout,
|
|
56972
|
+
onDecision: onDecision,
|
|
56973
|
+
disclaimerText: disclaimerText,
|
|
56974
|
+
disclaimerPosition: disclaimerPosition,
|
|
56975
|
+
resolvedAgentBubbleColor: resolvedAgentBubbleColor,
|
|
56976
|
+
resolvedUserMessageColor: resolvedUserMessageColor,
|
|
56977
|
+
resolvedTextColor: resolvedTextColor,
|
|
56978
|
+
isVoiceSessionActive: isVoiceSessionActive,
|
|
56979
|
+
voiceStatus: voiceStatus,
|
|
56980
|
+
messagesContainerRef: messagesContainerRef,
|
|
56981
|
+
companyLogo: companyLogo,
|
|
56982
|
+
conciergeName: conciergeName,
|
|
56983
|
+
companyName: companyName
|
|
56103
56984
|
})
|
|
56104
56985
|
}), /*#__PURE__*/jsxRuntimeExports.jsx(ChatInput, {
|
|
56105
56986
|
inputValue: inputValue,
|
|
@@ -56114,7 +56995,15 @@
|
|
|
56114
56995
|
textColor: resolvedTextColor,
|
|
56115
56996
|
fontFamily: fontFamily,
|
|
56116
56997
|
fontSize: fontSize,
|
|
56117
|
-
isRtl: isRtlLanguage
|
|
56998
|
+
isRtl: isRtlLanguage,
|
|
56999
|
+
enableVoiceInteraction: enableVoiceInteraction,
|
|
57000
|
+
isVoiceSessionActive: isVoiceSessionActive,
|
|
57001
|
+
voiceStatus: voiceStatus,
|
|
57002
|
+
voiceError: voiceError,
|
|
57003
|
+
onVoiceToggle: onVoiceToggle,
|
|
57004
|
+
onBidiSubmit: onBidiSubmit,
|
|
57005
|
+
disclaimerText: disclaimerText,
|
|
57006
|
+
disclaimerPosition: disclaimerPosition
|
|
56118
57007
|
})]
|
|
56119
57008
|
})]
|
|
56120
57009
|
});
|
|
@@ -56125,7 +57014,8 @@
|
|
|
56125
57014
|
isOpen,
|
|
56126
57015
|
isDark,
|
|
56127
57016
|
primaryColor,
|
|
56128
|
-
onToggle
|
|
57017
|
+
onToggle,
|
|
57018
|
+
textColor
|
|
56129
57019
|
} = _ref;
|
|
56130
57020
|
return /*#__PURE__*/jsxRuntimeExports.jsxs("button", {
|
|
56131
57021
|
onClick: onToggle,
|
|
@@ -56143,7 +57033,10 @@
|
|
|
56143
57033
|
className: "w-7 h-7"
|
|
56144
57034
|
}) : /*#__PURE__*/jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, {
|
|
56145
57035
|
children: [/*#__PURE__*/jsxRuntimeExports.jsx(MessageCircle, {
|
|
56146
|
-
className: "w-7 h-7"
|
|
57036
|
+
className: "w-7 h-7",
|
|
57037
|
+
style: {
|
|
57038
|
+
color: textColor
|
|
57039
|
+
}
|
|
56147
57040
|
}), /*#__PURE__*/jsxRuntimeExports.jsx("div", {
|
|
56148
57041
|
className: "absolute -top-1 -right-1 w-5 h-5 bg-red-500 rounded-full flex items-center justify-center text-[10px] font-bold border-2 border-white animate-pulse",
|
|
56149
57042
|
children: "1"
|
|
@@ -56159,6 +57052,7 @@
|
|
|
56159
57052
|
primaryColor = "#2563eb",
|
|
56160
57053
|
position = "bottom-right",
|
|
56161
57054
|
companyName = "Support Team",
|
|
57055
|
+
conciergeName,
|
|
56162
57056
|
companyLogo = null,
|
|
56163
57057
|
welcomeMessage = "Hi! How can we help?",
|
|
56164
57058
|
quickQuestions = [],
|
|
@@ -56166,6 +57060,8 @@
|
|
|
56166
57060
|
textColor = "#000000",
|
|
56167
57061
|
agentMessageBubbleColor,
|
|
56168
57062
|
userMessageBoxColor,
|
|
57063
|
+
assistantTextColor,
|
|
57064
|
+
userTextColor,
|
|
56169
57065
|
fontFamily = "Inter",
|
|
56170
57066
|
fontSize = "14px",
|
|
56171
57067
|
defaultLanguage = "en",
|
|
@@ -56175,7 +57071,12 @@
|
|
|
56175
57071
|
autoOpen = false,
|
|
56176
57072
|
openDelay = 0,
|
|
56177
57073
|
locale = "en",
|
|
56178
|
-
className = ""
|
|
57074
|
+
className = "",
|
|
57075
|
+
headerTextBold = false,
|
|
57076
|
+
headerTextItalic = false,
|
|
57077
|
+
enableVoiceInteraction = false,
|
|
57078
|
+
disclaimerText,
|
|
57079
|
+
disclaimerPosition = "top"
|
|
56179
57080
|
} = _ref;
|
|
56180
57081
|
const {
|
|
56181
57082
|
isOpen,
|
|
@@ -56192,7 +57093,13 @@
|
|
|
56192
57093
|
toggleChat,
|
|
56193
57094
|
toggleTheme,
|
|
56194
57095
|
toggleMinimize,
|
|
56195
|
-
closeChat
|
|
57096
|
+
closeChat,
|
|
57097
|
+
handleDecision,
|
|
57098
|
+
isVoiceSessionActive,
|
|
57099
|
+
voiceStatus,
|
|
57100
|
+
voiceError,
|
|
57101
|
+
handleVoiceToggle,
|
|
57102
|
+
sendBidiTextMessage
|
|
56196
57103
|
} = useChatState({
|
|
56197
57104
|
welcomeMessage,
|
|
56198
57105
|
quickQuestions,
|
|
@@ -56201,7 +57108,8 @@
|
|
|
56201
57108
|
organizationId,
|
|
56202
57109
|
autoOpen,
|
|
56203
57110
|
openDelay,
|
|
56204
|
-
darkMode
|
|
57111
|
+
darkMode,
|
|
57112
|
+
enableVoiceInteraction
|
|
56205
57113
|
});
|
|
56206
57114
|
|
|
56207
57115
|
// Set CSS variables for theming
|
|
@@ -56232,6 +57140,7 @@
|
|
|
56232
57140
|
primaryColor: primaryColor,
|
|
56233
57141
|
textColor: textColor,
|
|
56234
57142
|
companyName: companyName,
|
|
57143
|
+
conciergeName: conciergeName,
|
|
56235
57144
|
companyLogo: companyLogo,
|
|
56236
57145
|
messages: messages,
|
|
56237
57146
|
isLoading: isLoading,
|
|
@@ -56247,14 +57156,31 @@
|
|
|
56247
57156
|
quickQuestionsLayout: quickQuestionsLayout,
|
|
56248
57157
|
agentMessageBubbleColor: agentMessageBubbleColor,
|
|
56249
57158
|
userMessageBoxColor: userMessageBoxColor,
|
|
57159
|
+
assistantTextColor: assistantTextColor,
|
|
57160
|
+
userTextColor: userTextColor,
|
|
56250
57161
|
fontFamily: fontFamily,
|
|
56251
57162
|
fontSize: fontSize,
|
|
56252
|
-
defaultLanguage: defaultLanguage || locale
|
|
56253
|
-
|
|
57163
|
+
defaultLanguage: defaultLanguage || locale,
|
|
57164
|
+
onDecision: handleDecision,
|
|
57165
|
+
headerTextBold: headerTextBold,
|
|
57166
|
+
headerTextItalic: headerTextItalic,
|
|
57167
|
+
enableVoiceInteraction: enableVoiceInteraction,
|
|
57168
|
+
isVoiceSessionActive: isVoiceSessionActive,
|
|
57169
|
+
voiceStatus: voiceStatus,
|
|
57170
|
+
voiceError: voiceError,
|
|
57171
|
+
onVoiceToggle: handleVoiceToggle,
|
|
57172
|
+
onBidiSubmit: () => sendBidiTextMessage(inputValue),
|
|
57173
|
+
disclaimerText: disclaimerText,
|
|
57174
|
+
disclaimerPosition: disclaimerPosition,
|
|
57175
|
+
apiBaseUrl: apiBaseUrl,
|
|
57176
|
+
apiKey: apiKey,
|
|
57177
|
+
organizationId: organizationId
|
|
57178
|
+
}), !isOpen && /*#__PURE__*/jsxRuntimeExports.jsx(ToggleButton, {
|
|
56254
57179
|
isOpen: isOpen,
|
|
56255
57180
|
isDark: isDark,
|
|
56256
57181
|
primaryColor: primaryColor,
|
|
56257
|
-
onToggle: toggleChat
|
|
57182
|
+
onToggle: toggleChat,
|
|
57183
|
+
textColor: textColor
|
|
56258
57184
|
})]
|
|
56259
57185
|
});
|
|
56260
57186
|
};
|
|
@@ -56269,13 +57195,16 @@
|
|
|
56269
57195
|
primaryColor: '#2563eb',
|
|
56270
57196
|
position: 'bottom-right',
|
|
56271
57197
|
companyName: 'Support Team',
|
|
57198
|
+
conciergeName: null,
|
|
56272
57199
|
companyLogo: null,
|
|
56273
57200
|
welcomeMessage: 'Hi! How can we help?',
|
|
56274
57201
|
quickQuestions: [],
|
|
56275
57202
|
quickQuestionsLayout: 'vertical',
|
|
56276
|
-
textColor: '#
|
|
57203
|
+
textColor: '#fcfcfc',
|
|
56277
57204
|
agentMessageBubbleColor: undefined,
|
|
56278
57205
|
userMessageBoxColor: undefined,
|
|
57206
|
+
assistantTextColor: undefined,
|
|
57207
|
+
userTextColor: undefined,
|
|
56279
57208
|
fontFamily: 'Inter',
|
|
56280
57209
|
fontSize: '14px',
|
|
56281
57210
|
defaultLanguage: 'en',
|
|
@@ -56283,18 +57212,24 @@
|
|
|
56283
57212
|
openDelay: 0,
|
|
56284
57213
|
apiBaseUrl: null,
|
|
56285
57214
|
apiKey: null,
|
|
57215
|
+
organizationId: null,
|
|
56286
57216
|
sessionUrl: null,
|
|
56287
57217
|
userId: null,
|
|
56288
57218
|
userName: null,
|
|
56289
57219
|
userEmail: null,
|
|
56290
57220
|
locale: 'en',
|
|
57221
|
+
headerTextBold: false,
|
|
57222
|
+
headerTextItalic: false,
|
|
57223
|
+
enableVoiceInteraction: false,
|
|
57224
|
+
disclaimerText: undefined,
|
|
57225
|
+
disclaimerPosition: 'top',
|
|
56291
57226
|
onOpen: null,
|
|
56292
57227
|
onClose: null
|
|
56293
57228
|
};
|
|
56294
57229
|
const API = {
|
|
56295
|
-
/**
|
|
56296
|
-
* Initialize the chat widget
|
|
56297
|
-
* @param {Object} options - Configuration options
|
|
57230
|
+
/**
|
|
57231
|
+
* Initialize the chat widget
|
|
57232
|
+
* @param {Object} options - Configuration options
|
|
56298
57233
|
*/
|
|
56299
57234
|
init: async function () {
|
|
56300
57235
|
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -56334,17 +57269,17 @@
|
|
|
56334
57269
|
}
|
|
56335
57270
|
return API;
|
|
56336
57271
|
},
|
|
56337
|
-
/**
|
|
56338
|
-
* Update configuration
|
|
56339
|
-
* @param {Object} newConfig - New configuration options
|
|
57272
|
+
/**
|
|
57273
|
+
* Update configuration
|
|
57274
|
+
* @param {Object} newConfig - New configuration options
|
|
56340
57275
|
*/
|
|
56341
57276
|
updateConfig: function (newConfig) {
|
|
56342
57277
|
config = _objectSpread2(_objectSpread2({}, config), newConfig);
|
|
56343
57278
|
this.init(config);
|
|
56344
57279
|
return API;
|
|
56345
57280
|
},
|
|
56346
|
-
/**
|
|
56347
|
-
* Open the chat widget
|
|
57281
|
+
/**
|
|
57282
|
+
* Open the chat widget
|
|
56348
57283
|
*/
|
|
56349
57284
|
open: function () {
|
|
56350
57285
|
// Trigger open by updating config
|
|
@@ -56355,8 +57290,8 @@
|
|
|
56355
57290
|
if (config.onOpen) config.onOpen();
|
|
56356
57291
|
return API;
|
|
56357
57292
|
},
|
|
56358
|
-
/**
|
|
56359
|
-
* Close the chat widget
|
|
57293
|
+
/**
|
|
57294
|
+
* Close the chat widget
|
|
56360
57295
|
*/
|
|
56361
57296
|
close: function () {
|
|
56362
57297
|
this.updateConfig({
|
|
@@ -56365,8 +57300,8 @@
|
|
|
56365
57300
|
if (config.onClose) config.onClose();
|
|
56366
57301
|
return API;
|
|
56367
57302
|
},
|
|
56368
|
-
/**
|
|
56369
|
-
* Toggle dark mode
|
|
57303
|
+
/**
|
|
57304
|
+
* Toggle dark mode
|
|
56370
57305
|
*/
|
|
56371
57306
|
toggleTheme: function () {
|
|
56372
57307
|
config.darkMode = !config.darkMode;
|
|
@@ -56375,8 +57310,8 @@
|
|
|
56375
57310
|
});
|
|
56376
57311
|
return API;
|
|
56377
57312
|
},
|
|
56378
|
-
/**
|
|
56379
|
-
* Destroy the widget
|
|
57313
|
+
/**
|
|
57314
|
+
* Destroy the widget
|
|
56380
57315
|
*/
|
|
56381
57316
|
destroy: function () {
|
|
56382
57317
|
if (root) {
|
|
@@ -56391,8 +57326,8 @@
|
|
|
56391
57326
|
config = {};
|
|
56392
57327
|
return API;
|
|
56393
57328
|
},
|
|
56394
|
-
/**
|
|
56395
|
-
* Get current configuration
|
|
57329
|
+
/**
|
|
57330
|
+
* Get current configuration
|
|
56396
57331
|
*/
|
|
56397
57332
|
getConfig: function () {
|
|
56398
57333
|
return _objectSpread2({}, config);
|