@fluencypassdevs/cycle 1.32.0 → 1.33.1
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/bin/components.generated.mjs +70 -3
- package/dist/{chunk-GDPUWRNH.js → chunk-2MGHBZ7I.js} +9 -6
- package/dist/chunk-2MGHBZ7I.js.map +1 -0
- package/dist/{chunk-KNJTTOAD.js → chunk-2NVKK7UB.js} +3 -3
- package/dist/chunk-2NVKK7UB.js.map +1 -0
- package/dist/{chunk-VZ2GYSNK.js → chunk-OE4CHHIW.js} +46 -11
- package/dist/chunk-OE4CHHIW.js.map +1 -0
- package/dist/{chunk-OFGJDRRR.js → chunk-OZCMOOT7.js} +3 -3
- package/dist/{chunk-OFGJDRRR.js.map → chunk-OZCMOOT7.js.map} +1 -1
- package/dist/{chunk-WVCNTN4F.js → chunk-R7QITHNQ.js} +3 -3
- package/dist/{chunk-WVCNTN4F.js.map → chunk-R7QITHNQ.js.map} +1 -1
- package/dist/composites/chat-thread.js +2 -2
- package/dist/index.js +5 -5
- package/dist/lib/utils.js +0 -1
- package/dist/styles/tokens.css +24 -24
- package/dist/ui/chat-message.d.ts +20 -3
- package/dist/ui/chat-message.js +1 -1
- package/dist/ui/circular-progress.d.ts +6 -2
- package/dist/ui/circular-progress.js +1 -1
- package/dist/ui/file-dropzone.js +2 -2
- package/dist/ui/progress.d.ts +3 -1
- package/dist/ui/progress.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-GDPUWRNH.js.map +0 -1
- package/dist/chunk-KNJTTOAD.js.map +0 -1
- package/dist/chunk-VZ2GYSNK.js.map +0 -1
package/dist/ui/progress.d.ts
CHANGED
|
@@ -13,7 +13,9 @@ declare const indicatorVariants: (props?: ({
|
|
|
13
13
|
interface ProgressProps extends Omit<React.ComponentProps<typeof Progress$1.Root>, "children">, VariantProps<typeof progressVariants>, VariantProps<typeof indicatorVariants> {
|
|
14
14
|
/** Classe de tema aplicada apenas no indicator (ex: "theme-class") */
|
|
15
15
|
theme?: string;
|
|
16
|
+
/** Classes extras no indicator (a barra preenchida). `className` vai para o track. */
|
|
17
|
+
indicatorClassName?: string;
|
|
16
18
|
}
|
|
17
|
-
declare function Progress({ className, value, size, variant, theme, ...props }: ProgressProps): react_jsx_runtime.JSX.Element;
|
|
19
|
+
declare function Progress({ className, value, size, variant, theme, indicatorClassName, ...props }: ProgressProps): react_jsx_runtime.JSX.Element;
|
|
18
20
|
|
|
19
21
|
export { Progress, type ProgressProps, indicatorVariants, progressVariants };
|
package/dist/ui/progress.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
export { Progress, indicatorVariants, progressVariants } from '../chunk-
|
|
2
|
+
export { Progress, indicatorVariants, progressVariants } from '../chunk-2MGHBZ7I.js';
|
|
3
3
|
import '../chunk-LYTC7UMN.js';
|
|
4
4
|
import '../chunk-W4KJCBMW.js';
|
|
5
5
|
import '../chunk-2NMEKWO5.js';
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/ui/progress.tsx"],"names":["ProgressPrimitive"],"mappings":";;;;;;AAUA,IAAM,gBAAA,GAAmB,GAAA;AAAA,EACvB,+DAAA;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,IAAA,EAAM;AAAA,QACJ,EAAA,EAAI,KAAA;AAAA,QACJ,EAAA,EAAI,OAAA;AAAA,QACJ,OAAA,EAAS,KAAA;AAAA,QACT,EAAA,EAAI;AAAA;AACN,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,IAAA,EAAM;AAAA;AACR;AAEJ;AAIA,IAAM,iBAAA,GAAoB,GAAA;AAAA,EACxB,kDAAA;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA,QACP,OAAA,EAAS,YAAA;AAAA,QACT,SAAA,EAAW,cAAA;AAAA,QACX,WAAA,EAAa,gBAAA;AAAA,QACb,KAAA,EAAO;AAAA;AACT,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,OAAA,EAAS;AAAA;AACX;AAEJ;AAUA,SAAS,SAAS,EAAA,EAOA;AAPA,EAAA,IAAA,EAAA,GAAA,EAAA,EAChB;AAAA,IAAA,SAAA;AAAA,IACA,KAAA;AAAA,IACA,IAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GA3DF,GAsDkB,EAAA,EAMb,KAAA,GAAA,SAAA,CANa,EAAA,EAMb;AAAA,IALH,WAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GAAA,CAAA;AAGA,EAAA,uBACE,GAAA;AAAA,IAACA,UAAA,CAAkB,IAAA;AAAA,IAAlB,aAAA,CAAA,cAAA,CAAA;AAAA,MACC,WAAA,EAAU,UAAA;AAAA,MACV,WAAW,EAAA,CAAG,gBAAA,CAAiB,EAAE,IAAA,EAAM,GAAG,SAAS;AAAA,KAAA,EAC/C,KAAA,CAAA,EAHL;AAAA,MAKC,QAAA,kBAAA,GAAA;AAAA,QAACA,UAAA,CAAkB,SAAA;AAAA,QAAlB;AAAA,UACC,WAAA,EAAU,oBAAA;AAAA,UACV,WAAW,EAAA,CAAG,KAAA,EAAO,kBAAkB,EAAE,OAAA,EAAS,CAAC,CAAA;AAAA,UACnD,OAAO,EAAE,SAAA,EAAW,eAAe,GAAA,IAAO,KAAA,IAAS,EAAE,CAAA,EAAA,CAAA;AAAK;AAAA;AAC5D,KAAA;AAAA,GACF;AAEJ","file":"chunk-GDPUWRNH.js","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { Progress as ProgressPrimitive } from \"radix-ui\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* ─── Track variants ─── */\n\nconst progressVariants = cva(\n \"relative w-full overflow-hidden rounded-full bg-neutral-input\",\n {\n variants: {\n size: {\n xs: \"h-1\",\n sm: \"h-1.5\",\n default: \"h-2\",\n lg: \"h-3\",\n },\n },\n defaultVariants: {\n size: \"default\",\n },\n }\n)\n\n/* ─── Indicator variants ─── */\n\nconst indicatorVariants = cva(\n \"h-full w-full flex-1 rounded-full transition-all\",\n {\n variants: {\n variant: {\n default: \"bg-primary\",\n secondary: \"bg-secondary\",\n destructive: \"bg-destructive\",\n muted: \"bg-muted-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nexport interface ProgressProps\n extends Omit<React.ComponentProps<typeof ProgressPrimitive.Root>, \"children\">,\n VariantProps<typeof progressVariants>,\n VariantProps<typeof indicatorVariants> {\n /** Classe de tema aplicada apenas no indicator (ex: \"theme-class\") */\n theme?: string\n}\n\nfunction Progress({\n className,\n value,\n size,\n variant,\n theme,\n ...props\n}: ProgressProps) {\n return (\n <ProgressPrimitive.Root\n data-slot=\"progress\"\n className={cn(progressVariants({ size }), className)}\n {...props}\n >\n <ProgressPrimitive.Indicator\n data-slot=\"progress-indicator\"\n className={cn(theme, indicatorVariants({ variant }))}\n style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\n />\n </ProgressPrimitive.Root>\n )\n}\n\nexport { Progress, progressVariants, indicatorVariants }\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/ui/circular-progress.tsx"],"names":[],"mappings":"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","file":"chunk-KNJTTOAD.js","sourcesContent":["import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* ─── Size config ─── */\n\nconst SIZE_CONFIG = {\n xs: { px: 48, stroke: 4, fontClass: \"text-sm font-semibold\" },\n sm: { px: 64, stroke: 5, fontClass: \"text-base font-semibold\" },\n default: { px: 80, stroke: 6, fontClass: \"text-2xl font-semibold\" },\n lg: { px: 120, stroke: 8, fontClass: \"text-3xl font-semibold\" },\n} as const\n\nconst circularProgressVariants = cva(\"relative inline-flex shrink-0\", {\n variants: {\n size: {\n xs: \"size-12\",\n sm: \"size-16\",\n default: \"size-20\",\n lg: \"size-30\",\n },\n },\n defaultVariants: {\n size: \"default\",\n },\n})\n\n/* ─── Auto-theme thresholds ─── */\n\nfunction getAutoTheme(value: number): string {\n if (value < 34) return \"theme-critical\"\n if (value < 67) return \"theme-warning\"\n return \"theme-positive\"\n}\n\nexport interface CircularProgressProps\n extends Omit<React.ComponentProps<\"div\">, \"children\">,\n VariantProps<typeof circularProgressVariants> {\n /** Valor de 0 a 100 (clamped) */\n value: number\n /** Classe de tema fixa (ex: \"theme-brand\", \"theme-class\"). Tem precedencia sobre autoTheme. */\n theme?: string\n /** Se true, escolhe o tema automaticamente: 0–33 critical, 34–66 warning, 67–100 positive. */\n autoTheme?: boolean\n /** Mostrar label central com a porcentagem (default true) */\n showLabel?: boolean\n /** Label customizado — sobrescreve `${value}%` */\n label?: string\n}\n\nfunction CircularProgress({\n value,\n size = \"default\",\n theme,\n autoTheme = false,\n showLabel = true,\n label,\n className,\n ...props\n}: CircularProgressProps) {\n const clamped = Math.min(100, Math.max(0, value))\n const config = SIZE_CONFIG[size ?? \"default\"]\n const { px, stroke, fontClass } = config\n\n const radius = (px - stroke) / 2\n const circumference = 2 * Math.PI * radius\n const dash = (clamped / 100) * circumference\n\n const resolvedTheme = theme ?? (autoTheme ? getAutoTheme(clamped) : undefined)\n const displayLabel = label ?? `${Math.round(clamped)}%`\n\n return (\n <div\n data-slot=\"circular-progress\"\n role=\"progressbar\"\n aria-valuenow={clamped}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={!showLabel && !label ? `Progress: ${Math.round(clamped)}%` : undefined}\n className={cn(circularProgressVariants({ size }), resolvedTheme, className)}\n style={{ width: px, height: px }}\n {...props}\n >\n {/* Inner pastel fill */}\n <div\n className={cn(\n \"absolute rounded-full\",\n resolvedTheme ? \"bg-accent\" : \"bg-neutral-input/40\"\n )}\n style={{ inset: stroke }}\n />\n\n {/* Progress arcs */}\n <svg\n className=\"absolute inset-0 size-full -rotate-90\"\n viewBox={`0 0 ${px} ${px}`}\n aria-hidden=\"true\"\n >\n <circle\n cx={px / 2}\n cy={px / 2}\n r={radius}\n fill=\"none\"\n strokeWidth={stroke}\n className={cn(resolvedTheme ? \"stroke-muted\" : \"stroke-neutral-input\")}\n />\n <circle\n cx={px / 2}\n cy={px / 2}\n r={radius}\n fill=\"none\"\n strokeWidth={stroke}\n strokeLinecap=\"round\"\n strokeDasharray={`${dash} ${circumference}`}\n className={cn(\"transition-[stroke-dasharray] duration-500\", resolvedTheme ? \"stroke-primary\" : \"stroke-neutral-foreground\")}\n />\n </svg>\n\n {/* Center label */}\n {showLabel && (\n <span\n className={cn(\n \"relative z-10 flex size-full items-center justify-center text-neutral-foreground\",\n fontClass\n )}\n >\n {displayLabel}\n </span>\n )}\n </div>\n )\n}\n\nexport { CircularProgress, circularProgressVariants }\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/ui/chat-message.tsx"],"names":["_a","waveform"],"mappings":"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","file":"chunk-VZ2GYSNK.js","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Play, Pause, User } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Avatar, AvatarImage, AvatarFallback } from \"@/components/ui/avatar\"\nimport { LikeDislike, type LikeDislikeValue } from \"@/components/ui/like-dislike\"\nimport { Ai, CycleIcon } from \"@/components/icons\"\n\n/* ─── Container variants ──────────────────────────────────────── */\n\nconst chatMessageVariants = cva(\"flex w-full text-sm\", {\n variants: {\n persona: {\n ai: \"justify-start\",\n user: \"justify-end\",\n system: \"justify-center\",\n },\n },\n defaultVariants: {\n persona: \"ai\",\n },\n})\n\n/* ─── Types ───────────────────────────────────────────────────── */\n\nexport interface ChatMessageProps\n extends Omit<React.ComponentProps<\"div\">, \"content\">,\n VariantProps<typeof chatMessageVariants> {\n /** Quem enviou: AI (assistente), user (aluno), system (mensagem do sistema) */\n persona: \"ai\" | \"user\" | \"system\"\n /** Texto da mensagem. Convencao do produto:\n * - Em `persona=\"ai\"` com `audioSrc`, o texto e o roteiro/legenda do audio TTS.\n * - Em `persona=\"user\"` com `audioSrc`, o texto e a transcricao do audio (gerada por IA).\n * Em ambos os casos, aparece em bubble separada acima do audio. */\n text?: string\n /** URL do audio — renderiza AudioPlayer dentro do bubble. Convencao do produto:\n * toda msg da IA tem `text` + `audioSrc` (TTS) e toda msg do user com audio tem\n * `text` (transcricao). Garante acessibilidade (leitura + escuta) e busca no historico. */\n audioSrc?: string\n /** Avatar do user (so usado em persona=\"user\") */\n avatar?: string\n /** Nome do user para fallback do avatar */\n author?: string\n /** Mostrar like/dislike inline (so faz sentido em persona=\"ai\") */\n showFeedback?: boolean\n /** Valor controlado do feedback */\n feedbackValue?: LikeDislikeValue\n /** Callback quando feedback muda */\n onFeedbackChange?: (value: LikeDislikeValue) => void\n /** Estado de loading: mostra typing indicator (\"...\") */\n loading?: boolean\n /**\n * Classe de tema da bolha do user (bubble, audio e badge de velocidade herdam\n * `bg-accent`/`bg-primary` dela). Default `\"theme-positive\"` — verde, leitura\n * familiar de \"mensagem enviada\" (WhatsApp); nao colide com critical nem disputa\n * com os botoes brand. So tem efeito em `persona=\"user\"`. Ex.: `theme=\"theme-class\"`.\n */\n theme?: string\n}\n\n/* ─── Helpers ─────────────────────────────────────────────────── */\n\nfunction getInitials(name?: string): string {\n if (!name) return \"\"\n return name\n .split(\" \")\n .slice(0, 2)\n .map((w) => w[0])\n .join(\"\")\n .toUpperCase()\n}\n\n/* ─── Typing indicator ────────────────────────────────────────── */\n\nfunction TypingDots() {\n return (\n <span\n className=\"inline-flex items-center gap-1\"\n aria-label=\"Digitando...\"\n role=\"status\"\n >\n <span className=\"size-1.5 rounded-full bg-current opacity-40 animate-bounce [animation-delay:-0.3s]\" />\n <span className=\"size-1.5 rounded-full bg-current opacity-40 animate-bounce [animation-delay:-0.15s]\" />\n <span className=\"size-1.5 rounded-full bg-current opacity-40 animate-bounce\" />\n </span>\n )\n}\n\n/* ─── ChatAudio (compact inline audio player com waveform real) ── */\n\n/** Fallback estatico (valores 0-1) — usado enquanto peaks reais carregam ou quando audio nao pode ser analisado (CORS/decode error) */\nconst STATIC_FALLBACK_PEAKS = [\n 2, 2, 2, 2, 8, 24, 18, 24, 8, 18, 24, 24, 18, 24, 18, 18, 24, 24, 32, 24,\n 24, 32, 24, 32, 32, 24, 18, 24, 24, 18, 24, 18, 18, 24, 24, 24, 24, 24, 32, 24,\n 32, 18, 24, 18, 24, 18, 24, 18, 18, 24, 24, 24, 24, 24, 32, 24, 32, 18, 24, 18,\n 24, 8, 18, 24, 8, 4, 2, 2, 2, 2, 4, 8, 24, 24, 18, 24, 18, 18, 24, 24,\n 32, 24, 24, 32, 24, 32, 32, 24, 18, 24, 24, 18, 24, 8, 18, 24, 8, 2, 2, 4,\n].map((h) => h / 32)\n\nconst MIN_BAR_HEIGHT = 2 // px (silencio)\nconst MAX_BAR_HEIGHT = 32 // px (pico maximo)\nconst SPEED_OPTIONS = [1, 1.25, 1.5, 2, 0.75]\n\n/** Cache modular para evitar re-computar peaks do mesmo audio em multiplas instancias */\nconst peaksCache = new Map<string, number[]>()\n\n/**\n * Calcula picos (amplitude maxima) de um audio dividido em N buckets.\n * Usa Web Audio API (decodeAudioData) — sem dependencias externas.\n * Retorna array de valores 0-1 (normalizado pelo pico maximo).\n */\nasync function calculatePeaks(audioUrl: string, barCount: number): Promise<number[]> {\n const response = await fetch(audioUrl)\n const arrayBuffer = await response.arrayBuffer()\n\n const AudioContextClass =\n window.AudioContext ||\n (window as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext\n const audioContext = new AudioContextClass()\n const audioBuffer = await audioContext.decodeAudioData(arrayBuffer)\n\n const channelData = audioBuffer.getChannelData(0) // mono ou canal esquerdo\n const samplesPerBar = Math.floor(channelData.length / barCount)\n const peaks: number[] = []\n\n for (let i = 0; i < barCount; i++) {\n const start = i * samplesPerBar\n const end = Math.min(start + samplesPerBar, channelData.length)\n let max = 0\n for (let j = start; j < end; j++) {\n const absSample = Math.abs(channelData[j])\n if (absSample > max) max = absSample\n }\n peaks.push(max)\n }\n\n // Normaliza para 0-1 relativo ao pico maximo do clip\n const maxPeak = Math.max(...peaks, 0.01)\n\n // Fecha o AudioContext (libera recursos)\n void audioContext.close()\n\n return peaks.map((p) => p / maxPeak)\n}\n\n/** Wrapper com cache */\nasync function getPeaks(url: string, barCount: number): Promise<number[]> {\n const cacheKey = `${url}|${barCount}`\n const cached = peaksCache.get(cacheKey)\n if (cached) return cached\n const peaks = await calculatePeaks(url, barCount)\n peaksCache.set(cacheKey, peaks)\n return peaks\n}\n\nfunction formatAudioTime(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\nexport interface ChatAudioProps extends React.ComponentProps<\"div\"> {\n /** URL do audio */\n src: string\n /**\n * Variante visual:\n * - `neutral`: container `bg-muted` (cinza claro) — usado em AI messages\n * - `brand`: container `bg-accent` tematizado — usado em User messages.\n * A cor vem do wrapper `.theme-*` do componente pai (ChatMessage aplica\n * `theme-positive` por default; nome mantido por retrocompatibilidade)\n */\n variant?: \"neutral\" | \"brand\"\n /**\n * Array de picos pre-calculados (valores 0-1). Quando fornecido, o componente\n * usa direto sem analisar o audio. Util para SSR, performance ou audios sem CORS.\n * Se nao fornecido, o componente analisa o audio automaticamente via Web Audio API.\n */\n peaks?: number[]\n /**\n * Numero de barras no waveform (default: 60).\n * Ignorado se `peaks` for fornecido (usa o length do array).\n * Reduzido de 100 → 60 para barras nao ficarem finas demais em containers menores.\n */\n barCount?: number\n}\n\nfunction ChatAudio({\n src,\n variant = \"neutral\",\n peaks: providedPeaks,\n barCount = 60,\n className,\n ...props\n}: ChatAudioProps) {\n const audioRef = React.useRef<HTMLAudioElement>(null)\n const [isPlaying, setIsPlaying] = React.useState(false)\n const [currentTime, setCurrentTime] = React.useState(0)\n const [duration, setDuration] = React.useState(0)\n const [speed, setSpeed] = React.useState(1)\n const [computedPeaks, setComputedPeaks] = React.useState<number[] | null>(null)\n\n /** Auto-computa peaks se nao foram fornecidos */\n React.useEffect(() => {\n if (providedPeaks) return // consumer ja forneceu, skip analise\n let cancelled = false\n getPeaks(src, barCount)\n .then((p) => {\n if (!cancelled) setComputedPeaks(p)\n })\n .catch((err) => {\n /* fallback silencioso: mantem null, usa fallback estatico.\n Causa comum: CORS (audio source nao tem Access-Control-Allow-Origin).\n Log apenas em dev para nao poluir prod. */\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n `[ChatAudio] Failed to analyze waveform for \"${src}\". ` +\n `Falling back to static waveform. ` +\n `Reason: ${err instanceof Error ? err.message : String(err)}. ` +\n `Audio source likely missing CORS headers (Access-Control-Allow-Origin).`\n )\n }\n })\n return () => {\n cancelled = true\n }\n }, [src, providedPeaks, barCount])\n\n /** Fallback estatico ajustado para o barCount atual (evita troca visual brusca quando peaks reais carregam) */\n const fallbackPeaks = React.useMemo(() => {\n return Array.from(\n { length: barCount },\n (_, i) => STATIC_FALLBACK_PEAKS[i % STATIC_FALLBACK_PEAKS.length]\n )\n }, [barCount])\n\n /** Resolve peaks: provided > computed > fallback (ajustado por barCount) */\n const peaks = providedPeaks ?? computedPeaks ?? fallbackPeaks\n\n /** Seta duracao apenas se valor for finito e positivo (evita Infinity/NaN) */\n const setDurationSafe = React.useCallback((value: number) => {\n if (Number.isFinite(value) && value > 0) {\n setDuration((prev) => (prev !== value ? value : prev))\n }\n }, [])\n\n /** Subscribe a multiplos eventos para garantir captura da duracao\n * (alguns audio sources nao disparam loadedmetadata, so durationchange/canplay) */\n React.useEffect(() => {\n const audio = audioRef.current\n if (!audio) return\n\n const handleDuration = () => setDurationSafe(audio.duration)\n handleDuration() // checa se ja esta carregado\n\n audio.addEventListener(\"loadedmetadata\", handleDuration)\n audio.addEventListener(\"durationchange\", handleDuration)\n audio.addEventListener(\"canplay\", handleDuration)\n return () => {\n audio.removeEventListener(\"loadedmetadata\", handleDuration)\n audio.removeEventListener(\"durationchange\", handleDuration)\n audio.removeEventListener(\"canplay\", handleDuration)\n }\n }, [src, setDurationSafe])\n\n /** Progresso fluido durante o playback.\n * `timeupdate` dispara ~4x/s (250ms) — a bolinha pulava em stop motion.\n * Enquanto toca, lemos `currentTime` a cada frame via rAF (60fps).\n * `timeupdate` continua como fallback (pause, seek, ended). */\n React.useEffect(() => {\n if (!isPlaying) return\n const audio = audioRef.current\n if (!audio) return\n let rafId = 0\n const tick = () => {\n setCurrentTime(audio.currentTime)\n rafId = requestAnimationFrame(tick)\n }\n rafId = requestAnimationFrame(tick)\n return () => cancelAnimationFrame(rafId)\n }, [isPlaying])\n\n const togglePlay = () => {\n const audio = audioRef.current\n if (!audio) return\n if (audio.paused) {\n audio.play().catch(() => {})\n } else {\n audio.pause()\n }\n }\n\n const cycleSpeed = () => {\n const idx = SPEED_OPTIONS.indexOf(speed)\n const next = SPEED_OPTIONS[(idx + 1) % SPEED_OPTIONS.length] ?? 1\n setSpeed(next)\n if (audioRef.current) audioRef.current.playbackRate = next\n }\n\n /* ─── Seek/drag via pointer no waveform ───────────────────── */\n\n const waveformRef = React.useRef<HTMLDivElement>(null)\n const isDraggingRef = React.useRef(false)\n\n /** Converte clientX (event) em time do audio, baseado na largura do container do waveform */\n const seekToClientX = React.useCallback(\n (clientX: number) => {\n const audio = audioRef.current\n const waveform = waveformRef.current\n if (!audio || !waveform || !duration) return\n const rect = waveform.getBoundingClientRect()\n const x = clientX - rect.left\n const newProgress = Math.max(0, Math.min(x / rect.width, 1))\n audio.currentTime = newProgress * duration\n },\n [duration]\n )\n\n const handlePointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!duration) return\n isDraggingRef.current = true\n e.currentTarget.setPointerCapture(e.pointerId)\n seekToClientX(e.clientX)\n }\n\n const handlePointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!isDraggingRef.current) return\n seekToClientX(e.clientX)\n }\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 const progress = duration > 0 ? currentTime / duration : 0\n const displayTime = formatAudioTime(currentTime)\n\n /* Waveform JSX — reusado entre layouts mobile (top) e desktop (inline).\n Barras com largura FIXA de 2px (matches Figma) distribuidas via justify-between\n para preencher toda a largura do container — gap entre barras se torna fluido\n conforme o waveform expande. Garante espacamento simetrico com time (esquerda)\n e speed badge (direita). Pointer events permitem clicar/arrastar para seek. */\n const waveform = (\n <div\n ref={waveformRef}\n className=\"flex-1 relative h-8 min-w-0 touch-none cursor-pointer select-none\"\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n role=\"slider\"\n aria-label=\"Posicao do audio\"\n aria-valuemin={0}\n aria-valuemax={Math.round(duration)}\n aria-valuenow={Math.round(currentTime)}\n >\n <div className=\"absolute inset-0 flex items-center justify-between\">\n {peaks.map((peak, i) => {\n const isPlayed = i / peaks.length <= progress\n const height = Math.max(\n MIN_BAR_HEIGHT,\n Math.round(peak * MAX_BAR_HEIGHT)\n )\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 {/* Bolinha verde — posicionada em PORCENTAGEM da largura do container,\n alinhada com a distribuicao fluida das barras. */}\n {duration > 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] pointer-events-none shadow-md\"\n style={{ left: `${progress * 100}%` }}\n aria-hidden=\"true\"\n />\n )}\n </div>\n )\n\n /* Time display — reusado entre layouts */\n const timeDisplay = (\n <span className=\"shrink-0 text-sm text-neutral-ring tabular-nums\">\n {displayTime}\n </span>\n )\n\n /* Speed badge — reusado entre layouts */\n const speedBadge = (\n <button\n type=\"button\"\n onClick={cycleSpeed}\n className={cn(\n \"shrink-0 h-[26px] min-w-16 rounded-full text-sm font-medium px-2 transition-opacity hover:opacity-80\",\n variant === \"brand\"\n ? \"bg-muted text-muted-foreground\"\n : \"bg-background text-neutral-muted-foreground\"\n )}\n aria-label={`Velocidade ${speed}x. Clique para alternar.`}\n >\n {speed === 1 ? \"1x\" : `${speed}x`}\n </button>\n )\n\n return (\n <div\n data-slot=\"chat-audio\"\n className={cn(\n \"rounded-2xl w-full max-w-md flex flex-col gap-2 p-3 sm:flex-row sm:items-center sm:gap-2 sm:pl-5 sm:pr-3 sm:py-3\",\n variant === \"brand\" ? \"bg-accent\" : \"bg-muted\",\n className\n )}\n {...props}\n >\n <audio\n ref={audioRef}\n src={src}\n preload=\"metadata\"\n onPlay={() => setIsPlaying(true)}\n onPause={() => setIsPlaying(false)}\n onTimeUpdate={(e) => {\n setCurrentTime(e.currentTarget.currentTime)\n /* Fallback: alguns sources so expoem duration durante o playback */\n setDurationSafe(e.currentTarget.duration)\n }}\n onEnded={() => setIsPlaying(false)}\n />\n\n {/* Mobile top row + Desktop inline row */}\n <div className=\"flex items-center gap-2 flex-1 min-w-0\">\n {/* Play/Pause — icones FILLED */}\n <button\n type=\"button\"\n onClick={togglePlay}\n className=\"shrink-0 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-4\" fill=\"currentColor\" strokeWidth={0} />\n ) : (\n <Play className=\"size-4\" fill=\"currentColor\" strokeWidth={0} />\n )}\n </button>\n\n {/* Time — apenas desktop (no mobile aparece embaixo) */}\n <div className=\"hidden sm:contents\">{timeDisplay}</div>\n\n {waveform}\n\n {/* Speed — apenas desktop (no mobile aparece embaixo) */}\n <div className=\"hidden sm:contents\">{speedBadge}</div>\n </div>\n\n {/* Mobile bottom row: time + speed badge */}\n <div className=\"flex items-center justify-between sm:hidden\">\n {timeDisplay}\n {speedBadge}\n </div>\n </div>\n )\n}\n\nexport { ChatAudio }\n\n/* ─── Component ───────────────────────────────────────────────── */\n\nfunction ChatMessage({\n persona,\n text,\n audioSrc,\n avatar,\n author,\n showFeedback = false,\n feedbackValue,\n onFeedbackChange,\n loading = false,\n theme = \"theme-positive\",\n className,\n ...props\n}: ChatMessageProps) {\n /* System: centered italic */\n if (persona === \"system\") {\n return (\n <div\n data-slot=\"chat-message\"\n data-persona=\"system\"\n className={cn(chatMessageVariants({ persona }), className)}\n {...props}\n >\n <span className=\"text-xs text-muted-foreground italic\">{text}</span>\n </div>\n )\n }\n\n /* AI: badge quadrado (esquerda, apenas desktop) + conteudo empilhado */\n if (persona === \"ai\") {\n return (\n <div\n data-slot=\"chat-message\"\n data-persona=\"ai\"\n className={cn(chatMessageVariants({ persona }), className)}\n {...props}\n >\n <div className=\"flex gap-3 max-w-[85%] sm:max-w-[75%] w-full\">\n {/* AI badge: oculto no mobile, visivel no desktop */}\n <div className=\"hidden sm:flex shrink-0 size-8 rounded-md bg-primary items-center justify-center theme-brand\">\n <span className=\"text-primary-foreground\">\n <Ai size=\"sm\" decorative />\n </span>\n </div>\n <div className=\"flex flex-col gap-2 min-w-0 flex-1\">\n {loading ? (\n /* Loading: dots dentro de bubble cinza (speech bubble shape — top-left reto em todos os breakpoints) */\n <div className=\"self-start inline-flex items-center rounded-2xl rounded-tl-none bg-muted p-5 text-muted-foreground\">\n <TypingDots />\n </div>\n ) : (\n <>\n {text && (\n /* Text bubble: bg-muted sempre, speech bubble shape (tl-none) em todos os breakpoints */\n <div className=\"rounded-2xl rounded-tl-none bg-muted p-5\">\n <p className=\"text-base leading-6 text-neutral-foreground break-words\">{text}</p>\n </div>\n )}\n {audioSrc && <ChatAudio src={audioSrc} variant=\"neutral\" />}\n {showFeedback && (\n <LikeDislike\n size=\"xs\"\n value={feedbackValue}\n onValueChange={onFeedbackChange}\n />\n )}\n </>\n )}\n </div>\n </div>\n </div>\n )\n }\n\n /* User: bubble (direita) + avatar (apenas desktop, alinhado ao topo) */\n return (\n <div\n data-slot=\"chat-message\"\n data-persona=\"user\"\n className={cn(chatMessageVariants({ persona }), className)}\n {...props}\n >\n <div className=\"flex items-start gap-3 max-w-[85%] sm:max-w-[75%] w-full justify-end\">\n <div className={cn(\"flex flex-col gap-2 min-w-0 items-end flex-1\", theme)}>\n {loading ? (\n /* Loading: dots dentro de bubble tematizada (speech bubble shape — top-right reto em todos os breakpoints) */\n <div className=\"inline-flex items-center rounded-2xl rounded-tr-none bg-accent p-5 text-neutral-muted-foreground\">\n <TypingDots />\n </div>\n ) : (\n <>\n {text && (\n /* Text bubble: speech bubble shape (top-right reto) em todos os breakpoints.\n text-neutral-foreground = preto neutro fixo, nao muda com o tema */\n <div className=\"rounded-2xl rounded-tr-none bg-accent p-5\">\n <p className=\"text-base leading-6 text-neutral-foreground break-words\">{text}</p>\n </div>\n )}\n {audioSrc && <ChatAudio src={audioSrc} variant=\"brand\" />}\n </>\n )}\n </div>\n {/* Avatar: 40x40 rounded-lg, oculto no mobile, alinhado ao topo */}\n <Avatar size=\"lg\" className=\"hidden sm:flex shrink-0 rounded-lg\">\n {avatar && (\n <AvatarImage src={avatar} alt={author ?? \"User\"} className=\"rounded-lg\" />\n )}\n <AvatarFallback className=\"rounded-lg bg-muted text-muted-foreground text-sm\">\n {author ? (\n getInitials(author)\n ) : (\n <CycleIcon icon={User} size=\"sm\" decorative />\n )}\n </AvatarFallback>\n </Avatar>\n </div>\n </div>\n )\n}\n\nexport { ChatMessage, chatMessageVariants }\n"]}
|