@copilotz/chat-ui 0.1.31 → 0.1.32
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 +895 -291
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +59 -1
- package/dist/index.d.ts +59 -1
- package/dist/index.js +898 -294
- package/dist/index.js.map +1 -1
- package/dist/styles.css +21 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30,6 +30,23 @@ var defaultChatConfig = {
|
|
|
30
30
|
attachFileTooltip: "Attach file",
|
|
31
31
|
recordAudio: "Record Audio",
|
|
32
32
|
recordAudioTooltip: "Record audio",
|
|
33
|
+
voiceEnter: "Voice input",
|
|
34
|
+
voiceExit: "Use keyboard",
|
|
35
|
+
voiceTitle: "Voice input",
|
|
36
|
+
voicePreparing: "Preparing microphone...",
|
|
37
|
+
voiceWaiting: "Waiting for speech...",
|
|
38
|
+
voiceListening: "Listening...",
|
|
39
|
+
voiceFinishing: "Finishing capture...",
|
|
40
|
+
voiceReview: "Ready to send",
|
|
41
|
+
voiceStart: "Start recording",
|
|
42
|
+
voiceStop: "Stop recording",
|
|
43
|
+
voiceSendNow: "Send now",
|
|
44
|
+
voiceCancel: "Cancel",
|
|
45
|
+
voiceRecordAgain: "Record again",
|
|
46
|
+
voiceAutoSendIn: "Auto-sends in {{seconds}}s",
|
|
47
|
+
voiceTranscriptPending: "Transcript unavailable",
|
|
48
|
+
voicePermissionDenied: "Microphone access was denied.",
|
|
49
|
+
voiceCaptureError: "Unable to capture audio.",
|
|
33
50
|
// Header labels
|
|
34
51
|
exportData: "Export data",
|
|
35
52
|
importData: "Import data",
|
|
@@ -92,6 +109,15 @@ var defaultChatConfig = {
|
|
|
92
109
|
longMessageChunkChars: 12e3,
|
|
93
110
|
renderUserMarkdown: true
|
|
94
111
|
},
|
|
112
|
+
voiceCompose: {
|
|
113
|
+
enabled: false,
|
|
114
|
+
autoSendDelayMs: 5e3,
|
|
115
|
+
persistComposer: true,
|
|
116
|
+
showTranscriptPreview: true,
|
|
117
|
+
transcriptMode: "final-only",
|
|
118
|
+
maxRecordingMs: 6e4,
|
|
119
|
+
createProvider: void 0
|
|
120
|
+
},
|
|
95
121
|
customComponent: {},
|
|
96
122
|
headerActions: null
|
|
97
123
|
};
|
|
@@ -114,6 +140,10 @@ function mergeConfig(_baseConfig, userConfig) {
|
|
|
114
140
|
...defaultChatConfig.ui,
|
|
115
141
|
...userConfig.ui
|
|
116
142
|
},
|
|
143
|
+
voiceCompose: {
|
|
144
|
+
...defaultChatConfig.voiceCompose,
|
|
145
|
+
...userConfig.voiceCompose
|
|
146
|
+
},
|
|
117
147
|
agentSelector: {
|
|
118
148
|
...defaultChatConfig.agentSelector,
|
|
119
149
|
...userConfig.agentSelector
|
|
@@ -732,7 +762,7 @@ var MediaRenderer = memo(function MediaRenderer2({ attachment }) {
|
|
|
732
762
|
URL.revokeObjectURL(objectUrl);
|
|
733
763
|
};
|
|
734
764
|
}, [attachment.kind, attachment.dataUrl]);
|
|
735
|
-
const
|
|
765
|
+
const formatDuration2 = (ms) => {
|
|
736
766
|
if (!ms) return "";
|
|
737
767
|
const seconds = Math.floor(ms / 1e3);
|
|
738
768
|
const minutes = Math.floor(seconds / 60);
|
|
@@ -2794,6 +2824,215 @@ function useChatUserContext() {
|
|
|
2794
2824
|
return v;
|
|
2795
2825
|
}
|
|
2796
2826
|
|
|
2827
|
+
// src/lib/voiceCompose.ts
|
|
2828
|
+
var AUDIO_MIME_TYPES = [
|
|
2829
|
+
"audio/webm;codecs=opus",
|
|
2830
|
+
"audio/webm",
|
|
2831
|
+
"audio/mp4",
|
|
2832
|
+
"audio/ogg;codecs=opus"
|
|
2833
|
+
];
|
|
2834
|
+
var pickRecorderMimeType = () => {
|
|
2835
|
+
if (typeof MediaRecorder === "undefined") return void 0;
|
|
2836
|
+
for (const mimeType of AUDIO_MIME_TYPES) {
|
|
2837
|
+
if (typeof MediaRecorder.isTypeSupported === "function" && MediaRecorder.isTypeSupported(mimeType)) {
|
|
2838
|
+
return mimeType;
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2841
|
+
return void 0;
|
|
2842
|
+
};
|
|
2843
|
+
var blobToDataUrl = (blob) => new Promise((resolve, reject) => {
|
|
2844
|
+
const reader = new FileReader();
|
|
2845
|
+
reader.onload = () => resolve(reader.result);
|
|
2846
|
+
reader.onerror = () => reject(reader.error ?? new Error("Failed to read recorded audio"));
|
|
2847
|
+
reader.readAsDataURL(blob);
|
|
2848
|
+
});
|
|
2849
|
+
var stopStream = (stream) => {
|
|
2850
|
+
if (!stream) return;
|
|
2851
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
2852
|
+
};
|
|
2853
|
+
var closeAudioContext = async (audioContext) => {
|
|
2854
|
+
if (!audioContext) return;
|
|
2855
|
+
try {
|
|
2856
|
+
await audioContext.close();
|
|
2857
|
+
} catch {
|
|
2858
|
+
}
|
|
2859
|
+
};
|
|
2860
|
+
var emitDuration = (handlers, startedAt) => {
|
|
2861
|
+
handlers.onDurationChange?.(Math.max(0, Date.now() - startedAt));
|
|
2862
|
+
};
|
|
2863
|
+
var createManualVoiceProvider = async (handlers, options = {}) => {
|
|
2864
|
+
let mediaRecorder = null;
|
|
2865
|
+
let mediaStream = null;
|
|
2866
|
+
let audioContext = null;
|
|
2867
|
+
let analyser = null;
|
|
2868
|
+
let levelData = null;
|
|
2869
|
+
let levelFrame = 0;
|
|
2870
|
+
let durationTimer = null;
|
|
2871
|
+
let maxDurationTimer = null;
|
|
2872
|
+
let startedAt = 0;
|
|
2873
|
+
let shouldEmitSegment = true;
|
|
2874
|
+
let isStarting = false;
|
|
2875
|
+
const clearTimers = () => {
|
|
2876
|
+
if (durationTimer) {
|
|
2877
|
+
clearInterval(durationTimer);
|
|
2878
|
+
durationTimer = null;
|
|
2879
|
+
}
|
|
2880
|
+
if (maxDurationTimer) {
|
|
2881
|
+
clearTimeout(maxDurationTimer);
|
|
2882
|
+
maxDurationTimer = null;
|
|
2883
|
+
}
|
|
2884
|
+
};
|
|
2885
|
+
const stopLevelLoop = () => {
|
|
2886
|
+
if (levelFrame) {
|
|
2887
|
+
cancelAnimationFrame(levelFrame);
|
|
2888
|
+
levelFrame = 0;
|
|
2889
|
+
}
|
|
2890
|
+
handlers.onAudioLevelChange?.(0);
|
|
2891
|
+
};
|
|
2892
|
+
const startLevelLoop = () => {
|
|
2893
|
+
if (!analyser || !levelData) return;
|
|
2894
|
+
const tick = () => {
|
|
2895
|
+
if (!analyser || !levelData) return;
|
|
2896
|
+
analyser.getByteTimeDomainData(levelData);
|
|
2897
|
+
let sum = 0;
|
|
2898
|
+
for (let index = 0; index < levelData.length; index += 1) {
|
|
2899
|
+
const centered = (levelData[index] - 128) / 128;
|
|
2900
|
+
sum += centered * centered;
|
|
2901
|
+
}
|
|
2902
|
+
const rms = Math.sqrt(sum / levelData.length);
|
|
2903
|
+
handlers.onAudioLevelChange?.(Math.min(1, rms * 4));
|
|
2904
|
+
levelFrame = requestAnimationFrame(tick);
|
|
2905
|
+
};
|
|
2906
|
+
tick();
|
|
2907
|
+
};
|
|
2908
|
+
const cleanupActiveResources = async () => {
|
|
2909
|
+
clearTimers();
|
|
2910
|
+
stopLevelLoop();
|
|
2911
|
+
stopStream(mediaStream);
|
|
2912
|
+
mediaStream = null;
|
|
2913
|
+
analyser = null;
|
|
2914
|
+
levelData = null;
|
|
2915
|
+
await closeAudioContext(audioContext);
|
|
2916
|
+
audioContext = null;
|
|
2917
|
+
};
|
|
2918
|
+
const finalizeStop = async () => {
|
|
2919
|
+
mediaRecorder = null;
|
|
2920
|
+
isStarting = false;
|
|
2921
|
+
await cleanupActiveResources();
|
|
2922
|
+
};
|
|
2923
|
+
const start = async () => {
|
|
2924
|
+
if (isStarting || mediaRecorder?.state === "recording") {
|
|
2925
|
+
return;
|
|
2926
|
+
}
|
|
2927
|
+
if (!navigator.mediaDevices?.getUserMedia) {
|
|
2928
|
+
throw new Error("Audio capture is not supported in this browser");
|
|
2929
|
+
}
|
|
2930
|
+
if (typeof MediaRecorder === "undefined") {
|
|
2931
|
+
throw new Error("MediaRecorder is not supported in this browser");
|
|
2932
|
+
}
|
|
2933
|
+
isStarting = true;
|
|
2934
|
+
shouldEmitSegment = true;
|
|
2935
|
+
handlers.onTranscriptChange?.({});
|
|
2936
|
+
handlers.onDurationChange?.(0);
|
|
2937
|
+
handlers.onAudioLevelChange?.(0);
|
|
2938
|
+
handlers.onStateChange?.("preparing");
|
|
2939
|
+
try {
|
|
2940
|
+
mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
2941
|
+
const mimeType = pickRecorderMimeType();
|
|
2942
|
+
mediaRecorder = mimeType ? new MediaRecorder(mediaStream, { mimeType }) : new MediaRecorder(mediaStream);
|
|
2943
|
+
const chunks = [];
|
|
2944
|
+
mediaRecorder.ondataavailable = (event) => {
|
|
2945
|
+
if (event.data.size > 0) {
|
|
2946
|
+
chunks.push(event.data);
|
|
2947
|
+
}
|
|
2948
|
+
};
|
|
2949
|
+
mediaRecorder.onerror = (event) => {
|
|
2950
|
+
const error = event.error ?? new Error("Audio recorder failed");
|
|
2951
|
+
handlers.onError?.(error);
|
|
2952
|
+
};
|
|
2953
|
+
mediaRecorder.onstop = async () => {
|
|
2954
|
+
const durationMs = startedAt > 0 ? Math.max(0, Date.now() - startedAt) : 0;
|
|
2955
|
+
try {
|
|
2956
|
+
if (shouldEmitSegment && chunks.length > 0) {
|
|
2957
|
+
const blob = new Blob(chunks, {
|
|
2958
|
+
type: mediaRecorder?.mimeType || mimeType || "audio/webm"
|
|
2959
|
+
});
|
|
2960
|
+
const dataUrl = await blobToDataUrl(blob);
|
|
2961
|
+
handlers.onSegmentReady?.({
|
|
2962
|
+
attachment: {
|
|
2963
|
+
kind: "audio",
|
|
2964
|
+
dataUrl,
|
|
2965
|
+
mimeType: blob.type || "audio/webm",
|
|
2966
|
+
durationMs,
|
|
2967
|
+
fileName: `voice-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.webm`,
|
|
2968
|
+
size: blob.size
|
|
2969
|
+
},
|
|
2970
|
+
metadata: { source: "manual" }
|
|
2971
|
+
});
|
|
2972
|
+
} else {
|
|
2973
|
+
handlers.onStateChange?.("idle");
|
|
2974
|
+
}
|
|
2975
|
+
} catch (error) {
|
|
2976
|
+
handlers.onError?.(error);
|
|
2977
|
+
} finally {
|
|
2978
|
+
await finalizeStop();
|
|
2979
|
+
}
|
|
2980
|
+
};
|
|
2981
|
+
const AudioContextCtor = globalThis.AudioContext || globalThis.webkitAudioContext;
|
|
2982
|
+
if (AudioContextCtor) {
|
|
2983
|
+
audioContext = new AudioContextCtor();
|
|
2984
|
+
await audioContext.resume().catch(() => void 0);
|
|
2985
|
+
const sourceNode = audioContext.createMediaStreamSource(mediaStream);
|
|
2986
|
+
analyser = audioContext.createAnalyser();
|
|
2987
|
+
analyser.fftSize = 1024;
|
|
2988
|
+
levelData = new Uint8Array(analyser.fftSize);
|
|
2989
|
+
sourceNode.connect(analyser);
|
|
2990
|
+
startLevelLoop();
|
|
2991
|
+
}
|
|
2992
|
+
startedAt = Date.now();
|
|
2993
|
+
emitDuration(handlers, startedAt);
|
|
2994
|
+
durationTimer = setInterval(() => emitDuration(handlers, startedAt), 200);
|
|
2995
|
+
if (options.maxRecordingMs && options.maxRecordingMs > 0) {
|
|
2996
|
+
maxDurationTimer = setTimeout(() => {
|
|
2997
|
+
void stop();
|
|
2998
|
+
}, options.maxRecordingMs);
|
|
2999
|
+
}
|
|
3000
|
+
mediaRecorder.start();
|
|
3001
|
+
handlers.onStateChange?.("listening");
|
|
3002
|
+
} catch (error) {
|
|
3003
|
+
isStarting = false;
|
|
3004
|
+
await cleanupActiveResources();
|
|
3005
|
+
throw error;
|
|
3006
|
+
}
|
|
3007
|
+
};
|
|
3008
|
+
const stop = async () => {
|
|
3009
|
+
if (!mediaRecorder || mediaRecorder.state === "inactive") {
|
|
3010
|
+
return;
|
|
3011
|
+
}
|
|
3012
|
+
handlers.onStateChange?.("finishing");
|
|
3013
|
+
mediaRecorder.stop();
|
|
3014
|
+
};
|
|
3015
|
+
const cancel = async () => {
|
|
3016
|
+
shouldEmitSegment = false;
|
|
3017
|
+
if (mediaRecorder && mediaRecorder.state !== "inactive") {
|
|
3018
|
+
mediaRecorder.stop();
|
|
3019
|
+
return;
|
|
3020
|
+
}
|
|
3021
|
+
await finalizeStop();
|
|
3022
|
+
handlers.onStateChange?.("idle");
|
|
3023
|
+
};
|
|
3024
|
+
const destroy = async () => {
|
|
3025
|
+
await cancel();
|
|
3026
|
+
};
|
|
3027
|
+
return {
|
|
3028
|
+
start,
|
|
3029
|
+
stop,
|
|
3030
|
+
cancel,
|
|
3031
|
+
destroy
|
|
3032
|
+
};
|
|
3033
|
+
};
|
|
3034
|
+
var resolveVoiceProviderFactory = (createProvider) => createProvider ?? createManualVoiceProvider;
|
|
3035
|
+
|
|
2797
3036
|
// src/components/ui/progress.tsx
|
|
2798
3037
|
import * as ProgressPrimitive from "@radix-ui/react-progress";
|
|
2799
3038
|
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
@@ -2823,21 +3062,174 @@ function Progress({
|
|
|
2823
3062
|
);
|
|
2824
3063
|
}
|
|
2825
3064
|
|
|
3065
|
+
// src/components/chat/VoiceComposer.tsx
|
|
3066
|
+
import { Keyboard, Loader2, Mic, RotateCcw as RotateCcw2, Send, Square, X as X2 } from "lucide-react";
|
|
3067
|
+
import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3068
|
+
var formatDuration = (durationMs) => {
|
|
3069
|
+
const totalSeconds = Math.max(0, Math.floor(durationMs / 1e3));
|
|
3070
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
3071
|
+
const seconds = totalSeconds % 60;
|
|
3072
|
+
return `${minutes}:${seconds.toString().padStart(2, "0")}`;
|
|
3073
|
+
};
|
|
3074
|
+
var interpolateSeconds = (label, seconds) => {
|
|
3075
|
+
if (!label) {
|
|
3076
|
+
return `Auto-sends in ${seconds}s`;
|
|
3077
|
+
}
|
|
3078
|
+
if (label.includes("{{seconds}}")) {
|
|
3079
|
+
return label.replace(/\{\{\s*seconds\s*\}\}/g, String(seconds));
|
|
3080
|
+
}
|
|
3081
|
+
return `${label} ${seconds}s`;
|
|
3082
|
+
};
|
|
3083
|
+
var resolveStateLabel = (state, labels, errorMessage) => {
|
|
3084
|
+
switch (state) {
|
|
3085
|
+
case "preparing":
|
|
3086
|
+
return labels?.voicePreparing || "Preparing microphone...";
|
|
3087
|
+
case "waiting_for_speech":
|
|
3088
|
+
return labels?.voiceWaiting || "Waiting for speech...";
|
|
3089
|
+
case "listening":
|
|
3090
|
+
return labels?.voiceListening || "Listening...";
|
|
3091
|
+
case "finishing":
|
|
3092
|
+
return labels?.voiceFinishing || "Finishing capture...";
|
|
3093
|
+
case "review":
|
|
3094
|
+
return labels?.voiceReview || "Ready to send";
|
|
3095
|
+
case "sending":
|
|
3096
|
+
return "Sending...";
|
|
3097
|
+
case "error":
|
|
3098
|
+
return errorMessage || labels?.voiceCaptureError || "Unable to capture audio.";
|
|
3099
|
+
case "idle":
|
|
3100
|
+
default:
|
|
3101
|
+
return labels?.voiceTitle || "Voice input";
|
|
3102
|
+
}
|
|
3103
|
+
};
|
|
3104
|
+
var resolveTranscriptText = (transcript, transcriptMode) => {
|
|
3105
|
+
if (transcriptMode === "none" || !transcript) {
|
|
3106
|
+
return null;
|
|
3107
|
+
}
|
|
3108
|
+
if (transcriptMode === "final-only") {
|
|
3109
|
+
return transcript.final?.trim() || null;
|
|
3110
|
+
}
|
|
3111
|
+
return transcript.final?.trim() || transcript.partial?.trim() || null;
|
|
3112
|
+
};
|
|
3113
|
+
var VoiceComposer = ({
|
|
3114
|
+
state,
|
|
3115
|
+
transcript,
|
|
3116
|
+
transcriptMode,
|
|
3117
|
+
showTranscriptPreview,
|
|
3118
|
+
durationMs,
|
|
3119
|
+
audioLevel,
|
|
3120
|
+
countdownMs,
|
|
3121
|
+
autoSendDelayMs,
|
|
3122
|
+
errorMessage,
|
|
3123
|
+
disabled = false,
|
|
3124
|
+
labels,
|
|
3125
|
+
onStart,
|
|
3126
|
+
onStop,
|
|
3127
|
+
onCancel,
|
|
3128
|
+
onSendNow,
|
|
3129
|
+
onRecordAgain,
|
|
3130
|
+
onExit
|
|
3131
|
+
}) => {
|
|
3132
|
+
const transcriptText = resolveTranscriptText(transcript, transcriptMode);
|
|
3133
|
+
const countdownSeconds = Math.max(1, Math.ceil(countdownMs / 1e3));
|
|
3134
|
+
const countdownValue = autoSendDelayMs > 0 ? Math.min(100, Math.max(0, (autoSendDelayMs - countdownMs) / autoSendDelayMs * 100)) : 100;
|
|
3135
|
+
const isBusy = state === "preparing" || state === "finishing" || state === "sending";
|
|
3136
|
+
const isCapturing = state === "waiting_for_speech" || state === "listening";
|
|
3137
|
+
const levelValue = isCapturing || state === "preparing" || state === "finishing" ? Math.max(8, Math.round(audioLevel * 100)) : 0;
|
|
3138
|
+
return /* @__PURE__ */ jsxs11("div", { className: "w-full md:min-w-3xl max-w-3xl rounded-xl border bg-background p-4 shadow-sm", children: [
|
|
3139
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between gap-3", children: [
|
|
3140
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
|
|
3141
|
+
/* @__PURE__ */ jsx21(Badge, { variant: "outline", children: labels?.voiceTitle || "Voice input" }),
|
|
3142
|
+
/* @__PURE__ */ jsx21("span", { className: "text-sm text-muted-foreground", children: resolveStateLabel(state, labels, errorMessage) })
|
|
3143
|
+
] }),
|
|
3144
|
+
/* @__PURE__ */ jsxs11(
|
|
3145
|
+
Button,
|
|
3146
|
+
{
|
|
3147
|
+
type: "button",
|
|
3148
|
+
variant: "ghost",
|
|
3149
|
+
size: "sm",
|
|
3150
|
+
onClick: onExit,
|
|
3151
|
+
disabled: disabled || isBusy,
|
|
3152
|
+
children: [
|
|
3153
|
+
/* @__PURE__ */ jsx21(Keyboard, { className: "h-4 w-4" }),
|
|
3154
|
+
labels?.voiceExit || "Use keyboard"
|
|
3155
|
+
]
|
|
3156
|
+
}
|
|
3157
|
+
)
|
|
3158
|
+
] }),
|
|
3159
|
+
/* @__PURE__ */ jsxs11("div", { className: "mt-4 flex flex-col items-center gap-4 rounded-xl border border-dashed border-primary/30 bg-primary/5 px-4 py-6 text-center", children: [
|
|
3160
|
+
/* @__PURE__ */ jsx21("div", { className: "flex h-20 w-20 items-center justify-center rounded-full bg-primary/10", children: isBusy ? /* @__PURE__ */ jsx21(Loader2, { className: "h-8 w-8 animate-spin text-primary" }) : isCapturing ? /* @__PURE__ */ jsx21(Square, { className: "h-8 w-8 text-primary" }) : /* @__PURE__ */ jsx21(Mic, { className: "h-8 w-8 text-primary" }) }),
|
|
3161
|
+
/* @__PURE__ */ jsxs11("div", { className: "w-full max-w-md space-y-2", children: [
|
|
3162
|
+
/* @__PURE__ */ jsx21(Progress, { value: levelValue, className: "h-2" }),
|
|
3163
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
|
|
3164
|
+
/* @__PURE__ */ jsx21("span", { children: formatDuration(durationMs) }),
|
|
3165
|
+
/* @__PURE__ */ jsx21("span", { children: resolveStateLabel(state, labels, errorMessage) })
|
|
3166
|
+
] })
|
|
3167
|
+
] }),
|
|
3168
|
+
showTranscriptPreview && transcriptMode !== "none" && transcriptText && /* @__PURE__ */ jsx21("div", { className: "w-full max-w-md rounded-lg border bg-background px-3 py-2 text-left text-sm", children: transcriptText })
|
|
3169
|
+
] }),
|
|
3170
|
+
state === "review" && autoSendDelayMs > 0 && /* @__PURE__ */ jsxs11("div", { className: "mt-4 space-y-2", children: [
|
|
3171
|
+
/* @__PURE__ */ jsx21(Progress, { value: countdownValue, className: "h-2" }),
|
|
3172
|
+
/* @__PURE__ */ jsx21("div", { className: "text-center text-xs text-muted-foreground", children: interpolateSeconds(labels?.voiceAutoSendIn, countdownSeconds) })
|
|
3173
|
+
] }),
|
|
3174
|
+
state === "error" && errorMessage && /* @__PURE__ */ jsx21("div", { className: "mt-4 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2 text-sm text-destructive", children: errorMessage }),
|
|
3175
|
+
/* @__PURE__ */ jsxs11("div", { className: "mt-4 flex flex-wrap items-center justify-center gap-2", children: [
|
|
3176
|
+
state === "idle" && /* @__PURE__ */ jsxs11(Button, { type: "button", onClick: onStart, disabled, children: [
|
|
3177
|
+
/* @__PURE__ */ jsx21(Mic, { className: "h-4 w-4" }),
|
|
3178
|
+
labels?.voiceStart || "Start recording"
|
|
3179
|
+
] }),
|
|
3180
|
+
isCapturing && /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
3181
|
+
/* @__PURE__ */ jsxs11(Button, { type: "button", onClick: onStop, disabled, children: [
|
|
3182
|
+
/* @__PURE__ */ jsx21(Square, { className: "h-4 w-4" }),
|
|
3183
|
+
labels?.voiceStop || "Stop recording"
|
|
3184
|
+
] }),
|
|
3185
|
+
/* @__PURE__ */ jsxs11(Button, { type: "button", variant: "outline", onClick: onCancel, disabled, children: [
|
|
3186
|
+
/* @__PURE__ */ jsx21(X2, { className: "h-4 w-4" }),
|
|
3187
|
+
labels?.voiceCancel || "Cancel"
|
|
3188
|
+
] })
|
|
3189
|
+
] }),
|
|
3190
|
+
state === "review" && /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
3191
|
+
/* @__PURE__ */ jsxs11(Button, { type: "button", variant: "outline", onClick: onCancel, disabled, children: [
|
|
3192
|
+
/* @__PURE__ */ jsx21(X2, { className: "h-4 w-4" }),
|
|
3193
|
+
labels?.voiceCancel || "Cancel"
|
|
3194
|
+
] }),
|
|
3195
|
+
/* @__PURE__ */ jsxs11(Button, { type: "button", variant: "outline", onClick: onRecordAgain, disabled, children: [
|
|
3196
|
+
/* @__PURE__ */ jsx21(RotateCcw2, { className: "h-4 w-4" }),
|
|
3197
|
+
labels?.voiceRecordAgain || "Record again"
|
|
3198
|
+
] }),
|
|
3199
|
+
/* @__PURE__ */ jsxs11(Button, { type: "button", onClick: onSendNow, disabled, children: [
|
|
3200
|
+
/* @__PURE__ */ jsx21(Send, { className: "h-4 w-4" }),
|
|
3201
|
+
labels?.voiceSendNow || "Send now"
|
|
3202
|
+
] })
|
|
3203
|
+
] }),
|
|
3204
|
+
state === "error" && /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
3205
|
+
/* @__PURE__ */ jsxs11(Button, { type: "button", variant: "outline", onClick: onCancel, disabled, children: [
|
|
3206
|
+
/* @__PURE__ */ jsx21(X2, { className: "h-4 w-4" }),
|
|
3207
|
+
labels?.voiceCancel || "Cancel"
|
|
3208
|
+
] }),
|
|
3209
|
+
/* @__PURE__ */ jsxs11(Button, { type: "button", onClick: onRecordAgain, disabled, children: [
|
|
3210
|
+
/* @__PURE__ */ jsx21(RotateCcw2, { className: "h-4 w-4" }),
|
|
3211
|
+
labels?.voiceRecordAgain || "Record again"
|
|
3212
|
+
] })
|
|
3213
|
+
] })
|
|
3214
|
+
] })
|
|
3215
|
+
] });
|
|
3216
|
+
};
|
|
3217
|
+
|
|
2826
3218
|
// src/components/chat/ChatInput.tsx
|
|
2827
3219
|
import {
|
|
2828
|
-
Send,
|
|
3220
|
+
Send as Send2,
|
|
2829
3221
|
Paperclip,
|
|
2830
|
-
Mic,
|
|
3222
|
+
Mic as Mic2,
|
|
2831
3223
|
Image as Image2,
|
|
2832
3224
|
Video,
|
|
2833
3225
|
FileText,
|
|
2834
|
-
X as
|
|
2835
|
-
Square,
|
|
3226
|
+
X as X3,
|
|
3227
|
+
Square as Square2,
|
|
2836
3228
|
Play,
|
|
2837
3229
|
Pause,
|
|
2838
|
-
Loader2
|
|
3230
|
+
Loader2 as Loader22
|
|
2839
3231
|
} from "lucide-react";
|
|
2840
|
-
import { Fragment as
|
|
3232
|
+
import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2841
3233
|
var FileUploadItem = memo2(function FileUploadItem2({ file, progress, onCancel }) {
|
|
2842
3234
|
const guessTypeFromName = (name) => {
|
|
2843
3235
|
const ext = (name || "").split(".").pop()?.toLowerCase();
|
|
@@ -2866,10 +3258,10 @@ var FileUploadItem = memo2(function FileUploadItem2({ file, progress, onCancel }
|
|
|
2866
3258
|
};
|
|
2867
3259
|
const getFileIcon = (type, name) => {
|
|
2868
3260
|
const t = typeof type === "string" && type.length > 0 ? type : guessTypeFromName(name);
|
|
2869
|
-
if (t.startsWith("image/")) return /* @__PURE__ */
|
|
2870
|
-
if (t.startsWith("video/")) return /* @__PURE__ */
|
|
2871
|
-
if (t.startsWith("audio/")) return /* @__PURE__ */
|
|
2872
|
-
return /* @__PURE__ */
|
|
3261
|
+
if (t.startsWith("image/")) return /* @__PURE__ */ jsx22(Image2, { className: "h-4 w-4" });
|
|
3262
|
+
if (t.startsWith("video/")) return /* @__PURE__ */ jsx22(Video, { className: "h-4 w-4" });
|
|
3263
|
+
if (t.startsWith("audio/")) return /* @__PURE__ */ jsx22(Mic2, { className: "h-4 w-4" });
|
|
3264
|
+
return /* @__PURE__ */ jsx22(FileText, { className: "h-4 w-4" });
|
|
2873
3265
|
};
|
|
2874
3266
|
const formatFileSize = (bytes) => {
|
|
2875
3267
|
if (bytes === 0) return "0 Bytes";
|
|
@@ -2878,21 +3270,21 @@ var FileUploadItem = memo2(function FileUploadItem2({ file, progress, onCancel }
|
|
|
2878
3270
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
2879
3271
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
|
2880
3272
|
};
|
|
2881
|
-
return /* @__PURE__ */
|
|
3273
|
+
return /* @__PURE__ */ jsx22(Card, { className: "relative", children: /* @__PURE__ */ jsx22(CardContent, { className: "p-3", children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
|
|
2882
3274
|
getFileIcon(file.type, file.name),
|
|
2883
|
-
/* @__PURE__ */
|
|
2884
|
-
/* @__PURE__ */
|
|
2885
|
-
/* @__PURE__ */
|
|
2886
|
-
/* @__PURE__ */
|
|
3275
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex-1 min-w-0", children: [
|
|
3276
|
+
/* @__PURE__ */ jsx22("p", { className: "text-sm font-medium truncate", children: file.name }),
|
|
3277
|
+
/* @__PURE__ */ jsx22("p", { className: "text-xs text-muted-foreground", children: formatFileSize(file.size ?? 0) }),
|
|
3278
|
+
/* @__PURE__ */ jsx22(Progress, { value: progress, className: "h-1 mt-1" })
|
|
2887
3279
|
] }),
|
|
2888
|
-
/* @__PURE__ */
|
|
3280
|
+
/* @__PURE__ */ jsx22(
|
|
2889
3281
|
Button,
|
|
2890
3282
|
{
|
|
2891
3283
|
variant: "ghost",
|
|
2892
3284
|
size: "icon",
|
|
2893
3285
|
className: "h-6 w-6",
|
|
2894
3286
|
onClick: onCancel,
|
|
2895
|
-
children: /* @__PURE__ */
|
|
3287
|
+
children: /* @__PURE__ */ jsx22(X3, { className: "h-3 w-3" })
|
|
2896
3288
|
}
|
|
2897
3289
|
)
|
|
2898
3290
|
] }) }) });
|
|
@@ -2926,15 +3318,15 @@ var AttachmentPreview = memo2(function AttachmentPreview2({ attachment, onRemove
|
|
|
2926
3318
|
setIsPlaying(!isPlaying);
|
|
2927
3319
|
}
|
|
2928
3320
|
};
|
|
2929
|
-
const
|
|
3321
|
+
const formatDuration2 = (ms) => {
|
|
2930
3322
|
if (!ms) return "";
|
|
2931
3323
|
const seconds = Math.floor(ms / 1e3);
|
|
2932
3324
|
const minutes = Math.floor(seconds / 60);
|
|
2933
3325
|
return `${minutes}:${(seconds % 60).toString().padStart(2, "0")}`;
|
|
2934
3326
|
};
|
|
2935
|
-
return /* @__PURE__ */
|
|
2936
|
-
attachment.kind === "image" && /* @__PURE__ */
|
|
2937
|
-
/* @__PURE__ */
|
|
3327
|
+
return /* @__PURE__ */ jsx22(Card, { className: "relative group", children: /* @__PURE__ */ jsxs12(CardContent, { className: "p-2", children: [
|
|
3328
|
+
attachment.kind === "image" && /* @__PURE__ */ jsxs12("div", { className: "relative", children: [
|
|
3329
|
+
/* @__PURE__ */ jsx22(
|
|
2938
3330
|
"img",
|
|
2939
3331
|
{
|
|
2940
3332
|
src: attachment.dataUrl,
|
|
@@ -2942,19 +3334,19 @@ var AttachmentPreview = memo2(function AttachmentPreview2({ attachment, onRemove
|
|
|
2942
3334
|
className: "w-full h-20 object-cover rounded"
|
|
2943
3335
|
}
|
|
2944
3336
|
),
|
|
2945
|
-
/* @__PURE__ */
|
|
3337
|
+
/* @__PURE__ */ jsx22("div", { className: "absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity rounded flex items-center justify-center", children: /* @__PURE__ */ jsx22(
|
|
2946
3338
|
Button,
|
|
2947
3339
|
{
|
|
2948
3340
|
variant: "destructive",
|
|
2949
3341
|
size: "icon",
|
|
2950
3342
|
className: "h-6 w-6",
|
|
2951
3343
|
onClick: onRemove,
|
|
2952
|
-
children: /* @__PURE__ */
|
|
3344
|
+
children: /* @__PURE__ */ jsx22(X3, { className: "h-3 w-3" })
|
|
2953
3345
|
}
|
|
2954
3346
|
) })
|
|
2955
3347
|
] }),
|
|
2956
|
-
attachment.kind === "video" && /* @__PURE__ */
|
|
2957
|
-
/* @__PURE__ */
|
|
3348
|
+
attachment.kind === "video" && /* @__PURE__ */ jsxs12("div", { className: "relative", children: [
|
|
3349
|
+
/* @__PURE__ */ jsx22(
|
|
2958
3350
|
"video",
|
|
2959
3351
|
{
|
|
2960
3352
|
src: attachment.dataUrl,
|
|
@@ -2963,34 +3355,34 @@ var AttachmentPreview = memo2(function AttachmentPreview2({ attachment, onRemove
|
|
|
2963
3355
|
muted: true
|
|
2964
3356
|
}
|
|
2965
3357
|
),
|
|
2966
|
-
/* @__PURE__ */
|
|
3358
|
+
/* @__PURE__ */ jsx22("div", { className: "absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity rounded flex items-center justify-center", children: /* @__PURE__ */ jsx22(
|
|
2967
3359
|
Button,
|
|
2968
3360
|
{
|
|
2969
3361
|
variant: "destructive",
|
|
2970
3362
|
size: "icon",
|
|
2971
3363
|
className: "h-6 w-6",
|
|
2972
3364
|
onClick: onRemove,
|
|
2973
|
-
children: /* @__PURE__ */
|
|
3365
|
+
children: /* @__PURE__ */ jsx22(X3, { className: "h-3 w-3" })
|
|
2974
3366
|
}
|
|
2975
3367
|
) }),
|
|
2976
|
-
/* @__PURE__ */
|
|
3368
|
+
/* @__PURE__ */ jsx22(Badge, { className: "absolute bottom-1 right-1 text-xs", children: formatDuration2(attachment.durationMs) })
|
|
2977
3369
|
] }),
|
|
2978
|
-
attachment.kind === "audio" && /* @__PURE__ */
|
|
2979
|
-
/* @__PURE__ */
|
|
3370
|
+
attachment.kind === "audio" && /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 p-2", children: [
|
|
3371
|
+
/* @__PURE__ */ jsx22(
|
|
2980
3372
|
Button,
|
|
2981
3373
|
{
|
|
2982
3374
|
variant: "outline",
|
|
2983
3375
|
size: "icon",
|
|
2984
3376
|
className: "h-8 w-8",
|
|
2985
3377
|
onClick: handlePlayPause,
|
|
2986
|
-
children: isPlaying ? /* @__PURE__ */
|
|
3378
|
+
children: isPlaying ? /* @__PURE__ */ jsx22(Pause, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx22(Play, { className: "h-3 w-3" })
|
|
2987
3379
|
}
|
|
2988
3380
|
),
|
|
2989
|
-
/* @__PURE__ */
|
|
2990
|
-
/* @__PURE__ */
|
|
2991
|
-
/* @__PURE__ */
|
|
3381
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex-1", children: [
|
|
3382
|
+
/* @__PURE__ */ jsx22("p", { className: "text-xs font-medium", children: attachment.fileName || "\xC1udio" }),
|
|
3383
|
+
/* @__PURE__ */ jsx22("p", { className: "text-xs text-muted-foreground", children: formatDuration2(attachment.durationMs) })
|
|
2992
3384
|
] }),
|
|
2993
|
-
/* @__PURE__ */
|
|
3385
|
+
/* @__PURE__ */ jsx22(
|
|
2994
3386
|
"audio",
|
|
2995
3387
|
{
|
|
2996
3388
|
ref: audioRef,
|
|
@@ -2998,21 +3390,21 @@ var AttachmentPreview = memo2(function AttachmentPreview2({ attachment, onRemove
|
|
|
2998
3390
|
onPause: () => setIsPlaying(false),
|
|
2999
3391
|
onEnded: () => setIsPlaying(false),
|
|
3000
3392
|
preload: "metadata",
|
|
3001
|
-
children: /* @__PURE__ */
|
|
3393
|
+
children: /* @__PURE__ */ jsx22("source", { src: audioPlaybackSrc, type: attachment.mimeType })
|
|
3002
3394
|
}
|
|
3003
3395
|
),
|
|
3004
|
-
/* @__PURE__ */
|
|
3396
|
+
/* @__PURE__ */ jsx22(
|
|
3005
3397
|
Button,
|
|
3006
3398
|
{
|
|
3007
3399
|
variant: "ghost",
|
|
3008
3400
|
size: "icon",
|
|
3009
3401
|
className: "h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity",
|
|
3010
3402
|
onClick: onRemove,
|
|
3011
|
-
children: /* @__PURE__ */
|
|
3403
|
+
children: /* @__PURE__ */ jsx22(X3, { className: "h-3 w-3" })
|
|
3012
3404
|
}
|
|
3013
3405
|
)
|
|
3014
3406
|
] }),
|
|
3015
|
-
attachment.fileName && attachment.kind !== "audio" && /* @__PURE__ */
|
|
3407
|
+
attachment.fileName && attachment.kind !== "audio" && /* @__PURE__ */ jsx22("div", { className: "absolute bottom-0 left-0 right-0 bg-black/70 text-white text-xs p-1 rounded-b", children: /* @__PURE__ */ jsx22("p", { className: "truncate", children: attachment.fileName }) })
|
|
3016
3408
|
] }) });
|
|
3017
3409
|
});
|
|
3018
3410
|
var AudioRecorder = memo2(function AudioRecorder2({ isRecording, onStartRecording, onStopRecording, onCancel, recordingDuration, config }) {
|
|
@@ -3022,47 +3414,47 @@ var AudioRecorder = memo2(function AudioRecorder2({ isRecording, onStartRecordin
|
|
|
3022
3414
|
return `${mins}:${secs.toString().padStart(2, "0")}`;
|
|
3023
3415
|
};
|
|
3024
3416
|
if (!isRecording) {
|
|
3025
|
-
return /* @__PURE__ */
|
|
3026
|
-
/* @__PURE__ */
|
|
3417
|
+
return /* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
3418
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
3027
3419
|
Button,
|
|
3028
3420
|
{
|
|
3029
3421
|
variant: "outline",
|
|
3030
3422
|
size: "icon",
|
|
3031
3423
|
onClick: onStartRecording,
|
|
3032
3424
|
className: "h-10 w-10",
|
|
3033
|
-
children: /* @__PURE__ */
|
|
3425
|
+
children: /* @__PURE__ */ jsx22(Mic2, { className: "h-4 w-4" })
|
|
3034
3426
|
}
|
|
3035
3427
|
) }),
|
|
3036
|
-
/* @__PURE__ */
|
|
3428
|
+
/* @__PURE__ */ jsx22(TooltipContent, { children: config?.labels?.recordAudioTooltip })
|
|
3037
3429
|
] });
|
|
3038
3430
|
}
|
|
3039
|
-
return /* @__PURE__ */
|
|
3040
|
-
/* @__PURE__ */
|
|
3041
|
-
/* @__PURE__ */
|
|
3042
|
-
/* @__PURE__ */
|
|
3431
|
+
return /* @__PURE__ */ jsx22(Card, { className: "border-red-200 bg-red-50 dark:border-red-800 dark:bg-red-950", children: /* @__PURE__ */ jsx22(CardContent, { className: "p-3", children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
|
|
3432
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
|
|
3433
|
+
/* @__PURE__ */ jsx22("div", { className: "h-3 w-3 bg-red-500 rounded-full animate-pulse" }),
|
|
3434
|
+
/* @__PURE__ */ jsx22("span", { className: "text-sm font-medium text-red-700 dark:text-red-300", children: "Gravando" })
|
|
3043
3435
|
] }),
|
|
3044
|
-
/* @__PURE__ */
|
|
3045
|
-
/* @__PURE__ */
|
|
3046
|
-
/* @__PURE__ */
|
|
3436
|
+
/* @__PURE__ */ jsx22(Badge, { variant: "outline", className: "text-xs", children: formatTime(recordingDuration) }),
|
|
3437
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex gap-1 ml-auto", children: [
|
|
3438
|
+
/* @__PURE__ */ jsxs12(
|
|
3047
3439
|
Button,
|
|
3048
3440
|
{
|
|
3049
3441
|
variant: "outline",
|
|
3050
3442
|
size: "sm",
|
|
3051
3443
|
onClick: onCancel,
|
|
3052
3444
|
children: [
|
|
3053
|
-
/* @__PURE__ */
|
|
3445
|
+
/* @__PURE__ */ jsx22(X3, { className: "h-3 w-3 mr-1" }),
|
|
3054
3446
|
"Cancelar"
|
|
3055
3447
|
]
|
|
3056
3448
|
}
|
|
3057
3449
|
),
|
|
3058
|
-
/* @__PURE__ */
|
|
3450
|
+
/* @__PURE__ */ jsxs12(
|
|
3059
3451
|
Button,
|
|
3060
3452
|
{
|
|
3061
3453
|
variant: "default",
|
|
3062
3454
|
size: "sm",
|
|
3063
3455
|
onClick: onStopRecording,
|
|
3064
3456
|
children: [
|
|
3065
|
-
/* @__PURE__ */
|
|
3457
|
+
/* @__PURE__ */ jsx22(Square2, { className: "h-3 w-3 mr-1" }),
|
|
3066
3458
|
"Parar"
|
|
3067
3459
|
]
|
|
3068
3460
|
}
|
|
@@ -3070,6 +3462,16 @@ var AudioRecorder = memo2(function AudioRecorder2({ isRecording, onStartRecordin
|
|
|
3070
3462
|
] })
|
|
3071
3463
|
] }) }) });
|
|
3072
3464
|
});
|
|
3465
|
+
var resolveVoiceErrorMessage = (error, config) => {
|
|
3466
|
+
if (error instanceof DOMException && error.name === "NotAllowedError") {
|
|
3467
|
+
return config?.labels?.voicePermissionDenied || "Microphone access was denied.";
|
|
3468
|
+
}
|
|
3469
|
+
if (error instanceof Error && error.message.trim().length > 0) {
|
|
3470
|
+
return error.message;
|
|
3471
|
+
}
|
|
3472
|
+
return config?.labels?.voiceCaptureError || "Unable to capture audio.";
|
|
3473
|
+
};
|
|
3474
|
+
var clearVoiceTranscript = () => ({});
|
|
3073
3475
|
var ChatInput = memo2(function ChatInput2({
|
|
3074
3476
|
value,
|
|
3075
3477
|
onChange,
|
|
@@ -3093,12 +3495,27 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3093
3495
|
const { setContext } = useChatUserContext();
|
|
3094
3496
|
const [recordingDuration, setRecordingDuration] = useState6(0);
|
|
3095
3497
|
const [uploadProgress, setUploadProgress] = useState6(/* @__PURE__ */ new Map());
|
|
3498
|
+
const [isVoiceComposerOpen, setIsVoiceComposerOpen] = useState6(false);
|
|
3499
|
+
const [voiceState, setVoiceState] = useState6("idle");
|
|
3500
|
+
const [voiceDraft, setVoiceDraft] = useState6(null);
|
|
3501
|
+
const [voiceTranscript, setVoiceTranscript] = useState6(clearVoiceTranscript);
|
|
3502
|
+
const [voiceDurationMs, setVoiceDurationMs] = useState6(0);
|
|
3503
|
+
const [voiceAudioLevel, setVoiceAudioLevel] = useState6(0);
|
|
3504
|
+
const [voiceCountdownMs, setVoiceCountdownMs] = useState6(0);
|
|
3505
|
+
const [voiceError, setVoiceError] = useState6(null);
|
|
3096
3506
|
const textareaRef = useRef5(null);
|
|
3097
3507
|
const fileInputRef = useRef5(null);
|
|
3098
3508
|
const mediaRecorderRef = useRef5(null);
|
|
3099
3509
|
const recordingStartTime = useRef5(0);
|
|
3100
3510
|
const recordingInterval = useRef5(null);
|
|
3101
3511
|
const mediaStreamRef = useRef5(null);
|
|
3512
|
+
const voiceProviderRef = useRef5(null);
|
|
3513
|
+
const voiceComposeEnabled = config?.voiceCompose?.enabled === true;
|
|
3514
|
+
const voiceAutoSendDelayMs = config?.voiceCompose?.autoSendDelayMs ?? 5e3;
|
|
3515
|
+
const voicePersistComposer = config?.voiceCompose?.persistComposer ?? true;
|
|
3516
|
+
const voiceShowTranscriptPreview = config?.voiceCompose?.showTranscriptPreview ?? true;
|
|
3517
|
+
const voiceTranscriptMode = config?.voiceCompose?.transcriptMode ?? "final-only";
|
|
3518
|
+
const voiceMaxRecordingMs = config?.voiceCompose?.maxRecordingMs;
|
|
3102
3519
|
useEffect9(() => {
|
|
3103
3520
|
return () => {
|
|
3104
3521
|
if (mediaStreamRef.current) {
|
|
@@ -3107,6 +3524,10 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3107
3524
|
if (recordingInterval.current) {
|
|
3108
3525
|
clearInterval(recordingInterval.current);
|
|
3109
3526
|
}
|
|
3527
|
+
if (voiceProviderRef.current) {
|
|
3528
|
+
void voiceProviderRef.current.destroy();
|
|
3529
|
+
voiceProviderRef.current = null;
|
|
3530
|
+
}
|
|
3110
3531
|
};
|
|
3111
3532
|
}, []);
|
|
3112
3533
|
const handleSubmit = (e) => {
|
|
@@ -3283,13 +3704,149 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3283
3704
|
}
|
|
3284
3705
|
}
|
|
3285
3706
|
};
|
|
3707
|
+
const resetVoiceComposerState = useCallback3((nextState = "idle") => {
|
|
3708
|
+
setVoiceState(nextState);
|
|
3709
|
+
setVoiceDraft(null);
|
|
3710
|
+
setVoiceTranscript(clearVoiceTranscript());
|
|
3711
|
+
setVoiceDurationMs(0);
|
|
3712
|
+
setVoiceAudioLevel(0);
|
|
3713
|
+
setVoiceCountdownMs(0);
|
|
3714
|
+
setVoiceError(null);
|
|
3715
|
+
}, []);
|
|
3716
|
+
const ensureVoiceProvider = useCallback3(async () => {
|
|
3717
|
+
if (voiceProviderRef.current) {
|
|
3718
|
+
return voiceProviderRef.current;
|
|
3719
|
+
}
|
|
3720
|
+
const createProvider = resolveVoiceProviderFactory(config?.voiceCompose?.createProvider);
|
|
3721
|
+
const provider = await createProvider({
|
|
3722
|
+
onStateChange: setVoiceState,
|
|
3723
|
+
onAudioLevelChange: setVoiceAudioLevel,
|
|
3724
|
+
onDurationChange: setVoiceDurationMs,
|
|
3725
|
+
onTranscriptChange: setVoiceTranscript,
|
|
3726
|
+
onSegmentReady: (segment) => {
|
|
3727
|
+
setVoiceDraft(segment);
|
|
3728
|
+
setVoiceTranscript(segment.transcript ?? clearVoiceTranscript());
|
|
3729
|
+
setVoiceDurationMs(segment.attachment.durationMs ?? 0);
|
|
3730
|
+
setVoiceAudioLevel(0);
|
|
3731
|
+
setVoiceCountdownMs(voiceAutoSendDelayMs);
|
|
3732
|
+
setVoiceError(null);
|
|
3733
|
+
setVoiceState("review");
|
|
3734
|
+
},
|
|
3735
|
+
onError: (error) => {
|
|
3736
|
+
setVoiceError(resolveVoiceErrorMessage(error, config));
|
|
3737
|
+
setVoiceAudioLevel(0);
|
|
3738
|
+
setVoiceCountdownMs(0);
|
|
3739
|
+
setVoiceState("error");
|
|
3740
|
+
}
|
|
3741
|
+
}, {
|
|
3742
|
+
maxRecordingMs: voiceMaxRecordingMs
|
|
3743
|
+
});
|
|
3744
|
+
voiceProviderRef.current = provider;
|
|
3745
|
+
return provider;
|
|
3746
|
+
}, [config, voiceAutoSendDelayMs, voiceMaxRecordingMs]);
|
|
3747
|
+
const closeVoiceComposer = useCallback3(async () => {
|
|
3748
|
+
setIsVoiceComposerOpen(false);
|
|
3749
|
+
setVoiceError(null);
|
|
3750
|
+
setVoiceCountdownMs(0);
|
|
3751
|
+
setVoiceAudioLevel(0);
|
|
3752
|
+
setVoiceTranscript(clearVoiceTranscript());
|
|
3753
|
+
setVoiceDraft(null);
|
|
3754
|
+
setVoiceDurationMs(0);
|
|
3755
|
+
setVoiceState("idle");
|
|
3756
|
+
if (voiceProviderRef.current) {
|
|
3757
|
+
await voiceProviderRef.current.cancel();
|
|
3758
|
+
}
|
|
3759
|
+
}, []);
|
|
3760
|
+
const startVoiceCapture = useCallback3(async () => {
|
|
3761
|
+
if (disabled || isGenerating) {
|
|
3762
|
+
return;
|
|
3763
|
+
}
|
|
3764
|
+
setIsVoiceComposerOpen(true);
|
|
3765
|
+
setVoiceError(null);
|
|
3766
|
+
setVoiceDraft(null);
|
|
3767
|
+
setVoiceCountdownMs(0);
|
|
3768
|
+
setVoiceTranscript(clearVoiceTranscript());
|
|
3769
|
+
setVoiceAudioLevel(0);
|
|
3770
|
+
setVoiceDurationMs(0);
|
|
3771
|
+
try {
|
|
3772
|
+
const provider = await ensureVoiceProvider();
|
|
3773
|
+
await provider.start();
|
|
3774
|
+
} catch (error) {
|
|
3775
|
+
setVoiceError(resolveVoiceErrorMessage(error, config));
|
|
3776
|
+
setVoiceState("error");
|
|
3777
|
+
}
|
|
3778
|
+
}, [disabled, isGenerating, ensureVoiceProvider, config]);
|
|
3779
|
+
const stopVoiceCapture = useCallback3(async () => {
|
|
3780
|
+
if (!voiceProviderRef.current) return;
|
|
3781
|
+
try {
|
|
3782
|
+
await voiceProviderRef.current.stop();
|
|
3783
|
+
} catch (error) {
|
|
3784
|
+
setVoiceError(resolveVoiceErrorMessage(error, config));
|
|
3785
|
+
setVoiceState("error");
|
|
3786
|
+
}
|
|
3787
|
+
}, [config]);
|
|
3788
|
+
const cancelVoiceCapture = useCallback3(async () => {
|
|
3789
|
+
if (voiceProviderRef.current) {
|
|
3790
|
+
await voiceProviderRef.current.cancel();
|
|
3791
|
+
}
|
|
3792
|
+
resetVoiceComposerState("idle");
|
|
3793
|
+
}, [resetVoiceComposerState]);
|
|
3794
|
+
const finalizeVoiceComposerAfterSend = useCallback3(() => {
|
|
3795
|
+
if (voicePersistComposer) {
|
|
3796
|
+
resetVoiceComposerState("idle");
|
|
3797
|
+
setIsVoiceComposerOpen(true);
|
|
3798
|
+
return;
|
|
3799
|
+
}
|
|
3800
|
+
void closeVoiceComposer();
|
|
3801
|
+
}, [voicePersistComposer, resetVoiceComposerState, closeVoiceComposer]);
|
|
3802
|
+
const sendVoiceDraft = useCallback3(() => {
|
|
3803
|
+
if (!voiceDraft || disabled || isGenerating) {
|
|
3804
|
+
return;
|
|
3805
|
+
}
|
|
3806
|
+
setVoiceState("sending");
|
|
3807
|
+
setVoiceCountdownMs(0);
|
|
3808
|
+
onSubmit("", [...attachments, voiceDraft.attachment]);
|
|
3809
|
+
onChange("");
|
|
3810
|
+
onAttachmentsChange([]);
|
|
3811
|
+
finalizeVoiceComposerAfterSend();
|
|
3812
|
+
}, [
|
|
3813
|
+
voiceDraft,
|
|
3814
|
+
disabled,
|
|
3815
|
+
isGenerating,
|
|
3816
|
+
onSubmit,
|
|
3817
|
+
attachments,
|
|
3818
|
+
onChange,
|
|
3819
|
+
onAttachmentsChange,
|
|
3820
|
+
finalizeVoiceComposerAfterSend
|
|
3821
|
+
]);
|
|
3822
|
+
const recordVoiceAgain = useCallback3(async () => {
|
|
3823
|
+
resetVoiceComposerState("idle");
|
|
3824
|
+
await startVoiceCapture();
|
|
3825
|
+
}, [resetVoiceComposerState, startVoiceCapture]);
|
|
3826
|
+
useEffect9(() => {
|
|
3827
|
+
if (voiceState !== "review" || !voiceDraft || voiceAutoSendDelayMs <= 0) {
|
|
3828
|
+
return;
|
|
3829
|
+
}
|
|
3830
|
+
const startedAt = Date.now();
|
|
3831
|
+
setVoiceCountdownMs(voiceAutoSendDelayMs);
|
|
3832
|
+
const timer = setInterval(() => {
|
|
3833
|
+
const remaining = Math.max(0, voiceAutoSendDelayMs - (Date.now() - startedAt));
|
|
3834
|
+
setVoiceCountdownMs(remaining);
|
|
3835
|
+
if (remaining <= 0) {
|
|
3836
|
+
clearInterval(timer);
|
|
3837
|
+
sendVoiceDraft();
|
|
3838
|
+
}
|
|
3839
|
+
}, 100);
|
|
3840
|
+
return () => clearInterval(timer);
|
|
3841
|
+
}, [voiceState, voiceDraft, voiceAutoSendDelayMs, sendVoiceDraft]);
|
|
3286
3842
|
const removeAttachment = (index) => {
|
|
3287
3843
|
const newAttachments = attachments.filter((_, i) => i !== index);
|
|
3288
3844
|
onAttachmentsChange(newAttachments);
|
|
3289
3845
|
};
|
|
3290
3846
|
const canAddMoreAttachments = attachments.length < maxAttachments;
|
|
3291
|
-
|
|
3292
|
-
|
|
3847
|
+
const showVoiceComposer = voiceComposeEnabled && isVoiceComposerOpen;
|
|
3848
|
+
return /* @__PURE__ */ jsx22(TooltipProvider, { children: /* @__PURE__ */ jsx22("div", { className: `border-t py-0 bg-transparent ${className}`, children: /* @__PURE__ */ jsxs12("div", { className: "px-0 md:p-2 pb-1 space-y-4 bg-transparent", children: [
|
|
3849
|
+
uploadProgress.size > 0 && /* @__PURE__ */ jsx22("div", { className: "space-y-2", children: Array.from(uploadProgress.entries()).map(([id, progress]) => /* @__PURE__ */ jsx22(
|
|
3293
3850
|
FileUploadItem,
|
|
3294
3851
|
{
|
|
3295
3852
|
file: { name: progress.fileName },
|
|
@@ -3304,7 +3861,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3304
3861
|
},
|
|
3305
3862
|
id
|
|
3306
3863
|
)) }),
|
|
3307
|
-
isRecording && /* @__PURE__ */
|
|
3864
|
+
isRecording && /* @__PURE__ */ jsx22(
|
|
3308
3865
|
AudioRecorder,
|
|
3309
3866
|
{
|
|
3310
3867
|
isRecording,
|
|
@@ -3315,7 +3872,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3315
3872
|
config
|
|
3316
3873
|
}
|
|
3317
3874
|
),
|
|
3318
|
-
attachments.length > 0 && /* @__PURE__ */
|
|
3875
|
+
attachments.length > 0 && /* @__PURE__ */ jsx22("div", { className: "grid grid-cols-4 gap-2", children: attachments.map((attachment, index) => /* @__PURE__ */ jsx22(
|
|
3319
3876
|
AttachmentPreview,
|
|
3320
3877
|
{
|
|
3321
3878
|
attachment,
|
|
@@ -3323,15 +3880,46 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3323
3880
|
},
|
|
3324
3881
|
index
|
|
3325
3882
|
)) }),
|
|
3326
|
-
/* @__PURE__ */
|
|
3883
|
+
showVoiceComposer ? /* @__PURE__ */ jsx22("div", { className: "mb-1 flex justify-center", children: /* @__PURE__ */ jsx22(
|
|
3884
|
+
VoiceComposer,
|
|
3885
|
+
{
|
|
3886
|
+
state: voiceState,
|
|
3887
|
+
transcript: voiceTranscript,
|
|
3888
|
+
transcriptMode: voiceTranscriptMode,
|
|
3889
|
+
showTranscriptPreview: voiceShowTranscriptPreview,
|
|
3890
|
+
durationMs: voiceDurationMs,
|
|
3891
|
+
audioLevel: voiceAudioLevel,
|
|
3892
|
+
countdownMs: voiceCountdownMs,
|
|
3893
|
+
autoSendDelayMs: voiceAutoSendDelayMs,
|
|
3894
|
+
errorMessage: voiceError,
|
|
3895
|
+
disabled: disabled || isGenerating,
|
|
3896
|
+
labels: config?.labels,
|
|
3897
|
+
onStart: () => {
|
|
3898
|
+
void startVoiceCapture();
|
|
3899
|
+
},
|
|
3900
|
+
onStop: () => {
|
|
3901
|
+
void stopVoiceCapture();
|
|
3902
|
+
},
|
|
3903
|
+
onCancel: () => {
|
|
3904
|
+
void cancelVoiceCapture();
|
|
3905
|
+
},
|
|
3906
|
+
onSendNow: sendVoiceDraft,
|
|
3907
|
+
onRecordAgain: () => {
|
|
3908
|
+
void recordVoiceAgain();
|
|
3909
|
+
},
|
|
3910
|
+
onExit: () => {
|
|
3911
|
+
void closeVoiceComposer();
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3914
|
+
) }) : /* @__PURE__ */ jsx22("form", { onSubmit: handleSubmit, className: "mb-1 flex justify-center", children: /* @__PURE__ */ jsxs12(
|
|
3327
3915
|
"div",
|
|
3328
3916
|
{
|
|
3329
3917
|
className: "flex items-end gap-2 p-3 border rounded-lg bg-background w-full md:min-w-3xl max-w-3xl",
|
|
3330
3918
|
onDrop: handleDrop,
|
|
3331
3919
|
onDragOver: handleDragOver,
|
|
3332
3920
|
children: [
|
|
3333
|
-
enableFileUpload && canAddMoreAttachments && /* @__PURE__ */
|
|
3334
|
-
/* @__PURE__ */
|
|
3921
|
+
enableFileUpload && canAddMoreAttachments && /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
3922
|
+
/* @__PURE__ */ jsx22(
|
|
3335
3923
|
"input",
|
|
3336
3924
|
{
|
|
3337
3925
|
ref: fileInputRef,
|
|
@@ -3342,8 +3930,8 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3342
3930
|
className: "hidden"
|
|
3343
3931
|
}
|
|
3344
3932
|
),
|
|
3345
|
-
/* @__PURE__ */
|
|
3346
|
-
/* @__PURE__ */
|
|
3933
|
+
/* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
3934
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
3347
3935
|
Button,
|
|
3348
3936
|
{
|
|
3349
3937
|
type: "button",
|
|
@@ -3356,13 +3944,13 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3356
3944
|
fileInputRef.current?.click();
|
|
3357
3945
|
},
|
|
3358
3946
|
disabled,
|
|
3359
|
-
children: /* @__PURE__ */
|
|
3947
|
+
children: /* @__PURE__ */ jsx22(Paperclip, { className: "h-4 w-4" })
|
|
3360
3948
|
}
|
|
3361
3949
|
) }),
|
|
3362
|
-
/* @__PURE__ */
|
|
3950
|
+
/* @__PURE__ */ jsx22(TooltipContent, { children: config?.labels?.attachFileTooltip })
|
|
3363
3951
|
] })
|
|
3364
3952
|
] }),
|
|
3365
|
-
/* @__PURE__ */
|
|
3953
|
+
/* @__PURE__ */ jsx22("div", { className: "flex-1", children: /* @__PURE__ */ jsx22(
|
|
3366
3954
|
Textarea,
|
|
3367
3955
|
{
|
|
3368
3956
|
ref: textareaRef,
|
|
@@ -3375,7 +3963,23 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3375
3963
|
rows: 1
|
|
3376
3964
|
}
|
|
3377
3965
|
) }),
|
|
3378
|
-
enableAudioRecording && !isRecording && canAddMoreAttachments && !value.trim() && /* @__PURE__ */
|
|
3966
|
+
enableAudioRecording && !isRecording && canAddMoreAttachments && !value.trim() && (voiceComposeEnabled ? /* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
3967
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
3968
|
+
Button,
|
|
3969
|
+
{
|
|
3970
|
+
type: "button",
|
|
3971
|
+
variant: "outline",
|
|
3972
|
+
size: "icon",
|
|
3973
|
+
className: "h-10 w-10",
|
|
3974
|
+
onClick: () => {
|
|
3975
|
+
void startVoiceCapture();
|
|
3976
|
+
},
|
|
3977
|
+
disabled: disabled || isGenerating,
|
|
3978
|
+
children: /* @__PURE__ */ jsx22(Mic2, { className: "h-4 w-4" })
|
|
3979
|
+
}
|
|
3980
|
+
) }),
|
|
3981
|
+
/* @__PURE__ */ jsx22(TooltipContent, { children: config?.labels?.voiceEnter || config?.labels?.recordAudioTooltip })
|
|
3982
|
+
] }) : /* @__PURE__ */ jsx22(
|
|
3379
3983
|
AudioRecorder,
|
|
3380
3984
|
{
|
|
3381
3985
|
isRecording,
|
|
@@ -3385,9 +3989,9 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3385
3989
|
recordingDuration,
|
|
3386
3990
|
config
|
|
3387
3991
|
}
|
|
3388
|
-
),
|
|
3389
|
-
isGenerating ? /* @__PURE__ */
|
|
3390
|
-
/* @__PURE__ */
|
|
3992
|
+
)),
|
|
3993
|
+
isGenerating ? /* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
3994
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
3391
3995
|
Button,
|
|
3392
3996
|
{
|
|
3393
3997
|
type: "button",
|
|
@@ -3395,36 +3999,36 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3395
3999
|
size: "icon",
|
|
3396
4000
|
className: "h-10 w-10",
|
|
3397
4001
|
onClick: onStopGeneration,
|
|
3398
|
-
children: /* @__PURE__ */
|
|
4002
|
+
children: /* @__PURE__ */ jsx22(Square2, { className: "h-4 w-4" })
|
|
3399
4003
|
}
|
|
3400
4004
|
) }),
|
|
3401
|
-
/* @__PURE__ */
|
|
3402
|
-
] }) : /* @__PURE__ */
|
|
3403
|
-
/* @__PURE__ */
|
|
4005
|
+
/* @__PURE__ */ jsx22(TooltipContent, { children: config?.labels?.stopGenerationTooltip })
|
|
4006
|
+
] }) : /* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
4007
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
3404
4008
|
Button,
|
|
3405
4009
|
{
|
|
3406
4010
|
type: "submit",
|
|
3407
4011
|
size: "icon",
|
|
3408
4012
|
className: "h-10 w-10",
|
|
3409
4013
|
disabled: disabled || !value.trim() && attachments.length === 0,
|
|
3410
|
-
children: disabled ? /* @__PURE__ */
|
|
4014
|
+
children: disabled ? /* @__PURE__ */ jsx22(Loader22, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx22(Send2, { className: "h-4 w-4" })
|
|
3411
4015
|
}
|
|
3412
4016
|
) }),
|
|
3413
|
-
/* @__PURE__ */
|
|
4017
|
+
/* @__PURE__ */ jsx22(TooltipContent, { children: config?.labels?.sendMessageTooltip })
|
|
3414
4018
|
] })
|
|
3415
4019
|
]
|
|
3416
4020
|
}
|
|
3417
4021
|
) }),
|
|
3418
|
-
/* @__PURE__ */
|
|
4022
|
+
/* @__PURE__ */ jsxs12("div", { className: "text-[10px] text-muted-foreground text-center", children: [
|
|
3419
4023
|
window.innerWidth > 768 ? config?.labels?.inputHelpText : "",
|
|
3420
|
-
attachments.length > 0 && /* @__PURE__ */
|
|
4024
|
+
attachments.length > 0 && /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
3421
4025
|
" \u2022 ",
|
|
3422
4026
|
attachments.length,
|
|
3423
4027
|
"/",
|
|
3424
4028
|
maxAttachments,
|
|
3425
4029
|
" anexos"
|
|
3426
4030
|
] }),
|
|
3427
|
-
config?.labels?.footerLabel && /* @__PURE__ */
|
|
4031
|
+
config?.labels?.footerLabel && /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
3428
4032
|
" \u2022 ",
|
|
3429
4033
|
config.labels.footerLabel
|
|
3430
4034
|
] })
|
|
@@ -3438,16 +4042,16 @@ import { useState as useState7 } from "react";
|
|
|
3438
4042
|
// src/components/ui/scroll-area.tsx
|
|
3439
4043
|
import * as React11 from "react";
|
|
3440
4044
|
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
|
3441
|
-
import { jsx as
|
|
4045
|
+
import { jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3442
4046
|
var ScrollArea = React11.forwardRef(({ className, children, viewportClassName, onScroll, onScrollCapture, ...props }, ref) => {
|
|
3443
|
-
return /* @__PURE__ */
|
|
4047
|
+
return /* @__PURE__ */ jsxs13(
|
|
3444
4048
|
ScrollAreaPrimitive.Root,
|
|
3445
4049
|
{
|
|
3446
4050
|
"data-slot": "scroll-area",
|
|
3447
4051
|
className: cn("relative", className),
|
|
3448
4052
|
...props,
|
|
3449
4053
|
children: [
|
|
3450
|
-
/* @__PURE__ */
|
|
4054
|
+
/* @__PURE__ */ jsx23(
|
|
3451
4055
|
ScrollAreaPrimitive.Viewport,
|
|
3452
4056
|
{
|
|
3453
4057
|
ref,
|
|
@@ -3461,8 +4065,8 @@ var ScrollArea = React11.forwardRef(({ className, children, viewportClassName, o
|
|
|
3461
4065
|
children
|
|
3462
4066
|
}
|
|
3463
4067
|
),
|
|
3464
|
-
/* @__PURE__ */
|
|
3465
|
-
/* @__PURE__ */
|
|
4068
|
+
/* @__PURE__ */ jsx23(ScrollBar, {}),
|
|
4069
|
+
/* @__PURE__ */ jsx23(ScrollAreaPrimitive.Corner, {})
|
|
3466
4070
|
]
|
|
3467
4071
|
}
|
|
3468
4072
|
);
|
|
@@ -3473,7 +4077,7 @@ function ScrollBar({
|
|
|
3473
4077
|
orientation = "vertical",
|
|
3474
4078
|
...props
|
|
3475
4079
|
}) {
|
|
3476
|
-
return /* @__PURE__ */
|
|
4080
|
+
return /* @__PURE__ */ jsx23(
|
|
3477
4081
|
ScrollAreaPrimitive.ScrollAreaScrollbar,
|
|
3478
4082
|
{
|
|
3479
4083
|
"data-slot": "scroll-area-scrollbar",
|
|
@@ -3485,7 +4089,7 @@ function ScrollBar({
|
|
|
3485
4089
|
className
|
|
3486
4090
|
),
|
|
3487
4091
|
...props,
|
|
3488
|
-
children: /* @__PURE__ */
|
|
4092
|
+
children: /* @__PURE__ */ jsx23(
|
|
3489
4093
|
ScrollAreaPrimitive.ScrollAreaThumb,
|
|
3490
4094
|
{
|
|
3491
4095
|
"data-slot": "scroll-area-thumb",
|
|
@@ -3522,9 +4126,9 @@ import {
|
|
|
3522
4126
|
Bot as Bot3,
|
|
3523
4127
|
Pencil,
|
|
3524
4128
|
Check as Check3,
|
|
3525
|
-
X as
|
|
4129
|
+
X as X4
|
|
3526
4130
|
} from "lucide-react";
|
|
3527
|
-
import { Fragment as
|
|
4131
|
+
import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3528
4132
|
var getInitials2 = (name, email) => {
|
|
3529
4133
|
if (name) {
|
|
3530
4134
|
return name.split(" ").map((n) => n[0]).slice(0, 2).join("").toUpperCase();
|
|
@@ -3538,29 +4142,29 @@ var getFieldIcon = (type, key) => {
|
|
|
3538
4142
|
const iconClass = "h-4 w-4 text-muted-foreground";
|
|
3539
4143
|
switch (type) {
|
|
3540
4144
|
case "email":
|
|
3541
|
-
return /* @__PURE__ */
|
|
4145
|
+
return /* @__PURE__ */ jsx24(Mail, { className: iconClass });
|
|
3542
4146
|
case "phone":
|
|
3543
|
-
return /* @__PURE__ */
|
|
4147
|
+
return /* @__PURE__ */ jsx24(Phone, { className: iconClass });
|
|
3544
4148
|
case "url":
|
|
3545
|
-
return /* @__PURE__ */
|
|
4149
|
+
return /* @__PURE__ */ jsx24(Globe, { className: iconClass });
|
|
3546
4150
|
case "date":
|
|
3547
|
-
return /* @__PURE__ */
|
|
4151
|
+
return /* @__PURE__ */ jsx24(Calendar, { className: iconClass });
|
|
3548
4152
|
}
|
|
3549
4153
|
const lowerKey = key?.toLowerCase() || "";
|
|
3550
|
-
if (lowerKey.includes("follower")) return /* @__PURE__ */
|
|
3551
|
-
if (lowerKey.includes("following")) return /* @__PURE__ */
|
|
3552
|
-
if (lowerKey.includes("post") || lowerKey.includes("publication")) return /* @__PURE__ */
|
|
3553
|
-
if (lowerKey.includes("verified") || lowerKey.includes("badge")) return /* @__PURE__ */
|
|
3554
|
-
if (lowerKey.includes("bio")) return /* @__PURE__ */
|
|
3555
|
-
if (lowerKey.includes("email")) return /* @__PURE__ */
|
|
3556
|
-
if (lowerKey.includes("phone") || lowerKey.includes("tel")) return /* @__PURE__ */
|
|
3557
|
-
if (lowerKey.includes("location") || lowerKey.includes("address") || lowerKey.includes("city")) return /* @__PURE__ */
|
|
3558
|
-
if (lowerKey.includes("company") || lowerKey.includes("org")) return /* @__PURE__ */
|
|
3559
|
-
if (lowerKey.includes("job") || lowerKey.includes("role") || lowerKey.includes("title") || lowerKey.includes("position")) return /* @__PURE__ */
|
|
3560
|
-
if (lowerKey.includes("website") || lowerKey.includes("url") || lowerKey.includes("link")) return /* @__PURE__ */
|
|
3561
|
-
if (lowerKey.includes("username") || lowerKey.includes("handle")) return /* @__PURE__ */
|
|
3562
|
-
if (lowerKey.includes("date") || lowerKey.includes("birthday") || lowerKey.includes("joined")) return /* @__PURE__ */
|
|
3563
|
-
return /* @__PURE__ */
|
|
4154
|
+
if (lowerKey.includes("follower")) return /* @__PURE__ */ jsx24(Users, { className: iconClass });
|
|
4155
|
+
if (lowerKey.includes("following")) return /* @__PURE__ */ jsx24(UserPlus, { className: iconClass });
|
|
4156
|
+
if (lowerKey.includes("post") || lowerKey.includes("publication")) return /* @__PURE__ */ jsx24(Image3, { className: iconClass });
|
|
4157
|
+
if (lowerKey.includes("verified") || lowerKey.includes("badge")) return /* @__PURE__ */ jsx24(BadgeCheck, { className: iconClass });
|
|
4158
|
+
if (lowerKey.includes("bio")) return /* @__PURE__ */ jsx24(FileText2, { className: iconClass });
|
|
4159
|
+
if (lowerKey.includes("email")) return /* @__PURE__ */ jsx24(Mail, { className: iconClass });
|
|
4160
|
+
if (lowerKey.includes("phone") || lowerKey.includes("tel")) return /* @__PURE__ */ jsx24(Phone, { className: iconClass });
|
|
4161
|
+
if (lowerKey.includes("location") || lowerKey.includes("address") || lowerKey.includes("city")) return /* @__PURE__ */ jsx24(MapPin, { className: iconClass });
|
|
4162
|
+
if (lowerKey.includes("company") || lowerKey.includes("org")) return /* @__PURE__ */ jsx24(Building, { className: iconClass });
|
|
4163
|
+
if (lowerKey.includes("job") || lowerKey.includes("role") || lowerKey.includes("title") || lowerKey.includes("position")) return /* @__PURE__ */ jsx24(Briefcase, { className: iconClass });
|
|
4164
|
+
if (lowerKey.includes("website") || lowerKey.includes("url") || lowerKey.includes("link")) return /* @__PURE__ */ jsx24(Globe, { className: iconClass });
|
|
4165
|
+
if (lowerKey.includes("username") || lowerKey.includes("handle")) return /* @__PURE__ */ jsx24(AtSign, { className: iconClass });
|
|
4166
|
+
if (lowerKey.includes("date") || lowerKey.includes("birthday") || lowerKey.includes("joined")) return /* @__PURE__ */ jsx24(Calendar, { className: iconClass });
|
|
4167
|
+
return /* @__PURE__ */ jsx24(User2, { className: iconClass });
|
|
3564
4168
|
};
|
|
3565
4169
|
var formatValue = (value, type, key) => {
|
|
3566
4170
|
if (value === null || value === void 0) return "-";
|
|
@@ -3594,15 +4198,15 @@ var getMemoryCategoryIcon = (category) => {
|
|
|
3594
4198
|
const iconClass = "h-4 w-4 text-muted-foreground";
|
|
3595
4199
|
switch (category) {
|
|
3596
4200
|
case "preference":
|
|
3597
|
-
return /* @__PURE__ */
|
|
4201
|
+
return /* @__PURE__ */ jsx24(Heart, { className: iconClass });
|
|
3598
4202
|
case "fact":
|
|
3599
|
-
return /* @__PURE__ */
|
|
4203
|
+
return /* @__PURE__ */ jsx24(Info, { className: iconClass });
|
|
3600
4204
|
case "goal":
|
|
3601
|
-
return /* @__PURE__ */
|
|
4205
|
+
return /* @__PURE__ */ jsx24(Target, { className: iconClass });
|
|
3602
4206
|
case "context":
|
|
3603
|
-
return /* @__PURE__ */
|
|
4207
|
+
return /* @__PURE__ */ jsx24(Lightbulb, { className: iconClass });
|
|
3604
4208
|
default:
|
|
3605
|
-
return /* @__PURE__ */
|
|
4209
|
+
return /* @__PURE__ */ jsx24(Brain2, { className: iconClass });
|
|
3606
4210
|
}
|
|
3607
4211
|
};
|
|
3608
4212
|
var getMemoryCategoryLabel = (category) => {
|
|
@@ -3672,66 +4276,66 @@ var UserProfile = ({
|
|
|
3672
4276
|
const displayName = user?.name || user?.email?.split("@")[0] || "User";
|
|
3673
4277
|
const initials = getInitials2(user?.name, user?.email);
|
|
3674
4278
|
const normalizedFields = normalizeCustomFields(customFields);
|
|
3675
|
-
return /* @__PURE__ */
|
|
4279
|
+
return /* @__PURE__ */ jsx24(Sheet, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxs14(
|
|
3676
4280
|
SheetContent,
|
|
3677
4281
|
{
|
|
3678
4282
|
side: "right",
|
|
3679
4283
|
className: cn("w-full sm:max-w-md p-0 flex flex-col h-full overflow-hidden", className),
|
|
3680
4284
|
children: [
|
|
3681
|
-
/* @__PURE__ */
|
|
3682
|
-
/* @__PURE__ */
|
|
3683
|
-
/* @__PURE__ */
|
|
3684
|
-
/* @__PURE__ */
|
|
3685
|
-
user?.avatar && /* @__PURE__ */
|
|
3686
|
-
/* @__PURE__ */
|
|
4285
|
+
/* @__PURE__ */ jsx24(SheetHeader, { className: "px-6 py-4 border-b shrink-0", children: /* @__PURE__ */ jsx24("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsx24(SheetTitle, { children: labels.title }) }) }),
|
|
4286
|
+
/* @__PURE__ */ jsx24(ScrollArea, { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxs14("div", { className: "p-6 space-y-6", children: [
|
|
4287
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex flex-col items-center text-center space-y-4", children: [
|
|
4288
|
+
/* @__PURE__ */ jsxs14(Avatar, { className: "h-24 w-24 shrink-0", children: [
|
|
4289
|
+
user?.avatar && /* @__PURE__ */ jsx24(AvatarImage, { src: user.avatar, alt: displayName }),
|
|
4290
|
+
/* @__PURE__ */ jsx24(AvatarFallback, { className: "text-2xl bg-primary/10 text-primary", children: initials })
|
|
3687
4291
|
] }),
|
|
3688
|
-
/* @__PURE__ */
|
|
3689
|
-
/* @__PURE__ */
|
|
3690
|
-
user?.email && /* @__PURE__ */
|
|
4292
|
+
/* @__PURE__ */ jsxs14("div", { className: "w-full px-2", children: [
|
|
4293
|
+
/* @__PURE__ */ jsx24("h2", { className: "text-xl font-semibold break-words", children: displayName }),
|
|
4294
|
+
user?.email && /* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground break-words", children: user.email })
|
|
3691
4295
|
] })
|
|
3692
4296
|
] }),
|
|
3693
|
-
/* @__PURE__ */
|
|
3694
|
-
/* @__PURE__ */
|
|
3695
|
-
/* @__PURE__ */
|
|
3696
|
-
/* @__PURE__ */
|
|
3697
|
-
/* @__PURE__ */
|
|
3698
|
-
/* @__PURE__ */
|
|
3699
|
-
/* @__PURE__ */
|
|
3700
|
-
/* @__PURE__ */
|
|
3701
|
-
/* @__PURE__ */
|
|
4297
|
+
/* @__PURE__ */ jsx24(Separator, {}),
|
|
4298
|
+
/* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
|
|
4299
|
+
/* @__PURE__ */ jsx24("h3", { className: "text-sm font-medium text-muted-foreground uppercase tracking-wider", children: labels.basicInfo }),
|
|
4300
|
+
/* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
|
|
4301
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50", children: [
|
|
4302
|
+
/* @__PURE__ */ jsx24(User2, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
4303
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex-1 min-w-0", children: [
|
|
4304
|
+
/* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: "Name" }),
|
|
4305
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm font-medium break-words", children: displayName })
|
|
3702
4306
|
] })
|
|
3703
4307
|
] }),
|
|
3704
|
-
user?.email && /* @__PURE__ */
|
|
3705
|
-
/* @__PURE__ */
|
|
3706
|
-
/* @__PURE__ */
|
|
3707
|
-
/* @__PURE__ */
|
|
3708
|
-
/* @__PURE__ */
|
|
4308
|
+
user?.email && /* @__PURE__ */ jsxs14("div", { className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50", children: [
|
|
4309
|
+
/* @__PURE__ */ jsx24(AtSign, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
4310
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex-1 min-w-0", children: [
|
|
4311
|
+
/* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: "Handle" }),
|
|
4312
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm font-medium break-words", children: user.email })
|
|
3709
4313
|
] })
|
|
3710
4314
|
] }),
|
|
3711
|
-
user?.id && user.id !== user?.name && user.id !== user?.email && /* @__PURE__ */
|
|
3712
|
-
/* @__PURE__ */
|
|
3713
|
-
/* @__PURE__ */
|
|
3714
|
-
/* @__PURE__ */
|
|
3715
|
-
/* @__PURE__ */
|
|
4315
|
+
user?.id && user.id !== user?.name && user.id !== user?.email && /* @__PURE__ */ jsxs14("div", { className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50", children: [
|
|
4316
|
+
/* @__PURE__ */ jsx24(User2, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
4317
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex-1 min-w-0", children: [
|
|
4318
|
+
/* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: "ID" }),
|
|
4319
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm font-medium break-words", children: user.id })
|
|
3716
4320
|
] })
|
|
3717
4321
|
] })
|
|
3718
4322
|
] })
|
|
3719
4323
|
] }),
|
|
3720
|
-
normalizedFields.length > 0 && /* @__PURE__ */
|
|
3721
|
-
/* @__PURE__ */
|
|
3722
|
-
/* @__PURE__ */
|
|
3723
|
-
/* @__PURE__ */
|
|
3724
|
-
/* @__PURE__ */
|
|
4324
|
+
normalizedFields.length > 0 && /* @__PURE__ */ jsxs14(Fragment6, { children: [
|
|
4325
|
+
/* @__PURE__ */ jsx24(Separator, {}),
|
|
4326
|
+
/* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
|
|
4327
|
+
/* @__PURE__ */ jsx24("h3", { className: "text-sm font-medium text-muted-foreground uppercase tracking-wider", children: labels.customFields }),
|
|
4328
|
+
/* @__PURE__ */ jsx24("div", { className: "space-y-2", children: normalizedFields.map((field) => {
|
|
3725
4329
|
const isBioField = field.key.toLowerCase().includes("bio");
|
|
3726
|
-
return /* @__PURE__ */
|
|
4330
|
+
return /* @__PURE__ */ jsxs14(
|
|
3727
4331
|
"div",
|
|
3728
4332
|
{
|
|
3729
4333
|
className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50",
|
|
3730
4334
|
children: [
|
|
3731
|
-
/* @__PURE__ */
|
|
3732
|
-
/* @__PURE__ */
|
|
3733
|
-
/* @__PURE__ */
|
|
3734
|
-
/* @__PURE__ */
|
|
4335
|
+
/* @__PURE__ */ jsx24("div", { className: "mt-0.5 shrink-0", children: field.icon || getFieldIcon(field.type, field.key) }),
|
|
4336
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex-1 min-w-0", children: [
|
|
4337
|
+
/* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: field.label }),
|
|
4338
|
+
/* @__PURE__ */ jsx24("p", { className: cn(
|
|
3735
4339
|
"text-sm font-medium",
|
|
3736
4340
|
isBioField ? "whitespace-pre-wrap break-words" : "break-words"
|
|
3737
4341
|
), children: formatValue(field.value, field.type, field.key) })
|
|
@@ -3743,26 +4347,26 @@ var UserProfile = ({
|
|
|
3743
4347
|
}) })
|
|
3744
4348
|
] })
|
|
3745
4349
|
] }),
|
|
3746
|
-
/* @__PURE__ */
|
|
3747
|
-
/* @__PURE__ */
|
|
3748
|
-
/* @__PURE__ */
|
|
3749
|
-
/* @__PURE__ */
|
|
3750
|
-
/* @__PURE__ */
|
|
4350
|
+
/* @__PURE__ */ jsx24(Separator, {}),
|
|
4351
|
+
/* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
|
|
4352
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between", children: [
|
|
4353
|
+
/* @__PURE__ */ jsxs14("h3", { className: "text-sm font-medium text-muted-foreground uppercase tracking-wider flex items-center gap-2", children: [
|
|
4354
|
+
/* @__PURE__ */ jsx24(Brain2, { className: "h-4 w-4" }),
|
|
3751
4355
|
labels.memories
|
|
3752
4356
|
] }),
|
|
3753
|
-
onAddMemory && /* @__PURE__ */
|
|
4357
|
+
onAddMemory && /* @__PURE__ */ jsx24(
|
|
3754
4358
|
Button,
|
|
3755
4359
|
{
|
|
3756
4360
|
variant: "ghost",
|
|
3757
4361
|
size: "sm",
|
|
3758
4362
|
className: "h-7 px-2",
|
|
3759
4363
|
onClick: () => setIsAddingMemory(true),
|
|
3760
|
-
children: /* @__PURE__ */
|
|
4364
|
+
children: /* @__PURE__ */ jsx24(Plus3, { className: "h-4 w-4" })
|
|
3761
4365
|
}
|
|
3762
4366
|
)
|
|
3763
4367
|
] }),
|
|
3764
|
-
isAddingMemory && onAddMemory && /* @__PURE__ */
|
|
3765
|
-
/* @__PURE__ */
|
|
4368
|
+
isAddingMemory && onAddMemory && /* @__PURE__ */ jsxs14("div", { className: "flex gap-2", children: [
|
|
4369
|
+
/* @__PURE__ */ jsx24(
|
|
3766
4370
|
Input,
|
|
3767
4371
|
{
|
|
3768
4372
|
value: newMemoryContent,
|
|
@@ -3779,24 +4383,24 @@ var UserProfile = ({
|
|
|
3779
4383
|
autoFocus: true
|
|
3780
4384
|
}
|
|
3781
4385
|
),
|
|
3782
|
-
/* @__PURE__ */
|
|
4386
|
+
/* @__PURE__ */ jsx24(Button, { size: "sm", onClick: handleAddMemory, disabled: !newMemoryContent.trim(), children: "Salvar" })
|
|
3783
4387
|
] }),
|
|
3784
|
-
/* @__PURE__ */
|
|
4388
|
+
/* @__PURE__ */ jsx24("div", { className: "space-y-2", children: memories.length === 0 ? /* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground text-center py-4", children: labels.noMemories }) : memories.map((memory) => {
|
|
3785
4389
|
const isEditing = editingMemoryId === memory.id;
|
|
3786
|
-
return /* @__PURE__ */
|
|
4390
|
+
return /* @__PURE__ */ jsxs14(
|
|
3787
4391
|
"div",
|
|
3788
4392
|
{
|
|
3789
4393
|
className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50 group",
|
|
3790
4394
|
children: [
|
|
3791
|
-
/* @__PURE__ */
|
|
3792
|
-
/* @__PURE__ */
|
|
3793
|
-
/* @__PURE__ */
|
|
3794
|
-
/* @__PURE__ */
|
|
3795
|
-
/* @__PURE__ */
|
|
3796
|
-
/* @__PURE__ */
|
|
4395
|
+
/* @__PURE__ */ jsx24("div", { className: "mt-0.5 shrink-0", children: memory.source === "agent" ? /* @__PURE__ */ jsx24(Bot3, { className: "h-4 w-4 text-primary" }) : getMemoryCategoryIcon(memory.category) }),
|
|
4396
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex-1 min-w-0", children: [
|
|
4397
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2 mb-0.5", children: [
|
|
4398
|
+
/* @__PURE__ */ jsx24("span", { className: "text-xs text-muted-foreground", children: getMemoryCategoryLabel(memory.category) }),
|
|
4399
|
+
/* @__PURE__ */ jsx24("span", { className: "text-xs text-muted-foreground", children: "\u2022" }),
|
|
4400
|
+
/* @__PURE__ */ jsx24("span", { className: "text-xs text-muted-foreground", children: memory.source === "agent" ? "IA" : "Voc\xEA" })
|
|
3797
4401
|
] }),
|
|
3798
|
-
isEditing ? /* @__PURE__ */
|
|
3799
|
-
/* @__PURE__ */
|
|
4402
|
+
isEditing ? /* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
|
|
4403
|
+
/* @__PURE__ */ jsx24(
|
|
3800
4404
|
Textarea,
|
|
3801
4405
|
{
|
|
3802
4406
|
value: editingMemoryContent,
|
|
@@ -3813,8 +4417,8 @@ var UserProfile = ({
|
|
|
3813
4417
|
}
|
|
3814
4418
|
}
|
|
3815
4419
|
),
|
|
3816
|
-
/* @__PURE__ */
|
|
3817
|
-
/* @__PURE__ */
|
|
4420
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex gap-1 justify-end", children: [
|
|
4421
|
+
/* @__PURE__ */ jsxs14(
|
|
3818
4422
|
Button,
|
|
3819
4423
|
{
|
|
3820
4424
|
variant: "ghost",
|
|
@@ -3822,12 +4426,12 @@ var UserProfile = ({
|
|
|
3822
4426
|
className: "h-7 px-2",
|
|
3823
4427
|
onClick: handleCancelEdit,
|
|
3824
4428
|
children: [
|
|
3825
|
-
/* @__PURE__ */
|
|
4429
|
+
/* @__PURE__ */ jsx24(X4, { className: "h-3.5 w-3.5 mr-1" }),
|
|
3826
4430
|
"Cancelar"
|
|
3827
4431
|
]
|
|
3828
4432
|
}
|
|
3829
4433
|
),
|
|
3830
|
-
/* @__PURE__ */
|
|
4434
|
+
/* @__PURE__ */ jsxs14(
|
|
3831
4435
|
Button,
|
|
3832
4436
|
{
|
|
3833
4437
|
size: "sm",
|
|
@@ -3835,33 +4439,33 @@ var UserProfile = ({
|
|
|
3835
4439
|
onClick: handleSaveEdit,
|
|
3836
4440
|
disabled: !editingMemoryContent.trim(),
|
|
3837
4441
|
children: [
|
|
3838
|
-
/* @__PURE__ */
|
|
4442
|
+
/* @__PURE__ */ jsx24(Check3, { className: "h-3.5 w-3.5 mr-1" }),
|
|
3839
4443
|
"Salvar"
|
|
3840
4444
|
]
|
|
3841
4445
|
}
|
|
3842
4446
|
)
|
|
3843
4447
|
] })
|
|
3844
|
-
] }) : /* @__PURE__ */
|
|
4448
|
+
] }) : /* @__PURE__ */ jsx24("p", { className: "text-sm break-words", children: memory.content })
|
|
3845
4449
|
] }),
|
|
3846
|
-
!isEditing && (onUpdateMemory || onDeleteMemory) && /* @__PURE__ */
|
|
3847
|
-
onUpdateMemory && /* @__PURE__ */
|
|
4450
|
+
!isEditing && (onUpdateMemory || onDeleteMemory) && /* @__PURE__ */ jsxs14("div", { className: "flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity shrink-0", children: [
|
|
4451
|
+
onUpdateMemory && /* @__PURE__ */ jsx24(
|
|
3848
4452
|
Button,
|
|
3849
4453
|
{
|
|
3850
4454
|
variant: "ghost",
|
|
3851
4455
|
size: "icon",
|
|
3852
4456
|
className: "h-7 w-7",
|
|
3853
4457
|
onClick: () => handleStartEdit(memory),
|
|
3854
|
-
children: /* @__PURE__ */
|
|
4458
|
+
children: /* @__PURE__ */ jsx24(Pencil, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
3855
4459
|
}
|
|
3856
4460
|
),
|
|
3857
|
-
onDeleteMemory && /* @__PURE__ */
|
|
4461
|
+
onDeleteMemory && /* @__PURE__ */ jsx24(
|
|
3858
4462
|
Button,
|
|
3859
4463
|
{
|
|
3860
4464
|
variant: "ghost",
|
|
3861
4465
|
size: "icon",
|
|
3862
4466
|
className: "h-7 w-7",
|
|
3863
4467
|
onClick: () => onDeleteMemory(memory.id),
|
|
3864
|
-
children: /* @__PURE__ */
|
|
4468
|
+
children: /* @__PURE__ */ jsx24(Trash23, { className: "h-3.5 w-3.5 text-destructive" })
|
|
3865
4469
|
}
|
|
3866
4470
|
)
|
|
3867
4471
|
] })
|
|
@@ -3872,8 +4476,8 @@ var UserProfile = ({
|
|
|
3872
4476
|
}) })
|
|
3873
4477
|
] })
|
|
3874
4478
|
] }) }),
|
|
3875
|
-
/* @__PURE__ */
|
|
3876
|
-
onEditProfile && /* @__PURE__ */
|
|
4479
|
+
/* @__PURE__ */ jsxs14("div", { className: "p-4 border-t space-y-2 shrink-0", children: [
|
|
4480
|
+
onEditProfile && /* @__PURE__ */ jsx24(
|
|
3877
4481
|
Button,
|
|
3878
4482
|
{
|
|
3879
4483
|
variant: "outline",
|
|
@@ -3882,7 +4486,7 @@ var UserProfile = ({
|
|
|
3882
4486
|
children: "Edit Profile"
|
|
3883
4487
|
}
|
|
3884
4488
|
),
|
|
3885
|
-
onLogout && /* @__PURE__ */
|
|
4489
|
+
onLogout && /* @__PURE__ */ jsx24(
|
|
3886
4490
|
Button,
|
|
3887
4491
|
{
|
|
3888
4492
|
variant: "destructive",
|
|
@@ -3899,7 +4503,7 @@ var UserProfile = ({
|
|
|
3899
4503
|
|
|
3900
4504
|
// src/components/chat/ChatUI.tsx
|
|
3901
4505
|
import { Sparkles, ArrowRight, MessageSquare, Lightbulb as Lightbulb2, Zap, HelpCircle } from "lucide-react";
|
|
3902
|
-
import { jsx as
|
|
4506
|
+
import { jsx as jsx25, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3903
4507
|
var ChatUI = ({
|
|
3904
4508
|
messages = [],
|
|
3905
4509
|
threads = [],
|
|
@@ -4165,13 +4769,13 @@ var ChatUI = ({
|
|
|
4165
4769
|
const SuggestionIconComponents = [MessageSquare, Lightbulb2, Zap, HelpCircle];
|
|
4166
4770
|
const renderSuggestions = () => {
|
|
4167
4771
|
if (messages.length > 0 || !suggestions.length) return null;
|
|
4168
|
-
return /* @__PURE__ */
|
|
4169
|
-
/* @__PURE__ */
|
|
4170
|
-
/* @__PURE__ */
|
|
4171
|
-
/* @__PURE__ */
|
|
4172
|
-
/* @__PURE__ */
|
|
4772
|
+
return /* @__PURE__ */ jsxs15("div", { className: "flex flex-col items-center justify-center min-h-[60vh] py-8 px-4", children: [
|
|
4773
|
+
/* @__PURE__ */ jsxs15("div", { className: "text-center mb-8", children: [
|
|
4774
|
+
/* @__PURE__ */ jsx25("div", { className: "inline-flex items-center justify-center w-14 h-14 rounded-2xl bg-gradient-to-br from-primary/20 to-primary/5 mb-4 shadow-sm", children: /* @__PURE__ */ jsx25(Sparkles, { className: "w-7 h-7 text-primary" }) }),
|
|
4775
|
+
/* @__PURE__ */ jsx25("h2", { className: "text-xl font-semibold mb-2", children: config.branding.title }),
|
|
4776
|
+
/* @__PURE__ */ jsx25("p", { className: "text-muted-foreground text-sm max-w-md", children: config.branding.subtitle })
|
|
4173
4777
|
] }),
|
|
4174
|
-
/* @__PURE__ */
|
|
4778
|
+
/* @__PURE__ */ jsx25("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3 w-full max-w-2xl", children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsxs15(
|
|
4175
4779
|
"button",
|
|
4176
4780
|
{
|
|
4177
4781
|
type: "button",
|
|
@@ -4180,10 +4784,10 @@ var ChatUI = ({
|
|
|
4180
4784
|
children: [
|
|
4181
4785
|
(() => {
|
|
4182
4786
|
const IconComponent = SuggestionIconComponents[index % SuggestionIconComponents.length];
|
|
4183
|
-
return /* @__PURE__ */
|
|
4787
|
+
return /* @__PURE__ */ jsx25("div", { className: "flex items-center justify-center w-8 h-8 rounded-lg bg-primary/10 text-primary shrink-0 group-hover:bg-primary/15 transition-colors", children: /* @__PURE__ */ jsx25(IconComponent, { className: "h-4 w-4" }) });
|
|
4184
4788
|
})(),
|
|
4185
|
-
/* @__PURE__ */
|
|
4186
|
-
/* @__PURE__ */
|
|
4789
|
+
/* @__PURE__ */ jsx25("div", { className: "flex-1 min-w-0 pr-6", children: /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium leading-snug line-clamp-2", children: suggestion }) }),
|
|
4790
|
+
/* @__PURE__ */ jsx25(ArrowRight, { className: "absolute right-4 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
|
|
4187
4791
|
]
|
|
4188
4792
|
},
|
|
4189
4793
|
index
|
|
@@ -4194,34 +4798,34 @@ var ChatUI = ({
|
|
|
4194
4798
|
const items = messageSuggestions?.[messageId];
|
|
4195
4799
|
if (!items || items.length === 0) return null;
|
|
4196
4800
|
const inlineSuggestionOffsetClass = config.ui.showAvatars ? config.ui.compactMode ? "ml-9" : "ml-11" : "";
|
|
4197
|
-
return /* @__PURE__ */
|
|
4801
|
+
return /* @__PURE__ */ jsx25("div", { className: `flex flex-wrap gap-2 mt-2 ${inlineSuggestionOffsetClass}`, children: items.map((suggestion, index) => /* @__PURE__ */ jsxs15(
|
|
4198
4802
|
"button",
|
|
4199
4803
|
{
|
|
4200
4804
|
type: "button",
|
|
4201
4805
|
onClick: () => handleSendMessage(suggestion),
|
|
4202
4806
|
className: "group inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full border border-border bg-background hover:bg-accent hover:border-accent-foreground/20 transition-all duration-150 text-foreground/80 hover:text-foreground",
|
|
4203
4807
|
children: [
|
|
4204
|
-
/* @__PURE__ */
|
|
4205
|
-
/* @__PURE__ */
|
|
4808
|
+
/* @__PURE__ */ jsx25(Sparkles, { className: "h-3 w-3 text-primary opacity-70 group-hover:opacity-100" }),
|
|
4809
|
+
/* @__PURE__ */ jsx25("span", { className: "max-w-[200px] truncate", children: suggestion })
|
|
4206
4810
|
]
|
|
4207
4811
|
},
|
|
4208
4812
|
`${messageId}-suggestion-${index}`
|
|
4209
4813
|
)) });
|
|
4210
4814
|
};
|
|
4211
|
-
const renderMessageLoadingSkeleton = () => /* @__PURE__ */
|
|
4815
|
+
const renderMessageLoadingSkeleton = () => /* @__PURE__ */ jsx25("div", { className: "space-y-6 py-2", children: [0, 1, 2, 3].map((index) => {
|
|
4212
4816
|
const isUserRow = index % 2 === 1;
|
|
4213
|
-
return /* @__PURE__ */
|
|
4817
|
+
return /* @__PURE__ */ jsxs15(
|
|
4214
4818
|
"div",
|
|
4215
4819
|
{
|
|
4216
4820
|
className: `flex gap-3 ${isUserRow ? "justify-end" : "justify-start"}`,
|
|
4217
4821
|
children: [
|
|
4218
|
-
!isUserRow && /* @__PURE__ */
|
|
4219
|
-
/* @__PURE__ */
|
|
4220
|
-
/* @__PURE__ */
|
|
4221
|
-
/* @__PURE__ */
|
|
4222
|
-
/* @__PURE__ */
|
|
4822
|
+
!isUserRow && /* @__PURE__ */ jsx25(Skeleton, { className: "h-8 w-8 rounded-full shrink-0" }),
|
|
4823
|
+
/* @__PURE__ */ jsxs15("div", { className: `space-y-2 ${isUserRow ? "w-[70%]" : "w-[75%]"}`, children: [
|
|
4824
|
+
/* @__PURE__ */ jsx25(Skeleton, { className: "h-4 w-24" }),
|
|
4825
|
+
/* @__PURE__ */ jsx25(Skeleton, { className: "h-4 w-full" }),
|
|
4826
|
+
/* @__PURE__ */ jsx25(Skeleton, { className: "h-4 w-[85%]" })
|
|
4223
4827
|
] }),
|
|
4224
|
-
isUserRow && /* @__PURE__ */
|
|
4828
|
+
isUserRow && /* @__PURE__ */ jsx25(Skeleton, { className: "h-8 w-8 rounded-full shrink-0" })
|
|
4225
4829
|
]
|
|
4226
4830
|
},
|
|
4227
4831
|
`message-skeleton-${index}`
|
|
@@ -4277,8 +4881,8 @@ var ChatUI = ({
|
|
|
4277
4881
|
const shouldShowAgentSelector = Boolean(
|
|
4278
4882
|
config.agentSelector?.enabled && onSelectAgent && agentOptions.length > 0 && (!config.agentSelector?.hideIfSingle || agentOptions.length > 1)
|
|
4279
4883
|
);
|
|
4280
|
-
return /* @__PURE__ */
|
|
4281
|
-
/* @__PURE__ */
|
|
4884
|
+
return /* @__PURE__ */ jsx25(TooltipProvider, { children: /* @__PURE__ */ jsx25(SidebarProvider, { defaultOpen: true, children: /* @__PURE__ */ jsxs15("div", { className: `flex h-[100svh] md:h-screen bg-background w-full overflow-hidden ${className}`, children: [
|
|
4885
|
+
/* @__PURE__ */ jsx25(
|
|
4282
4886
|
Sidebar2,
|
|
4283
4887
|
{
|
|
4284
4888
|
threads,
|
|
@@ -4295,8 +4899,8 @@ var ChatUI = ({
|
|
|
4295
4899
|
showThemeOptions: !!callbacks.onThemeChange
|
|
4296
4900
|
}
|
|
4297
4901
|
),
|
|
4298
|
-
/* @__PURE__ */
|
|
4299
|
-
/* @__PURE__ */
|
|
4902
|
+
/* @__PURE__ */ jsx25(SidebarInset, { children: /* @__PURE__ */ jsxs15("div", { className: "flex flex-col h-full min-h-0", children: [
|
|
4903
|
+
/* @__PURE__ */ jsx25(
|
|
4300
4904
|
ChatHeader,
|
|
4301
4905
|
{
|
|
4302
4906
|
config,
|
|
@@ -4311,9 +4915,9 @@ var ChatUI = ({
|
|
|
4311
4915
|
onSelectAgent
|
|
4312
4916
|
}
|
|
4313
4917
|
),
|
|
4314
|
-
/* @__PURE__ */
|
|
4315
|
-
/* @__PURE__ */
|
|
4316
|
-
/* @__PURE__ */
|
|
4918
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex flex-1 flex-row min-h-0 overflow-hidden", children: [
|
|
4919
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex-1 flex flex-col min-h-0", children: [
|
|
4920
|
+
/* @__PURE__ */ jsx25(
|
|
4317
4921
|
ScrollArea,
|
|
4318
4922
|
{
|
|
4319
4923
|
ref: scrollAreaRef,
|
|
@@ -4321,7 +4925,7 @@ var ChatUI = ({
|
|
|
4321
4925
|
viewportClassName: "p-4 overscroll-contain",
|
|
4322
4926
|
onScrollCapture: handleScroll,
|
|
4323
4927
|
style: { contain: "strict" },
|
|
4324
|
-
children: /* @__PURE__ */
|
|
4928
|
+
children: /* @__PURE__ */ jsx25("div", { className: "max-w-4xl mx-auto pb-4", children: isMessagesLoading ? renderMessageLoadingSkeleton() : messages.length === 0 ? renderSuggestions() : /* @__PURE__ */ jsx25(
|
|
4325
4929
|
"div",
|
|
4326
4930
|
{
|
|
4327
4931
|
style: {
|
|
@@ -4333,7 +4937,7 @@ var ChatUI = ({
|
|
|
4333
4937
|
const message = messages[virtualRow.index];
|
|
4334
4938
|
const prevMessage = virtualRow.index > 0 ? messages[virtualRow.index - 1] : null;
|
|
4335
4939
|
const isGrouped = prevMessage !== null && prevMessage.role === message.role;
|
|
4336
|
-
return /* @__PURE__ */
|
|
4940
|
+
return /* @__PURE__ */ jsx25(
|
|
4337
4941
|
"div",
|
|
4338
4942
|
{
|
|
4339
4943
|
"data-index": virtualRow.index,
|
|
@@ -4345,8 +4949,8 @@ var ChatUI = ({
|
|
|
4345
4949
|
width: "100%",
|
|
4346
4950
|
transform: `translateY(${virtualRow.start}px)`
|
|
4347
4951
|
},
|
|
4348
|
-
children: /* @__PURE__ */
|
|
4349
|
-
/* @__PURE__ */
|
|
4952
|
+
children: /* @__PURE__ */ jsxs15("div", { className: virtualRow.index === 0 ? "" : isGrouped ? "pt-2" : "pt-4", children: [
|
|
4953
|
+
/* @__PURE__ */ jsx25(
|
|
4350
4954
|
Message,
|
|
4351
4955
|
{
|
|
4352
4956
|
message,
|
|
@@ -4365,7 +4969,7 @@ var ChatUI = ({
|
|
|
4365
4969
|
) })
|
|
4366
4970
|
}
|
|
4367
4971
|
),
|
|
4368
|
-
/* @__PURE__ */
|
|
4972
|
+
/* @__PURE__ */ jsx25("div", { className: "bg-background pb-[env(safe-area-inset-bottom)]", children: /* @__PURE__ */ jsx25(
|
|
4369
4973
|
ChatInput,
|
|
4370
4974
|
{
|
|
4371
4975
|
value: inputValue,
|
|
@@ -4391,17 +4995,17 @@ var ChatUI = ({
|
|
|
4391
4995
|
}
|
|
4392
4996
|
) })
|
|
4393
4997
|
] }),
|
|
4394
|
-
config?.customComponent?.component && !isMobile && /* @__PURE__ */
|
|
4998
|
+
config?.customComponent?.component && !isMobile && /* @__PURE__ */ jsx25(
|
|
4395
4999
|
"div",
|
|
4396
5000
|
{
|
|
4397
5001
|
className: `h-full transition-all duration-300 ease-in-out overflow-hidden ${state.showSidebar ? "w-80" : "w-0"}`,
|
|
4398
|
-
children: state.showSidebar && /* @__PURE__ */
|
|
5002
|
+
children: state.showSidebar && /* @__PURE__ */ jsx25("div", { className: "flex flex-col h-full border-l bg-background animate-in slide-in-from-right-4 duration-300 w-80", children: renderCustomComponent() })
|
|
4399
5003
|
}
|
|
4400
5004
|
)
|
|
4401
5005
|
] })
|
|
4402
5006
|
] }) }),
|
|
4403
|
-
isCustomMounted && config.customComponent?.component && isMobile && /* @__PURE__ */
|
|
4404
|
-
/* @__PURE__ */
|
|
5007
|
+
isCustomMounted && config.customComponent?.component && isMobile && /* @__PURE__ */ jsxs15("div", { className: "fixed inset-0 z-50", children: [
|
|
5008
|
+
/* @__PURE__ */ jsx25(
|
|
4405
5009
|
"div",
|
|
4406
5010
|
{
|
|
4407
5011
|
className: `absolute inset-0 bg-background/80 backdrop-blur-sm transition-opacity duration-200 ease-out ${isCustomVisible ? "opacity-100" : "opacity-0"}`,
|
|
@@ -4409,16 +5013,16 @@ var ChatUI = ({
|
|
|
4409
5013
|
onClick: closeSidebar
|
|
4410
5014
|
}
|
|
4411
5015
|
),
|
|
4412
|
-
/* @__PURE__ */
|
|
5016
|
+
/* @__PURE__ */ jsx25(
|
|
4413
5017
|
"div",
|
|
4414
5018
|
{
|
|
4415
5019
|
className: `absolute top-0 right-0 h-full w-full bg-background transform-gpu transition-transform duration-200 ease-out ${isCustomVisible ? "translate-x-0" : "translate-x-full"}`,
|
|
4416
5020
|
style: { willChange: "transform" },
|
|
4417
|
-
children: /* @__PURE__ */
|
|
5021
|
+
children: /* @__PURE__ */ jsx25("div", { className: "h-full flex flex-col", children: renderCustomComponent() })
|
|
4418
5022
|
}
|
|
4419
5023
|
)
|
|
4420
5024
|
] }),
|
|
4421
|
-
isUserProfileOpen && /* @__PURE__ */
|
|
5025
|
+
isUserProfileOpen && /* @__PURE__ */ jsx25(
|
|
4422
5026
|
UserProfile,
|
|
4423
5027
|
{
|
|
4424
5028
|
isOpen: isUserProfileOpen,
|
|
@@ -4453,10 +5057,10 @@ import {
|
|
|
4453
5057
|
Filter as Filter2,
|
|
4454
5058
|
Calendar as Calendar2,
|
|
4455
5059
|
Hash,
|
|
4456
|
-
X as
|
|
5060
|
+
X as X5,
|
|
4457
5061
|
Check as Check4
|
|
4458
5062
|
} from "lucide-react";
|
|
4459
|
-
import { Fragment as
|
|
5063
|
+
import { Fragment as Fragment7, jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4460
5064
|
var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onArchive }) => {
|
|
4461
5065
|
const [isEditing, setIsEditing] = useState9(false);
|
|
4462
5066
|
const [editTitle, setEditTitle] = useState9(thread.title);
|
|
@@ -4485,9 +5089,9 @@ var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onAr
|
|
|
4485
5089
|
handleCancelEdit();
|
|
4486
5090
|
}
|
|
4487
5091
|
};
|
|
4488
|
-
return /* @__PURE__ */
|
|
4489
|
-
/* @__PURE__ */
|
|
4490
|
-
/* @__PURE__ */
|
|
5092
|
+
return /* @__PURE__ */ jsx26(Card, { className: `cursor-pointer transition-all duration-200 hover:shadow-md py-0 ${isActive ? "ring-2 ring-primary bg-primary/5" : "hover:bg-muted/50"}`, children: /* @__PURE__ */ jsx26(CardContent, { className: "p-3 max-w-sm", children: /* @__PURE__ */ jsxs16("div", { className: "flex items-start justify-between gap-2", children: [
|
|
5093
|
+
/* @__PURE__ */ jsx26("div", { className: "flex-1 min-w-0", onClick: onSelect, children: isEditing ? /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2", children: [
|
|
5094
|
+
/* @__PURE__ */ jsx26(
|
|
4491
5095
|
Input,
|
|
4492
5096
|
{
|
|
4493
5097
|
ref: inputRef,
|
|
@@ -4499,44 +5103,44 @@ var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onAr
|
|
|
4499
5103
|
placeholder: config?.labels?.threadNamePlaceholder || "Conversation name"
|
|
4500
5104
|
}
|
|
4501
5105
|
),
|
|
4502
|
-
/* @__PURE__ */
|
|
4503
|
-
/* @__PURE__ */
|
|
4504
|
-
] }) : /* @__PURE__ */
|
|
4505
|
-
/* @__PURE__ */
|
|
4506
|
-
/* @__PURE__ */
|
|
4507
|
-
/* @__PURE__ */
|
|
4508
|
-
/* @__PURE__ */
|
|
5106
|
+
/* @__PURE__ */ jsx26(Button, { size: "sm", variant: "ghost", onClick: handleSaveEdit, children: /* @__PURE__ */ jsx26(Check4, { className: "h-3 w-3" }) }),
|
|
5107
|
+
/* @__PURE__ */ jsx26(Button, { size: "sm", variant: "ghost", onClick: handleCancelEdit, children: /* @__PURE__ */ jsx26(X5, { className: "h-3 w-3" }) })
|
|
5108
|
+
] }) : /* @__PURE__ */ jsxs16(Fragment7, { children: [
|
|
5109
|
+
/* @__PURE__ */ jsx26("h4", { className: "font-medium text-sm truncate mb-1", children: thread.title }),
|
|
5110
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
5111
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-1", children: [
|
|
5112
|
+
/* @__PURE__ */ jsx26(Hash, { className: "h-3 w-3" }),
|
|
4509
5113
|
thread.messageCount,
|
|
4510
5114
|
" msgs"
|
|
4511
5115
|
] }),
|
|
4512
|
-
/* @__PURE__ */
|
|
4513
|
-
/* @__PURE__ */
|
|
4514
|
-
/* @__PURE__ */
|
|
5116
|
+
/* @__PURE__ */ jsx26(Separator, { orientation: "vertical", className: "h-3" }),
|
|
5117
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-1", children: [
|
|
5118
|
+
/* @__PURE__ */ jsx26(Calendar2, { className: "h-3 w-3" }),
|
|
4515
5119
|
formatDate(thread.updatedAt, config?.labels)
|
|
4516
5120
|
] }),
|
|
4517
|
-
thread.isArchived && /* @__PURE__ */
|
|
4518
|
-
/* @__PURE__ */
|
|
4519
|
-
/* @__PURE__ */
|
|
4520
|
-
/* @__PURE__ */
|
|
5121
|
+
thread.isArchived && /* @__PURE__ */ jsxs16(Fragment7, { children: [
|
|
5122
|
+
/* @__PURE__ */ jsx26(Separator, { orientation: "vertical", className: "h-3" }),
|
|
5123
|
+
/* @__PURE__ */ jsxs16(Badge, { variant: "secondary", className: "text-xs", children: [
|
|
5124
|
+
/* @__PURE__ */ jsx26(Archive2, { className: "h-2 w-2 mr-1" }),
|
|
4521
5125
|
config?.labels?.archiveThread || "Archived"
|
|
4522
5126
|
] })
|
|
4523
5127
|
] })
|
|
4524
5128
|
] })
|
|
4525
5129
|
] }) }),
|
|
4526
|
-
!isEditing && /* @__PURE__ */
|
|
4527
|
-
/* @__PURE__ */
|
|
4528
|
-
/* @__PURE__ */
|
|
4529
|
-
/* @__PURE__ */
|
|
4530
|
-
/* @__PURE__ */
|
|
5130
|
+
!isEditing && /* @__PURE__ */ jsxs16(DropdownMenu, { children: [
|
|
5131
|
+
/* @__PURE__ */ jsx26(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(Button, { variant: "ghost", size: "icon", className: "h-6 w-6 m-auto", children: /* @__PURE__ */ jsx26(MoreVertical2, { className: "h-3 w-3" }) }) }),
|
|
5132
|
+
/* @__PURE__ */ jsxs16(DropdownMenuContent, { align: "end", children: [
|
|
5133
|
+
/* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: () => setIsEditing(true), children: [
|
|
5134
|
+
/* @__PURE__ */ jsx26(Edit22, { className: "h-4 w-4 mr-2" }),
|
|
4531
5135
|
config?.labels?.renameThread || "Rename"
|
|
4532
5136
|
] }),
|
|
4533
|
-
/* @__PURE__ */
|
|
4534
|
-
/* @__PURE__ */
|
|
5137
|
+
/* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: onArchive, children: [
|
|
5138
|
+
/* @__PURE__ */ jsx26(Archive2, { className: "h-4 w-4 mr-2" }),
|
|
4535
5139
|
thread.isArchived ? config?.labels?.unarchiveThread || "Unarchive" : config?.labels?.archiveThread || "Archive"
|
|
4536
5140
|
] }),
|
|
4537
|
-
/* @__PURE__ */
|
|
4538
|
-
/* @__PURE__ */
|
|
4539
|
-
/* @__PURE__ */
|
|
5141
|
+
/* @__PURE__ */ jsx26(DropdownMenuSeparator, {}),
|
|
5142
|
+
/* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: onDelete, className: "text-destructive", children: [
|
|
5143
|
+
/* @__PURE__ */ jsx26(Trash24, { className: "h-4 w-4 mr-2" }),
|
|
4540
5144
|
config?.labels?.deleteThread || "Delete"
|
|
4541
5145
|
] })
|
|
4542
5146
|
] })
|
|
@@ -4551,17 +5155,17 @@ var CreateThreadDialog2 = ({ onCreateThread, config }) => {
|
|
|
4551
5155
|
setTitle("");
|
|
4552
5156
|
setIsOpen(false);
|
|
4553
5157
|
};
|
|
4554
|
-
return /* @__PURE__ */
|
|
4555
|
-
/* @__PURE__ */
|
|
4556
|
-
/* @__PURE__ */
|
|
5158
|
+
return /* @__PURE__ */ jsxs16(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: [
|
|
5159
|
+
/* @__PURE__ */ jsx26(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs16(Button, { variant: "outline", className: "w-full", children: [
|
|
5160
|
+
/* @__PURE__ */ jsx26(Plus4, { className: "h-4 w-4 mr-2" }),
|
|
4557
5161
|
config?.labels?.createNewThread || "New Conversation"
|
|
4558
5162
|
] }) }),
|
|
4559
|
-
/* @__PURE__ */
|
|
4560
|
-
/* @__PURE__ */
|
|
4561
|
-
/* @__PURE__ */
|
|
4562
|
-
/* @__PURE__ */
|
|
5163
|
+
/* @__PURE__ */ jsxs16(DialogContent, { children: [
|
|
5164
|
+
/* @__PURE__ */ jsxs16(DialogHeader, { children: [
|
|
5165
|
+
/* @__PURE__ */ jsx26(DialogTitle, { children: config?.labels?.createNewThread || "Create New Conversation" }),
|
|
5166
|
+
/* @__PURE__ */ jsx26(DialogDescription, { children: "Give your new conversation a name or leave blank to auto-generate one." })
|
|
4563
5167
|
] }),
|
|
4564
|
-
/* @__PURE__ */
|
|
5168
|
+
/* @__PURE__ */ jsx26(
|
|
4565
5169
|
Input,
|
|
4566
5170
|
{
|
|
4567
5171
|
value: title,
|
|
@@ -4571,9 +5175,9 @@ var CreateThreadDialog2 = ({ onCreateThread, config }) => {
|
|
|
4571
5175
|
autoFocus: true
|
|
4572
5176
|
}
|
|
4573
5177
|
),
|
|
4574
|
-
/* @__PURE__ */
|
|
4575
|
-
/* @__PURE__ */
|
|
4576
|
-
/* @__PURE__ */
|
|
5178
|
+
/* @__PURE__ */ jsxs16(DialogFooter, { children: [
|
|
5179
|
+
/* @__PURE__ */ jsx26(Button, { variant: "outline", onClick: () => setIsOpen(false), children: config?.labels?.cancel || "Cancel" }),
|
|
5180
|
+
/* @__PURE__ */ jsx26(Button, { onClick: handleCreate, children: config?.labels?.create || "Create" })
|
|
4577
5181
|
] })
|
|
4578
5182
|
] })
|
|
4579
5183
|
] });
|
|
@@ -4627,20 +5231,20 @@ var ThreadManager = ({
|
|
|
4627
5231
|
setDeleteThreadId(null);
|
|
4628
5232
|
};
|
|
4629
5233
|
if (!isOpen) return null;
|
|
4630
|
-
return /* @__PURE__ */
|
|
4631
|
-
/* @__PURE__ */
|
|
4632
|
-
/* @__PURE__ */
|
|
4633
|
-
/* @__PURE__ */
|
|
4634
|
-
/* @__PURE__ */
|
|
4635
|
-
/* @__PURE__ */
|
|
5234
|
+
return /* @__PURE__ */ jsx26(TooltipProvider, { children: /* @__PURE__ */ jsxs16("div", { className: `fixed inset-0 z-50 bg-background/80 backdrop-blur-sm ${className}`, children: [
|
|
5235
|
+
/* @__PURE__ */ jsx26("div", { className: "fixed left-0 top-0 h-full w-full max-w-md border-r bg-background shadow-lg", children: /* @__PURE__ */ jsxs16(Card, { className: "h-full border-0 rounded-none", children: [
|
|
5236
|
+
/* @__PURE__ */ jsxs16(CardHeader, { className: "border-b", children: [
|
|
5237
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between", children: [
|
|
5238
|
+
/* @__PURE__ */ jsxs16(CardTitle, { className: "flex items-center gap-2", children: [
|
|
5239
|
+
/* @__PURE__ */ jsx26(MessageSquare2, { className: "h-5 w-5" }),
|
|
4636
5240
|
config?.labels?.newChat || "Conversations"
|
|
4637
5241
|
] }),
|
|
4638
|
-
/* @__PURE__ */
|
|
5242
|
+
/* @__PURE__ */ jsx26(Button, { variant: "ghost", size: "icon", onClick: onClose, children: /* @__PURE__ */ jsx26(X5, { className: "h-4 w-4" }) })
|
|
4639
5243
|
] }),
|
|
4640
|
-
/* @__PURE__ */
|
|
4641
|
-
/* @__PURE__ */
|
|
4642
|
-
/* @__PURE__ */
|
|
4643
|
-
/* @__PURE__ */
|
|
5244
|
+
/* @__PURE__ */ jsxs16("div", { className: "space-y-3", children: [
|
|
5245
|
+
/* @__PURE__ */ jsxs16("div", { className: "relative", children: [
|
|
5246
|
+
/* @__PURE__ */ jsx26(Search2, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
5247
|
+
/* @__PURE__ */ jsx26(
|
|
4644
5248
|
Input,
|
|
4645
5249
|
{
|
|
4646
5250
|
placeholder: config?.labels?.search || "Search conversations...",
|
|
@@ -4650,8 +5254,8 @@ var ThreadManager = ({
|
|
|
4650
5254
|
}
|
|
4651
5255
|
)
|
|
4652
5256
|
] }),
|
|
4653
|
-
/* @__PURE__ */
|
|
4654
|
-
/* @__PURE__ */
|
|
5257
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between", children: [
|
|
5258
|
+
/* @__PURE__ */ jsxs16(
|
|
4655
5259
|
Button,
|
|
4656
5260
|
{
|
|
4657
5261
|
variant: "outline",
|
|
@@ -4659,12 +5263,12 @@ var ThreadManager = ({
|
|
|
4659
5263
|
onClick: () => setShowArchived(!showArchived),
|
|
4660
5264
|
className: "text-xs",
|
|
4661
5265
|
children: [
|
|
4662
|
-
/* @__PURE__ */
|
|
5266
|
+
/* @__PURE__ */ jsx26(Filter2, { className: "h-3 w-3 mr-1" }),
|
|
4663
5267
|
showArchived ? config?.labels?.hideArchived || "Hide Archived" : config?.labels?.showArchived || "Show Archived"
|
|
4664
5268
|
]
|
|
4665
5269
|
}
|
|
4666
5270
|
),
|
|
4667
|
-
/* @__PURE__ */
|
|
5271
|
+
/* @__PURE__ */ jsxs16(Badge, { variant: "secondary", className: "text-xs", children: [
|
|
4668
5272
|
filteredThreads.length,
|
|
4669
5273
|
" / ",
|
|
4670
5274
|
threads.length
|
|
@@ -4672,14 +5276,14 @@ var ThreadManager = ({
|
|
|
4672
5276
|
] })
|
|
4673
5277
|
] })
|
|
4674
5278
|
] }),
|
|
4675
|
-
/* @__PURE__ */
|
|
4676
|
-
/* @__PURE__ */
|
|
4677
|
-
/* @__PURE__ */
|
|
4678
|
-
/* @__PURE__ */
|
|
4679
|
-
/* @__PURE__ */
|
|
4680
|
-
] }) : Object.entries(groupedThreads).map(([group, groupThreads]) => /* @__PURE__ */
|
|
4681
|
-
/* @__PURE__ */
|
|
4682
|
-
/* @__PURE__ */
|
|
5279
|
+
/* @__PURE__ */ jsxs16(CardContent, { className: "p-0 flex-1", children: [
|
|
5280
|
+
/* @__PURE__ */ jsx26("div", { className: "p-4", children: onCreateThread && /* @__PURE__ */ jsx26(CreateThreadDialog2, { onCreateThread, config }) }),
|
|
5281
|
+
/* @__PURE__ */ jsx26(ScrollArea, { className: "h-[calc(100vh-280px)]", children: /* @__PURE__ */ jsx26("div", { className: "px-4 pb-4 space-y-4", children: Object.keys(groupedThreads).length === 0 ? /* @__PURE__ */ jsxs16("div", { className: "text-center py-8 text-muted-foreground", children: [
|
|
5282
|
+
/* @__PURE__ */ jsx26(MessageSquare2, { className: "h-12 w-12 mx-auto mb-3 opacity-50" }),
|
|
5283
|
+
/* @__PURE__ */ jsx26("p", { className: "text-sm", children: searchQuery ? config?.labels?.noThreadsFound || "No conversations found" : config?.labels?.noThreadsYet || "No conversations yet" })
|
|
5284
|
+
] }) : Object.entries(groupedThreads).map(([group, groupThreads]) => /* @__PURE__ */ jsxs16("div", { children: [
|
|
5285
|
+
/* @__PURE__ */ jsx26("h3", { className: "text-sm font-medium text-muted-foreground mb-2 px-2", children: group }),
|
|
5286
|
+
/* @__PURE__ */ jsx26("div", { className: "space-y-2", children: groupThreads.map((thread) => /* @__PURE__ */ jsx26(
|
|
4683
5287
|
ThreadItem,
|
|
4684
5288
|
{
|
|
4685
5289
|
thread,
|
|
@@ -4695,14 +5299,14 @@ var ThreadManager = ({
|
|
|
4695
5299
|
] }, group)) }) })
|
|
4696
5300
|
] })
|
|
4697
5301
|
] }) }),
|
|
4698
|
-
deleteThreadId && /* @__PURE__ */
|
|
4699
|
-
/* @__PURE__ */
|
|
4700
|
-
/* @__PURE__ */
|
|
4701
|
-
/* @__PURE__ */
|
|
5302
|
+
deleteThreadId && /* @__PURE__ */ jsx26(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ jsxs16(AlertDialogContent, { children: [
|
|
5303
|
+
/* @__PURE__ */ jsxs16(AlertDialogHeader, { children: [
|
|
5304
|
+
/* @__PURE__ */ jsx26(AlertDialogTitle, { children: config?.labels?.deleteConfirmTitle || "Delete Conversation" }),
|
|
5305
|
+
/* @__PURE__ */ jsx26(AlertDialogDescription, { children: config?.labels?.deleteConfirmDescription || "Are you sure you want to delete this conversation? This action cannot be undone." })
|
|
4702
5306
|
] }),
|
|
4703
|
-
/* @__PURE__ */
|
|
4704
|
-
/* @__PURE__ */
|
|
4705
|
-
/* @__PURE__ */
|
|
5307
|
+
/* @__PURE__ */ jsxs16(AlertDialogFooter, { children: [
|
|
5308
|
+
/* @__PURE__ */ jsx26(AlertDialogCancel, { children: config?.labels?.cancel || "Cancel" }),
|
|
5309
|
+
/* @__PURE__ */ jsx26(
|
|
4706
5310
|
AlertDialogAction,
|
|
4707
5311
|
{
|
|
4708
5312
|
onClick: () => deleteThreadId && handleDeleteThread(deleteThreadId),
|