@copilotz/chat-ui 0.1.30 → 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.cjs
CHANGED
|
@@ -86,6 +86,23 @@ var defaultChatConfig = {
|
|
|
86
86
|
attachFileTooltip: "Attach file",
|
|
87
87
|
recordAudio: "Record Audio",
|
|
88
88
|
recordAudioTooltip: "Record audio",
|
|
89
|
+
voiceEnter: "Voice input",
|
|
90
|
+
voiceExit: "Use keyboard",
|
|
91
|
+
voiceTitle: "Voice input",
|
|
92
|
+
voicePreparing: "Preparing microphone...",
|
|
93
|
+
voiceWaiting: "Waiting for speech...",
|
|
94
|
+
voiceListening: "Listening...",
|
|
95
|
+
voiceFinishing: "Finishing capture...",
|
|
96
|
+
voiceReview: "Ready to send",
|
|
97
|
+
voiceStart: "Start recording",
|
|
98
|
+
voiceStop: "Stop recording",
|
|
99
|
+
voiceSendNow: "Send now",
|
|
100
|
+
voiceCancel: "Cancel",
|
|
101
|
+
voiceRecordAgain: "Record again",
|
|
102
|
+
voiceAutoSendIn: "Auto-sends in {{seconds}}s",
|
|
103
|
+
voiceTranscriptPending: "Transcript unavailable",
|
|
104
|
+
voicePermissionDenied: "Microphone access was denied.",
|
|
105
|
+
voiceCaptureError: "Unable to capture audio.",
|
|
89
106
|
// Header labels
|
|
90
107
|
exportData: "Export data",
|
|
91
108
|
importData: "Import data",
|
|
@@ -148,6 +165,15 @@ var defaultChatConfig = {
|
|
|
148
165
|
longMessageChunkChars: 12e3,
|
|
149
166
|
renderUserMarkdown: true
|
|
150
167
|
},
|
|
168
|
+
voiceCompose: {
|
|
169
|
+
enabled: false,
|
|
170
|
+
autoSendDelayMs: 5e3,
|
|
171
|
+
persistComposer: true,
|
|
172
|
+
showTranscriptPreview: true,
|
|
173
|
+
transcriptMode: "final-only",
|
|
174
|
+
maxRecordingMs: 6e4,
|
|
175
|
+
createProvider: void 0
|
|
176
|
+
},
|
|
151
177
|
customComponent: {},
|
|
152
178
|
headerActions: null
|
|
153
179
|
};
|
|
@@ -170,6 +196,10 @@ function mergeConfig(_baseConfig, userConfig) {
|
|
|
170
196
|
...defaultChatConfig.ui,
|
|
171
197
|
...userConfig.ui
|
|
172
198
|
},
|
|
199
|
+
voiceCompose: {
|
|
200
|
+
...defaultChatConfig.voiceCompose,
|
|
201
|
+
...userConfig.voiceCompose
|
|
202
|
+
},
|
|
173
203
|
agentSelector: {
|
|
174
204
|
...defaultChatConfig.agentSelector,
|
|
175
205
|
...userConfig.agentSelector
|
|
@@ -777,7 +807,7 @@ var MediaRenderer = (0, import_react.memo)(function MediaRenderer2({ attachment
|
|
|
777
807
|
URL.revokeObjectURL(objectUrl);
|
|
778
808
|
};
|
|
779
809
|
}, [attachment.kind, attachment.dataUrl]);
|
|
780
|
-
const
|
|
810
|
+
const formatDuration2 = (ms) => {
|
|
781
811
|
if (!ms) return "";
|
|
782
812
|
const seconds = Math.floor(ms / 1e3);
|
|
783
813
|
const minutes = Math.floor(seconds / 60);
|
|
@@ -2810,6 +2840,215 @@ function useChatUserContext() {
|
|
|
2810
2840
|
return v;
|
|
2811
2841
|
}
|
|
2812
2842
|
|
|
2843
|
+
// src/lib/voiceCompose.ts
|
|
2844
|
+
var AUDIO_MIME_TYPES = [
|
|
2845
|
+
"audio/webm;codecs=opus",
|
|
2846
|
+
"audio/webm",
|
|
2847
|
+
"audio/mp4",
|
|
2848
|
+
"audio/ogg;codecs=opus"
|
|
2849
|
+
];
|
|
2850
|
+
var pickRecorderMimeType = () => {
|
|
2851
|
+
if (typeof MediaRecorder === "undefined") return void 0;
|
|
2852
|
+
for (const mimeType of AUDIO_MIME_TYPES) {
|
|
2853
|
+
if (typeof MediaRecorder.isTypeSupported === "function" && MediaRecorder.isTypeSupported(mimeType)) {
|
|
2854
|
+
return mimeType;
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
return void 0;
|
|
2858
|
+
};
|
|
2859
|
+
var blobToDataUrl = (blob) => new Promise((resolve, reject) => {
|
|
2860
|
+
const reader = new FileReader();
|
|
2861
|
+
reader.onload = () => resolve(reader.result);
|
|
2862
|
+
reader.onerror = () => reject(reader.error ?? new Error("Failed to read recorded audio"));
|
|
2863
|
+
reader.readAsDataURL(blob);
|
|
2864
|
+
});
|
|
2865
|
+
var stopStream = (stream) => {
|
|
2866
|
+
if (!stream) return;
|
|
2867
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
2868
|
+
};
|
|
2869
|
+
var closeAudioContext = async (audioContext) => {
|
|
2870
|
+
if (!audioContext) return;
|
|
2871
|
+
try {
|
|
2872
|
+
await audioContext.close();
|
|
2873
|
+
} catch {
|
|
2874
|
+
}
|
|
2875
|
+
};
|
|
2876
|
+
var emitDuration = (handlers, startedAt) => {
|
|
2877
|
+
handlers.onDurationChange?.(Math.max(0, Date.now() - startedAt));
|
|
2878
|
+
};
|
|
2879
|
+
var createManualVoiceProvider = async (handlers, options = {}) => {
|
|
2880
|
+
let mediaRecorder = null;
|
|
2881
|
+
let mediaStream = null;
|
|
2882
|
+
let audioContext = null;
|
|
2883
|
+
let analyser = null;
|
|
2884
|
+
let levelData = null;
|
|
2885
|
+
let levelFrame = 0;
|
|
2886
|
+
let durationTimer = null;
|
|
2887
|
+
let maxDurationTimer = null;
|
|
2888
|
+
let startedAt = 0;
|
|
2889
|
+
let shouldEmitSegment = true;
|
|
2890
|
+
let isStarting = false;
|
|
2891
|
+
const clearTimers = () => {
|
|
2892
|
+
if (durationTimer) {
|
|
2893
|
+
clearInterval(durationTimer);
|
|
2894
|
+
durationTimer = null;
|
|
2895
|
+
}
|
|
2896
|
+
if (maxDurationTimer) {
|
|
2897
|
+
clearTimeout(maxDurationTimer);
|
|
2898
|
+
maxDurationTimer = null;
|
|
2899
|
+
}
|
|
2900
|
+
};
|
|
2901
|
+
const stopLevelLoop = () => {
|
|
2902
|
+
if (levelFrame) {
|
|
2903
|
+
cancelAnimationFrame(levelFrame);
|
|
2904
|
+
levelFrame = 0;
|
|
2905
|
+
}
|
|
2906
|
+
handlers.onAudioLevelChange?.(0);
|
|
2907
|
+
};
|
|
2908
|
+
const startLevelLoop = () => {
|
|
2909
|
+
if (!analyser || !levelData) return;
|
|
2910
|
+
const tick = () => {
|
|
2911
|
+
if (!analyser || !levelData) return;
|
|
2912
|
+
analyser.getByteTimeDomainData(levelData);
|
|
2913
|
+
let sum = 0;
|
|
2914
|
+
for (let index = 0; index < levelData.length; index += 1) {
|
|
2915
|
+
const centered = (levelData[index] - 128) / 128;
|
|
2916
|
+
sum += centered * centered;
|
|
2917
|
+
}
|
|
2918
|
+
const rms = Math.sqrt(sum / levelData.length);
|
|
2919
|
+
handlers.onAudioLevelChange?.(Math.min(1, rms * 4));
|
|
2920
|
+
levelFrame = requestAnimationFrame(tick);
|
|
2921
|
+
};
|
|
2922
|
+
tick();
|
|
2923
|
+
};
|
|
2924
|
+
const cleanupActiveResources = async () => {
|
|
2925
|
+
clearTimers();
|
|
2926
|
+
stopLevelLoop();
|
|
2927
|
+
stopStream(mediaStream);
|
|
2928
|
+
mediaStream = null;
|
|
2929
|
+
analyser = null;
|
|
2930
|
+
levelData = null;
|
|
2931
|
+
await closeAudioContext(audioContext);
|
|
2932
|
+
audioContext = null;
|
|
2933
|
+
};
|
|
2934
|
+
const finalizeStop = async () => {
|
|
2935
|
+
mediaRecorder = null;
|
|
2936
|
+
isStarting = false;
|
|
2937
|
+
await cleanupActiveResources();
|
|
2938
|
+
};
|
|
2939
|
+
const start = async () => {
|
|
2940
|
+
if (isStarting || mediaRecorder?.state === "recording") {
|
|
2941
|
+
return;
|
|
2942
|
+
}
|
|
2943
|
+
if (!navigator.mediaDevices?.getUserMedia) {
|
|
2944
|
+
throw new Error("Audio capture is not supported in this browser");
|
|
2945
|
+
}
|
|
2946
|
+
if (typeof MediaRecorder === "undefined") {
|
|
2947
|
+
throw new Error("MediaRecorder is not supported in this browser");
|
|
2948
|
+
}
|
|
2949
|
+
isStarting = true;
|
|
2950
|
+
shouldEmitSegment = true;
|
|
2951
|
+
handlers.onTranscriptChange?.({});
|
|
2952
|
+
handlers.onDurationChange?.(0);
|
|
2953
|
+
handlers.onAudioLevelChange?.(0);
|
|
2954
|
+
handlers.onStateChange?.("preparing");
|
|
2955
|
+
try {
|
|
2956
|
+
mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
2957
|
+
const mimeType = pickRecorderMimeType();
|
|
2958
|
+
mediaRecorder = mimeType ? new MediaRecorder(mediaStream, { mimeType }) : new MediaRecorder(mediaStream);
|
|
2959
|
+
const chunks = [];
|
|
2960
|
+
mediaRecorder.ondataavailable = (event) => {
|
|
2961
|
+
if (event.data.size > 0) {
|
|
2962
|
+
chunks.push(event.data);
|
|
2963
|
+
}
|
|
2964
|
+
};
|
|
2965
|
+
mediaRecorder.onerror = (event) => {
|
|
2966
|
+
const error = event.error ?? new Error("Audio recorder failed");
|
|
2967
|
+
handlers.onError?.(error);
|
|
2968
|
+
};
|
|
2969
|
+
mediaRecorder.onstop = async () => {
|
|
2970
|
+
const durationMs = startedAt > 0 ? Math.max(0, Date.now() - startedAt) : 0;
|
|
2971
|
+
try {
|
|
2972
|
+
if (shouldEmitSegment && chunks.length > 0) {
|
|
2973
|
+
const blob = new Blob(chunks, {
|
|
2974
|
+
type: mediaRecorder?.mimeType || mimeType || "audio/webm"
|
|
2975
|
+
});
|
|
2976
|
+
const dataUrl = await blobToDataUrl(blob);
|
|
2977
|
+
handlers.onSegmentReady?.({
|
|
2978
|
+
attachment: {
|
|
2979
|
+
kind: "audio",
|
|
2980
|
+
dataUrl,
|
|
2981
|
+
mimeType: blob.type || "audio/webm",
|
|
2982
|
+
durationMs,
|
|
2983
|
+
fileName: `voice-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.webm`,
|
|
2984
|
+
size: blob.size
|
|
2985
|
+
},
|
|
2986
|
+
metadata: { source: "manual" }
|
|
2987
|
+
});
|
|
2988
|
+
} else {
|
|
2989
|
+
handlers.onStateChange?.("idle");
|
|
2990
|
+
}
|
|
2991
|
+
} catch (error) {
|
|
2992
|
+
handlers.onError?.(error);
|
|
2993
|
+
} finally {
|
|
2994
|
+
await finalizeStop();
|
|
2995
|
+
}
|
|
2996
|
+
};
|
|
2997
|
+
const AudioContextCtor = globalThis.AudioContext || globalThis.webkitAudioContext;
|
|
2998
|
+
if (AudioContextCtor) {
|
|
2999
|
+
audioContext = new AudioContextCtor();
|
|
3000
|
+
await audioContext.resume().catch(() => void 0);
|
|
3001
|
+
const sourceNode = audioContext.createMediaStreamSource(mediaStream);
|
|
3002
|
+
analyser = audioContext.createAnalyser();
|
|
3003
|
+
analyser.fftSize = 1024;
|
|
3004
|
+
levelData = new Uint8Array(analyser.fftSize);
|
|
3005
|
+
sourceNode.connect(analyser);
|
|
3006
|
+
startLevelLoop();
|
|
3007
|
+
}
|
|
3008
|
+
startedAt = Date.now();
|
|
3009
|
+
emitDuration(handlers, startedAt);
|
|
3010
|
+
durationTimer = setInterval(() => emitDuration(handlers, startedAt), 200);
|
|
3011
|
+
if (options.maxRecordingMs && options.maxRecordingMs > 0) {
|
|
3012
|
+
maxDurationTimer = setTimeout(() => {
|
|
3013
|
+
void stop();
|
|
3014
|
+
}, options.maxRecordingMs);
|
|
3015
|
+
}
|
|
3016
|
+
mediaRecorder.start();
|
|
3017
|
+
handlers.onStateChange?.("listening");
|
|
3018
|
+
} catch (error) {
|
|
3019
|
+
isStarting = false;
|
|
3020
|
+
await cleanupActiveResources();
|
|
3021
|
+
throw error;
|
|
3022
|
+
}
|
|
3023
|
+
};
|
|
3024
|
+
const stop = async () => {
|
|
3025
|
+
if (!mediaRecorder || mediaRecorder.state === "inactive") {
|
|
3026
|
+
return;
|
|
3027
|
+
}
|
|
3028
|
+
handlers.onStateChange?.("finishing");
|
|
3029
|
+
mediaRecorder.stop();
|
|
3030
|
+
};
|
|
3031
|
+
const cancel = async () => {
|
|
3032
|
+
shouldEmitSegment = false;
|
|
3033
|
+
if (mediaRecorder && mediaRecorder.state !== "inactive") {
|
|
3034
|
+
mediaRecorder.stop();
|
|
3035
|
+
return;
|
|
3036
|
+
}
|
|
3037
|
+
await finalizeStop();
|
|
3038
|
+
handlers.onStateChange?.("idle");
|
|
3039
|
+
};
|
|
3040
|
+
const destroy = async () => {
|
|
3041
|
+
await cancel();
|
|
3042
|
+
};
|
|
3043
|
+
return {
|
|
3044
|
+
start,
|
|
3045
|
+
stop,
|
|
3046
|
+
cancel,
|
|
3047
|
+
destroy
|
|
3048
|
+
};
|
|
3049
|
+
};
|
|
3050
|
+
var resolveVoiceProviderFactory = (createProvider) => createProvider ?? createManualVoiceProvider;
|
|
3051
|
+
|
|
2813
3052
|
// src/components/ui/progress.tsx
|
|
2814
3053
|
var ProgressPrimitive = __toESM(require("@radix-ui/react-progress"), 1);
|
|
2815
3054
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
@@ -2839,9 +3078,162 @@ function Progress({
|
|
|
2839
3078
|
);
|
|
2840
3079
|
}
|
|
2841
3080
|
|
|
2842
|
-
// src/components/chat/
|
|
3081
|
+
// src/components/chat/VoiceComposer.tsx
|
|
2843
3082
|
var import_lucide_react9 = require("lucide-react");
|
|
2844
3083
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
3084
|
+
var formatDuration = (durationMs) => {
|
|
3085
|
+
const totalSeconds = Math.max(0, Math.floor(durationMs / 1e3));
|
|
3086
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
3087
|
+
const seconds = totalSeconds % 60;
|
|
3088
|
+
return `${minutes}:${seconds.toString().padStart(2, "0")}`;
|
|
3089
|
+
};
|
|
3090
|
+
var interpolateSeconds = (label, seconds) => {
|
|
3091
|
+
if (!label) {
|
|
3092
|
+
return `Auto-sends in ${seconds}s`;
|
|
3093
|
+
}
|
|
3094
|
+
if (label.includes("{{seconds}}")) {
|
|
3095
|
+
return label.replace(/\{\{\s*seconds\s*\}\}/g, String(seconds));
|
|
3096
|
+
}
|
|
3097
|
+
return `${label} ${seconds}s`;
|
|
3098
|
+
};
|
|
3099
|
+
var resolveStateLabel = (state, labels, errorMessage) => {
|
|
3100
|
+
switch (state) {
|
|
3101
|
+
case "preparing":
|
|
3102
|
+
return labels?.voicePreparing || "Preparing microphone...";
|
|
3103
|
+
case "waiting_for_speech":
|
|
3104
|
+
return labels?.voiceWaiting || "Waiting for speech...";
|
|
3105
|
+
case "listening":
|
|
3106
|
+
return labels?.voiceListening || "Listening...";
|
|
3107
|
+
case "finishing":
|
|
3108
|
+
return labels?.voiceFinishing || "Finishing capture...";
|
|
3109
|
+
case "review":
|
|
3110
|
+
return labels?.voiceReview || "Ready to send";
|
|
3111
|
+
case "sending":
|
|
3112
|
+
return "Sending...";
|
|
3113
|
+
case "error":
|
|
3114
|
+
return errorMessage || labels?.voiceCaptureError || "Unable to capture audio.";
|
|
3115
|
+
case "idle":
|
|
3116
|
+
default:
|
|
3117
|
+
return labels?.voiceTitle || "Voice input";
|
|
3118
|
+
}
|
|
3119
|
+
};
|
|
3120
|
+
var resolveTranscriptText = (transcript, transcriptMode) => {
|
|
3121
|
+
if (transcriptMode === "none" || !transcript) {
|
|
3122
|
+
return null;
|
|
3123
|
+
}
|
|
3124
|
+
if (transcriptMode === "final-only") {
|
|
3125
|
+
return transcript.final?.trim() || null;
|
|
3126
|
+
}
|
|
3127
|
+
return transcript.final?.trim() || transcript.partial?.trim() || null;
|
|
3128
|
+
};
|
|
3129
|
+
var VoiceComposer = ({
|
|
3130
|
+
state,
|
|
3131
|
+
transcript,
|
|
3132
|
+
transcriptMode,
|
|
3133
|
+
showTranscriptPreview,
|
|
3134
|
+
durationMs,
|
|
3135
|
+
audioLevel,
|
|
3136
|
+
countdownMs,
|
|
3137
|
+
autoSendDelayMs,
|
|
3138
|
+
errorMessage,
|
|
3139
|
+
disabled = false,
|
|
3140
|
+
labels,
|
|
3141
|
+
onStart,
|
|
3142
|
+
onStop,
|
|
3143
|
+
onCancel,
|
|
3144
|
+
onSendNow,
|
|
3145
|
+
onRecordAgain,
|
|
3146
|
+
onExit
|
|
3147
|
+
}) => {
|
|
3148
|
+
const transcriptText = resolveTranscriptText(transcript, transcriptMode);
|
|
3149
|
+
const countdownSeconds = Math.max(1, Math.ceil(countdownMs / 1e3));
|
|
3150
|
+
const countdownValue = autoSendDelayMs > 0 ? Math.min(100, Math.max(0, (autoSendDelayMs - countdownMs) / autoSendDelayMs * 100)) : 100;
|
|
3151
|
+
const isBusy = state === "preparing" || state === "finishing" || state === "sending";
|
|
3152
|
+
const isCapturing = state === "waiting_for_speech" || state === "listening";
|
|
3153
|
+
const levelValue = isCapturing || state === "preparing" || state === "finishing" ? Math.max(8, Math.round(audioLevel * 100)) : 0;
|
|
3154
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "w-full md:min-w-3xl max-w-3xl rounded-xl border bg-background p-4 shadow-sm", children: [
|
|
3155
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center justify-between gap-3", children: [
|
|
3156
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3157
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "outline", children: labels?.voiceTitle || "Voice input" }),
|
|
3158
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-sm text-muted-foreground", children: resolveStateLabel(state, labels, errorMessage) })
|
|
3159
|
+
] }),
|
|
3160
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
3161
|
+
Button,
|
|
3162
|
+
{
|
|
3163
|
+
type: "button",
|
|
3164
|
+
variant: "ghost",
|
|
3165
|
+
size: "sm",
|
|
3166
|
+
onClick: onExit,
|
|
3167
|
+
disabled: disabled || isBusy,
|
|
3168
|
+
children: [
|
|
3169
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Keyboard, { className: "h-4 w-4" }),
|
|
3170
|
+
labels?.voiceExit || "Use keyboard"
|
|
3171
|
+
]
|
|
3172
|
+
}
|
|
3173
|
+
)
|
|
3174
|
+
] }),
|
|
3175
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("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: [
|
|
3176
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex h-20 w-20 items-center justify-center rounded-full bg-primary/10", children: isBusy ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Loader2, { className: "h-8 w-8 animate-spin text-primary" }) : isCapturing ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Square, { className: "h-8 w-8 text-primary" }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Mic, { className: "h-8 w-8 text-primary" }) }),
|
|
3177
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "w-full max-w-md space-y-2", children: [
|
|
3178
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Progress, { value: levelValue, className: "h-2" }),
|
|
3179
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
|
|
3180
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: formatDuration(durationMs) }),
|
|
3181
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: resolveStateLabel(state, labels, errorMessage) })
|
|
3182
|
+
] })
|
|
3183
|
+
] }),
|
|
3184
|
+
showTranscriptPreview && transcriptMode !== "none" && transcriptText && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-full max-w-md rounded-lg border bg-background px-3 py-2 text-left text-sm", children: transcriptText })
|
|
3185
|
+
] }),
|
|
3186
|
+
state === "review" && autoSendDelayMs > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-4 space-y-2", children: [
|
|
3187
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Progress, { value: countdownValue, className: "h-2" }),
|
|
3188
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-center text-xs text-muted-foreground", children: interpolateSeconds(labels?.voiceAutoSendIn, countdownSeconds) })
|
|
3189
|
+
] }),
|
|
3190
|
+
state === "error" && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-4 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2 text-sm text-destructive", children: errorMessage }),
|
|
3191
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-4 flex flex-wrap items-center justify-center gap-2", children: [
|
|
3192
|
+
state === "idle" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { type: "button", onClick: onStart, disabled, children: [
|
|
3193
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Mic, { className: "h-4 w-4" }),
|
|
3194
|
+
labels?.voiceStart || "Start recording"
|
|
3195
|
+
] }),
|
|
3196
|
+
isCapturing && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
3197
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { type: "button", onClick: onStop, disabled, children: [
|
|
3198
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Square, { className: "h-4 w-4" }),
|
|
3199
|
+
labels?.voiceStop || "Stop recording"
|
|
3200
|
+
] }),
|
|
3201
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { type: "button", variant: "outline", onClick: onCancel, disabled, children: [
|
|
3202
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.X, { className: "h-4 w-4" }),
|
|
3203
|
+
labels?.voiceCancel || "Cancel"
|
|
3204
|
+
] })
|
|
3205
|
+
] }),
|
|
3206
|
+
state === "review" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
3207
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { type: "button", variant: "outline", onClick: onCancel, disabled, children: [
|
|
3208
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.X, { className: "h-4 w-4" }),
|
|
3209
|
+
labels?.voiceCancel || "Cancel"
|
|
3210
|
+
] }),
|
|
3211
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { type: "button", variant: "outline", onClick: onRecordAgain, disabled, children: [
|
|
3212
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.RotateCcw, { className: "h-4 w-4" }),
|
|
3213
|
+
labels?.voiceRecordAgain || "Record again"
|
|
3214
|
+
] }),
|
|
3215
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { type: "button", onClick: onSendNow, disabled, children: [
|
|
3216
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Send, { className: "h-4 w-4" }),
|
|
3217
|
+
labels?.voiceSendNow || "Send now"
|
|
3218
|
+
] })
|
|
3219
|
+
] }),
|
|
3220
|
+
state === "error" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
3221
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { type: "button", variant: "outline", onClick: onCancel, disabled, children: [
|
|
3222
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.X, { className: "h-4 w-4" }),
|
|
3223
|
+
labels?.voiceCancel || "Cancel"
|
|
3224
|
+
] }),
|
|
3225
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { type: "button", onClick: onRecordAgain, disabled, children: [
|
|
3226
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.RotateCcw, { className: "h-4 w-4" }),
|
|
3227
|
+
labels?.voiceRecordAgain || "Record again"
|
|
3228
|
+
] })
|
|
3229
|
+
] })
|
|
3230
|
+
] })
|
|
3231
|
+
] });
|
|
3232
|
+
};
|
|
3233
|
+
|
|
3234
|
+
// src/components/chat/ChatInput.tsx
|
|
3235
|
+
var import_lucide_react10 = require("lucide-react");
|
|
3236
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2845
3237
|
var FileUploadItem = (0, import_react5.memo)(function FileUploadItem2({ file, progress, onCancel }) {
|
|
2846
3238
|
const guessTypeFromName = (name) => {
|
|
2847
3239
|
const ext = (name || "").split(".").pop()?.toLowerCase();
|
|
@@ -2870,10 +3262,10 @@ var FileUploadItem = (0, import_react5.memo)(function FileUploadItem2({ file, pr
|
|
|
2870
3262
|
};
|
|
2871
3263
|
const getFileIcon = (type, name) => {
|
|
2872
3264
|
const t = typeof type === "string" && type.length > 0 ? type : guessTypeFromName(name);
|
|
2873
|
-
if (t.startsWith("image/")) return /* @__PURE__ */ (0,
|
|
2874
|
-
if (t.startsWith("video/")) return /* @__PURE__ */ (0,
|
|
2875
|
-
if (t.startsWith("audio/")) return /* @__PURE__ */ (0,
|
|
2876
|
-
return /* @__PURE__ */ (0,
|
|
3265
|
+
if (t.startsWith("image/")) return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Image, { className: "h-4 w-4" });
|
|
3266
|
+
if (t.startsWith("video/")) return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Video, { className: "h-4 w-4" });
|
|
3267
|
+
if (t.startsWith("audio/")) return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Mic, { className: "h-4 w-4" });
|
|
3268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.FileText, { className: "h-4 w-4" });
|
|
2877
3269
|
};
|
|
2878
3270
|
const formatFileSize = (bytes) => {
|
|
2879
3271
|
if (bytes === 0) return "0 Bytes";
|
|
@@ -2882,21 +3274,21 @@ var FileUploadItem = (0, import_react5.memo)(function FileUploadItem2({ file, pr
|
|
|
2882
3274
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
2883
3275
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
|
2884
3276
|
};
|
|
2885
|
-
return /* @__PURE__ */ (0,
|
|
3277
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Card, { className: "relative", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CardContent, { className: "p-3", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
2886
3278
|
getFileIcon(file.type, file.name),
|
|
2887
|
-
/* @__PURE__ */ (0,
|
|
2888
|
-
/* @__PURE__ */ (0,
|
|
2889
|
-
/* @__PURE__ */ (0,
|
|
2890
|
-
/* @__PURE__ */ (0,
|
|
3279
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
3280
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-sm font-medium truncate", children: file.name }),
|
|
3281
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-xs text-muted-foreground", children: formatFileSize(file.size ?? 0) }),
|
|
3282
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Progress, { value: progress, className: "h-1 mt-1" })
|
|
2891
3283
|
] }),
|
|
2892
|
-
/* @__PURE__ */ (0,
|
|
3284
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2893
3285
|
Button,
|
|
2894
3286
|
{
|
|
2895
3287
|
variant: "ghost",
|
|
2896
3288
|
size: "icon",
|
|
2897
3289
|
className: "h-6 w-6",
|
|
2898
3290
|
onClick: onCancel,
|
|
2899
|
-
children: /* @__PURE__ */ (0,
|
|
3291
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.X, { className: "h-3 w-3" })
|
|
2900
3292
|
}
|
|
2901
3293
|
)
|
|
2902
3294
|
] }) }) });
|
|
@@ -2930,15 +3322,15 @@ var AttachmentPreview = (0, import_react5.memo)(function AttachmentPreview2({ at
|
|
|
2930
3322
|
setIsPlaying(!isPlaying);
|
|
2931
3323
|
}
|
|
2932
3324
|
};
|
|
2933
|
-
const
|
|
3325
|
+
const formatDuration2 = (ms) => {
|
|
2934
3326
|
if (!ms) return "";
|
|
2935
3327
|
const seconds = Math.floor(ms / 1e3);
|
|
2936
3328
|
const minutes = Math.floor(seconds / 60);
|
|
2937
3329
|
return `${minutes}:${(seconds % 60).toString().padStart(2, "0")}`;
|
|
2938
3330
|
};
|
|
2939
|
-
return /* @__PURE__ */ (0,
|
|
2940
|
-
attachment.kind === "image" && /* @__PURE__ */ (0,
|
|
2941
|
-
/* @__PURE__ */ (0,
|
|
3331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Card, { className: "relative group", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(CardContent, { className: "p-2", children: [
|
|
3332
|
+
attachment.kind === "image" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "relative", children: [
|
|
3333
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2942
3334
|
"img",
|
|
2943
3335
|
{
|
|
2944
3336
|
src: attachment.dataUrl,
|
|
@@ -2946,19 +3338,19 @@ var AttachmentPreview = (0, import_react5.memo)(function AttachmentPreview2({ at
|
|
|
2946
3338
|
className: "w-full h-20 object-cover rounded"
|
|
2947
3339
|
}
|
|
2948
3340
|
),
|
|
2949
|
-
/* @__PURE__ */ (0,
|
|
3341
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity rounded flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2950
3342
|
Button,
|
|
2951
3343
|
{
|
|
2952
3344
|
variant: "destructive",
|
|
2953
3345
|
size: "icon",
|
|
2954
3346
|
className: "h-6 w-6",
|
|
2955
3347
|
onClick: onRemove,
|
|
2956
|
-
children: /* @__PURE__ */ (0,
|
|
3348
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.X, { className: "h-3 w-3" })
|
|
2957
3349
|
}
|
|
2958
3350
|
) })
|
|
2959
3351
|
] }),
|
|
2960
|
-
attachment.kind === "video" && /* @__PURE__ */ (0,
|
|
2961
|
-
/* @__PURE__ */ (0,
|
|
3352
|
+
attachment.kind === "video" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "relative", children: [
|
|
3353
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2962
3354
|
"video",
|
|
2963
3355
|
{
|
|
2964
3356
|
src: attachment.dataUrl,
|
|
@@ -2967,34 +3359,34 @@ var AttachmentPreview = (0, import_react5.memo)(function AttachmentPreview2({ at
|
|
|
2967
3359
|
muted: true
|
|
2968
3360
|
}
|
|
2969
3361
|
),
|
|
2970
|
-
/* @__PURE__ */ (0,
|
|
3362
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity rounded flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2971
3363
|
Button,
|
|
2972
3364
|
{
|
|
2973
3365
|
variant: "destructive",
|
|
2974
3366
|
size: "icon",
|
|
2975
3367
|
className: "h-6 w-6",
|
|
2976
3368
|
onClick: onRemove,
|
|
2977
|
-
children: /* @__PURE__ */ (0,
|
|
3369
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.X, { className: "h-3 w-3" })
|
|
2978
3370
|
}
|
|
2979
3371
|
) }),
|
|
2980
|
-
/* @__PURE__ */ (0,
|
|
3372
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Badge, { className: "absolute bottom-1 right-1 text-xs", children: formatDuration2(attachment.durationMs) })
|
|
2981
3373
|
] }),
|
|
2982
|
-
attachment.kind === "audio" && /* @__PURE__ */ (0,
|
|
2983
|
-
/* @__PURE__ */ (0,
|
|
3374
|
+
attachment.kind === "audio" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2 p-2", children: [
|
|
3375
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2984
3376
|
Button,
|
|
2985
3377
|
{
|
|
2986
3378
|
variant: "outline",
|
|
2987
3379
|
size: "icon",
|
|
2988
3380
|
className: "h-8 w-8",
|
|
2989
3381
|
onClick: handlePlayPause,
|
|
2990
|
-
children: isPlaying ? /* @__PURE__ */ (0,
|
|
3382
|
+
children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Pause, { className: "h-3 w-3" }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Play, { className: "h-3 w-3" })
|
|
2991
3383
|
}
|
|
2992
3384
|
),
|
|
2993
|
-
/* @__PURE__ */ (0,
|
|
2994
|
-
/* @__PURE__ */ (0,
|
|
2995
|
-
/* @__PURE__ */ (0,
|
|
3385
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex-1", children: [
|
|
3386
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-xs font-medium", children: attachment.fileName || "\xC1udio" }),
|
|
3387
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-xs text-muted-foreground", children: formatDuration2(attachment.durationMs) })
|
|
2996
3388
|
] }),
|
|
2997
|
-
/* @__PURE__ */ (0,
|
|
3389
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2998
3390
|
"audio",
|
|
2999
3391
|
{
|
|
3000
3392
|
ref: audioRef,
|
|
@@ -3002,21 +3394,21 @@ var AttachmentPreview = (0, import_react5.memo)(function AttachmentPreview2({ at
|
|
|
3002
3394
|
onPause: () => setIsPlaying(false),
|
|
3003
3395
|
onEnded: () => setIsPlaying(false),
|
|
3004
3396
|
preload: "metadata",
|
|
3005
|
-
children: /* @__PURE__ */ (0,
|
|
3397
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("source", { src: audioPlaybackSrc, type: attachment.mimeType })
|
|
3006
3398
|
}
|
|
3007
3399
|
),
|
|
3008
|
-
/* @__PURE__ */ (0,
|
|
3400
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3009
3401
|
Button,
|
|
3010
3402
|
{
|
|
3011
3403
|
variant: "ghost",
|
|
3012
3404
|
size: "icon",
|
|
3013
3405
|
className: "h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity",
|
|
3014
3406
|
onClick: onRemove,
|
|
3015
|
-
children: /* @__PURE__ */ (0,
|
|
3407
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.X, { className: "h-3 w-3" })
|
|
3016
3408
|
}
|
|
3017
3409
|
)
|
|
3018
3410
|
] }),
|
|
3019
|
-
attachment.fileName && attachment.kind !== "audio" && /* @__PURE__ */ (0,
|
|
3411
|
+
attachment.fileName && attachment.kind !== "audio" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "absolute bottom-0 left-0 right-0 bg-black/70 text-white text-xs p-1 rounded-b", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "truncate", children: attachment.fileName }) })
|
|
3020
3412
|
] }) });
|
|
3021
3413
|
});
|
|
3022
3414
|
var AudioRecorder = (0, import_react5.memo)(function AudioRecorder2({ isRecording, onStartRecording, onStopRecording, onCancel, recordingDuration, config }) {
|
|
@@ -3026,47 +3418,47 @@ var AudioRecorder = (0, import_react5.memo)(function AudioRecorder2({ isRecordin
|
|
|
3026
3418
|
return `${mins}:${secs.toString().padStart(2, "0")}`;
|
|
3027
3419
|
};
|
|
3028
3420
|
if (!isRecording) {
|
|
3029
|
-
return /* @__PURE__ */ (0,
|
|
3030
|
-
/* @__PURE__ */ (0,
|
|
3421
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
3422
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3031
3423
|
Button,
|
|
3032
3424
|
{
|
|
3033
3425
|
variant: "outline",
|
|
3034
3426
|
size: "icon",
|
|
3035
3427
|
onClick: onStartRecording,
|
|
3036
3428
|
className: "h-10 w-10",
|
|
3037
|
-
children: /* @__PURE__ */ (0,
|
|
3429
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Mic, { className: "h-4 w-4" })
|
|
3038
3430
|
}
|
|
3039
3431
|
) }),
|
|
3040
|
-
/* @__PURE__ */ (0,
|
|
3432
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { children: config?.labels?.recordAudioTooltip })
|
|
3041
3433
|
] });
|
|
3042
3434
|
}
|
|
3043
|
-
return /* @__PURE__ */ (0,
|
|
3044
|
-
/* @__PURE__ */ (0,
|
|
3045
|
-
/* @__PURE__ */ (0,
|
|
3046
|
-
/* @__PURE__ */ (0,
|
|
3435
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Card, { className: "border-red-200 bg-red-50 dark:border-red-800 dark:bg-red-950", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CardContent, { className: "p-3", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
3436
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3437
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "h-3 w-3 bg-red-500 rounded-full animate-pulse" }),
|
|
3438
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-sm font-medium text-red-700 dark:text-red-300", children: "Gravando" })
|
|
3047
3439
|
] }),
|
|
3048
|
-
/* @__PURE__ */ (0,
|
|
3049
|
-
/* @__PURE__ */ (0,
|
|
3050
|
-
/* @__PURE__ */ (0,
|
|
3440
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Badge, { variant: "outline", className: "text-xs", children: formatTime(recordingDuration) }),
|
|
3441
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex gap-1 ml-auto", children: [
|
|
3442
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
3051
3443
|
Button,
|
|
3052
3444
|
{
|
|
3053
3445
|
variant: "outline",
|
|
3054
3446
|
size: "sm",
|
|
3055
3447
|
onClick: onCancel,
|
|
3056
3448
|
children: [
|
|
3057
|
-
/* @__PURE__ */ (0,
|
|
3449
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.X, { className: "h-3 w-3 mr-1" }),
|
|
3058
3450
|
"Cancelar"
|
|
3059
3451
|
]
|
|
3060
3452
|
}
|
|
3061
3453
|
),
|
|
3062
|
-
/* @__PURE__ */ (0,
|
|
3454
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
3063
3455
|
Button,
|
|
3064
3456
|
{
|
|
3065
3457
|
variant: "default",
|
|
3066
3458
|
size: "sm",
|
|
3067
3459
|
onClick: onStopRecording,
|
|
3068
3460
|
children: [
|
|
3069
|
-
/* @__PURE__ */ (0,
|
|
3461
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Square, { className: "h-3 w-3 mr-1" }),
|
|
3070
3462
|
"Parar"
|
|
3071
3463
|
]
|
|
3072
3464
|
}
|
|
@@ -3074,6 +3466,16 @@ var AudioRecorder = (0, import_react5.memo)(function AudioRecorder2({ isRecordin
|
|
|
3074
3466
|
] })
|
|
3075
3467
|
] }) }) });
|
|
3076
3468
|
});
|
|
3469
|
+
var resolveVoiceErrorMessage = (error, config) => {
|
|
3470
|
+
if (error instanceof DOMException && error.name === "NotAllowedError") {
|
|
3471
|
+
return config?.labels?.voicePermissionDenied || "Microphone access was denied.";
|
|
3472
|
+
}
|
|
3473
|
+
if (error instanceof Error && error.message.trim().length > 0) {
|
|
3474
|
+
return error.message;
|
|
3475
|
+
}
|
|
3476
|
+
return config?.labels?.voiceCaptureError || "Unable to capture audio.";
|
|
3477
|
+
};
|
|
3478
|
+
var clearVoiceTranscript = () => ({});
|
|
3077
3479
|
var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
3078
3480
|
value,
|
|
3079
3481
|
onChange,
|
|
@@ -3097,12 +3499,27 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3097
3499
|
const { setContext } = useChatUserContext();
|
|
3098
3500
|
const [recordingDuration, setRecordingDuration] = (0, import_react5.useState)(0);
|
|
3099
3501
|
const [uploadProgress, setUploadProgress] = (0, import_react5.useState)(/* @__PURE__ */ new Map());
|
|
3502
|
+
const [isVoiceComposerOpen, setIsVoiceComposerOpen] = (0, import_react5.useState)(false);
|
|
3503
|
+
const [voiceState, setVoiceState] = (0, import_react5.useState)("idle");
|
|
3504
|
+
const [voiceDraft, setVoiceDraft] = (0, import_react5.useState)(null);
|
|
3505
|
+
const [voiceTranscript, setVoiceTranscript] = (0, import_react5.useState)(clearVoiceTranscript);
|
|
3506
|
+
const [voiceDurationMs, setVoiceDurationMs] = (0, import_react5.useState)(0);
|
|
3507
|
+
const [voiceAudioLevel, setVoiceAudioLevel] = (0, import_react5.useState)(0);
|
|
3508
|
+
const [voiceCountdownMs, setVoiceCountdownMs] = (0, import_react5.useState)(0);
|
|
3509
|
+
const [voiceError, setVoiceError] = (0, import_react5.useState)(null);
|
|
3100
3510
|
const textareaRef = (0, import_react5.useRef)(null);
|
|
3101
3511
|
const fileInputRef = (0, import_react5.useRef)(null);
|
|
3102
3512
|
const mediaRecorderRef = (0, import_react5.useRef)(null);
|
|
3103
3513
|
const recordingStartTime = (0, import_react5.useRef)(0);
|
|
3104
3514
|
const recordingInterval = (0, import_react5.useRef)(null);
|
|
3105
3515
|
const mediaStreamRef = (0, import_react5.useRef)(null);
|
|
3516
|
+
const voiceProviderRef = (0, import_react5.useRef)(null);
|
|
3517
|
+
const voiceComposeEnabled = config?.voiceCompose?.enabled === true;
|
|
3518
|
+
const voiceAutoSendDelayMs = config?.voiceCompose?.autoSendDelayMs ?? 5e3;
|
|
3519
|
+
const voicePersistComposer = config?.voiceCompose?.persistComposer ?? true;
|
|
3520
|
+
const voiceShowTranscriptPreview = config?.voiceCompose?.showTranscriptPreview ?? true;
|
|
3521
|
+
const voiceTranscriptMode = config?.voiceCompose?.transcriptMode ?? "final-only";
|
|
3522
|
+
const voiceMaxRecordingMs = config?.voiceCompose?.maxRecordingMs;
|
|
3106
3523
|
(0, import_react5.useEffect)(() => {
|
|
3107
3524
|
return () => {
|
|
3108
3525
|
if (mediaStreamRef.current) {
|
|
@@ -3111,6 +3528,10 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3111
3528
|
if (recordingInterval.current) {
|
|
3112
3529
|
clearInterval(recordingInterval.current);
|
|
3113
3530
|
}
|
|
3531
|
+
if (voiceProviderRef.current) {
|
|
3532
|
+
void voiceProviderRef.current.destroy();
|
|
3533
|
+
voiceProviderRef.current = null;
|
|
3534
|
+
}
|
|
3114
3535
|
};
|
|
3115
3536
|
}, []);
|
|
3116
3537
|
const handleSubmit = (e) => {
|
|
@@ -3287,13 +3708,149 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3287
3708
|
}
|
|
3288
3709
|
}
|
|
3289
3710
|
};
|
|
3711
|
+
const resetVoiceComposerState = (0, import_react5.useCallback)((nextState = "idle") => {
|
|
3712
|
+
setVoiceState(nextState);
|
|
3713
|
+
setVoiceDraft(null);
|
|
3714
|
+
setVoiceTranscript(clearVoiceTranscript());
|
|
3715
|
+
setVoiceDurationMs(0);
|
|
3716
|
+
setVoiceAudioLevel(0);
|
|
3717
|
+
setVoiceCountdownMs(0);
|
|
3718
|
+
setVoiceError(null);
|
|
3719
|
+
}, []);
|
|
3720
|
+
const ensureVoiceProvider = (0, import_react5.useCallback)(async () => {
|
|
3721
|
+
if (voiceProviderRef.current) {
|
|
3722
|
+
return voiceProviderRef.current;
|
|
3723
|
+
}
|
|
3724
|
+
const createProvider = resolveVoiceProviderFactory(config?.voiceCompose?.createProvider);
|
|
3725
|
+
const provider = await createProvider({
|
|
3726
|
+
onStateChange: setVoiceState,
|
|
3727
|
+
onAudioLevelChange: setVoiceAudioLevel,
|
|
3728
|
+
onDurationChange: setVoiceDurationMs,
|
|
3729
|
+
onTranscriptChange: setVoiceTranscript,
|
|
3730
|
+
onSegmentReady: (segment) => {
|
|
3731
|
+
setVoiceDraft(segment);
|
|
3732
|
+
setVoiceTranscript(segment.transcript ?? clearVoiceTranscript());
|
|
3733
|
+
setVoiceDurationMs(segment.attachment.durationMs ?? 0);
|
|
3734
|
+
setVoiceAudioLevel(0);
|
|
3735
|
+
setVoiceCountdownMs(voiceAutoSendDelayMs);
|
|
3736
|
+
setVoiceError(null);
|
|
3737
|
+
setVoiceState("review");
|
|
3738
|
+
},
|
|
3739
|
+
onError: (error) => {
|
|
3740
|
+
setVoiceError(resolveVoiceErrorMessage(error, config));
|
|
3741
|
+
setVoiceAudioLevel(0);
|
|
3742
|
+
setVoiceCountdownMs(0);
|
|
3743
|
+
setVoiceState("error");
|
|
3744
|
+
}
|
|
3745
|
+
}, {
|
|
3746
|
+
maxRecordingMs: voiceMaxRecordingMs
|
|
3747
|
+
});
|
|
3748
|
+
voiceProviderRef.current = provider;
|
|
3749
|
+
return provider;
|
|
3750
|
+
}, [config, voiceAutoSendDelayMs, voiceMaxRecordingMs]);
|
|
3751
|
+
const closeVoiceComposer = (0, import_react5.useCallback)(async () => {
|
|
3752
|
+
setIsVoiceComposerOpen(false);
|
|
3753
|
+
setVoiceError(null);
|
|
3754
|
+
setVoiceCountdownMs(0);
|
|
3755
|
+
setVoiceAudioLevel(0);
|
|
3756
|
+
setVoiceTranscript(clearVoiceTranscript());
|
|
3757
|
+
setVoiceDraft(null);
|
|
3758
|
+
setVoiceDurationMs(0);
|
|
3759
|
+
setVoiceState("idle");
|
|
3760
|
+
if (voiceProviderRef.current) {
|
|
3761
|
+
await voiceProviderRef.current.cancel();
|
|
3762
|
+
}
|
|
3763
|
+
}, []);
|
|
3764
|
+
const startVoiceCapture = (0, import_react5.useCallback)(async () => {
|
|
3765
|
+
if (disabled || isGenerating) {
|
|
3766
|
+
return;
|
|
3767
|
+
}
|
|
3768
|
+
setIsVoiceComposerOpen(true);
|
|
3769
|
+
setVoiceError(null);
|
|
3770
|
+
setVoiceDraft(null);
|
|
3771
|
+
setVoiceCountdownMs(0);
|
|
3772
|
+
setVoiceTranscript(clearVoiceTranscript());
|
|
3773
|
+
setVoiceAudioLevel(0);
|
|
3774
|
+
setVoiceDurationMs(0);
|
|
3775
|
+
try {
|
|
3776
|
+
const provider = await ensureVoiceProvider();
|
|
3777
|
+
await provider.start();
|
|
3778
|
+
} catch (error) {
|
|
3779
|
+
setVoiceError(resolveVoiceErrorMessage(error, config));
|
|
3780
|
+
setVoiceState("error");
|
|
3781
|
+
}
|
|
3782
|
+
}, [disabled, isGenerating, ensureVoiceProvider, config]);
|
|
3783
|
+
const stopVoiceCapture = (0, import_react5.useCallback)(async () => {
|
|
3784
|
+
if (!voiceProviderRef.current) return;
|
|
3785
|
+
try {
|
|
3786
|
+
await voiceProviderRef.current.stop();
|
|
3787
|
+
} catch (error) {
|
|
3788
|
+
setVoiceError(resolveVoiceErrorMessage(error, config));
|
|
3789
|
+
setVoiceState("error");
|
|
3790
|
+
}
|
|
3791
|
+
}, [config]);
|
|
3792
|
+
const cancelVoiceCapture = (0, import_react5.useCallback)(async () => {
|
|
3793
|
+
if (voiceProviderRef.current) {
|
|
3794
|
+
await voiceProviderRef.current.cancel();
|
|
3795
|
+
}
|
|
3796
|
+
resetVoiceComposerState("idle");
|
|
3797
|
+
}, [resetVoiceComposerState]);
|
|
3798
|
+
const finalizeVoiceComposerAfterSend = (0, import_react5.useCallback)(() => {
|
|
3799
|
+
if (voicePersistComposer) {
|
|
3800
|
+
resetVoiceComposerState("idle");
|
|
3801
|
+
setIsVoiceComposerOpen(true);
|
|
3802
|
+
return;
|
|
3803
|
+
}
|
|
3804
|
+
void closeVoiceComposer();
|
|
3805
|
+
}, [voicePersistComposer, resetVoiceComposerState, closeVoiceComposer]);
|
|
3806
|
+
const sendVoiceDraft = (0, import_react5.useCallback)(() => {
|
|
3807
|
+
if (!voiceDraft || disabled || isGenerating) {
|
|
3808
|
+
return;
|
|
3809
|
+
}
|
|
3810
|
+
setVoiceState("sending");
|
|
3811
|
+
setVoiceCountdownMs(0);
|
|
3812
|
+
onSubmit("", [...attachments, voiceDraft.attachment]);
|
|
3813
|
+
onChange("");
|
|
3814
|
+
onAttachmentsChange([]);
|
|
3815
|
+
finalizeVoiceComposerAfterSend();
|
|
3816
|
+
}, [
|
|
3817
|
+
voiceDraft,
|
|
3818
|
+
disabled,
|
|
3819
|
+
isGenerating,
|
|
3820
|
+
onSubmit,
|
|
3821
|
+
attachments,
|
|
3822
|
+
onChange,
|
|
3823
|
+
onAttachmentsChange,
|
|
3824
|
+
finalizeVoiceComposerAfterSend
|
|
3825
|
+
]);
|
|
3826
|
+
const recordVoiceAgain = (0, import_react5.useCallback)(async () => {
|
|
3827
|
+
resetVoiceComposerState("idle");
|
|
3828
|
+
await startVoiceCapture();
|
|
3829
|
+
}, [resetVoiceComposerState, startVoiceCapture]);
|
|
3830
|
+
(0, import_react5.useEffect)(() => {
|
|
3831
|
+
if (voiceState !== "review" || !voiceDraft || voiceAutoSendDelayMs <= 0) {
|
|
3832
|
+
return;
|
|
3833
|
+
}
|
|
3834
|
+
const startedAt = Date.now();
|
|
3835
|
+
setVoiceCountdownMs(voiceAutoSendDelayMs);
|
|
3836
|
+
const timer = setInterval(() => {
|
|
3837
|
+
const remaining = Math.max(0, voiceAutoSendDelayMs - (Date.now() - startedAt));
|
|
3838
|
+
setVoiceCountdownMs(remaining);
|
|
3839
|
+
if (remaining <= 0) {
|
|
3840
|
+
clearInterval(timer);
|
|
3841
|
+
sendVoiceDraft();
|
|
3842
|
+
}
|
|
3843
|
+
}, 100);
|
|
3844
|
+
return () => clearInterval(timer);
|
|
3845
|
+
}, [voiceState, voiceDraft, voiceAutoSendDelayMs, sendVoiceDraft]);
|
|
3290
3846
|
const removeAttachment = (index) => {
|
|
3291
3847
|
const newAttachments = attachments.filter((_, i) => i !== index);
|
|
3292
3848
|
onAttachmentsChange(newAttachments);
|
|
3293
3849
|
};
|
|
3294
3850
|
const canAddMoreAttachments = attachments.length < maxAttachments;
|
|
3295
|
-
|
|
3296
|
-
|
|
3851
|
+
const showVoiceComposer = voiceComposeEnabled && isVoiceComposerOpen;
|
|
3852
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: `border-t py-0 bg-transparent ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "px-0 md:p-2 pb-1 space-y-4 bg-transparent", children: [
|
|
3853
|
+
uploadProgress.size > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "space-y-2", children: Array.from(uploadProgress.entries()).map(([id, progress]) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3297
3854
|
FileUploadItem,
|
|
3298
3855
|
{
|
|
3299
3856
|
file: { name: progress.fileName },
|
|
@@ -3308,7 +3865,7 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3308
3865
|
},
|
|
3309
3866
|
id
|
|
3310
3867
|
)) }),
|
|
3311
|
-
isRecording && /* @__PURE__ */ (0,
|
|
3868
|
+
isRecording && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3312
3869
|
AudioRecorder,
|
|
3313
3870
|
{
|
|
3314
3871
|
isRecording,
|
|
@@ -3319,7 +3876,7 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3319
3876
|
config
|
|
3320
3877
|
}
|
|
3321
3878
|
),
|
|
3322
|
-
attachments.length > 0 && /* @__PURE__ */ (0,
|
|
3879
|
+
attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "grid grid-cols-4 gap-2", children: attachments.map((attachment, index) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3323
3880
|
AttachmentPreview,
|
|
3324
3881
|
{
|
|
3325
3882
|
attachment,
|
|
@@ -3327,15 +3884,46 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3327
3884
|
},
|
|
3328
3885
|
index
|
|
3329
3886
|
)) }),
|
|
3330
|
-
/* @__PURE__ */ (0,
|
|
3887
|
+
showVoiceComposer ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "mb-1 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3888
|
+
VoiceComposer,
|
|
3889
|
+
{
|
|
3890
|
+
state: voiceState,
|
|
3891
|
+
transcript: voiceTranscript,
|
|
3892
|
+
transcriptMode: voiceTranscriptMode,
|
|
3893
|
+
showTranscriptPreview: voiceShowTranscriptPreview,
|
|
3894
|
+
durationMs: voiceDurationMs,
|
|
3895
|
+
audioLevel: voiceAudioLevel,
|
|
3896
|
+
countdownMs: voiceCountdownMs,
|
|
3897
|
+
autoSendDelayMs: voiceAutoSendDelayMs,
|
|
3898
|
+
errorMessage: voiceError,
|
|
3899
|
+
disabled: disabled || isGenerating,
|
|
3900
|
+
labels: config?.labels,
|
|
3901
|
+
onStart: () => {
|
|
3902
|
+
void startVoiceCapture();
|
|
3903
|
+
},
|
|
3904
|
+
onStop: () => {
|
|
3905
|
+
void stopVoiceCapture();
|
|
3906
|
+
},
|
|
3907
|
+
onCancel: () => {
|
|
3908
|
+
void cancelVoiceCapture();
|
|
3909
|
+
},
|
|
3910
|
+
onSendNow: sendVoiceDraft,
|
|
3911
|
+
onRecordAgain: () => {
|
|
3912
|
+
void recordVoiceAgain();
|
|
3913
|
+
},
|
|
3914
|
+
onExit: () => {
|
|
3915
|
+
void closeVoiceComposer();
|
|
3916
|
+
}
|
|
3917
|
+
}
|
|
3918
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("form", { onSubmit: handleSubmit, className: "mb-1 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
3331
3919
|
"div",
|
|
3332
3920
|
{
|
|
3333
3921
|
className: "flex items-end gap-2 p-3 border rounded-lg bg-background w-full md:min-w-3xl max-w-3xl",
|
|
3334
3922
|
onDrop: handleDrop,
|
|
3335
3923
|
onDragOver: handleDragOver,
|
|
3336
3924
|
children: [
|
|
3337
|
-
enableFileUpload && canAddMoreAttachments && /* @__PURE__ */ (0,
|
|
3338
|
-
/* @__PURE__ */ (0,
|
|
3925
|
+
enableFileUpload && canAddMoreAttachments && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
3926
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3339
3927
|
"input",
|
|
3340
3928
|
{
|
|
3341
3929
|
ref: fileInputRef,
|
|
@@ -3346,8 +3934,8 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3346
3934
|
className: "hidden"
|
|
3347
3935
|
}
|
|
3348
3936
|
),
|
|
3349
|
-
/* @__PURE__ */ (0,
|
|
3350
|
-
/* @__PURE__ */ (0,
|
|
3937
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
3938
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3351
3939
|
Button,
|
|
3352
3940
|
{
|
|
3353
3941
|
type: "button",
|
|
@@ -3360,13 +3948,13 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3360
3948
|
fileInputRef.current?.click();
|
|
3361
3949
|
},
|
|
3362
3950
|
disabled,
|
|
3363
|
-
children: /* @__PURE__ */ (0,
|
|
3951
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Paperclip, { className: "h-4 w-4" })
|
|
3364
3952
|
}
|
|
3365
3953
|
) }),
|
|
3366
|
-
/* @__PURE__ */ (0,
|
|
3954
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { children: config?.labels?.attachFileTooltip })
|
|
3367
3955
|
] })
|
|
3368
3956
|
] }),
|
|
3369
|
-
/* @__PURE__ */ (0,
|
|
3957
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3370
3958
|
Textarea,
|
|
3371
3959
|
{
|
|
3372
3960
|
ref: textareaRef,
|
|
@@ -3379,7 +3967,23 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3379
3967
|
rows: 1
|
|
3380
3968
|
}
|
|
3381
3969
|
) }),
|
|
3382
|
-
enableAudioRecording && !isRecording && canAddMoreAttachments && !value.trim() && /* @__PURE__ */ (0,
|
|
3970
|
+
enableAudioRecording && !isRecording && canAddMoreAttachments && !value.trim() && (voiceComposeEnabled ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
3971
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3972
|
+
Button,
|
|
3973
|
+
{
|
|
3974
|
+
type: "button",
|
|
3975
|
+
variant: "outline",
|
|
3976
|
+
size: "icon",
|
|
3977
|
+
className: "h-10 w-10",
|
|
3978
|
+
onClick: () => {
|
|
3979
|
+
void startVoiceCapture();
|
|
3980
|
+
},
|
|
3981
|
+
disabled: disabled || isGenerating,
|
|
3982
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Mic, { className: "h-4 w-4" })
|
|
3983
|
+
}
|
|
3984
|
+
) }),
|
|
3985
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { children: config?.labels?.voiceEnter || config?.labels?.recordAudioTooltip })
|
|
3986
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3383
3987
|
AudioRecorder,
|
|
3384
3988
|
{
|
|
3385
3989
|
isRecording,
|
|
@@ -3389,9 +3993,9 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3389
3993
|
recordingDuration,
|
|
3390
3994
|
config
|
|
3391
3995
|
}
|
|
3392
|
-
),
|
|
3393
|
-
isGenerating ? /* @__PURE__ */ (0,
|
|
3394
|
-
/* @__PURE__ */ (0,
|
|
3996
|
+
)),
|
|
3997
|
+
isGenerating ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
3998
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3395
3999
|
Button,
|
|
3396
4000
|
{
|
|
3397
4001
|
type: "button",
|
|
@@ -3399,36 +4003,36 @@ var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
|
3399
4003
|
size: "icon",
|
|
3400
4004
|
className: "h-10 w-10",
|
|
3401
4005
|
onClick: onStopGeneration,
|
|
3402
|
-
children: /* @__PURE__ */ (0,
|
|
4006
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Square, { className: "h-4 w-4" })
|
|
3403
4007
|
}
|
|
3404
4008
|
) }),
|
|
3405
|
-
/* @__PURE__ */ (0,
|
|
3406
|
-
] }) : /* @__PURE__ */ (0,
|
|
3407
|
-
/* @__PURE__ */ (0,
|
|
4009
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { children: config?.labels?.stopGenerationTooltip })
|
|
4010
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
4011
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3408
4012
|
Button,
|
|
3409
4013
|
{
|
|
3410
4014
|
type: "submit",
|
|
3411
4015
|
size: "icon",
|
|
3412
4016
|
className: "h-10 w-10",
|
|
3413
4017
|
disabled: disabled || !value.trim() && attachments.length === 0,
|
|
3414
|
-
children: disabled ? /* @__PURE__ */ (0,
|
|
4018
|
+
children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Loader2, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Send, { className: "h-4 w-4" })
|
|
3415
4019
|
}
|
|
3416
4020
|
) }),
|
|
3417
|
-
/* @__PURE__ */ (0,
|
|
4021
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { children: config?.labels?.sendMessageTooltip })
|
|
3418
4022
|
] })
|
|
3419
4023
|
]
|
|
3420
4024
|
}
|
|
3421
4025
|
) }),
|
|
3422
|
-
/* @__PURE__ */ (0,
|
|
4026
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "text-[10px] text-muted-foreground text-center", children: [
|
|
3423
4027
|
window.innerWidth > 768 ? config?.labels?.inputHelpText : "",
|
|
3424
|
-
attachments.length > 0 && /* @__PURE__ */ (0,
|
|
4028
|
+
attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
3425
4029
|
" \u2022 ",
|
|
3426
4030
|
attachments.length,
|
|
3427
4031
|
"/",
|
|
3428
4032
|
maxAttachments,
|
|
3429
4033
|
" anexos"
|
|
3430
4034
|
] }),
|
|
3431
|
-
config?.labels?.footerLabel && /* @__PURE__ */ (0,
|
|
4035
|
+
config?.labels?.footerLabel && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
3432
4036
|
" \u2022 ",
|
|
3433
4037
|
config.labels.footerLabel
|
|
3434
4038
|
] })
|
|
@@ -3442,16 +4046,16 @@ var import_react6 = require("react");
|
|
|
3442
4046
|
// src/components/ui/scroll-area.tsx
|
|
3443
4047
|
var React11 = __toESM(require("react"), 1);
|
|
3444
4048
|
var ScrollAreaPrimitive = __toESM(require("@radix-ui/react-scroll-area"), 1);
|
|
3445
|
-
var
|
|
4049
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
3446
4050
|
var ScrollArea = React11.forwardRef(({ className, children, viewportClassName, onScroll, onScrollCapture, ...props }, ref) => {
|
|
3447
|
-
return /* @__PURE__ */ (0,
|
|
4051
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
3448
4052
|
ScrollAreaPrimitive.Root,
|
|
3449
4053
|
{
|
|
3450
4054
|
"data-slot": "scroll-area",
|
|
3451
4055
|
className: cn("relative", className),
|
|
3452
4056
|
...props,
|
|
3453
4057
|
children: [
|
|
3454
|
-
/* @__PURE__ */ (0,
|
|
4058
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3455
4059
|
ScrollAreaPrimitive.Viewport,
|
|
3456
4060
|
{
|
|
3457
4061
|
ref,
|
|
@@ -3465,8 +4069,8 @@ var ScrollArea = React11.forwardRef(({ className, children, viewportClassName, o
|
|
|
3465
4069
|
children
|
|
3466
4070
|
}
|
|
3467
4071
|
),
|
|
3468
|
-
/* @__PURE__ */ (0,
|
|
3469
|
-
/* @__PURE__ */ (0,
|
|
4072
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ScrollBar, {}),
|
|
4073
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ScrollAreaPrimitive.Corner, {})
|
|
3470
4074
|
]
|
|
3471
4075
|
}
|
|
3472
4076
|
);
|
|
@@ -3477,7 +4081,7 @@ function ScrollBar({
|
|
|
3477
4081
|
orientation = "vertical",
|
|
3478
4082
|
...props
|
|
3479
4083
|
}) {
|
|
3480
|
-
return /* @__PURE__ */ (0,
|
|
4084
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3481
4085
|
ScrollAreaPrimitive.ScrollAreaScrollbar,
|
|
3482
4086
|
{
|
|
3483
4087
|
"data-slot": "scroll-area-scrollbar",
|
|
@@ -3489,7 +4093,7 @@ function ScrollBar({
|
|
|
3489
4093
|
className
|
|
3490
4094
|
),
|
|
3491
4095
|
...props,
|
|
3492
|
-
children: /* @__PURE__ */ (0,
|
|
4096
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3493
4097
|
ScrollAreaPrimitive.ScrollAreaThumb,
|
|
3494
4098
|
{
|
|
3495
4099
|
"data-slot": "scroll-area-thumb",
|
|
@@ -3501,8 +4105,8 @@ function ScrollBar({
|
|
|
3501
4105
|
}
|
|
3502
4106
|
|
|
3503
4107
|
// src/components/chat/UserProfile.tsx
|
|
3504
|
-
var
|
|
3505
|
-
var
|
|
4108
|
+
var import_lucide_react11 = require("lucide-react");
|
|
4109
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
3506
4110
|
var getInitials2 = (name, email) => {
|
|
3507
4111
|
if (name) {
|
|
3508
4112
|
return name.split(" ").map((n) => n[0]).slice(0, 2).join("").toUpperCase();
|
|
@@ -3516,29 +4120,29 @@ var getFieldIcon = (type, key) => {
|
|
|
3516
4120
|
const iconClass = "h-4 w-4 text-muted-foreground";
|
|
3517
4121
|
switch (type) {
|
|
3518
4122
|
case "email":
|
|
3519
|
-
return /* @__PURE__ */ (0,
|
|
4123
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Mail, { className: iconClass });
|
|
3520
4124
|
case "phone":
|
|
3521
|
-
return /* @__PURE__ */ (0,
|
|
4125
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Phone, { className: iconClass });
|
|
3522
4126
|
case "url":
|
|
3523
|
-
return /* @__PURE__ */ (0,
|
|
4127
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Globe, { className: iconClass });
|
|
3524
4128
|
case "date":
|
|
3525
|
-
return /* @__PURE__ */ (0,
|
|
4129
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Calendar, { className: iconClass });
|
|
3526
4130
|
}
|
|
3527
4131
|
const lowerKey = key?.toLowerCase() || "";
|
|
3528
|
-
if (lowerKey.includes("follower")) return /* @__PURE__ */ (0,
|
|
3529
|
-
if (lowerKey.includes("following")) return /* @__PURE__ */ (0,
|
|
3530
|
-
if (lowerKey.includes("post") || lowerKey.includes("publication")) return /* @__PURE__ */ (0,
|
|
3531
|
-
if (lowerKey.includes("verified") || lowerKey.includes("badge")) return /* @__PURE__ */ (0,
|
|
3532
|
-
if (lowerKey.includes("bio")) return /* @__PURE__ */ (0,
|
|
3533
|
-
if (lowerKey.includes("email")) return /* @__PURE__ */ (0,
|
|
3534
|
-
if (lowerKey.includes("phone") || lowerKey.includes("tel")) return /* @__PURE__ */ (0,
|
|
3535
|
-
if (lowerKey.includes("location") || lowerKey.includes("address") || lowerKey.includes("city")) return /* @__PURE__ */ (0,
|
|
3536
|
-
if (lowerKey.includes("company") || lowerKey.includes("org")) return /* @__PURE__ */ (0,
|
|
3537
|
-
if (lowerKey.includes("job") || lowerKey.includes("role") || lowerKey.includes("title") || lowerKey.includes("position")) return /* @__PURE__ */ (0,
|
|
3538
|
-
if (lowerKey.includes("website") || lowerKey.includes("url") || lowerKey.includes("link")) return /* @__PURE__ */ (0,
|
|
3539
|
-
if (lowerKey.includes("username") || lowerKey.includes("handle")) return /* @__PURE__ */ (0,
|
|
3540
|
-
if (lowerKey.includes("date") || lowerKey.includes("birthday") || lowerKey.includes("joined")) return /* @__PURE__ */ (0,
|
|
3541
|
-
return /* @__PURE__ */ (0,
|
|
4132
|
+
if (lowerKey.includes("follower")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Users, { className: iconClass });
|
|
4133
|
+
if (lowerKey.includes("following")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.UserPlus, { className: iconClass });
|
|
4134
|
+
if (lowerKey.includes("post") || lowerKey.includes("publication")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Image, { className: iconClass });
|
|
4135
|
+
if (lowerKey.includes("verified") || lowerKey.includes("badge")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.BadgeCheck, { className: iconClass });
|
|
4136
|
+
if (lowerKey.includes("bio")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.FileText, { className: iconClass });
|
|
4137
|
+
if (lowerKey.includes("email")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Mail, { className: iconClass });
|
|
4138
|
+
if (lowerKey.includes("phone") || lowerKey.includes("tel")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Phone, { className: iconClass });
|
|
4139
|
+
if (lowerKey.includes("location") || lowerKey.includes("address") || lowerKey.includes("city")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.MapPin, { className: iconClass });
|
|
4140
|
+
if (lowerKey.includes("company") || lowerKey.includes("org")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Building, { className: iconClass });
|
|
4141
|
+
if (lowerKey.includes("job") || lowerKey.includes("role") || lowerKey.includes("title") || lowerKey.includes("position")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Briefcase, { className: iconClass });
|
|
4142
|
+
if (lowerKey.includes("website") || lowerKey.includes("url") || lowerKey.includes("link")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Globe, { className: iconClass });
|
|
4143
|
+
if (lowerKey.includes("username") || lowerKey.includes("handle")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.AtSign, { className: iconClass });
|
|
4144
|
+
if (lowerKey.includes("date") || lowerKey.includes("birthday") || lowerKey.includes("joined")) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Calendar, { className: iconClass });
|
|
4145
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.User, { className: iconClass });
|
|
3542
4146
|
};
|
|
3543
4147
|
var formatValue = (value, type, key) => {
|
|
3544
4148
|
if (value === null || value === void 0) return "-";
|
|
@@ -3572,15 +4176,15 @@ var getMemoryCategoryIcon = (category) => {
|
|
|
3572
4176
|
const iconClass = "h-4 w-4 text-muted-foreground";
|
|
3573
4177
|
switch (category) {
|
|
3574
4178
|
case "preference":
|
|
3575
|
-
return /* @__PURE__ */ (0,
|
|
4179
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Heart, { className: iconClass });
|
|
3576
4180
|
case "fact":
|
|
3577
|
-
return /* @__PURE__ */ (0,
|
|
4181
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Info, { className: iconClass });
|
|
3578
4182
|
case "goal":
|
|
3579
|
-
return /* @__PURE__ */ (0,
|
|
4183
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Target, { className: iconClass });
|
|
3580
4184
|
case "context":
|
|
3581
|
-
return /* @__PURE__ */ (0,
|
|
4185
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Lightbulb, { className: iconClass });
|
|
3582
4186
|
default:
|
|
3583
|
-
return /* @__PURE__ */ (0,
|
|
4187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Brain, { className: iconClass });
|
|
3584
4188
|
}
|
|
3585
4189
|
};
|
|
3586
4190
|
var getMemoryCategoryLabel = (category) => {
|
|
@@ -3650,66 +4254,66 @@ var UserProfile = ({
|
|
|
3650
4254
|
const displayName = user?.name || user?.email?.split("@")[0] || "User";
|
|
3651
4255
|
const initials = getInitials2(user?.name, user?.email);
|
|
3652
4256
|
const normalizedFields = normalizeCustomFields(customFields);
|
|
3653
|
-
return /* @__PURE__ */ (0,
|
|
4257
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Sheet, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
3654
4258
|
SheetContent,
|
|
3655
4259
|
{
|
|
3656
4260
|
side: "right",
|
|
3657
4261
|
className: cn("w-full sm:max-w-md p-0 flex flex-col h-full overflow-hidden", className),
|
|
3658
4262
|
children: [
|
|
3659
|
-
/* @__PURE__ */ (0,
|
|
3660
|
-
/* @__PURE__ */ (0,
|
|
3661
|
-
/* @__PURE__ */ (0,
|
|
3662
|
-
/* @__PURE__ */ (0,
|
|
3663
|
-
user?.avatar && /* @__PURE__ */ (0,
|
|
3664
|
-
/* @__PURE__ */ (0,
|
|
4263
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SheetHeader, { className: "px-6 py-4 border-b shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SheetTitle, { children: labels.title }) }) }),
|
|
4264
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ScrollArea, { className: "flex-1 min-h-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "p-6 space-y-6", children: [
|
|
4265
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col items-center text-center space-y-4", children: [
|
|
4266
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Avatar, { className: "h-24 w-24 shrink-0", children: [
|
|
4267
|
+
user?.avatar && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AvatarImage, { src: user.avatar, alt: displayName }),
|
|
4268
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AvatarFallback, { className: "text-2xl bg-primary/10 text-primary", children: initials })
|
|
3665
4269
|
] }),
|
|
3666
|
-
/* @__PURE__ */ (0,
|
|
3667
|
-
/* @__PURE__ */ (0,
|
|
3668
|
-
user?.email && /* @__PURE__ */ (0,
|
|
4270
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "w-full px-2", children: [
|
|
4271
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { className: "text-xl font-semibold break-words", children: displayName }),
|
|
4272
|
+
user?.email && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm text-muted-foreground break-words", children: user.email })
|
|
3669
4273
|
] })
|
|
3670
4274
|
] }),
|
|
3671
|
-
/* @__PURE__ */ (0,
|
|
3672
|
-
/* @__PURE__ */ (0,
|
|
3673
|
-
/* @__PURE__ */ (0,
|
|
3674
|
-
/* @__PURE__ */ (0,
|
|
3675
|
-
/* @__PURE__ */ (0,
|
|
3676
|
-
/* @__PURE__ */ (0,
|
|
3677
|
-
/* @__PURE__ */ (0,
|
|
3678
|
-
/* @__PURE__ */ (0,
|
|
3679
|
-
/* @__PURE__ */ (0,
|
|
4275
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Separator, {}),
|
|
4276
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "space-y-3", children: [
|
|
4277
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { className: "text-sm font-medium text-muted-foreground uppercase tracking-wider", children: labels.basicInfo }),
|
|
4278
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "space-y-2", children: [
|
|
4279
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50", children: [
|
|
4280
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.User, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
4281
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
4282
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-xs text-muted-foreground", children: "Name" }),
|
|
4283
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm font-medium break-words", children: displayName })
|
|
3680
4284
|
] })
|
|
3681
4285
|
] }),
|
|
3682
|
-
user?.email && /* @__PURE__ */ (0,
|
|
3683
|
-
/* @__PURE__ */ (0,
|
|
3684
|
-
/* @__PURE__ */ (0,
|
|
3685
|
-
/* @__PURE__ */ (0,
|
|
3686
|
-
/* @__PURE__ */ (0,
|
|
4286
|
+
user?.email && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50", children: [
|
|
4287
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.AtSign, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
4288
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
4289
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-xs text-muted-foreground", children: "Handle" }),
|
|
4290
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm font-medium break-words", children: user.email })
|
|
3687
4291
|
] })
|
|
3688
4292
|
] }),
|
|
3689
|
-
user?.id && user.id !== user?.name && user.id !== user?.email && /* @__PURE__ */ (0,
|
|
3690
|
-
/* @__PURE__ */ (0,
|
|
3691
|
-
/* @__PURE__ */ (0,
|
|
3692
|
-
/* @__PURE__ */ (0,
|
|
3693
|
-
/* @__PURE__ */ (0,
|
|
4293
|
+
user?.id && user.id !== user?.name && user.id !== user?.email && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50", children: [
|
|
4294
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.User, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
4295
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
4296
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-xs text-muted-foreground", children: "ID" }),
|
|
4297
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm font-medium break-words", children: user.id })
|
|
3694
4298
|
] })
|
|
3695
4299
|
] })
|
|
3696
4300
|
] })
|
|
3697
4301
|
] }),
|
|
3698
|
-
normalizedFields.length > 0 && /* @__PURE__ */ (0,
|
|
3699
|
-
/* @__PURE__ */ (0,
|
|
3700
|
-
/* @__PURE__ */ (0,
|
|
3701
|
-
/* @__PURE__ */ (0,
|
|
3702
|
-
/* @__PURE__ */ (0,
|
|
4302
|
+
normalizedFields.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
4303
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Separator, {}),
|
|
4304
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "space-y-3", children: [
|
|
4305
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { className: "text-sm font-medium text-muted-foreground uppercase tracking-wider", children: labels.customFields }),
|
|
4306
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "space-y-2", children: normalizedFields.map((field) => {
|
|
3703
4307
|
const isBioField = field.key.toLowerCase().includes("bio");
|
|
3704
|
-
return /* @__PURE__ */ (0,
|
|
4308
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
3705
4309
|
"div",
|
|
3706
4310
|
{
|
|
3707
4311
|
className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50",
|
|
3708
4312
|
children: [
|
|
3709
|
-
/* @__PURE__ */ (0,
|
|
3710
|
-
/* @__PURE__ */ (0,
|
|
3711
|
-
/* @__PURE__ */ (0,
|
|
3712
|
-
/* @__PURE__ */ (0,
|
|
4313
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "mt-0.5 shrink-0", children: field.icon || getFieldIcon(field.type, field.key) }),
|
|
4314
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
4315
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-xs text-muted-foreground", children: field.label }),
|
|
4316
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: cn(
|
|
3713
4317
|
"text-sm font-medium",
|
|
3714
4318
|
isBioField ? "whitespace-pre-wrap break-words" : "break-words"
|
|
3715
4319
|
), children: formatValue(field.value, field.type, field.key) })
|
|
@@ -3721,26 +4325,26 @@ var UserProfile = ({
|
|
|
3721
4325
|
}) })
|
|
3722
4326
|
] })
|
|
3723
4327
|
] }),
|
|
3724
|
-
/* @__PURE__ */ (0,
|
|
3725
|
-
/* @__PURE__ */ (0,
|
|
3726
|
-
/* @__PURE__ */ (0,
|
|
3727
|
-
/* @__PURE__ */ (0,
|
|
3728
|
-
/* @__PURE__ */ (0,
|
|
4328
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Separator, {}),
|
|
4329
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "space-y-3", children: [
|
|
4330
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
4331
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("h3", { className: "text-sm font-medium text-muted-foreground uppercase tracking-wider flex items-center gap-2", children: [
|
|
4332
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Brain, { className: "h-4 w-4" }),
|
|
3729
4333
|
labels.memories
|
|
3730
4334
|
] }),
|
|
3731
|
-
onAddMemory && /* @__PURE__ */ (0,
|
|
4335
|
+
onAddMemory && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3732
4336
|
Button,
|
|
3733
4337
|
{
|
|
3734
4338
|
variant: "ghost",
|
|
3735
4339
|
size: "sm",
|
|
3736
4340
|
className: "h-7 px-2",
|
|
3737
4341
|
onClick: () => setIsAddingMemory(true),
|
|
3738
|
-
children: /* @__PURE__ */ (0,
|
|
4342
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Plus, { className: "h-4 w-4" })
|
|
3739
4343
|
}
|
|
3740
4344
|
)
|
|
3741
4345
|
] }),
|
|
3742
|
-
isAddingMemory && onAddMemory && /* @__PURE__ */ (0,
|
|
3743
|
-
/* @__PURE__ */ (0,
|
|
4346
|
+
isAddingMemory && onAddMemory && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-2", children: [
|
|
4347
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3744
4348
|
Input,
|
|
3745
4349
|
{
|
|
3746
4350
|
value: newMemoryContent,
|
|
@@ -3757,24 +4361,24 @@ var UserProfile = ({
|
|
|
3757
4361
|
autoFocus: true
|
|
3758
4362
|
}
|
|
3759
4363
|
),
|
|
3760
|
-
/* @__PURE__ */ (0,
|
|
4364
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Button, { size: "sm", onClick: handleAddMemory, disabled: !newMemoryContent.trim(), children: "Salvar" })
|
|
3761
4365
|
] }),
|
|
3762
|
-
/* @__PURE__ */ (0,
|
|
4366
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "space-y-2", children: memories.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm text-muted-foreground text-center py-4", children: labels.noMemories }) : memories.map((memory) => {
|
|
3763
4367
|
const isEditing = editingMemoryId === memory.id;
|
|
3764
|
-
return /* @__PURE__ */ (0,
|
|
4368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
3765
4369
|
"div",
|
|
3766
4370
|
{
|
|
3767
4371
|
className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50 group",
|
|
3768
4372
|
children: [
|
|
3769
|
-
/* @__PURE__ */ (0,
|
|
3770
|
-
/* @__PURE__ */ (0,
|
|
3771
|
-
/* @__PURE__ */ (0,
|
|
3772
|
-
/* @__PURE__ */ (0,
|
|
3773
|
-
/* @__PURE__ */ (0,
|
|
3774
|
-
/* @__PURE__ */ (0,
|
|
4373
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "mt-0.5 shrink-0", children: memory.source === "agent" ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Bot, { className: "h-4 w-4 text-primary" }) : getMemoryCategoryIcon(memory.category) }),
|
|
4374
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
4375
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-2 mb-0.5", children: [
|
|
4376
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-xs text-muted-foreground", children: getMemoryCategoryLabel(memory.category) }),
|
|
4377
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-xs text-muted-foreground", children: "\u2022" }),
|
|
4378
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-xs text-muted-foreground", children: memory.source === "agent" ? "IA" : "Voc\xEA" })
|
|
3775
4379
|
] }),
|
|
3776
|
-
isEditing ? /* @__PURE__ */ (0,
|
|
3777
|
-
/* @__PURE__ */ (0,
|
|
4380
|
+
isEditing ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "space-y-2", children: [
|
|
4381
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3778
4382
|
Textarea,
|
|
3779
4383
|
{
|
|
3780
4384
|
value: editingMemoryContent,
|
|
@@ -3791,8 +4395,8 @@ var UserProfile = ({
|
|
|
3791
4395
|
}
|
|
3792
4396
|
}
|
|
3793
4397
|
),
|
|
3794
|
-
/* @__PURE__ */ (0,
|
|
3795
|
-
/* @__PURE__ */ (0,
|
|
4398
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-1 justify-end", children: [
|
|
4399
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
3796
4400
|
Button,
|
|
3797
4401
|
{
|
|
3798
4402
|
variant: "ghost",
|
|
@@ -3800,12 +4404,12 @@ var UserProfile = ({
|
|
|
3800
4404
|
className: "h-7 px-2",
|
|
3801
4405
|
onClick: handleCancelEdit,
|
|
3802
4406
|
children: [
|
|
3803
|
-
/* @__PURE__ */ (0,
|
|
4407
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.X, { className: "h-3.5 w-3.5 mr-1" }),
|
|
3804
4408
|
"Cancelar"
|
|
3805
4409
|
]
|
|
3806
4410
|
}
|
|
3807
4411
|
),
|
|
3808
|
-
/* @__PURE__ */ (0,
|
|
4412
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
3809
4413
|
Button,
|
|
3810
4414
|
{
|
|
3811
4415
|
size: "sm",
|
|
@@ -3813,33 +4417,33 @@ var UserProfile = ({
|
|
|
3813
4417
|
onClick: handleSaveEdit,
|
|
3814
4418
|
disabled: !editingMemoryContent.trim(),
|
|
3815
4419
|
children: [
|
|
3816
|
-
/* @__PURE__ */ (0,
|
|
4420
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Check, { className: "h-3.5 w-3.5 mr-1" }),
|
|
3817
4421
|
"Salvar"
|
|
3818
4422
|
]
|
|
3819
4423
|
}
|
|
3820
4424
|
)
|
|
3821
4425
|
] })
|
|
3822
|
-
] }) : /* @__PURE__ */ (0,
|
|
4426
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm break-words", children: memory.content })
|
|
3823
4427
|
] }),
|
|
3824
|
-
!isEditing && (onUpdateMemory || onDeleteMemory) && /* @__PURE__ */ (0,
|
|
3825
|
-
onUpdateMemory && /* @__PURE__ */ (0,
|
|
4428
|
+
!isEditing && (onUpdateMemory || onDeleteMemory) && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity shrink-0", children: [
|
|
4429
|
+
onUpdateMemory && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3826
4430
|
Button,
|
|
3827
4431
|
{
|
|
3828
4432
|
variant: "ghost",
|
|
3829
4433
|
size: "icon",
|
|
3830
4434
|
className: "h-7 w-7",
|
|
3831
4435
|
onClick: () => handleStartEdit(memory),
|
|
3832
|
-
children: /* @__PURE__ */ (0,
|
|
4436
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Pencil, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
3833
4437
|
}
|
|
3834
4438
|
),
|
|
3835
|
-
onDeleteMemory && /* @__PURE__ */ (0,
|
|
4439
|
+
onDeleteMemory && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3836
4440
|
Button,
|
|
3837
4441
|
{
|
|
3838
4442
|
variant: "ghost",
|
|
3839
4443
|
size: "icon",
|
|
3840
4444
|
className: "h-7 w-7",
|
|
3841
4445
|
onClick: () => onDeleteMemory(memory.id),
|
|
3842
|
-
children: /* @__PURE__ */ (0,
|
|
4446
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Trash2, { className: "h-3.5 w-3.5 text-destructive" })
|
|
3843
4447
|
}
|
|
3844
4448
|
)
|
|
3845
4449
|
] })
|
|
@@ -3850,8 +4454,8 @@ var UserProfile = ({
|
|
|
3850
4454
|
}) })
|
|
3851
4455
|
] })
|
|
3852
4456
|
] }) }),
|
|
3853
|
-
/* @__PURE__ */ (0,
|
|
3854
|
-
onEditProfile && /* @__PURE__ */ (0,
|
|
4457
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "p-4 border-t space-y-2 shrink-0", children: [
|
|
4458
|
+
onEditProfile && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3855
4459
|
Button,
|
|
3856
4460
|
{
|
|
3857
4461
|
variant: "outline",
|
|
@@ -3860,7 +4464,7 @@ var UserProfile = ({
|
|
|
3860
4464
|
children: "Edit Profile"
|
|
3861
4465
|
}
|
|
3862
4466
|
),
|
|
3863
|
-
onLogout && /* @__PURE__ */ (0,
|
|
4467
|
+
onLogout && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3864
4468
|
Button,
|
|
3865
4469
|
{
|
|
3866
4470
|
variant: "destructive",
|
|
@@ -3876,8 +4480,8 @@ var UserProfile = ({
|
|
|
3876
4480
|
};
|
|
3877
4481
|
|
|
3878
4482
|
// src/components/chat/ChatUI.tsx
|
|
3879
|
-
var
|
|
3880
|
-
var
|
|
4483
|
+
var import_lucide_react12 = require("lucide-react");
|
|
4484
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
3881
4485
|
var ChatUI = ({
|
|
3882
4486
|
messages = [],
|
|
3883
4487
|
threads = [],
|
|
@@ -4140,16 +4744,16 @@ var ChatUI = ({
|
|
|
4140
4744
|
}
|
|
4141
4745
|
return component;
|
|
4142
4746
|
}, [config?.customComponent?.component, closeSidebar, isMobile]);
|
|
4143
|
-
const SuggestionIconComponents = [
|
|
4747
|
+
const SuggestionIconComponents = [import_lucide_react12.MessageSquare, import_lucide_react12.Lightbulb, import_lucide_react12.Zap, import_lucide_react12.HelpCircle];
|
|
4144
4748
|
const renderSuggestions = () => {
|
|
4145
4749
|
if (messages.length > 0 || !suggestions.length) return null;
|
|
4146
|
-
return /* @__PURE__ */ (0,
|
|
4147
|
-
/* @__PURE__ */ (0,
|
|
4148
|
-
/* @__PURE__ */ (0,
|
|
4149
|
-
/* @__PURE__ */ (0,
|
|
4150
|
-
/* @__PURE__ */ (0,
|
|
4750
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col items-center justify-center min-h-[60vh] py-8 px-4", children: [
|
|
4751
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "text-center mb-8", children: [
|
|
4752
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "inline-flex items-center justify-center w-14 h-14 rounded-2xl bg-gradient-to-br from-primary/20 to-primary/5 mb-4 shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Sparkles, { className: "w-7 h-7 text-primary" }) }),
|
|
4753
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h2", { className: "text-xl font-semibold mb-2", children: config.branding.title }),
|
|
4754
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "text-muted-foreground text-sm max-w-md", children: config.branding.subtitle })
|
|
4151
4755
|
] }),
|
|
4152
|
-
/* @__PURE__ */ (0,
|
|
4756
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3 w-full max-w-2xl", children: suggestions.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
4153
4757
|
"button",
|
|
4154
4758
|
{
|
|
4155
4759
|
type: "button",
|
|
@@ -4158,10 +4762,10 @@ var ChatUI = ({
|
|
|
4158
4762
|
children: [
|
|
4159
4763
|
(() => {
|
|
4160
4764
|
const IconComponent = SuggestionIconComponents[index % SuggestionIconComponents.length];
|
|
4161
|
-
return /* @__PURE__ */ (0,
|
|
4765
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex items-center justify-center w-8 h-8 rounded-lg bg-primary/10 text-primary shrink-0 group-hover:bg-primary/15 transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(IconComponent, { className: "h-4 w-4" }) });
|
|
4162
4766
|
})(),
|
|
4163
|
-
/* @__PURE__ */ (0,
|
|
4164
|
-
/* @__PURE__ */ (0,
|
|
4767
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex-1 min-w-0 pr-6", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "text-sm font-medium leading-snug line-clamp-2", children: suggestion }) }),
|
|
4768
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.ArrowRight, { className: "absolute right-4 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
|
|
4165
4769
|
]
|
|
4166
4770
|
},
|
|
4167
4771
|
index
|
|
@@ -4172,34 +4776,34 @@ var ChatUI = ({
|
|
|
4172
4776
|
const items = messageSuggestions?.[messageId];
|
|
4173
4777
|
if (!items || items.length === 0) return null;
|
|
4174
4778
|
const inlineSuggestionOffsetClass = config.ui.showAvatars ? config.ui.compactMode ? "ml-9" : "ml-11" : "";
|
|
4175
|
-
return /* @__PURE__ */ (0,
|
|
4779
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: `flex flex-wrap gap-2 mt-2 ${inlineSuggestionOffsetClass}`, children: items.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
4176
4780
|
"button",
|
|
4177
4781
|
{
|
|
4178
4782
|
type: "button",
|
|
4179
4783
|
onClick: () => handleSendMessage(suggestion),
|
|
4180
4784
|
className: "group inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full border border-border bg-background hover:bg-accent hover:border-accent-foreground/20 transition-all duration-150 text-foreground/80 hover:text-foreground",
|
|
4181
4785
|
children: [
|
|
4182
|
-
/* @__PURE__ */ (0,
|
|
4183
|
-
/* @__PURE__ */ (0,
|
|
4786
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Sparkles, { className: "h-3 w-3 text-primary opacity-70 group-hover:opacity-100" }),
|
|
4787
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "max-w-[200px] truncate", children: suggestion })
|
|
4184
4788
|
]
|
|
4185
4789
|
},
|
|
4186
4790
|
`${messageId}-suggestion-${index}`
|
|
4187
4791
|
)) });
|
|
4188
4792
|
};
|
|
4189
|
-
const renderMessageLoadingSkeleton = () => /* @__PURE__ */ (0,
|
|
4793
|
+
const renderMessageLoadingSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "space-y-6 py-2", children: [0, 1, 2, 3].map((index) => {
|
|
4190
4794
|
const isUserRow = index % 2 === 1;
|
|
4191
|
-
return /* @__PURE__ */ (0,
|
|
4795
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
4192
4796
|
"div",
|
|
4193
4797
|
{
|
|
4194
4798
|
className: `flex gap-3 ${isUserRow ? "justify-end" : "justify-start"}`,
|
|
4195
4799
|
children: [
|
|
4196
|
-
!isUserRow && /* @__PURE__ */ (0,
|
|
4197
|
-
/* @__PURE__ */ (0,
|
|
4198
|
-
/* @__PURE__ */ (0,
|
|
4199
|
-
/* @__PURE__ */ (0,
|
|
4200
|
-
/* @__PURE__ */ (0,
|
|
4800
|
+
!isUserRow && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Skeleton, { className: "h-8 w-8 rounded-full shrink-0" }),
|
|
4801
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: `space-y-2 ${isUserRow ? "w-[70%]" : "w-[75%]"}`, children: [
|
|
4802
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Skeleton, { className: "h-4 w-24" }),
|
|
4803
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Skeleton, { className: "h-4 w-full" }),
|
|
4804
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Skeleton, { className: "h-4 w-[85%]" })
|
|
4201
4805
|
] }),
|
|
4202
|
-
isUserRow && /* @__PURE__ */ (0,
|
|
4806
|
+
isUserRow && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Skeleton, { className: "h-8 w-8 rounded-full shrink-0" })
|
|
4203
4807
|
]
|
|
4204
4808
|
},
|
|
4205
4809
|
`message-skeleton-${index}`
|
|
@@ -4255,8 +4859,8 @@ var ChatUI = ({
|
|
|
4255
4859
|
const shouldShowAgentSelector = Boolean(
|
|
4256
4860
|
config.agentSelector?.enabled && onSelectAgent && agentOptions.length > 0 && (!config.agentSelector?.hideIfSingle || agentOptions.length > 1)
|
|
4257
4861
|
);
|
|
4258
|
-
return /* @__PURE__ */ (0,
|
|
4259
|
-
/* @__PURE__ */ (0,
|
|
4862
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SidebarProvider, { defaultOpen: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: `flex h-[100svh] md:h-screen bg-background w-full overflow-hidden ${className}`, children: [
|
|
4863
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4260
4864
|
Sidebar2,
|
|
4261
4865
|
{
|
|
4262
4866
|
threads,
|
|
@@ -4273,8 +4877,8 @@ var ChatUI = ({
|
|
|
4273
4877
|
showThemeOptions: !!callbacks.onThemeChange
|
|
4274
4878
|
}
|
|
4275
4879
|
),
|
|
4276
|
-
/* @__PURE__ */ (0,
|
|
4277
|
-
/* @__PURE__ */ (0,
|
|
4880
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SidebarInset, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col h-full min-h-0", children: [
|
|
4881
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4278
4882
|
ChatHeader,
|
|
4279
4883
|
{
|
|
4280
4884
|
config,
|
|
@@ -4289,9 +4893,9 @@ var ChatUI = ({
|
|
|
4289
4893
|
onSelectAgent
|
|
4290
4894
|
}
|
|
4291
4895
|
),
|
|
4292
|
-
/* @__PURE__ */ (0,
|
|
4293
|
-
/* @__PURE__ */ (0,
|
|
4294
|
-
/* @__PURE__ */ (0,
|
|
4896
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-1 flex-row min-h-0 overflow-hidden", children: [
|
|
4897
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex-1 flex flex-col min-h-0", children: [
|
|
4898
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4295
4899
|
ScrollArea,
|
|
4296
4900
|
{
|
|
4297
4901
|
ref: scrollAreaRef,
|
|
@@ -4299,7 +4903,7 @@ var ChatUI = ({
|
|
|
4299
4903
|
viewportClassName: "p-4 overscroll-contain",
|
|
4300
4904
|
onScrollCapture: handleScroll,
|
|
4301
4905
|
style: { contain: "strict" },
|
|
4302
|
-
children: /* @__PURE__ */ (0,
|
|
4906
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "max-w-4xl mx-auto pb-4", children: isMessagesLoading ? renderMessageLoadingSkeleton() : messages.length === 0 ? renderSuggestions() : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4303
4907
|
"div",
|
|
4304
4908
|
{
|
|
4305
4909
|
style: {
|
|
@@ -4311,7 +4915,7 @@ var ChatUI = ({
|
|
|
4311
4915
|
const message = messages[virtualRow.index];
|
|
4312
4916
|
const prevMessage = virtualRow.index > 0 ? messages[virtualRow.index - 1] : null;
|
|
4313
4917
|
const isGrouped = prevMessage !== null && prevMessage.role === message.role;
|
|
4314
|
-
return /* @__PURE__ */ (0,
|
|
4918
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4315
4919
|
"div",
|
|
4316
4920
|
{
|
|
4317
4921
|
"data-index": virtualRow.index,
|
|
@@ -4323,8 +4927,8 @@ var ChatUI = ({
|
|
|
4323
4927
|
width: "100%",
|
|
4324
4928
|
transform: `translateY(${virtualRow.start}px)`
|
|
4325
4929
|
},
|
|
4326
|
-
children: /* @__PURE__ */ (0,
|
|
4327
|
-
/* @__PURE__ */ (0,
|
|
4930
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: virtualRow.index === 0 ? "" : isGrouped ? "pt-2" : "pt-4", children: [
|
|
4931
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4328
4932
|
Message,
|
|
4329
4933
|
{
|
|
4330
4934
|
message,
|
|
@@ -4343,7 +4947,7 @@ var ChatUI = ({
|
|
|
4343
4947
|
) })
|
|
4344
4948
|
}
|
|
4345
4949
|
),
|
|
4346
|
-
/* @__PURE__ */ (0,
|
|
4950
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "bg-background pb-[env(safe-area-inset-bottom)]", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4347
4951
|
ChatInput,
|
|
4348
4952
|
{
|
|
4349
4953
|
value: inputValue,
|
|
@@ -4369,17 +4973,17 @@ var ChatUI = ({
|
|
|
4369
4973
|
}
|
|
4370
4974
|
) })
|
|
4371
4975
|
] }),
|
|
4372
|
-
config?.customComponent?.component && !isMobile && /* @__PURE__ */ (0,
|
|
4976
|
+
config?.customComponent?.component && !isMobile && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4373
4977
|
"div",
|
|
4374
4978
|
{
|
|
4375
4979
|
className: `h-full transition-all duration-300 ease-in-out overflow-hidden ${state.showSidebar ? "w-80" : "w-0"}`,
|
|
4376
|
-
children: state.showSidebar && /* @__PURE__ */ (0,
|
|
4980
|
+
children: state.showSidebar && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex flex-col h-full border-l bg-background animate-in slide-in-from-right-4 duration-300 w-80", children: renderCustomComponent() })
|
|
4377
4981
|
}
|
|
4378
4982
|
)
|
|
4379
4983
|
] })
|
|
4380
4984
|
] }) }),
|
|
4381
|
-
isCustomMounted && config.customComponent?.component && isMobile && /* @__PURE__ */ (0,
|
|
4382
|
-
/* @__PURE__ */ (0,
|
|
4985
|
+
isCustomMounted && config.customComponent?.component && isMobile && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "fixed inset-0 z-50", children: [
|
|
4986
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4383
4987
|
"div",
|
|
4384
4988
|
{
|
|
4385
4989
|
className: `absolute inset-0 bg-background/80 backdrop-blur-sm transition-opacity duration-200 ease-out ${isCustomVisible ? "opacity-100" : "opacity-0"}`,
|
|
@@ -4387,16 +4991,16 @@ var ChatUI = ({
|
|
|
4387
4991
|
onClick: closeSidebar
|
|
4388
4992
|
}
|
|
4389
4993
|
),
|
|
4390
|
-
/* @__PURE__ */ (0,
|
|
4994
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4391
4995
|
"div",
|
|
4392
4996
|
{
|
|
4393
4997
|
className: `absolute top-0 right-0 h-full w-full bg-background transform-gpu transition-transform duration-200 ease-out ${isCustomVisible ? "translate-x-0" : "translate-x-full"}`,
|
|
4394
4998
|
style: { willChange: "transform" },
|
|
4395
|
-
children: /* @__PURE__ */ (0,
|
|
4999
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-full flex flex-col", children: renderCustomComponent() })
|
|
4396
5000
|
}
|
|
4397
5001
|
)
|
|
4398
5002
|
] }),
|
|
4399
|
-
isUserProfileOpen && /* @__PURE__ */ (0,
|
|
5003
|
+
isUserProfileOpen && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4400
5004
|
UserProfile,
|
|
4401
5005
|
{
|
|
4402
5006
|
isOpen: isUserProfileOpen,
|
|
@@ -4420,8 +5024,8 @@ var ChatUI = ({
|
|
|
4420
5024
|
|
|
4421
5025
|
// src/components/chat/ThreadManager.tsx
|
|
4422
5026
|
var import_react8 = require("react");
|
|
4423
|
-
var
|
|
4424
|
-
var
|
|
5027
|
+
var import_lucide_react13 = require("lucide-react");
|
|
5028
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
4425
5029
|
var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onArchive }) => {
|
|
4426
5030
|
const [isEditing, setIsEditing] = (0, import_react8.useState)(false);
|
|
4427
5031
|
const [editTitle, setEditTitle] = (0, import_react8.useState)(thread.title);
|
|
@@ -4450,9 +5054,9 @@ var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onAr
|
|
|
4450
5054
|
handleCancelEdit();
|
|
4451
5055
|
}
|
|
4452
5056
|
};
|
|
4453
|
-
return /* @__PURE__ */ (0,
|
|
4454
|
-
/* @__PURE__ */ (0,
|
|
4455
|
-
/* @__PURE__ */ (0,
|
|
5057
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Card, { className: `cursor-pointer transition-all duration-200 hover:shadow-md py-0 ${isActive ? "ring-2 ring-primary bg-primary/5" : "hover:bg-muted/50"}`, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CardContent, { className: "p-3 max-w-sm", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-start justify-between gap-2", children: [
|
|
5058
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex-1 min-w-0", onClick: onSelect, children: isEditing ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
5059
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
4456
5060
|
Input,
|
|
4457
5061
|
{
|
|
4458
5062
|
ref: inputRef,
|
|
@@ -4464,44 +5068,44 @@ var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onAr
|
|
|
4464
5068
|
placeholder: config?.labels?.threadNamePlaceholder || "Conversation name"
|
|
4465
5069
|
}
|
|
4466
5070
|
),
|
|
4467
|
-
/* @__PURE__ */ (0,
|
|
4468
|
-
/* @__PURE__ */ (0,
|
|
4469
|
-
] }) : /* @__PURE__ */ (0,
|
|
4470
|
-
/* @__PURE__ */ (0,
|
|
4471
|
-
/* @__PURE__ */ (0,
|
|
4472
|
-
/* @__PURE__ */ (0,
|
|
4473
|
-
/* @__PURE__ */ (0,
|
|
5071
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button, { size: "sm", variant: "ghost", onClick: handleSaveEdit, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Check, { className: "h-3 w-3" }) }),
|
|
5072
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button, { size: "sm", variant: "ghost", onClick: handleCancelEdit, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.X, { className: "h-3 w-3" }) })
|
|
5073
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
|
|
5074
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h4", { className: "font-medium text-sm truncate mb-1", children: thread.title }),
|
|
5075
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
5076
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
5077
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Hash, { className: "h-3 w-3" }),
|
|
4474
5078
|
thread.messageCount,
|
|
4475
5079
|
" msgs"
|
|
4476
5080
|
] }),
|
|
4477
|
-
/* @__PURE__ */ (0,
|
|
4478
|
-
/* @__PURE__ */ (0,
|
|
4479
|
-
/* @__PURE__ */ (0,
|
|
5081
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Separator, { orientation: "vertical", className: "h-3" }),
|
|
5082
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
5083
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Calendar, { className: "h-3 w-3" }),
|
|
4480
5084
|
formatDate(thread.updatedAt, config?.labels)
|
|
4481
5085
|
] }),
|
|
4482
|
-
thread.isArchived && /* @__PURE__ */ (0,
|
|
4483
|
-
/* @__PURE__ */ (0,
|
|
4484
|
-
/* @__PURE__ */ (0,
|
|
4485
|
-
/* @__PURE__ */ (0,
|
|
5086
|
+
thread.isArchived && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
|
|
5087
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Separator, { orientation: "vertical", className: "h-3" }),
|
|
5088
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Badge, { variant: "secondary", className: "text-xs", children: [
|
|
5089
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Archive, { className: "h-2 w-2 mr-1" }),
|
|
4486
5090
|
config?.labels?.archiveThread || "Archived"
|
|
4487
5091
|
] })
|
|
4488
5092
|
] })
|
|
4489
5093
|
] })
|
|
4490
5094
|
] }) }),
|
|
4491
|
-
!isEditing && /* @__PURE__ */ (0,
|
|
4492
|
-
/* @__PURE__ */ (0,
|
|
4493
|
-
/* @__PURE__ */ (0,
|
|
4494
|
-
/* @__PURE__ */ (0,
|
|
4495
|
-
/* @__PURE__ */ (0,
|
|
5095
|
+
!isEditing && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenu, { children: [
|
|
5096
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button, { variant: "ghost", size: "icon", className: "h-6 w-6 m-auto", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.MoreVertical, { className: "h-3 w-3" }) }) }),
|
|
5097
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuContent, { align: "end", children: [
|
|
5098
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: () => setIsEditing(true), children: [
|
|
5099
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Edit2, { className: "h-4 w-4 mr-2" }),
|
|
4496
5100
|
config?.labels?.renameThread || "Rename"
|
|
4497
5101
|
] }),
|
|
4498
|
-
/* @__PURE__ */ (0,
|
|
4499
|
-
/* @__PURE__ */ (0,
|
|
5102
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: onArchive, children: [
|
|
5103
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Archive, { className: "h-4 w-4 mr-2" }),
|
|
4500
5104
|
thread.isArchived ? config?.labels?.unarchiveThread || "Unarchive" : config?.labels?.archiveThread || "Archive"
|
|
4501
5105
|
] }),
|
|
4502
|
-
/* @__PURE__ */ (0,
|
|
4503
|
-
/* @__PURE__ */ (0,
|
|
4504
|
-
/* @__PURE__ */ (0,
|
|
5106
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DropdownMenuSeparator, {}),
|
|
5107
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenuItem, { onClick: onDelete, className: "text-destructive", children: [
|
|
5108
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Trash2, { className: "h-4 w-4 mr-2" }),
|
|
4505
5109
|
config?.labels?.deleteThread || "Delete"
|
|
4506
5110
|
] })
|
|
4507
5111
|
] })
|
|
@@ -4516,17 +5120,17 @@ var CreateThreadDialog2 = ({ onCreateThread, config }) => {
|
|
|
4516
5120
|
setTitle("");
|
|
4517
5121
|
setIsOpen(false);
|
|
4518
5122
|
};
|
|
4519
|
-
return /* @__PURE__ */ (0,
|
|
4520
|
-
/* @__PURE__ */ (0,
|
|
4521
|
-
/* @__PURE__ */ (0,
|
|
5123
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: [
|
|
5124
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DialogTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Button, { variant: "outline", className: "w-full", children: [
|
|
5125
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Plus, { className: "h-4 w-4 mr-2" }),
|
|
4522
5126
|
config?.labels?.createNewThread || "New Conversation"
|
|
4523
5127
|
] }) }),
|
|
4524
|
-
/* @__PURE__ */ (0,
|
|
4525
|
-
/* @__PURE__ */ (0,
|
|
4526
|
-
/* @__PURE__ */ (0,
|
|
4527
|
-
/* @__PURE__ */ (0,
|
|
5128
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DialogContent, { children: [
|
|
5129
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DialogHeader, { children: [
|
|
5130
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DialogTitle, { children: config?.labels?.createNewThread || "Create New Conversation" }),
|
|
5131
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DialogDescription, { children: "Give your new conversation a name or leave blank to auto-generate one." })
|
|
4528
5132
|
] }),
|
|
4529
|
-
/* @__PURE__ */ (0,
|
|
5133
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
4530
5134
|
Input,
|
|
4531
5135
|
{
|
|
4532
5136
|
value: title,
|
|
@@ -4536,9 +5140,9 @@ var CreateThreadDialog2 = ({ onCreateThread, config }) => {
|
|
|
4536
5140
|
autoFocus: true
|
|
4537
5141
|
}
|
|
4538
5142
|
),
|
|
4539
|
-
/* @__PURE__ */ (0,
|
|
4540
|
-
/* @__PURE__ */ (0,
|
|
4541
|
-
/* @__PURE__ */ (0,
|
|
5143
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DialogFooter, { children: [
|
|
5144
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button, { variant: "outline", onClick: () => setIsOpen(false), children: config?.labels?.cancel || "Cancel" }),
|
|
5145
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button, { onClick: handleCreate, children: config?.labels?.create || "Create" })
|
|
4542
5146
|
] })
|
|
4543
5147
|
] })
|
|
4544
5148
|
] });
|
|
@@ -4592,20 +5196,20 @@ var ThreadManager = ({
|
|
|
4592
5196
|
setDeleteThreadId(null);
|
|
4593
5197
|
};
|
|
4594
5198
|
if (!isOpen) return null;
|
|
4595
|
-
return /* @__PURE__ */ (0,
|
|
4596
|
-
/* @__PURE__ */ (0,
|
|
4597
|
-
/* @__PURE__ */ (0,
|
|
4598
|
-
/* @__PURE__ */ (0,
|
|
4599
|
-
/* @__PURE__ */ (0,
|
|
4600
|
-
/* @__PURE__ */ (0,
|
|
5199
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: `fixed inset-0 z-50 bg-background/80 backdrop-blur-sm ${className}`, children: [
|
|
5200
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "fixed left-0 top-0 h-full w-full max-w-md border-r bg-background shadow-lg", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Card, { className: "h-full border-0 rounded-none", children: [
|
|
5201
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardHeader, { className: "border-b", children: [
|
|
5202
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
5203
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardTitle, { className: "flex items-center gap-2", children: [
|
|
5204
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.MessageSquare, { className: "h-5 w-5" }),
|
|
4601
5205
|
config?.labels?.newChat || "Conversations"
|
|
4602
5206
|
] }),
|
|
4603
|
-
/* @__PURE__ */ (0,
|
|
5207
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button, { variant: "ghost", size: "icon", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.X, { className: "h-4 w-4" }) })
|
|
4604
5208
|
] }),
|
|
4605
|
-
/* @__PURE__ */ (0,
|
|
4606
|
-
/* @__PURE__ */ (0,
|
|
4607
|
-
/* @__PURE__ */ (0,
|
|
4608
|
-
/* @__PURE__ */ (0,
|
|
5209
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "space-y-3", children: [
|
|
5210
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "relative", children: [
|
|
5211
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
5212
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
4609
5213
|
Input,
|
|
4610
5214
|
{
|
|
4611
5215
|
placeholder: config?.labels?.search || "Search conversations...",
|
|
@@ -4615,8 +5219,8 @@ var ThreadManager = ({
|
|
|
4615
5219
|
}
|
|
4616
5220
|
)
|
|
4617
5221
|
] }),
|
|
4618
|
-
/* @__PURE__ */ (0,
|
|
4619
|
-
/* @__PURE__ */ (0,
|
|
5222
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
5223
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
4620
5224
|
Button,
|
|
4621
5225
|
{
|
|
4622
5226
|
variant: "outline",
|
|
@@ -4624,12 +5228,12 @@ var ThreadManager = ({
|
|
|
4624
5228
|
onClick: () => setShowArchived(!showArchived),
|
|
4625
5229
|
className: "text-xs",
|
|
4626
5230
|
children: [
|
|
4627
|
-
/* @__PURE__ */ (0,
|
|
5231
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Filter, { className: "h-3 w-3 mr-1" }),
|
|
4628
5232
|
showArchived ? config?.labels?.hideArchived || "Hide Archived" : config?.labels?.showArchived || "Show Archived"
|
|
4629
5233
|
]
|
|
4630
5234
|
}
|
|
4631
5235
|
),
|
|
4632
|
-
/* @__PURE__ */ (0,
|
|
5236
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Badge, { variant: "secondary", className: "text-xs", children: [
|
|
4633
5237
|
filteredThreads.length,
|
|
4634
5238
|
" / ",
|
|
4635
5239
|
threads.length
|
|
@@ -4637,14 +5241,14 @@ var ThreadManager = ({
|
|
|
4637
5241
|
] })
|
|
4638
5242
|
] })
|
|
4639
5243
|
] }),
|
|
4640
|
-
/* @__PURE__ */ (0,
|
|
4641
|
-
/* @__PURE__ */ (0,
|
|
4642
|
-
/* @__PURE__ */ (0,
|
|
4643
|
-
/* @__PURE__ */ (0,
|
|
4644
|
-
/* @__PURE__ */ (0,
|
|
4645
|
-
] }) : Object.entries(groupedThreads).map(([group, groupThreads]) => /* @__PURE__ */ (0,
|
|
4646
|
-
/* @__PURE__ */ (0,
|
|
4647
|
-
/* @__PURE__ */ (0,
|
|
5244
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CardContent, { className: "p-0 flex-1", children: [
|
|
5245
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "p-4", children: onCreateThread && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CreateThreadDialog2, { onCreateThread, config }) }),
|
|
5246
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ScrollArea, { className: "h-[calc(100vh-280px)]", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "px-4 pb-4 space-y-4", children: Object.keys(groupedThreads).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "text-center py-8 text-muted-foreground", children: [
|
|
5247
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.MessageSquare, { className: "h-12 w-12 mx-auto mb-3 opacity-50" }),
|
|
5248
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-sm", children: searchQuery ? config?.labels?.noThreadsFound || "No conversations found" : config?.labels?.noThreadsYet || "No conversations yet" })
|
|
5249
|
+
] }) : Object.entries(groupedThreads).map(([group, groupThreads]) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { children: [
|
|
5250
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h3", { className: "text-sm font-medium text-muted-foreground mb-2 px-2", children: group }),
|
|
5251
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "space-y-2", children: groupThreads.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
4648
5252
|
ThreadItem,
|
|
4649
5253
|
{
|
|
4650
5254
|
thread,
|
|
@@ -4660,14 +5264,14 @@ var ThreadManager = ({
|
|
|
4660
5264
|
] }, group)) }) })
|
|
4661
5265
|
] })
|
|
4662
5266
|
] }) }),
|
|
4663
|
-
deleteThreadId && /* @__PURE__ */ (0,
|
|
4664
|
-
/* @__PURE__ */ (0,
|
|
4665
|
-
/* @__PURE__ */ (0,
|
|
4666
|
-
/* @__PURE__ */ (0,
|
|
5267
|
+
deleteThreadId && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(AlertDialogContent, { children: [
|
|
5268
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(AlertDialogHeader, { children: [
|
|
5269
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AlertDialogTitle, { children: config?.labels?.deleteConfirmTitle || "Delete Conversation" }),
|
|
5270
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AlertDialogDescription, { children: config?.labels?.deleteConfirmDescription || "Are you sure you want to delete this conversation? This action cannot be undone." })
|
|
4667
5271
|
] }),
|
|
4668
|
-
/* @__PURE__ */ (0,
|
|
4669
|
-
/* @__PURE__ */ (0,
|
|
4670
|
-
/* @__PURE__ */ (0,
|
|
5272
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(AlertDialogFooter, { children: [
|
|
5273
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AlertDialogCancel, { children: config?.labels?.cancel || "Cancel" }),
|
|
5274
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
4671
5275
|
AlertDialogAction,
|
|
4672
5276
|
{
|
|
4673
5277
|
onClick: () => deleteThreadId && handleDeleteThread(deleteThreadId),
|