@copilotz/chat-ui 0.1.31 → 0.1.33
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/index.cjs +943 -298
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -1
- package/dist/index.d.ts +63 -1
- package/dist/index.js +948 -303
- package/dist/index.js.map +1 -1
- package/dist/styles.css +105 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30,6 +30,26 @@ var defaultChatConfig = {
|
|
|
30
30
|
attachFileTooltip: "Attach file",
|
|
31
31
|
recordAudio: "Record Audio",
|
|
32
32
|
recordAudioTooltip: "Record audio",
|
|
33
|
+
voiceEnter: "Voice input",
|
|
34
|
+
voiceExit: "Use keyboard",
|
|
35
|
+
voiceTitle: "Voice",
|
|
36
|
+
voiceIdle: "Tap the mic to record",
|
|
37
|
+
voicePreparing: "Preparing microphone...",
|
|
38
|
+
voiceWaiting: "Waiting for speech...",
|
|
39
|
+
voiceListening: "Listening...",
|
|
40
|
+
voiceFinishing: "Finishing capture...",
|
|
41
|
+
voiceReview: "Ready to send",
|
|
42
|
+
voiceSending: "Sending...",
|
|
43
|
+
voiceStart: "Start recording",
|
|
44
|
+
voiceStop: "Stop recording",
|
|
45
|
+
voiceSendNow: "Send now",
|
|
46
|
+
voiceCancel: "Cancel",
|
|
47
|
+
voiceDiscard: "Delete recording",
|
|
48
|
+
voiceRecordAgain: "Record again",
|
|
49
|
+
voiceAutoSendIn: "Auto-sends in {{seconds}}s",
|
|
50
|
+
voiceTranscriptPending: "Transcript unavailable",
|
|
51
|
+
voicePermissionDenied: "Microphone access was denied.",
|
|
52
|
+
voiceCaptureError: "Unable to capture audio.",
|
|
33
53
|
// Header labels
|
|
34
54
|
exportData: "Export data",
|
|
35
55
|
importData: "Import data",
|
|
@@ -92,6 +112,16 @@ var defaultChatConfig = {
|
|
|
92
112
|
longMessageChunkChars: 12e3,
|
|
93
113
|
renderUserMarkdown: true
|
|
94
114
|
},
|
|
115
|
+
voiceCompose: {
|
|
116
|
+
enabled: false,
|
|
117
|
+
defaultMode: "text",
|
|
118
|
+
autoSendDelayMs: 5e3,
|
|
119
|
+
persistComposer: true,
|
|
120
|
+
showTranscriptPreview: true,
|
|
121
|
+
transcriptMode: "final-only",
|
|
122
|
+
maxRecordingMs: 6e4,
|
|
123
|
+
createProvider: void 0
|
|
124
|
+
},
|
|
95
125
|
customComponent: {},
|
|
96
126
|
headerActions: null
|
|
97
127
|
};
|
|
@@ -114,6 +144,10 @@ function mergeConfig(_baseConfig, userConfig) {
|
|
|
114
144
|
...defaultChatConfig.ui,
|
|
115
145
|
...userConfig.ui
|
|
116
146
|
},
|
|
147
|
+
voiceCompose: {
|
|
148
|
+
...defaultChatConfig.voiceCompose,
|
|
149
|
+
...userConfig.voiceCompose
|
|
150
|
+
},
|
|
117
151
|
agentSelector: {
|
|
118
152
|
...defaultChatConfig.agentSelector,
|
|
119
153
|
...userConfig.agentSelector
|
|
@@ -732,7 +766,7 @@ var MediaRenderer = memo(function MediaRenderer2({ attachment }) {
|
|
|
732
766
|
URL.revokeObjectURL(objectUrl);
|
|
733
767
|
};
|
|
734
768
|
}, [attachment.kind, attachment.dataUrl]);
|
|
735
|
-
const
|
|
769
|
+
const formatDuration2 = (ms) => {
|
|
736
770
|
if (!ms) return "";
|
|
737
771
|
const seconds = Math.floor(ms / 1e3);
|
|
738
772
|
const minutes = Math.floor(seconds / 60);
|
|
@@ -2794,6 +2828,215 @@ function useChatUserContext() {
|
|
|
2794
2828
|
return v;
|
|
2795
2829
|
}
|
|
2796
2830
|
|
|
2831
|
+
// src/lib/voiceCompose.ts
|
|
2832
|
+
var AUDIO_MIME_TYPES = [
|
|
2833
|
+
"audio/webm;codecs=opus",
|
|
2834
|
+
"audio/webm",
|
|
2835
|
+
"audio/mp4",
|
|
2836
|
+
"audio/ogg;codecs=opus"
|
|
2837
|
+
];
|
|
2838
|
+
var pickRecorderMimeType = () => {
|
|
2839
|
+
if (typeof MediaRecorder === "undefined") return void 0;
|
|
2840
|
+
for (const mimeType of AUDIO_MIME_TYPES) {
|
|
2841
|
+
if (typeof MediaRecorder.isTypeSupported === "function" && MediaRecorder.isTypeSupported(mimeType)) {
|
|
2842
|
+
return mimeType;
|
|
2843
|
+
}
|
|
2844
|
+
}
|
|
2845
|
+
return void 0;
|
|
2846
|
+
};
|
|
2847
|
+
var blobToDataUrl = (blob) => new Promise((resolve, reject) => {
|
|
2848
|
+
const reader = new FileReader();
|
|
2849
|
+
reader.onload = () => resolve(reader.result);
|
|
2850
|
+
reader.onerror = () => reject(reader.error ?? new Error("Failed to read recorded audio"));
|
|
2851
|
+
reader.readAsDataURL(blob);
|
|
2852
|
+
});
|
|
2853
|
+
var stopStream = (stream) => {
|
|
2854
|
+
if (!stream) return;
|
|
2855
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
2856
|
+
};
|
|
2857
|
+
var closeAudioContext = async (audioContext) => {
|
|
2858
|
+
if (!audioContext) return;
|
|
2859
|
+
try {
|
|
2860
|
+
await audioContext.close();
|
|
2861
|
+
} catch {
|
|
2862
|
+
}
|
|
2863
|
+
};
|
|
2864
|
+
var emitDuration = (handlers, startedAt) => {
|
|
2865
|
+
handlers.onDurationChange?.(Math.max(0, Date.now() - startedAt));
|
|
2866
|
+
};
|
|
2867
|
+
var createManualVoiceProvider = async (handlers, options = {}) => {
|
|
2868
|
+
let mediaRecorder = null;
|
|
2869
|
+
let mediaStream = null;
|
|
2870
|
+
let audioContext = null;
|
|
2871
|
+
let analyser = null;
|
|
2872
|
+
let levelData = null;
|
|
2873
|
+
let levelFrame = 0;
|
|
2874
|
+
let durationTimer = null;
|
|
2875
|
+
let maxDurationTimer = null;
|
|
2876
|
+
let startedAt = 0;
|
|
2877
|
+
let shouldEmitSegment = true;
|
|
2878
|
+
let isStarting = false;
|
|
2879
|
+
const clearTimers = () => {
|
|
2880
|
+
if (durationTimer) {
|
|
2881
|
+
clearInterval(durationTimer);
|
|
2882
|
+
durationTimer = null;
|
|
2883
|
+
}
|
|
2884
|
+
if (maxDurationTimer) {
|
|
2885
|
+
clearTimeout(maxDurationTimer);
|
|
2886
|
+
maxDurationTimer = null;
|
|
2887
|
+
}
|
|
2888
|
+
};
|
|
2889
|
+
const stopLevelLoop = () => {
|
|
2890
|
+
if (levelFrame) {
|
|
2891
|
+
cancelAnimationFrame(levelFrame);
|
|
2892
|
+
levelFrame = 0;
|
|
2893
|
+
}
|
|
2894
|
+
handlers.onAudioLevelChange?.(0);
|
|
2895
|
+
};
|
|
2896
|
+
const startLevelLoop = () => {
|
|
2897
|
+
if (!analyser || !levelData) return;
|
|
2898
|
+
const tick = () => {
|
|
2899
|
+
if (!analyser || !levelData) return;
|
|
2900
|
+
analyser.getByteTimeDomainData(levelData);
|
|
2901
|
+
let sum = 0;
|
|
2902
|
+
for (let index = 0; index < levelData.length; index += 1) {
|
|
2903
|
+
const centered = (levelData[index] - 128) / 128;
|
|
2904
|
+
sum += centered * centered;
|
|
2905
|
+
}
|
|
2906
|
+
const rms = Math.sqrt(sum / levelData.length);
|
|
2907
|
+
handlers.onAudioLevelChange?.(Math.min(1, rms * 4));
|
|
2908
|
+
levelFrame = requestAnimationFrame(tick);
|
|
2909
|
+
};
|
|
2910
|
+
tick();
|
|
2911
|
+
};
|
|
2912
|
+
const cleanupActiveResources = async () => {
|
|
2913
|
+
clearTimers();
|
|
2914
|
+
stopLevelLoop();
|
|
2915
|
+
stopStream(mediaStream);
|
|
2916
|
+
mediaStream = null;
|
|
2917
|
+
analyser = null;
|
|
2918
|
+
levelData = null;
|
|
2919
|
+
await closeAudioContext(audioContext);
|
|
2920
|
+
audioContext = null;
|
|
2921
|
+
};
|
|
2922
|
+
const finalizeStop = async () => {
|
|
2923
|
+
mediaRecorder = null;
|
|
2924
|
+
isStarting = false;
|
|
2925
|
+
await cleanupActiveResources();
|
|
2926
|
+
};
|
|
2927
|
+
const start = async () => {
|
|
2928
|
+
if (isStarting || mediaRecorder?.state === "recording") {
|
|
2929
|
+
return;
|
|
2930
|
+
}
|
|
2931
|
+
if (!navigator.mediaDevices?.getUserMedia) {
|
|
2932
|
+
throw new Error("Audio capture is not supported in this browser");
|
|
2933
|
+
}
|
|
2934
|
+
if (typeof MediaRecorder === "undefined") {
|
|
2935
|
+
throw new Error("MediaRecorder is not supported in this browser");
|
|
2936
|
+
}
|
|
2937
|
+
isStarting = true;
|
|
2938
|
+
shouldEmitSegment = true;
|
|
2939
|
+
handlers.onTranscriptChange?.({});
|
|
2940
|
+
handlers.onDurationChange?.(0);
|
|
2941
|
+
handlers.onAudioLevelChange?.(0);
|
|
2942
|
+
handlers.onStateChange?.("preparing");
|
|
2943
|
+
try {
|
|
2944
|
+
mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
2945
|
+
const mimeType = pickRecorderMimeType();
|
|
2946
|
+
mediaRecorder = mimeType ? new MediaRecorder(mediaStream, { mimeType }) : new MediaRecorder(mediaStream);
|
|
2947
|
+
const chunks = [];
|
|
2948
|
+
mediaRecorder.ondataavailable = (event) => {
|
|
2949
|
+
if (event.data.size > 0) {
|
|
2950
|
+
chunks.push(event.data);
|
|
2951
|
+
}
|
|
2952
|
+
};
|
|
2953
|
+
mediaRecorder.onerror = (event) => {
|
|
2954
|
+
const error = event.error ?? new Error("Audio recorder failed");
|
|
2955
|
+
handlers.onError?.(error);
|
|
2956
|
+
};
|
|
2957
|
+
mediaRecorder.onstop = async () => {
|
|
2958
|
+
const durationMs = startedAt > 0 ? Math.max(0, Date.now() - startedAt) : 0;
|
|
2959
|
+
try {
|
|
2960
|
+
if (shouldEmitSegment && chunks.length > 0) {
|
|
2961
|
+
const blob = new Blob(chunks, {
|
|
2962
|
+
type: mediaRecorder?.mimeType || mimeType || "audio/webm"
|
|
2963
|
+
});
|
|
2964
|
+
const dataUrl = await blobToDataUrl(blob);
|
|
2965
|
+
handlers.onSegmentReady?.({
|
|
2966
|
+
attachment: {
|
|
2967
|
+
kind: "audio",
|
|
2968
|
+
dataUrl,
|
|
2969
|
+
mimeType: blob.type || "audio/webm",
|
|
2970
|
+
durationMs,
|
|
2971
|
+
fileName: `voice-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.webm`,
|
|
2972
|
+
size: blob.size
|
|
2973
|
+
},
|
|
2974
|
+
metadata: { source: "manual" }
|
|
2975
|
+
});
|
|
2976
|
+
} else {
|
|
2977
|
+
handlers.onStateChange?.("idle");
|
|
2978
|
+
}
|
|
2979
|
+
} catch (error) {
|
|
2980
|
+
handlers.onError?.(error);
|
|
2981
|
+
} finally {
|
|
2982
|
+
await finalizeStop();
|
|
2983
|
+
}
|
|
2984
|
+
};
|
|
2985
|
+
const AudioContextCtor = globalThis.AudioContext || globalThis.webkitAudioContext;
|
|
2986
|
+
if (AudioContextCtor) {
|
|
2987
|
+
audioContext = new AudioContextCtor();
|
|
2988
|
+
await audioContext.resume().catch(() => void 0);
|
|
2989
|
+
const sourceNode = audioContext.createMediaStreamSource(mediaStream);
|
|
2990
|
+
analyser = audioContext.createAnalyser();
|
|
2991
|
+
analyser.fftSize = 1024;
|
|
2992
|
+
levelData = new Uint8Array(analyser.fftSize);
|
|
2993
|
+
sourceNode.connect(analyser);
|
|
2994
|
+
startLevelLoop();
|
|
2995
|
+
}
|
|
2996
|
+
startedAt = Date.now();
|
|
2997
|
+
emitDuration(handlers, startedAt);
|
|
2998
|
+
durationTimer = setInterval(() => emitDuration(handlers, startedAt), 200);
|
|
2999
|
+
if (options.maxRecordingMs && options.maxRecordingMs > 0) {
|
|
3000
|
+
maxDurationTimer = setTimeout(() => {
|
|
3001
|
+
void stop();
|
|
3002
|
+
}, options.maxRecordingMs);
|
|
3003
|
+
}
|
|
3004
|
+
mediaRecorder.start();
|
|
3005
|
+
handlers.onStateChange?.("listening");
|
|
3006
|
+
} catch (error) {
|
|
3007
|
+
isStarting = false;
|
|
3008
|
+
await cleanupActiveResources();
|
|
3009
|
+
throw error;
|
|
3010
|
+
}
|
|
3011
|
+
};
|
|
3012
|
+
const stop = async () => {
|
|
3013
|
+
if (!mediaRecorder || mediaRecorder.state === "inactive") {
|
|
3014
|
+
return;
|
|
3015
|
+
}
|
|
3016
|
+
handlers.onStateChange?.("finishing");
|
|
3017
|
+
mediaRecorder.stop();
|
|
3018
|
+
};
|
|
3019
|
+
const cancel = async () => {
|
|
3020
|
+
shouldEmitSegment = false;
|
|
3021
|
+
if (mediaRecorder && mediaRecorder.state !== "inactive") {
|
|
3022
|
+
mediaRecorder.stop();
|
|
3023
|
+
return;
|
|
3024
|
+
}
|
|
3025
|
+
await finalizeStop();
|
|
3026
|
+
handlers.onStateChange?.("idle");
|
|
3027
|
+
};
|
|
3028
|
+
const destroy = async () => {
|
|
3029
|
+
await cancel();
|
|
3030
|
+
};
|
|
3031
|
+
return {
|
|
3032
|
+
start,
|
|
3033
|
+
stop,
|
|
3034
|
+
cancel,
|
|
3035
|
+
destroy
|
|
3036
|
+
};
|
|
3037
|
+
};
|
|
3038
|
+
var resolveVoiceProviderFactory = (createProvider) => createProvider ?? createManualVoiceProvider;
|
|
3039
|
+
|
|
2797
3040
|
// src/components/ui/progress.tsx
|
|
2798
3041
|
import * as ProgressPrimitive from "@radix-ui/react-progress";
|
|
2799
3042
|
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
@@ -2823,21 +3066,197 @@ function Progress({
|
|
|
2823
3066
|
);
|
|
2824
3067
|
}
|
|
2825
3068
|
|
|
3069
|
+
// src/components/chat/VoiceComposer.tsx
|
|
3070
|
+
import { Keyboard, Loader2, Mic, Send, Square, Trash2 as Trash23, X as X2 } from "lucide-react";
|
|
3071
|
+
import { jsx as jsx21, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3072
|
+
var formatDuration = (durationMs) => {
|
|
3073
|
+
const totalSeconds = Math.max(0, Math.floor(durationMs / 1e3));
|
|
3074
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
3075
|
+
const seconds = totalSeconds % 60;
|
|
3076
|
+
return `${minutes}:${seconds.toString().padStart(2, "0")}`;
|
|
3077
|
+
};
|
|
3078
|
+
var interpolateSeconds = (label, seconds) => {
|
|
3079
|
+
if (!label) {
|
|
3080
|
+
return `Auto-sends in ${seconds}s`;
|
|
3081
|
+
}
|
|
3082
|
+
if (label.includes("{{seconds}}")) {
|
|
3083
|
+
return label.replace(/\{\{\s*seconds\s*\}\}/g, String(seconds));
|
|
3084
|
+
}
|
|
3085
|
+
return `${label} ${seconds}s`;
|
|
3086
|
+
};
|
|
3087
|
+
var resolveStateLabel = (state, labels, errorMessage) => {
|
|
3088
|
+
switch (state) {
|
|
3089
|
+
case "preparing":
|
|
3090
|
+
return labels?.voicePreparing || "Preparing microphone...";
|
|
3091
|
+
case "waiting_for_speech":
|
|
3092
|
+
return labels?.voiceWaiting || "Waiting for speech...";
|
|
3093
|
+
case "listening":
|
|
3094
|
+
return labels?.voiceListening || "Listening...";
|
|
3095
|
+
case "finishing":
|
|
3096
|
+
return labels?.voiceFinishing || "Finishing capture...";
|
|
3097
|
+
case "review":
|
|
3098
|
+
return labels?.voiceReview || "Ready to send";
|
|
3099
|
+
case "sending":
|
|
3100
|
+
return labels?.voiceSending || "Sending...";
|
|
3101
|
+
case "error":
|
|
3102
|
+
return errorMessage || labels?.voiceCaptureError || "Unable to capture audio.";
|
|
3103
|
+
case "idle":
|
|
3104
|
+
default:
|
|
3105
|
+
return labels?.voiceIdle || "Tap the mic to record";
|
|
3106
|
+
}
|
|
3107
|
+
};
|
|
3108
|
+
var resolveTranscriptText = (transcript, transcriptMode) => {
|
|
3109
|
+
if (transcriptMode === "none" || !transcript) {
|
|
3110
|
+
return null;
|
|
3111
|
+
}
|
|
3112
|
+
if (transcriptMode === "final-only") {
|
|
3113
|
+
return transcript.final?.trim() || null;
|
|
3114
|
+
}
|
|
3115
|
+
return transcript.final?.trim() || transcript.partial?.trim() || null;
|
|
3116
|
+
};
|
|
3117
|
+
var VoiceComposer = ({
|
|
3118
|
+
state,
|
|
3119
|
+
transcript,
|
|
3120
|
+
transcriptMode,
|
|
3121
|
+
showTranscriptPreview,
|
|
3122
|
+
attachment,
|
|
3123
|
+
durationMs,
|
|
3124
|
+
audioLevel,
|
|
3125
|
+
countdownMs,
|
|
3126
|
+
autoSendDelayMs,
|
|
3127
|
+
isAutoSendActive,
|
|
3128
|
+
errorMessage,
|
|
3129
|
+
disabled = false,
|
|
3130
|
+
labels,
|
|
3131
|
+
onStart,
|
|
3132
|
+
onStop,
|
|
3133
|
+
onCancelAutoSend,
|
|
3134
|
+
onDiscard,
|
|
3135
|
+
onRecordAgain,
|
|
3136
|
+
onSendNow,
|
|
3137
|
+
onExit
|
|
3138
|
+
}) => {
|
|
3139
|
+
const transcriptText = resolveTranscriptText(transcript, transcriptMode);
|
|
3140
|
+
const countdownSeconds = Math.max(1, Math.ceil(countdownMs / 1e3));
|
|
3141
|
+
const countdownValue = autoSendDelayMs > 0 ? Math.min(100, Math.max(0, (autoSendDelayMs - countdownMs) / autoSendDelayMs * 100)) : 100;
|
|
3142
|
+
const isBusy = state === "preparing" || state === "finishing" || state === "sending";
|
|
3143
|
+
const isCapturing = state === "waiting_for_speech" || state === "listening";
|
|
3144
|
+
const isReviewing = state === "review";
|
|
3145
|
+
const levelValue = isCapturing || state === "preparing" || state === "finishing" ? Math.max(8, Math.round(audioLevel * 100)) : 0;
|
|
3146
|
+
const headerLabel = state === "error" ? labels?.voiceCaptureError || "Unable to capture audio." : resolveStateLabel(state, labels, errorMessage);
|
|
3147
|
+
return /* @__PURE__ */ jsxs11("div", { className: "w-full max-w-3xl rounded-xl border bg-background p-3 shadow-sm sm:p-4 md:min-w-3xl", children: [
|
|
3148
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between gap-2 sm:gap-3", children: [
|
|
3149
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
3150
|
+
/* @__PURE__ */ jsx21(Badge, { variant: "outline", children: labels?.voiceTitle || "Voice" }),
|
|
3151
|
+
/* @__PURE__ */ jsx21("span", { className: "truncate text-xs sm:text-sm text-muted-foreground", children: headerLabel })
|
|
3152
|
+
] }),
|
|
3153
|
+
/* @__PURE__ */ jsxs11(
|
|
3154
|
+
Button,
|
|
3155
|
+
{
|
|
3156
|
+
type: "button",
|
|
3157
|
+
variant: "ghost",
|
|
3158
|
+
size: "sm",
|
|
3159
|
+
className: "shrink-0 px-2 sm:px-3",
|
|
3160
|
+
onClick: onExit,
|
|
3161
|
+
disabled: disabled || isBusy,
|
|
3162
|
+
children: [
|
|
3163
|
+
/* @__PURE__ */ jsx21(Keyboard, { className: "h-4 w-4" }),
|
|
3164
|
+
/* @__PURE__ */ jsx21("span", { className: "hidden sm:inline", children: labels?.voiceExit || "Use keyboard" })
|
|
3165
|
+
]
|
|
3166
|
+
}
|
|
3167
|
+
)
|
|
3168
|
+
] }),
|
|
3169
|
+
!isReviewing ? /* @__PURE__ */ jsx21("div", { className: "mt-3 rounded-xl border border-dashed border-primary/30 bg-primary/5 px-3 py-3 text-center sm:px-4 sm:py-4", children: /* @__PURE__ */ jsxs11("div", { className: "mx-auto flex w-full max-w-sm flex-col items-center gap-3", children: [
|
|
3170
|
+
/* @__PURE__ */ jsx21(
|
|
3171
|
+
Button,
|
|
3172
|
+
{
|
|
3173
|
+
type: "button",
|
|
3174
|
+
size: "icon",
|
|
3175
|
+
variant: isCapturing ? "destructive" : "outline",
|
|
3176
|
+
className: `h-16 w-16 rounded-full sm:h-20 sm:w-20 ${isCapturing ? "bg-red-500 hover:bg-red-600 text-white border-red-500" : "border-red-200 bg-red-50 text-red-600 hover:bg-red-100 hover:text-red-700"}`,
|
|
3177
|
+
onClick: isCapturing ? onStop : onStart,
|
|
3178
|
+
disabled: disabled || isBusy,
|
|
3179
|
+
children: isBusy ? /* @__PURE__ */ jsx21(Loader2, { className: "h-7 w-7 animate-spin" }) : isCapturing ? /* @__PURE__ */ jsx21(Square, { className: "h-7 w-7" }) : /* @__PURE__ */ jsx21(Mic, { className: "h-7 w-7" })
|
|
3180
|
+
}
|
|
3181
|
+
),
|
|
3182
|
+
/* @__PURE__ */ jsxs11("div", { className: "w-full space-y-2", children: [
|
|
3183
|
+
/* @__PURE__ */ jsx21(Progress, { value: levelValue, className: "h-2" }),
|
|
3184
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
|
|
3185
|
+
/* @__PURE__ */ jsx21("span", { children: formatDuration(durationMs) }),
|
|
3186
|
+
/* @__PURE__ */ jsx21("span", { children: isCapturing ? labels?.voiceStop || "Stop recording" : labels?.voiceStart || "Start recording" })
|
|
3187
|
+
] })
|
|
3188
|
+
] }),
|
|
3189
|
+
showTranscriptPreview && transcriptMode !== "none" && transcriptText && /* @__PURE__ */ jsx21("div", { className: "w-full rounded-lg border bg-background px-3 py-2 text-left text-sm", children: transcriptText })
|
|
3190
|
+
] }) }) : /* @__PURE__ */ jsxs11("div", { className: "mt-3 rounded-xl border bg-muted/20 p-3 sm:p-4", children: [
|
|
3191
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-start justify-between gap-2", children: [
|
|
3192
|
+
/* @__PURE__ */ jsxs11("div", { className: "min-w-0", children: [
|
|
3193
|
+
/* @__PURE__ */ jsx21("div", { className: "text-sm font-medium text-foreground", children: labels?.voiceReview || "Ready to send" }),
|
|
3194
|
+
/* @__PURE__ */ jsx21("div", { className: "text-xs text-muted-foreground", children: formatDuration(durationMs) })
|
|
3195
|
+
] }),
|
|
3196
|
+
/* @__PURE__ */ jsx21(
|
|
3197
|
+
Button,
|
|
3198
|
+
{
|
|
3199
|
+
type: "button",
|
|
3200
|
+
variant: "ghost",
|
|
3201
|
+
size: "icon",
|
|
3202
|
+
className: "h-8 w-8 shrink-0 text-muted-foreground hover:text-destructive",
|
|
3203
|
+
onClick: onDiscard,
|
|
3204
|
+
disabled,
|
|
3205
|
+
"aria-label": labels?.voiceDiscard || "Delete recording",
|
|
3206
|
+
title: labels?.voiceDiscard || "Delete recording",
|
|
3207
|
+
children: /* @__PURE__ */ jsx21(Trash23, { className: "h-4 w-4" })
|
|
3208
|
+
}
|
|
3209
|
+
)
|
|
3210
|
+
] }),
|
|
3211
|
+
attachment && /* @__PURE__ */ jsx21("div", { className: "mt-3 rounded-lg bg-background p-2", children: /* @__PURE__ */ jsx21("audio", { controls: true, preload: "metadata", className: "w-full", children: /* @__PURE__ */ jsx21("source", { src: attachment.dataUrl, type: attachment.mimeType }) }) }),
|
|
3212
|
+
showTranscriptPreview && transcriptMode !== "none" && transcriptText && /* @__PURE__ */ jsx21("div", { className: "mt-3 rounded-lg border bg-background px-3 py-2 text-left text-sm", children: transcriptText }),
|
|
3213
|
+
isAutoSendActive && autoSendDelayMs > 0 && /* @__PURE__ */ jsxs11("div", { className: "mt-3 space-y-2", children: [
|
|
3214
|
+
/* @__PURE__ */ jsx21(Progress, { value: countdownValue, className: "h-2" }),
|
|
3215
|
+
/* @__PURE__ */ jsx21("div", { className: "text-center text-xs text-muted-foreground", children: interpolateSeconds(labels?.voiceAutoSendIn, countdownSeconds) })
|
|
3216
|
+
] }),
|
|
3217
|
+
/* @__PURE__ */ jsxs11("div", { className: "mt-3 flex items-center justify-end gap-2", children: [
|
|
3218
|
+
isAutoSendActive && /* @__PURE__ */ jsxs11(Button, { type: "button", variant: "ghost", size: "sm", onClick: onCancelAutoSend, disabled, children: [
|
|
3219
|
+
/* @__PURE__ */ jsx21(X2, { className: "h-4 w-4" }),
|
|
3220
|
+
labels?.voiceCancel || "Cancel"
|
|
3221
|
+
] }),
|
|
3222
|
+
!isAutoSendActive && /* @__PURE__ */ jsx21(
|
|
3223
|
+
Button,
|
|
3224
|
+
{
|
|
3225
|
+
type: "button",
|
|
3226
|
+
variant: "outline",
|
|
3227
|
+
size: "icon",
|
|
3228
|
+
onClick: onRecordAgain,
|
|
3229
|
+
disabled,
|
|
3230
|
+
"aria-label": labels?.voiceRecordAgain || "Record again",
|
|
3231
|
+
title: labels?.voiceRecordAgain || "Record again",
|
|
3232
|
+
children: /* @__PURE__ */ jsx21(Mic, { className: "h-4 w-4" })
|
|
3233
|
+
}
|
|
3234
|
+
),
|
|
3235
|
+
/* @__PURE__ */ jsxs11(Button, { type: "button", size: "sm", onClick: onSendNow, disabled, children: [
|
|
3236
|
+
/* @__PURE__ */ jsx21(Send, { className: "h-4 w-4" }),
|
|
3237
|
+
labels?.voiceSendNow || "Send now"
|
|
3238
|
+
] })
|
|
3239
|
+
] })
|
|
3240
|
+
] }),
|
|
3241
|
+
state === "error" && errorMessage && /* @__PURE__ */ jsx21("div", { className: "mt-3 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2 text-sm text-destructive", children: errorMessage })
|
|
3242
|
+
] });
|
|
3243
|
+
};
|
|
3244
|
+
|
|
2826
3245
|
// src/components/chat/ChatInput.tsx
|
|
2827
3246
|
import {
|
|
2828
|
-
Send,
|
|
3247
|
+
Send as Send2,
|
|
2829
3248
|
Paperclip,
|
|
2830
|
-
Mic,
|
|
3249
|
+
Mic as Mic2,
|
|
2831
3250
|
Image as Image2,
|
|
2832
3251
|
Video,
|
|
2833
3252
|
FileText,
|
|
2834
|
-
X as
|
|
2835
|
-
Square,
|
|
3253
|
+
X as X3,
|
|
3254
|
+
Square as Square2,
|
|
2836
3255
|
Play,
|
|
2837
3256
|
Pause,
|
|
2838
|
-
Loader2
|
|
3257
|
+
Loader2 as Loader22
|
|
2839
3258
|
} from "lucide-react";
|
|
2840
|
-
import { Fragment as Fragment4, jsx as
|
|
3259
|
+
import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2841
3260
|
var FileUploadItem = memo2(function FileUploadItem2({ file, progress, onCancel }) {
|
|
2842
3261
|
const guessTypeFromName = (name) => {
|
|
2843
3262
|
const ext = (name || "").split(".").pop()?.toLowerCase();
|
|
@@ -2866,10 +3285,10 @@ var FileUploadItem = memo2(function FileUploadItem2({ file, progress, onCancel }
|
|
|
2866
3285
|
};
|
|
2867
3286
|
const getFileIcon = (type, name) => {
|
|
2868
3287
|
const t = typeof type === "string" && type.length > 0 ? type : guessTypeFromName(name);
|
|
2869
|
-
if (t.startsWith("image/")) return /* @__PURE__ */
|
|
2870
|
-
if (t.startsWith("video/")) return /* @__PURE__ */
|
|
2871
|
-
if (t.startsWith("audio/")) return /* @__PURE__ */
|
|
2872
|
-
return /* @__PURE__ */
|
|
3288
|
+
if (t.startsWith("image/")) return /* @__PURE__ */ jsx22(Image2, { className: "h-4 w-4" });
|
|
3289
|
+
if (t.startsWith("video/")) return /* @__PURE__ */ jsx22(Video, { className: "h-4 w-4" });
|
|
3290
|
+
if (t.startsWith("audio/")) return /* @__PURE__ */ jsx22(Mic2, { className: "h-4 w-4" });
|
|
3291
|
+
return /* @__PURE__ */ jsx22(FileText, { className: "h-4 w-4" });
|
|
2873
3292
|
};
|
|
2874
3293
|
const formatFileSize = (bytes) => {
|
|
2875
3294
|
if (bytes === 0) return "0 Bytes";
|
|
@@ -2878,21 +3297,21 @@ var FileUploadItem = memo2(function FileUploadItem2({ file, progress, onCancel }
|
|
|
2878
3297
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
2879
3298
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
|
2880
3299
|
};
|
|
2881
|
-
return /* @__PURE__ */
|
|
3300
|
+
return /* @__PURE__ */ jsx22(Card, { className: "relative", children: /* @__PURE__ */ jsx22(CardContent, { className: "p-3", children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
|
|
2882
3301
|
getFileIcon(file.type, file.name),
|
|
2883
|
-
/* @__PURE__ */
|
|
2884
|
-
/* @__PURE__ */
|
|
2885
|
-
/* @__PURE__ */
|
|
2886
|
-
/* @__PURE__ */
|
|
3302
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex-1 min-w-0", children: [
|
|
3303
|
+
/* @__PURE__ */ jsx22("p", { className: "text-sm font-medium truncate", children: file.name }),
|
|
3304
|
+
/* @__PURE__ */ jsx22("p", { className: "text-xs text-muted-foreground", children: formatFileSize(file.size ?? 0) }),
|
|
3305
|
+
/* @__PURE__ */ jsx22(Progress, { value: progress, className: "h-1 mt-1" })
|
|
2887
3306
|
] }),
|
|
2888
|
-
/* @__PURE__ */
|
|
3307
|
+
/* @__PURE__ */ jsx22(
|
|
2889
3308
|
Button,
|
|
2890
3309
|
{
|
|
2891
3310
|
variant: "ghost",
|
|
2892
3311
|
size: "icon",
|
|
2893
3312
|
className: "h-6 w-6",
|
|
2894
3313
|
onClick: onCancel,
|
|
2895
|
-
children: /* @__PURE__ */
|
|
3314
|
+
children: /* @__PURE__ */ jsx22(X3, { className: "h-3 w-3" })
|
|
2896
3315
|
}
|
|
2897
3316
|
)
|
|
2898
3317
|
] }) }) });
|
|
@@ -2926,35 +3345,35 @@ var AttachmentPreview = memo2(function AttachmentPreview2({ attachment, onRemove
|
|
|
2926
3345
|
setIsPlaying(!isPlaying);
|
|
2927
3346
|
}
|
|
2928
3347
|
};
|
|
2929
|
-
const
|
|
3348
|
+
const formatDuration2 = (ms) => {
|
|
2930
3349
|
if (!ms) return "";
|
|
2931
3350
|
const seconds = Math.floor(ms / 1e3);
|
|
2932
3351
|
const minutes = Math.floor(seconds / 60);
|
|
2933
3352
|
return `${minutes}:${(seconds % 60).toString().padStart(2, "0")}`;
|
|
2934
3353
|
};
|
|
2935
|
-
return /* @__PURE__ */
|
|
2936
|
-
attachment.kind === "image" && /* @__PURE__ */
|
|
2937
|
-
/* @__PURE__ */
|
|
3354
|
+
return /* @__PURE__ */ jsx22(Card, { className: "relative group", children: /* @__PURE__ */ jsxs12(CardContent, { className: "p-2", children: [
|
|
3355
|
+
attachment.kind === "image" && /* @__PURE__ */ jsxs12("div", { className: "relative", children: [
|
|
3356
|
+
/* @__PURE__ */ jsx22(
|
|
2938
3357
|
"img",
|
|
2939
3358
|
{
|
|
2940
3359
|
src: attachment.dataUrl,
|
|
2941
|
-
alt: attachment.fileName || "
|
|
3360
|
+
alt: attachment.fileName || "Attachment",
|
|
2942
3361
|
className: "w-full h-20 object-cover rounded"
|
|
2943
3362
|
}
|
|
2944
3363
|
),
|
|
2945
|
-
/* @__PURE__ */
|
|
3364
|
+
/* @__PURE__ */ jsx22("div", { className: "absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity rounded flex items-center justify-center", children: /* @__PURE__ */ jsx22(
|
|
2946
3365
|
Button,
|
|
2947
3366
|
{
|
|
2948
3367
|
variant: "destructive",
|
|
2949
3368
|
size: "icon",
|
|
2950
3369
|
className: "h-6 w-6",
|
|
2951
3370
|
onClick: onRemove,
|
|
2952
|
-
children: /* @__PURE__ */
|
|
3371
|
+
children: /* @__PURE__ */ jsx22(X3, { className: "h-3 w-3" })
|
|
2953
3372
|
}
|
|
2954
3373
|
) })
|
|
2955
3374
|
] }),
|
|
2956
|
-
attachment.kind === "video" && /* @__PURE__ */
|
|
2957
|
-
/* @__PURE__ */
|
|
3375
|
+
attachment.kind === "video" && /* @__PURE__ */ jsxs12("div", { className: "relative", children: [
|
|
3376
|
+
/* @__PURE__ */ jsx22(
|
|
2958
3377
|
"video",
|
|
2959
3378
|
{
|
|
2960
3379
|
src: attachment.dataUrl,
|
|
@@ -2963,34 +3382,34 @@ var AttachmentPreview = memo2(function AttachmentPreview2({ attachment, onRemove
|
|
|
2963
3382
|
muted: true
|
|
2964
3383
|
}
|
|
2965
3384
|
),
|
|
2966
|
-
/* @__PURE__ */
|
|
3385
|
+
/* @__PURE__ */ jsx22("div", { className: "absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity rounded flex items-center justify-center", children: /* @__PURE__ */ jsx22(
|
|
2967
3386
|
Button,
|
|
2968
3387
|
{
|
|
2969
3388
|
variant: "destructive",
|
|
2970
3389
|
size: "icon",
|
|
2971
3390
|
className: "h-6 w-6",
|
|
2972
3391
|
onClick: onRemove,
|
|
2973
|
-
children: /* @__PURE__ */
|
|
3392
|
+
children: /* @__PURE__ */ jsx22(X3, { className: "h-3 w-3" })
|
|
2974
3393
|
}
|
|
2975
3394
|
) }),
|
|
2976
|
-
/* @__PURE__ */
|
|
3395
|
+
/* @__PURE__ */ jsx22(Badge, { className: "absolute bottom-1 right-1 text-xs", children: formatDuration2(attachment.durationMs) })
|
|
2977
3396
|
] }),
|
|
2978
|
-
attachment.kind === "audio" && /* @__PURE__ */
|
|
2979
|
-
/* @__PURE__ */
|
|
3397
|
+
attachment.kind === "audio" && /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 p-2", children: [
|
|
3398
|
+
/* @__PURE__ */ jsx22(
|
|
2980
3399
|
Button,
|
|
2981
3400
|
{
|
|
2982
3401
|
variant: "outline",
|
|
2983
3402
|
size: "icon",
|
|
2984
3403
|
className: "h-8 w-8",
|
|
2985
3404
|
onClick: handlePlayPause,
|
|
2986
|
-
children: isPlaying ? /* @__PURE__ */
|
|
3405
|
+
children: isPlaying ? /* @__PURE__ */ jsx22(Pause, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx22(Play, { className: "h-3 w-3" })
|
|
2987
3406
|
}
|
|
2988
3407
|
),
|
|
2989
|
-
/* @__PURE__ */
|
|
2990
|
-
/* @__PURE__ */
|
|
2991
|
-
/* @__PURE__ */
|
|
3408
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex-1", children: [
|
|
3409
|
+
/* @__PURE__ */ jsx22("p", { className: "text-xs font-medium", children: attachment.fileName || "Audio" }),
|
|
3410
|
+
/* @__PURE__ */ jsx22("p", { className: "text-xs text-muted-foreground", children: formatDuration2(attachment.durationMs) })
|
|
2992
3411
|
] }),
|
|
2993
|
-
/* @__PURE__ */
|
|
3412
|
+
/* @__PURE__ */ jsx22(
|
|
2994
3413
|
"audio",
|
|
2995
3414
|
{
|
|
2996
3415
|
ref: audioRef,
|
|
@@ -2998,21 +3417,21 @@ var AttachmentPreview = memo2(function AttachmentPreview2({ attachment, onRemove
|
|
|
2998
3417
|
onPause: () => setIsPlaying(false),
|
|
2999
3418
|
onEnded: () => setIsPlaying(false),
|
|
3000
3419
|
preload: "metadata",
|
|
3001
|
-
children: /* @__PURE__ */
|
|
3420
|
+
children: /* @__PURE__ */ jsx22("source", { src: audioPlaybackSrc, type: attachment.mimeType })
|
|
3002
3421
|
}
|
|
3003
3422
|
),
|
|
3004
|
-
/* @__PURE__ */
|
|
3423
|
+
/* @__PURE__ */ jsx22(
|
|
3005
3424
|
Button,
|
|
3006
3425
|
{
|
|
3007
3426
|
variant: "ghost",
|
|
3008
3427
|
size: "icon",
|
|
3009
3428
|
className: "h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity",
|
|
3010
3429
|
onClick: onRemove,
|
|
3011
|
-
children: /* @__PURE__ */
|
|
3430
|
+
children: /* @__PURE__ */ jsx22(X3, { className: "h-3 w-3" })
|
|
3012
3431
|
}
|
|
3013
3432
|
)
|
|
3014
3433
|
] }),
|
|
3015
|
-
attachment.fileName && attachment.kind !== "audio" && /* @__PURE__ */
|
|
3434
|
+
attachment.fileName && attachment.kind !== "audio" && /* @__PURE__ */ jsx22("div", { className: "absolute bottom-0 left-0 right-0 bg-black/70 text-white text-xs p-1 rounded-b", children: /* @__PURE__ */ jsx22("p", { className: "truncate", children: attachment.fileName }) })
|
|
3016
3435
|
] }) });
|
|
3017
3436
|
});
|
|
3018
3437
|
var AudioRecorder = memo2(function AudioRecorder2({ isRecording, onStartRecording, onStopRecording, onCancel, recordingDuration, config }) {
|
|
@@ -3022,61 +3441,71 @@ var AudioRecorder = memo2(function AudioRecorder2({ isRecording, onStartRecordin
|
|
|
3022
3441
|
return `${mins}:${secs.toString().padStart(2, "0")}`;
|
|
3023
3442
|
};
|
|
3024
3443
|
if (!isRecording) {
|
|
3025
|
-
return /* @__PURE__ */
|
|
3026
|
-
/* @__PURE__ */
|
|
3444
|
+
return /* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
3445
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
3027
3446
|
Button,
|
|
3028
3447
|
{
|
|
3029
3448
|
variant: "outline",
|
|
3030
3449
|
size: "icon",
|
|
3031
3450
|
onClick: onStartRecording,
|
|
3032
3451
|
className: "h-10 w-10",
|
|
3033
|
-
children: /* @__PURE__ */
|
|
3452
|
+
children: /* @__PURE__ */ jsx22(Mic2, { className: "h-4 w-4" })
|
|
3034
3453
|
}
|
|
3035
3454
|
) }),
|
|
3036
|
-
/* @__PURE__ */
|
|
3455
|
+
/* @__PURE__ */ jsx22(TooltipContent, { children: config?.labels?.recordAudioTooltip })
|
|
3037
3456
|
] });
|
|
3038
3457
|
}
|
|
3039
|
-
return /* @__PURE__ */
|
|
3040
|
-
/* @__PURE__ */
|
|
3041
|
-
/* @__PURE__ */
|
|
3042
|
-
/* @__PURE__ */
|
|
3458
|
+
return /* @__PURE__ */ jsx22(Card, { className: "border-red-200 bg-red-50 dark:border-red-800 dark:bg-red-950", children: /* @__PURE__ */ jsx22(CardContent, { className: "p-3", children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
|
|
3459
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
|
|
3460
|
+
/* @__PURE__ */ jsx22("div", { className: "h-3 w-3 bg-red-500 rounded-full animate-pulse" }),
|
|
3461
|
+
/* @__PURE__ */ jsx22("span", { className: "text-sm font-medium text-red-700 dark:text-red-300", children: config?.labels?.voiceListening || "Recording" })
|
|
3043
3462
|
] }),
|
|
3044
|
-
/* @__PURE__ */
|
|
3045
|
-
/* @__PURE__ */
|
|
3046
|
-
/* @__PURE__ */
|
|
3463
|
+
/* @__PURE__ */ jsx22(Badge, { variant: "outline", className: "text-xs", children: formatTime(recordingDuration) }),
|
|
3464
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex gap-1 ml-auto", children: [
|
|
3465
|
+
/* @__PURE__ */ jsxs12(
|
|
3047
3466
|
Button,
|
|
3048
3467
|
{
|
|
3049
3468
|
variant: "outline",
|
|
3050
3469
|
size: "sm",
|
|
3051
3470
|
onClick: onCancel,
|
|
3052
3471
|
children: [
|
|
3053
|
-
/* @__PURE__ */
|
|
3054
|
-
"
|
|
3472
|
+
/* @__PURE__ */ jsx22(X3, { className: "h-3 w-3 mr-1" }),
|
|
3473
|
+
config?.labels?.cancel || "Cancel"
|
|
3055
3474
|
]
|
|
3056
3475
|
}
|
|
3057
3476
|
),
|
|
3058
|
-
/* @__PURE__ */
|
|
3477
|
+
/* @__PURE__ */ jsxs12(
|
|
3059
3478
|
Button,
|
|
3060
3479
|
{
|
|
3061
3480
|
variant: "default",
|
|
3062
3481
|
size: "sm",
|
|
3063
3482
|
onClick: onStopRecording,
|
|
3064
3483
|
children: [
|
|
3065
|
-
/* @__PURE__ */
|
|
3066
|
-
"
|
|
3484
|
+
/* @__PURE__ */ jsx22(Square2, { className: "h-3 w-3 mr-1" }),
|
|
3485
|
+
config?.labels?.voiceStop || "Stop"
|
|
3067
3486
|
]
|
|
3068
3487
|
}
|
|
3069
3488
|
)
|
|
3070
3489
|
] })
|
|
3071
3490
|
] }) }) });
|
|
3072
3491
|
});
|
|
3492
|
+
var resolveVoiceErrorMessage = (error, config) => {
|
|
3493
|
+
if (error instanceof DOMException && error.name === "NotAllowedError") {
|
|
3494
|
+
return config?.labels?.voicePermissionDenied || "Microphone access was denied.";
|
|
3495
|
+
}
|
|
3496
|
+
if (error instanceof Error && error.message.trim().length > 0) {
|
|
3497
|
+
return error.message;
|
|
3498
|
+
}
|
|
3499
|
+
return config?.labels?.voiceCaptureError || "Unable to capture audio.";
|
|
3500
|
+
};
|
|
3501
|
+
var clearVoiceTranscript = () => ({});
|
|
3073
3502
|
var ChatInput = memo2(function ChatInput2({
|
|
3074
3503
|
value,
|
|
3075
3504
|
onChange,
|
|
3076
3505
|
onSubmit,
|
|
3077
3506
|
attachments,
|
|
3078
3507
|
onAttachmentsChange,
|
|
3079
|
-
placeholder = "
|
|
3508
|
+
placeholder = "Type your message...",
|
|
3080
3509
|
disabled = false,
|
|
3081
3510
|
isGenerating = false,
|
|
3082
3511
|
onStopGeneration,
|
|
@@ -3089,16 +3518,35 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3089
3518
|
className = "",
|
|
3090
3519
|
config
|
|
3091
3520
|
}) {
|
|
3521
|
+
const voiceComposeEnabled = config?.voiceCompose?.enabled === true;
|
|
3522
|
+
const voiceDefaultMode = config?.voiceCompose?.defaultMode ?? "text";
|
|
3523
|
+
const voiceAutoSendDelayMs = config?.voiceCompose?.autoSendDelayMs ?? 5e3;
|
|
3524
|
+
const voicePersistComposer = config?.voiceCompose?.persistComposer ?? true;
|
|
3525
|
+
const voiceShowTranscriptPreview = config?.voiceCompose?.showTranscriptPreview ?? true;
|
|
3526
|
+
const voiceTranscriptMode = config?.voiceCompose?.transcriptMode ?? "final-only";
|
|
3527
|
+
const voiceMaxRecordingMs = config?.voiceCompose?.maxRecordingMs;
|
|
3092
3528
|
const [isRecording, setIsRecording] = useState6(false);
|
|
3093
3529
|
const { setContext } = useChatUserContext();
|
|
3094
3530
|
const [recordingDuration, setRecordingDuration] = useState6(0);
|
|
3095
3531
|
const [uploadProgress, setUploadProgress] = useState6(/* @__PURE__ */ new Map());
|
|
3532
|
+
const [isVoiceComposerOpen, setIsVoiceComposerOpen] = useState6(
|
|
3533
|
+
() => voiceComposeEnabled && voiceDefaultMode === "voice"
|
|
3534
|
+
);
|
|
3535
|
+
const [voiceState, setVoiceState] = useState6("idle");
|
|
3536
|
+
const [voiceDraft, setVoiceDraft] = useState6(null);
|
|
3537
|
+
const [voiceTranscript, setVoiceTranscript] = useState6(clearVoiceTranscript);
|
|
3538
|
+
const [voiceDurationMs, setVoiceDurationMs] = useState6(0);
|
|
3539
|
+
const [voiceAudioLevel, setVoiceAudioLevel] = useState6(0);
|
|
3540
|
+
const [voiceCountdownMs, setVoiceCountdownMs] = useState6(0);
|
|
3541
|
+
const [isVoiceAutoSendActive, setIsVoiceAutoSendActive] = useState6(false);
|
|
3542
|
+
const [voiceError, setVoiceError] = useState6(null);
|
|
3096
3543
|
const textareaRef = useRef5(null);
|
|
3097
3544
|
const fileInputRef = useRef5(null);
|
|
3098
3545
|
const mediaRecorderRef = useRef5(null);
|
|
3099
3546
|
const recordingStartTime = useRef5(0);
|
|
3100
3547
|
const recordingInterval = useRef5(null);
|
|
3101
3548
|
const mediaStreamRef = useRef5(null);
|
|
3549
|
+
const voiceProviderRef = useRef5(null);
|
|
3102
3550
|
useEffect9(() => {
|
|
3103
3551
|
return () => {
|
|
3104
3552
|
if (mediaStreamRef.current) {
|
|
@@ -3107,6 +3555,10 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3107
3555
|
if (recordingInterval.current) {
|
|
3108
3556
|
clearInterval(recordingInterval.current);
|
|
3109
3557
|
}
|
|
3558
|
+
if (voiceProviderRef.current) {
|
|
3559
|
+
void voiceProviderRef.current.destroy();
|
|
3560
|
+
voiceProviderRef.current = null;
|
|
3561
|
+
}
|
|
3110
3562
|
};
|
|
3111
3563
|
}, []);
|
|
3112
3564
|
const handleSubmit = (e) => {
|
|
@@ -3124,7 +3576,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3124
3576
|
};
|
|
3125
3577
|
const processFile = async (file) => {
|
|
3126
3578
|
if (file.size > maxFileSize) {
|
|
3127
|
-
alert(`
|
|
3579
|
+
alert(`File too large. Max allowed: ${Math.round(maxFileSize / 1024 / 1024)}MB`);
|
|
3128
3580
|
return null;
|
|
3129
3581
|
}
|
|
3130
3582
|
const fileId = `${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
@@ -3183,7 +3635,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3183
3635
|
newMap.delete(fileId);
|
|
3184
3636
|
return newMap;
|
|
3185
3637
|
});
|
|
3186
|
-
alert("
|
|
3638
|
+
alert("Failed to process file");
|
|
3187
3639
|
return null;
|
|
3188
3640
|
}
|
|
3189
3641
|
};
|
|
@@ -3258,7 +3710,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3258
3710
|
}, 1e3);
|
|
3259
3711
|
} catch (error) {
|
|
3260
3712
|
console.error("Error starting recording:", error);
|
|
3261
|
-
alert(
|
|
3713
|
+
alert(config?.labels?.voicePermissionDenied || "Microphone access was denied.");
|
|
3262
3714
|
}
|
|
3263
3715
|
};
|
|
3264
3716
|
const stopRecording = () => {
|
|
@@ -3283,13 +3735,154 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3283
3735
|
}
|
|
3284
3736
|
}
|
|
3285
3737
|
};
|
|
3738
|
+
const resetVoiceComposerState = useCallback3((nextState = "idle") => {
|
|
3739
|
+
setVoiceState(nextState);
|
|
3740
|
+
setVoiceDraft(null);
|
|
3741
|
+
setVoiceTranscript(clearVoiceTranscript());
|
|
3742
|
+
setVoiceDurationMs(0);
|
|
3743
|
+
setVoiceAudioLevel(0);
|
|
3744
|
+
setVoiceCountdownMs(0);
|
|
3745
|
+
setIsVoiceAutoSendActive(false);
|
|
3746
|
+
setVoiceError(null);
|
|
3747
|
+
}, []);
|
|
3748
|
+
const ensureVoiceProvider = useCallback3(async () => {
|
|
3749
|
+
if (voiceProviderRef.current) {
|
|
3750
|
+
return voiceProviderRef.current;
|
|
3751
|
+
}
|
|
3752
|
+
const createProvider = resolveVoiceProviderFactory(config?.voiceCompose?.createProvider);
|
|
3753
|
+
const provider = await createProvider({
|
|
3754
|
+
onStateChange: setVoiceState,
|
|
3755
|
+
onAudioLevelChange: setVoiceAudioLevel,
|
|
3756
|
+
onDurationChange: setVoiceDurationMs,
|
|
3757
|
+
onTranscriptChange: setVoiceTranscript,
|
|
3758
|
+
onSegmentReady: (segment) => {
|
|
3759
|
+
setVoiceDraft(segment);
|
|
3760
|
+
setVoiceTranscript(segment.transcript ?? clearVoiceTranscript());
|
|
3761
|
+
setVoiceDurationMs(segment.attachment.durationMs ?? 0);
|
|
3762
|
+
setVoiceAudioLevel(0);
|
|
3763
|
+
setVoiceCountdownMs(voiceAutoSendDelayMs);
|
|
3764
|
+
setIsVoiceAutoSendActive(voiceAutoSendDelayMs > 0);
|
|
3765
|
+
setVoiceError(null);
|
|
3766
|
+
setVoiceState("review");
|
|
3767
|
+
},
|
|
3768
|
+
onError: (error) => {
|
|
3769
|
+
setVoiceError(resolveVoiceErrorMessage(error, config));
|
|
3770
|
+
setVoiceAudioLevel(0);
|
|
3771
|
+
setVoiceCountdownMs(0);
|
|
3772
|
+
setIsVoiceAutoSendActive(false);
|
|
3773
|
+
setVoiceState("error");
|
|
3774
|
+
}
|
|
3775
|
+
}, {
|
|
3776
|
+
maxRecordingMs: voiceMaxRecordingMs
|
|
3777
|
+
});
|
|
3778
|
+
voiceProviderRef.current = provider;
|
|
3779
|
+
return provider;
|
|
3780
|
+
}, [config, voiceAutoSendDelayMs, voiceMaxRecordingMs]);
|
|
3781
|
+
const closeVoiceComposer = useCallback3(async () => {
|
|
3782
|
+
setIsVoiceComposerOpen(false);
|
|
3783
|
+
setVoiceError(null);
|
|
3784
|
+
setVoiceCountdownMs(0);
|
|
3785
|
+
setVoiceAudioLevel(0);
|
|
3786
|
+
setVoiceTranscript(clearVoiceTranscript());
|
|
3787
|
+
setVoiceDraft(null);
|
|
3788
|
+
setVoiceDurationMs(0);
|
|
3789
|
+
setVoiceState("idle");
|
|
3790
|
+
if (voiceProviderRef.current) {
|
|
3791
|
+
await voiceProviderRef.current.cancel();
|
|
3792
|
+
}
|
|
3793
|
+
}, []);
|
|
3794
|
+
const startVoiceCapture = useCallback3(async () => {
|
|
3795
|
+
if (disabled || isGenerating) {
|
|
3796
|
+
return;
|
|
3797
|
+
}
|
|
3798
|
+
setIsVoiceComposerOpen(true);
|
|
3799
|
+
setVoiceError(null);
|
|
3800
|
+
setVoiceDraft(null);
|
|
3801
|
+
setVoiceCountdownMs(0);
|
|
3802
|
+
setVoiceTranscript(clearVoiceTranscript());
|
|
3803
|
+
setVoiceAudioLevel(0);
|
|
3804
|
+
setVoiceDurationMs(0);
|
|
3805
|
+
setIsVoiceAutoSendActive(false);
|
|
3806
|
+
try {
|
|
3807
|
+
const provider = await ensureVoiceProvider();
|
|
3808
|
+
await provider.start();
|
|
3809
|
+
} catch (error) {
|
|
3810
|
+
setVoiceError(resolveVoiceErrorMessage(error, config));
|
|
3811
|
+
setVoiceState("error");
|
|
3812
|
+
}
|
|
3813
|
+
}, [disabled, isGenerating, ensureVoiceProvider, config]);
|
|
3814
|
+
const stopVoiceCapture = useCallback3(async () => {
|
|
3815
|
+
if (!voiceProviderRef.current) return;
|
|
3816
|
+
try {
|
|
3817
|
+
await voiceProviderRef.current.stop();
|
|
3818
|
+
} catch (error) {
|
|
3819
|
+
setVoiceError(resolveVoiceErrorMessage(error, config));
|
|
3820
|
+
setVoiceState("error");
|
|
3821
|
+
}
|
|
3822
|
+
}, [config]);
|
|
3823
|
+
const cancelVoiceCapture = useCallback3(async () => {
|
|
3824
|
+
if (voiceProviderRef.current) {
|
|
3825
|
+
await voiceProviderRef.current.cancel();
|
|
3826
|
+
}
|
|
3827
|
+
resetVoiceComposerState("idle");
|
|
3828
|
+
}, [resetVoiceComposerState]);
|
|
3829
|
+
const finalizeVoiceComposerAfterSend = useCallback3(() => {
|
|
3830
|
+
if (voicePersistComposer) {
|
|
3831
|
+
resetVoiceComposerState("idle");
|
|
3832
|
+
setIsVoiceComposerOpen(true);
|
|
3833
|
+
return;
|
|
3834
|
+
}
|
|
3835
|
+
void closeVoiceComposer();
|
|
3836
|
+
}, [voicePersistComposer, resetVoiceComposerState, closeVoiceComposer]);
|
|
3837
|
+
const sendVoiceDraft = useCallback3(() => {
|
|
3838
|
+
if (!voiceDraft || disabled || isGenerating) {
|
|
3839
|
+
return;
|
|
3840
|
+
}
|
|
3841
|
+
setVoiceState("sending");
|
|
3842
|
+
setVoiceCountdownMs(0);
|
|
3843
|
+
setIsVoiceAutoSendActive(false);
|
|
3844
|
+
onSubmit("", [...attachments, voiceDraft.attachment]);
|
|
3845
|
+
onChange("");
|
|
3846
|
+
onAttachmentsChange([]);
|
|
3847
|
+
finalizeVoiceComposerAfterSend();
|
|
3848
|
+
}, [
|
|
3849
|
+
voiceDraft,
|
|
3850
|
+
disabled,
|
|
3851
|
+
isGenerating,
|
|
3852
|
+
onSubmit,
|
|
3853
|
+
attachments,
|
|
3854
|
+
onChange,
|
|
3855
|
+
onAttachmentsChange,
|
|
3856
|
+
finalizeVoiceComposerAfterSend
|
|
3857
|
+
]);
|
|
3858
|
+
const cancelVoiceAutoSend = useCallback3(() => {
|
|
3859
|
+
setVoiceCountdownMs(0);
|
|
3860
|
+
setIsVoiceAutoSendActive(false);
|
|
3861
|
+
}, []);
|
|
3862
|
+
useEffect9(() => {
|
|
3863
|
+
if (voiceState !== "review" || !voiceDraft || voiceAutoSendDelayMs <= 0 || !isVoiceAutoSendActive) {
|
|
3864
|
+
return;
|
|
3865
|
+
}
|
|
3866
|
+
const startedAt = Date.now();
|
|
3867
|
+
setVoiceCountdownMs(voiceAutoSendDelayMs);
|
|
3868
|
+
const timer = setInterval(() => {
|
|
3869
|
+
const remaining = Math.max(0, voiceAutoSendDelayMs - (Date.now() - startedAt));
|
|
3870
|
+
setVoiceCountdownMs(remaining);
|
|
3871
|
+
if (remaining <= 0) {
|
|
3872
|
+
clearInterval(timer);
|
|
3873
|
+
sendVoiceDraft();
|
|
3874
|
+
}
|
|
3875
|
+
}, 100);
|
|
3876
|
+
return () => clearInterval(timer);
|
|
3877
|
+
}, [voiceState, voiceDraft, voiceAutoSendDelayMs, isVoiceAutoSendActive, sendVoiceDraft]);
|
|
3286
3878
|
const removeAttachment = (index) => {
|
|
3287
3879
|
const newAttachments = attachments.filter((_, i) => i !== index);
|
|
3288
3880
|
onAttachmentsChange(newAttachments);
|
|
3289
3881
|
};
|
|
3290
3882
|
const canAddMoreAttachments = attachments.length < maxAttachments;
|
|
3291
|
-
|
|
3292
|
-
|
|
3883
|
+
const showVoiceComposer = voiceComposeEnabled && isVoiceComposerOpen;
|
|
3884
|
+
return /* @__PURE__ */ jsx22(TooltipProvider, { children: /* @__PURE__ */ jsx22("div", { className: `border-t py-0 bg-transparent ${className}`, children: /* @__PURE__ */ jsxs12("div", { className: "px-0 md:p-2 pb-1 space-y-4 bg-transparent", children: [
|
|
3885
|
+
uploadProgress.size > 0 && /* @__PURE__ */ jsx22("div", { className: "space-y-2", children: Array.from(uploadProgress.entries()).map(([id, progress]) => /* @__PURE__ */ jsx22(
|
|
3293
3886
|
FileUploadItem,
|
|
3294
3887
|
{
|
|
3295
3888
|
file: { name: progress.fileName },
|
|
@@ -3304,7 +3897,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3304
3897
|
},
|
|
3305
3898
|
id
|
|
3306
3899
|
)) }),
|
|
3307
|
-
isRecording && /* @__PURE__ */
|
|
3900
|
+
isRecording && /* @__PURE__ */ jsx22(
|
|
3308
3901
|
AudioRecorder,
|
|
3309
3902
|
{
|
|
3310
3903
|
isRecording,
|
|
@@ -3315,7 +3908,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3315
3908
|
config
|
|
3316
3909
|
}
|
|
3317
3910
|
),
|
|
3318
|
-
attachments.length > 0 && /* @__PURE__ */
|
|
3911
|
+
attachments.length > 0 && /* @__PURE__ */ jsx22("div", { className: "grid grid-cols-4 gap-2", children: attachments.map((attachment, index) => /* @__PURE__ */ jsx22(
|
|
3319
3912
|
AttachmentPreview,
|
|
3320
3913
|
{
|
|
3321
3914
|
attachment,
|
|
@@ -3323,15 +3916,51 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3323
3916
|
},
|
|
3324
3917
|
index
|
|
3325
3918
|
)) }),
|
|
3326
|
-
/* @__PURE__ */
|
|
3919
|
+
showVoiceComposer ? /* @__PURE__ */ jsx22("div", { className: "mb-1 flex justify-center", children: /* @__PURE__ */ jsx22(
|
|
3920
|
+
VoiceComposer,
|
|
3921
|
+
{
|
|
3922
|
+
state: voiceState,
|
|
3923
|
+
transcript: voiceTranscript,
|
|
3924
|
+
transcriptMode: voiceTranscriptMode,
|
|
3925
|
+
showTranscriptPreview: voiceShowTranscriptPreview,
|
|
3926
|
+
attachment: voiceDraft?.attachment ?? null,
|
|
3927
|
+
durationMs: voiceDurationMs,
|
|
3928
|
+
audioLevel: voiceAudioLevel,
|
|
3929
|
+
countdownMs: voiceCountdownMs,
|
|
3930
|
+
autoSendDelayMs: voiceAutoSendDelayMs,
|
|
3931
|
+
isAutoSendActive: isVoiceAutoSendActive,
|
|
3932
|
+
errorMessage: voiceError,
|
|
3933
|
+
disabled: disabled || isGenerating,
|
|
3934
|
+
labels: config?.labels,
|
|
3935
|
+
onStart: () => {
|
|
3936
|
+
void startVoiceCapture();
|
|
3937
|
+
},
|
|
3938
|
+
onStop: () => {
|
|
3939
|
+
void stopVoiceCapture();
|
|
3940
|
+
},
|
|
3941
|
+
onCancelAutoSend: () => {
|
|
3942
|
+
cancelVoiceAutoSend();
|
|
3943
|
+
},
|
|
3944
|
+
onDiscard: () => {
|
|
3945
|
+
void cancelVoiceCapture();
|
|
3946
|
+
},
|
|
3947
|
+
onRecordAgain: () => {
|
|
3948
|
+
void startVoiceCapture();
|
|
3949
|
+
},
|
|
3950
|
+
onSendNow: sendVoiceDraft,
|
|
3951
|
+
onExit: () => {
|
|
3952
|
+
void closeVoiceComposer();
|
|
3953
|
+
}
|
|
3954
|
+
}
|
|
3955
|
+
) }) : /* @__PURE__ */ jsx22("form", { onSubmit: handleSubmit, className: "mb-1 flex justify-center", children: /* @__PURE__ */ jsxs12(
|
|
3327
3956
|
"div",
|
|
3328
3957
|
{
|
|
3329
3958
|
className: "flex items-end gap-2 p-3 border rounded-lg bg-background w-full md:min-w-3xl max-w-3xl",
|
|
3330
3959
|
onDrop: handleDrop,
|
|
3331
3960
|
onDragOver: handleDragOver,
|
|
3332
3961
|
children: [
|
|
3333
|
-
enableFileUpload && canAddMoreAttachments && /* @__PURE__ */
|
|
3334
|
-
/* @__PURE__ */
|
|
3962
|
+
enableFileUpload && canAddMoreAttachments && /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
3963
|
+
/* @__PURE__ */ jsx22(
|
|
3335
3964
|
"input",
|
|
3336
3965
|
{
|
|
3337
3966
|
ref: fileInputRef,
|
|
@@ -3342,8 +3971,8 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3342
3971
|
className: "hidden"
|
|
3343
3972
|
}
|
|
3344
3973
|
),
|
|
3345
|
-
/* @__PURE__ */
|
|
3346
|
-
/* @__PURE__ */
|
|
3974
|
+
/* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
3975
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
3347
3976
|
Button,
|
|
3348
3977
|
{
|
|
3349
3978
|
type: "button",
|
|
@@ -3356,13 +3985,13 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3356
3985
|
fileInputRef.current?.click();
|
|
3357
3986
|
},
|
|
3358
3987
|
disabled,
|
|
3359
|
-
children: /* @__PURE__ */
|
|
3988
|
+
children: /* @__PURE__ */ jsx22(Paperclip, { className: "h-4 w-4" })
|
|
3360
3989
|
}
|
|
3361
3990
|
) }),
|
|
3362
|
-
/* @__PURE__ */
|
|
3991
|
+
/* @__PURE__ */ jsx22(TooltipContent, { children: config?.labels?.attachFileTooltip })
|
|
3363
3992
|
] })
|
|
3364
3993
|
] }),
|
|
3365
|
-
/* @__PURE__ */
|
|
3994
|
+
/* @__PURE__ */ jsx22("div", { className: "flex-1", children: /* @__PURE__ */ jsx22(
|
|
3366
3995
|
Textarea,
|
|
3367
3996
|
{
|
|
3368
3997
|
ref: textareaRef,
|
|
@@ -3375,7 +4004,23 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3375
4004
|
rows: 1
|
|
3376
4005
|
}
|
|
3377
4006
|
) }),
|
|
3378
|
-
enableAudioRecording && !isRecording && canAddMoreAttachments && !value.trim() && /* @__PURE__ */
|
|
4007
|
+
enableAudioRecording && !isRecording && canAddMoreAttachments && !value.trim() && (voiceComposeEnabled ? /* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
4008
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
4009
|
+
Button,
|
|
4010
|
+
{
|
|
4011
|
+
type: "button",
|
|
4012
|
+
variant: "outline",
|
|
4013
|
+
size: "icon",
|
|
4014
|
+
className: "h-10 w-10",
|
|
4015
|
+
onClick: () => {
|
|
4016
|
+
void startVoiceCapture();
|
|
4017
|
+
},
|
|
4018
|
+
disabled: disabled || isGenerating,
|
|
4019
|
+
children: /* @__PURE__ */ jsx22(Mic2, { className: "h-4 w-4" })
|
|
4020
|
+
}
|
|
4021
|
+
) }),
|
|
4022
|
+
/* @__PURE__ */ jsx22(TooltipContent, { children: config?.labels?.voiceEnter || config?.labels?.recordAudioTooltip })
|
|
4023
|
+
] }) : /* @__PURE__ */ jsx22(
|
|
3379
4024
|
AudioRecorder,
|
|
3380
4025
|
{
|
|
3381
4026
|
isRecording,
|
|
@@ -3385,9 +4030,9 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3385
4030
|
recordingDuration,
|
|
3386
4031
|
config
|
|
3387
4032
|
}
|
|
3388
|
-
),
|
|
3389
|
-
isGenerating ? /* @__PURE__ */
|
|
3390
|
-
/* @__PURE__ */
|
|
4033
|
+
)),
|
|
4034
|
+
isGenerating ? /* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
4035
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
3391
4036
|
Button,
|
|
3392
4037
|
{
|
|
3393
4038
|
type: "button",
|
|
@@ -3395,36 +4040,36 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3395
4040
|
size: "icon",
|
|
3396
4041
|
className: "h-10 w-10",
|
|
3397
4042
|
onClick: onStopGeneration,
|
|
3398
|
-
children: /* @__PURE__ */
|
|
4043
|
+
children: /* @__PURE__ */ jsx22(Square2, { className: "h-4 w-4" })
|
|
3399
4044
|
}
|
|
3400
4045
|
) }),
|
|
3401
|
-
/* @__PURE__ */
|
|
3402
|
-
] }) : /* @__PURE__ */
|
|
3403
|
-
/* @__PURE__ */
|
|
4046
|
+
/* @__PURE__ */ jsx22(TooltipContent, { children: config?.labels?.stopGenerationTooltip })
|
|
4047
|
+
] }) : /* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
4048
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
3404
4049
|
Button,
|
|
3405
4050
|
{
|
|
3406
4051
|
type: "submit",
|
|
3407
4052
|
size: "icon",
|
|
3408
4053
|
className: "h-10 w-10",
|
|
3409
4054
|
disabled: disabled || !value.trim() && attachments.length === 0,
|
|
3410
|
-
children: disabled ? /* @__PURE__ */
|
|
4055
|
+
children: disabled ? /* @__PURE__ */ jsx22(Loader22, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx22(Send2, { className: "h-4 w-4" })
|
|
3411
4056
|
}
|
|
3412
4057
|
) }),
|
|
3413
|
-
/* @__PURE__ */
|
|
4058
|
+
/* @__PURE__ */ jsx22(TooltipContent, { children: config?.labels?.sendMessageTooltip })
|
|
3414
4059
|
] })
|
|
3415
4060
|
]
|
|
3416
4061
|
}
|
|
3417
4062
|
) }),
|
|
3418
|
-
/* @__PURE__ */
|
|
4063
|
+
/* @__PURE__ */ jsxs12("div", { className: "text-[10px] text-muted-foreground text-center", children: [
|
|
3419
4064
|
window.innerWidth > 768 ? config?.labels?.inputHelpText : "",
|
|
3420
|
-
attachments.length > 0 && /* @__PURE__ */
|
|
4065
|
+
attachments.length > 0 && /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
3421
4066
|
" \u2022 ",
|
|
3422
4067
|
attachments.length,
|
|
3423
4068
|
"/",
|
|
3424
4069
|
maxAttachments,
|
|
3425
4070
|
" anexos"
|
|
3426
4071
|
] }),
|
|
3427
|
-
config?.labels?.footerLabel && /* @__PURE__ */
|
|
4072
|
+
config?.labels?.footerLabel && /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
3428
4073
|
" \u2022 ",
|
|
3429
4074
|
config.labels.footerLabel
|
|
3430
4075
|
] })
|
|
@@ -3438,16 +4083,16 @@ import { useState as useState7 } from "react";
|
|
|
3438
4083
|
// src/components/ui/scroll-area.tsx
|
|
3439
4084
|
import * as React11 from "react";
|
|
3440
4085
|
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
|
3441
|
-
import { jsx as
|
|
4086
|
+
import { jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3442
4087
|
var ScrollArea = React11.forwardRef(({ className, children, viewportClassName, onScroll, onScrollCapture, ...props }, ref) => {
|
|
3443
|
-
return /* @__PURE__ */
|
|
4088
|
+
return /* @__PURE__ */ jsxs13(
|
|
3444
4089
|
ScrollAreaPrimitive.Root,
|
|
3445
4090
|
{
|
|
3446
4091
|
"data-slot": "scroll-area",
|
|
3447
4092
|
className: cn("relative", className),
|
|
3448
4093
|
...props,
|
|
3449
4094
|
children: [
|
|
3450
|
-
/* @__PURE__ */
|
|
4095
|
+
/* @__PURE__ */ jsx23(
|
|
3451
4096
|
ScrollAreaPrimitive.Viewport,
|
|
3452
4097
|
{
|
|
3453
4098
|
ref,
|
|
@@ -3461,8 +4106,8 @@ var ScrollArea = React11.forwardRef(({ className, children, viewportClassName, o
|
|
|
3461
4106
|
children
|
|
3462
4107
|
}
|
|
3463
4108
|
),
|
|
3464
|
-
/* @__PURE__ */
|
|
3465
|
-
/* @__PURE__ */
|
|
4109
|
+
/* @__PURE__ */ jsx23(ScrollBar, {}),
|
|
4110
|
+
/* @__PURE__ */ jsx23(ScrollAreaPrimitive.Corner, {})
|
|
3466
4111
|
]
|
|
3467
4112
|
}
|
|
3468
4113
|
);
|
|
@@ -3473,7 +4118,7 @@ function ScrollBar({
|
|
|
3473
4118
|
orientation = "vertical",
|
|
3474
4119
|
...props
|
|
3475
4120
|
}) {
|
|
3476
|
-
return /* @__PURE__ */
|
|
4121
|
+
return /* @__PURE__ */ jsx23(
|
|
3477
4122
|
ScrollAreaPrimitive.ScrollAreaScrollbar,
|
|
3478
4123
|
{
|
|
3479
4124
|
"data-slot": "scroll-area-scrollbar",
|
|
@@ -3485,7 +4130,7 @@ function ScrollBar({
|
|
|
3485
4130
|
className
|
|
3486
4131
|
),
|
|
3487
4132
|
...props,
|
|
3488
|
-
children: /* @__PURE__ */
|
|
4133
|
+
children: /* @__PURE__ */ jsx23(
|
|
3489
4134
|
ScrollAreaPrimitive.ScrollAreaThumb,
|
|
3490
4135
|
{
|
|
3491
4136
|
"data-slot": "scroll-area-thumb",
|
|
@@ -3514,7 +4159,7 @@ import {
|
|
|
3514
4159
|
FileText as FileText2,
|
|
3515
4160
|
Brain as Brain2,
|
|
3516
4161
|
Plus as Plus3,
|
|
3517
|
-
Trash2 as
|
|
4162
|
+
Trash2 as Trash24,
|
|
3518
4163
|
Target,
|
|
3519
4164
|
Lightbulb,
|
|
3520
4165
|
Info,
|
|
@@ -3522,9 +4167,9 @@ import {
|
|
|
3522
4167
|
Bot as Bot3,
|
|
3523
4168
|
Pencil,
|
|
3524
4169
|
Check as Check3,
|
|
3525
|
-
X as
|
|
4170
|
+
X as X4
|
|
3526
4171
|
} from "lucide-react";
|
|
3527
|
-
import { Fragment as Fragment5, jsx as
|
|
4172
|
+
import { Fragment as Fragment5, jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3528
4173
|
var getInitials2 = (name, email) => {
|
|
3529
4174
|
if (name) {
|
|
3530
4175
|
return name.split(" ").map((n) => n[0]).slice(0, 2).join("").toUpperCase();
|
|
@@ -3538,29 +4183,29 @@ var getFieldIcon = (type, key) => {
|
|
|
3538
4183
|
const iconClass = "h-4 w-4 text-muted-foreground";
|
|
3539
4184
|
switch (type) {
|
|
3540
4185
|
case "email":
|
|
3541
|
-
return /* @__PURE__ */
|
|
4186
|
+
return /* @__PURE__ */ jsx24(Mail, { className: iconClass });
|
|
3542
4187
|
case "phone":
|
|
3543
|
-
return /* @__PURE__ */
|
|
4188
|
+
return /* @__PURE__ */ jsx24(Phone, { className: iconClass });
|
|
3544
4189
|
case "url":
|
|
3545
|
-
return /* @__PURE__ */
|
|
4190
|
+
return /* @__PURE__ */ jsx24(Globe, { className: iconClass });
|
|
3546
4191
|
case "date":
|
|
3547
|
-
return /* @__PURE__ */
|
|
4192
|
+
return /* @__PURE__ */ jsx24(Calendar, { className: iconClass });
|
|
3548
4193
|
}
|
|
3549
4194
|
const lowerKey = key?.toLowerCase() || "";
|
|
3550
|
-
if (lowerKey.includes("follower")) return /* @__PURE__ */
|
|
3551
|
-
if (lowerKey.includes("following")) return /* @__PURE__ */
|
|
3552
|
-
if (lowerKey.includes("post") || lowerKey.includes("publication")) return /* @__PURE__ */
|
|
3553
|
-
if (lowerKey.includes("verified") || lowerKey.includes("badge")) return /* @__PURE__ */
|
|
3554
|
-
if (lowerKey.includes("bio")) return /* @__PURE__ */
|
|
3555
|
-
if (lowerKey.includes("email")) return /* @__PURE__ */
|
|
3556
|
-
if (lowerKey.includes("phone") || lowerKey.includes("tel")) return /* @__PURE__ */
|
|
3557
|
-
if (lowerKey.includes("location") || lowerKey.includes("address") || lowerKey.includes("city")) return /* @__PURE__ */
|
|
3558
|
-
if (lowerKey.includes("company") || lowerKey.includes("org")) return /* @__PURE__ */
|
|
3559
|
-
if (lowerKey.includes("job") || lowerKey.includes("role") || lowerKey.includes("title") || lowerKey.includes("position")) return /* @__PURE__ */
|
|
3560
|
-
if (lowerKey.includes("website") || lowerKey.includes("url") || lowerKey.includes("link")) return /* @__PURE__ */
|
|
3561
|
-
if (lowerKey.includes("username") || lowerKey.includes("handle")) return /* @__PURE__ */
|
|
3562
|
-
if (lowerKey.includes("date") || lowerKey.includes("birthday") || lowerKey.includes("joined")) return /* @__PURE__ */
|
|
3563
|
-
return /* @__PURE__ */
|
|
4195
|
+
if (lowerKey.includes("follower")) return /* @__PURE__ */ jsx24(Users, { className: iconClass });
|
|
4196
|
+
if (lowerKey.includes("following")) return /* @__PURE__ */ jsx24(UserPlus, { className: iconClass });
|
|
4197
|
+
if (lowerKey.includes("post") || lowerKey.includes("publication")) return /* @__PURE__ */ jsx24(Image3, { className: iconClass });
|
|
4198
|
+
if (lowerKey.includes("verified") || lowerKey.includes("badge")) return /* @__PURE__ */ jsx24(BadgeCheck, { className: iconClass });
|
|
4199
|
+
if (lowerKey.includes("bio")) return /* @__PURE__ */ jsx24(FileText2, { className: iconClass });
|
|
4200
|
+
if (lowerKey.includes("email")) return /* @__PURE__ */ jsx24(Mail, { className: iconClass });
|
|
4201
|
+
if (lowerKey.includes("phone") || lowerKey.includes("tel")) return /* @__PURE__ */ jsx24(Phone, { className: iconClass });
|
|
4202
|
+
if (lowerKey.includes("location") || lowerKey.includes("address") || lowerKey.includes("city")) return /* @__PURE__ */ jsx24(MapPin, { className: iconClass });
|
|
4203
|
+
if (lowerKey.includes("company") || lowerKey.includes("org")) return /* @__PURE__ */ jsx24(Building, { className: iconClass });
|
|
4204
|
+
if (lowerKey.includes("job") || lowerKey.includes("role") || lowerKey.includes("title") || lowerKey.includes("position")) return /* @__PURE__ */ jsx24(Briefcase, { className: iconClass });
|
|
4205
|
+
if (lowerKey.includes("website") || lowerKey.includes("url") || lowerKey.includes("link")) return /* @__PURE__ */ jsx24(Globe, { className: iconClass });
|
|
4206
|
+
if (lowerKey.includes("username") || lowerKey.includes("handle")) return /* @__PURE__ */ jsx24(AtSign, { className: iconClass });
|
|
4207
|
+
if (lowerKey.includes("date") || lowerKey.includes("birthday") || lowerKey.includes("joined")) return /* @__PURE__ */ jsx24(Calendar, { className: iconClass });
|
|
4208
|
+
return /* @__PURE__ */ jsx24(User2, { className: iconClass });
|
|
3564
4209
|
};
|
|
3565
4210
|
var formatValue = (value, type, key) => {
|
|
3566
4211
|
if (value === null || value === void 0) return "-";
|
|
@@ -3594,15 +4239,15 @@ var getMemoryCategoryIcon = (category) => {
|
|
|
3594
4239
|
const iconClass = "h-4 w-4 text-muted-foreground";
|
|
3595
4240
|
switch (category) {
|
|
3596
4241
|
case "preference":
|
|
3597
|
-
return /* @__PURE__ */
|
|
4242
|
+
return /* @__PURE__ */ jsx24(Heart, { className: iconClass });
|
|
3598
4243
|
case "fact":
|
|
3599
|
-
return /* @__PURE__ */
|
|
4244
|
+
return /* @__PURE__ */ jsx24(Info, { className: iconClass });
|
|
3600
4245
|
case "goal":
|
|
3601
|
-
return /* @__PURE__ */
|
|
4246
|
+
return /* @__PURE__ */ jsx24(Target, { className: iconClass });
|
|
3602
4247
|
case "context":
|
|
3603
|
-
return /* @__PURE__ */
|
|
4248
|
+
return /* @__PURE__ */ jsx24(Lightbulb, { className: iconClass });
|
|
3604
4249
|
default:
|
|
3605
|
-
return /* @__PURE__ */
|
|
4250
|
+
return /* @__PURE__ */ jsx24(Brain2, { className: iconClass });
|
|
3606
4251
|
}
|
|
3607
4252
|
};
|
|
3608
4253
|
var getMemoryCategoryLabel = (category) => {
|
|
@@ -3672,66 +4317,66 @@ var UserProfile = ({
|
|
|
3672
4317
|
const displayName = user?.name || user?.email?.split("@")[0] || "User";
|
|
3673
4318
|
const initials = getInitials2(user?.name, user?.email);
|
|
3674
4319
|
const normalizedFields = normalizeCustomFields(customFields);
|
|
3675
|
-
return /* @__PURE__ */
|
|
4320
|
+
return /* @__PURE__ */ jsx24(Sheet, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxs14(
|
|
3676
4321
|
SheetContent,
|
|
3677
4322
|
{
|
|
3678
4323
|
side: "right",
|
|
3679
4324
|
className: cn("w-full sm:max-w-md p-0 flex flex-col h-full overflow-hidden", className),
|
|
3680
4325
|
children: [
|
|
3681
|
-
/* @__PURE__ */
|
|
3682
|
-
/* @__PURE__ */
|
|
3683
|
-
/* @__PURE__ */
|
|
3684
|
-
/* @__PURE__ */
|
|
3685
|
-
user?.avatar && /* @__PURE__ */
|
|
3686
|
-
/* @__PURE__ */
|
|
4326
|
+
/* @__PURE__ */ jsx24(SheetHeader, { className: "px-6 py-4 border-b shrink-0", children: /* @__PURE__ */ jsx24("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsx24(SheetTitle, { children: labels.title }) }) }),
|
|
4327
|
+
/* @__PURE__ */ jsx24(ScrollArea, { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxs14("div", { className: "p-6 space-y-6", children: [
|
|
4328
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex flex-col items-center text-center space-y-4", children: [
|
|
4329
|
+
/* @__PURE__ */ jsxs14(Avatar, { className: "h-24 w-24 shrink-0", children: [
|
|
4330
|
+
user?.avatar && /* @__PURE__ */ jsx24(AvatarImage, { src: user.avatar, alt: displayName }),
|
|
4331
|
+
/* @__PURE__ */ jsx24(AvatarFallback, { className: "text-2xl bg-primary/10 text-primary", children: initials })
|
|
3687
4332
|
] }),
|
|
3688
|
-
/* @__PURE__ */
|
|
3689
|
-
/* @__PURE__ */
|
|
3690
|
-
user?.email && /* @__PURE__ */
|
|
4333
|
+
/* @__PURE__ */ jsxs14("div", { className: "w-full px-2", children: [
|
|
4334
|
+
/* @__PURE__ */ jsx24("h2", { className: "text-xl font-semibold break-words", children: displayName }),
|
|
4335
|
+
user?.email && /* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground break-words", children: user.email })
|
|
3691
4336
|
] })
|
|
3692
4337
|
] }),
|
|
3693
|
-
/* @__PURE__ */
|
|
3694
|
-
/* @__PURE__ */
|
|
3695
|
-
/* @__PURE__ */
|
|
3696
|
-
/* @__PURE__ */
|
|
3697
|
-
/* @__PURE__ */
|
|
3698
|
-
/* @__PURE__ */
|
|
3699
|
-
/* @__PURE__ */
|
|
3700
|
-
/* @__PURE__ */
|
|
3701
|
-
/* @__PURE__ */
|
|
4338
|
+
/* @__PURE__ */ jsx24(Separator, {}),
|
|
4339
|
+
/* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
|
|
4340
|
+
/* @__PURE__ */ jsx24("h3", { className: "text-sm font-medium text-muted-foreground uppercase tracking-wider", children: labels.basicInfo }),
|
|
4341
|
+
/* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
|
|
4342
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50", children: [
|
|
4343
|
+
/* @__PURE__ */ jsx24(User2, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
4344
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex-1 min-w-0", children: [
|
|
4345
|
+
/* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: "Name" }),
|
|
4346
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm font-medium break-words", children: displayName })
|
|
3702
4347
|
] })
|
|
3703
4348
|
] }),
|
|
3704
|
-
user?.email && /* @__PURE__ */
|
|
3705
|
-
/* @__PURE__ */
|
|
3706
|
-
/* @__PURE__ */
|
|
3707
|
-
/* @__PURE__ */
|
|
3708
|
-
/* @__PURE__ */
|
|
4349
|
+
user?.email && /* @__PURE__ */ jsxs14("div", { className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50", children: [
|
|
4350
|
+
/* @__PURE__ */ jsx24(AtSign, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
4351
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex-1 min-w-0", children: [
|
|
4352
|
+
/* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: "Handle" }),
|
|
4353
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm font-medium break-words", children: user.email })
|
|
3709
4354
|
] })
|
|
3710
4355
|
] }),
|
|
3711
|
-
user?.id && user.id !== user?.name && user.id !== user?.email && /* @__PURE__ */
|
|
3712
|
-
/* @__PURE__ */
|
|
3713
|
-
/* @__PURE__ */
|
|
3714
|
-
/* @__PURE__ */
|
|
3715
|
-
/* @__PURE__ */
|
|
4356
|
+
user?.id && user.id !== user?.name && user.id !== user?.email && /* @__PURE__ */ jsxs14("div", { className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50", children: [
|
|
4357
|
+
/* @__PURE__ */ jsx24(User2, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
4358
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex-1 min-w-0", children: [
|
|
4359
|
+
/* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: "ID" }),
|
|
4360
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm font-medium break-words", children: user.id })
|
|
3716
4361
|
] })
|
|
3717
4362
|
] })
|
|
3718
4363
|
] })
|
|
3719
4364
|
] }),
|
|
3720
|
-
normalizedFields.length > 0 && /* @__PURE__ */
|
|
3721
|
-
/* @__PURE__ */
|
|
3722
|
-
/* @__PURE__ */
|
|
3723
|
-
/* @__PURE__ */
|
|
3724
|
-
/* @__PURE__ */
|
|
4365
|
+
normalizedFields.length > 0 && /* @__PURE__ */ jsxs14(Fragment5, { children: [
|
|
4366
|
+
/* @__PURE__ */ jsx24(Separator, {}),
|
|
4367
|
+
/* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
|
|
4368
|
+
/* @__PURE__ */ jsx24("h3", { className: "text-sm font-medium text-muted-foreground uppercase tracking-wider", children: labels.customFields }),
|
|
4369
|
+
/* @__PURE__ */ jsx24("div", { className: "space-y-2", children: normalizedFields.map((field) => {
|
|
3725
4370
|
const isBioField = field.key.toLowerCase().includes("bio");
|
|
3726
|
-
return /* @__PURE__ */
|
|
4371
|
+
return /* @__PURE__ */ jsxs14(
|
|
3727
4372
|
"div",
|
|
3728
4373
|
{
|
|
3729
4374
|
className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50",
|
|
3730
4375
|
children: [
|
|
3731
|
-
/* @__PURE__ */
|
|
3732
|
-
/* @__PURE__ */
|
|
3733
|
-
/* @__PURE__ */
|
|
3734
|
-
/* @__PURE__ */
|
|
4376
|
+
/* @__PURE__ */ jsx24("div", { className: "mt-0.5 shrink-0", children: field.icon || getFieldIcon(field.type, field.key) }),
|
|
4377
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex-1 min-w-0", children: [
|
|
4378
|
+
/* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: field.label }),
|
|
4379
|
+
/* @__PURE__ */ jsx24("p", { className: cn(
|
|
3735
4380
|
"text-sm font-medium",
|
|
3736
4381
|
isBioField ? "whitespace-pre-wrap break-words" : "break-words"
|
|
3737
4382
|
), children: formatValue(field.value, field.type, field.key) })
|
|
@@ -3743,26 +4388,26 @@ var UserProfile = ({
|
|
|
3743
4388
|
}) })
|
|
3744
4389
|
] })
|
|
3745
4390
|
] }),
|
|
3746
|
-
/* @__PURE__ */
|
|
3747
|
-
/* @__PURE__ */
|
|
3748
|
-
/* @__PURE__ */
|
|
3749
|
-
/* @__PURE__ */
|
|
3750
|
-
/* @__PURE__ */
|
|
4391
|
+
/* @__PURE__ */ jsx24(Separator, {}),
|
|
4392
|
+
/* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
|
|
4393
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between", children: [
|
|
4394
|
+
/* @__PURE__ */ jsxs14("h3", { className: "text-sm font-medium text-muted-foreground uppercase tracking-wider flex items-center gap-2", children: [
|
|
4395
|
+
/* @__PURE__ */ jsx24(Brain2, { className: "h-4 w-4" }),
|
|
3751
4396
|
labels.memories
|
|
3752
4397
|
] }),
|
|
3753
|
-
onAddMemory && /* @__PURE__ */
|
|
4398
|
+
onAddMemory && /* @__PURE__ */ jsx24(
|
|
3754
4399
|
Button,
|
|
3755
4400
|
{
|
|
3756
4401
|
variant: "ghost",
|
|
3757
4402
|
size: "sm",
|
|
3758
4403
|
className: "h-7 px-2",
|
|
3759
4404
|
onClick: () => setIsAddingMemory(true),
|
|
3760
|
-
children: /* @__PURE__ */
|
|
4405
|
+
children: /* @__PURE__ */ jsx24(Plus3, { className: "h-4 w-4" })
|
|
3761
4406
|
}
|
|
3762
4407
|
)
|
|
3763
4408
|
] }),
|
|
3764
|
-
isAddingMemory && onAddMemory && /* @__PURE__ */
|
|
3765
|
-
/* @__PURE__ */
|
|
4409
|
+
isAddingMemory && onAddMemory && /* @__PURE__ */ jsxs14("div", { className: "flex gap-2", children: [
|
|
4410
|
+
/* @__PURE__ */ jsx24(
|
|
3766
4411
|
Input,
|
|
3767
4412
|
{
|
|
3768
4413
|
value: newMemoryContent,
|
|
@@ -3779,24 +4424,24 @@ var UserProfile = ({
|
|
|
3779
4424
|
autoFocus: true
|
|
3780
4425
|
}
|
|
3781
4426
|
),
|
|
3782
|
-
/* @__PURE__ */
|
|
4427
|
+
/* @__PURE__ */ jsx24(Button, { size: "sm", onClick: handleAddMemory, disabled: !newMemoryContent.trim(), children: "Salvar" })
|
|
3783
4428
|
] }),
|
|
3784
|
-
/* @__PURE__ */
|
|
4429
|
+
/* @__PURE__ */ jsx24("div", { className: "space-y-2", children: memories.length === 0 ? /* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground text-center py-4", children: labels.noMemories }) : memories.map((memory) => {
|
|
3785
4430
|
const isEditing = editingMemoryId === memory.id;
|
|
3786
|
-
return /* @__PURE__ */
|
|
4431
|
+
return /* @__PURE__ */ jsxs14(
|
|
3787
4432
|
"div",
|
|
3788
4433
|
{
|
|
3789
4434
|
className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50 group",
|
|
3790
4435
|
children: [
|
|
3791
|
-
/* @__PURE__ */
|
|
3792
|
-
/* @__PURE__ */
|
|
3793
|
-
/* @__PURE__ */
|
|
3794
|
-
/* @__PURE__ */
|
|
3795
|
-
/* @__PURE__ */
|
|
3796
|
-
/* @__PURE__ */
|
|
4436
|
+
/* @__PURE__ */ jsx24("div", { className: "mt-0.5 shrink-0", children: memory.source === "agent" ? /* @__PURE__ */ jsx24(Bot3, { className: "h-4 w-4 text-primary" }) : getMemoryCategoryIcon(memory.category) }),
|
|
4437
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex-1 min-w-0", children: [
|
|
4438
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2 mb-0.5", children: [
|
|
4439
|
+
/* @__PURE__ */ jsx24("span", { className: "text-xs text-muted-foreground", children: getMemoryCategoryLabel(memory.category) }),
|
|
4440
|
+
/* @__PURE__ */ jsx24("span", { className: "text-xs text-muted-foreground", children: "\u2022" }),
|
|
4441
|
+
/* @__PURE__ */ jsx24("span", { className: "text-xs text-muted-foreground", children: memory.source === "agent" ? "IA" : "Voc\xEA" })
|
|
3797
4442
|
] }),
|
|
3798
|
-
isEditing ? /* @__PURE__ */
|
|
3799
|
-
/* @__PURE__ */
|
|
4443
|
+
isEditing ? /* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
|
|
4444
|
+
/* @__PURE__ */ jsx24(
|
|
3800
4445
|
Textarea,
|
|
3801
4446
|
{
|
|
3802
4447
|
value: editingMemoryContent,
|
|
@@ -3813,8 +4458,8 @@ var UserProfile = ({
|
|
|
3813
4458
|
}
|
|
3814
4459
|
}
|
|
3815
4460
|
),
|
|
3816
|
-
/* @__PURE__ */
|
|
3817
|
-
/* @__PURE__ */
|
|
4461
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex gap-1 justify-end", children: [
|
|
4462
|
+
/* @__PURE__ */ jsxs14(
|
|
3818
4463
|
Button,
|
|
3819
4464
|
{
|
|
3820
4465
|
variant: "ghost",
|
|
@@ -3822,12 +4467,12 @@ var UserProfile = ({
|
|
|
3822
4467
|
className: "h-7 px-2",
|
|
3823
4468
|
onClick: handleCancelEdit,
|
|
3824
4469
|
children: [
|
|
3825
|
-
/* @__PURE__ */
|
|
4470
|
+
/* @__PURE__ */ jsx24(X4, { className: "h-3.5 w-3.5 mr-1" }),
|
|
3826
4471
|
"Cancelar"
|
|
3827
4472
|
]
|
|
3828
4473
|
}
|
|
3829
4474
|
),
|
|
3830
|
-
/* @__PURE__ */
|
|
4475
|
+
/* @__PURE__ */ jsxs14(
|
|
3831
4476
|
Button,
|
|
3832
4477
|
{
|
|
3833
4478
|
size: "sm",
|
|
@@ -3835,33 +4480,33 @@ var UserProfile = ({
|
|
|
3835
4480
|
onClick: handleSaveEdit,
|
|
3836
4481
|
disabled: !editingMemoryContent.trim(),
|
|
3837
4482
|
children: [
|
|
3838
|
-
/* @__PURE__ */
|
|
4483
|
+
/* @__PURE__ */ jsx24(Check3, { className: "h-3.5 w-3.5 mr-1" }),
|
|
3839
4484
|
"Salvar"
|
|
3840
4485
|
]
|
|
3841
4486
|
}
|
|
3842
4487
|
)
|
|
3843
4488
|
] })
|
|
3844
|
-
] }) : /* @__PURE__ */
|
|
4489
|
+
] }) : /* @__PURE__ */ jsx24("p", { className: "text-sm break-words", children: memory.content })
|
|
3845
4490
|
] }),
|
|
3846
|
-
!isEditing && (onUpdateMemory || onDeleteMemory) && /* @__PURE__ */
|
|
3847
|
-
onUpdateMemory && /* @__PURE__ */
|
|
4491
|
+
!isEditing && (onUpdateMemory || onDeleteMemory) && /* @__PURE__ */ jsxs14("div", { className: "flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity shrink-0", children: [
|
|
4492
|
+
onUpdateMemory && /* @__PURE__ */ jsx24(
|
|
3848
4493
|
Button,
|
|
3849
4494
|
{
|
|
3850
4495
|
variant: "ghost",
|
|
3851
4496
|
size: "icon",
|
|
3852
4497
|
className: "h-7 w-7",
|
|
3853
4498
|
onClick: () => handleStartEdit(memory),
|
|
3854
|
-
children: /* @__PURE__ */
|
|
4499
|
+
children: /* @__PURE__ */ jsx24(Pencil, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
3855
4500
|
}
|
|
3856
4501
|
),
|
|
3857
|
-
onDeleteMemory && /* @__PURE__ */
|
|
4502
|
+
onDeleteMemory && /* @__PURE__ */ jsx24(
|
|
3858
4503
|
Button,
|
|
3859
4504
|
{
|
|
3860
4505
|
variant: "ghost",
|
|
3861
4506
|
size: "icon",
|
|
3862
4507
|
className: "h-7 w-7",
|
|
3863
4508
|
onClick: () => onDeleteMemory(memory.id),
|
|
3864
|
-
children: /* @__PURE__ */
|
|
4509
|
+
children: /* @__PURE__ */ jsx24(Trash24, { className: "h-3.5 w-3.5 text-destructive" })
|
|
3865
4510
|
}
|
|
3866
4511
|
)
|
|
3867
4512
|
] })
|
|
@@ -3872,8 +4517,8 @@ var UserProfile = ({
|
|
|
3872
4517
|
}) })
|
|
3873
4518
|
] })
|
|
3874
4519
|
] }) }),
|
|
3875
|
-
/* @__PURE__ */
|
|
3876
|
-
onEditProfile && /* @__PURE__ */
|
|
4520
|
+
/* @__PURE__ */ jsxs14("div", { className: "p-4 border-t space-y-2 shrink-0", children: [
|
|
4521
|
+
onEditProfile && /* @__PURE__ */ jsx24(
|
|
3877
4522
|
Button,
|
|
3878
4523
|
{
|
|
3879
4524
|
variant: "outline",
|
|
@@ -3882,7 +4527,7 @@ var UserProfile = ({
|
|
|
3882
4527
|
children: "Edit Profile"
|
|
3883
4528
|
}
|
|
3884
4529
|
),
|
|
3885
|
-
onLogout && /* @__PURE__ */
|
|
4530
|
+
onLogout && /* @__PURE__ */ jsx24(
|
|
3886
4531
|
Button,
|
|
3887
4532
|
{
|
|
3888
4533
|
variant: "destructive",
|
|
@@ -3899,7 +4544,7 @@ var UserProfile = ({
|
|
|
3899
4544
|
|
|
3900
4545
|
// src/components/chat/ChatUI.tsx
|
|
3901
4546
|
import { Sparkles, ArrowRight, MessageSquare, Lightbulb as Lightbulb2, Zap, HelpCircle } from "lucide-react";
|
|
3902
|
-
import { jsx as
|
|
4547
|
+
import { jsx as jsx25, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3903
4548
|
var ChatUI = ({
|
|
3904
4549
|
messages = [],
|
|
3905
4550
|
threads = [],
|
|
@@ -4165,13 +4810,13 @@ var ChatUI = ({
|
|
|
4165
4810
|
const SuggestionIconComponents = [MessageSquare, Lightbulb2, Zap, HelpCircle];
|
|
4166
4811
|
const renderSuggestions = () => {
|
|
4167
4812
|
if (messages.length > 0 || !suggestions.length) return null;
|
|
4168
|
-
return /* @__PURE__ */
|
|
4169
|
-
/* @__PURE__ */
|
|
4170
|
-
/* @__PURE__ */
|
|
4171
|
-
/* @__PURE__ */
|
|
4172
|
-
/* @__PURE__ */
|
|
4813
|
+
return /* @__PURE__ */ jsxs15("div", { className: "flex flex-col items-center justify-center min-h-[60vh] py-8 px-4", children: [
|
|
4814
|
+
/* @__PURE__ */ jsxs15("div", { className: "text-center mb-8", children: [
|
|
4815
|
+
/* @__PURE__ */ jsx25("div", { className: "inline-flex items-center justify-center w-14 h-14 rounded-2xl bg-gradient-to-br from-primary/20 to-primary/5 mb-4 shadow-sm", children: /* @__PURE__ */ jsx25(Sparkles, { className: "w-7 h-7 text-primary" }) }),
|
|
4816
|
+
/* @__PURE__ */ jsx25("h2", { className: "text-xl font-semibold mb-2", children: config.branding.title }),
|
|
4817
|
+
/* @__PURE__ */ jsx25("p", { className: "text-muted-foreground text-sm max-w-md", children: config.branding.subtitle })
|
|
4173
4818
|
] }),
|
|
4174
|
-
/* @__PURE__ */
|
|
4819
|
+
/* @__PURE__ */ jsx25("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3 w-full max-w-2xl", children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsxs15(
|
|
4175
4820
|
"button",
|
|
4176
4821
|
{
|
|
4177
4822
|
type: "button",
|
|
@@ -4180,10 +4825,10 @@ var ChatUI = ({
|
|
|
4180
4825
|
children: [
|
|
4181
4826
|
(() => {
|
|
4182
4827
|
const IconComponent = SuggestionIconComponents[index % SuggestionIconComponents.length];
|
|
4183
|
-
return /* @__PURE__ */
|
|
4828
|
+
return /* @__PURE__ */ jsx25("div", { className: "flex items-center justify-center w-8 h-8 rounded-lg bg-primary/10 text-primary shrink-0 group-hover:bg-primary/15 transition-colors", children: /* @__PURE__ */ jsx25(IconComponent, { className: "h-4 w-4" }) });
|
|
4184
4829
|
})(),
|
|
4185
|
-
/* @__PURE__ */
|
|
4186
|
-
/* @__PURE__ */
|
|
4830
|
+
/* @__PURE__ */ jsx25("div", { className: "flex-1 min-w-0 pr-6", children: /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium leading-snug line-clamp-2", children: suggestion }) }),
|
|
4831
|
+
/* @__PURE__ */ jsx25(ArrowRight, { className: "absolute right-4 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
|
|
4187
4832
|
]
|
|
4188
4833
|
},
|
|
4189
4834
|
index
|
|
@@ -4194,34 +4839,34 @@ var ChatUI = ({
|
|
|
4194
4839
|
const items = messageSuggestions?.[messageId];
|
|
4195
4840
|
if (!items || items.length === 0) return null;
|
|
4196
4841
|
const inlineSuggestionOffsetClass = config.ui.showAvatars ? config.ui.compactMode ? "ml-9" : "ml-11" : "";
|
|
4197
|
-
return /* @__PURE__ */
|
|
4842
|
+
return /* @__PURE__ */ jsx25("div", { className: `flex flex-wrap gap-2 mt-2 ${inlineSuggestionOffsetClass}`, children: items.map((suggestion, index) => /* @__PURE__ */ jsxs15(
|
|
4198
4843
|
"button",
|
|
4199
4844
|
{
|
|
4200
4845
|
type: "button",
|
|
4201
4846
|
onClick: () => handleSendMessage(suggestion),
|
|
4202
4847
|
className: "group inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full border border-border bg-background hover:bg-accent hover:border-accent-foreground/20 transition-all duration-150 text-foreground/80 hover:text-foreground",
|
|
4203
4848
|
children: [
|
|
4204
|
-
/* @__PURE__ */
|
|
4205
|
-
/* @__PURE__ */
|
|
4849
|
+
/* @__PURE__ */ jsx25(Sparkles, { className: "h-3 w-3 text-primary opacity-70 group-hover:opacity-100" }),
|
|
4850
|
+
/* @__PURE__ */ jsx25("span", { className: "max-w-[200px] truncate", children: suggestion })
|
|
4206
4851
|
]
|
|
4207
4852
|
},
|
|
4208
4853
|
`${messageId}-suggestion-${index}`
|
|
4209
4854
|
)) });
|
|
4210
4855
|
};
|
|
4211
|
-
const renderMessageLoadingSkeleton = () => /* @__PURE__ */
|
|
4856
|
+
const renderMessageLoadingSkeleton = () => /* @__PURE__ */ jsx25("div", { className: "space-y-6 py-2", children: [0, 1, 2, 3].map((index) => {
|
|
4212
4857
|
const isUserRow = index % 2 === 1;
|
|
4213
|
-
return /* @__PURE__ */
|
|
4858
|
+
return /* @__PURE__ */ jsxs15(
|
|
4214
4859
|
"div",
|
|
4215
4860
|
{
|
|
4216
4861
|
className: `flex gap-3 ${isUserRow ? "justify-end" : "justify-start"}`,
|
|
4217
4862
|
children: [
|
|
4218
|
-
!isUserRow && /* @__PURE__ */
|
|
4219
|
-
/* @__PURE__ */
|
|
4220
|
-
/* @__PURE__ */
|
|
4221
|
-
/* @__PURE__ */
|
|
4222
|
-
/* @__PURE__ */
|
|
4863
|
+
!isUserRow && /* @__PURE__ */ jsx25(Skeleton, { className: "h-8 w-8 rounded-full shrink-0" }),
|
|
4864
|
+
/* @__PURE__ */ jsxs15("div", { className: `space-y-2 ${isUserRow ? "w-[70%]" : "w-[75%]"}`, children: [
|
|
4865
|
+
/* @__PURE__ */ jsx25(Skeleton, { className: "h-4 w-24" }),
|
|
4866
|
+
/* @__PURE__ */ jsx25(Skeleton, { className: "h-4 w-full" }),
|
|
4867
|
+
/* @__PURE__ */ jsx25(Skeleton, { className: "h-4 w-[85%]" })
|
|
4223
4868
|
] }),
|
|
4224
|
-
isUserRow && /* @__PURE__ */
|
|
4869
|
+
isUserRow && /* @__PURE__ */ jsx25(Skeleton, { className: "h-8 w-8 rounded-full shrink-0" })
|
|
4225
4870
|
]
|
|
4226
4871
|
},
|
|
4227
4872
|
`message-skeleton-${index}`
|
|
@@ -4277,8 +4922,8 @@ var ChatUI = ({
|
|
|
4277
4922
|
const shouldShowAgentSelector = Boolean(
|
|
4278
4923
|
config.agentSelector?.enabled && onSelectAgent && agentOptions.length > 0 && (!config.agentSelector?.hideIfSingle || agentOptions.length > 1)
|
|
4279
4924
|
);
|
|
4280
|
-
return /* @__PURE__ */
|
|
4281
|
-
/* @__PURE__ */
|
|
4925
|
+
return /* @__PURE__ */ jsx25(TooltipProvider, { children: /* @__PURE__ */ jsx25(SidebarProvider, { defaultOpen: true, children: /* @__PURE__ */ jsxs15("div", { className: `flex h-[100svh] md:h-screen bg-background w-full overflow-hidden ${className}`, children: [
|
|
4926
|
+
/* @__PURE__ */ jsx25(
|
|
4282
4927
|
Sidebar2,
|
|
4283
4928
|
{
|
|
4284
4929
|
threads,
|
|
@@ -4295,8 +4940,8 @@ var ChatUI = ({
|
|
|
4295
4940
|
showThemeOptions: !!callbacks.onThemeChange
|
|
4296
4941
|
}
|
|
4297
4942
|
),
|
|
4298
|
-
/* @__PURE__ */
|
|
4299
|
-
/* @__PURE__ */
|
|
4943
|
+
/* @__PURE__ */ jsx25(SidebarInset, { children: /* @__PURE__ */ jsxs15("div", { className: "flex flex-col h-full min-h-0", children: [
|
|
4944
|
+
/* @__PURE__ */ jsx25(
|
|
4300
4945
|
ChatHeader,
|
|
4301
4946
|
{
|
|
4302
4947
|
config,
|
|
@@ -4311,9 +4956,9 @@ var ChatUI = ({
|
|
|
4311
4956
|
onSelectAgent
|
|
4312
4957
|
}
|
|
4313
4958
|
),
|
|
4314
|
-
/* @__PURE__ */
|
|
4315
|
-
/* @__PURE__ */
|
|
4316
|
-
/* @__PURE__ */
|
|
4959
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex flex-1 flex-row min-h-0 overflow-hidden", children: [
|
|
4960
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex-1 flex flex-col min-h-0", children: [
|
|
4961
|
+
/* @__PURE__ */ jsx25(
|
|
4317
4962
|
ScrollArea,
|
|
4318
4963
|
{
|
|
4319
4964
|
ref: scrollAreaRef,
|
|
@@ -4321,7 +4966,7 @@ var ChatUI = ({
|
|
|
4321
4966
|
viewportClassName: "p-4 overscroll-contain",
|
|
4322
4967
|
onScrollCapture: handleScroll,
|
|
4323
4968
|
style: { contain: "strict" },
|
|
4324
|
-
children: /* @__PURE__ */
|
|
4969
|
+
children: /* @__PURE__ */ jsx25("div", { className: "max-w-4xl mx-auto pb-4", children: isMessagesLoading ? renderMessageLoadingSkeleton() : messages.length === 0 ? renderSuggestions() : /* @__PURE__ */ jsx25(
|
|
4325
4970
|
"div",
|
|
4326
4971
|
{
|
|
4327
4972
|
style: {
|
|
@@ -4333,7 +4978,7 @@ var ChatUI = ({
|
|
|
4333
4978
|
const message = messages[virtualRow.index];
|
|
4334
4979
|
const prevMessage = virtualRow.index > 0 ? messages[virtualRow.index - 1] : null;
|
|
4335
4980
|
const isGrouped = prevMessage !== null && prevMessage.role === message.role;
|
|
4336
|
-
return /* @__PURE__ */
|
|
4981
|
+
return /* @__PURE__ */ jsx25(
|
|
4337
4982
|
"div",
|
|
4338
4983
|
{
|
|
4339
4984
|
"data-index": virtualRow.index,
|
|
@@ -4345,8 +4990,8 @@ var ChatUI = ({
|
|
|
4345
4990
|
width: "100%",
|
|
4346
4991
|
transform: `translateY(${virtualRow.start}px)`
|
|
4347
4992
|
},
|
|
4348
|
-
children: /* @__PURE__ */
|
|
4349
|
-
/* @__PURE__ */
|
|
4993
|
+
children: /* @__PURE__ */ jsxs15("div", { className: virtualRow.index === 0 ? "" : isGrouped ? "pt-2" : "pt-4", children: [
|
|
4994
|
+
/* @__PURE__ */ jsx25(
|
|
4350
4995
|
Message,
|
|
4351
4996
|
{
|
|
4352
4997
|
message,
|
|
@@ -4365,7 +5010,7 @@ var ChatUI = ({
|
|
|
4365
5010
|
) })
|
|
4366
5011
|
}
|
|
4367
5012
|
),
|
|
4368
|
-
/* @__PURE__ */
|
|
5013
|
+
/* @__PURE__ */ jsx25("div", { className: "bg-background pb-[env(safe-area-inset-bottom)]", children: /* @__PURE__ */ jsx25(
|
|
4369
5014
|
ChatInput,
|
|
4370
5015
|
{
|
|
4371
5016
|
value: inputValue,
|
|
@@ -4391,17 +5036,17 @@ var ChatUI = ({
|
|
|
4391
5036
|
}
|
|
4392
5037
|
) })
|
|
4393
5038
|
] }),
|
|
4394
|
-
config?.customComponent?.component && !isMobile && /* @__PURE__ */
|
|
5039
|
+
config?.customComponent?.component && !isMobile && /* @__PURE__ */ jsx25(
|
|
4395
5040
|
"div",
|
|
4396
5041
|
{
|
|
4397
5042
|
className: `h-full transition-all duration-300 ease-in-out overflow-hidden ${state.showSidebar ? "w-80" : "w-0"}`,
|
|
4398
|
-
children: state.showSidebar && /* @__PURE__ */
|
|
5043
|
+
children: state.showSidebar && /* @__PURE__ */ jsx25("div", { className: "flex flex-col h-full border-l bg-background animate-in slide-in-from-right-4 duration-300 w-80", children: renderCustomComponent() })
|
|
4399
5044
|
}
|
|
4400
5045
|
)
|
|
4401
5046
|
] })
|
|
4402
5047
|
] }) }),
|
|
4403
|
-
isCustomMounted && config.customComponent?.component && isMobile && /* @__PURE__ */
|
|
4404
|
-
/* @__PURE__ */
|
|
5048
|
+
isCustomMounted && config.customComponent?.component && isMobile && /* @__PURE__ */ jsxs15("div", { className: "fixed inset-0 z-50", children: [
|
|
5049
|
+
/* @__PURE__ */ jsx25(
|
|
4405
5050
|
"div",
|
|
4406
5051
|
{
|
|
4407
5052
|
className: `absolute inset-0 bg-background/80 backdrop-blur-sm transition-opacity duration-200 ease-out ${isCustomVisible ? "opacity-100" : "opacity-0"}`,
|
|
@@ -4409,16 +5054,16 @@ var ChatUI = ({
|
|
|
4409
5054
|
onClick: closeSidebar
|
|
4410
5055
|
}
|
|
4411
5056
|
),
|
|
4412
|
-
/* @__PURE__ */
|
|
5057
|
+
/* @__PURE__ */ jsx25(
|
|
4413
5058
|
"div",
|
|
4414
5059
|
{
|
|
4415
5060
|
className: `absolute top-0 right-0 h-full w-full bg-background transform-gpu transition-transform duration-200 ease-out ${isCustomVisible ? "translate-x-0" : "translate-x-full"}`,
|
|
4416
5061
|
style: { willChange: "transform" },
|
|
4417
|
-
children: /* @__PURE__ */
|
|
5062
|
+
children: /* @__PURE__ */ jsx25("div", { className: "h-full flex flex-col", children: renderCustomComponent() })
|
|
4418
5063
|
}
|
|
4419
5064
|
)
|
|
4420
5065
|
] }),
|
|
4421
|
-
isUserProfileOpen && /* @__PURE__ */
|
|
5066
|
+
isUserProfileOpen && /* @__PURE__ */ jsx25(
|
|
4422
5067
|
UserProfile,
|
|
4423
5068
|
{
|
|
4424
5069
|
isOpen: isUserProfileOpen,
|
|
@@ -4447,16 +5092,16 @@ import {
|
|
|
4447
5092
|
MessageSquare as MessageSquare2,
|
|
4448
5093
|
MoreVertical as MoreVertical2,
|
|
4449
5094
|
Edit2 as Edit22,
|
|
4450
|
-
Trash2 as
|
|
5095
|
+
Trash2 as Trash25,
|
|
4451
5096
|
Archive as Archive2,
|
|
4452
5097
|
Search as Search2,
|
|
4453
5098
|
Filter as Filter2,
|
|
4454
5099
|
Calendar as Calendar2,
|
|
4455
5100
|
Hash,
|
|
4456
|
-
X as
|
|
5101
|
+
X as X5,
|
|
4457
5102
|
Check as Check4
|
|
4458
5103
|
} from "lucide-react";
|
|
4459
|
-
import { Fragment as Fragment6, jsx as
|
|
5104
|
+
import { Fragment as Fragment6, jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4460
5105
|
var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onArchive }) => {
|
|
4461
5106
|
const [isEditing, setIsEditing] = useState9(false);
|
|
4462
5107
|
const [editTitle, setEditTitle] = useState9(thread.title);
|
|
@@ -4485,9 +5130,9 @@ var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onAr
|
|
|
4485
5130
|
handleCancelEdit();
|
|
4486
5131
|
}
|
|
4487
5132
|
};
|
|
4488
|
-
return /* @__PURE__ */
|
|
4489
|
-
/* @__PURE__ */
|
|
4490
|
-
/* @__PURE__ */
|
|
5133
|
+
return /* @__PURE__ */ jsx26(Card, { className: `cursor-pointer transition-all duration-200 hover:shadow-md py-0 ${isActive ? "ring-2 ring-primary bg-primary/5" : "hover:bg-muted/50"}`, children: /* @__PURE__ */ jsx26(CardContent, { className: "p-3 max-w-sm", children: /* @__PURE__ */ jsxs16("div", { className: "flex items-start justify-between gap-2", children: [
|
|
5134
|
+
/* @__PURE__ */ jsx26("div", { className: "flex-1 min-w-0", onClick: onSelect, children: isEditing ? /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2", children: [
|
|
5135
|
+
/* @__PURE__ */ jsx26(
|
|
4491
5136
|
Input,
|
|
4492
5137
|
{
|
|
4493
5138
|
ref: inputRef,
|
|
@@ -4499,44 +5144,44 @@ var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onAr
|
|
|
4499
5144
|
placeholder: config?.labels?.threadNamePlaceholder || "Conversation name"
|
|
4500
5145
|
}
|
|
4501
5146
|
),
|
|
4502
|
-
/* @__PURE__ */
|
|
4503
|
-
/* @__PURE__ */
|
|
4504
|
-
] }) : /* @__PURE__ */
|
|
4505
|
-
/* @__PURE__ */
|
|
4506
|
-
/* @__PURE__ */
|
|
4507
|
-
/* @__PURE__ */
|
|
4508
|
-
/* @__PURE__ */
|
|
5147
|
+
/* @__PURE__ */ jsx26(Button, { size: "sm", variant: "ghost", onClick: handleSaveEdit, children: /* @__PURE__ */ jsx26(Check4, { className: "h-3 w-3" }) }),
|
|
5148
|
+
/* @__PURE__ */ jsx26(Button, { size: "sm", variant: "ghost", onClick: handleCancelEdit, children: /* @__PURE__ */ jsx26(X5, { className: "h-3 w-3" }) })
|
|
5149
|
+
] }) : /* @__PURE__ */ jsxs16(Fragment6, { children: [
|
|
5150
|
+
/* @__PURE__ */ jsx26("h4", { className: "font-medium text-sm truncate mb-1", children: thread.title }),
|
|
5151
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
5152
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-1", children: [
|
|
5153
|
+
/* @__PURE__ */ jsx26(Hash, { className: "h-3 w-3" }),
|
|
4509
5154
|
thread.messageCount,
|
|
4510
5155
|
" msgs"
|
|
4511
5156
|
] }),
|
|
4512
|
-
/* @__PURE__ */
|
|
4513
|
-
/* @__PURE__ */
|
|
4514
|
-
/* @__PURE__ */
|
|
5157
|
+
/* @__PURE__ */ jsx26(Separator, { orientation: "vertical", className: "h-3" }),
|
|
5158
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-1", children: [
|
|
5159
|
+
/* @__PURE__ */ jsx26(Calendar2, { className: "h-3 w-3" }),
|
|
4515
5160
|
formatDate(thread.updatedAt, config?.labels)
|
|
4516
5161
|
] }),
|
|
4517
|
-
thread.isArchived && /* @__PURE__ */
|
|
4518
|
-
/* @__PURE__ */
|
|
4519
|
-
/* @__PURE__ */
|
|
4520
|
-
/* @__PURE__ */
|
|
5162
|
+
thread.isArchived && /* @__PURE__ */ jsxs16(Fragment6, { children: [
|
|
5163
|
+
/* @__PURE__ */ jsx26(Separator, { orientation: "vertical", className: "h-3" }),
|
|
5164
|
+
/* @__PURE__ */ jsxs16(Badge, { variant: "secondary", className: "text-xs", children: [
|
|
5165
|
+
/* @__PURE__ */ jsx26(Archive2, { className: "h-2 w-2 mr-1" }),
|
|
4521
5166
|
config?.labels?.archiveThread || "Archived"
|
|
4522
5167
|
] })
|
|
4523
5168
|
] })
|
|
4524
5169
|
] })
|
|
4525
5170
|
] }) }),
|
|
4526
|
-
!isEditing && /* @__PURE__ */
|
|
4527
|
-
/* @__PURE__ */
|
|
4528
|
-
/* @__PURE__ */
|
|
4529
|
-
/* @__PURE__ */
|
|
4530
|
-
/* @__PURE__ */
|
|
5171
|
+
!isEditing && /* @__PURE__ */ jsxs16(DropdownMenu, { children: [
|
|
5172
|
+
/* @__PURE__ */ jsx26(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(Button, { variant: "ghost", size: "icon", className: "h-6 w-6 m-auto", children: /* @__PURE__ */ jsx26(MoreVertical2, { className: "h-3 w-3" }) }) }),
|
|
5173
|
+
/* @__PURE__ */ jsxs16(DropdownMenuContent, { align: "end", children: [
|
|
5174
|
+
/* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: () => setIsEditing(true), children: [
|
|
5175
|
+
/* @__PURE__ */ jsx26(Edit22, { className: "h-4 w-4 mr-2" }),
|
|
4531
5176
|
config?.labels?.renameThread || "Rename"
|
|
4532
5177
|
] }),
|
|
4533
|
-
/* @__PURE__ */
|
|
4534
|
-
/* @__PURE__ */
|
|
5178
|
+
/* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: onArchive, children: [
|
|
5179
|
+
/* @__PURE__ */ jsx26(Archive2, { className: "h-4 w-4 mr-2" }),
|
|
4535
5180
|
thread.isArchived ? config?.labels?.unarchiveThread || "Unarchive" : config?.labels?.archiveThread || "Archive"
|
|
4536
5181
|
] }),
|
|
4537
|
-
/* @__PURE__ */
|
|
4538
|
-
/* @__PURE__ */
|
|
4539
|
-
/* @__PURE__ */
|
|
5182
|
+
/* @__PURE__ */ jsx26(DropdownMenuSeparator, {}),
|
|
5183
|
+
/* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: onDelete, className: "text-destructive", children: [
|
|
5184
|
+
/* @__PURE__ */ jsx26(Trash25, { className: "h-4 w-4 mr-2" }),
|
|
4540
5185
|
config?.labels?.deleteThread || "Delete"
|
|
4541
5186
|
] })
|
|
4542
5187
|
] })
|
|
@@ -4551,17 +5196,17 @@ var CreateThreadDialog2 = ({ onCreateThread, config }) => {
|
|
|
4551
5196
|
setTitle("");
|
|
4552
5197
|
setIsOpen(false);
|
|
4553
5198
|
};
|
|
4554
|
-
return /* @__PURE__ */
|
|
4555
|
-
/* @__PURE__ */
|
|
4556
|
-
/* @__PURE__ */
|
|
5199
|
+
return /* @__PURE__ */ jsxs16(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: [
|
|
5200
|
+
/* @__PURE__ */ jsx26(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs16(Button, { variant: "outline", className: "w-full", children: [
|
|
5201
|
+
/* @__PURE__ */ jsx26(Plus4, { className: "h-4 w-4 mr-2" }),
|
|
4557
5202
|
config?.labels?.createNewThread || "New Conversation"
|
|
4558
5203
|
] }) }),
|
|
4559
|
-
/* @__PURE__ */
|
|
4560
|
-
/* @__PURE__ */
|
|
4561
|
-
/* @__PURE__ */
|
|
4562
|
-
/* @__PURE__ */
|
|
5204
|
+
/* @__PURE__ */ jsxs16(DialogContent, { children: [
|
|
5205
|
+
/* @__PURE__ */ jsxs16(DialogHeader, { children: [
|
|
5206
|
+
/* @__PURE__ */ jsx26(DialogTitle, { children: config?.labels?.createNewThread || "Create New Conversation" }),
|
|
5207
|
+
/* @__PURE__ */ jsx26(DialogDescription, { children: "Give your new conversation a name or leave blank to auto-generate one." })
|
|
4563
5208
|
] }),
|
|
4564
|
-
/* @__PURE__ */
|
|
5209
|
+
/* @__PURE__ */ jsx26(
|
|
4565
5210
|
Input,
|
|
4566
5211
|
{
|
|
4567
5212
|
value: title,
|
|
@@ -4571,9 +5216,9 @@ var CreateThreadDialog2 = ({ onCreateThread, config }) => {
|
|
|
4571
5216
|
autoFocus: true
|
|
4572
5217
|
}
|
|
4573
5218
|
),
|
|
4574
|
-
/* @__PURE__ */
|
|
4575
|
-
/* @__PURE__ */
|
|
4576
|
-
/* @__PURE__ */
|
|
5219
|
+
/* @__PURE__ */ jsxs16(DialogFooter, { children: [
|
|
5220
|
+
/* @__PURE__ */ jsx26(Button, { variant: "outline", onClick: () => setIsOpen(false), children: config?.labels?.cancel || "Cancel" }),
|
|
5221
|
+
/* @__PURE__ */ jsx26(Button, { onClick: handleCreate, children: config?.labels?.create || "Create" })
|
|
4577
5222
|
] })
|
|
4578
5223
|
] })
|
|
4579
5224
|
] });
|
|
@@ -4627,20 +5272,20 @@ var ThreadManager = ({
|
|
|
4627
5272
|
setDeleteThreadId(null);
|
|
4628
5273
|
};
|
|
4629
5274
|
if (!isOpen) return null;
|
|
4630
|
-
return /* @__PURE__ */
|
|
4631
|
-
/* @__PURE__ */
|
|
4632
|
-
/* @__PURE__ */
|
|
4633
|
-
/* @__PURE__ */
|
|
4634
|
-
/* @__PURE__ */
|
|
4635
|
-
/* @__PURE__ */
|
|
5275
|
+
return /* @__PURE__ */ jsx26(TooltipProvider, { children: /* @__PURE__ */ jsxs16("div", { className: `fixed inset-0 z-50 bg-background/80 backdrop-blur-sm ${className}`, children: [
|
|
5276
|
+
/* @__PURE__ */ jsx26("div", { className: "fixed left-0 top-0 h-full w-full max-w-md border-r bg-background shadow-lg", children: /* @__PURE__ */ jsxs16(Card, { className: "h-full border-0 rounded-none", children: [
|
|
5277
|
+
/* @__PURE__ */ jsxs16(CardHeader, { className: "border-b", children: [
|
|
5278
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between", children: [
|
|
5279
|
+
/* @__PURE__ */ jsxs16(CardTitle, { className: "flex items-center gap-2", children: [
|
|
5280
|
+
/* @__PURE__ */ jsx26(MessageSquare2, { className: "h-5 w-5" }),
|
|
4636
5281
|
config?.labels?.newChat || "Conversations"
|
|
4637
5282
|
] }),
|
|
4638
|
-
/* @__PURE__ */
|
|
5283
|
+
/* @__PURE__ */ jsx26(Button, { variant: "ghost", size: "icon", onClick: onClose, children: /* @__PURE__ */ jsx26(X5, { className: "h-4 w-4" }) })
|
|
4639
5284
|
] }),
|
|
4640
|
-
/* @__PURE__ */
|
|
4641
|
-
/* @__PURE__ */
|
|
4642
|
-
/* @__PURE__ */
|
|
4643
|
-
/* @__PURE__ */
|
|
5285
|
+
/* @__PURE__ */ jsxs16("div", { className: "space-y-3", children: [
|
|
5286
|
+
/* @__PURE__ */ jsxs16("div", { className: "relative", children: [
|
|
5287
|
+
/* @__PURE__ */ jsx26(Search2, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
5288
|
+
/* @__PURE__ */ jsx26(
|
|
4644
5289
|
Input,
|
|
4645
5290
|
{
|
|
4646
5291
|
placeholder: config?.labels?.search || "Search conversations...",
|
|
@@ -4650,8 +5295,8 @@ var ThreadManager = ({
|
|
|
4650
5295
|
}
|
|
4651
5296
|
)
|
|
4652
5297
|
] }),
|
|
4653
|
-
/* @__PURE__ */
|
|
4654
|
-
/* @__PURE__ */
|
|
5298
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between", children: [
|
|
5299
|
+
/* @__PURE__ */ jsxs16(
|
|
4655
5300
|
Button,
|
|
4656
5301
|
{
|
|
4657
5302
|
variant: "outline",
|
|
@@ -4659,12 +5304,12 @@ var ThreadManager = ({
|
|
|
4659
5304
|
onClick: () => setShowArchived(!showArchived),
|
|
4660
5305
|
className: "text-xs",
|
|
4661
5306
|
children: [
|
|
4662
|
-
/* @__PURE__ */
|
|
5307
|
+
/* @__PURE__ */ jsx26(Filter2, { className: "h-3 w-3 mr-1" }),
|
|
4663
5308
|
showArchived ? config?.labels?.hideArchived || "Hide Archived" : config?.labels?.showArchived || "Show Archived"
|
|
4664
5309
|
]
|
|
4665
5310
|
}
|
|
4666
5311
|
),
|
|
4667
|
-
/* @__PURE__ */
|
|
5312
|
+
/* @__PURE__ */ jsxs16(Badge, { variant: "secondary", className: "text-xs", children: [
|
|
4668
5313
|
filteredThreads.length,
|
|
4669
5314
|
" / ",
|
|
4670
5315
|
threads.length
|
|
@@ -4672,14 +5317,14 @@ var ThreadManager = ({
|
|
|
4672
5317
|
] })
|
|
4673
5318
|
] })
|
|
4674
5319
|
] }),
|
|
4675
|
-
/* @__PURE__ */
|
|
4676
|
-
/* @__PURE__ */
|
|
4677
|
-
/* @__PURE__ */
|
|
4678
|
-
/* @__PURE__ */
|
|
4679
|
-
/* @__PURE__ */
|
|
4680
|
-
] }) : Object.entries(groupedThreads).map(([group, groupThreads]) => /* @__PURE__ */
|
|
4681
|
-
/* @__PURE__ */
|
|
4682
|
-
/* @__PURE__ */
|
|
5320
|
+
/* @__PURE__ */ jsxs16(CardContent, { className: "p-0 flex-1", children: [
|
|
5321
|
+
/* @__PURE__ */ jsx26("div", { className: "p-4", children: onCreateThread && /* @__PURE__ */ jsx26(CreateThreadDialog2, { onCreateThread, config }) }),
|
|
5322
|
+
/* @__PURE__ */ jsx26(ScrollArea, { className: "h-[calc(100vh-280px)]", children: /* @__PURE__ */ jsx26("div", { className: "px-4 pb-4 space-y-4", children: Object.keys(groupedThreads).length === 0 ? /* @__PURE__ */ jsxs16("div", { className: "text-center py-8 text-muted-foreground", children: [
|
|
5323
|
+
/* @__PURE__ */ jsx26(MessageSquare2, { className: "h-12 w-12 mx-auto mb-3 opacity-50" }),
|
|
5324
|
+
/* @__PURE__ */ jsx26("p", { className: "text-sm", children: searchQuery ? config?.labels?.noThreadsFound || "No conversations found" : config?.labels?.noThreadsYet || "No conversations yet" })
|
|
5325
|
+
] }) : Object.entries(groupedThreads).map(([group, groupThreads]) => /* @__PURE__ */ jsxs16("div", { children: [
|
|
5326
|
+
/* @__PURE__ */ jsx26("h3", { className: "text-sm font-medium text-muted-foreground mb-2 px-2", children: group }),
|
|
5327
|
+
/* @__PURE__ */ jsx26("div", { className: "space-y-2", children: groupThreads.map((thread) => /* @__PURE__ */ jsx26(
|
|
4683
5328
|
ThreadItem,
|
|
4684
5329
|
{
|
|
4685
5330
|
thread,
|
|
@@ -4695,14 +5340,14 @@ var ThreadManager = ({
|
|
|
4695
5340
|
] }, group)) }) })
|
|
4696
5341
|
] })
|
|
4697
5342
|
] }) }),
|
|
4698
|
-
deleteThreadId && /* @__PURE__ */
|
|
4699
|
-
/* @__PURE__ */
|
|
4700
|
-
/* @__PURE__ */
|
|
4701
|
-
/* @__PURE__ */
|
|
5343
|
+
deleteThreadId && /* @__PURE__ */ jsx26(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ jsxs16(AlertDialogContent, { children: [
|
|
5344
|
+
/* @__PURE__ */ jsxs16(AlertDialogHeader, { children: [
|
|
5345
|
+
/* @__PURE__ */ jsx26(AlertDialogTitle, { children: config?.labels?.deleteConfirmTitle || "Delete Conversation" }),
|
|
5346
|
+
/* @__PURE__ */ jsx26(AlertDialogDescription, { children: config?.labels?.deleteConfirmDescription || "Are you sure you want to delete this conversation? This action cannot be undone." })
|
|
4702
5347
|
] }),
|
|
4703
|
-
/* @__PURE__ */
|
|
4704
|
-
/* @__PURE__ */
|
|
4705
|
-
/* @__PURE__ */
|
|
5348
|
+
/* @__PURE__ */ jsxs16(AlertDialogFooter, { children: [
|
|
5349
|
+
/* @__PURE__ */ jsx26(AlertDialogCancel, { children: config?.labels?.cancel || "Cancel" }),
|
|
5350
|
+
/* @__PURE__ */ jsx26(
|
|
4706
5351
|
AlertDialogAction,
|
|
4707
5352
|
{
|
|
4708
5353
|
onClick: () => deleteThreadId && handleDeleteThread(deleteThreadId),
|