@copilotz/chat-ui 0.1.32 → 0.1.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +119 -78
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +134 -93
- package/dist/index.js.map +1 -1
- package/dist/styles.css +86 -2
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -123,15 +123,18 @@ interface ChatConfig {
|
|
|
123
123
|
voiceEnter?: string;
|
|
124
124
|
voiceExit?: string;
|
|
125
125
|
voiceTitle?: string;
|
|
126
|
+
voiceIdle?: string;
|
|
126
127
|
voicePreparing?: string;
|
|
127
128
|
voiceWaiting?: string;
|
|
128
129
|
voiceListening?: string;
|
|
129
130
|
voiceFinishing?: string;
|
|
130
131
|
voiceReview?: string;
|
|
132
|
+
voiceSending?: string;
|
|
131
133
|
voiceStart?: string;
|
|
132
134
|
voiceStop?: string;
|
|
133
135
|
voiceSendNow?: string;
|
|
134
136
|
voiceCancel?: string;
|
|
137
|
+
voiceDiscard?: string;
|
|
135
138
|
voiceRecordAgain?: string;
|
|
136
139
|
voiceAutoSendIn?: string;
|
|
137
140
|
voiceTranscriptPending?: string;
|
|
@@ -198,6 +201,7 @@ interface ChatConfig {
|
|
|
198
201
|
};
|
|
199
202
|
voiceCompose?: {
|
|
200
203
|
enabled?: boolean;
|
|
204
|
+
defaultMode?: 'text' | 'voice';
|
|
201
205
|
autoSendDelayMs?: number;
|
|
202
206
|
persistComposer?: boolean;
|
|
203
207
|
showTranscriptPreview?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -123,15 +123,18 @@ interface ChatConfig {
|
|
|
123
123
|
voiceEnter?: string;
|
|
124
124
|
voiceExit?: string;
|
|
125
125
|
voiceTitle?: string;
|
|
126
|
+
voiceIdle?: string;
|
|
126
127
|
voicePreparing?: string;
|
|
127
128
|
voiceWaiting?: string;
|
|
128
129
|
voiceListening?: string;
|
|
129
130
|
voiceFinishing?: string;
|
|
130
131
|
voiceReview?: string;
|
|
132
|
+
voiceSending?: string;
|
|
131
133
|
voiceStart?: string;
|
|
132
134
|
voiceStop?: string;
|
|
133
135
|
voiceSendNow?: string;
|
|
134
136
|
voiceCancel?: string;
|
|
137
|
+
voiceDiscard?: string;
|
|
135
138
|
voiceRecordAgain?: string;
|
|
136
139
|
voiceAutoSendIn?: string;
|
|
137
140
|
voiceTranscriptPending?: string;
|
|
@@ -198,6 +201,7 @@ interface ChatConfig {
|
|
|
198
201
|
};
|
|
199
202
|
voiceCompose?: {
|
|
200
203
|
enabled?: boolean;
|
|
204
|
+
defaultMode?: 'text' | 'voice';
|
|
201
205
|
autoSendDelayMs?: number;
|
|
202
206
|
persistComposer?: boolean;
|
|
203
207
|
showTranscriptPreview?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -32,16 +32,19 @@ var defaultChatConfig = {
|
|
|
32
32
|
recordAudioTooltip: "Record audio",
|
|
33
33
|
voiceEnter: "Voice input",
|
|
34
34
|
voiceExit: "Use keyboard",
|
|
35
|
-
voiceTitle: "Voice
|
|
35
|
+
voiceTitle: "Voice",
|
|
36
|
+
voiceIdle: "Tap the mic to record",
|
|
36
37
|
voicePreparing: "Preparing microphone...",
|
|
37
38
|
voiceWaiting: "Waiting for speech...",
|
|
38
39
|
voiceListening: "Listening...",
|
|
39
40
|
voiceFinishing: "Finishing capture...",
|
|
40
41
|
voiceReview: "Ready to send",
|
|
42
|
+
voiceSending: "Sending...",
|
|
41
43
|
voiceStart: "Start recording",
|
|
42
44
|
voiceStop: "Stop recording",
|
|
43
45
|
voiceSendNow: "Send now",
|
|
44
46
|
voiceCancel: "Cancel",
|
|
47
|
+
voiceDiscard: "Delete recording",
|
|
45
48
|
voiceRecordAgain: "Record again",
|
|
46
49
|
voiceAutoSendIn: "Auto-sends in {{seconds}}s",
|
|
47
50
|
voiceTranscriptPending: "Transcript unavailable",
|
|
@@ -111,6 +114,7 @@ var defaultChatConfig = {
|
|
|
111
114
|
},
|
|
112
115
|
voiceCompose: {
|
|
113
116
|
enabled: false,
|
|
117
|
+
defaultMode: "text",
|
|
114
118
|
autoSendDelayMs: 5e3,
|
|
115
119
|
persistComposer: true,
|
|
116
120
|
showTranscriptPreview: true,
|
|
@@ -3063,8 +3067,8 @@ function Progress({
|
|
|
3063
3067
|
}
|
|
3064
3068
|
|
|
3065
3069
|
// src/components/chat/VoiceComposer.tsx
|
|
3066
|
-
import { Keyboard, Loader2, Mic,
|
|
3067
|
-
import {
|
|
3070
|
+
import { Keyboard, Loader2, Mic, Send, Square, Trash2 as Trash23, X as X2 } from "lucide-react";
|
|
3071
|
+
import { jsx as jsx21, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3068
3072
|
var formatDuration = (durationMs) => {
|
|
3069
3073
|
const totalSeconds = Math.max(0, Math.floor(durationMs / 1e3));
|
|
3070
3074
|
const minutes = Math.floor(totalSeconds / 60);
|
|
@@ -3093,12 +3097,12 @@ var resolveStateLabel = (state, labels, errorMessage) => {
|
|
|
3093
3097
|
case "review":
|
|
3094
3098
|
return labels?.voiceReview || "Ready to send";
|
|
3095
3099
|
case "sending":
|
|
3096
|
-
return "Sending...";
|
|
3100
|
+
return labels?.voiceSending || "Sending...";
|
|
3097
3101
|
case "error":
|
|
3098
3102
|
return errorMessage || labels?.voiceCaptureError || "Unable to capture audio.";
|
|
3099
3103
|
case "idle":
|
|
3100
3104
|
default:
|
|
3101
|
-
return labels?.
|
|
3105
|
+
return labels?.voiceIdle || "Tap the mic to record";
|
|
3102
3106
|
}
|
|
3103
3107
|
};
|
|
3104
3108
|
var resolveTranscriptText = (transcript, transcriptMode) => {
|
|
@@ -3115,18 +3119,21 @@ var VoiceComposer = ({
|
|
|
3115
3119
|
transcript,
|
|
3116
3120
|
transcriptMode,
|
|
3117
3121
|
showTranscriptPreview,
|
|
3122
|
+
attachment,
|
|
3118
3123
|
durationMs,
|
|
3119
3124
|
audioLevel,
|
|
3120
3125
|
countdownMs,
|
|
3121
3126
|
autoSendDelayMs,
|
|
3127
|
+
isAutoSendActive,
|
|
3122
3128
|
errorMessage,
|
|
3123
3129
|
disabled = false,
|
|
3124
3130
|
labels,
|
|
3125
3131
|
onStart,
|
|
3126
3132
|
onStop,
|
|
3127
|
-
|
|
3128
|
-
|
|
3133
|
+
onCancelAutoSend,
|
|
3134
|
+
onDiscard,
|
|
3129
3135
|
onRecordAgain,
|
|
3136
|
+
onSendNow,
|
|
3130
3137
|
onExit
|
|
3131
3138
|
}) => {
|
|
3132
3139
|
const transcriptText = resolveTranscriptText(transcript, transcriptMode);
|
|
@@ -3134,12 +3141,14 @@ var VoiceComposer = ({
|
|
|
3134
3141
|
const countdownValue = autoSendDelayMs > 0 ? Math.min(100, Math.max(0, (autoSendDelayMs - countdownMs) / autoSendDelayMs * 100)) : 100;
|
|
3135
3142
|
const isBusy = state === "preparing" || state === "finishing" || state === "sending";
|
|
3136
3143
|
const isCapturing = state === "waiting_for_speech" || state === "listening";
|
|
3144
|
+
const isReviewing = state === "review";
|
|
3137
3145
|
const levelValue = isCapturing || state === "preparing" || state === "finishing" ? Math.max(8, Math.round(audioLevel * 100)) : 0;
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
/* @__PURE__ */ jsx21(
|
|
3146
|
+
const headerLabel = state === "error" ? labels?.voiceCaptureError || "Unable to capture audio." : resolveStateLabel(state, labels, errorMessage);
|
|
3147
|
+
return /* @__PURE__ */ jsxs11("div", { className: "w-full max-w-3xl rounded-xl border bg-background p-3 shadow-sm sm:p-4 md:min-w-3xl", children: [
|
|
3148
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between gap-2 sm:gap-3", children: [
|
|
3149
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
3150
|
+
/* @__PURE__ */ jsx21(Badge, { variant: "outline", children: labels?.voiceTitle || "Voice" }),
|
|
3151
|
+
/* @__PURE__ */ jsx21("span", { className: "truncate text-xs sm:text-sm text-muted-foreground", children: headerLabel })
|
|
3143
3152
|
] }),
|
|
3144
3153
|
/* @__PURE__ */ jsxs11(
|
|
3145
3154
|
Button,
|
|
@@ -3147,71 +3156,89 @@ var VoiceComposer = ({
|
|
|
3147
3156
|
type: "button",
|
|
3148
3157
|
variant: "ghost",
|
|
3149
3158
|
size: "sm",
|
|
3159
|
+
className: "shrink-0 px-2 sm:px-3",
|
|
3150
3160
|
onClick: onExit,
|
|
3151
3161
|
disabled: disabled || isBusy,
|
|
3152
3162
|
children: [
|
|
3153
3163
|
/* @__PURE__ */ jsx21(Keyboard, { className: "h-4 w-4" }),
|
|
3154
|
-
labels?.voiceExit || "Use keyboard"
|
|
3164
|
+
/* @__PURE__ */ jsx21("span", { className: "hidden sm:inline", children: labels?.voiceExit || "Use keyboard" })
|
|
3155
3165
|
]
|
|
3156
3166
|
}
|
|
3157
3167
|
)
|
|
3158
3168
|
] }),
|
|
3159
|
-
/* @__PURE__ */
|
|
3160
|
-
/* @__PURE__ */ jsx21(
|
|
3161
|
-
|
|
3169
|
+
!isReviewing ? /* @__PURE__ */ jsx21("div", { className: "mt-3 rounded-xl border border-dashed border-primary/30 bg-primary/5 px-3 py-3 text-center sm:px-4 sm:py-4", children: /* @__PURE__ */ jsxs11("div", { className: "mx-auto flex w-full max-w-sm flex-col items-center gap-3", children: [
|
|
3170
|
+
/* @__PURE__ */ jsx21(
|
|
3171
|
+
Button,
|
|
3172
|
+
{
|
|
3173
|
+
type: "button",
|
|
3174
|
+
size: "icon",
|
|
3175
|
+
variant: isCapturing ? "destructive" : "outline",
|
|
3176
|
+
className: `h-16 w-16 rounded-full sm:h-20 sm:w-20 ${isCapturing ? "bg-red-500 hover:bg-red-600 text-white border-red-500" : "border-red-200 bg-red-50 text-red-600 hover:bg-red-100 hover:text-red-700"}`,
|
|
3177
|
+
onClick: isCapturing ? onStop : onStart,
|
|
3178
|
+
disabled: disabled || isBusy,
|
|
3179
|
+
children: isBusy ? /* @__PURE__ */ jsx21(Loader2, { className: "h-7 w-7 animate-spin" }) : isCapturing ? /* @__PURE__ */ jsx21(Square, { className: "h-7 w-7" }) : /* @__PURE__ */ jsx21(Mic, { className: "h-7 w-7" })
|
|
3180
|
+
}
|
|
3181
|
+
),
|
|
3182
|
+
/* @__PURE__ */ jsxs11("div", { className: "w-full space-y-2", children: [
|
|
3162
3183
|
/* @__PURE__ */ jsx21(Progress, { value: levelValue, className: "h-2" }),
|
|
3163
3184
|
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
|
|
3164
3185
|
/* @__PURE__ */ jsx21("span", { children: formatDuration(durationMs) }),
|
|
3165
|
-
/* @__PURE__ */ jsx21("span", { children:
|
|
3186
|
+
/* @__PURE__ */ jsx21("span", { children: isCapturing ? labels?.voiceStop || "Stop recording" : labels?.voiceStart || "Start recording" })
|
|
3166
3187
|
] })
|
|
3167
3188
|
] }),
|
|
3168
|
-
showTranscriptPreview && transcriptMode !== "none" && transcriptText && /* @__PURE__ */ jsx21("div", { className: "w-full
|
|
3169
|
-
] }),
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
state === "error" && errorMessage && /* @__PURE__ */ jsx21("div", { className: "mt-4 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2 text-sm text-destructive", children: errorMessage }),
|
|
3175
|
-
/* @__PURE__ */ jsxs11("div", { className: "mt-4 flex flex-wrap items-center justify-center gap-2", children: [
|
|
3176
|
-
state === "idle" && /* @__PURE__ */ jsxs11(Button, { type: "button", onClick: onStart, disabled, children: [
|
|
3177
|
-
/* @__PURE__ */ jsx21(Mic, { className: "h-4 w-4" }),
|
|
3178
|
-
labels?.voiceStart || "Start recording"
|
|
3179
|
-
] }),
|
|
3180
|
-
isCapturing && /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
3181
|
-
/* @__PURE__ */ jsxs11(Button, { type: "button", onClick: onStop, disabled, children: [
|
|
3182
|
-
/* @__PURE__ */ jsx21(Square, { className: "h-4 w-4" }),
|
|
3183
|
-
labels?.voiceStop || "Stop recording"
|
|
3189
|
+
showTranscriptPreview && transcriptMode !== "none" && transcriptText && /* @__PURE__ */ jsx21("div", { className: "w-full rounded-lg border bg-background px-3 py-2 text-left text-sm", children: transcriptText })
|
|
3190
|
+
] }) }) : /* @__PURE__ */ jsxs11("div", { className: "mt-3 rounded-xl border bg-muted/20 p-3 sm:p-4", children: [
|
|
3191
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-start justify-between gap-2", children: [
|
|
3192
|
+
/* @__PURE__ */ jsxs11("div", { className: "min-w-0", children: [
|
|
3193
|
+
/* @__PURE__ */ jsx21("div", { className: "text-sm font-medium text-foreground", children: labels?.voiceReview || "Ready to send" }),
|
|
3194
|
+
/* @__PURE__ */ jsx21("div", { className: "text-xs text-muted-foreground", children: formatDuration(durationMs) })
|
|
3184
3195
|
] }),
|
|
3185
|
-
/* @__PURE__ */
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3196
|
+
/* @__PURE__ */ jsx21(
|
|
3197
|
+
Button,
|
|
3198
|
+
{
|
|
3199
|
+
type: "button",
|
|
3200
|
+
variant: "ghost",
|
|
3201
|
+
size: "icon",
|
|
3202
|
+
className: "h-8 w-8 shrink-0 text-muted-foreground hover:text-destructive",
|
|
3203
|
+
onClick: onDiscard,
|
|
3204
|
+
disabled,
|
|
3205
|
+
"aria-label": labels?.voiceDiscard || "Delete recording",
|
|
3206
|
+
title: labels?.voiceDiscard || "Delete recording",
|
|
3207
|
+
children: /* @__PURE__ */ jsx21(Trash23, { className: "h-4 w-4" })
|
|
3208
|
+
}
|
|
3209
|
+
)
|
|
3210
|
+
] }),
|
|
3211
|
+
attachment && /* @__PURE__ */ jsx21("div", { className: "mt-3 rounded-lg bg-background p-2", children: /* @__PURE__ */ jsx21("audio", { controls: true, preload: "metadata", className: "w-full", children: /* @__PURE__ */ jsx21("source", { src: attachment.dataUrl, type: attachment.mimeType }) }) }),
|
|
3212
|
+
showTranscriptPreview && transcriptMode !== "none" && transcriptText && /* @__PURE__ */ jsx21("div", { className: "mt-3 rounded-lg border bg-background px-3 py-2 text-left text-sm", children: transcriptText }),
|
|
3213
|
+
isAutoSendActive && autoSendDelayMs > 0 && /* @__PURE__ */ jsxs11("div", { className: "mt-3 space-y-2", children: [
|
|
3214
|
+
/* @__PURE__ */ jsx21(Progress, { value: countdownValue, className: "h-2" }),
|
|
3215
|
+
/* @__PURE__ */ jsx21("div", { className: "text-center text-xs text-muted-foreground", children: interpolateSeconds(labels?.voiceAutoSendIn, countdownSeconds) })
|
|
3189
3216
|
] }),
|
|
3190
|
-
|
|
3191
|
-
/* @__PURE__ */ jsxs11(Button, { type: "button", variant: "
|
|
3217
|
+
/* @__PURE__ */ jsxs11("div", { className: "mt-3 flex items-center justify-end gap-2", children: [
|
|
3218
|
+
isAutoSendActive && /* @__PURE__ */ jsxs11(Button, { type: "button", variant: "ghost", size: "sm", onClick: onCancelAutoSend, disabled, children: [
|
|
3192
3219
|
/* @__PURE__ */ jsx21(X2, { className: "h-4 w-4" }),
|
|
3193
3220
|
labels?.voiceCancel || "Cancel"
|
|
3194
3221
|
] }),
|
|
3195
|
-
/* @__PURE__ */
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3222
|
+
!isAutoSendActive && /* @__PURE__ */ jsx21(
|
|
3223
|
+
Button,
|
|
3224
|
+
{
|
|
3225
|
+
type: "button",
|
|
3226
|
+
variant: "outline",
|
|
3227
|
+
size: "icon",
|
|
3228
|
+
onClick: onRecordAgain,
|
|
3229
|
+
disabled,
|
|
3230
|
+
"aria-label": labels?.voiceRecordAgain || "Record again",
|
|
3231
|
+
title: labels?.voiceRecordAgain || "Record again",
|
|
3232
|
+
children: /* @__PURE__ */ jsx21(Mic, { className: "h-4 w-4" })
|
|
3233
|
+
}
|
|
3234
|
+
),
|
|
3235
|
+
/* @__PURE__ */ jsxs11(Button, { type: "button", size: "sm", onClick: onSendNow, disabled, children: [
|
|
3200
3236
|
/* @__PURE__ */ jsx21(Send, { className: "h-4 w-4" }),
|
|
3201
3237
|
labels?.voiceSendNow || "Send now"
|
|
3202
3238
|
] })
|
|
3203
|
-
] }),
|
|
3204
|
-
state === "error" && /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
3205
|
-
/* @__PURE__ */ jsxs11(Button, { type: "button", variant: "outline", onClick: onCancel, disabled, children: [
|
|
3206
|
-
/* @__PURE__ */ jsx21(X2, { className: "h-4 w-4" }),
|
|
3207
|
-
labels?.voiceCancel || "Cancel"
|
|
3208
|
-
] }),
|
|
3209
|
-
/* @__PURE__ */ jsxs11(Button, { type: "button", onClick: onRecordAgain, disabled, children: [
|
|
3210
|
-
/* @__PURE__ */ jsx21(RotateCcw2, { className: "h-4 w-4" }),
|
|
3211
|
-
labels?.voiceRecordAgain || "Record again"
|
|
3212
|
-
] })
|
|
3213
3239
|
] })
|
|
3214
|
-
] })
|
|
3240
|
+
] }),
|
|
3241
|
+
state === "error" && errorMessage && /* @__PURE__ */ jsx21("div", { className: "mt-3 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2 text-sm text-destructive", children: errorMessage })
|
|
3215
3242
|
] });
|
|
3216
3243
|
};
|
|
3217
3244
|
|
|
@@ -3229,7 +3256,7 @@ import {
|
|
|
3229
3256
|
Pause,
|
|
3230
3257
|
Loader2 as Loader22
|
|
3231
3258
|
} from "lucide-react";
|
|
3232
|
-
import { Fragment as
|
|
3259
|
+
import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3233
3260
|
var FileUploadItem = memo2(function FileUploadItem2({ file, progress, onCancel }) {
|
|
3234
3261
|
const guessTypeFromName = (name) => {
|
|
3235
3262
|
const ext = (name || "").split(".").pop()?.toLowerCase();
|
|
@@ -3330,7 +3357,7 @@ var AttachmentPreview = memo2(function AttachmentPreview2({ attachment, onRemove
|
|
|
3330
3357
|
"img",
|
|
3331
3358
|
{
|
|
3332
3359
|
src: attachment.dataUrl,
|
|
3333
|
-
alt: attachment.fileName || "
|
|
3360
|
+
alt: attachment.fileName || "Attachment",
|
|
3334
3361
|
className: "w-full h-20 object-cover rounded"
|
|
3335
3362
|
}
|
|
3336
3363
|
),
|
|
@@ -3379,7 +3406,7 @@ var AttachmentPreview = memo2(function AttachmentPreview2({ attachment, onRemove
|
|
|
3379
3406
|
}
|
|
3380
3407
|
),
|
|
3381
3408
|
/* @__PURE__ */ jsxs12("div", { className: "flex-1", children: [
|
|
3382
|
-
/* @__PURE__ */ jsx22("p", { className: "text-xs font-medium", children: attachment.fileName || "
|
|
3409
|
+
/* @__PURE__ */ jsx22("p", { className: "text-xs font-medium", children: attachment.fileName || "Audio" }),
|
|
3383
3410
|
/* @__PURE__ */ jsx22("p", { className: "text-xs text-muted-foreground", children: formatDuration2(attachment.durationMs) })
|
|
3384
3411
|
] }),
|
|
3385
3412
|
/* @__PURE__ */ jsx22(
|
|
@@ -3431,7 +3458,7 @@ var AudioRecorder = memo2(function AudioRecorder2({ isRecording, onStartRecordin
|
|
|
3431
3458
|
return /* @__PURE__ */ jsx22(Card, { className: "border-red-200 bg-red-50 dark:border-red-800 dark:bg-red-950", children: /* @__PURE__ */ jsx22(CardContent, { className: "p-3", children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
|
|
3432
3459
|
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
|
|
3433
3460
|
/* @__PURE__ */ jsx22("div", { className: "h-3 w-3 bg-red-500 rounded-full animate-pulse" }),
|
|
3434
|
-
/* @__PURE__ */ jsx22("span", { className: "text-sm font-medium text-red-700 dark:text-red-300", children: "
|
|
3461
|
+
/* @__PURE__ */ jsx22("span", { className: "text-sm font-medium text-red-700 dark:text-red-300", children: config?.labels?.voiceListening || "Recording" })
|
|
3435
3462
|
] }),
|
|
3436
3463
|
/* @__PURE__ */ jsx22(Badge, { variant: "outline", className: "text-xs", children: formatTime(recordingDuration) }),
|
|
3437
3464
|
/* @__PURE__ */ jsxs12("div", { className: "flex gap-1 ml-auto", children: [
|
|
@@ -3443,7 +3470,7 @@ var AudioRecorder = memo2(function AudioRecorder2({ isRecording, onStartRecordin
|
|
|
3443
3470
|
onClick: onCancel,
|
|
3444
3471
|
children: [
|
|
3445
3472
|
/* @__PURE__ */ jsx22(X3, { className: "h-3 w-3 mr-1" }),
|
|
3446
|
-
"
|
|
3473
|
+
config?.labels?.cancel || "Cancel"
|
|
3447
3474
|
]
|
|
3448
3475
|
}
|
|
3449
3476
|
),
|
|
@@ -3455,7 +3482,7 @@ var AudioRecorder = memo2(function AudioRecorder2({ isRecording, onStartRecordin
|
|
|
3455
3482
|
onClick: onStopRecording,
|
|
3456
3483
|
children: [
|
|
3457
3484
|
/* @__PURE__ */ jsx22(Square2, { className: "h-3 w-3 mr-1" }),
|
|
3458
|
-
"
|
|
3485
|
+
config?.labels?.voiceStop || "Stop"
|
|
3459
3486
|
]
|
|
3460
3487
|
}
|
|
3461
3488
|
)
|
|
@@ -3478,7 +3505,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3478
3505
|
onSubmit,
|
|
3479
3506
|
attachments,
|
|
3480
3507
|
onAttachmentsChange,
|
|
3481
|
-
placeholder = "
|
|
3508
|
+
placeholder = "Type your message...",
|
|
3482
3509
|
disabled = false,
|
|
3483
3510
|
isGenerating = false,
|
|
3484
3511
|
onStopGeneration,
|
|
@@ -3491,17 +3518,27 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3491
3518
|
className = "",
|
|
3492
3519
|
config
|
|
3493
3520
|
}) {
|
|
3521
|
+
const voiceComposeEnabled = config?.voiceCompose?.enabled === true;
|
|
3522
|
+
const voiceDefaultMode = config?.voiceCompose?.defaultMode ?? "text";
|
|
3523
|
+
const voiceAutoSendDelayMs = config?.voiceCompose?.autoSendDelayMs ?? 5e3;
|
|
3524
|
+
const voicePersistComposer = config?.voiceCompose?.persistComposer ?? true;
|
|
3525
|
+
const voiceShowTranscriptPreview = config?.voiceCompose?.showTranscriptPreview ?? true;
|
|
3526
|
+
const voiceTranscriptMode = config?.voiceCompose?.transcriptMode ?? "final-only";
|
|
3527
|
+
const voiceMaxRecordingMs = config?.voiceCompose?.maxRecordingMs;
|
|
3494
3528
|
const [isRecording, setIsRecording] = useState6(false);
|
|
3495
3529
|
const { setContext } = useChatUserContext();
|
|
3496
3530
|
const [recordingDuration, setRecordingDuration] = useState6(0);
|
|
3497
3531
|
const [uploadProgress, setUploadProgress] = useState6(/* @__PURE__ */ new Map());
|
|
3498
|
-
const [isVoiceComposerOpen, setIsVoiceComposerOpen] = useState6(
|
|
3532
|
+
const [isVoiceComposerOpen, setIsVoiceComposerOpen] = useState6(
|
|
3533
|
+
() => voiceComposeEnabled && voiceDefaultMode === "voice"
|
|
3534
|
+
);
|
|
3499
3535
|
const [voiceState, setVoiceState] = useState6("idle");
|
|
3500
3536
|
const [voiceDraft, setVoiceDraft] = useState6(null);
|
|
3501
3537
|
const [voiceTranscript, setVoiceTranscript] = useState6(clearVoiceTranscript);
|
|
3502
3538
|
const [voiceDurationMs, setVoiceDurationMs] = useState6(0);
|
|
3503
3539
|
const [voiceAudioLevel, setVoiceAudioLevel] = useState6(0);
|
|
3504
3540
|
const [voiceCountdownMs, setVoiceCountdownMs] = useState6(0);
|
|
3541
|
+
const [isVoiceAutoSendActive, setIsVoiceAutoSendActive] = useState6(false);
|
|
3505
3542
|
const [voiceError, setVoiceError] = useState6(null);
|
|
3506
3543
|
const textareaRef = useRef5(null);
|
|
3507
3544
|
const fileInputRef = useRef5(null);
|
|
@@ -3510,12 +3547,6 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3510
3547
|
const recordingInterval = useRef5(null);
|
|
3511
3548
|
const mediaStreamRef = useRef5(null);
|
|
3512
3549
|
const voiceProviderRef = useRef5(null);
|
|
3513
|
-
const voiceComposeEnabled = config?.voiceCompose?.enabled === true;
|
|
3514
|
-
const voiceAutoSendDelayMs = config?.voiceCompose?.autoSendDelayMs ?? 5e3;
|
|
3515
|
-
const voicePersistComposer = config?.voiceCompose?.persistComposer ?? true;
|
|
3516
|
-
const voiceShowTranscriptPreview = config?.voiceCompose?.showTranscriptPreview ?? true;
|
|
3517
|
-
const voiceTranscriptMode = config?.voiceCompose?.transcriptMode ?? "final-only";
|
|
3518
|
-
const voiceMaxRecordingMs = config?.voiceCompose?.maxRecordingMs;
|
|
3519
3550
|
useEffect9(() => {
|
|
3520
3551
|
return () => {
|
|
3521
3552
|
if (mediaStreamRef.current) {
|
|
@@ -3545,7 +3576,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3545
3576
|
};
|
|
3546
3577
|
const processFile = async (file) => {
|
|
3547
3578
|
if (file.size > maxFileSize) {
|
|
3548
|
-
alert(`
|
|
3579
|
+
alert(`File too large. Max allowed: ${Math.round(maxFileSize / 1024 / 1024)}MB`);
|
|
3549
3580
|
return null;
|
|
3550
3581
|
}
|
|
3551
3582
|
const fileId = `${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
@@ -3604,7 +3635,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3604
3635
|
newMap.delete(fileId);
|
|
3605
3636
|
return newMap;
|
|
3606
3637
|
});
|
|
3607
|
-
alert("
|
|
3638
|
+
alert("Failed to process file");
|
|
3608
3639
|
return null;
|
|
3609
3640
|
}
|
|
3610
3641
|
};
|
|
@@ -3679,7 +3710,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3679
3710
|
}, 1e3);
|
|
3680
3711
|
} catch (error) {
|
|
3681
3712
|
console.error("Error starting recording:", error);
|
|
3682
|
-
alert(
|
|
3713
|
+
alert(config?.labels?.voicePermissionDenied || "Microphone access was denied.");
|
|
3683
3714
|
}
|
|
3684
3715
|
};
|
|
3685
3716
|
const stopRecording = () => {
|
|
@@ -3711,6 +3742,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3711
3742
|
setVoiceDurationMs(0);
|
|
3712
3743
|
setVoiceAudioLevel(0);
|
|
3713
3744
|
setVoiceCountdownMs(0);
|
|
3745
|
+
setIsVoiceAutoSendActive(false);
|
|
3714
3746
|
setVoiceError(null);
|
|
3715
3747
|
}, []);
|
|
3716
3748
|
const ensureVoiceProvider = useCallback3(async () => {
|
|
@@ -3729,6 +3761,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3729
3761
|
setVoiceDurationMs(segment.attachment.durationMs ?? 0);
|
|
3730
3762
|
setVoiceAudioLevel(0);
|
|
3731
3763
|
setVoiceCountdownMs(voiceAutoSendDelayMs);
|
|
3764
|
+
setIsVoiceAutoSendActive(voiceAutoSendDelayMs > 0);
|
|
3732
3765
|
setVoiceError(null);
|
|
3733
3766
|
setVoiceState("review");
|
|
3734
3767
|
},
|
|
@@ -3736,6 +3769,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3736
3769
|
setVoiceError(resolveVoiceErrorMessage(error, config));
|
|
3737
3770
|
setVoiceAudioLevel(0);
|
|
3738
3771
|
setVoiceCountdownMs(0);
|
|
3772
|
+
setIsVoiceAutoSendActive(false);
|
|
3739
3773
|
setVoiceState("error");
|
|
3740
3774
|
}
|
|
3741
3775
|
}, {
|
|
@@ -3768,6 +3802,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3768
3802
|
setVoiceTranscript(clearVoiceTranscript());
|
|
3769
3803
|
setVoiceAudioLevel(0);
|
|
3770
3804
|
setVoiceDurationMs(0);
|
|
3805
|
+
setIsVoiceAutoSendActive(false);
|
|
3771
3806
|
try {
|
|
3772
3807
|
const provider = await ensureVoiceProvider();
|
|
3773
3808
|
await provider.start();
|
|
@@ -3805,6 +3840,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3805
3840
|
}
|
|
3806
3841
|
setVoiceState("sending");
|
|
3807
3842
|
setVoiceCountdownMs(0);
|
|
3843
|
+
setIsVoiceAutoSendActive(false);
|
|
3808
3844
|
onSubmit("", [...attachments, voiceDraft.attachment]);
|
|
3809
3845
|
onChange("");
|
|
3810
3846
|
onAttachmentsChange([]);
|
|
@@ -3819,12 +3855,12 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3819
3855
|
onAttachmentsChange,
|
|
3820
3856
|
finalizeVoiceComposerAfterSend
|
|
3821
3857
|
]);
|
|
3822
|
-
const
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
}, [
|
|
3858
|
+
const cancelVoiceAutoSend = useCallback3(() => {
|
|
3859
|
+
setVoiceCountdownMs(0);
|
|
3860
|
+
setIsVoiceAutoSendActive(false);
|
|
3861
|
+
}, []);
|
|
3826
3862
|
useEffect9(() => {
|
|
3827
|
-
if (voiceState !== "review" || !voiceDraft || voiceAutoSendDelayMs <= 0) {
|
|
3863
|
+
if (voiceState !== "review" || !voiceDraft || voiceAutoSendDelayMs <= 0 || !isVoiceAutoSendActive) {
|
|
3828
3864
|
return;
|
|
3829
3865
|
}
|
|
3830
3866
|
const startedAt = Date.now();
|
|
@@ -3838,7 +3874,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3838
3874
|
}
|
|
3839
3875
|
}, 100);
|
|
3840
3876
|
return () => clearInterval(timer);
|
|
3841
|
-
}, [voiceState, voiceDraft, voiceAutoSendDelayMs, sendVoiceDraft]);
|
|
3877
|
+
}, [voiceState, voiceDraft, voiceAutoSendDelayMs, isVoiceAutoSendActive, sendVoiceDraft]);
|
|
3842
3878
|
const removeAttachment = (index) => {
|
|
3843
3879
|
const newAttachments = attachments.filter((_, i) => i !== index);
|
|
3844
3880
|
onAttachmentsChange(newAttachments);
|
|
@@ -3887,10 +3923,12 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3887
3923
|
transcript: voiceTranscript,
|
|
3888
3924
|
transcriptMode: voiceTranscriptMode,
|
|
3889
3925
|
showTranscriptPreview: voiceShowTranscriptPreview,
|
|
3926
|
+
attachment: voiceDraft?.attachment ?? null,
|
|
3890
3927
|
durationMs: voiceDurationMs,
|
|
3891
3928
|
audioLevel: voiceAudioLevel,
|
|
3892
3929
|
countdownMs: voiceCountdownMs,
|
|
3893
3930
|
autoSendDelayMs: voiceAutoSendDelayMs,
|
|
3931
|
+
isAutoSendActive: isVoiceAutoSendActive,
|
|
3894
3932
|
errorMessage: voiceError,
|
|
3895
3933
|
disabled: disabled || isGenerating,
|
|
3896
3934
|
labels: config?.labels,
|
|
@@ -3900,13 +3938,16 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3900
3938
|
onStop: () => {
|
|
3901
3939
|
void stopVoiceCapture();
|
|
3902
3940
|
},
|
|
3903
|
-
|
|
3941
|
+
onCancelAutoSend: () => {
|
|
3942
|
+
cancelVoiceAutoSend();
|
|
3943
|
+
},
|
|
3944
|
+
onDiscard: () => {
|
|
3904
3945
|
void cancelVoiceCapture();
|
|
3905
3946
|
},
|
|
3906
|
-
onSendNow: sendVoiceDraft,
|
|
3907
3947
|
onRecordAgain: () => {
|
|
3908
|
-
void
|
|
3948
|
+
void startVoiceCapture();
|
|
3909
3949
|
},
|
|
3950
|
+
onSendNow: sendVoiceDraft,
|
|
3910
3951
|
onExit: () => {
|
|
3911
3952
|
void closeVoiceComposer();
|
|
3912
3953
|
}
|
|
@@ -3918,7 +3959,7 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
3918
3959
|
onDrop: handleDrop,
|
|
3919
3960
|
onDragOver: handleDragOver,
|
|
3920
3961
|
children: [
|
|
3921
|
-
enableFileUpload && canAddMoreAttachments && /* @__PURE__ */ jsxs12(
|
|
3962
|
+
enableFileUpload && canAddMoreAttachments && /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
3922
3963
|
/* @__PURE__ */ jsx22(
|
|
3923
3964
|
"input",
|
|
3924
3965
|
{
|
|
@@ -4021,14 +4062,14 @@ var ChatInput = memo2(function ChatInput2({
|
|
|
4021
4062
|
) }),
|
|
4022
4063
|
/* @__PURE__ */ jsxs12("div", { className: "text-[10px] text-muted-foreground text-center", children: [
|
|
4023
4064
|
window.innerWidth > 768 ? config?.labels?.inputHelpText : "",
|
|
4024
|
-
attachments.length > 0 && /* @__PURE__ */ jsxs12(
|
|
4065
|
+
attachments.length > 0 && /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
4025
4066
|
" \u2022 ",
|
|
4026
4067
|
attachments.length,
|
|
4027
4068
|
"/",
|
|
4028
4069
|
maxAttachments,
|
|
4029
4070
|
" anexos"
|
|
4030
4071
|
] }),
|
|
4031
|
-
config?.labels?.footerLabel && /* @__PURE__ */ jsxs12(
|
|
4072
|
+
config?.labels?.footerLabel && /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
4032
4073
|
" \u2022 ",
|
|
4033
4074
|
config.labels.footerLabel
|
|
4034
4075
|
] })
|
|
@@ -4118,7 +4159,7 @@ import {
|
|
|
4118
4159
|
FileText as FileText2,
|
|
4119
4160
|
Brain as Brain2,
|
|
4120
4161
|
Plus as Plus3,
|
|
4121
|
-
Trash2 as
|
|
4162
|
+
Trash2 as Trash24,
|
|
4122
4163
|
Target,
|
|
4123
4164
|
Lightbulb,
|
|
4124
4165
|
Info,
|
|
@@ -4128,7 +4169,7 @@ import {
|
|
|
4128
4169
|
Check as Check3,
|
|
4129
4170
|
X as X4
|
|
4130
4171
|
} from "lucide-react";
|
|
4131
|
-
import { Fragment as
|
|
4172
|
+
import { Fragment as Fragment5, jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
4132
4173
|
var getInitials2 = (name, email) => {
|
|
4133
4174
|
if (name) {
|
|
4134
4175
|
return name.split(" ").map((n) => n[0]).slice(0, 2).join("").toUpperCase();
|
|
@@ -4321,7 +4362,7 @@ var UserProfile = ({
|
|
|
4321
4362
|
] })
|
|
4322
4363
|
] })
|
|
4323
4364
|
] }),
|
|
4324
|
-
normalizedFields.length > 0 && /* @__PURE__ */ jsxs14(
|
|
4365
|
+
normalizedFields.length > 0 && /* @__PURE__ */ jsxs14(Fragment5, { children: [
|
|
4325
4366
|
/* @__PURE__ */ jsx24(Separator, {}),
|
|
4326
4367
|
/* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
|
|
4327
4368
|
/* @__PURE__ */ jsx24("h3", { className: "text-sm font-medium text-muted-foreground uppercase tracking-wider", children: labels.customFields }),
|
|
@@ -4465,7 +4506,7 @@ var UserProfile = ({
|
|
|
4465
4506
|
size: "icon",
|
|
4466
4507
|
className: "h-7 w-7",
|
|
4467
4508
|
onClick: () => onDeleteMemory(memory.id),
|
|
4468
|
-
children: /* @__PURE__ */ jsx24(
|
|
4509
|
+
children: /* @__PURE__ */ jsx24(Trash24, { className: "h-3.5 w-3.5 text-destructive" })
|
|
4469
4510
|
}
|
|
4470
4511
|
)
|
|
4471
4512
|
] })
|
|
@@ -5051,7 +5092,7 @@ import {
|
|
|
5051
5092
|
MessageSquare as MessageSquare2,
|
|
5052
5093
|
MoreVertical as MoreVertical2,
|
|
5053
5094
|
Edit2 as Edit22,
|
|
5054
|
-
Trash2 as
|
|
5095
|
+
Trash2 as Trash25,
|
|
5055
5096
|
Archive as Archive2,
|
|
5056
5097
|
Search as Search2,
|
|
5057
5098
|
Filter as Filter2,
|
|
@@ -5060,7 +5101,7 @@ import {
|
|
|
5060
5101
|
X as X5,
|
|
5061
5102
|
Check as Check4
|
|
5062
5103
|
} from "lucide-react";
|
|
5063
|
-
import { Fragment as
|
|
5104
|
+
import { Fragment as Fragment6, jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
5064
5105
|
var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onArchive }) => {
|
|
5065
5106
|
const [isEditing, setIsEditing] = useState9(false);
|
|
5066
5107
|
const [editTitle, setEditTitle] = useState9(thread.title);
|
|
@@ -5105,7 +5146,7 @@ var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onAr
|
|
|
5105
5146
|
),
|
|
5106
5147
|
/* @__PURE__ */ jsx26(Button, { size: "sm", variant: "ghost", onClick: handleSaveEdit, children: /* @__PURE__ */ jsx26(Check4, { className: "h-3 w-3" }) }),
|
|
5107
5148
|
/* @__PURE__ */ jsx26(Button, { size: "sm", variant: "ghost", onClick: handleCancelEdit, children: /* @__PURE__ */ jsx26(X5, { className: "h-3 w-3" }) })
|
|
5108
|
-
] }) : /* @__PURE__ */ jsxs16(
|
|
5149
|
+
] }) : /* @__PURE__ */ jsxs16(Fragment6, { children: [
|
|
5109
5150
|
/* @__PURE__ */ jsx26("h4", { className: "font-medium text-sm truncate mb-1", children: thread.title }),
|
|
5110
5151
|
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
5111
5152
|
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-1", children: [
|
|
@@ -5118,7 +5159,7 @@ var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onAr
|
|
|
5118
5159
|
/* @__PURE__ */ jsx26(Calendar2, { className: "h-3 w-3" }),
|
|
5119
5160
|
formatDate(thread.updatedAt, config?.labels)
|
|
5120
5161
|
] }),
|
|
5121
|
-
thread.isArchived && /* @__PURE__ */ jsxs16(
|
|
5162
|
+
thread.isArchived && /* @__PURE__ */ jsxs16(Fragment6, { children: [
|
|
5122
5163
|
/* @__PURE__ */ jsx26(Separator, { orientation: "vertical", className: "h-3" }),
|
|
5123
5164
|
/* @__PURE__ */ jsxs16(Badge, { variant: "secondary", className: "text-xs", children: [
|
|
5124
5165
|
/* @__PURE__ */ jsx26(Archive2, { className: "h-2 w-2 mr-1" }),
|
|
@@ -5140,7 +5181,7 @@ var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onAr
|
|
|
5140
5181
|
] }),
|
|
5141
5182
|
/* @__PURE__ */ jsx26(DropdownMenuSeparator, {}),
|
|
5142
5183
|
/* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: onDelete, className: "text-destructive", children: [
|
|
5143
|
-
/* @__PURE__ */ jsx26(
|
|
5184
|
+
/* @__PURE__ */ jsx26(Trash25, { className: "h-4 w-4 mr-2" }),
|
|
5144
5185
|
config?.labels?.deleteThread || "Delete"
|
|
5145
5186
|
] })
|
|
5146
5187
|
] })
|