@fluencypassdevs/cycle 1.9.3 → 1.9.7
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/{chunk-KUJHXRWG.js → chunk-27PO7X4G.js} +45 -14
- package/dist/chunk-27PO7X4G.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/layout/container.d.ts +1 -1
- package/dist/ui/badge.d.ts +2 -2
- package/dist/ui/button.d.ts +2 -2
- package/dist/ui/checkbox.d.ts +1 -1
- package/dist/ui/circular-progress.d.ts +1 -1
- package/dist/ui/empty.d.ts +1 -1
- package/dist/ui/fab.d.ts +1 -1
- package/dist/ui/file-card.d.ts +1 -1
- package/dist/ui/like-dislike.d.ts +1 -1
- package/dist/ui/message-bar.js +1 -1
- package/dist/ui/progress-dot.d.ts +2 -2
- package/dist/ui/progress-stage.d.ts +1 -1
- package/dist/ui/progress.d.ts +1 -1
- package/dist/ui/radio-group.d.ts +1 -1
- package/dist/ui/slider.d.ts +1 -1
- package/dist/ui/switch.d.ts +1 -1
- package/dist/ui/toggle.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunk-KUJHXRWG.js.map +0 -1
|
@@ -23,11 +23,23 @@ function MicButton({
|
|
|
23
23
|
className,
|
|
24
24
|
style
|
|
25
25
|
}) {
|
|
26
|
+
const buttonRef = React.useRef(null);
|
|
27
|
+
const hasPressFlow = !!onPointerDown;
|
|
28
|
+
React.useEffect(() => {
|
|
29
|
+
const btn = buttonRef.current;
|
|
30
|
+
if (!btn || !hasPressFlow) return;
|
|
31
|
+
const onTouchStart = (e) => {
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
};
|
|
34
|
+
btn.addEventListener("touchstart", onTouchStart, { passive: false });
|
|
35
|
+
return () => btn.removeEventListener("touchstart", onTouchStart);
|
|
36
|
+
}, [hasPressFlow]);
|
|
26
37
|
const sizeClass = variant === "large" ? "size-16" : size === "default" ? "size-10" : "size-8";
|
|
27
38
|
const radiusClass = variant === "large" ? "rounded-lg" : "rounded-md";
|
|
28
39
|
return /* @__PURE__ */ jsx(
|
|
29
40
|
"button",
|
|
30
41
|
{
|
|
42
|
+
ref: buttonRef,
|
|
31
43
|
type: "button",
|
|
32
44
|
onClick,
|
|
33
45
|
onPointerDown,
|
|
@@ -39,7 +51,10 @@ function MicButton({
|
|
|
39
51
|
"shrink-0 inline-flex items-center justify-center bg-primary text-primary-foreground theme-brand transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50",
|
|
40
52
|
sizeClass,
|
|
41
53
|
radiusClass,
|
|
42
|
-
pressed && "opacity-90
|
|
54
|
+
pressed && "opacity-90 select-none",
|
|
55
|
+
// touch-none aplicado sempre que ha press flow (nao so quando ja esta pressed),
|
|
56
|
+
// pra Android Chrome nao classificar o touchstart como scroll
|
|
57
|
+
(hasPressFlow || pressed) && "touch-none",
|
|
43
58
|
className
|
|
44
59
|
),
|
|
45
60
|
style,
|
|
@@ -326,15 +341,19 @@ function PressedRecordingOverlay({
|
|
|
326
341
|
}) {
|
|
327
342
|
const aboutToLock = deltaY <= -lockThreshold;
|
|
328
343
|
const aboutToCancel = deltaX <= -cancelThreshold;
|
|
329
|
-
const
|
|
330
|
-
const
|
|
344
|
+
const clampedX = Math.min(0, deltaX);
|
|
345
|
+
const clampedY = Math.min(0, deltaY);
|
|
346
|
+
const absX = Math.abs(clampedX);
|
|
347
|
+
const absY = Math.abs(clampedY);
|
|
348
|
+
const micTranslateX = absX >= absY ? clampedX : 0;
|
|
349
|
+
const micTranslateY = absY > absX ? clampedY : 0;
|
|
331
350
|
return /* @__PURE__ */ jsx(
|
|
332
351
|
"div",
|
|
333
352
|
{
|
|
334
353
|
"data-slot": "message-bar",
|
|
335
354
|
"data-state": "recording-pressed",
|
|
336
355
|
className: cn(
|
|
337
|
-
"flex items-center gap-2 p-2 sm:gap-3 sm:p-0",
|
|
356
|
+
"flex items-center gap-2 p-2 sm:gap-3 sm:p-0 touch-none select-none",
|
|
338
357
|
variant === "audio-only" && "justify-center"
|
|
339
358
|
),
|
|
340
359
|
children: variant === "audio-only" ? /* @__PURE__ */ jsxs("div", { className: "relative flex items-center gap-2", children: [
|
|
@@ -511,6 +530,7 @@ function MessageBar(_a) {
|
|
|
511
530
|
const pressDeltaRef = React.useRef({ x: 0, y: 0 });
|
|
512
531
|
const pressCancelThresholdRef = React.useRef(CANCEL_THRESHOLD_MAX);
|
|
513
532
|
const pressInfoRef = React.useRef({ startX: 0, startY: 0, startTime: 0, locked: false });
|
|
533
|
+
const isPressedRef = React.useRef(false);
|
|
514
534
|
const callbacksRef = React.useRef({ onStartRecording, onCancelRecording, onSendAudio });
|
|
515
535
|
React.useEffect(() => {
|
|
516
536
|
callbacksRef.current = { onStartRecording, onCancelRecording, onSendAudio };
|
|
@@ -519,6 +539,15 @@ function MessageBar(_a) {
|
|
|
519
539
|
pressDeltaRef.current = { x: dx, y: dy };
|
|
520
540
|
setPressDelta({ x: dx, y: dy });
|
|
521
541
|
};
|
|
542
|
+
React.useEffect(() => {
|
|
543
|
+
const onTouchMove = (e) => {
|
|
544
|
+
if (isPressedRef.current) {
|
|
545
|
+
e.preventDefault();
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
window.addEventListener("touchmove", onTouchMove, { passive: false });
|
|
549
|
+
return () => window.removeEventListener("touchmove", onTouchMove);
|
|
550
|
+
}, []);
|
|
522
551
|
const triggerHaptic = (ms = 50) => {
|
|
523
552
|
if (typeof navigator !== "undefined" && typeof navigator.vibrate === "function") {
|
|
524
553
|
try {
|
|
@@ -527,9 +556,14 @@ function MessageBar(_a) {
|
|
|
527
556
|
}
|
|
528
557
|
}
|
|
529
558
|
};
|
|
559
|
+
React.useEffect(() => {
|
|
560
|
+
isPressedRef.current = isPressed;
|
|
561
|
+
}, [isPressed]);
|
|
530
562
|
React.useEffect(() => {
|
|
531
563
|
if (!isPressed) return;
|
|
532
|
-
const
|
|
564
|
+
const prevHtmlTouchAction = document.documentElement.style.touchAction;
|
|
565
|
+
const prevBodyTouchAction = document.body.style.touchAction;
|
|
566
|
+
document.documentElement.style.touchAction = "none";
|
|
533
567
|
document.body.style.touchAction = "none";
|
|
534
568
|
const onMove = (e) => {
|
|
535
569
|
if (pressInfoRef.current.locked) return;
|
|
@@ -559,18 +593,15 @@ function MessageBar(_a) {
|
|
|
559
593
|
}
|
|
560
594
|
(_d = (_c = callbacksRef.current).onSendAudio) == null ? void 0 : _d.call(_c);
|
|
561
595
|
};
|
|
562
|
-
const onCancel = () => {
|
|
563
|
-
setIsPressed(false);
|
|
564
|
-
updateDelta(0, 0);
|
|
565
|
-
};
|
|
566
596
|
window.addEventListener("pointermove", onMove);
|
|
567
597
|
window.addEventListener("pointerup", onEnd);
|
|
568
|
-
window.addEventListener("pointercancel",
|
|
598
|
+
window.addEventListener("pointercancel", onEnd);
|
|
569
599
|
return () => {
|
|
570
600
|
window.removeEventListener("pointermove", onMove);
|
|
571
601
|
window.removeEventListener("pointerup", onEnd);
|
|
572
|
-
window.removeEventListener("pointercancel",
|
|
573
|
-
document.
|
|
602
|
+
window.removeEventListener("pointercancel", onEnd);
|
|
603
|
+
document.documentElement.style.touchAction = prevHtmlTouchAction;
|
|
604
|
+
document.body.style.touchAction = prevBodyTouchAction;
|
|
574
605
|
};
|
|
575
606
|
}, [isPressed]);
|
|
576
607
|
const handlePressStart = (e) => {
|
|
@@ -811,5 +842,5 @@ function MessageBar(_a) {
|
|
|
811
842
|
}
|
|
812
843
|
|
|
813
844
|
export { MessageBar };
|
|
814
|
-
//# sourceMappingURL=chunk-
|
|
815
|
-
//# sourceMappingURL=chunk-
|
|
845
|
+
//# sourceMappingURL=chunk-27PO7X4G.js.map
|
|
846
|
+
//# sourceMappingURL=chunk-27PO7X4G.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/message-bar.tsx"],"names":["_a","_b"],"mappings":"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","file":"chunk-27PO7X4G.js","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { Mic, Send, Trash2, Pause, Play, Lock, ChevronUp, ChevronLeft } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* ─── Types ───────────────────────────────────────────────────── */\n\n/**\n * Estados visuais do MessageBar:\n * - `default`: input texto + botao mic (estado inicial, sem texto digitado)\n * - `audio-only`: apenas botao mic centralizado (modo so audio)\n * - `active`: input texto com conteudo digitado + botao send\n * - `disabled`: input desabilitado\n * - `recording`: barra de gravacao (timer + waveform live + delete/pause/send)\n * - `paused`: gravacao pausada (timer + waveform + play/delete/mic/send)\n */\nexport type MessageBarState =\n | \"default\"\n | \"audio-only\"\n | \"active\"\n | \"disabled\"\n | \"recording\"\n | \"paused\"\n\nexport interface MessageBarProps extends Omit<React.ComponentProps<\"div\">, \"onChange\"> {\n /** Estado visual do componente (controlado pelo consumer) */\n state?: MessageBarState\n /** Valor do input de texto */\n value?: string\n /** Callback ao digitar */\n onChange?: (value: string) => void\n /** Callback ao enviar texto (Enter ou clique no botao send) */\n onSendText?: (text: string) => void\n /** Inicia gravacao (consumer chama MediaRecorder.start) */\n onStartRecording?: () => void\n /** Pausa gravacao */\n onPauseRecording?: () => void\n /** Retoma gravacao */\n onResumeRecording?: () => void\n /** Cancela/deleta gravacao */\n onCancelRecording?: () => void\n /** Envia o audio gravado */\n onSendAudio?: () => void\n /** Toggle play/pause do audio gravado durante o estado `paused` */\n onTogglePlay?: () => void\n /** Duracao da gravacao em segundos (controlado pelo consumer) */\n recordingDuration?: number\n /** Indica se esta tocando o audio (durante state=paused) */\n isPlaying?: boolean\n /**\n * MediaStream do microfone (durante state=recording). Quando fornecido,\n * o componente analisa em tempo real e renderiza as barras conforme a voz.\n * Sem stream → fallback para waveform decorativo.\n *\n * Como usar:\n * ```ts\n * const stream = await navigator.mediaDevices.getUserMedia({ audio: true })\n * const recorder = new MediaRecorder(stream)\n * // Passa o MESMO stream pro MessageBar:\n * <MessageBar state=\"recording\" recordingStream={stream} ... />\n * ```\n */\n recordingStream?: MediaStream | null\n /**\n * Progresso do playback do audio gravado (0-1), usado durante state=paused.\n * Quando fornecido, o waveform mostra barras tocadas/nao tocadas + dot verde\n * sincronizado. Sem isso, o waveform mostra todas as barras como nao tocadas.\n */\n playbackProgress?: number\n /**\n * Callback ao clicar/arrastar no waveform durante state=paused.\n * Recebe o novo progresso (0-1); o consumer deve setar currentTime do audio.\n */\n onSeekPlayback?: (progress: number) => void\n /** Placeholder do input */\n placeholder?: string\n}\n\n/* ─── Helpers ─────────────────────────────────────────────────── */\n\nfunction formatDuration(seconds: number): string {\n if (!Number.isFinite(seconds) || seconds < 0) return \"00:00\"\n const m = Math.floor(seconds / 60)\n const s = Math.floor(seconds % 60)\n return `${m.toString().padStart(2, \"0\")}:${s.toString().padStart(2, \"0\")}`\n}\n\n/* ─── Sub-componentes ─────────────────────────────────────────── */\n\n/** Botao mic vermelho coral (theme-brand) — usado em default, audio-only e durante press.\n * - `variant=\"large\"` aumenta para 64x64 (overlay durante press)\n * - `pressed` aplica scale-110 + opacity 90\n * - Aceita pointer events para suportar press-and-hold (mobile WhatsApp-style) */\nfunction MicButton({\n onClick,\n onPointerDown,\n onPointerMove,\n onPointerUp,\n onPointerCancel,\n size = \"default\",\n variant = \"default\",\n pressed = false,\n ariaLabel = \"Gravar audio\",\n className,\n style,\n}: {\n onClick?: () => void\n onPointerDown?: (e: React.PointerEvent<HTMLButtonElement>) => void\n onPointerMove?: (e: React.PointerEvent<HTMLButtonElement>) => void\n onPointerUp?: (e: React.PointerEvent<HTMLButtonElement>) => void\n onPointerCancel?: (e: React.PointerEvent<HTMLButtonElement>) => void\n size?: \"default\" | \"sm\"\n variant?: \"default\" | \"large\"\n pressed?: boolean\n ariaLabel?: string\n className?: string\n style?: React.CSSProperties\n}) {\n const buttonRef = React.useRef<HTMLButtonElement>(null)\n const hasPressFlow = !!onPointerDown\n\n /* touchstart non-passive — marca o gesto como NAO scroll desde o primeiro evento.\n * Critico pra Android Chrome (Blink): se o touchstart for passive (default no React),\n * o navegador classifica o gesto como \"potencialmente scroll\" e ignora preventDefault\n * posterior. Listener via addEventListener pra poder usar { passive: false }. */\n React.useEffect(() => {\n const btn = buttonRef.current\n if (!btn || !hasPressFlow) return\n const onTouchStart = (e: TouchEvent) => {\n e.preventDefault()\n }\n btn.addEventListener(\"touchstart\", onTouchStart, { passive: false })\n return () => btn.removeEventListener(\"touchstart\", onTouchStart)\n }, [hasPressFlow])\n\n const sizeClass =\n variant === \"large\" ? \"size-16\" : size === \"default\" ? \"size-10\" : \"size-8\"\n const radiusClass = variant === \"large\" ? \"rounded-lg\" : \"rounded-md\"\n return (\n <button\n ref={buttonRef}\n type=\"button\"\n onClick={onClick}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerCancel}\n aria-pressed={pressed || undefined}\n className={cn(\n \"shrink-0 inline-flex items-center justify-center bg-primary text-primary-foreground theme-brand transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50\",\n sizeClass,\n radiusClass,\n pressed && \"opacity-90 select-none\",\n // touch-none aplicado sempre que ha press flow (nao so quando ja esta pressed),\n // pra Android Chrome nao classificar o touchstart como scroll\n (hasPressFlow || pressed) && \"touch-none\",\n className\n )}\n style={style}\n aria-label={ariaLabel}\n >\n <Mic className={variant === \"large\" ? \"size-6\" : \"size-5\"} />\n </button>\n )\n}\n\n/** Botao send verde (theme-positive) */\nfunction SendButton({\n onClick,\n disabled,\n ariaLabel = \"Enviar\",\n}: {\n onClick?: () => void\n disabled?: boolean\n ariaLabel?: string\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n className=\"shrink-0 inline-flex items-center justify-center size-10 rounded-md bg-primary text-primary-foreground theme-positive transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:opacity-50 disabled:cursor-not-allowed\"\n aria-label={ariaLabel}\n >\n <Send className=\"size-5\" fill=\"currentColor\" strokeWidth={0} />\n </button>\n )\n}\n\n/** Botao icon-only neutral (trash, pause, play, mic durante paused) */\nfunction IconButton({\n onClick,\n icon: Icon,\n ariaLabel,\n filled = false,\n}: {\n onClick?: () => void\n icon: React.ComponentType<{ className?: string; fill?: string; strokeWidth?: number }>\n ariaLabel: string\n filled?: boolean\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"shrink-0 inline-flex items-center justify-center size-10 rounded-md text-neutral-foreground hover:bg-muted/50 transition-colors focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n aria-label={ariaLabel}\n >\n <Icon\n className=\"size-5\"\n {...(filled ? { fill: \"currentColor\", strokeWidth: 0 } : {})}\n />\n </button>\n )\n}\n\n/** Indicador de gravacao (red dot pulsando) */\nfunction RecordingIndicator() {\n return (\n <span className=\"shrink-0 relative inline-flex items-center justify-center size-3\" aria-label=\"Gravando\">\n <span className=\"absolute inset-0 rounded-full bg-primary theme-brand animate-ping opacity-75\" />\n <span className=\"relative size-2.5 rounded-full bg-primary theme-brand\" />\n </span>\n )\n}\n\n/** Helper: agrega N samples brutos em K barras (pico por chunk). Quando samples.length\n * < barCount, \"estica\" via lookup proporcional (cada barra pega o sample mais proximo). */\nfunction aggregateSamples(samples: number[], barCount: number): number[] {\n if (samples.length === 0 || barCount === 0) return new Array(barCount).fill(0)\n const result = new Array(barCount).fill(0)\n // Poucos samples: estica via lookup proporcional\n if (samples.length < barCount) {\n for (let i = 0; i < barCount; i++) {\n const idx = Math.floor((i / barCount) * samples.length)\n result[i] = samples[idx] ?? 0\n }\n return result\n }\n // Muitos samples: agrega pegando o pico (max) do chunk\n const chunkSize = samples.length / barCount\n for (let i = 0; i < barCount; i++) {\n const start = Math.floor(i * chunkSize)\n const end = Math.floor((i + 1) * chunkSize)\n let max = 0\n for (let j = start; j < end && j < samples.length; j++) {\n if (samples[j] > max) max = samples[j]\n }\n result[i] = max\n }\n return result\n}\n\n/** LiveWaveform — analise em tempo real do microfone via AnalyserNode.\n * Comportamento estilo WhatsApp:\n * - **Preenche toda a largura disponivel** (ResizeObserver detecta width e calcula limite max de barras)\n * - Cada bar = 2px wide, 2px gap (4px stride)\n * - **Comeca VAZIO**: primeiras barras entram pela DIREITA e empurram pra esquerda\n * - Depois que enche: rolling window (mais antiga sai esquerda, nova entra direita)\n * - Visualmente: container alinha barras com `justify-end` */\nfunction LiveWaveform({\n stream,\n samplesRef,\n}: {\n stream?: MediaStream | null\n /** Ref opcional: quando fornecido, acumula TODOS os samples brutos da gravacao (para usar no\n * state=paused via RecordedWaveform). O LiveWaveform mantem seu rolling window separado. */\n samplesRef?: React.MutableRefObject<number[]>\n}) {\n const STRIDE = 4 // 2px barra + 2px gap\n const MIN_BARS = 20\n const containerRef = React.useRef<HTMLDivElement>(null)\n const [bars, setBars] = React.useState<number[]>([])\n const barCountRef = React.useRef<number>(MIN_BARS)\n\n /* ResizeObserver: ajusta o LIMITE de barras (nao o buffer atual, exceto se shrink). */\n React.useEffect(() => {\n const el = containerRef.current\n if (!el) return\n\n const updateBarCount = (width: number) => {\n const count = Math.max(MIN_BARS, Math.floor(width / STRIDE))\n barCountRef.current = count\n // Se o buffer atual passou do novo limite (shrink), trunca mantendo as mais recentes\n setBars((prev) => (prev.length > count ? prev.slice(prev.length - count) : prev))\n }\n\n updateBarCount(el.clientWidth)\n\n const ro = new ResizeObserver((entries) => {\n const width = entries[0]?.contentRect.width ?? 0\n updateBarCount(width)\n })\n ro.observe(el)\n\n return () => ro.disconnect()\n }, [])\n\n /* Audio analysis setup (so depende do stream) */\n React.useEffect(() => {\n if (!stream) {\n setBars([])\n return\n }\n\n const AudioContextClass =\n window.AudioContext ||\n (window as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext\n const audioContext = new AudioContextClass()\n const source = audioContext.createMediaStreamSource(stream)\n const analyser = audioContext.createAnalyser()\n analyser.fftSize = 256\n source.connect(analyser)\n\n const dataArray = new Uint8Array(analyser.frequencyBinCount)\n let rafId: number | null = null\n let lastUpdate = 0\n let cancelled = false\n\n const tick = (timestamp: number) => {\n if (cancelled) return\n // Throttle ~30fps (33ms entre samples)\n if (timestamp - lastUpdate >= 33) {\n lastUpdate = timestamp\n analyser.getByteTimeDomainData(dataArray)\n\n // RMS — amplitude media percebida\n let sum = 0\n for (let i = 0; i < dataArray.length; i++) {\n const v = (dataArray[i] - 128) / 128\n sum += v * v\n }\n const rms = Math.sqrt(sum / dataArray.length)\n\n // Acumula no ref do parent (para reaproveitar no state=paused via RecordedWaveform)\n if (samplesRef) samplesRef.current.push(rms)\n\n setBars((prev) => {\n // Enquanto nao encheu: append no final (vai aparecer na direita por causa do justify-end)\n if (prev.length < barCountRef.current) return [...prev, rms]\n // Cheio: rolling window (descarta mais antiga, adiciona nova)\n return [...prev.slice(1), rms]\n })\n }\n rafId = requestAnimationFrame(tick)\n }\n\n rafId = requestAnimationFrame(tick)\n\n return () => {\n cancelled = true\n if (rafId !== null) cancelAnimationFrame(rafId)\n void audioContext.close()\n }\n }, [stream, samplesRef])\n\n return (\n <div\n ref={containerRef}\n className=\"flex-1 relative h-8 min-w-0 overflow-hidden\"\n >\n <div className=\"absolute inset-y-0 left-0 right-0 flex items-center justify-end gap-[2px]\">\n {bars.map((amp, i) => {\n // Voz humana tende a ter RMS baixo (~0.05-0.3). Boost x4 para visual.\n const normalized = Math.min(amp * 4, 1)\n const height = Math.max(2, Math.round(normalized * 32))\n return (\n <div\n key={i}\n className=\"w-[2px] shrink-0 rounded-full bg-neutral-foreground\"\n style={{ height: `${height}px` }}\n />\n )\n })}\n </div>\n </div>\n )\n}\n\n/** RecordedWaveform — waveform real do audio ja gravado (usado no state=paused).\n * - Recebe samples brutos acumulados durante o recording (via samplesRef)\n * - Agrega em N barras via ResizeObserver (largura dinamica, igual ChatAudio)\n * - Barras tocadas (i / N <= progress) em `bg-neutral-foreground`, demais em `bg-neutral-ring`\n * - Dot verde sincronizado com o progresso\n * - Click/drag-to-seek via pointer events */\nfunction RecordedWaveform({\n samples,\n progress = 0,\n onSeek,\n}: {\n samples: number[]\n progress?: number\n onSeek?: (progress: number) => void\n}) {\n const STRIDE = 4 // 2px barra + 2px gap\n const MIN_BARS = 20\n const containerRef = React.useRef<HTMLDivElement>(null)\n const [barCount, setBarCount] = React.useState<number>(MIN_BARS)\n\n React.useEffect(() => {\n const el = containerRef.current\n if (!el) return\n const updateBarCount = (width: number) => {\n const count = Math.max(MIN_BARS, Math.floor(width / STRIDE))\n setBarCount(count)\n }\n updateBarCount(el.clientWidth)\n const ro = new ResizeObserver((entries) => {\n updateBarCount(entries[0]?.contentRect.width ?? 0)\n })\n ro.observe(el)\n return () => ro.disconnect()\n }, [])\n\n // Agrega samples acumulados em barCount barras + normaliza para 0-1 (relativo ao pico)\n const bars = React.useMemo(() => {\n const aggregated = aggregateSamples(samples, barCount)\n const maxPeak = Math.max(...aggregated, 0.01)\n return aggregated.map((p) => p / maxPeak)\n }, [samples, barCount])\n\n const isDraggingRef = React.useRef(false)\n\n const seekFromClientX = React.useCallback(\n (clientX: number) => {\n const el = containerRef.current\n if (!el || !onSeek) return\n const rect = el.getBoundingClientRect()\n const x = clientX - rect.left\n const newProgress = Math.max(0, Math.min(x / rect.width, 1))\n onSeek(newProgress)\n },\n [onSeek]\n )\n\n const handlePointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!onSeek) return\n isDraggingRef.current = true\n e.currentTarget.setPointerCapture(e.pointerId)\n seekFromClientX(e.clientX)\n }\n const handlePointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!isDraggingRef.current) return\n seekFromClientX(e.clientX)\n }\n const handlePointerUp = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!isDraggingRef.current) return\n isDraggingRef.current = false\n e.currentTarget.releasePointerCapture(e.pointerId)\n }\n\n // Largura natural do layout das barras (px), usada para posicionar o dot em pixels\n const barsLayoutWidth = bars.length * STRIDE - 2\n\n return (\n <div\n ref={containerRef}\n className={cn(\n \"flex-1 relative h-8 min-w-0 overflow-hidden select-none\",\n onSeek && \"touch-none cursor-pointer\"\n )}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n role={onSeek ? \"slider\" : undefined}\n aria-label={onSeek ? \"Posicao do audio\" : undefined}\n aria-valuemin={onSeek ? 0 : undefined}\n aria-valuemax={onSeek ? 100 : undefined}\n aria-valuenow={onSeek ? Math.round(progress * 100) : undefined}\n >\n <div className=\"absolute inset-y-0 left-0 flex items-center gap-[2px]\">\n {bars.map((amp, i) => {\n const isPlayed = i / bars.length <= progress\n const height = Math.max(2, Math.round(amp * 32))\n return (\n <div\n key={i}\n className={cn(\n \"w-[2px] shrink-0 rounded-full\",\n isPlayed ? \"bg-neutral-foreground\" : \"bg-neutral-ring\"\n )}\n style={{ height: `${height}px` }}\n />\n )\n })}\n </div>\n {progress > 0 && (\n <div\n className=\"absolute top-1/2 z-10 -translate-y-1/2 -translate-x-1/2 size-3 rounded-full bg-[#098A5E] shadow-md pointer-events-none\"\n style={{ left: `${progress * barsLayoutWidth}px` }}\n aria-hidden=\"true\"\n />\n )}\n </div>\n )\n}\n\n/* ─── Press-to-record constants ───────────────────────────────── */\n\nconst LOCK_THRESHOLD = 120 // px arrastados pra cima → trava em modo hands-free\nconst CANCEL_THRESHOLD_RATIO = 0.65 // % da largura do MessageBar\nconst CANCEL_THRESHOLD_MIN = 140 // floor (telas pequenas — iPhone SE)\nconst CANCEL_THRESHOLD_MAX = 220 // ceiling (telas grandes — nao precisa atravessar a tela toda)\nconst MIN_DURATION = 1000 // ms — release antes disso cancela\n\n/** Calcula o threshold de cancel baseado na largura do container do MessageBar.\n * Sempre proporcional, com clamps min/max pra funcionar bem em telas pequenas (iPhone SE)\n * sem ficar trivialmente facil em telas grandes. */\nfunction computeCancelThreshold(containerWidth: number): number {\n return Math.min(\n CANCEL_THRESHOLD_MAX,\n Math.max(CANCEL_THRESHOLD_MIN, containerWidth * CANCEL_THRESHOLD_RATIO)\n )\n}\n\n/** PressedRecordingOverlay — UI exibida enquanto o usuario mantem o mic pressionado.\n * Inspirado no comportamento de gravacao de audio do WhatsApp.\n *\n * - Pill esquerda: live dot + timer + \"Deslize para cancelar\"\n * - Mic vermelho 64×64 (acompanha o cursor via translate clamped)\n * - Pill flutuante ACIMA do mic com lock + chevron up (indica \"deslize pra travar\")\n *\n * Variants:\n * - `default`: layout horizontal (cancel pill esquerda + mic direita)\n * - `audio-only`: layout horizontal centralizado (cancel pill curta + mic + timer pill) */\nfunction PressedRecordingOverlay({\n variant,\n duration,\n deltaX,\n deltaY,\n lockThreshold,\n cancelThreshold,\n}: {\n variant: \"default\" | \"audio-only\"\n duration: number\n deltaX: number\n deltaY: number\n lockThreshold: number\n cancelThreshold: number\n}) {\n const aboutToLock = deltaY <= -lockThreshold\n const aboutToCancel = deltaX <= -cancelThreshold\n // Clamp: so move pra cima/esquerda (delta negativo); ignora positivos\n const clampedX = Math.min(0, deltaX)\n const clampedY = Math.min(0, deltaY)\n // Restringe a UM EIXO POR VEZ — sem movimento diagonal.\n // Detecta direcao dominante (maior magnitude) e zera o outro eixo.\n const absX = Math.abs(clampedX)\n const absY = Math.abs(clampedY)\n const micTranslateX = absX >= absY ? clampedX : 0\n const micTranslateY = absY > absX ? clampedY : 0\n\n return (\n <div\n data-slot=\"message-bar\"\n data-state=\"recording-pressed\"\n className={cn(\n \"flex items-center gap-2 p-2 sm:gap-3 sm:p-0 touch-none select-none\",\n variant === \"audio-only\" && \"justify-center\"\n )}\n >\n {/* Layout: cancel-pill + mic (default) | cancel-pill + mic + timer-pill (audio-only) */}\n {variant === \"audio-only\" ? (\n <div className=\"relative flex items-center gap-2\">\n {/* Cancel pill (compact) */}\n <div\n className={cn(\n \"flex items-center gap-1 rounded-full bg-muted h-7 px-3 transition-colors\",\n aboutToCancel && \"bg-destructive/10\"\n )}\n >\n <ChevronLeft className=\"size-3 text-muted-foreground\" />\n <span\n className={cn(\n \"text-xs\",\n aboutToCancel ? \"text-destructive font-medium\" : \"text-muted-foreground\"\n )}\n >\n Cancelar\n </span>\n </div>\n\n {/* Mic + lock pill (anchor) */}\n <div className=\"relative\">\n {/* Lock pill ACIMA do mic */}\n <div\n className={cn(\n \"absolute left-1/2 -translate-x-1/2 bottom-full mb-2 flex flex-col items-center gap-3 rounded-t-full bg-muted h-20 w-8 py-3 transition-transform\",\n aboutToLock && \"scale-125 ring-2 ring-[#0EA460]\"\n )}\n aria-hidden=\"true\"\n >\n <Lock className={cn(\"size-3\", aboutToLock ? \"text-[#0EA460]\" : \"text-muted-foreground\")} />\n <ChevronUp className=\"size-3 text-muted-foreground animate-bounce\" />\n </div>\n\n <MicButton\n variant=\"large\"\n pressed\n ariaLabel=\"Gravando — arraste para cima para travar, para esquerda para cancelar\"\n className={cn(aboutToCancel && \"animate-shake\")}\n style={\n aboutToCancel\n ? undefined\n : { transform: `translate(${micTranslateX}px, ${micTranslateY}px) scale(1.1)` }\n }\n />\n </div>\n\n {/* Timer pill */}\n <div className=\"flex items-center gap-1 rounded-full bg-muted h-7 px-3\">\n <RecordingIndicator />\n <span className=\"text-sm tabular-nums text-neutral-foreground\">\n {formatDuration(duration)}\n </span>\n </div>\n </div>\n ) : (\n // Variant default: cancel pill flex-1 + mic\n <>\n <div\n className={cn(\n \"flex-1 flex items-center justify-between gap-2 rounded-xl bg-muted px-4 py-3 h-14\",\n aboutToCancel && \"bg-destructive/10\"\n )}\n >\n <div className=\"flex items-center gap-2\">\n <RecordingIndicator />\n <span className=\"text-sm tabular-nums text-neutral-foreground\">\n {formatDuration(duration)}\n </span>\n </div>\n <div\n className={cn(\n \"flex items-center gap-1 text-xs\",\n aboutToCancel ? \"text-destructive font-medium\" : \"text-muted-foreground\"\n )}\n >\n <ChevronLeft className=\"size-3\" />\n <span>Deslize para cancelar</span>\n </div>\n </div>\n\n {/* Mic + lock pill */}\n <div className=\"relative\">\n <div\n className={cn(\n \"absolute left-1/2 -translate-x-1/2 bottom-full mb-2 flex flex-col items-center gap-3 rounded-t-full bg-muted h-20 w-8 py-3 transition-transform\",\n aboutToLock && \"scale-125 ring-2 ring-[#0EA460]\"\n )}\n aria-hidden=\"true\"\n >\n <Lock className={cn(\"size-3\", aboutToLock ? \"text-[#0EA460]\" : \"text-muted-foreground\")} />\n <ChevronUp className=\"size-3 text-muted-foreground animate-bounce\" />\n </div>\n\n <MicButton\n variant=\"large\"\n pressed\n ariaLabel=\"Gravando — arraste para cima para travar, para esquerda para cancelar\"\n className={cn(aboutToCancel && \"animate-shake\")}\n style={\n aboutToCancel\n ? undefined\n : { transform: `translate(${micTranslateX}px, ${micTranslateY}px) scale(1.1)` }\n }\n />\n </div>\n </>\n )}\n </div>\n )\n}\n\n/* ─── Component principal ─────────────────────────────────────── */\n\nfunction MessageBar({\n state = \"default\",\n value = \"\",\n onChange,\n onSendText,\n onStartRecording,\n onPauseRecording,\n onResumeRecording,\n onCancelRecording,\n onSendAudio,\n onTogglePlay,\n recordingDuration = 0,\n isPlaying = false,\n recordingStream,\n playbackProgress = 0,\n onSeekPlayback,\n placeholder = \"Digite sua mensagem...\",\n className,\n ...props\n}: MessageBarProps) {\n // Acumula samples brutos do microfone durante recording — reaproveitado em paused via RecordedWaveform\n const samplesRef = React.useRef<number[]>([])\n\n // Reset dos samples quando inicia nova gravacao (transicao para recording a partir de outros estados)\n // Nao zera ao voltar de paused → recording (continua a mesma gravacao)\n const prevStateRef = React.useRef<MessageBarState>(state)\n // Lembra o ultimo base state (default/audio-only) pra escolher variant do overlay pressed\n const lastBaseStateRef = React.useRef<\"default\" | \"audio-only\">(\n state === \"audio-only\" ? \"audio-only\" : \"default\"\n )\n React.useEffect(() => {\n const prev = prevStateRef.current\n if (state === \"recording\" && prev !== \"paused\" && prev !== \"recording\") {\n samplesRef.current = []\n }\n if (state === \"default\" || state === \"audio-only\") {\n lastBaseStateRef.current = state\n }\n prevStateRef.current = state\n }, [state])\n\n /* ─── Press-to-record (WhatsApp-like, touch-only) ───────────── */\n const [isPressed, setIsPressed] = React.useState(false)\n const [pressDelta, setPressDelta] = React.useState({ x: 0, y: 0 })\n // Cancel threshold dinamico — calculado baseado na largura do container no pointerdown\n const [pressCancelThreshold, setPressCancelThreshold] = React.useState(CANCEL_THRESHOLD_MAX)\n const pressDeltaRef = React.useRef({ x: 0, y: 0 })\n const pressCancelThresholdRef = React.useRef(CANCEL_THRESHOLD_MAX)\n const pressInfoRef = React.useRef({ startX: 0, startY: 0, startTime: 0, locked: false })\n // Ref sincronizada com isPressed — usada por listener permanente de touchmove\n // (instalado no mount, mas so preventDefault quando esta pressionado)\n const isPressedRef = React.useRef(false)\n // Refs pros callbacks — handlers do window leem a versao mais recente sem precisar reinstalar listeners\n const callbacksRef = React.useRef({ onStartRecording, onCancelRecording, onSendAudio })\n React.useEffect(() => {\n callbacksRef.current = { onStartRecording, onCancelRecording, onSendAudio }\n })\n\n const updateDelta = (dx: number, dy: number) => {\n pressDeltaRef.current = { x: dx, y: dy }\n setPressDelta({ x: dx, y: dy })\n }\n\n /* Listener PERMANENTE de touchmove com preventDefault — instalado no mount.\n * Por que permanente: se instalar so quando isPressed=true (dentro do useEffect transient),\n * o iOS ja decidiu que o gesto e scroll/swipe ANTES do listener montar.\n * Solucao: listener sempre presente, com guard via isPressedRef.current. */\n React.useEffect(() => {\n const onTouchMove = (e: TouchEvent) => {\n if (isPressedRef.current) {\n e.preventDefault()\n }\n }\n window.addEventListener(\"touchmove\", onTouchMove, { passive: false })\n return () => window.removeEventListener(\"touchmove\", onTouchMove)\n }, [])\n\n const triggerHaptic = (ms = 50) => {\n if (typeof navigator !== \"undefined\" && typeof navigator.vibrate === \"function\") {\n try {\n navigator.vibrate(ms)\n } catch {\n /* ignore — alguns browsers podem rejeitar fora de user gesture */\n }\n }\n }\n\n // Listeners no window (sobrevivem a troca de DOM quando o overlay aparece e o MicButton original desmonta)\n // Sincroniza isPressedRef com isPressed pra o listener permanente de touchmove ler\n React.useEffect(() => {\n isPressedRef.current = isPressed\n }, [isPressed])\n\n // Listeners de pointer (transient): so existem durante o press flow\n React.useEffect(() => {\n if (!isPressed) return\n\n // touch-action: none em html + body bloqueia gestos nativos (backup, ja temos o\n // touchmove permanente com preventDefault)\n const prevHtmlTouchAction = document.documentElement.style.touchAction\n const prevBodyTouchAction = document.body.style.touchAction\n document.documentElement.style.touchAction = \"none\"\n document.body.style.touchAction = \"none\"\n\n const onMove = (e: PointerEvent) => {\n if (pressInfoRef.current.locked) return\n const { startX, startY } = pressInfoRef.current\n const dx = e.clientX - startX\n const dy = e.clientY - startY\n updateDelta(dx, dy)\n // Atinge lock threshold → trava em modo hands-free\n if (dy <= -LOCK_THRESHOLD) {\n pressInfoRef.current.locked = true\n triggerHaptic(50)\n setIsPressed(false)\n updateDelta(0, 0)\n }\n }\n\n const onEnd = () => {\n if (pressInfoRef.current.locked) return\n const { startTime } = pressInfoRef.current\n const elapsed = Date.now() - startTime\n const { x: dx } = pressDeltaRef.current\n\n setIsPressed(false)\n updateDelta(0, 0)\n\n if (dx <= -pressCancelThresholdRef.current || elapsed < MIN_DURATION) {\n triggerHaptic(50)\n callbacksRef.current.onCancelRecording?.()\n return\n }\n callbacksRef.current.onSendAudio?.()\n }\n\n window.addEventListener(\"pointermove\", onMove)\n window.addEventListener(\"pointerup\", onEnd)\n // pointercancel tratado como release (usa delta atual pra decidir cancel/send)\n window.addEventListener(\"pointercancel\", onEnd)\n return () => {\n window.removeEventListener(\"pointermove\", onMove)\n window.removeEventListener(\"pointerup\", onEnd)\n window.removeEventListener(\"pointercancel\", onEnd)\n document.documentElement.style.touchAction = prevHtmlTouchAction\n document.body.style.touchAction = prevBodyTouchAction\n }\n }, [isPressed])\n\n const handlePressStart = (e: React.PointerEvent<HTMLButtonElement>) => {\n // Desktop (mouse/pen): comportamento antigo de click — dispara onStartRecording, sai do flow press\n if (e.pointerType !== \"touch\") {\n onStartRecording?.()\n return\n }\n // Mede a largura do container do MessageBar pra calcular o cancel threshold adaptativo\n const wrapper = e.currentTarget.closest('[data-slot=\"message-bar\"]')\n const containerWidth =\n wrapper instanceof HTMLElement ? wrapper.clientWidth : window.innerWidth\n const threshold = computeCancelThreshold(containerWidth)\n pressCancelThresholdRef.current = threshold\n setPressCancelThreshold(threshold)\n\n pressInfoRef.current = {\n startX: e.clientX,\n startY: e.clientY,\n startTime: Date.now(),\n locked: false,\n }\n updateDelta(0, 0)\n setIsPressed(true)\n onStartRecording?.()\n }\n\n const pressHandlers = {\n onPointerDown: handlePressStart,\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey && value.trim()) {\n e.preventDefault()\n onSendText?.(value)\n }\n }\n\n /* ─── State: audio-only (so botao mic centralizado) ─────────── */\n if (state === \"audio-only\") {\n return (\n <div\n data-slot=\"message-bar\"\n data-state=\"audio-only\"\n className={cn(\"flex items-center justify-center p-2\", className)}\n {...props}\n >\n <MicButton {...pressHandlers} />\n </div>\n )\n }\n\n /* ─── State: recording + pressed (overlay WhatsApp-like) ────── */\n if (state === \"recording\" && isPressed) {\n return (\n <PressedRecordingOverlay\n variant={lastBaseStateRef.current}\n duration={recordingDuration}\n deltaX={pressDelta.x}\n deltaY={pressDelta.y}\n lockThreshold={LOCK_THRESHOLD}\n cancelThreshold={pressCancelThreshold}\n />\n )\n }\n\n /* ─── State: recording (hands-free, apos lock ou click no mic) ─ */\n if (state === \"recording\") {\n return (\n <div\n data-slot=\"message-bar\"\n data-state=\"recording\"\n className={cn(\n \"flex items-center gap-2 p-2 sm:gap-3 sm:p-0\",\n className\n )}\n {...props}\n >\n {/* Mobile: 2-row layout */}\n <div className=\"flex flex-col gap-2 w-full sm:contents\">\n {/* Top: trash + recording info + waveform (mobile) / inline (desktop) */}\n <div className=\"flex items-center gap-2 sm:contents\">\n {/* Trash — only inline at desktop, mobile shows in bottom row */}\n <div className=\"hidden sm:contents\">\n <IconButton\n onClick={onCancelRecording}\n icon={Trash2}\n ariaLabel=\"Cancelar gravacao\"\n />\n </div>\n\n {/* Recording bar — bg-muted container */}\n <div className=\"flex items-center gap-3 flex-1 rounded-2xl bg-muted px-4 py-3\">\n <RecordingIndicator />\n <span className=\"shrink-0 text-sm text-neutral-foreground tabular-nums\">\n {formatDuration(recordingDuration)}\n </span>\n <LiveWaveform stream={recordingStream} samplesRef={samplesRef} />\n {/* Pause inside the bar — only desktop */}\n <div className=\"hidden sm:contents\">\n <button\n type=\"button\"\n onClick={onPauseRecording}\n className=\"shrink-0 inline-flex items-center justify-center text-neutral-foreground hover:opacity-80 transition-opacity\"\n aria-label=\"Pausar gravacao\"\n >\n <Pause className=\"size-5\" fill=\"currentColor\" strokeWidth={0} />\n </button>\n </div>\n </div>\n\n {/* Send — only inline at desktop */}\n <div className=\"hidden sm:contents\">\n <SendButton onClick={onSendAudio} ariaLabel=\"Enviar audio\" />\n </div>\n </div>\n\n {/* Bottom row — mobile only */}\n <div className=\"flex items-center justify-between sm:hidden\">\n <IconButton\n onClick={onCancelRecording}\n icon={Trash2}\n ariaLabel=\"Cancelar gravacao\"\n />\n <button\n type=\"button\"\n onClick={onPauseRecording}\n className=\"shrink-0 inline-flex items-center justify-center size-10 text-neutral-foreground hover:opacity-80 transition-opacity\"\n aria-label=\"Pausar gravacao\"\n >\n <Pause className=\"size-5\" fill=\"currentColor\" strokeWidth={0} />\n </button>\n <SendButton onClick={onSendAudio} ariaLabel=\"Enviar audio\" />\n </div>\n </div>\n </div>\n )\n }\n\n /* ─── State: paused (com audio gravado) ──────────────────────── */\n if (state === \"paused\") {\n return (\n <div\n data-slot=\"message-bar\"\n data-state=\"paused\"\n className={cn(\n \"flex items-center gap-2 p-2 sm:gap-3 sm:p-0\",\n className\n )}\n {...props}\n >\n <div className=\"flex flex-col gap-2 w-full sm:contents\">\n <div className=\"flex items-center gap-2 sm:contents\">\n <div className=\"hidden sm:contents\">\n <IconButton\n onClick={onCancelRecording}\n icon={Trash2}\n ariaLabel=\"Cancelar gravacao\"\n />\n </div>\n\n <div className=\"flex items-center gap-3 flex-1 rounded-2xl bg-muted px-4 py-3\">\n <button\n type=\"button\"\n onClick={onTogglePlay}\n className=\"shrink-0 inline-flex items-center justify-center text-neutral-foreground hover:opacity-80 transition-opacity\"\n aria-label={isPlaying ? \"Pausar\" : \"Reproduzir\"}\n >\n {isPlaying ? (\n <Pause className=\"size-5\" fill=\"currentColor\" strokeWidth={0} />\n ) : (\n <Play className=\"size-5\" fill=\"currentColor\" strokeWidth={0} />\n )}\n </button>\n <span className=\"shrink-0 text-sm text-neutral-foreground tabular-nums\">\n {formatDuration(recordingDuration)}\n </span>\n <RecordedWaveform\n samples={samplesRef.current}\n progress={playbackProgress}\n onSeek={onSeekPlayback}\n />\n {/* Mic inline — only desktop */}\n <div className=\"hidden sm:contents\">\n <button\n type=\"button\"\n onClick={onResumeRecording}\n className=\"shrink-0 inline-flex items-center justify-center text-neutral-foreground hover:opacity-80 transition-opacity\"\n aria-label=\"Continuar gravacao\"\n >\n <Mic className=\"size-5\" />\n </button>\n </div>\n </div>\n\n <div className=\"hidden sm:contents\">\n <SendButton onClick={onSendAudio} ariaLabel=\"Enviar audio\" />\n </div>\n </div>\n\n {/* Bottom row — mobile only */}\n <div className=\"flex items-center justify-between sm:hidden\">\n <IconButton\n onClick={onCancelRecording}\n icon={Trash2}\n ariaLabel=\"Cancelar gravacao\"\n />\n <button\n type=\"button\"\n onClick={onResumeRecording}\n className=\"shrink-0 inline-flex items-center justify-center size-10 text-neutral-foreground hover:opacity-80 transition-opacity\"\n aria-label=\"Continuar gravacao\"\n >\n <Mic className=\"size-5\" />\n </button>\n <SendButton onClick={onSendAudio} ariaLabel=\"Enviar audio\" />\n </div>\n </div>\n </div>\n )\n }\n\n /* ─── States: default | active | disabled (input + button) ──── */\n const isDisabled = state === \"disabled\"\n const isActive = state === \"active\" || (state === \"default\" && value.trim().length > 0)\n\n return (\n <div\n data-slot=\"message-bar\"\n data-state={state}\n className={cn(\n \"flex items-center gap-2 rounded-2xl bg-muted p-2\",\n className\n )}\n {...props}\n >\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange?.(e.target.value)}\n onKeyDown={handleKeyDown}\n disabled={isDisabled}\n placeholder={placeholder}\n className={cn(\n \"flex-1 min-w-0 bg-transparent px-3 py-2 text-base text-neutral-foreground placeholder:text-neutral-muted-foreground outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\"\n )}\n aria-label=\"Mensagem\"\n />\n {isActive ? (\n <SendButton\n onClick={() => value.trim() && onSendText?.(value)}\n disabled={!value.trim()}\n />\n ) : (\n <MicButton {...pressHandlers} />\n )}\n </div>\n )\n}\n\nexport { MessageBar }\n"]}
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ export { Popover, PopoverAnchor, PopoverContent, PopoverDescription, PopoverHead
|
|
|
18
18
|
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './chunk-IGMII4BK.js';
|
|
19
19
|
export { ChatAudio, ChatMessage, chatMessageVariants } from './chunk-YMWRR7ET.js';
|
|
20
20
|
export { MessageRating } from './chunk-37C2K2NM.js';
|
|
21
|
-
export { MessageBar } from './chunk-
|
|
21
|
+
export { MessageBar } from './chunk-27PO7X4G.js';
|
|
22
22
|
export { ChatPanel } from './chunk-L32AMI4K.js';
|
|
23
23
|
export { ChatBubble, chatBubbleVariants } from './chunk-HZJRM5EK.js';
|
|
24
24
|
export { LikeDislike, likeDislikeVariants } from './chunk-F2XA2Z75.js';
|
|
@@ -13,7 +13,7 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
13
13
|
*/
|
|
14
14
|
declare const containerVariants: (props?: ({
|
|
15
15
|
size?: "default" | "prose" | "wide" | "full" | null | undefined;
|
|
16
|
-
padding?: "
|
|
16
|
+
padding?: "none" | "default" | null | undefined;
|
|
17
17
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
18
18
|
interface ContainerProps extends React.ComponentProps<"div">, VariantProps<typeof containerVariants> {
|
|
19
19
|
/** HTML element to render (default: div) */
|
package/dist/ui/badge.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ import * as React from 'react';
|
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
6
|
declare const badgeVariants: (props?: ({
|
|
7
|
-
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "
|
|
8
|
-
size?: "
|
|
7
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "progress" | "muted" | "success" | "progress-completed" | null | undefined;
|
|
8
|
+
size?: "sm" | "lg" | "default" | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
interface BadgeProps extends React.ComponentProps<"span">, VariantProps<typeof badgeVariants> {
|
|
11
11
|
asChild?: boolean;
|
package/dist/ui/button.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ import * as React from 'react';
|
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
6
|
declare const buttonVariants: (props?: ({
|
|
7
|
-
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" |
|
|
8
|
-
size?: "
|
|
7
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
|
|
8
|
+
size?: "xs" | "sm" | "lg" | "icon" | "default" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
interface ButtonProps extends React.ComponentProps<"button">, VariantProps<typeof buttonVariants> {
|
|
11
11
|
asChild?: boolean;
|
package/dist/ui/checkbox.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { Checkbox as Checkbox$1 } from 'radix-ui';
|
|
|
5
5
|
import { VariantProps } from 'class-variance-authority';
|
|
6
6
|
|
|
7
7
|
declare const checkboxVariants: (props?: ({
|
|
8
|
-
size?: "
|
|
8
|
+
size?: "sm" | "lg" | "default" | null | undefined;
|
|
9
9
|
variant?: "default" | "circular" | null | undefined;
|
|
10
10
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
11
11
|
interface CheckboxProps extends React.ComponentProps<typeof Checkbox$1.Root>, VariantProps<typeof checkboxVariants> {
|
|
@@ -4,7 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
6
|
declare const circularProgressVariants: (props?: ({
|
|
7
|
-
size?: "
|
|
7
|
+
size?: "xs" | "sm" | "lg" | "default" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface CircularProgressProps extends Omit<React.ComponentProps<"div">, "children">, VariantProps<typeof circularProgressVariants> {
|
|
10
10
|
/** Valor de 0 a 100 (clamped) */
|
package/dist/ui/empty.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
5
5
|
declare function Empty({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
6
6
|
declare function EmptyHeader({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
7
7
|
declare const emptyMediaVariants: (props?: ({
|
|
8
|
-
variant?: "
|
|
8
|
+
variant?: "icon" | "default" | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
declare function EmptyMedia({ className, variant, ...props }: React.ComponentProps<"div"> & VariantProps<typeof emptyMediaVariants>): react_jsx_runtime.JSX.Element;
|
|
11
11
|
declare function EmptyTitle({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
package/dist/ui/fab.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
6
|
declare const fabVariants: (props?: ({
|
|
7
|
-
size?: "
|
|
7
|
+
size?: "sm" | "lg" | "default" | null | undefined;
|
|
8
8
|
variant?: "default" | "outline" | "secondary" | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
interface FabProps extends React.ComponentProps<"button">, VariantProps<typeof fabVariants> {
|
package/dist/ui/file-card.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
6
|
declare const fileCardVariants: (props?: ({
|
|
7
|
-
size?: "sm" | "
|
|
7
|
+
size?: "sm" | "md" | "lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface FileCardProps extends Omit<React.ComponentProps<"button">, "children" | "size">, VariantProps<typeof fileCardVariants> {
|
|
10
10
|
/** Nome do arquivo exibido como titulo */
|
|
@@ -4,7 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
6
|
declare const likeDislikeVariants: (props?: ({
|
|
7
|
-
size?: "
|
|
7
|
+
size?: "xs" | "sm" | "lg" | "default" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
type LikeDislikeValue = "like" | "dislike" | null;
|
|
10
10
|
interface LikeDislikeProps extends Omit<React.ComponentProps<"div">, "onChange" | "defaultValue">, VariantProps<typeof likeDislikeVariants> {
|
package/dist/ui/message-bar.js
CHANGED
|
@@ -4,10 +4,10 @@ import * as React from 'react';
|
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
6
|
declare const progressDotVariants: (props?: ({
|
|
7
|
-
size?: "
|
|
7
|
+
size?: "xs" | "sm" | "lg" | "default" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
declare const dotVariants: (props?: ({
|
|
10
|
-
size?: "
|
|
10
|
+
size?: "xs" | "sm" | "lg" | "default" | null | undefined;
|
|
11
11
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
12
12
|
interface ProgressDotProps extends React.ComponentProps<"div">, VariantProps<typeof dotVariants> {
|
|
13
13
|
/** Numero total de stages (2–10) */
|
|
@@ -4,7 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
6
|
declare const progressStagePillVariants: (props?: ({
|
|
7
|
-
size?: "
|
|
7
|
+
size?: "xs" | "sm" | "lg" | "default" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface ProgressStageProps extends React.ComponentProps<"div">, VariantProps<typeof progressStagePillVariants> {
|
|
10
10
|
/** Numero total de stages (2–10) */
|
package/dist/ui/progress.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { Progress as Progress$1 } from 'radix-ui';
|
|
|
5
5
|
import { VariantProps } from 'class-variance-authority';
|
|
6
6
|
|
|
7
7
|
declare const progressVariants: (props?: ({
|
|
8
|
-
size?: "
|
|
8
|
+
size?: "xs" | "sm" | "lg" | "default" | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
declare const indicatorVariants: (props?: ({
|
|
11
11
|
variant?: "default" | "destructive" | "secondary" | "muted" | null | undefined;
|
package/dist/ui/radio-group.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { RadioGroup as RadioGroup$1 } from 'radix-ui';
|
|
|
5
5
|
import { VariantProps } from 'class-variance-authority';
|
|
6
6
|
|
|
7
7
|
declare const radioVariants: (props?: ({
|
|
8
|
-
size?: "
|
|
8
|
+
size?: "sm" | "lg" | "default" | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
interface RadioGroupProps extends React.ComponentProps<typeof RadioGroup$1.Root> {
|
|
11
11
|
}
|
package/dist/ui/slider.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { Slider as Slider$1 } from 'radix-ui';
|
|
|
5
5
|
import { VariantProps } from 'class-variance-authority';
|
|
6
6
|
|
|
7
7
|
declare const sliderVariants: (props?: ({
|
|
8
|
-
size?: "
|
|
8
|
+
size?: "sm" | "lg" | "default" | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
interface SliderProps extends React.ComponentProps<typeof Slider$1.Root>, VariantProps<typeof sliderVariants> {
|
|
11
11
|
/** Classe de tema aplicada (ex: "theme-brand") */
|
package/dist/ui/switch.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { Switch as Switch$1 } from 'radix-ui';
|
|
|
5
5
|
import { VariantProps } from 'class-variance-authority';
|
|
6
6
|
|
|
7
7
|
declare const switchVariants: (props?: ({
|
|
8
|
-
size?: "
|
|
8
|
+
size?: "sm" | "lg" | "default" | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
interface SwitchProps extends React.ComponentProps<typeof Switch$1.Root>, VariantProps<typeof switchVariants> {
|
|
11
11
|
/** Classe de tema aplicada no estado checked (ex: "theme-brand") */
|
package/dist/ui/toggle.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { Toggle as Toggle$1 } from 'radix-ui';
|
|
|
6
6
|
|
|
7
7
|
declare const toggleVariants: (props?: ({
|
|
8
8
|
variant?: "default" | "outline" | null | undefined;
|
|
9
|
-
size?: "
|
|
9
|
+
size?: "xs" | "sm" | "lg" | "icon" | "default" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
10
10
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
11
11
|
interface ToggleProps extends React.ComponentProps<typeof Toggle$1.Root>, VariantProps<typeof toggleVariants> {
|
|
12
12
|
/** Preenche icones SVG quando o toggle esta ativo (on). Ideal para icones como Heart, Star, Bookmark. */
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/ui/message-bar.tsx"],"names":["_a","_b"],"mappings":"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","file":"chunk-KUJHXRWG.js","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { Mic, Send, Trash2, Pause, Play, Lock, ChevronUp, ChevronLeft } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* ─── Types ───────────────────────────────────────────────────── */\n\n/**\n * Estados visuais do MessageBar:\n * - `default`: input texto + botao mic (estado inicial, sem texto digitado)\n * - `audio-only`: apenas botao mic centralizado (modo so audio)\n * - `active`: input texto com conteudo digitado + botao send\n * - `disabled`: input desabilitado\n * - `recording`: barra de gravacao (timer + waveform live + delete/pause/send)\n * - `paused`: gravacao pausada (timer + waveform + play/delete/mic/send)\n */\nexport type MessageBarState =\n | \"default\"\n | \"audio-only\"\n | \"active\"\n | \"disabled\"\n | \"recording\"\n | \"paused\"\n\nexport interface MessageBarProps extends Omit<React.ComponentProps<\"div\">, \"onChange\"> {\n /** Estado visual do componente (controlado pelo consumer) */\n state?: MessageBarState\n /** Valor do input de texto */\n value?: string\n /** Callback ao digitar */\n onChange?: (value: string) => void\n /** Callback ao enviar texto (Enter ou clique no botao send) */\n onSendText?: (text: string) => void\n /** Inicia gravacao (consumer chama MediaRecorder.start) */\n onStartRecording?: () => void\n /** Pausa gravacao */\n onPauseRecording?: () => void\n /** Retoma gravacao */\n onResumeRecording?: () => void\n /** Cancela/deleta gravacao */\n onCancelRecording?: () => void\n /** Envia o audio gravado */\n onSendAudio?: () => void\n /** Toggle play/pause do audio gravado durante o estado `paused` */\n onTogglePlay?: () => void\n /** Duracao da gravacao em segundos (controlado pelo consumer) */\n recordingDuration?: number\n /** Indica se esta tocando o audio (durante state=paused) */\n isPlaying?: boolean\n /**\n * MediaStream do microfone (durante state=recording). Quando fornecido,\n * o componente analisa em tempo real e renderiza as barras conforme a voz.\n * Sem stream → fallback para waveform decorativo.\n *\n * Como usar:\n * ```ts\n * const stream = await navigator.mediaDevices.getUserMedia({ audio: true })\n * const recorder = new MediaRecorder(stream)\n * // Passa o MESMO stream pro MessageBar:\n * <MessageBar state=\"recording\" recordingStream={stream} ... />\n * ```\n */\n recordingStream?: MediaStream | null\n /**\n * Progresso do playback do audio gravado (0-1), usado durante state=paused.\n * Quando fornecido, o waveform mostra barras tocadas/nao tocadas + dot verde\n * sincronizado. Sem isso, o waveform mostra todas as barras como nao tocadas.\n */\n playbackProgress?: number\n /**\n * Callback ao clicar/arrastar no waveform durante state=paused.\n * Recebe o novo progresso (0-1); o consumer deve setar currentTime do audio.\n */\n onSeekPlayback?: (progress: number) => void\n /** Placeholder do input */\n placeholder?: string\n}\n\n/* ─── Helpers ─────────────────────────────────────────────────── */\n\nfunction formatDuration(seconds: number): string {\n if (!Number.isFinite(seconds) || seconds < 0) return \"00:00\"\n const m = Math.floor(seconds / 60)\n const s = Math.floor(seconds % 60)\n return `${m.toString().padStart(2, \"0\")}:${s.toString().padStart(2, \"0\")}`\n}\n\n/* ─── Sub-componentes ─────────────────────────────────────────── */\n\n/** Botao mic vermelho coral (theme-brand) — usado em default, audio-only e durante press.\n * - `variant=\"large\"` aumenta para 64x64 (overlay durante press)\n * - `pressed` aplica scale-110 + opacity 90\n * - Aceita pointer events para suportar press-and-hold (mobile WhatsApp-style) */\nfunction MicButton({\n onClick,\n onPointerDown,\n onPointerMove,\n onPointerUp,\n onPointerCancel,\n size = \"default\",\n variant = \"default\",\n pressed = false,\n ariaLabel = \"Gravar audio\",\n className,\n style,\n}: {\n onClick?: () => void\n onPointerDown?: (e: React.PointerEvent<HTMLButtonElement>) => void\n onPointerMove?: (e: React.PointerEvent<HTMLButtonElement>) => void\n onPointerUp?: (e: React.PointerEvent<HTMLButtonElement>) => void\n onPointerCancel?: (e: React.PointerEvent<HTMLButtonElement>) => void\n size?: \"default\" | \"sm\"\n variant?: \"default\" | \"large\"\n pressed?: boolean\n ariaLabel?: string\n className?: string\n style?: React.CSSProperties\n}) {\n const sizeClass =\n variant === \"large\" ? \"size-16\" : size === \"default\" ? \"size-10\" : \"size-8\"\n const radiusClass = variant === \"large\" ? \"rounded-lg\" : \"rounded-md\"\n return (\n <button\n type=\"button\"\n onClick={onClick}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerCancel}\n aria-pressed={pressed || undefined}\n className={cn(\n \"shrink-0 inline-flex items-center justify-center bg-primary text-primary-foreground theme-brand transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50\",\n sizeClass,\n radiusClass,\n pressed && \"opacity-90 touch-none select-none\",\n className\n )}\n style={style}\n aria-label={ariaLabel}\n >\n <Mic className={variant === \"large\" ? \"size-6\" : \"size-5\"} />\n </button>\n )\n}\n\n/** Botao send verde (theme-positive) */\nfunction SendButton({\n onClick,\n disabled,\n ariaLabel = \"Enviar\",\n}: {\n onClick?: () => void\n disabled?: boolean\n ariaLabel?: string\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n className=\"shrink-0 inline-flex items-center justify-center size-10 rounded-md bg-primary text-primary-foreground theme-positive transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:opacity-50 disabled:cursor-not-allowed\"\n aria-label={ariaLabel}\n >\n <Send className=\"size-5\" fill=\"currentColor\" strokeWidth={0} />\n </button>\n )\n}\n\n/** Botao icon-only neutral (trash, pause, play, mic durante paused) */\nfunction IconButton({\n onClick,\n icon: Icon,\n ariaLabel,\n filled = false,\n}: {\n onClick?: () => void\n icon: React.ComponentType<{ className?: string; fill?: string; strokeWidth?: number }>\n ariaLabel: string\n filled?: boolean\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"shrink-0 inline-flex items-center justify-center size-10 rounded-md text-neutral-foreground hover:bg-muted/50 transition-colors focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n aria-label={ariaLabel}\n >\n <Icon\n className=\"size-5\"\n {...(filled ? { fill: \"currentColor\", strokeWidth: 0 } : {})}\n />\n </button>\n )\n}\n\n/** Indicador de gravacao (red dot pulsando) */\nfunction RecordingIndicator() {\n return (\n <span className=\"shrink-0 relative inline-flex items-center justify-center size-3\" aria-label=\"Gravando\">\n <span className=\"absolute inset-0 rounded-full bg-primary theme-brand animate-ping opacity-75\" />\n <span className=\"relative size-2.5 rounded-full bg-primary theme-brand\" />\n </span>\n )\n}\n\n/** Helper: agrega N samples brutos em K barras (pico por chunk). Quando samples.length\n * < barCount, \"estica\" via lookup proporcional (cada barra pega o sample mais proximo). */\nfunction aggregateSamples(samples: number[], barCount: number): number[] {\n if (samples.length === 0 || barCount === 0) return new Array(barCount).fill(0)\n const result = new Array(barCount).fill(0)\n // Poucos samples: estica via lookup proporcional\n if (samples.length < barCount) {\n for (let i = 0; i < barCount; i++) {\n const idx = Math.floor((i / barCount) * samples.length)\n result[i] = samples[idx] ?? 0\n }\n return result\n }\n // Muitos samples: agrega pegando o pico (max) do chunk\n const chunkSize = samples.length / barCount\n for (let i = 0; i < barCount; i++) {\n const start = Math.floor(i * chunkSize)\n const end = Math.floor((i + 1) * chunkSize)\n let max = 0\n for (let j = start; j < end && j < samples.length; j++) {\n if (samples[j] > max) max = samples[j]\n }\n result[i] = max\n }\n return result\n}\n\n/** LiveWaveform — analise em tempo real do microfone via AnalyserNode.\n * Comportamento estilo WhatsApp:\n * - **Preenche toda a largura disponivel** (ResizeObserver detecta width e calcula limite max de barras)\n * - Cada bar = 2px wide, 2px gap (4px stride)\n * - **Comeca VAZIO**: primeiras barras entram pela DIREITA e empurram pra esquerda\n * - Depois que enche: rolling window (mais antiga sai esquerda, nova entra direita)\n * - Visualmente: container alinha barras com `justify-end` */\nfunction LiveWaveform({\n stream,\n samplesRef,\n}: {\n stream?: MediaStream | null\n /** Ref opcional: quando fornecido, acumula TODOS os samples brutos da gravacao (para usar no\n * state=paused via RecordedWaveform). O LiveWaveform mantem seu rolling window separado. */\n samplesRef?: React.MutableRefObject<number[]>\n}) {\n const STRIDE = 4 // 2px barra + 2px gap\n const MIN_BARS = 20\n const containerRef = React.useRef<HTMLDivElement>(null)\n const [bars, setBars] = React.useState<number[]>([])\n const barCountRef = React.useRef<number>(MIN_BARS)\n\n /* ResizeObserver: ajusta o LIMITE de barras (nao o buffer atual, exceto se shrink). */\n React.useEffect(() => {\n const el = containerRef.current\n if (!el) return\n\n const updateBarCount = (width: number) => {\n const count = Math.max(MIN_BARS, Math.floor(width / STRIDE))\n barCountRef.current = count\n // Se o buffer atual passou do novo limite (shrink), trunca mantendo as mais recentes\n setBars((prev) => (prev.length > count ? prev.slice(prev.length - count) : prev))\n }\n\n updateBarCount(el.clientWidth)\n\n const ro = new ResizeObserver((entries) => {\n const width = entries[0]?.contentRect.width ?? 0\n updateBarCount(width)\n })\n ro.observe(el)\n\n return () => ro.disconnect()\n }, [])\n\n /* Audio analysis setup (so depende do stream) */\n React.useEffect(() => {\n if (!stream) {\n setBars([])\n return\n }\n\n const AudioContextClass =\n window.AudioContext ||\n (window as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext\n const audioContext = new AudioContextClass()\n const source = audioContext.createMediaStreamSource(stream)\n const analyser = audioContext.createAnalyser()\n analyser.fftSize = 256\n source.connect(analyser)\n\n const dataArray = new Uint8Array(analyser.frequencyBinCount)\n let rafId: number | null = null\n let lastUpdate = 0\n let cancelled = false\n\n const tick = (timestamp: number) => {\n if (cancelled) return\n // Throttle ~30fps (33ms entre samples)\n if (timestamp - lastUpdate >= 33) {\n lastUpdate = timestamp\n analyser.getByteTimeDomainData(dataArray)\n\n // RMS — amplitude media percebida\n let sum = 0\n for (let i = 0; i < dataArray.length; i++) {\n const v = (dataArray[i] - 128) / 128\n sum += v * v\n }\n const rms = Math.sqrt(sum / dataArray.length)\n\n // Acumula no ref do parent (para reaproveitar no state=paused via RecordedWaveform)\n if (samplesRef) samplesRef.current.push(rms)\n\n setBars((prev) => {\n // Enquanto nao encheu: append no final (vai aparecer na direita por causa do justify-end)\n if (prev.length < barCountRef.current) return [...prev, rms]\n // Cheio: rolling window (descarta mais antiga, adiciona nova)\n return [...prev.slice(1), rms]\n })\n }\n rafId = requestAnimationFrame(tick)\n }\n\n rafId = requestAnimationFrame(tick)\n\n return () => {\n cancelled = true\n if (rafId !== null) cancelAnimationFrame(rafId)\n void audioContext.close()\n }\n }, [stream, samplesRef])\n\n return (\n <div\n ref={containerRef}\n className=\"flex-1 relative h-8 min-w-0 overflow-hidden\"\n >\n <div className=\"absolute inset-y-0 left-0 right-0 flex items-center justify-end gap-[2px]\">\n {bars.map((amp, i) => {\n // Voz humana tende a ter RMS baixo (~0.05-0.3). Boost x4 para visual.\n const normalized = Math.min(amp * 4, 1)\n const height = Math.max(2, Math.round(normalized * 32))\n return (\n <div\n key={i}\n className=\"w-[2px] shrink-0 rounded-full bg-neutral-foreground\"\n style={{ height: `${height}px` }}\n />\n )\n })}\n </div>\n </div>\n )\n}\n\n/** RecordedWaveform — waveform real do audio ja gravado (usado no state=paused).\n * - Recebe samples brutos acumulados durante o recording (via samplesRef)\n * - Agrega em N barras via ResizeObserver (largura dinamica, igual ChatAudio)\n * - Barras tocadas (i / N <= progress) em `bg-neutral-foreground`, demais em `bg-neutral-ring`\n * - Dot verde sincronizado com o progresso\n * - Click/drag-to-seek via pointer events */\nfunction RecordedWaveform({\n samples,\n progress = 0,\n onSeek,\n}: {\n samples: number[]\n progress?: number\n onSeek?: (progress: number) => void\n}) {\n const STRIDE = 4 // 2px barra + 2px gap\n const MIN_BARS = 20\n const containerRef = React.useRef<HTMLDivElement>(null)\n const [barCount, setBarCount] = React.useState<number>(MIN_BARS)\n\n React.useEffect(() => {\n const el = containerRef.current\n if (!el) return\n const updateBarCount = (width: number) => {\n const count = Math.max(MIN_BARS, Math.floor(width / STRIDE))\n setBarCount(count)\n }\n updateBarCount(el.clientWidth)\n const ro = new ResizeObserver((entries) => {\n updateBarCount(entries[0]?.contentRect.width ?? 0)\n })\n ro.observe(el)\n return () => ro.disconnect()\n }, [])\n\n // Agrega samples acumulados em barCount barras + normaliza para 0-1 (relativo ao pico)\n const bars = React.useMemo(() => {\n const aggregated = aggregateSamples(samples, barCount)\n const maxPeak = Math.max(...aggregated, 0.01)\n return aggregated.map((p) => p / maxPeak)\n }, [samples, barCount])\n\n const isDraggingRef = React.useRef(false)\n\n const seekFromClientX = React.useCallback(\n (clientX: number) => {\n const el = containerRef.current\n if (!el || !onSeek) return\n const rect = el.getBoundingClientRect()\n const x = clientX - rect.left\n const newProgress = Math.max(0, Math.min(x / rect.width, 1))\n onSeek(newProgress)\n },\n [onSeek]\n )\n\n const handlePointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!onSeek) return\n isDraggingRef.current = true\n e.currentTarget.setPointerCapture(e.pointerId)\n seekFromClientX(e.clientX)\n }\n const handlePointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!isDraggingRef.current) return\n seekFromClientX(e.clientX)\n }\n const handlePointerUp = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!isDraggingRef.current) return\n isDraggingRef.current = false\n e.currentTarget.releasePointerCapture(e.pointerId)\n }\n\n // Largura natural do layout das barras (px), usada para posicionar o dot em pixels\n const barsLayoutWidth = bars.length * STRIDE - 2\n\n return (\n <div\n ref={containerRef}\n className={cn(\n \"flex-1 relative h-8 min-w-0 overflow-hidden select-none\",\n onSeek && \"touch-none cursor-pointer\"\n )}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n role={onSeek ? \"slider\" : undefined}\n aria-label={onSeek ? \"Posicao do audio\" : undefined}\n aria-valuemin={onSeek ? 0 : undefined}\n aria-valuemax={onSeek ? 100 : undefined}\n aria-valuenow={onSeek ? Math.round(progress * 100) : undefined}\n >\n <div className=\"absolute inset-y-0 left-0 flex items-center gap-[2px]\">\n {bars.map((amp, i) => {\n const isPlayed = i / bars.length <= progress\n const height = Math.max(2, Math.round(amp * 32))\n return (\n <div\n key={i}\n className={cn(\n \"w-[2px] shrink-0 rounded-full\",\n isPlayed ? \"bg-neutral-foreground\" : \"bg-neutral-ring\"\n )}\n style={{ height: `${height}px` }}\n />\n )\n })}\n </div>\n {progress > 0 && (\n <div\n className=\"absolute top-1/2 z-10 -translate-y-1/2 -translate-x-1/2 size-3 rounded-full bg-[#098A5E] shadow-md pointer-events-none\"\n style={{ left: `${progress * barsLayoutWidth}px` }}\n aria-hidden=\"true\"\n />\n )}\n </div>\n )\n}\n\n/* ─── Press-to-record constants ───────────────────────────────── */\n\nconst LOCK_THRESHOLD = 120 // px arrastados pra cima → trava em modo hands-free\nconst CANCEL_THRESHOLD_RATIO = 0.65 // % da largura do MessageBar\nconst CANCEL_THRESHOLD_MIN = 140 // floor (telas pequenas — iPhone SE)\nconst CANCEL_THRESHOLD_MAX = 220 // ceiling (telas grandes — nao precisa atravessar a tela toda)\nconst MIN_DURATION = 1000 // ms — release antes disso cancela\n\n/** Calcula o threshold de cancel baseado na largura do container do MessageBar.\n * Sempre proporcional, com clamps min/max pra funcionar bem em telas pequenas (iPhone SE)\n * sem ficar trivialmente facil em telas grandes. */\nfunction computeCancelThreshold(containerWidth: number): number {\n return Math.min(\n CANCEL_THRESHOLD_MAX,\n Math.max(CANCEL_THRESHOLD_MIN, containerWidth * CANCEL_THRESHOLD_RATIO)\n )\n}\n\n/** PressedRecordingOverlay — UI exibida enquanto o usuario mantem o mic pressionado.\n * Inspirado no comportamento de gravacao de audio do WhatsApp.\n *\n * - Pill esquerda: live dot + timer + \"Deslize para cancelar\"\n * - Mic vermelho 64×64 (acompanha o cursor via translate clamped)\n * - Pill flutuante ACIMA do mic com lock + chevron up (indica \"deslize pra travar\")\n *\n * Variants:\n * - `default`: layout horizontal (cancel pill esquerda + mic direita)\n * - `audio-only`: layout horizontal centralizado (cancel pill curta + mic + timer pill) */\nfunction PressedRecordingOverlay({\n variant,\n duration,\n deltaX,\n deltaY,\n lockThreshold,\n cancelThreshold,\n}: {\n variant: \"default\" | \"audio-only\"\n duration: number\n deltaX: number\n deltaY: number\n lockThreshold: number\n cancelThreshold: number\n}) {\n const aboutToLock = deltaY <= -lockThreshold\n const aboutToCancel = deltaX <= -cancelThreshold\n // Clamp: so move pra cima/esquerda (delta negativo); ignora positivos\n const micTranslateX = Math.min(0, deltaX)\n const micTranslateY = Math.min(0, deltaY)\n\n return (\n <div\n data-slot=\"message-bar\"\n data-state=\"recording-pressed\"\n className={cn(\n \"flex items-center gap-2 p-2 sm:gap-3 sm:p-0\",\n variant === \"audio-only\" && \"justify-center\"\n )}\n >\n {/* Layout: cancel-pill + mic (default) | cancel-pill + mic + timer-pill (audio-only) */}\n {variant === \"audio-only\" ? (\n <div className=\"relative flex items-center gap-2\">\n {/* Cancel pill (compact) */}\n <div\n className={cn(\n \"flex items-center gap-1 rounded-full bg-muted h-7 px-3 transition-colors\",\n aboutToCancel && \"bg-destructive/10\"\n )}\n >\n <ChevronLeft className=\"size-3 text-muted-foreground\" />\n <span\n className={cn(\n \"text-xs\",\n aboutToCancel ? \"text-destructive font-medium\" : \"text-muted-foreground\"\n )}\n >\n Cancelar\n </span>\n </div>\n\n {/* Mic + lock pill (anchor) */}\n <div className=\"relative\">\n {/* Lock pill ACIMA do mic */}\n <div\n className={cn(\n \"absolute left-1/2 -translate-x-1/2 bottom-full mb-2 flex flex-col items-center gap-3 rounded-t-full bg-muted h-20 w-8 py-3 transition-transform\",\n aboutToLock && \"scale-125 ring-2 ring-[#0EA460]\"\n )}\n aria-hidden=\"true\"\n >\n <Lock className={cn(\"size-3\", aboutToLock ? \"text-[#0EA460]\" : \"text-muted-foreground\")} />\n <ChevronUp className=\"size-3 text-muted-foreground animate-bounce\" />\n </div>\n\n <MicButton\n variant=\"large\"\n pressed\n ariaLabel=\"Gravando — arraste para cima para travar, para esquerda para cancelar\"\n className={cn(aboutToCancel && \"animate-shake\")}\n style={\n aboutToCancel\n ? undefined\n : { transform: `translate(${micTranslateX}px, ${micTranslateY}px) scale(1.1)` }\n }\n />\n </div>\n\n {/* Timer pill */}\n <div className=\"flex items-center gap-1 rounded-full bg-muted h-7 px-3\">\n <RecordingIndicator />\n <span className=\"text-sm tabular-nums text-neutral-foreground\">\n {formatDuration(duration)}\n </span>\n </div>\n </div>\n ) : (\n // Variant default: cancel pill flex-1 + mic\n <>\n <div\n className={cn(\n \"flex-1 flex items-center justify-between gap-2 rounded-xl bg-muted px-4 py-3 h-14\",\n aboutToCancel && \"bg-destructive/10\"\n )}\n >\n <div className=\"flex items-center gap-2\">\n <RecordingIndicator />\n <span className=\"text-sm tabular-nums text-neutral-foreground\">\n {formatDuration(duration)}\n </span>\n </div>\n <div\n className={cn(\n \"flex items-center gap-1 text-xs\",\n aboutToCancel ? \"text-destructive font-medium\" : \"text-muted-foreground\"\n )}\n >\n <ChevronLeft className=\"size-3\" />\n <span>Deslize para cancelar</span>\n </div>\n </div>\n\n {/* Mic + lock pill */}\n <div className=\"relative\">\n <div\n className={cn(\n \"absolute left-1/2 -translate-x-1/2 bottom-full mb-2 flex flex-col items-center gap-3 rounded-t-full bg-muted h-20 w-8 py-3 transition-transform\",\n aboutToLock && \"scale-125 ring-2 ring-[#0EA460]\"\n )}\n aria-hidden=\"true\"\n >\n <Lock className={cn(\"size-3\", aboutToLock ? \"text-[#0EA460]\" : \"text-muted-foreground\")} />\n <ChevronUp className=\"size-3 text-muted-foreground animate-bounce\" />\n </div>\n\n <MicButton\n variant=\"large\"\n pressed\n ariaLabel=\"Gravando — arraste para cima para travar, para esquerda para cancelar\"\n className={cn(aboutToCancel && \"animate-shake\")}\n style={\n aboutToCancel\n ? undefined\n : { transform: `translate(${micTranslateX}px, ${micTranslateY}px) scale(1.1)` }\n }\n />\n </div>\n </>\n )}\n </div>\n )\n}\n\n/* ─── Component principal ─────────────────────────────────────── */\n\nfunction MessageBar({\n state = \"default\",\n value = \"\",\n onChange,\n onSendText,\n onStartRecording,\n onPauseRecording,\n onResumeRecording,\n onCancelRecording,\n onSendAudio,\n onTogglePlay,\n recordingDuration = 0,\n isPlaying = false,\n recordingStream,\n playbackProgress = 0,\n onSeekPlayback,\n placeholder = \"Digite sua mensagem...\",\n className,\n ...props\n}: MessageBarProps) {\n // Acumula samples brutos do microfone durante recording — reaproveitado em paused via RecordedWaveform\n const samplesRef = React.useRef<number[]>([])\n\n // Reset dos samples quando inicia nova gravacao (transicao para recording a partir de outros estados)\n // Nao zera ao voltar de paused → recording (continua a mesma gravacao)\n const prevStateRef = React.useRef<MessageBarState>(state)\n // Lembra o ultimo base state (default/audio-only) pra escolher variant do overlay pressed\n const lastBaseStateRef = React.useRef<\"default\" | \"audio-only\">(\n state === \"audio-only\" ? \"audio-only\" : \"default\"\n )\n React.useEffect(() => {\n const prev = prevStateRef.current\n if (state === \"recording\" && prev !== \"paused\" && prev !== \"recording\") {\n samplesRef.current = []\n }\n if (state === \"default\" || state === \"audio-only\") {\n lastBaseStateRef.current = state\n }\n prevStateRef.current = state\n }, [state])\n\n /* ─── Press-to-record (WhatsApp-like, touch-only) ───────────── */\n const [isPressed, setIsPressed] = React.useState(false)\n const [pressDelta, setPressDelta] = React.useState({ x: 0, y: 0 })\n // Cancel threshold dinamico — calculado baseado na largura do container no pointerdown\n const [pressCancelThreshold, setPressCancelThreshold] = React.useState(CANCEL_THRESHOLD_MAX)\n const pressDeltaRef = React.useRef({ x: 0, y: 0 })\n const pressCancelThresholdRef = React.useRef(CANCEL_THRESHOLD_MAX)\n const pressInfoRef = React.useRef({ startX: 0, startY: 0, startTime: 0, locked: false })\n // Refs pros callbacks — handlers do window leem a versao mais recente sem precisar reinstalar listeners\n const callbacksRef = React.useRef({ onStartRecording, onCancelRecording, onSendAudio })\n React.useEffect(() => {\n callbacksRef.current = { onStartRecording, onCancelRecording, onSendAudio }\n })\n\n const updateDelta = (dx: number, dy: number) => {\n pressDeltaRef.current = { x: dx, y: dy }\n setPressDelta({ x: dx, y: dy })\n }\n\n const triggerHaptic = (ms = 50) => {\n if (typeof navigator !== \"undefined\" && typeof navigator.vibrate === \"function\") {\n try {\n navigator.vibrate(ms)\n } catch {\n /* ignore — alguns browsers podem rejeitar fora de user gesture */\n }\n }\n }\n\n // Listeners no window (sobrevivem a troca de DOM quando o overlay aparece e o MicButton original desmonta)\n React.useEffect(() => {\n if (!isPressed) return\n\n // Previne o browser de interceptar gestos nativos (swipe-back iOS, scroll, pinch)\n // durante o press — sem isso, iOS Safari dispara pointercancel ao detectar swipe horizontal.\n const prevTouchAction = document.body.style.touchAction\n document.body.style.touchAction = \"none\"\n\n const onMove = (e: PointerEvent) => {\n if (pressInfoRef.current.locked) return\n const { startX, startY } = pressInfoRef.current\n const dx = e.clientX - startX\n const dy = e.clientY - startY\n updateDelta(dx, dy)\n // Atinge lock threshold → trava em modo hands-free\n if (dy <= -LOCK_THRESHOLD) {\n pressInfoRef.current.locked = true\n triggerHaptic(50)\n setIsPressed(false)\n updateDelta(0, 0)\n }\n }\n\n const onEnd = () => {\n if (pressInfoRef.current.locked) return\n const { startTime } = pressInfoRef.current\n const elapsed = Date.now() - startTime\n const { x: dx } = pressDeltaRef.current\n\n setIsPressed(false)\n updateDelta(0, 0)\n\n if (dx <= -pressCancelThresholdRef.current || elapsed < MIN_DURATION) {\n triggerHaptic(50)\n callbacksRef.current.onCancelRecording?.()\n return\n }\n callbacksRef.current.onSendAudio?.()\n }\n\n // pointercancel = browser interrompeu o gesto (swipe-back iOS, scroll, etc.).\n // NAO eh release intencional do usuario — apenas reseta o state sem\n // disparar onCancelRecording/onSendAudio.\n const onCancel = () => {\n setIsPressed(false)\n updateDelta(0, 0)\n }\n\n window.addEventListener(\"pointermove\", onMove)\n window.addEventListener(\"pointerup\", onEnd)\n window.addEventListener(\"pointercancel\", onCancel)\n return () => {\n window.removeEventListener(\"pointermove\", onMove)\n window.removeEventListener(\"pointerup\", onEnd)\n window.removeEventListener(\"pointercancel\", onCancel)\n document.body.style.touchAction = prevTouchAction\n }\n }, [isPressed])\n\n const handlePressStart = (e: React.PointerEvent<HTMLButtonElement>) => {\n // Desktop (mouse/pen): comportamento antigo de click — dispara onStartRecording, sai do flow press\n if (e.pointerType !== \"touch\") {\n onStartRecording?.()\n return\n }\n // Mede a largura do container do MessageBar pra calcular o cancel threshold adaptativo\n const wrapper = e.currentTarget.closest('[data-slot=\"message-bar\"]')\n const containerWidth =\n wrapper instanceof HTMLElement ? wrapper.clientWidth : window.innerWidth\n const threshold = computeCancelThreshold(containerWidth)\n pressCancelThresholdRef.current = threshold\n setPressCancelThreshold(threshold)\n\n pressInfoRef.current = {\n startX: e.clientX,\n startY: e.clientY,\n startTime: Date.now(),\n locked: false,\n }\n updateDelta(0, 0)\n setIsPressed(true)\n onStartRecording?.()\n }\n\n const pressHandlers = {\n onPointerDown: handlePressStart,\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey && value.trim()) {\n e.preventDefault()\n onSendText?.(value)\n }\n }\n\n /* ─── State: audio-only (so botao mic centralizado) ─────────── */\n if (state === \"audio-only\") {\n return (\n <div\n data-slot=\"message-bar\"\n data-state=\"audio-only\"\n className={cn(\"flex items-center justify-center p-2\", className)}\n {...props}\n >\n <MicButton {...pressHandlers} />\n </div>\n )\n }\n\n /* ─── State: recording + pressed (overlay WhatsApp-like) ────── */\n if (state === \"recording\" && isPressed) {\n return (\n <PressedRecordingOverlay\n variant={lastBaseStateRef.current}\n duration={recordingDuration}\n deltaX={pressDelta.x}\n deltaY={pressDelta.y}\n lockThreshold={LOCK_THRESHOLD}\n cancelThreshold={pressCancelThreshold}\n />\n )\n }\n\n /* ─── State: recording (hands-free, apos lock ou click no mic) ─ */\n if (state === \"recording\") {\n return (\n <div\n data-slot=\"message-bar\"\n data-state=\"recording\"\n className={cn(\n \"flex items-center gap-2 p-2 sm:gap-3 sm:p-0\",\n className\n )}\n {...props}\n >\n {/* Mobile: 2-row layout */}\n <div className=\"flex flex-col gap-2 w-full sm:contents\">\n {/* Top: trash + recording info + waveform (mobile) / inline (desktop) */}\n <div className=\"flex items-center gap-2 sm:contents\">\n {/* Trash — only inline at desktop, mobile shows in bottom row */}\n <div className=\"hidden sm:contents\">\n <IconButton\n onClick={onCancelRecording}\n icon={Trash2}\n ariaLabel=\"Cancelar gravacao\"\n />\n </div>\n\n {/* Recording bar — bg-muted container */}\n <div className=\"flex items-center gap-3 flex-1 rounded-2xl bg-muted px-4 py-3\">\n <RecordingIndicator />\n <span className=\"shrink-0 text-sm text-neutral-foreground tabular-nums\">\n {formatDuration(recordingDuration)}\n </span>\n <LiveWaveform stream={recordingStream} samplesRef={samplesRef} />\n {/* Pause inside the bar — only desktop */}\n <div className=\"hidden sm:contents\">\n <button\n type=\"button\"\n onClick={onPauseRecording}\n className=\"shrink-0 inline-flex items-center justify-center text-neutral-foreground hover:opacity-80 transition-opacity\"\n aria-label=\"Pausar gravacao\"\n >\n <Pause className=\"size-5\" fill=\"currentColor\" strokeWidth={0} />\n </button>\n </div>\n </div>\n\n {/* Send — only inline at desktop */}\n <div className=\"hidden sm:contents\">\n <SendButton onClick={onSendAudio} ariaLabel=\"Enviar audio\" />\n </div>\n </div>\n\n {/* Bottom row — mobile only */}\n <div className=\"flex items-center justify-between sm:hidden\">\n <IconButton\n onClick={onCancelRecording}\n icon={Trash2}\n ariaLabel=\"Cancelar gravacao\"\n />\n <button\n type=\"button\"\n onClick={onPauseRecording}\n className=\"shrink-0 inline-flex items-center justify-center size-10 text-neutral-foreground hover:opacity-80 transition-opacity\"\n aria-label=\"Pausar gravacao\"\n >\n <Pause className=\"size-5\" fill=\"currentColor\" strokeWidth={0} />\n </button>\n <SendButton onClick={onSendAudio} ariaLabel=\"Enviar audio\" />\n </div>\n </div>\n </div>\n )\n }\n\n /* ─── State: paused (com audio gravado) ──────────────────────── */\n if (state === \"paused\") {\n return (\n <div\n data-slot=\"message-bar\"\n data-state=\"paused\"\n className={cn(\n \"flex items-center gap-2 p-2 sm:gap-3 sm:p-0\",\n className\n )}\n {...props}\n >\n <div className=\"flex flex-col gap-2 w-full sm:contents\">\n <div className=\"flex items-center gap-2 sm:contents\">\n <div className=\"hidden sm:contents\">\n <IconButton\n onClick={onCancelRecording}\n icon={Trash2}\n ariaLabel=\"Cancelar gravacao\"\n />\n </div>\n\n <div className=\"flex items-center gap-3 flex-1 rounded-2xl bg-muted px-4 py-3\">\n <button\n type=\"button\"\n onClick={onTogglePlay}\n className=\"shrink-0 inline-flex items-center justify-center text-neutral-foreground hover:opacity-80 transition-opacity\"\n aria-label={isPlaying ? \"Pausar\" : \"Reproduzir\"}\n >\n {isPlaying ? (\n <Pause className=\"size-5\" fill=\"currentColor\" strokeWidth={0} />\n ) : (\n <Play className=\"size-5\" fill=\"currentColor\" strokeWidth={0} />\n )}\n </button>\n <span className=\"shrink-0 text-sm text-neutral-foreground tabular-nums\">\n {formatDuration(recordingDuration)}\n </span>\n <RecordedWaveform\n samples={samplesRef.current}\n progress={playbackProgress}\n onSeek={onSeekPlayback}\n />\n {/* Mic inline — only desktop */}\n <div className=\"hidden sm:contents\">\n <button\n type=\"button\"\n onClick={onResumeRecording}\n className=\"shrink-0 inline-flex items-center justify-center text-neutral-foreground hover:opacity-80 transition-opacity\"\n aria-label=\"Continuar gravacao\"\n >\n <Mic className=\"size-5\" />\n </button>\n </div>\n </div>\n\n <div className=\"hidden sm:contents\">\n <SendButton onClick={onSendAudio} ariaLabel=\"Enviar audio\" />\n </div>\n </div>\n\n {/* Bottom row — mobile only */}\n <div className=\"flex items-center justify-between sm:hidden\">\n <IconButton\n onClick={onCancelRecording}\n icon={Trash2}\n ariaLabel=\"Cancelar gravacao\"\n />\n <button\n type=\"button\"\n onClick={onResumeRecording}\n className=\"shrink-0 inline-flex items-center justify-center size-10 text-neutral-foreground hover:opacity-80 transition-opacity\"\n aria-label=\"Continuar gravacao\"\n >\n <Mic className=\"size-5\" />\n </button>\n <SendButton onClick={onSendAudio} ariaLabel=\"Enviar audio\" />\n </div>\n </div>\n </div>\n )\n }\n\n /* ─── States: default | active | disabled (input + button) ──── */\n const isDisabled = state === \"disabled\"\n const isActive = state === \"active\" || (state === \"default\" && value.trim().length > 0)\n\n return (\n <div\n data-slot=\"message-bar\"\n data-state={state}\n className={cn(\n \"flex items-center gap-2 rounded-2xl bg-muted p-2\",\n className\n )}\n {...props}\n >\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange?.(e.target.value)}\n onKeyDown={handleKeyDown}\n disabled={isDisabled}\n placeholder={placeholder}\n className={cn(\n \"flex-1 min-w-0 bg-transparent px-3 py-2 text-base text-neutral-foreground placeholder:text-neutral-muted-foreground outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\"\n )}\n aria-label=\"Mensagem\"\n />\n {isActive ? (\n <SendButton\n onClick={() => value.trim() && onSendText?.(value)}\n disabled={!value.trim()}\n />\n ) : (\n <MicButton {...pressHandlers} />\n )}\n </div>\n )\n}\n\nexport { MessageBar }\n"]}
|