@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.cjs
CHANGED
|
@@ -86,6 +86,26 @@ var defaultChatConfig = {
|
|
|
86
86
|
attachFileTooltip: "Attach file",
|
|
87
87
|
recordAudio: "Record Audio",
|
|
88
88
|
recordAudioTooltip: "Record audio",
|
|
89
|
+
voiceEnter: "Voice input",
|
|
90
|
+
voiceExit: "Use keyboard",
|
|
91
|
+
voiceTitle: "Voice",
|
|
92
|
+
voiceIdle: "Tap the mic to record",
|
|
93
|
+
voicePreparing: "Preparing microphone...",
|
|
94
|
+
voiceWaiting: "Waiting for speech...",
|
|
95
|
+
voiceListening: "Listening...",
|
|
96
|
+
voiceFinishing: "Finishing capture...",
|
|
97
|
+
voiceReview: "Ready to send",
|
|
98
|
+
voiceSending: "Sending...",
|
|
99
|
+
voiceStart: "Start recording",
|
|
100
|
+
voiceStop: "Stop recording",
|
|
101
|
+
voiceSendNow: "Send now",
|
|
102
|
+
voiceCancel: "Cancel",
|
|
103
|
+
voiceDiscard: "Delete recording",
|
|
104
|
+
voiceRecordAgain: "Record again",
|
|
105
|
+
voiceAutoSendIn: "Auto-sends in {{seconds}}s",
|
|
106
|
+
voiceTranscriptPending: "Transcript unavailable",
|
|
107
|
+
voicePermissionDenied: "Microphone access was denied.",
|
|
108
|
+
voiceCaptureError: "Unable to capture audio.",
|
|
89
109
|
// Header labels
|
|
90
110
|
exportData: "Export data",
|
|
91
111
|
importData: "Import data",
|
|
@@ -148,6 +168,16 @@ var defaultChatConfig = {
|
|
|
148
168
|
longMessageChunkChars: 12e3,
|
|
149
169
|
renderUserMarkdown: true
|
|
150
170
|
},
|
|
171
|
+
voiceCompose: {
|
|
172
|
+
enabled: false,
|
|
173
|
+
defaultMode: "text",
|
|
174
|
+
autoSendDelayMs: 5e3,
|
|
175
|
+
persistComposer: true,
|
|
176
|
+
showTranscriptPreview: true,
|
|
177
|
+
transcriptMode: "final-only",
|
|
178
|
+
maxRecordingMs: 6e4,
|
|
179
|
+
createProvider: void 0
|
|
180
|
+
},
|
|
151
181
|
customComponent: {},
|
|
152
182
|
headerActions: null
|
|
153
183
|
};
|
|
@@ -170,6 +200,10 @@ function mergeConfig(_baseConfig, userConfig) {
|
|
|
170
200
|
...defaultChatConfig.ui,
|
|
171
201
|
...userConfig.ui
|
|
172
202
|
},
|
|
203
|
+
voiceCompose: {
|
|
204
|
+
...defaultChatConfig.voiceCompose,
|
|
205
|
+
...userConfig.voiceCompose
|
|
206
|
+
},
|
|
173
207
|
agentSelector: {
|
|
174
208
|
...defaultChatConfig.agentSelector,
|
|
175
209
|
...userConfig.agentSelector
|
|
@@ -777,7 +811,7 @@ var MediaRenderer = (0, import_react.memo)(function MediaRenderer2({ attachment
|
|
|
777
811
|
URL.revokeObjectURL(objectUrl);
|
|
778
812
|
};
|
|
779
813
|
}, [attachment.kind, attachment.dataUrl]);
|
|
780
|
-
const
|
|
814
|
+
const formatDuration2 = (ms) => {
|
|
781
815
|
if (!ms) return "";
|
|
782
816
|
const seconds = Math.floor(ms / 1e3);
|
|
783
817
|
const minutes = Math.floor(seconds / 60);
|
|
@@ -2810,6 +2844,215 @@ function useChatUserContext() {
|
|
|
2810
2844
|
return v;
|
|
2811
2845
|
}
|
|
2812
2846
|
|
|
2847
|
+
// src/lib/voiceCompose.ts
|
|
2848
|
+
var AUDIO_MIME_TYPES = [
|
|
2849
|
+
"audio/webm;codecs=opus",
|
|
2850
|
+
"audio/webm",
|
|
2851
|
+
"audio/mp4",
|
|
2852
|
+
"audio/ogg;codecs=opus"
|
|
2853
|
+
];
|
|
2854
|
+
var pickRecorderMimeType = () => {
|
|
2855
|
+
if (typeof MediaRecorder === "undefined") return void 0;
|
|
2856
|
+
for (const mimeType of AUDIO_MIME_TYPES) {
|
|
2857
|
+
if (typeof MediaRecorder.isTypeSupported === "function" && MediaRecorder.isTypeSupported(mimeType)) {
|
|
2858
|
+
return mimeType;
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
return void 0;
|
|
2862
|
+
};
|
|
2863
|
+
var blobToDataUrl = (blob) => new Promise((resolve, reject) => {
|
|
2864
|
+
const reader = new FileReader();
|
|
2865
|
+
reader.onload = () => resolve(reader.result);
|
|
2866
|
+
reader.onerror = () => reject(reader.error ?? new Error("Failed to read recorded audio"));
|
|
2867
|
+
reader.readAsDataURL(blob);
|
|
2868
|
+
});
|
|
2869
|
+
var stopStream = (stream) => {
|
|
2870
|
+
if (!stream) return;
|
|
2871
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
2872
|
+
};
|
|
2873
|
+
var closeAudioContext = async (audioContext) => {
|
|
2874
|
+
if (!audioContext) return;
|
|
2875
|
+
try {
|
|
2876
|
+
await audioContext.close();
|
|
2877
|
+
} catch {
|
|
2878
|
+
}
|
|
2879
|
+
};
|
|
2880
|
+
var emitDuration = (handlers, startedAt) => {
|
|
2881
|
+
handlers.onDurationChange?.(Math.max(0, Date.now() - startedAt));
|
|
2882
|
+
};
|
|
2883
|
+
var createManualVoiceProvider = async (handlers, options = {}) => {
|
|
2884
|
+
let mediaRecorder = null;
|
|
2885
|
+
let mediaStream = null;
|
|
2886
|
+
let audioContext = null;
|
|
2887
|
+
let analyser = null;
|
|
2888
|
+
let levelData = null;
|
|
2889
|
+
let levelFrame = 0;
|
|
2890
|
+
let durationTimer = null;
|
|
2891
|
+
let maxDurationTimer = null;
|
|
2892
|
+
let startedAt = 0;
|
|
2893
|
+
let shouldEmitSegment = true;
|
|
2894
|
+
let isStarting = false;
|
|
2895
|
+
const clearTimers = () => {
|
|
2896
|
+
if (durationTimer) {
|
|
2897
|
+
clearInterval(durationTimer);
|
|
2898
|
+
durationTimer = null;
|
|
2899
|
+
}
|
|
2900
|
+
if (maxDurationTimer) {
|
|
2901
|
+
clearTimeout(maxDurationTimer);
|
|
2902
|
+
maxDurationTimer = null;
|
|
2903
|
+
}
|
|
2904
|
+
};
|
|
2905
|
+
const stopLevelLoop = () => {
|
|
2906
|
+
if (levelFrame) {
|
|
2907
|
+
cancelAnimationFrame(levelFrame);
|
|
2908
|
+
levelFrame = 0;
|
|
2909
|
+
}
|
|
2910
|
+
handlers.onAudioLevelChange?.(0);
|
|
2911
|
+
};
|
|
2912
|
+
const startLevelLoop = () => {
|
|
2913
|
+
if (!analyser || !levelData) return;
|
|
2914
|
+
const tick = () => {
|
|
2915
|
+
if (!analyser || !levelData) return;
|
|
2916
|
+
analyser.getByteTimeDomainData(levelData);
|
|
2917
|
+
let sum = 0;
|
|
2918
|
+
for (let index = 0; index < levelData.length; index += 1) {
|
|
2919
|
+
const centered = (levelData[index] - 128) / 128;
|
|
2920
|
+
sum += centered * centered;
|
|
2921
|
+
}
|
|
2922
|
+
const rms = Math.sqrt(sum / levelData.length);
|
|
2923
|
+
handlers.onAudioLevelChange?.(Math.min(1, rms * 4));
|
|
2924
|
+
levelFrame = requestAnimationFrame(tick);
|
|
2925
|
+
};
|
|
2926
|
+
tick();
|
|
2927
|
+
};
|
|
2928
|
+
const cleanupActiveResources = async () => {
|
|
2929
|
+
clearTimers();
|
|
2930
|
+
stopLevelLoop();
|
|
2931
|
+
stopStream(mediaStream);
|
|
2932
|
+
mediaStream = null;
|
|
2933
|
+
analyser = null;
|
|
2934
|
+
levelData = null;
|
|
2935
|
+
await closeAudioContext(audioContext);
|
|
2936
|
+
audioContext = null;
|
|
2937
|
+
};
|
|
2938
|
+
const finalizeStop = async () => {
|
|
2939
|
+
mediaRecorder = null;
|
|
2940
|
+
isStarting = false;
|
|
2941
|
+
await cleanupActiveResources();
|
|
2942
|
+
};
|
|
2943
|
+
const start = async () => {
|
|
2944
|
+
if (isStarting || mediaRecorder?.state === "recording") {
|
|
2945
|
+
return;
|
|
2946
|
+
}
|
|
2947
|
+
if (!navigator.mediaDevices?.getUserMedia) {
|
|
2948
|
+
throw new Error("Audio capture is not supported in this browser");
|
|
2949
|
+
}
|
|
2950
|
+
if (typeof MediaRecorder === "undefined") {
|
|
2951
|
+
throw new Error("MediaRecorder is not supported in this browser");
|
|
2952
|
+
}
|
|
2953
|
+
isStarting = true;
|
|
2954
|
+
shouldEmitSegment = true;
|
|
2955
|
+
handlers.onTranscriptChange?.({});
|
|
2956
|
+
handlers.onDurationChange?.(0);
|
|
2957
|
+
handlers.onAudioLevelChange?.(0);
|
|
2958
|
+
handlers.onStateChange?.("preparing");
|
|
2959
|
+
try {
|
|
2960
|
+
mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
2961
|
+
const mimeType = pickRecorderMimeType();
|
|
2962
|
+
mediaRecorder = mimeType ? new MediaRecorder(mediaStream, { mimeType }) : new MediaRecorder(mediaStream);
|
|
2963
|
+
const chunks = [];
|
|
2964
|
+
mediaRecorder.ondataavailable = (event) => {
|
|
2965
|
+
if (event.data.size > 0) {
|
|
2966
|
+
chunks.push(event.data);
|
|
2967
|
+
}
|
|
2968
|
+
};
|
|
2969
|
+
mediaRecorder.onerror = (event) => {
|
|
2970
|
+
const error = event.error ?? new Error("Audio recorder failed");
|
|
2971
|
+
handlers.onError?.(error);
|
|
2972
|
+
};
|
|
2973
|
+
mediaRecorder.onstop = async () => {
|
|
2974
|
+
const durationMs = startedAt > 0 ? Math.max(0, Date.now() - startedAt) : 0;
|
|
2975
|
+
try {
|
|
2976
|
+
if (shouldEmitSegment && chunks.length > 0) {
|
|
2977
|
+
const blob = new Blob(chunks, {
|
|
2978
|
+
type: mediaRecorder?.mimeType || mimeType || "audio/webm"
|
|
2979
|
+
});
|
|
2980
|
+
const dataUrl = await blobToDataUrl(blob);
|
|
2981
|
+
handlers.onSegmentReady?.({
|
|
2982
|
+
attachment: {
|
|
2983
|
+
kind: "audio",
|
|
2984
|
+
dataUrl,
|
|
2985
|
+
mimeType: blob.type || "audio/webm",
|
|
2986
|
+
durationMs,
|
|
2987
|
+
fileName: `voice-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.webm`,
|
|
2988
|
+
size: blob.size
|
|
2989
|
+
},
|
|
2990
|
+
metadata: { source: "manual" }
|
|
2991
|
+
});
|
|
2992
|
+
} else {
|
|
2993
|
+
handlers.onStateChange?.("idle");
|
|
2994
|
+
}
|
|
2995
|
+
} catch (error) {
|
|
2996
|
+
handlers.onError?.(error);
|
|
2997
|
+
} finally {
|
|
2998
|
+
await finalizeStop();
|
|
2999
|
+
}
|
|
3000
|
+
};
|
|
3001
|
+
const AudioContextCtor = globalThis.AudioContext || globalThis.webkitAudioContext;
|
|
3002
|
+
if (AudioContextCtor) {
|
|
3003
|
+
audioContext = new AudioContextCtor();
|
|
3004
|
+
await audioContext.resume().catch(() => void 0);
|
|
3005
|
+
const sourceNode = audioContext.createMediaStreamSource(mediaStream);
|
|
3006
|
+
analyser = audioContext.createAnalyser();
|
|
3007
|
+
analyser.fftSize = 1024;
|
|
3008
|
+
levelData = new Uint8Array(analyser.fftSize);
|
|
3009
|
+
sourceNode.connect(analyser);
|
|
3010
|
+
startLevelLoop();
|
|
3011
|
+
}
|
|
3012
|
+
startedAt = Date.now();
|
|
3013
|
+
emitDuration(handlers, startedAt);
|
|
3014
|
+
durationTimer = setInterval(() => emitDuration(handlers, startedAt), 200);
|
|
3015
|
+
if (options.maxRecordingMs && options.maxRecordingMs > 0) {
|
|
3016
|
+
maxDurationTimer = setTimeout(() => {
|
|
3017
|
+
void stop();
|
|
3018
|
+
}, options.maxRecordingMs);
|
|
3019
|
+
}
|
|
3020
|
+
mediaRecorder.start();
|
|
3021
|
+
handlers.onStateChange?.("listening");
|
|
3022
|
+
} catch (error) {
|
|
3023
|
+
isStarting = false;
|
|
3024
|
+
await cleanupActiveResources();
|
|
3025
|
+
throw error;
|
|
3026
|
+
}
|
|
3027
|
+
};
|
|
3028
|
+
const stop = async () => {
|
|
3029
|
+
if (!mediaRecorder || mediaRecorder.state === "inactive") {
|
|
3030
|
+
return;
|
|
3031
|
+
}
|
|
3032
|
+
handlers.onStateChange?.("finishing");
|
|
3033
|
+
mediaRecorder.stop();
|
|
3034
|
+
};
|
|
3035
|
+
const cancel = async () => {
|
|
3036
|
+
shouldEmitSegment = false;
|
|
3037
|
+
if (mediaRecorder && mediaRecorder.state !== "inactive") {
|
|
3038
|
+
mediaRecorder.stop();
|
|
3039
|
+
return;
|
|
3040
|
+
}
|
|
3041
|
+
await finalizeStop();
|
|
3042
|
+
handlers.onStateChange?.("idle");
|
|
3043
|
+
};
|
|
3044
|
+
const destroy = async () => {
|
|
3045
|
+
await cancel();
|
|
3046
|
+
};
|
|
3047
|
+
return {
|
|
3048
|
+
start,
|
|
3049
|
+
stop,
|
|
3050
|
+
cancel,
|
|
3051
|
+
destroy
|
|
3052
|
+
};
|
|
3053
|
+
};
|
|
3054
|
+
var resolveVoiceProviderFactory = (createProvider) => createProvider ?? createManualVoiceProvider;
|
|
3055
|
+
|
|
2813
3056
|
// src/components/ui/progress.tsx
|
|
2814
3057
|
var ProgressPrimitive = __toESM(require("@radix-ui/react-progress"), 1);
|
|
2815
3058
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
@@ -2839,9 +3082,185 @@ function Progress({
|
|
|
2839
3082
|
);
|
|
2840
3083
|
}
|
|
2841
3084
|
|
|
2842
|
-
// src/components/chat/
|
|
3085
|
+
// src/components/chat/VoiceComposer.tsx
|
|
2843
3086
|
var import_lucide_react9 = require("lucide-react");
|
|
2844
3087
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
3088
|
+
var formatDuration = (durationMs) => {
|
|
3089
|
+
const totalSeconds = Math.max(0, Math.floor(durationMs / 1e3));
|
|
3090
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
3091
|
+
const seconds = totalSeconds % 60;
|
|
3092
|
+
return `${minutes}:${seconds.toString().padStart(2, "0")}`;
|
|
3093
|
+
};
|
|
3094
|
+
var interpolateSeconds = (label, seconds) => {
|
|
3095
|
+
if (!label) {
|
|
3096
|
+
return `Auto-sends in ${seconds}s`;
|
|
3097
|
+
}
|
|
3098
|
+
if (label.includes("{{seconds}}")) {
|
|
3099
|
+
return label.replace(/\{\{\s*seconds\s*\}\}/g, String(seconds));
|
|
3100
|
+
}
|
|
3101
|
+
return `${label} ${seconds}s`;
|
|
3102
|
+
};
|
|
3103
|
+
var resolveStateLabel = (state, labels, errorMessage) => {
|
|
3104
|
+
switch (state) {
|
|
3105
|
+
case "preparing":
|
|
3106
|
+
return labels?.voicePreparing || "Preparing microphone...";
|
|
3107
|
+
case "waiting_for_speech":
|
|
3108
|
+
return labels?.voiceWaiting || "Waiting for speech...";
|
|
3109
|
+
case "listening":
|
|
3110
|
+
return labels?.voiceListening || "Listening...";
|
|
3111
|
+
case "finishing":
|
|
3112
|
+
return labels?.voiceFinishing || "Finishing capture...";
|
|
3113
|
+
case "review":
|
|
3114
|
+
return labels?.voiceReview || "Ready to send";
|
|
3115
|
+
case "sending":
|
|
3116
|
+
return labels?.voiceSending || "Sending...";
|
|
3117
|
+
case "error":
|
|
3118
|
+
return errorMessage || labels?.voiceCaptureError || "Unable to capture audio.";
|
|
3119
|
+
case "idle":
|
|
3120
|
+
default:
|
|
3121
|
+
return labels?.voiceIdle || "Tap the mic to record";
|
|
3122
|
+
}
|
|
3123
|
+
};
|
|
3124
|
+
var resolveTranscriptText = (transcript, transcriptMode) => {
|
|
3125
|
+
if (transcriptMode === "none" || !transcript) {
|
|
3126
|
+
return null;
|
|
3127
|
+
}
|
|
3128
|
+
if (transcriptMode === "final-only") {
|
|
3129
|
+
return transcript.final?.trim() || null;
|
|
3130
|
+
}
|
|
3131
|
+
return transcript.final?.trim() || transcript.partial?.trim() || null;
|
|
3132
|
+
};
|
|
3133
|
+
var VoiceComposer = ({
|
|
3134
|
+
state,
|
|
3135
|
+
transcript,
|
|
3136
|
+
transcriptMode,
|
|
3137
|
+
showTranscriptPreview,
|
|
3138
|
+
attachment,
|
|
3139
|
+
durationMs,
|
|
3140
|
+
audioLevel,
|
|
3141
|
+
countdownMs,
|
|
3142
|
+
autoSendDelayMs,
|
|
3143
|
+
isAutoSendActive,
|
|
3144
|
+
errorMessage,
|
|
3145
|
+
disabled = false,
|
|
3146
|
+
labels,
|
|
3147
|
+
onStart,
|
|
3148
|
+
onStop,
|
|
3149
|
+
onCancelAutoSend,
|
|
3150
|
+
onDiscard,
|
|
3151
|
+
onRecordAgain,
|
|
3152
|
+
onSendNow,
|
|
3153
|
+
onExit
|
|
3154
|
+
}) => {
|
|
3155
|
+
const transcriptText = resolveTranscriptText(transcript, transcriptMode);
|
|
3156
|
+
const countdownSeconds = Math.max(1, Math.ceil(countdownMs / 1e3));
|
|
3157
|
+
const countdownValue = autoSendDelayMs > 0 ? Math.min(100, Math.max(0, (autoSendDelayMs - countdownMs) / autoSendDelayMs * 100)) : 100;
|
|
3158
|
+
const isBusy = state === "preparing" || state === "finishing" || state === "sending";
|
|
3159
|
+
const isCapturing = state === "waiting_for_speech" || state === "listening";
|
|
3160
|
+
const isReviewing = state === "review";
|
|
3161
|
+
const levelValue = isCapturing || state === "preparing" || state === "finishing" ? Math.max(8, Math.round(audioLevel * 100)) : 0;
|
|
3162
|
+
const headerLabel = state === "error" ? labels?.voiceCaptureError || "Unable to capture audio." : resolveStateLabel(state, labels, errorMessage);
|
|
3163
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "w-full max-w-3xl rounded-xl border bg-background p-3 shadow-sm sm:p-4 md:min-w-3xl", children: [
|
|
3164
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center justify-between gap-2 sm:gap-3", children: [
|
|
3165
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
3166
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "outline", children: labels?.voiceTitle || "Voice" }),
|
|
3167
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "truncate text-xs sm:text-sm text-muted-foreground", children: headerLabel })
|
|
3168
|
+
] }),
|
|
3169
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
3170
|
+
Button,
|
|
3171
|
+
{
|
|
3172
|
+
type: "button",
|
|
3173
|
+
variant: "ghost",
|
|
3174
|
+
size: "sm",
|
|
3175
|
+
className: "shrink-0 px-2 sm:px-3",
|
|
3176
|
+
onClick: onExit,
|
|
3177
|
+
disabled: disabled || isBusy,
|
|
3178
|
+
children: [
|
|
3179
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Keyboard, { className: "h-4 w-4" }),
|
|
3180
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "hidden sm:inline", children: labels?.voiceExit || "Use keyboard" })
|
|
3181
|
+
]
|
|
3182
|
+
}
|
|
3183
|
+
)
|
|
3184
|
+
] }),
|
|
3185
|
+
!isReviewing ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("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__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mx-auto flex w-full max-w-sm flex-col items-center gap-3", children: [
|
|
3186
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3187
|
+
Button,
|
|
3188
|
+
{
|
|
3189
|
+
type: "button",
|
|
3190
|
+
size: "icon",
|
|
3191
|
+
variant: isCapturing ? "destructive" : "outline",
|
|
3192
|
+
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"}`,
|
|
3193
|
+
onClick: isCapturing ? onStop : onStart,
|
|
3194
|
+
disabled: disabled || isBusy,
|
|
3195
|
+
children: isBusy ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Loader2, { className: "h-7 w-7 animate-spin" }) : isCapturing ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Square, { className: "h-7 w-7" }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Mic, { className: "h-7 w-7" })
|
|
3196
|
+
}
|
|
3197
|
+
),
|
|
3198
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "w-full space-y-2", children: [
|
|
3199
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Progress, { value: levelValue, className: "h-2" }),
|
|
3200
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
|
|
3201
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: formatDuration(durationMs) }),
|
|
3202
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: isCapturing ? labels?.voiceStop || "Stop recording" : labels?.voiceStart || "Start recording" })
|
|
3203
|
+
] })
|
|
3204
|
+
] }),
|
|
3205
|
+
showTranscriptPreview && transcriptMode !== "none" && transcriptText && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-full rounded-lg border bg-background px-3 py-2 text-left text-sm", children: transcriptText })
|
|
3206
|
+
] }) }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-3 rounded-xl border bg-muted/20 p-3 sm:p-4", children: [
|
|
3207
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-start justify-between gap-2", children: [
|
|
3208
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "min-w-0", children: [
|
|
3209
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-sm font-medium text-foreground", children: labels?.voiceReview || "Ready to send" }),
|
|
3210
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-xs text-muted-foreground", children: formatDuration(durationMs) })
|
|
3211
|
+
] }),
|
|
3212
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3213
|
+
Button,
|
|
3214
|
+
{
|
|
3215
|
+
type: "button",
|
|
3216
|
+
variant: "ghost",
|
|
3217
|
+
size: "icon",
|
|
3218
|
+
className: "h-8 w-8 shrink-0 text-muted-foreground hover:text-destructive",
|
|
3219
|
+
onClick: onDiscard,
|
|
3220
|
+
disabled,
|
|
3221
|
+
"aria-label": labels?.voiceDiscard || "Delete recording",
|
|
3222
|
+
title: labels?.voiceDiscard || "Delete recording",
|
|
3223
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Trash2, { className: "h-4 w-4" })
|
|
3224
|
+
}
|
|
3225
|
+
)
|
|
3226
|
+
] }),
|
|
3227
|
+
attachment && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-3 rounded-lg bg-background p-2", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("audio", { controls: true, preload: "metadata", className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("source", { src: attachment.dataUrl, type: attachment.mimeType }) }) }),
|
|
3228
|
+
showTranscriptPreview && transcriptMode !== "none" && transcriptText && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-3 rounded-lg border bg-background px-3 py-2 text-left text-sm", children: transcriptText }),
|
|
3229
|
+
isAutoSendActive && autoSendDelayMs > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-3 space-y-2", children: [
|
|
3230
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Progress, { value: countdownValue, className: "h-2" }),
|
|
3231
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-center text-xs text-muted-foreground", children: interpolateSeconds(labels?.voiceAutoSendIn, countdownSeconds) })
|
|
3232
|
+
] }),
|
|
3233
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-3 flex items-center justify-end gap-2", children: [
|
|
3234
|
+
isAutoSendActive && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { type: "button", variant: "ghost", size: "sm", onClick: onCancelAutoSend, disabled, children: [
|
|
3235
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.X, { className: "h-4 w-4" }),
|
|
3236
|
+
labels?.voiceCancel || "Cancel"
|
|
3237
|
+
] }),
|
|
3238
|
+
!isAutoSendActive && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3239
|
+
Button,
|
|
3240
|
+
{
|
|
3241
|
+
type: "button",
|
|
3242
|
+
variant: "outline",
|
|
3243
|
+
size: "icon",
|
|
3244
|
+
onClick: onRecordAgain,
|
|
3245
|
+
disabled,
|
|
3246
|
+
"aria-label": labels?.voiceRecordAgain || "Record again",
|
|
3247
|
+
title: labels?.voiceRecordAgain || "Record again",
|
|
3248
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Mic, { className: "h-4 w-4" })
|
|
3249
|
+
}
|
|
3250
|
+
),
|
|
3251
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { type: "button", size: "sm", onClick: onSendNow, disabled, children: [
|
|
3252
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Send, { className: "h-4 w-4" }),
|
|
3253
|
+
labels?.voiceSendNow || "Send now"
|
|
3254
|
+
] })
|
|
3255
|
+
] })
|
|
3256
|
+
] }),
|
|
3257
|
+
state === "error" && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-3 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2 text-sm text-destructive", children: errorMessage })
|
|
3258
|
+
] });
|
|
3259
|
+
};
|
|
3260
|
+
|
|
3261
|
+
// src/components/chat/ChatInput.tsx
|
|
3262
|
+
var import_lucide_react10 = require("lucide-react");
|
|
3263
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2845
3264
|
var FileUploadItem = (0, import_react5.memo)(function FileUploadItem2({ file, progress, onCancel }) {
|
|
2846
3265
|
const guessTypeFromName = (name) => {
|
|
2847
3266
|
const ext = (name || "").split(".").pop()?.toLowerCase();
|
|
@@ -2870,10 +3289,10 @@ var FileUploadItem = (0, import_react5.memo)(function FileUploadItem2({ file, pr
|
|
|
2870
3289
|
};
|
|
2871
3290
|
const getFileIcon = (type, name) => {
|
|
2872
3291
|
const t = typeof type === "string" && type.length > 0 ? type : guessTypeFromName(name);
|
|
2873
|
-
if (t.startsWith("image/")) return /* @__PURE__ */ (0,
|
|
2874
|
-
if (t.startsWith("video/")) return /* @__PURE__ */ (0,
|
|
2875
|
-
if (t.startsWith("audio/")) return /* @__PURE__ */ (0,
|
|
2876
|
-
return /* @__PURE__ */ (0,
|
|
3292
|
+
if (t.startsWith("image/")) return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Image, { className: "h-4 w-4" });
|
|
3293
|
+
if (t.startsWith("video/")) return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Video, { className: "h-4 w-4" });
|
|
3294
|
+
if (t.startsWith("audio/")) return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Mic, { className: "h-4 w-4" });
|
|
3295
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.FileText, { className: "h-4 w-4" });
|
|
2877
3296
|
};
|
|
2878
3297
|
const formatFileSize = (bytes) => {
|
|
2879
3298
|
if (bytes === 0) return "0 Bytes";
|
|
@@ -2882,21 +3301,21 @@ var FileUploadItem = (0, import_react5.memo)(function FileUploadItem2({ file, pr
|
|
|
2882
3301
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
2883
3302
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
|
2884
3303
|
};
|
|
2885
|
-
return /* @__PURE__ */ (0,
|
|
3304
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Card, { className: "relative", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CardContent, { className: "p-3", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
2886
3305
|
getFileIcon(file.type, file.name),
|
|
2887
|
-
/* @__PURE__ */ (0,
|
|
2888
|
-
/* @__PURE__ */ (0,
|
|
2889
|
-
/* @__PURE__ */ (0,
|
|
2890
|
-
/* @__PURE__ */ (0,
|
|
3306
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
3307
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-sm font-medium truncate", children: file.name }),
|
|
3308
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-xs text-muted-foreground", children: formatFileSize(file.size ?? 0) }),
|
|
3309
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Progress, { value: progress, className: "h-1 mt-1" })
|
|
2891
3310
|
] }),
|
|
2892
|
-
/* @__PURE__ */ (0,
|
|
3311
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2893
3312
|
Button,
|
|
2894
3313
|
{
|
|
2895
3314
|
variant: "ghost",
|
|
2896
3315
|
size: "icon",
|
|
2897
3316
|
className: "h-6 w-6",
|
|
2898
3317
|
onClick: onCancel,
|
|
2899
|
-
children: /* @__PURE__ */ (0,
|
|
3318
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.X, { className: "h-3 w-3" })
|
|
2900
3319
|
}
|
|
2901
3320
|
)
|
|
2902
3321
|
] }) }) });
|
|
@@ -2930,35 +3349,35 @@ var AttachmentPreview = (0, import_react5.memo)(function AttachmentPreview2({ at
|
|
|
2930
3349
|
setIsPlaying(!isPlaying);
|
|
2931
3350
|
}
|
|
2932
3351
|
};
|
|
2933
|
-
const
|
|
3352
|
+
const formatDuration2 = (ms) => {
|
|
2934
3353
|
if (!ms) return "";
|
|
2935
3354
|
const seconds = Math.floor(ms / 1e3);
|
|
2936
3355
|
const minutes = Math.floor(seconds / 60);
|
|
2937
3356
|
return `${minutes}:${(seconds % 60).toString().padStart(2, "0")}`;
|
|
2938
3357
|
};
|
|
2939
|
-
return /* @__PURE__ */ (0,
|
|
2940
|
-
attachment.kind === "image" && /* @__PURE__ */ (0,
|
|
2941
|
-
/* @__PURE__ */ (0,
|
|
3358
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Card, { className: "relative group", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(CardContent, { className: "p-2", children: [
|
|
3359
|
+
attachment.kind === "image" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "relative", children: [
|
|
3360
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2942
3361
|
"img",
|
|
2943
3362
|
{
|
|
2944
3363
|
src: attachment.dataUrl,
|
|
2945
|
-
alt: attachment.fileName || "
|
|
3364
|
+
alt: attachment.fileName || "Attachment",
|
|
2946
3365
|
className: "w-full h-20 object-cover rounded"
|
|
2947
3366
|
}
|
|
2948
3367
|
),
|
|
2949
|
-
/* @__PURE__ */ (0,
|
|
3368
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity rounded flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2950
3369
|
Button,
|
|
2951
3370
|
{
|
|
2952
3371
|
variant: "destructive",
|
|
2953
3372
|
size: "icon",
|
|
2954
3373
|
className: "h-6 w-6",
|
|
2955
3374
|
onClick: onRemove,
|
|
2956
|
-
children: /* @__PURE__ */ (0,
|
|
3375
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.X, { className: "h-3 w-3" })
|
|
2957
3376
|
}
|
|
2958
3377
|
) })
|
|
2959
3378
|
] }),
|
|
2960
|
-
attachment.kind === "video" && /* @__PURE__ */ (0,
|
|
2961
|
-
/* @__PURE__ */ (0,
|
|
3379
|
+
attachment.kind === "video" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "relative", children: [
|
|
3380
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2962
3381
|
"video",
|
|
2963
3382
|
{
|
|
2964
3383
|
src: attachment.dataUrl,
|
|
@@ -2967,34 +3386,34 @@ var AttachmentPreview = (0, import_react5.memo)(function AttachmentPreview2({ at
|
|
|
2967
3386
|
muted: true
|
|
2968
3387
|
}
|
|
2969
3388
|
),
|
|
2970
|
-
/* @__PURE__ */ (0,
|
|
3389
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity rounded flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2971
3390
|
Button,
|
|
2972
3391
|
{
|
|
2973
3392
|
variant: "destructive",
|
|
2974
3393
|
size: "icon",
|
|
2975
3394
|
className: "h-6 w-6",
|
|
2976
3395
|
onClick: onRemove,
|
|
2977
|
-
children: /* @__PURE__ */ (0,
|
|
3396
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.X, { className: "h-3 w-3" })
|
|
2978
3397
|
}
|
|
2979
3398
|
) }),
|
|
2980
|
-
/* @__PURE__ */ (0,
|
|
3399
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Badge, { className: "absolute bottom-1 right-1 text-xs", children: formatDuration2(attachment.durationMs) })
|
|
2981
3400
|
] }),
|
|
2982
|
-
attachment.kind === "audio" && /* @__PURE__ */ (0,
|
|
2983
|
-
/* @__PURE__ */ (0,
|
|
3401
|
+
attachment.kind === "audio" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2 p-2", children: [
|
|
3402
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2984
3403
|
Button,
|
|
2985
3404
|
{
|
|
2986
3405
|
variant: "outline",
|
|
2987
3406
|
size: "icon",
|
|
2988
3407
|
className: "h-8 w-8",
|
|
2989
3408
|
onClick: handlePlayPause,
|
|
2990
|
-
children: isPlaying ? /* @__PURE__ */ (0,
|
|
3409
|
+
children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Pause, { className: "h-3 w-3" }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Play, { className: "h-3 w-3" })
|
|
2991
3410
|
}
|
|
2992
3411
|
),
|
|
2993
|
-
/* @__PURE__ */ (0,
|
|
2994
|
-
/* @__PURE__ */ (0,
|
|
2995
|
-
/* @__PURE__ */ (0,
|
|
3412
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex-1", children: [
|
|
3413
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-xs font-medium", children: attachment.fileName || "Audio" }),
|
|
3414
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-xs text-muted-foreground", children: formatDuration2(attachment.durationMs) })
|
|
2996
3415
|
] }),
|
|
2997
|
-
/* @__PURE__ */ (0,
|
|
3416
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2998
3417
|
"audio",
|
|
2999
3418
|
{
|
|
3000
3419
|
ref: audioRef,
|
|
@@ -3002,21 +3421,21 @@ var AttachmentPreview = (0, import_react5.memo)(function AttachmentPreview2({ at
|
|
|
3002
3421
|
onPause: () => setIsPlaying(false),
|
|
3003
3422
|
onEnded: () => setIsPlaying(false),
|
|
3004
3423
|
preload: "metadata",
|
|
3005
|
-
children: /* @__PURE__ */ (0,
|
|
3424
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("source", { src: audioPlaybackSrc, type: attachment.mimeType })
|
|
3006
3425
|
}
|
|
3007
3426
|
),
|
|
3008
|
-
/* @__PURE__ */ (0,
|
|
3427
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3009
3428
|
Button,
|
|
3010
3429
|
{
|
|
3011
3430
|
variant: "ghost",
|
|
3012
3431
|
size: "icon",
|
|
3013
3432
|
className: "h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity",
|
|
3014
3433
|
onClick: onRemove,
|
|
3015
|
-
children: /* @__PURE__ */ (0,
|
|
3434
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.X, { className: "h-3 w-3" })
|
|
3016
3435
|
}
|
|
3017
3436
|
)
|
|
3018
3437
|
] }),
|
|
3019
|
-
attachment.fileName && attachment.kind !== "audio" && /* @__PURE__ */ (0,
|
|
3438
|
+
attachment.fileName && attachment.kind !== "audio" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "absolute bottom-0 left-0 right-0 bg-black/70 text-white text-xs p-1 rounded-b", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "truncate", children: attachment.fileName }) })
|
|
3020
3439
|
] }) });
|
|
3021
3440
|
});
|
|
3022
3441
|
var AudioRecorder = (0, import_react5.memo)(function AudioRecorder2({ isRecording, onStartRecording, onStopRecording, onCancel, recordingDuration, config }) {
|
|
@@ -3026,61 +3445,71 @@ var AudioRecorder = (0, import_react5.memo)(function AudioRecorder2({ isRecordin
|
|
|
3026
3445
|
return `${mins}:${secs.toString().padStart(2, "0")}`;
|
|
3027
3446
|
};
|
|
3028
3447
|
if (!isRecording) {
|
|
3029
|
-
return /* @__PURE__ */ (0,
|
|
3030
|
-
/* @__PURE__ */ (0,
|
|
3448
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
3449
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3031
3450
|
Button,
|
|
3032
3451
|
{
|
|
3033
3452
|
variant: "outline",
|
|
3034
3453
|
size: "icon",
|
|
3035
3454
|
onClick: onStartRecording,
|
|
3036
3455
|
className: "h-10 w-10",
|
|
3037
|
-
children: /* @__PURE__ */ (0,
|
|
3456
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Mic, { className: "h-4 w-4" })
|
|
3038
3457
|
}
|
|
3039
3458
|
) }),
|
|
3040
|
-
/* @__PURE__ */ (0,
|
|
3459
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { children: config?.labels?.recordAudioTooltip })
|
|
3041
3460
|
] });
|
|
3042
3461
|
}
|
|
3043
|
-
return /* @__PURE__ */ (0,
|
|
3044
|
-
/* @__PURE__ */ (0,
|
|
3045
|
-
/* @__PURE__ */ (0,
|
|
3046
|
-
/* @__PURE__ */ (0,
|
|
3462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Card, { className: "border-red-200 bg-red-50 dark:border-red-800 dark:bg-red-950", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CardContent, { className: "p-3", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
3463
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3464
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "h-3 w-3 bg-red-500 rounded-full animate-pulse" }),
|
|
3465
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-sm font-medium text-red-700 dark:text-red-300", children: config?.labels?.voiceListening || "Recording" })
|
|
3047
3466
|
] }),
|
|
3048
|
-
/* @__PURE__ */ (0,
|
|
3049
|
-
/* @__PURE__ */ (0,
|
|
3050
|
-
/* @__PURE__ */ (0,
|
|
3467
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Badge, { variant: "outline", className: "text-xs", children: formatTime(recordingDuration) }),
|
|
3468
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex gap-1 ml-auto", children: [
|
|
3469
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
3051
3470
|
Button,
|
|
3052
3471
|
{
|
|
3053
3472
|
variant: "outline",
|
|
3054
3473
|
size: "sm",
|
|
3055
3474
|
onClick: onCancel,
|
|
3056
3475
|
children: [
|
|
3057
|
-
/* @__PURE__ */ (0,
|
|
3058
|
-
"
|
|
3476
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.X, { className: "h-3 w-3 mr-1" }),
|
|
3477
|
+
config?.labels?.cancel || "Cancel"
|
|
3059
3478
|
]
|
|
3060
3479
|
}
|
|
3061
3480
|
),
|
|
3062
|
-
/* @__PURE__ */ (0,
|
|
3481
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
3063
3482
|
Button,
|
|
3064
3483
|
{
|
|
3065
3484
|
variant: "default",
|
|
3066
3485
|
size: "sm",
|
|
3067
3486
|
onClick: onStopRecording,
|
|
3068
3487
|
children: [
|
|
3069
|
-
/* @__PURE__ */ (0,
|
|
3070
|
-
"
|
|
3488
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Square, { className: "h-3 w-3 mr-1" }),
|
|
3489
|
+
config?.labels?.voiceStop || "Stop"
|
|
3071
3490
|
]
|
|
3072
3491
|
}
|
|
3073
3492
|
)
|
|
3074
3493
|
] })
|
|
3075
3494
|
] }) }) });
|
|
3076
3495
|
});
|
|
3496
|
+
var resolveVoiceErrorMessage = (error, config) => {
|
|
3497
|
+
if (error instanceof DOMException && error.name === "NotAllowedError") {
|
|
3498
|
+
return config?.labels?.voicePermissionDenied || "Microphone access was denied.";
|
|
3499
|
+
}
|
|
3500
|
+
if (error instanceof Error && error.message.trim().length > 0) {
|
|
3501
|
+
return error.message;
|
|
3502
|
+
}
|
|
3503
|
+
return config?.labels?.voiceCaptureError || "Unable to capture audio.";
|
|
3504
|
+
};
|
|
3505
|
+
var clearVoiceTranscript = () => ({});
|
|
3077
3506
|
var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
3078
3507
|
value,
|
|
3079
3508
|
onChange,
|
|
3080
3509
|
onSubmit,
|
|
3081
3510
|
attachments,
|
|
3082
3511
|
onAttachmentsChange,
|
|
3083
|
-
placeholder = "
|
|
3512
|
+
placeholder = "Type your message...",
|
|
3084
3513
|
disabled = false,
|
|
3085
3514
|
isGenerating = false,
|
|
3086
3515
|
onStopGeneration,
|
|
@@ -3093,16 +3522,35 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3093
3522
|
className = "",
|
|
3094
3523
|
config
|
|
3095
3524
|
}) {
|
|
3525
|
+
const voiceComposeEnabled = config?.voiceCompose?.enabled === true;
|
|
3526
|
+
const voiceDefaultMode = config?.voiceCompose?.defaultMode ?? "text";
|
|
3527
|
+
const voiceAutoSendDelayMs = config?.voiceCompose?.autoSendDelayMs ?? 5e3;
|
|
3528
|
+
const voicePersistComposer = config?.voiceCompose?.persistComposer ?? true;
|
|
3529
|
+
const voiceShowTranscriptPreview = config?.voiceCompose?.showTranscriptPreview ?? true;
|
|
3530
|
+
const voiceTranscriptMode = config?.voiceCompose?.transcriptMode ?? "final-only";
|
|
3531
|
+
const voiceMaxRecordingMs = config?.voiceCompose?.maxRecordingMs;
|
|
3096
3532
|
const [isRecording, setIsRecording] = (0, import_react5.useState)(false);
|
|
3097
3533
|
const { setContext } = useChatUserContext();
|
|
3098
3534
|
const [recordingDuration, setRecordingDuration] = (0, import_react5.useState)(0);
|
|
3099
3535
|
const [uploadProgress, setUploadProgress] = (0, import_react5.useState)(/* @__PURE__ */ new Map());
|
|
3536
|
+
const [isVoiceComposerOpen, setIsVoiceComposerOpen] = (0, import_react5.useState)(
|
|
3537
|
+
() => voiceComposeEnabled && voiceDefaultMode === "voice"
|
|
3538
|
+
);
|
|
3539
|
+
const [voiceState, setVoiceState] = (0, import_react5.useState)("idle");
|
|
3540
|
+
const [voiceDraft, setVoiceDraft] = (0, import_react5.useState)(null);
|
|
3541
|
+
const [voiceTranscript, setVoiceTranscript] = (0, import_react5.useState)(clearVoiceTranscript);
|
|
3542
|
+
const [voiceDurationMs, setVoiceDurationMs] = (0, import_react5.useState)(0);
|
|
3543
|
+
const [voiceAudioLevel, setVoiceAudioLevel] = (0, import_react5.useState)(0);
|
|
3544
|
+
const [voiceCountdownMs, setVoiceCountdownMs] = (0, import_react5.useState)(0);
|
|
3545
|
+
const [isVoiceAutoSendActive, setIsVoiceAutoSendActive] = (0, import_react5.useState)(false);
|
|
3546
|
+
const [voiceError, setVoiceError] = (0, import_react5.useState)(null);
|
|
3100
3547
|
const textareaRef = (0, import_react5.useRef)(null);
|
|
3101
3548
|
const fileInputRef = (0, import_react5.useRef)(null);
|
|
3102
3549
|
const mediaRecorderRef = (0, import_react5.useRef)(null);
|
|
3103
3550
|
const recordingStartTime = (0, import_react5.useRef)(0);
|
|
3104
3551
|
const recordingInterval = (0, import_react5.useRef)(null);
|
|
3105
3552
|
const mediaStreamRef = (0, import_react5.useRef)(null);
|
|
3553
|
+
const voiceProviderRef = (0, import_react5.useRef)(null);
|
|
3106
3554
|
(0, import_react5.useEffect)(() => {
|
|
3107
3555
|
return () => {
|
|
3108
3556
|
if (mediaStreamRef.current) {
|
|
@@ -3111,6 +3559,10 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3111
3559
|
if (recordingInterval.current) {
|
|
3112
3560
|
clearInterval(recordingInterval.current);
|
|
3113
3561
|
}
|
|
3562
|
+
if (voiceProviderRef.current) {
|
|
3563
|
+
void voiceProviderRef.current.destroy();
|
|
3564
|
+
voiceProviderRef.current = null;
|
|
3565
|
+
}
|
|
3114
3566
|
};
|
|
3115
3567
|
}, []);
|
|
3116
3568
|
const handleSubmit = (e) => {
|
|
@@ -3128,7 +3580,7 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3128
3580
|
};
|
|
3129
3581
|
const processFile = async (file) => {
|
|
3130
3582
|
if (file.size > maxFileSize) {
|
|
3131
|
-
alert(`
|
|
3583
|
+
alert(`File too large. Max allowed: ${Math.round(maxFileSize / 1024 / 1024)}MB`);
|
|
3132
3584
|
return null;
|
|
3133
3585
|
}
|
|
3134
3586
|
const fileId = `${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
@@ -3187,7 +3639,7 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3187
3639
|
newMap.delete(fileId);
|
|
3188
3640
|
return newMap;
|
|
3189
3641
|
});
|
|
3190
|
-
alert("
|
|
3642
|
+
alert("Failed to process file");
|
|
3191
3643
|
return null;
|
|
3192
3644
|
}
|
|
3193
3645
|
};
|
|
@@ -3262,7 +3714,7 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3262
3714
|
}, 1e3);
|
|
3263
3715
|
} catch (error) {
|
|
3264
3716
|
console.error("Error starting recording:", error);
|
|
3265
|
-
alert(
|
|
3717
|
+
alert(config?.labels?.voicePermissionDenied || "Microphone access was denied.");
|
|
3266
3718
|
}
|
|
3267
3719
|
};
|
|
3268
3720
|
const stopRecording = () => {
|
|
@@ -3287,13 +3739,154 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3287
3739
|
}
|
|
3288
3740
|
}
|
|
3289
3741
|
};
|
|
3742
|
+
const resetVoiceComposerState = (0, import_react5.useCallback)((nextState = "idle") => {
|
|
3743
|
+
setVoiceState(nextState);
|
|
3744
|
+
setVoiceDraft(null);
|
|
3745
|
+
setVoiceTranscript(clearVoiceTranscript());
|
|
3746
|
+
setVoiceDurationMs(0);
|
|
3747
|
+
setVoiceAudioLevel(0);
|
|
3748
|
+
setVoiceCountdownMs(0);
|
|
3749
|
+
setIsVoiceAutoSendActive(false);
|
|
3750
|
+
setVoiceError(null);
|
|
3751
|
+
}, []);
|
|
3752
|
+
const ensureVoiceProvider = (0, import_react5.useCallback)(async () => {
|
|
3753
|
+
if (voiceProviderRef.current) {
|
|
3754
|
+
return voiceProviderRef.current;
|
|
3755
|
+
}
|
|
3756
|
+
const createProvider = resolveVoiceProviderFactory(config?.voiceCompose?.createProvider);
|
|
3757
|
+
const provider = await createProvider({
|
|
3758
|
+
onStateChange: setVoiceState,
|
|
3759
|
+
onAudioLevelChange: setVoiceAudioLevel,
|
|
3760
|
+
onDurationChange: setVoiceDurationMs,
|
|
3761
|
+
onTranscriptChange: setVoiceTranscript,
|
|
3762
|
+
onSegmentReady: (segment) => {
|
|
3763
|
+
setVoiceDraft(segment);
|
|
3764
|
+
setVoiceTranscript(segment.transcript ?? clearVoiceTranscript());
|
|
3765
|
+
setVoiceDurationMs(segment.attachment.durationMs ?? 0);
|
|
3766
|
+
setVoiceAudioLevel(0);
|
|
3767
|
+
setVoiceCountdownMs(voiceAutoSendDelayMs);
|
|
3768
|
+
setIsVoiceAutoSendActive(voiceAutoSendDelayMs > 0);
|
|
3769
|
+
setVoiceError(null);
|
|
3770
|
+
setVoiceState("review");
|
|
3771
|
+
},
|
|
3772
|
+
onError: (error) => {
|
|
3773
|
+
setVoiceError(resolveVoiceErrorMessage(error, config));
|
|
3774
|
+
setVoiceAudioLevel(0);
|
|
3775
|
+
setVoiceCountdownMs(0);
|
|
3776
|
+
setIsVoiceAutoSendActive(false);
|
|
3777
|
+
setVoiceState("error");
|
|
3778
|
+
}
|
|
3779
|
+
}, {
|
|
3780
|
+
maxRecordingMs: voiceMaxRecordingMs
|
|
3781
|
+
});
|
|
3782
|
+
voiceProviderRef.current = provider;
|
|
3783
|
+
return provider;
|
|
3784
|
+
}, [config, voiceAutoSendDelayMs, voiceMaxRecordingMs]);
|
|
3785
|
+
const closeVoiceComposer = (0, import_react5.useCallback)(async () => {
|
|
3786
|
+
setIsVoiceComposerOpen(false);
|
|
3787
|
+
setVoiceError(null);
|
|
3788
|
+
setVoiceCountdownMs(0);
|
|
3789
|
+
setVoiceAudioLevel(0);
|
|
3790
|
+
setVoiceTranscript(clearVoiceTranscript());
|
|
3791
|
+
setVoiceDraft(null);
|
|
3792
|
+
setVoiceDurationMs(0);
|
|
3793
|
+
setVoiceState("idle");
|
|
3794
|
+
if (voiceProviderRef.current) {
|
|
3795
|
+
await voiceProviderRef.current.cancel();
|
|
3796
|
+
}
|
|
3797
|
+
}, []);
|
|
3798
|
+
const startVoiceCapture = (0, import_react5.useCallback)(async () => {
|
|
3799
|
+
if (disabled || isGenerating) {
|
|
3800
|
+
return;
|
|
3801
|
+
}
|
|
3802
|
+
setIsVoiceComposerOpen(true);
|
|
3803
|
+
setVoiceError(null);
|
|
3804
|
+
setVoiceDraft(null);
|
|
3805
|
+
setVoiceCountdownMs(0);
|
|
3806
|
+
setVoiceTranscript(clearVoiceTranscript());
|
|
3807
|
+
setVoiceAudioLevel(0);
|
|
3808
|
+
setVoiceDurationMs(0);
|
|
3809
|
+
setIsVoiceAutoSendActive(false);
|
|
3810
|
+
try {
|
|
3811
|
+
const provider = await ensureVoiceProvider();
|
|
3812
|
+
await provider.start();
|
|
3813
|
+
} catch (error) {
|
|
3814
|
+
setVoiceError(resolveVoiceErrorMessage(error, config));
|
|
3815
|
+
setVoiceState("error");
|
|
3816
|
+
}
|
|
3817
|
+
}, [disabled, isGenerating, ensureVoiceProvider, config]);
|
|
3818
|
+
const stopVoiceCapture = (0, import_react5.useCallback)(async () => {
|
|
3819
|
+
if (!voiceProviderRef.current) return;
|
|
3820
|
+
try {
|
|
3821
|
+
await voiceProviderRef.current.stop();
|
|
3822
|
+
} catch (error) {
|
|
3823
|
+
setVoiceError(resolveVoiceErrorMessage(error, config));
|
|
3824
|
+
setVoiceState("error");
|
|
3825
|
+
}
|
|
3826
|
+
}, [config]);
|
|
3827
|
+
const cancelVoiceCapture = (0, import_react5.useCallback)(async () => {
|
|
3828
|
+
if (voiceProviderRef.current) {
|
|
3829
|
+
await voiceProviderRef.current.cancel();
|
|
3830
|
+
}
|
|
3831
|
+
resetVoiceComposerState("idle");
|
|
3832
|
+
}, [resetVoiceComposerState]);
|
|
3833
|
+
const finalizeVoiceComposerAfterSend = (0, import_react5.useCallback)(() => {
|
|
3834
|
+
if (voicePersistComposer) {
|
|
3835
|
+
resetVoiceComposerState("idle");
|
|
3836
|
+
setIsVoiceComposerOpen(true);
|
|
3837
|
+
return;
|
|
3838
|
+
}
|
|
3839
|
+
void closeVoiceComposer();
|
|
3840
|
+
}, [voicePersistComposer, resetVoiceComposerState, closeVoiceComposer]);
|
|
3841
|
+
const sendVoiceDraft = (0, import_react5.useCallback)(() => {
|
|
3842
|
+
if (!voiceDraft || disabled || isGenerating) {
|
|
3843
|
+
return;
|
|
3844
|
+
}
|
|
3845
|
+
setVoiceState("sending");
|
|
3846
|
+
setVoiceCountdownMs(0);
|
|
3847
|
+
setIsVoiceAutoSendActive(false);
|
|
3848
|
+
onSubmit("", [...attachments, voiceDraft.attachment]);
|
|
3849
|
+
onChange("");
|
|
3850
|
+
onAttachmentsChange([]);
|
|
3851
|
+
finalizeVoiceComposerAfterSend();
|
|
3852
|
+
}, [
|
|
3853
|
+
voiceDraft,
|
|
3854
|
+
disabled,
|
|
3855
|
+
isGenerating,
|
|
3856
|
+
onSubmit,
|
|
3857
|
+
attachments,
|
|
3858
|
+
onChange,
|
|
3859
|
+
onAttachmentsChange,
|
|
3860
|
+
finalizeVoiceComposerAfterSend
|
|
3861
|
+
]);
|
|
3862
|
+
const cancelVoiceAutoSend = (0, import_react5.useCallback)(() => {
|
|
3863
|
+
setVoiceCountdownMs(0);
|
|
3864
|
+
setIsVoiceAutoSendActive(false);
|
|
3865
|
+
}, []);
|
|
3866
|
+
(0, import_react5.useEffect)(() => {
|
|
3867
|
+
if (voiceState !== "review" || !voiceDraft || voiceAutoSendDelayMs <= 0 || !isVoiceAutoSendActive) {
|
|
3868
|
+
return;
|
|
3869
|
+
}
|
|
3870
|
+
const startedAt = Date.now();
|
|
3871
|
+
setVoiceCountdownMs(voiceAutoSendDelayMs);
|
|
3872
|
+
const timer = setInterval(() => {
|
|
3873
|
+
const remaining = Math.max(0, voiceAutoSendDelayMs - (Date.now() - startedAt));
|
|
3874
|
+
setVoiceCountdownMs(remaining);
|
|
3875
|
+
if (remaining <= 0) {
|
|
3876
|
+
clearInterval(timer);
|
|
3877
|
+
sendVoiceDraft();
|
|
3878
|
+
}
|
|
3879
|
+
}, 100);
|
|
3880
|
+
return () => clearInterval(timer);
|
|
3881
|
+
}, [voiceState, voiceDraft, voiceAutoSendDelayMs, isVoiceAutoSendActive, sendVoiceDraft]);
|
|
3290
3882
|
const removeAttachment = (index) => {
|
|
3291
3883
|
const newAttachments = attachments.filter((_, i) => i !== index);
|
|
3292
3884
|
onAttachmentsChange(newAttachments);
|
|
3293
3885
|
};
|
|
3294
3886
|
const canAddMoreAttachments = attachments.length < maxAttachments;
|
|
3295
|
-
|
|
3296
|
-
|
|
3887
|
+
const showVoiceComposer = voiceComposeEnabled && isVoiceComposerOpen;
|
|
3888
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: `border-t py-0 bg-transparent ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "px-0 md:p-2 pb-1 space-y-4 bg-transparent", children: [
|
|
3889
|
+
uploadProgress.size > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "space-y-2", children: Array.from(uploadProgress.entries()).map(([id, progress]) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3297
3890
|
FileUploadItem,
|
|
3298
3891
|
{
|
|
3299
3892
|
file: { name: progress.fileName },
|
|
@@ -3308,7 +3901,7 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3308
3901
|
},
|
|
3309
3902
|
id
|
|
3310
3903
|
)) }),
|
|
3311
|
-
isRecording && /* @__PURE__ */ (0,
|
|
3904
|
+
isRecording && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3312
3905
|
AudioRecorder,
|
|
3313
3906
|
{
|
|
3314
3907
|
isRecording,
|
|
@@ -3319,7 +3912,7 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3319
3912
|
config
|
|
3320
3913
|
}
|
|
3321
3914
|
),
|
|
3322
|
-
attachments.length > 0 && /* @__PURE__ */ (0,
|
|
3915
|
+
attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "grid grid-cols-4 gap-2", children: attachments.map((attachment, index) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3323
3916
|
AttachmentPreview,
|
|
3324
3917
|
{
|
|
3325
3918
|
attachment,
|
|
@@ -3327,15 +3920,51 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3327
3920
|
},
|
|
3328
3921
|
index
|
|
3329
3922
|
)) }),
|
|
3330
|
-
/* @__PURE__ */ (0,
|
|
3923
|
+
showVoiceComposer ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "mb-1 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3924
|
+
VoiceComposer,
|
|
3925
|
+
{
|
|
3926
|
+
state: voiceState,
|
|
3927
|
+
transcript: voiceTranscript,
|
|
3928
|
+
transcriptMode: voiceTranscriptMode,
|
|
3929
|
+
showTranscriptPreview: voiceShowTranscriptPreview,
|
|
3930
|
+
attachment: voiceDraft?.attachment ?? null,
|
|
3931
|
+
durationMs: voiceDurationMs,
|
|
3932
|
+
audioLevel: voiceAudioLevel,
|
|
3933
|
+
countdownMs: voiceCountdownMs,
|
|
3934
|
+
autoSendDelayMs: voiceAutoSendDelayMs,
|
|
3935
|
+
isAutoSendActive: isVoiceAutoSendActive,
|
|
3936
|
+
errorMessage: voiceError,
|
|
3937
|
+
disabled: disabled || isGenerating,
|
|
3938
|
+
labels: config?.labels,
|
|
3939
|
+
onStart: () => {
|
|
3940
|
+
void startVoiceCapture();
|
|
3941
|
+
},
|
|
3942
|
+
onStop: () => {
|
|
3943
|
+
void stopVoiceCapture();
|
|
3944
|
+
},
|
|
3945
|
+
onCancelAutoSend: () => {
|
|
3946
|
+
cancelVoiceAutoSend();
|
|
3947
|
+
},
|
|
3948
|
+
onDiscard: () => {
|
|
3949
|
+
void cancelVoiceCapture();
|
|
3950
|
+
},
|
|
3951
|
+
onRecordAgain: () => {
|
|
3952
|
+
void startVoiceCapture();
|
|
3953
|
+
},
|
|
3954
|
+
onSendNow: sendVoiceDraft,
|
|
3955
|
+
onExit: () => {
|
|
3956
|
+
void closeVoiceComposer();
|
|
3957
|
+
}
|
|
3958
|
+
}
|
|
3959
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("form", { onSubmit: handleSubmit, className: "mb-1 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
3331
3960
|
"div",
|
|
3332
3961
|
{
|
|
3333
3962
|
className: "flex items-end gap-2 p-3 border rounded-lg bg-background w-full md:min-w-3xl max-w-3xl",
|
|
3334
3963
|
onDrop: handleDrop,
|
|
3335
3964
|
onDragOver: handleDragOver,
|
|
3336
3965
|
children: [
|
|
3337
|
-
enableFileUpload && canAddMoreAttachments && /* @__PURE__ */ (0,
|
|
3338
|
-
/* @__PURE__ */ (0,
|
|
3966
|
+
enableFileUpload && canAddMoreAttachments && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
3967
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3339
3968
|
"input",
|
|
3340
3969
|
{
|
|
3341
3970
|
ref: fileInputRef,
|
|
@@ -3346,8 +3975,8 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3346
3975
|
className: "hidden"
|
|
3347
3976
|
}
|
|
3348
3977
|
),
|
|
3349
|
-
/* @__PURE__ */ (0,
|
|
3350
|
-
/* @__PURE__ */ (0,
|
|
3978
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
3979
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3351
3980
|
Button,
|
|
3352
3981
|
{
|
|
3353
3982
|
type: "button",
|
|
@@ -3360,13 +3989,13 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3360
3989
|
fileInputRef.current?.click();
|
|
3361
3990
|
},
|
|
3362
3991
|
disabled,
|
|
3363
|
-
children: /* @__PURE__ */ (0,
|
|
3992
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Paperclip, { className: "h-4 w-4" })
|
|
3364
3993
|
}
|
|
3365
3994
|
) }),
|
|
3366
|
-
/* @__PURE__ */ (0,
|
|
3995
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { children: config?.labels?.attachFileTooltip })
|
|
3367
3996
|
] })
|
|
3368
3997
|
] }),
|
|
3369
|
-
/* @__PURE__ */ (0,
|
|
3998
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3370
3999
|
Textarea,
|
|
3371
4000
|
{
|
|
3372
4001
|
ref: textareaRef,
|
|
@@ -3379,7 +4008,23 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3379
4008
|
rows: 1
|
|
3380
4009
|
}
|
|
3381
4010
|
) }),
|
|
3382
|
-
enableAudioRecording && !isRecording && canAddMoreAttachments && !value.trim() && /* @__PURE__ */ (0,
|
|
4011
|
+
enableAudioRecording && !isRecording && canAddMoreAttachments && !value.trim() && (voiceComposeEnabled ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
4012
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4013
|
+
Button,
|
|
4014
|
+
{
|
|
4015
|
+
type: "button",
|
|
4016
|
+
variant: "outline",
|
|
4017
|
+
size: "icon",
|
|
4018
|
+
className: "h-10 w-10",
|
|
4019
|
+
onClick: () => {
|
|
4020
|
+
void startVoiceCapture();
|
|
4021
|
+
},
|
|
4022
|
+
disabled: disabled || isGenerating,
|
|
4023
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Mic, { className: "h-4 w-4" })
|
|
4024
|
+
}
|
|
4025
|
+
) }),
|
|
4026
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { children: config?.labels?.voiceEnter || config?.labels?.recordAudioTooltip })
|
|
4027
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3383
4028
|
AudioRecorder,
|
|
3384
4029
|
{
|
|
3385
4030
|
isRecording,
|
|
@@ -3389,9 +4034,9 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3389
4034
|
recordingDuration,
|
|
3390
4035
|
config
|
|
3391
4036
|
}
|
|
3392
|
-
),
|
|
3393
|
-
isGenerating ? /* @__PURE__ */ (0,
|
|
3394
|
-
/* @__PURE__ */ (0,
|
|
4037
|
+
)),
|
|
4038
|
+
isGenerating ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
4039
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3395
4040
|
Button,
|
|
3396
4041
|
{
|
|
3397
4042
|
type: "button",
|
|
@@ -3399,36 +4044,36 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3399
4044
|
size: "icon",
|
|
3400
4045
|
className: "h-10 w-10",
|
|
3401
4046
|
onClick: onStopGeneration,
|
|
3402
|
-
children: /* @__PURE__ */ (0,
|
|
4047
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Square, { className: "h-4 w-4" })
|
|
3403
4048
|
}
|
|
3404
4049
|
) }),
|
|
3405
|
-
/* @__PURE__ */ (0,
|
|
3406
|
-
] }) : /* @__PURE__ */ (0,
|
|
3407
|
-
/* @__PURE__ */ (0,
|
|
4050
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { children: config?.labels?.stopGenerationTooltip })
|
|
4051
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
4052
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3408
4053
|
Button,
|
|
3409
4054
|
{
|
|
3410
4055
|
type: "submit",
|
|
3411
4056
|
size: "icon",
|
|
3412
4057
|
className: "h-10 w-10",
|
|
3413
4058
|
disabled: disabled || !value.trim() && attachments.length === 0,
|
|
3414
|
-
children: disabled ? /* @__PURE__ */ (0,
|
|
4059
|
+
children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Loader2, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Send, { className: "h-4 w-4" })
|
|
3415
4060
|
}
|
|
3416
4061
|
) }),
|
|
3417
|
-
/* @__PURE__ */ (0,
|
|
4062
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { children: config?.labels?.sendMessageTooltip })
|
|
3418
4063
|
] })
|
|
3419
4064
|
]
|
|
3420
4065
|
}
|
|
3421
4066
|
) }),
|
|
3422
|
-
/* @__PURE__ */ (0,
|
|
4067
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "text-[10px] text-muted-foreground text-center", children: [
|
|
3423
4068
|
window.innerWidth > 768 ? config?.labels?.inputHelpText : "",
|
|
3424
|
-
attachments.length > 0 && /* @__PURE__ */ (0,
|
|
4069
|
+
attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
3425
4070
|
" \u2022 ",
|
|
3426
4071
|
attachments.length,
|
|
3427
4072
|
"/",
|
|
3428
4073
|
maxAttachments,
|
|
3429
4074
|
" anexos"
|
|
3430
4075
|
] }),
|
|
3431
|
-
config?.labels?.footerLabel && /* @__PURE__ */ (0,
|
|
4076
|
+
config?.labels?.footerLabel && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
3432
4077
|
" \u2022 ",
|
|
3433
4078
|
config.labels.footerLabel
|
|
3434
4079
|
] })
|
|
@@ -3442,16 +4087,16 @@ var import_react6 = require("react");
|
|
|
3442
4087
|
// src/components/ui/scroll-area.tsx
|
|
3443
4088
|
var React11 = __toESM(require("react"), 1);
|
|
3444
4089
|
var ScrollAreaPrimitive = __toESM(require("@radix-ui/react-scroll-area"), 1);
|
|
3445
|
-
var
|
|
4090
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
3446
4091
|
var ScrollArea = React11.forwardRef(({ className, children, viewportClassName, onScroll, onScrollCapture, ...props }, ref) => {
|
|
3447
|
-
return /* @__PURE__ */ (0,
|
|
4092
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
3448
4093
|
ScrollAreaPrimitive.Root,
|
|
3449
4094
|
{
|
|
3450
4095
|
"data-slot": "scroll-area",
|
|
3451
4096
|
className: cn("relative", className),
|
|
3452
4097
|
...props,
|
|
3453
4098
|
children: [
|
|
3454
|
-
/* @__PURE__ */ (0,
|
|
4099
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3455
4100
|
ScrollAreaPrimitive.Viewport,
|
|
3456
4101
|
{
|
|
3457
4102
|
ref,
|
|
@@ -3465,8 +4110,8 @@ var ScrollArea = React11.forwardRef(({ className, children, viewportClassName, o
|
|
|
3465
4110
|
children
|
|
3466
4111
|
}
|
|
3467
4112
|
),
|
|
3468
|
-
/* @__PURE__ */ (0,
|
|
3469
|
-
/* @__PURE__ */ (0,
|
|
4113
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ScrollBar, {}),
|
|
4114
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ScrollAreaPrimitive.Corner, {})
|
|
3470
4115
|
]
|
|
3471
4116
|
}
|
|
3472
4117
|
);
|
|
@@ -3477,7 +4122,7 @@ function ScrollBar({
|
|
|
3477
4122
|
orientation = "vertical",
|
|
3478
4123
|
...props
|
|
3479
4124
|
}) {
|
|
3480
|
-
return /* @__PURE__ */ (0,
|
|
4125
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3481
4126
|
ScrollAreaPrimitive.ScrollAreaScrollbar,
|
|
3482
4127
|
{
|
|
3483
4128
|
"data-slot": "scroll-area-scrollbar",
|
|
@@ -3489,7 +4134,7 @@ function ScrollBar({
|
|
|
3489
4134
|
className
|
|
3490
4135
|
),
|
|
3491
4136
|
...props,
|
|
3492
|
-
children: /* @__PURE__ */ (0,
|
|
4137
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3493
4138
|
ScrollAreaPrimitive.ScrollAreaThumb,
|
|
3494
4139
|
{
|
|
3495
4140
|
"data-slot": "scroll-area-thumb",
|
|
@@ -3501,8 +4146,8 @@ function ScrollBar({
|
|
|
3501
4146
|
}
|
|
3502
4147
|
|
|
3503
4148
|
// src/components/chat/UserProfile.tsx
|
|
3504
|
-
var
|
|
3505
|
-
var
|
|
4149
|
+
var import_lucide_react11 = require("lucide-react");
|
|
4150
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
3506
4151
|
var getInitials2 = (name, email) => {
|
|
3507
4152
|
if (name) {
|
|
3508
4153
|
return name.split(" ").map((n) => n[0]).slice(0, 2).join("").toUpperCase();
|
|
@@ -3516,29 +4161,29 @@ var getFieldIcon = (type, key) => {
|
|
|
3516
4161
|
const iconClass = "h-4 w-4 text-muted-foreground";
|
|
3517
4162
|
switch (type) {
|
|
3518
4163
|
case "email":
|
|
3519
|
-
return /* @__PURE__ */ (0,
|
|
4164
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Mail, { className: iconClass });
|
|
3520
4165
|
case "phone":
|
|
3521
|
-
return /* @__PURE__ */ (0,
|
|
4166
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Phone, { className: iconClass });
|
|
3522
4167
|
case "url":
|
|
3523
|
-
return /* @__PURE__ */ (0,
|
|
4168
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Globe, { className: iconClass });
|
|
3524
4169
|
case "date":
|
|
3525
|
-
return /* @__PURE__ */ (0,
|
|
4170
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Calendar, { className: iconClass });
|
|
3526
4171
|
}
|
|
3527
4172
|
const lowerKey = key?.toLowerCase() || "";
|
|
3528
|
-
if (lowerKey.includes("follower")) return /* @__PURE__ */ (0,
|
|
3529
|
-
if (lowerKey.includes("following")) return /* @__PURE__ */ (0,
|
|
3530
|
-
if (lowerKey.includes("post") || lowerKey.includes("publication")) return /* @__PURE__ */ (0,
|
|
3531
|
-
if (lowerKey.includes("verified") || lowerKey.includes("badge")) return /* @__PURE__ */ (0,
|
|
3532
|
-
if (lowerKey.includes("bio")) return /* @__PURE__ */ (0,
|
|
3533
|
-
if (lowerKey.includes("email")) return /* @__PURE__ */ (0,
|
|
3534
|
-
if (lowerKey.includes("phone") || lowerKey.includes("tel")) return /* @__PURE__ */ (0,
|
|
3535
|
-
if (lowerKey.includes("location") || lowerKey.includes("address") || lowerKey.includes("city")) return /* @__PURE__ */ (0,
|
|
3536
|
-
if (lowerKey.includes("company") || lowerKey.includes("org")) return /* @__PURE__ */ (0,
|
|
3537
|
-
if (lowerKey.includes("job") || lowerKey.includes("role") || lowerKey.includes("title") || lowerKey.includes("position")) return /* @__PURE__ */ (0,
|
|
3538
|
-
if (lowerKey.includes("website") || lowerKey.includes("url") || lowerKey.includes("link")) return /* @__PURE__ */ (0,
|
|
3539
|
-
if (lowerKey.includes("username") || lowerKey.includes("handle")) return /* @__PURE__ */ (0,
|
|
3540
|
-
if (lowerKey.includes("date") || lowerKey.includes("birthday") || lowerKey.includes("joined")) return /* @__PURE__ */ (0,
|
|
3541
|
-
return /* @__PURE__ */ (0,
|
|
4173
|
+
if (lowerKey.includes("follower")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Users, { className: iconClass });
|
|
4174
|
+
if (lowerKey.includes("following")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.UserPlus, { className: iconClass });
|
|
4175
|
+
if (lowerKey.includes("post") || lowerKey.includes("publication")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Image, { className: iconClass });
|
|
4176
|
+
if (lowerKey.includes("verified") || lowerKey.includes("badge")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.BadgeCheck, { className: iconClass });
|
|
4177
|
+
if (lowerKey.includes("bio")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.FileText, { className: iconClass });
|
|
4178
|
+
if (lowerKey.includes("email")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Mail, { className: iconClass });
|
|
4179
|
+
if (lowerKey.includes("phone") || lowerKey.includes("tel")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Phone, { className: iconClass });
|
|
4180
|
+
if (lowerKey.includes("location") || lowerKey.includes("address") || lowerKey.includes("city")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.MapPin, { className: iconClass });
|
|
4181
|
+
if (lowerKey.includes("company") || lowerKey.includes("org")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Building, { className: iconClass });
|
|
4182
|
+
if (lowerKey.includes("job") || lowerKey.includes("role") || lowerKey.includes("title") || lowerKey.includes("position")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Briefcase, { className: iconClass });
|
|
4183
|
+
if (lowerKey.includes("website") || lowerKey.includes("url") || lowerKey.includes("link")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Globe, { className: iconClass });
|
|
4184
|
+
if (lowerKey.includes("username") || lowerKey.includes("handle")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.AtSign, { className: iconClass });
|
|
4185
|
+
if (lowerKey.includes("date") || lowerKey.includes("birthday") || lowerKey.includes("joined")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Calendar, { className: iconClass });
|
|
4186
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.User, { className: iconClass });
|
|
3542
4187
|
};
|
|
3543
4188
|
var formatValue = (value, type, key) => {
|
|
3544
4189
|
if (value === null || value === void 0) return "-";
|
|
@@ -3572,15 +4217,15 @@ var getMemoryCategoryIcon = (category) => {
|
|
|
3572
4217
|
const iconClass = "h-4 w-4 text-muted-foreground";
|
|
3573
4218
|
switch (category) {
|
|
3574
4219
|
case "preference":
|
|
3575
|
-
return /* @__PURE__ */ (0,
|
|
4220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Heart, { className: iconClass });
|
|
3576
4221
|
case "fact":
|
|
3577
|
-
return /* @__PURE__ */ (0,
|
|
4222
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Info, { className: iconClass });
|
|
3578
4223
|
case "goal":
|
|
3579
|
-
return /* @__PURE__ */ (0,
|
|
4224
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Target, { className: iconClass });
|
|
3580
4225
|
case "context":
|
|
3581
|
-
return /* @__PURE__ */ (0,
|
|
4226
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Lightbulb, { className: iconClass });
|
|
3582
4227
|
default:
|
|
3583
|
-
return /* @__PURE__ */ (0,
|
|
4228
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Brain, { className: iconClass });
|
|
3584
4229
|
}
|
|
3585
4230
|
};
|
|
3586
4231
|
var getMemoryCategoryLabel = (category) => {
|
|
@@ -3650,66 +4295,66 @@ var UserProfile = ({
|
|
|
3650
4295
|
const displayName = user?.name || user?.email?.split("@")[0] || "User";
|
|
3651
4296
|
const initials = getInitials2(user?.name, user?.email);
|
|
3652
4297
|
const normalizedFields = normalizeCustomFields(customFields);
|
|
3653
|
-
return /* @__PURE__ */ (0,
|
|
4298
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Sheet, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
3654
4299
|
SheetContent,
|
|
3655
4300
|
{
|
|
3656
4301
|
side: "right",
|
|
3657
4302
|
className: cn("w-full sm:max-w-md p-0 flex flex-col h-full overflow-hidden", className),
|
|
3658
4303
|
children: [
|
|
3659
|
-
/* @__PURE__ */ (0,
|
|
3660
|
-
/* @__PURE__ */ (0,
|
|
3661
|
-
/* @__PURE__ */ (0,
|
|
3662
|
-
/* @__PURE__ */ (0,
|
|
3663
|
-
user?.avatar && /* @__PURE__ */ (0,
|
|
3664
|
-
/* @__PURE__ */ (0,
|
|
4304
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SheetHeader, { className: "px-6 py-4 border-b shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SheetTitle, { children: labels.title }) }) }),
|
|
4305
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ScrollArea, { className: "flex-1 min-h-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "p-6 space-y-6", children: [
|
|
4306
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col items-center text-center space-y-4", children: [
|
|
4307
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Avatar, { className: "h-24 w-24 shrink-0", children: [
|
|
4308
|
+
user?.avatar && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AvatarImage, { src: user.avatar, alt: displayName }),
|
|
4309
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AvatarFallback, { className: "text-2xl bg-primary/10 text-primary", children: initials })
|
|
3665
4310
|
] }),
|
|
3666
|
-
/* @__PURE__ */ (0,
|
|
3667
|
-
/* @__PURE__ */ (0,
|
|
3668
|
-
user?.email && /* @__PURE__ */ (0,
|
|
4311
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "w-full px-2", children: [
|
|
4312
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { className: "text-xl font-semibold break-words", children: displayName }),
|
|
4313
|
+
user?.email && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm text-muted-foreground break-words", children: user.email })
|
|
3669
4314
|
] })
|
|
3670
4315
|
] }),
|
|
3671
|
-
/* @__PURE__ */ (0,
|
|
3672
|
-
/* @__PURE__ */ (0,
|
|
3673
|
-
/* @__PURE__ */ (0,
|
|
3674
|
-
/* @__PURE__ */ (0,
|
|
3675
|
-
/* @__PURE__ */ (0,
|
|
3676
|
-
/* @__PURE__ */ (0,
|
|
3677
|
-
/* @__PURE__ */ (0,
|
|
3678
|
-
/* @__PURE__ */ (0,
|
|
3679
|
-
/* @__PURE__ */ (0,
|
|
4316
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Separator, {}),
|
|
4317
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "space-y-3", children: [
|
|
4318
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { className: "text-sm font-medium text-muted-foreground uppercase tracking-wider", children: labels.basicInfo }),
|
|
4319
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "space-y-2", children: [
|
|
4320
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50", children: [
|
|
4321
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.User, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
4322
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
4323
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-xs text-muted-foreground", children: "Name" }),
|
|
4324
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm font-medium break-words", children: displayName })
|
|
3680
4325
|
] })
|
|
3681
4326
|
] }),
|
|
3682
|
-
user?.email && /* @__PURE__ */ (0,
|
|
3683
|
-
/* @__PURE__ */ (0,
|
|
3684
|
-
/* @__PURE__ */ (0,
|
|
3685
|
-
/* @__PURE__ */ (0,
|
|
3686
|
-
/* @__PURE__ */ (0,
|
|
4327
|
+
user?.email && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50", children: [
|
|
4328
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.AtSign, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
4329
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
4330
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-xs text-muted-foreground", children: "Handle" }),
|
|
4331
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm font-medium break-words", children: user.email })
|
|
3687
4332
|
] })
|
|
3688
4333
|
] }),
|
|
3689
|
-
user?.id && user.id !== user?.name && user.id !== user?.email && /* @__PURE__ */ (0,
|
|
3690
|
-
/* @__PURE__ */ (0,
|
|
3691
|
-
/* @__PURE__ */ (0,
|
|
3692
|
-
/* @__PURE__ */ (0,
|
|
3693
|
-
/* @__PURE__ */ (0,
|
|
4334
|
+
user?.id && user.id !== user?.name && user.id !== user?.email && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50", children: [
|
|
4335
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.User, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
4336
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
4337
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-xs text-muted-foreground", children: "ID" }),
|
|
4338
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm font-medium break-words", children: user.id })
|
|
3694
4339
|
] })
|
|
3695
4340
|
] })
|
|
3696
4341
|
] })
|
|
3697
4342
|
] }),
|
|
3698
|
-
normalizedFields.length > 0 && /* @__PURE__ */ (0,
|
|
3699
|
-
/* @__PURE__ */ (0,
|
|
3700
|
-
/* @__PURE__ */ (0,
|
|
3701
|
-
/* @__PURE__ */ (0,
|
|
3702
|
-
/* @__PURE__ */ (0,
|
|
4343
|
+
normalizedFields.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
4344
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Separator, {}),
|
|
4345
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "space-y-3", children: [
|
|
4346
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { className: "text-sm font-medium text-muted-foreground uppercase tracking-wider", children: labels.customFields }),
|
|
4347
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "space-y-2", children: normalizedFields.map((field) => {
|
|
3703
4348
|
const isBioField = field.key.toLowerCase().includes("bio");
|
|
3704
|
-
return /* @__PURE__ */ (0,
|
|
4349
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
3705
4350
|
"div",
|
|
3706
4351
|
{
|
|
3707
4352
|
className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50",
|
|
3708
4353
|
children: [
|
|
3709
|
-
/* @__PURE__ */ (0,
|
|
3710
|
-
/* @__PURE__ */ (0,
|
|
3711
|
-
/* @__PURE__ */ (0,
|
|
3712
|
-
/* @__PURE__ */ (0,
|
|
4354
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "mt-0.5 shrink-0", children: field.icon || getFieldIcon(field.type, field.key) }),
|
|
4355
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
4356
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-xs text-muted-foreground", children: field.label }),
|
|
4357
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: cn(
|
|
3713
4358
|
"text-sm font-medium",
|
|
3714
4359
|
isBioField ? "whitespace-pre-wrap break-words" : "break-words"
|
|
3715
4360
|
), children: formatValue(field.value, field.type, field.key) })
|
|
@@ -3721,26 +4366,26 @@ var UserProfile = ({
|
|
|
3721
4366
|
}) })
|
|
3722
4367
|
] })
|
|
3723
4368
|
] }),
|
|
3724
|
-
/* @__PURE__ */ (0,
|
|
3725
|
-
/* @__PURE__ */ (0,
|
|
3726
|
-
/* @__PURE__ */ (0,
|
|
3727
|
-
/* @__PURE__ */ (0,
|
|
3728
|
-
/* @__PURE__ */ (0,
|
|
4369
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Separator, {}),
|
|
4370
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "space-y-3", children: [
|
|
4371
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
4372
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("h3", { className: "text-sm font-medium text-muted-foreground uppercase tracking-wider flex items-center gap-2", children: [
|
|
4373
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Brain, { className: "h-4 w-4" }),
|
|
3729
4374
|
labels.memories
|
|
3730
4375
|
] }),
|
|
3731
|
-
onAddMemory && /* @__PURE__ */ (0,
|
|
4376
|
+
onAddMemory && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3732
4377
|
Button,
|
|
3733
4378
|
{
|
|
3734
4379
|
variant: "ghost",
|
|
3735
4380
|
size: "sm",
|
|
3736
4381
|
className: "h-7 px-2",
|
|
3737
4382
|
onClick: () => setIsAddingMemory(true),
|
|
3738
|
-
children: /* @__PURE__ */ (0,
|
|
4383
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Plus, { className: "h-4 w-4" })
|
|
3739
4384
|
}
|
|
3740
4385
|
)
|
|
3741
4386
|
] }),
|
|
3742
|
-
isAddingMemory && onAddMemory && /* @__PURE__ */ (0,
|
|
3743
|
-
/* @__PURE__ */ (0,
|
|
4387
|
+
isAddingMemory && onAddMemory && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-2", children: [
|
|
4388
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3744
4389
|
Input,
|
|
3745
4390
|
{
|
|
3746
4391
|
value: newMemoryContent,
|
|
@@ -3757,24 +4402,24 @@ var UserProfile = ({
|
|
|
3757
4402
|
autoFocus: true
|
|
3758
4403
|
}
|
|
3759
4404
|
),
|
|
3760
|
-
/* @__PURE__ */ (0,
|
|
4405
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Button, { size: "sm", onClick: handleAddMemory, disabled: !newMemoryContent.trim(), children: "Salvar" })
|
|
3761
4406
|
] }),
|
|
3762
|
-
/* @__PURE__ */ (0,
|
|
4407
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "space-y-2", children: memories.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm text-muted-foreground text-center py-4", children: labels.noMemories }) : memories.map((memory) => {
|
|
3763
4408
|
const isEditing = editingMemoryId === memory.id;
|
|
3764
|
-
return /* @__PURE__ */ (0,
|
|
4409
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
3765
4410
|
"div",
|
|
3766
4411
|
{
|
|
3767
4412
|
className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50 group",
|
|
3768
4413
|
children: [
|
|
3769
|
-
/* @__PURE__ */ (0,
|
|
3770
|
-
/* @__PURE__ */ (0,
|
|
3771
|
-
/* @__PURE__ */ (0,
|
|
3772
|
-
/* @__PURE__ */ (0,
|
|
3773
|
-
/* @__PURE__ */ (0,
|
|
3774
|
-
/* @__PURE__ */ (0,
|
|
4414
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "mt-0.5 shrink-0", children: memory.source === "agent" ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Bot, { className: "h-4 w-4 text-primary" }) : getMemoryCategoryIcon(memory.category) }),
|
|
4415
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
4416
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-2 mb-0.5", children: [
|
|
4417
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-xs text-muted-foreground", children: getMemoryCategoryLabel(memory.category) }),
|
|
4418
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-xs text-muted-foreground", children: "\u2022" }),
|
|
4419
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-xs text-muted-foreground", children: memory.source === "agent" ? "IA" : "Voc\xEA" })
|
|
3775
4420
|
] }),
|
|
3776
|
-
isEditing ? /* @__PURE__ */ (0,
|
|
3777
|
-
/* @__PURE__ */ (0,
|
|
4421
|
+
isEditing ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "space-y-2", children: [
|
|
4422
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3778
4423
|
Textarea,
|
|
3779
4424
|
{
|
|
3780
4425
|
value: editingMemoryContent,
|
|
@@ -3791,8 +4436,8 @@ var UserProfile = ({
|
|
|
3791
4436
|
}
|
|
3792
4437
|
}
|
|
3793
4438
|
),
|
|
3794
|
-
/* @__PURE__ */ (0,
|
|
3795
|
-
/* @__PURE__ */ (0,
|
|
4439
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-1 justify-end", children: [
|
|
4440
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
3796
4441
|
Button,
|
|
3797
4442
|
{
|
|
3798
4443
|
variant: "ghost",
|
|
@@ -3800,12 +4445,12 @@ var UserProfile = ({
|
|
|
3800
4445
|
className: "h-7 px-2",
|
|
3801
4446
|
onClick: handleCancelEdit,
|
|
3802
4447
|
children: [
|
|
3803
|
-
/* @__PURE__ */ (0,
|
|
4448
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.X, { className: "h-3.5 w-3.5 mr-1" }),
|
|
3804
4449
|
"Cancelar"
|
|
3805
4450
|
]
|
|
3806
4451
|
}
|
|
3807
4452
|
),
|
|
3808
|
-
/* @__PURE__ */ (0,
|
|
4453
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
3809
4454
|
Button,
|
|
3810
4455
|
{
|
|
3811
4456
|
size: "sm",
|
|
@@ -3813,33 +4458,33 @@ var UserProfile = ({
|
|
|
3813
4458
|
onClick: handleSaveEdit,
|
|
3814
4459
|
disabled: !editingMemoryContent.trim(),
|
|
3815
4460
|
children: [
|
|
3816
|
-
/* @__PURE__ */ (0,
|
|
4461
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Check, { className: "h-3.5 w-3.5 mr-1" }),
|
|
3817
4462
|
"Salvar"
|
|
3818
4463
|
]
|
|
3819
4464
|
}
|
|
3820
4465
|
)
|
|
3821
4466
|
] })
|
|
3822
|
-
] }) : /* @__PURE__ */ (0,
|
|
4467
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm break-words", children: memory.content })
|
|
3823
4468
|
] }),
|
|
3824
|
-
!isEditing && (onUpdateMemory || onDeleteMemory) && /* @__PURE__ */ (0,
|
|
3825
|
-
onUpdateMemory && /* @__PURE__ */ (0,
|
|
4469
|
+
!isEditing && (onUpdateMemory || onDeleteMemory) && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity shrink-0", children: [
|
|
4470
|
+
onUpdateMemory && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3826
4471
|
Button,
|
|
3827
4472
|
{
|
|
3828
4473
|
variant: "ghost",
|
|
3829
4474
|
size: "icon",
|
|
3830
4475
|
className: "h-7 w-7",
|
|
3831
4476
|
onClick: () => handleStartEdit(memory),
|
|
3832
|
-
children: /* @__PURE__ */ (0,
|
|
4477
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Pencil, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
3833
4478
|
}
|
|
3834
4479
|
),
|
|
3835
|
-
onDeleteMemory && /* @__PURE__ */ (0,
|
|
4480
|
+
onDeleteMemory && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3836
4481
|
Button,
|
|
3837
4482
|
{
|
|
3838
4483
|
variant: "ghost",
|
|
3839
4484
|
size: "icon",
|
|
3840
4485
|
className: "h-7 w-7",
|
|
3841
4486
|
onClick: () => onDeleteMemory(memory.id),
|
|
3842
|
-
children: /* @__PURE__ */ (0,
|
|
4487
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Trash2, { className: "h-3.5 w-3.5 text-destructive" })
|
|
3843
4488
|
}
|
|
3844
4489
|
)
|
|
3845
4490
|
] })
|
|
@@ -3850,8 +4495,8 @@ var UserProfile = ({
|
|
|
3850
4495
|
}) })
|
|
3851
4496
|
] })
|
|
3852
4497
|
] }) }),
|
|
3853
|
-
/* @__PURE__ */ (0,
|
|
3854
|
-
onEditProfile && /* @__PURE__ */ (0,
|
|
4498
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "p-4 border-t space-y-2 shrink-0", children: [
|
|
4499
|
+
onEditProfile && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3855
4500
|
Button,
|
|
3856
4501
|
{
|
|
3857
4502
|
variant: "outline",
|
|
@@ -3860,7 +4505,7 @@ var UserProfile = ({
|
|
|
3860
4505
|
children: "Edit Profile"
|
|
3861
4506
|
}
|
|
3862
4507
|
),
|
|
3863
|
-
onLogout && /* @__PURE__ */ (0,
|
|
4508
|
+
onLogout && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3864
4509
|
Button,
|
|
3865
4510
|
{
|
|
3866
4511
|
variant: "destructive",
|
|
@@ -3876,8 +4521,8 @@ var UserProfile = ({
|
|
|
3876
4521
|
};
|
|
3877
4522
|
|
|
3878
4523
|
// src/components/chat/ChatUI.tsx
|
|
3879
|
-
var
|
|
3880
|
-
var
|
|
4524
|
+
var import_lucide_react12 = require("lucide-react");
|
|
4525
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
3881
4526
|
var ChatUI = ({
|
|
3882
4527
|
messages = [],
|
|
3883
4528
|
threads = [],
|
|
@@ -4140,16 +4785,16 @@ var ChatUI = ({
|
|
|
4140
4785
|
}
|
|
4141
4786
|
return component;
|
|
4142
4787
|
}, [config?.customComponent?.component, closeSidebar, isMobile]);
|
|
4143
|
-
const SuggestionIconComponents = [
|
|
4788
|
+
const SuggestionIconComponents = [import_lucide_react12.MessageSquare, import_lucide_react12.Lightbulb, import_lucide_react12.Zap, import_lucide_react12.HelpCircle];
|
|
4144
4789
|
const renderSuggestions = () => {
|
|
4145
4790
|
if (messages.length > 0 || !suggestions.length) return null;
|
|
4146
|
-
return /* @__PURE__ */ (0,
|
|
4147
|
-
/* @__PURE__ */ (0,
|
|
4148
|
-
/* @__PURE__ */ (0,
|
|
4149
|
-
/* @__PURE__ */ (0,
|
|
4150
|
-
/* @__PURE__ */ (0,
|
|
4791
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col items-center justify-center min-h-[60vh] py-8 px-4", children: [
|
|
4792
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "text-center mb-8", children: [
|
|
4793
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("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__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Sparkles, { className: "w-7 h-7 text-primary" }) }),
|
|
4794
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h2", { className: "text-xl font-semibold mb-2", children: config.branding.title }),
|
|
4795
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "text-muted-foreground text-sm max-w-md", children: config.branding.subtitle })
|
|
4151
4796
|
] }),
|
|
4152
|
-
/* @__PURE__ */ (0,
|
|
4797
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3 w-full max-w-2xl", children: suggestions.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
4153
4798
|
"button",
|
|
4154
4799
|
{
|
|
4155
4800
|
type: "button",
|
|
@@ -4158,10 +4803,10 @@ var ChatUI = ({
|
|
|
4158
4803
|
children: [
|
|
4159
4804
|
(() => {
|
|
4160
4805
|
const IconComponent = SuggestionIconComponents[index % SuggestionIconComponents.length];
|
|
4161
|
-
return /* @__PURE__ */ (0,
|
|
4806
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("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__ */ (0, import_jsx_runtime25.jsx)(IconComponent, { className: "h-4 w-4" }) });
|
|
4162
4807
|
})(),
|
|
4163
|
-
/* @__PURE__ */ (0,
|
|
4164
|
-
/* @__PURE__ */ (0,
|
|
4808
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex-1 min-w-0 pr-6", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "text-sm font-medium leading-snug line-clamp-2", children: suggestion }) }),
|
|
4809
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.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" })
|
|
4165
4810
|
]
|
|
4166
4811
|
},
|
|
4167
4812
|
index
|
|
@@ -4172,34 +4817,34 @@ var ChatUI = ({
|
|
|
4172
4817
|
const items = messageSuggestions?.[messageId];
|
|
4173
4818
|
if (!items || items.length === 0) return null;
|
|
4174
4819
|
const inlineSuggestionOffsetClass = config.ui.showAvatars ? config.ui.compactMode ? "ml-9" : "ml-11" : "";
|
|
4175
|
-
return /* @__PURE__ */ (0,
|
|
4820
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: `flex flex-wrap gap-2 mt-2 ${inlineSuggestionOffsetClass}`, children: items.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
4176
4821
|
"button",
|
|
4177
4822
|
{
|
|
4178
4823
|
type: "button",
|
|
4179
4824
|
onClick: () => handleSendMessage(suggestion),
|
|
4180
4825
|
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",
|
|
4181
4826
|
children: [
|
|
4182
|
-
/* @__PURE__ */ (0,
|
|
4183
|
-
/* @__PURE__ */ (0,
|
|
4827
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Sparkles, { className: "h-3 w-3 text-primary opacity-70 group-hover:opacity-100" }),
|
|
4828
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "max-w-[200px] truncate", children: suggestion })
|
|
4184
4829
|
]
|
|
4185
4830
|
},
|
|
4186
4831
|
`${messageId}-suggestion-${index}`
|
|
4187
4832
|
)) });
|
|
4188
4833
|
};
|
|
4189
|
-
const renderMessageLoadingSkeleton = () => /* @__PURE__ */ (0,
|
|
4834
|
+
const renderMessageLoadingSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "space-y-6 py-2", children: [0, 1, 2, 3].map((index) => {
|
|
4190
4835
|
const isUserRow = index % 2 === 1;
|
|
4191
|
-
return /* @__PURE__ */ (0,
|
|
4836
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
4192
4837
|
"div",
|
|
4193
4838
|
{
|
|
4194
4839
|
className: `flex gap-3 ${isUserRow ? "justify-end" : "justify-start"}`,
|
|
4195
4840
|
children: [
|
|
4196
|
-
!isUserRow && /* @__PURE__ */ (0,
|
|
4197
|
-
/* @__PURE__ */ (0,
|
|
4198
|
-
/* @__PURE__ */ (0,
|
|
4199
|
-
/* @__PURE__ */ (0,
|
|
4200
|
-
/* @__PURE__ */ (0,
|
|
4841
|
+
!isUserRow && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Skeleton, { className: "h-8 w-8 rounded-full shrink-0" }),
|
|
4842
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: `space-y-2 ${isUserRow ? "w-[70%]" : "w-[75%]"}`, children: [
|
|
4843
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Skeleton, { className: "h-4 w-24" }),
|
|
4844
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Skeleton, { className: "h-4 w-full" }),
|
|
4845
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Skeleton, { className: "h-4 w-[85%]" })
|
|
4201
4846
|
] }),
|
|
4202
|
-
isUserRow && /* @__PURE__ */ (0,
|
|
4847
|
+
isUserRow && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Skeleton, { className: "h-8 w-8 rounded-full shrink-0" })
|
|
4203
4848
|
]
|
|
4204
4849
|
},
|
|
4205
4850
|
`message-skeleton-${index}`
|
|
@@ -4255,8 +4900,8 @@ var ChatUI = ({
|
|
|
4255
4900
|
const shouldShowAgentSelector = Boolean(
|
|
4256
4901
|
config.agentSelector?.enabled && onSelectAgent && agentOptions.length > 0 && (!config.agentSelector?.hideIfSingle || agentOptions.length > 1)
|
|
4257
4902
|
);
|
|
4258
|
-
return /* @__PURE__ */ (0,
|
|
4259
|
-
/* @__PURE__ */ (0,
|
|
4903
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SidebarProvider, { defaultOpen: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: `flex h-[100svh] md:h-screen bg-background w-full overflow-hidden ${className}`, children: [
|
|
4904
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4260
4905
|
Sidebar2,
|
|
4261
4906
|
{
|
|
4262
4907
|
threads,
|
|
@@ -4273,8 +4918,8 @@ var ChatUI = ({
|
|
|
4273
4918
|
showThemeOptions: !!callbacks.onThemeChange
|
|
4274
4919
|
}
|
|
4275
4920
|
),
|
|
4276
|
-
/* @__PURE__ */ (0,
|
|
4277
|
-
/* @__PURE__ */ (0,
|
|
4921
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SidebarInset, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col h-full min-h-0", children: [
|
|
4922
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4278
4923
|
ChatHeader,
|
|
4279
4924
|
{
|
|
4280
4925
|
config,
|
|
@@ -4289,9 +4934,9 @@ var ChatUI = ({
|
|
|
4289
4934
|
onSelectAgent
|
|
4290
4935
|
}
|
|
4291
4936
|
),
|
|
4292
|
-
/* @__PURE__ */ (0,
|
|
4293
|
-
/* @__PURE__ */ (0,
|
|
4294
|
-
/* @__PURE__ */ (0,
|
|
4937
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-1 flex-row min-h-0 overflow-hidden", children: [
|
|
4938
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex-1 flex flex-col min-h-0", children: [
|
|
4939
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4295
4940
|
ScrollArea,
|
|
4296
4941
|
{
|
|
4297
4942
|
ref: scrollAreaRef,
|
|
@@ -4299,7 +4944,7 @@ var ChatUI = ({
|
|
|
4299
4944
|
viewportClassName: "p-4 overscroll-contain",
|
|
4300
4945
|
onScrollCapture: handleScroll,
|
|
4301
4946
|
style: { contain: "strict" },
|
|
4302
|
-
children: /* @__PURE__ */ (0,
|
|
4947
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "max-w-4xl mx-auto pb-4", children: isMessagesLoading ? renderMessageLoadingSkeleton() : messages.length === 0 ? renderSuggestions() : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4303
4948
|
"div",
|
|
4304
4949
|
{
|
|
4305
4950
|
style: {
|
|
@@ -4311,7 +4956,7 @@ var ChatUI = ({
|
|
|
4311
4956
|
const message = messages[virtualRow.index];
|
|
4312
4957
|
const prevMessage = virtualRow.index > 0 ? messages[virtualRow.index - 1] : null;
|
|
4313
4958
|
const isGrouped = prevMessage !== null && prevMessage.role === message.role;
|
|
4314
|
-
return /* @__PURE__ */ (0,
|
|
4959
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4315
4960
|
"div",
|
|
4316
4961
|
{
|
|
4317
4962
|
"data-index": virtualRow.index,
|
|
@@ -4323,8 +4968,8 @@ var ChatUI = ({
|
|
|
4323
4968
|
width: "100%",
|
|
4324
4969
|
transform: `translateY(${virtualRow.start}px)`
|
|
4325
4970
|
},
|
|
4326
|
-
children: /* @__PURE__ */ (0,
|
|
4327
|
-
/* @__PURE__ */ (0,
|
|
4971
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: virtualRow.index === 0 ? "" : isGrouped ? "pt-2" : "pt-4", children: [
|
|
4972
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4328
4973
|
Message,
|
|
4329
4974
|
{
|
|
4330
4975
|
message,
|
|
@@ -4343,7 +4988,7 @@ var ChatUI = ({
|
|
|
4343
4988
|
) })
|
|
4344
4989
|
}
|
|
4345
4990
|
),
|
|
4346
|
-
/* @__PURE__ */ (0,
|
|
4991
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "bg-background pb-[env(safe-area-inset-bottom)]", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4347
4992
|
ChatInput,
|
|
4348
4993
|
{
|
|
4349
4994
|
value: inputValue,
|
|
@@ -4369,17 +5014,17 @@ var ChatUI = ({
|
|
|
4369
5014
|
}
|
|
4370
5015
|
) })
|
|
4371
5016
|
] }),
|
|
4372
|
-
config?.customComponent?.component && !isMobile && /* @__PURE__ */ (0,
|
|
5017
|
+
config?.customComponent?.component && !isMobile && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4373
5018
|
"div",
|
|
4374
5019
|
{
|
|
4375
5020
|
className: `h-full transition-all duration-300 ease-in-out overflow-hidden ${state.showSidebar ? "w-80" : "w-0"}`,
|
|
4376
|
-
children: state.showSidebar && /* @__PURE__ */ (0,
|
|
5021
|
+
children: state.showSidebar && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex flex-col h-full border-l bg-background animate-in slide-in-from-right-4 duration-300 w-80", children: renderCustomComponent() })
|
|
4377
5022
|
}
|
|
4378
5023
|
)
|
|
4379
5024
|
] })
|
|
4380
5025
|
] }) }),
|
|
4381
|
-
isCustomMounted && config.customComponent?.component && isMobile && /* @__PURE__ */ (0,
|
|
4382
|
-
/* @__PURE__ */ (0,
|
|
5026
|
+
isCustomMounted && config.customComponent?.component && isMobile && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "fixed inset-0 z-50", children: [
|
|
5027
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4383
5028
|
"div",
|
|
4384
5029
|
{
|
|
4385
5030
|
className: `absolute inset-0 bg-background/80 backdrop-blur-sm transition-opacity duration-200 ease-out ${isCustomVisible ? "opacity-100" : "opacity-0"}`,
|
|
@@ -4387,16 +5032,16 @@ var ChatUI = ({
|
|
|
4387
5032
|
onClick: closeSidebar
|
|
4388
5033
|
}
|
|
4389
5034
|
),
|
|
4390
|
-
/* @__PURE__ */ (0,
|
|
5035
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4391
5036
|
"div",
|
|
4392
5037
|
{
|
|
4393
5038
|
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"}`,
|
|
4394
5039
|
style: { willChange: "transform" },
|
|
4395
|
-
children: /* @__PURE__ */ (0,
|
|
5040
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-full flex flex-col", children: renderCustomComponent() })
|
|
4396
5041
|
}
|
|
4397
5042
|
)
|
|
4398
5043
|
] }),
|
|
4399
|
-
isUserProfileOpen && /* @__PURE__ */ (0,
|
|
5044
|
+
isUserProfileOpen && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4400
5045
|
UserProfile,
|
|
4401
5046
|
{
|
|
4402
5047
|
isOpen: isUserProfileOpen,
|
|
@@ -4420,8 +5065,8 @@ var ChatUI = ({
|
|
|
4420
5065
|
|
|
4421
5066
|
// src/components/chat/ThreadManager.tsx
|
|
4422
5067
|
var import_react8 = require("react");
|
|
4423
|
-
var
|
|
4424
|
-
var
|
|
5068
|
+
var import_lucide_react13 = require("lucide-react");
|
|
5069
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
4425
5070
|
var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onArchive }) => {
|
|
4426
5071
|
const [isEditing, setIsEditing] = (0, import_react8.useState)(false);
|
|
4427
5072
|
const [editTitle, setEditTitle] = (0, import_react8.useState)(thread.title);
|
|
@@ -4450,9 +5095,9 @@ var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onAr
|
|
|
4450
5095
|
handleCancelEdit();
|
|
4451
5096
|
}
|
|
4452
5097
|
};
|
|
4453
|
-
return /* @__PURE__ */ (0,
|
|
4454
|
-
/* @__PURE__ */ (0,
|
|
4455
|
-
/* @__PURE__ */ (0,
|
|
5098
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(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__ */ (0, import_jsx_runtime26.jsx)(CardContent, { className: "p-3 max-w-sm", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-start justify-between gap-2", children: [
|
|
5099
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex-1 min-w-0", onClick: onSelect, children: isEditing ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
5100
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
4456
5101
|
Input,
|
|
4457
5102
|
{
|
|
4458
5103
|
ref: inputRef,
|
|
@@ -4464,44 +5109,44 @@ var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onAr
|
|
|
4464
5109
|
placeholder: config?.labels?.threadNamePlaceholder || "Conversation name"
|
|
4465
5110
|
}
|
|
4466
5111
|
),
|
|
4467
|
-
/* @__PURE__ */ (0,
|
|
4468
|
-
/* @__PURE__ */ (0,
|
|
4469
|
-
] }) : /* @__PURE__ */ (0,
|
|
4470
|
-
/* @__PURE__ */ (0,
|
|
4471
|
-
/* @__PURE__ */ (0,
|
|
4472
|
-
/* @__PURE__ */ (0,
|
|
4473
|
-
/* @__PURE__ */ (0,
|
|
5112
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button, { size: "sm", variant: "ghost", onClick: handleSaveEdit, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Check, { className: "h-3 w-3" }) }),
|
|
5113
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button, { size: "sm", variant: "ghost", onClick: handleCancelEdit, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.X, { className: "h-3 w-3" }) })
|
|
5114
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
|
|
5115
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h4", { className: "font-medium text-sm truncate mb-1", children: thread.title }),
|
|
5116
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
5117
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
5118
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Hash, { className: "h-3 w-3" }),
|
|
4474
5119
|
thread.messageCount,
|
|
4475
5120
|
" msgs"
|
|
4476
5121
|
] }),
|
|
4477
|
-
/* @__PURE__ */ (0,
|
|
4478
|
-
/* @__PURE__ */ (0,
|
|
4479
|
-
/* @__PURE__ */ (0,
|
|
5122
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Separator, { orientation: "vertical", className: "h-3" }),
|
|
5123
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
5124
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Calendar, { className: "h-3 w-3" }),
|
|
4480
5125
|
formatDate(thread.updatedAt, config?.labels)
|
|
4481
5126
|
] }),
|
|
4482
|
-
thread.isArchived && /* @__PURE__ */ (0,
|
|
4483
|
-
/* @__PURE__ */ (0,
|
|
4484
|
-
/* @__PURE__ */ (0,
|
|
4485
|
-
/* @__PURE__ */ (0,
|
|
5127
|
+
thread.isArchived && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
|
|
5128
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Separator, { orientation: "vertical", className: "h-3" }),
|
|
5129
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Badge, { variant: "secondary", className: "text-xs", children: [
|
|
5130
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Archive, { className: "h-2 w-2 mr-1" }),
|
|
4486
5131
|
config?.labels?.archiveThread || "Archived"
|
|
4487
5132
|
] })
|
|
4488
5133
|
] })
|
|
4489
5134
|
] })
|
|
4490
5135
|
] }) }),
|
|
4491
|
-
!isEditing && /* @__PURE__ */ (0,
|
|
4492
|
-
/* @__PURE__ */ (0,
|
|
4493
|
-
/* @__PURE__ */ (0,
|
|
4494
|
-
/* @__PURE__ */ (0,
|
|
4495
|
-
/* @__PURE__ */ (0,
|
|
5136
|
+
!isEditing && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenu, { children: [
|
|
5137
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button, { variant: "ghost", size: "icon", className: "h-6 w-6 m-auto", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.MoreVertical, { className: "h-3 w-3" }) }) }),
|
|
5138
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuContent, { align: "end", children: [
|
|
5139
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: () => setIsEditing(true), children: [
|
|
5140
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Edit2, { className: "h-4 w-4 mr-2" }),
|
|
4496
5141
|
config?.labels?.renameThread || "Rename"
|
|
4497
5142
|
] }),
|
|
4498
|
-
/* @__PURE__ */ (0,
|
|
4499
|
-
/* @__PURE__ */ (0,
|
|
5143
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: onArchive, children: [
|
|
5144
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Archive, { className: "h-4 w-4 mr-2" }),
|
|
4500
5145
|
thread.isArchived ? config?.labels?.unarchiveThread || "Unarchive" : config?.labels?.archiveThread || "Archive"
|
|
4501
5146
|
] }),
|
|
4502
|
-
/* @__PURE__ */ (0,
|
|
4503
|
-
/* @__PURE__ */ (0,
|
|
4504
|
-
/* @__PURE__ */ (0,
|
|
5147
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DropdownMenuSeparator, {}),
|
|
5148
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: onDelete, className: "text-destructive", children: [
|
|
5149
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Trash2, { className: "h-4 w-4 mr-2" }),
|
|
4505
5150
|
config?.labels?.deleteThread || "Delete"
|
|
4506
5151
|
] })
|
|
4507
5152
|
] })
|
|
@@ -4516,17 +5161,17 @@ var CreateThreadDialog2 = ({ onCreateThread, config }) => {
|
|
|
4516
5161
|
setTitle("");
|
|
4517
5162
|
setIsOpen(false);
|
|
4518
5163
|
};
|
|
4519
|
-
return /* @__PURE__ */ (0,
|
|
4520
|
-
/* @__PURE__ */ (0,
|
|
4521
|
-
/* @__PURE__ */ (0,
|
|
5164
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: [
|
|
5165
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DialogTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Button, { variant: "outline", className: "w-full", children: [
|
|
5166
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Plus, { className: "h-4 w-4 mr-2" }),
|
|
4522
5167
|
config?.labels?.createNewThread || "New Conversation"
|
|
4523
5168
|
] }) }),
|
|
4524
|
-
/* @__PURE__ */ (0,
|
|
4525
|
-
/* @__PURE__ */ (0,
|
|
4526
|
-
/* @__PURE__ */ (0,
|
|
4527
|
-
/* @__PURE__ */ (0,
|
|
5169
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DialogContent, { children: [
|
|
5170
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DialogHeader, { children: [
|
|
5171
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DialogTitle, { children: config?.labels?.createNewThread || "Create New Conversation" }),
|
|
5172
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DialogDescription, { children: "Give your new conversation a name or leave blank to auto-generate one." })
|
|
4528
5173
|
] }),
|
|
4529
|
-
/* @__PURE__ */ (0,
|
|
5174
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
4530
5175
|
Input,
|
|
4531
5176
|
{
|
|
4532
5177
|
value: title,
|
|
@@ -4536,9 +5181,9 @@ var CreateThreadDialog2 = ({ onCreateThread, config }) => {
|
|
|
4536
5181
|
autoFocus: true
|
|
4537
5182
|
}
|
|
4538
5183
|
),
|
|
4539
|
-
/* @__PURE__ */ (0,
|
|
4540
|
-
/* @__PURE__ */ (0,
|
|
4541
|
-
/* @__PURE__ */ (0,
|
|
5184
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DialogFooter, { children: [
|
|
5185
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button, { variant: "outline", onClick: () => setIsOpen(false), children: config?.labels?.cancel || "Cancel" }),
|
|
5186
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button, { onClick: handleCreate, children: config?.labels?.create || "Create" })
|
|
4542
5187
|
] })
|
|
4543
5188
|
] })
|
|
4544
5189
|
] });
|
|
@@ -4592,20 +5237,20 @@ var ThreadManager = ({
|
|
|
4592
5237
|
setDeleteThreadId(null);
|
|
4593
5238
|
};
|
|
4594
5239
|
if (!isOpen) return null;
|
|
4595
|
-
return /* @__PURE__ */ (0,
|
|
4596
|
-
/* @__PURE__ */ (0,
|
|
4597
|
-
/* @__PURE__ */ (0,
|
|
4598
|
-
/* @__PURE__ */ (0,
|
|
4599
|
-
/* @__PURE__ */ (0,
|
|
4600
|
-
/* @__PURE__ */ (0,
|
|
5240
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: `fixed inset-0 z-50 bg-background/80 backdrop-blur-sm ${className}`, children: [
|
|
5241
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "fixed left-0 top-0 h-full w-full max-w-md border-r bg-background shadow-lg", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Card, { className: "h-full border-0 rounded-none", children: [
|
|
5242
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardHeader, { className: "border-b", children: [
|
|
5243
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
5244
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardTitle, { className: "flex items-center gap-2", children: [
|
|
5245
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.MessageSquare, { className: "h-5 w-5" }),
|
|
4601
5246
|
config?.labels?.newChat || "Conversations"
|
|
4602
5247
|
] }),
|
|
4603
|
-
/* @__PURE__ */ (0,
|
|
5248
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button, { variant: "ghost", size: "icon", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.X, { className: "h-4 w-4" }) })
|
|
4604
5249
|
] }),
|
|
4605
|
-
/* @__PURE__ */ (0,
|
|
4606
|
-
/* @__PURE__ */ (0,
|
|
4607
|
-
/* @__PURE__ */ (0,
|
|
4608
|
-
/* @__PURE__ */ (0,
|
|
5250
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "space-y-3", children: [
|
|
5251
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "relative", children: [
|
|
5252
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
5253
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
4609
5254
|
Input,
|
|
4610
5255
|
{
|
|
4611
5256
|
placeholder: config?.labels?.search || "Search conversations...",
|
|
@@ -4615,8 +5260,8 @@ var ThreadManager = ({
|
|
|
4615
5260
|
}
|
|
4616
5261
|
)
|
|
4617
5262
|
] }),
|
|
4618
|
-
/* @__PURE__ */ (0,
|
|
4619
|
-
/* @__PURE__ */ (0,
|
|
5263
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
5264
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
4620
5265
|
Button,
|
|
4621
5266
|
{
|
|
4622
5267
|
variant: "outline",
|
|
@@ -4624,12 +5269,12 @@ var ThreadManager = ({
|
|
|
4624
5269
|
onClick: () => setShowArchived(!showArchived),
|
|
4625
5270
|
className: "text-xs",
|
|
4626
5271
|
children: [
|
|
4627
|
-
/* @__PURE__ */ (0,
|
|
5272
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Filter, { className: "h-3 w-3 mr-1" }),
|
|
4628
5273
|
showArchived ? config?.labels?.hideArchived || "Hide Archived" : config?.labels?.showArchived || "Show Archived"
|
|
4629
5274
|
]
|
|
4630
5275
|
}
|
|
4631
5276
|
),
|
|
4632
|
-
/* @__PURE__ */ (0,
|
|
5277
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Badge, { variant: "secondary", className: "text-xs", children: [
|
|
4633
5278
|
filteredThreads.length,
|
|
4634
5279
|
" / ",
|
|
4635
5280
|
threads.length
|
|
@@ -4637,14 +5282,14 @@ var ThreadManager = ({
|
|
|
4637
5282
|
] })
|
|
4638
5283
|
] })
|
|
4639
5284
|
] }),
|
|
4640
|
-
/* @__PURE__ */ (0,
|
|
4641
|
-
/* @__PURE__ */ (0,
|
|
4642
|
-
/* @__PURE__ */ (0,
|
|
4643
|
-
/* @__PURE__ */ (0,
|
|
4644
|
-
/* @__PURE__ */ (0,
|
|
4645
|
-
] }) : Object.entries(groupedThreads).map(([group, groupThreads]) => /* @__PURE__ */ (0,
|
|
4646
|
-
/* @__PURE__ */ (0,
|
|
4647
|
-
/* @__PURE__ */ (0,
|
|
5285
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardContent, { className: "p-0 flex-1", children: [
|
|
5286
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "p-4", children: onCreateThread && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CreateThreadDialog2, { onCreateThread, config }) }),
|
|
5287
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ScrollArea, { className: "h-[calc(100vh-280px)]", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "px-4 pb-4 space-y-4", children: Object.keys(groupedThreads).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "text-center py-8 text-muted-foreground", children: [
|
|
5288
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.MessageSquare, { className: "h-12 w-12 mx-auto mb-3 opacity-50" }),
|
|
5289
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-sm", children: searchQuery ? config?.labels?.noThreadsFound || "No conversations found" : config?.labels?.noThreadsYet || "No conversations yet" })
|
|
5290
|
+
] }) : Object.entries(groupedThreads).map(([group, groupThreads]) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { children: [
|
|
5291
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h3", { className: "text-sm font-medium text-muted-foreground mb-2 px-2", children: group }),
|
|
5292
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "space-y-2", children: groupThreads.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
4648
5293
|
ThreadItem,
|
|
4649
5294
|
{
|
|
4650
5295
|
thread,
|
|
@@ -4660,14 +5305,14 @@ var ThreadManager = ({
|
|
|
4660
5305
|
] }, group)) }) })
|
|
4661
5306
|
] })
|
|
4662
5307
|
] }) }),
|
|
4663
|
-
deleteThreadId && /* @__PURE__ */ (0,
|
|
4664
|
-
/* @__PURE__ */ (0,
|
|
4665
|
-
/* @__PURE__ */ (0,
|
|
4666
|
-
/* @__PURE__ */ (0,
|
|
5308
|
+
deleteThreadId && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(AlertDialogContent, { children: [
|
|
5309
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(AlertDialogHeader, { children: [
|
|
5310
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AlertDialogTitle, { children: config?.labels?.deleteConfirmTitle || "Delete Conversation" }),
|
|
5311
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AlertDialogDescription, { children: config?.labels?.deleteConfirmDescription || "Are you sure you want to delete this conversation? This action cannot be undone." })
|
|
4667
5312
|
] }),
|
|
4668
|
-
/* @__PURE__ */ (0,
|
|
4669
|
-
/* @__PURE__ */ (0,
|
|
4670
|
-
/* @__PURE__ */ (0,
|
|
5313
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(AlertDialogFooter, { children: [
|
|
5314
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AlertDialogCancel, { children: config?.labels?.cancel || "Cancel" }),
|
|
5315
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
4671
5316
|
AlertDialogAction,
|
|
4672
5317
|
{
|
|
4673
5318
|
onClick: () => deleteThreadId && handleDeleteThread(deleteThreadId),
|