@copilotz/chat-ui 0.1.35 → 0.1.37

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 CHANGED
@@ -3274,14 +3274,14 @@ var VoiceComposer = ({
3274
3274
  }) => {
3275
3275
  const transcriptText = resolveTranscriptText(transcript, transcriptMode);
3276
3276
  const countdownSeconds = Math.max(1, Math.ceil(countdownMs / 1e3));
3277
- const countdownValue = autoSendDelayMs > 0 ? Math.min(100, Math.max(0, (autoSendDelayMs - countdownMs) / autoSendDelayMs * 100)) : 100;
3278
3277
  const isBusy = state === "preparing" || state === "finishing" || state === "sending";
3279
3278
  const isCapturing = state === "waiting_for_speech" || state === "listening";
3280
3279
  const hasDraft = Boolean(attachment);
3281
3280
  const isDraftLayout = hasDraft;
3282
3281
  const isArmedDraft = isDraftLayout && reviewMode === "armed" && (state === "waiting_for_speech" || state === "listening");
3282
+ const draftStatusLabel = state === "listening" ? labels?.voiceListening || "Listening..." : state === "waiting_for_speech" ? labels?.voiceWaiting || "Waiting for speech..." : state === "finishing" ? labels?.voiceFinishing || "Finishing capture..." : state === "sending" ? labels?.voiceSending || "Sending..." : labels?.voiceReview || "Ready to send";
3283
3283
  const levelValue = isCapturing || state === "preparing" || state === "finishing" ? Math.max(8, Math.round(audioLevel * 100)) : 0;
3284
- const headerLabel = hasDraft && state !== "sending" && state !== "error" ? labels?.voiceReview || "Ready to send" : state === "error" ? labels?.voiceCaptureError || "Unable to capture audio." : resolveStateLabel(state, labels, errorMessage);
3284
+ const headerLabel = hasDraft && state !== "sending" && state !== "error" ? draftStatusLabel : state === "error" ? labels?.voiceCaptureError || "Unable to capture audio." : resolveStateLabel(state, labels, errorMessage);
3285
3285
  const reviewHelperText = isArmedDraft ? labels?.voiceReviewArmedHint || "Speak to add more before it sends." : labels?.voiceReviewPausedHint || labels?.voiceRecordAgain || "Tap the mic to continue this message.";
3286
3286
  const orbIsListening = state === "listening";
3287
3287
  const orbCanStop = !isDraftLayout && (state === "waiting_for_speech" || state === "listening");
@@ -3297,11 +3297,11 @@ var VoiceComposer = ({
3297
3297
  }
3298
3298
  onRecordAgain();
3299
3299
  };
3300
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "w-full max-w-3xl rounded-xl border bg-background p-3 shadow-sm sm:p-4 md:min-w-3xl", children: [
3300
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "w-full max-w-3xl rounded-2xl border bg-background p-3 shadow-sm sm:p-4 md:min-w-3xl", children: [
3301
3301
  /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center justify-between gap-2 sm:gap-3", children: [
3302
3302
  /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [
3303
3303
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "outline", children: labels?.voiceTitle || "Voice" }),
3304
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "truncate text-xs sm:text-sm text-muted-foreground", children: headerLabel })
3304
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "truncate rounded-full bg-muted px-2.5 py-1 text-[11px] sm:text-xs text-muted-foreground", children: headerLabel })
3305
3305
  ] }),
3306
3306
  /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
3307
3307
  Button,
@@ -3341,11 +3341,8 @@ var VoiceComposer = ({
3341
3341
  ] }),
3342
3342
  showTranscriptPreview && transcriptMode !== "none" && transcriptText && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-full rounded-lg border bg-background px-3 py-2 text-left text-sm", children: transcriptText })
3343
3343
  ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-3 rounded-xl border bg-muted/20 p-3 sm:p-4", children: [
3344
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-start justify-between gap-2", children: [
3345
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "min-w-0", children: [
3346
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-sm font-medium text-foreground", children: labels?.voiceReview || "Ready to send" }),
3347
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-xs text-muted-foreground", children: formatDuration(durationMs) })
3348
- ] }),
3344
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center justify-between gap-2 text-xs text-muted-foreground", children: [
3345
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: formatDuration(durationMs) }),
3349
3346
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3350
3347
  Button,
3351
3348
  {
@@ -3361,39 +3358,39 @@ var VoiceComposer = ({
3361
3358
  }
3362
3359
  )
3363
3360
  ] }),
3364
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-4 flex flex-col items-center gap-3 text-center", children: [
3361
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-4 flex flex-col items-center gap-4 text-center", children: [
3365
3362
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3366
3363
  Button,
3367
3364
  {
3368
3365
  type: "button",
3369
3366
  size: "icon",
3370
3367
  variant: orbCanStop ? "destructive" : "outline",
3371
- className: `h-16 w-16 rounded-full sm:h-20 sm:w-20 ${orbIsListening ? "border-red-500 bg-red-500 text-white hover:bg-red-600" : isArmedDraft ? "border-red-200 bg-red-50 text-red-600 shadow-[0_0_0_10px_rgba(239,68,68,0.08)] hover:bg-red-100 hover:text-red-700" : "border-red-200 bg-red-50 text-red-600 hover:bg-red-100 hover:text-red-700"}`,
3368
+ className: `h-20 w-20 rounded-full sm:h-24 sm:w-24 ${orbIsListening ? "border-red-500 bg-red-500 text-white hover:bg-red-600" : isArmedDraft ? "border-red-200 bg-red-50 text-red-600 shadow-[0_0_0_10px_rgba(239,68,68,0.08)] hover:bg-red-100 hover:text-red-700" : "border-red-200 bg-red-50 text-red-600 hover:bg-red-100 hover:text-red-700"}`,
3372
3369
  onClick: handleReviewOrbClick,
3373
3370
  disabled: disabled || orbIsReviewBusy,
3374
3371
  children: orbIsReviewBusy ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Loader2, { className: "h-7 w-7 animate-spin" }) : orbIsListening ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Square, { className: "h-7 w-7" }) : isArmedDraft ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Mic, { className: "h-7 w-7 animate-pulse" }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Mic, { className: "h-7 w-7" })
3375
3372
  }
3376
3373
  ),
3377
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "w-full max-w-sm space-y-2", children: [
3378
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Progress, { value: levelValue, className: "h-2" }),
3379
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
3380
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: formatDuration(durationMs) }),
3381
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "max-w-[15rem] text-right", children: reviewHelperText })
3382
- ] })
3374
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "max-w-sm space-y-1 px-2", children: [
3375
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-sm text-foreground", children: reviewHelperText }),
3376
+ isCapturing && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mx-auto h-1.5 w-32 overflow-hidden rounded-full bg-red-100", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3377
+ "div",
3378
+ {
3379
+ className: "h-full rounded-full bg-red-500 transition-[width] duration-150",
3380
+ style: { width: `${levelValue}%` }
3381
+ }
3382
+ ) })
3383
3383
  ] })
3384
3384
  ] }),
3385
- attachment && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-3 rounded-lg bg-background p-2", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("audio", { controls: true, preload: "metadata", className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("source", { src: attachment.dataUrl, type: attachment.mimeType }) }) }),
3385
+ attachment && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-4 rounded-lg border bg-background/90 p-2 shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("audio", { controls: true, preload: "metadata", className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("source", { src: attachment.dataUrl, type: attachment.mimeType }) }) }),
3386
3386
  showTranscriptPreview && transcriptMode !== "none" && transcriptText && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-3 rounded-lg border bg-background px-3 py-2 text-left text-sm", children: transcriptText }),
3387
- isAutoSendActive && autoSendDelayMs > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-3 space-y-2", children: [
3388
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Progress, { value: countdownValue, className: "h-2" }),
3389
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-center text-xs text-muted-foreground", children: interpolateSeconds(labels?.voiceAutoSendIn, countdownSeconds) })
3390
- ] }),
3391
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-3 flex items-center justify-end gap-2", children: [
3392
- isAutoSendActive && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { type: "button", variant: "ghost", size: "sm", onClick: onCancelAutoSend, disabled, children: [
3387
+ isAutoSendActive && autoSendDelayMs > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-3 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "inline-flex items-center rounded-full border bg-background px-3 py-1 text-xs text-muted-foreground", children: interpolateSeconds(labels?.voiceAutoSendIn, countdownSeconds) }) }),
3388
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-4 grid grid-cols-1 gap-2 sm:flex sm:items-center sm:justify-end", children: [
3389
+ isAutoSendActive && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { type: "button", variant: "ghost", size: "sm", onClick: onCancelAutoSend, disabled, className: "w-full sm:w-auto", children: [
3393
3390
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.X, { className: "h-4 w-4" }),
3394
3391
  labels?.voiceCancel || "Cancel"
3395
3392
  ] }),
3396
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { type: "button", size: "sm", onClick: onSendNow, disabled, children: [
3393
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { type: "button", size: "sm", onClick: onSendNow, disabled, className: "w-full sm:w-auto", children: [
3397
3394
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Send, { className: "h-4 w-4" }),
3398
3395
  labels?.voiceSendNow || "Send now"
3399
3396
  ] })