@fluencypassdevs/cycle 1.27.0 → 1.28.0
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 +2949 -0
- package/bin/mcp.mjs +3 -1466
- package/dist/{chunk-EAVNA2RW.js → chunk-CLMO3IRS.js} +9 -42
- package/dist/chunk-CLMO3IRS.js.map +1 -0
- package/dist/{chunk-TK67WF35.js → chunk-JPEQ4BYK.js} +2 -2
- package/dist/chunk-JPEQ4BYK.js.map +1 -0
- package/dist/{chunk-VUVC2NAK.js → chunk-KSEDDFGG.js} +19 -5
- package/dist/chunk-KSEDDFGG.js.map +1 -0
- package/dist/{chunk-R33NNSFO.js → chunk-QXZRH3HU.js} +3 -3
- package/dist/{chunk-R33NNSFO.js.map → chunk-QXZRH3HU.js.map} +1 -1
- package/dist/composites/chat-thread.d.ts +3 -1
- package/dist/composites/chat-thread.js +3 -3
- package/dist/index.js +4 -4
- package/dist/ui/chat-message.d.ts +11 -3
- package/dist/ui/chat-message.js +1 -1
- package/dist/ui/message-bar.d.ts +4 -0
- package/dist/ui/message-bar.js +1 -1
- package/dist/ui/video-player.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-EAVNA2RW.js.map +0 -1
- package/dist/chunk-TK67WF35.js.map +0 -1
- package/dist/chunk-VUVC2NAK.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/ui/video-player.tsx"],"names":["forwardRef","CaptionsIcon","VideoPlayer","_a"],"mappings":"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","file":"chunk-R33NNSFO.js","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport {\n MediaPlayer,\n MediaProvider,\n Poster,\n Controls,\n Gesture,\n TimeSlider,\n VolumeSlider,\n Time,\n PlayButton,\n MuteButton,\n FullscreenButton,\n CaptionButton,\n PIPButton,\n SeekButton,\n Captions,\n Spinner,\n Track,\n Tooltip,\n Menu,\n LiveButton,\n MediaAnnouncer,\n useMediaState,\n useMediaRemote,\n useVideoQualityOptions,\n useCaptionOptions,\n type MediaPlayerInstance,\n type PlayerSrc,\n} from \"@vidstack/react\"\n// Desktop-only controls use the above. Mobile uses DefaultVideoLayout below.\nimport {\n DefaultVideoLayout,\n defaultLayoutIcons,\n} from \"@vidstack/react/player/layouts/default\"\nimport \"@vidstack/react/player/styles/base.css\"\nimport \"@vidstack/react/player/styles/default/theme.css\"\nimport \"@vidstack/react/player/styles/default/layouts/video.css\"\nimport {\n Play,\n Pause,\n Volume2,\n VolumeX,\n Volume1,\n Maximize,\n Minimize,\n Captions as CaptionsIcon,\n CaptionsOff,\n PictureInPicture2,\n RotateCcw,\n RotateCw,\n Gauge,\n Settings,\n Check,\n} from \"lucide-react\"\nimport { CycleIcon } from \"@/components/icons\"\nimport { cn } from \"@/lib/utils\"\nimport {\n type PlayerLocale,\n type VideoDesktopLabels,\n resolveVideoLabels,\n resolveVidstackTranslations,\n} from \"@/components/ui/player-i18n\"\n\n/* ─── Types ─── */\n\nexport interface CaptionTrack {\n /** URL do arquivo VTT de legenda */\n src: string\n /** Codigo do idioma (BCP 47, ex: \"pt-BR\", \"en\", \"es\") */\n language: string\n /** Label exibido no seletor de legendas (ex: \"Portugues\", \"English\") */\n label: string\n /** Se true, esta faixa sera ativada por padrao */\n default?: boolean\n}\n\nexport interface VideoPlayerRef {\n play(): void\n pause(): void\n readonly currentTime: number\n readonly duration: number\n}\n\n/** @deprecated Use `Partial<VideoDesktopLabels>` — kept for backward compatibility */\nexport type VideoPlayerLabels = Partial<VideoDesktopLabels>\n\n/** Fonte de video: URL string ou objeto com MIME type explicito.\n O Vidstack infere o tipo pela EXTENSAO no path da URL — quando ela nao\n existe (blob: de arquivo local, endpoints sem extensao), o provider\n nao carrega. Nesses casos, passar { src, type } (ex: type do File.type\n local ou o ContentType salvo no upload). */\nexport type VideoPlayerSrc = string | { src: string; type: string }\n\n/** blob: → \"video/object\" (unica rota que o isVideoSrc do Vidstack aceita\n para blob). Demais objetos passam direto — cast porque o runtime aceita\n mais MIME types que a uniao VideoMimeType dos tipos. */\nfunction resolveVideoSrc(src: VideoPlayerSrc): PlayerSrc {\n if (typeof src === \"string\") return src\n if (src.src.startsWith(\"blob:\")) return { src: src.src, type: \"video/object\" }\n return src as PlayerSrc\n}\n\nexport interface VideoPlayerProps {\n /** Fonte do video: URL (mp4, webm, m3u8 para HLS) ou { src, type } para blob:/URL sem extensao */\n src: VideoPlayerSrc\n /** URL da imagem de poster */\n poster?: string\n /** Alt text do poster */\n posterAlt?: string\n /** URL do arquivo de thumbnails (VTT sprite sheet) */\n thumbnails?: string\n /** URL do arquivo VTT de chapters (marcadores de seção no timeline) */\n chapters?: string\n /** Faixas de legenda/subtitles (VTT). Suporta multiplos idiomas. */\n captions?: CaptionTrack[]\n /** Exibir spinner durante buffering (default: true) */\n showBuffering?: boolean\n /** Habilitar anuncios de acessibilidade para screen readers (default: true) */\n announcer?: boolean\n /** Iniciar automaticamente */\n autoPlay?: boolean\n /** Iniciar mutado */\n muted?: boolean\n /** Repetir ao terminar */\n loop?: boolean\n /** Tempo inicial em segundos — usado para retomar de onde o usuario parou (resume position) */\n startTime?: number\n /** Idioma dos controles (default: \"pt-BR\"). 13 locales pre-configurados. */\n locale?: PlayerLocale\n /** Overrides pontuais de labels — aplicados em cima do locale selecionado */\n labels?: VideoPlayerLabels\n /** Callback com progresso do video (currentTime em segundos, duration em segundos) */\n onTimeUpdate?: (currentTime: number, duration: number) => void\n /** Callback disparado quando o video termina */\n onEnded?: () => void\n className?: string\n}\n\n/* ─── Labels context ─── */\n\nconst VideoLabelsContext = React.createContext<VideoDesktopLabels>(\n resolveVideoLabels(\"pt-BR\")\n)\nfunction useVideoLabels() {\n return React.useContext(VideoLabelsContext)\n}\n\n/* ─── Shared styles ─── */\n\nconst controlBtnClass =\n \"group inline-flex size-9 cursor-pointer items-center justify-center rounded-md text-white outline-none transition-colors hover:bg-white/20 focus-visible:ring-2 focus-visible:ring-white/50\"\n\n/* SEM `animate-in`/`animate-out` aqui — de propósito.\n O Popper do Vidstack esconde o tooltip assim: `if (hasAnimation(content))`\n (= `getComputedStyle(el).animationName !== \"none\"`) ele NÃO aplica\n `display: none` na hora; espera um evento `animationend`. As utilities\n `animate-in` deixam `animation-name: enter` permanente no elemento, e o\n par `data-[state=closed]:animate-out` é convenção do Radix — o Vidstack\n marca `data-visible`, nunca `data-state`. Resultado: depois que a animação\n de entrada termina, nenhum `animationend` novo dispara, o `display: none`\n nunca chega e o tooltip fica congelado na tela (ClickUp 86ajtpear).\n Transition não entra no `animationName`, então o hide volta a ser síncrono. */\nconst tooltipClass =\n \"z-50 rounded bg-black/90 px-2 py-1 text-xs font-medium text-white shadow-lg transition-opacity duration-150\"\n\n/** Wraps a control button with a Vidstack tooltip. Desktop only (no hover on mobile). */\nfunction ControlTooltip({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <Tooltip.Root>\n <Tooltip.Trigger asChild>{children}</Tooltip.Trigger>\n <Tooltip.Content className={tooltipClass} placement=\"top\">\n {label}\n </Tooltip.Content>\n </Tooltip.Root>\n )\n}\n\n/** Play, Pause e Volume usam icones filled (solid) no player — igual YouTube */\nconst filledIconClass = \"text-white fill-current !stroke-transparent\"\n\n/* ─── Sub-components (controles customizados) ─── */\n\nfunction PlayOverlay() {\n const isPaused = useMediaState(\"paused\")\n const hasStarted = useMediaState(\"started\")\n\n if (!isPaused && hasStarted) return null\n\n return (\n <PlayButton className=\"absolute inset-0 z-10 flex cursor-pointer items-center justify-center bg-black/30 transition-opacity\">\n <div className=\"flex size-16 items-center justify-center rounded-full bg-white/20 backdrop-blur-sm transition-transform hover:scale-110\">\n <CycleIcon icon={Play} size=\"lg\" decorative className={cn(filledIconClass, \"ml-1\")} />\n </div>\n </PlayButton>\n )\n}\n\nfunction PlayControl() {\n const isPaused = useMediaState(\"paused\")\n const l = useVideoLabels()\n return (\n <ControlTooltip label={isPaused ? l.play : l.pause}>\n <PlayButton className={controlBtnClass}>\n {isPaused ? (\n <CycleIcon icon={Play} size=\"sm\" decorative className={filledIconClass} />\n ) : (\n <CycleIcon icon={Pause} size=\"sm\" decorative className={filledIconClass} />\n )}\n </PlayButton>\n </ControlTooltip>\n )\n}\n\nfunction SeekBackwardControl() {\n const l = useVideoLabels()\n return (\n <ControlTooltip label={l.seekBackward}>\n <SeekButton className={controlBtnClass} seconds={-10}>\n <CycleIcon icon={RotateCcw} size=\"sm\" decorative className=\"text-white\" />\n </SeekButton>\n </ControlTooltip>\n )\n}\n\nfunction SeekForwardControl() {\n const l = useVideoLabels()\n return (\n <ControlTooltip label={l.seekForward}>\n <SeekButton className={controlBtnClass} seconds={10}>\n <CycleIcon icon={RotateCw} size=\"sm\" decorative className=\"text-white\" />\n </SeekButton>\n </ControlTooltip>\n )\n}\n\nfunction MuteControl() {\n const volume = useMediaState(\"volume\")\n const isMuted = useMediaState(\"muted\")\n const l = useVideoLabels()\n\n const Icon = isMuted || volume === 0 ? VolumeX : volume < 0.5 ? Volume1 : Volume2\n const label = isMuted || volume === 0 ? l.unmute : l.mute\n\n return (\n <ControlTooltip label={label}>\n <MuteButton className={controlBtnClass}>\n <CycleIcon icon={Icon} size=\"sm\" decorative className={filledIconClass} />\n </MuteButton>\n </ControlTooltip>\n )\n}\n\nfunction VolumeControl() {\n return (\n <VolumeSlider.Root className=\"group relative hidden h-9 w-20 shrink-0 cursor-pointer touch-none select-none items-center outline-none @[480px]:inline-flex\">\n <VolumeSlider.Track className=\"relative h-[4px] w-full rounded-full bg-white/30\">\n <VolumeSlider.TrackFill className=\"absolute h-full w-[var(--slider-fill)] rounded-full bg-white\" />\n </VolumeSlider.Track>\n <VolumeSlider.Thumb className=\"absolute left-[var(--slider-fill)] top-1/2 size-3 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white opacity-0 transition-opacity group-data-[active]:opacity-100 group-data-[dragging]:opacity-100\" />\n </VolumeSlider.Root>\n )\n}\n\nfunction BufferingIndicator() {\n return (\n <div className=\"pointer-events-none absolute inset-0 z-[35] flex items-center justify-center media-buffering:opacity-100 media-can-play:opacity-0 opacity-0 transition-opacity duration-300\">\n <Spinner.Root className=\"size-16 text-white\" size={64}>\n <Spinner.Track className=\"opacity-25\" width={4} />\n <Spinner.TrackFill className=\"opacity-75\" width={4} />\n </Spinner.Root>\n </div>\n )\n}\n\nfunction SeekBar({ thumbnails, chapters }: { thumbnails?: string; chapters?: boolean }) {\n const trackContent = (\n <>\n <TimeSlider.Track className=\"relative h-[4px] w-full rounded-full bg-white/30\">\n <TimeSlider.Progress className=\"absolute h-full w-[var(--slider-progress)] rounded-full bg-white/50\" />\n <TimeSlider.TrackFill className=\"absolute h-full w-[var(--slider-fill)] rounded-full bg-white\" />\n </TimeSlider.Track>\n </>\n )\n\n return (\n <TimeSlider.Root className=\"group relative inline-flex h-9 w-full cursor-pointer touch-none select-none items-center outline-none\">\n {chapters ? (\n <TimeSlider.Chapters className=\"relative flex w-full items-center\">\n {(cues, forwardRef) =>\n cues.map((cue) => (\n <div\n className=\"relative flex h-full w-full items-center last:mr-0 mr-0.5\"\n key={cue.startTime}\n ref={forwardRef}\n >\n {trackContent}\n </div>\n ))\n }\n </TimeSlider.Chapters>\n ) : (\n trackContent\n )}\n\n <TimeSlider.Thumb className=\"absolute left-[var(--slider-fill)] top-1/2 size-3 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white opacity-0 transition-opacity group-data-[active]:opacity-100 group-data-[dragging]:opacity-100\" />\n\n {/* Thumbnail preview on hover */}\n {thumbnails && (\n <TimeSlider.Preview className=\"pointer-events-none flex flex-col items-center gap-1 opacity-0 transition-opacity duration-200 data-[visible]:opacity-100\">\n <TimeSlider.Thumbnail.Root\n src={thumbnails}\n className=\"block h-[var(--thumbnail-height)] max-h-[160px] min-h-[80px] w-[var(--thumbnail-width)] min-w-[120px] max-w-[200px] overflow-hidden rounded-md border-2 border-white bg-black\"\n >\n <TimeSlider.Thumbnail.Img />\n </TimeSlider.Thumbnail.Root>\n {chapters && <TimeSlider.ChapterTitle className=\"text-[11px] text-white/80\" />}\n <TimeSlider.Value className=\"rounded bg-black/80 px-1.5 py-0.5 text-[11px] font-mono text-white\" />\n </TimeSlider.Preview>\n )}\n\n {/* Time preview (no thumbnails) */}\n {!thumbnails && (\n <TimeSlider.Preview className=\"pointer-events-none flex flex-col items-center opacity-0 transition-opacity duration-200 data-[visible]:opacity-100\">\n {chapters && <TimeSlider.ChapterTitle className=\"text-[11px] text-white/80 mb-0.5\" />}\n <TimeSlider.Value className=\"rounded bg-black/80 px-1.5 py-0.5 text-[11px] font-mono text-white\" />\n </TimeSlider.Preview>\n )}\n </TimeSlider.Root>\n )\n}\n\nfunction TimeDisplay() {\n return (\n <div className=\"flex shrink-0 items-center gap-1 text-xs font-mono text-white/80 tabular-nums whitespace-nowrap\">\n <Time type=\"current\" />\n <span>/</span>\n <Time type=\"duration\" />\n </div>\n )\n}\n\nfunction CaptionControl() {\n const track = useMediaState(\"textTrack\")\n const hasCaptions = useMediaState(\"hasCaptions\")\n const options = useCaptionOptions()\n const l = useVideoLabels()\n\n // Single track or none: simple toggle button (native CaptionButton behavior)\n if (options.length <= 2) {\n return (\n <ControlTooltip label={track ? l.captionsOn : l.captionsOff}>\n <CaptionButton className={cn(controlBtnClass, !hasCaptions && \"opacity-50 pointer-events-none\")}>\n {track ? (\n <CycleIcon icon={CaptionsIcon} size=\"sm\" decorative className=\"text-white\" />\n ) : (\n <CycleIcon icon={CaptionsOff} size=\"sm\" decorative className=\"text-white\" />\n )}\n </CaptionButton>\n </ControlTooltip>\n )\n }\n\n // Multiple tracks: menu with language selection (native Vidstack Menu behavior)\n return (\n <Menu.Root>\n <ControlTooltip label={l.captions}>\n <Menu.Button className={controlBtnClass}>\n {track ? (\n <CycleIcon icon={CaptionsIcon} size=\"sm\" decorative className=\"text-white\" />\n ) : (\n <CycleIcon icon={CaptionsOff} size=\"sm\" decorative className=\"text-white\" />\n )}\n </Menu.Button>\n </ControlTooltip>\n\n <Menu.Content\n className=\"absolute bottom-full right-0 z-50 mb-2 min-w-[140px] rounded-lg border border-white/10 bg-black/90 backdrop-blur-md p-1 shadow-xl\"\n placement=\"top\"\n >\n <p className=\"px-3 py-1 text-[11px] font-semibold uppercase tracking-wider text-white/50\">\n {l.captions}\n </p>\n <Menu.RadioGroup value={options.selectedValue}>\n {options.map((option) => (\n <Menu.Radio\n key={option.value}\n value={option.value}\n onSelect={option.select}\n className={cn(\n \"flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-sm text-white/80 transition-colors hover:bg-white/10 hover:text-white cursor-pointer\",\n option.selected && \"text-white font-medium\"\n )}\n >\n <span className=\"size-4 flex items-center justify-center\">\n {option.selected && <CycleIcon icon={Check} size=\"2xs\" decorative className=\"text-white\" />}\n </span>\n <span>{option.label}</span>\n </Menu.Radio>\n ))}\n </Menu.RadioGroup>\n </Menu.Content>\n </Menu.Root>\n )\n}\n\nfunction PIPControl() {\n const isPIP = useMediaState(\"pictureInPicture\")\n const canPIP = useMediaState(\"canPictureInPicture\")\n const l = useVideoLabels()\n\n if (!canPIP) return null\n\n return (\n <ControlTooltip label={isPIP ? l.pipExit : l.pip}>\n <PIPButton className={controlBtnClass}>\n <CycleIcon icon={PictureInPicture2} size=\"sm\" decorative className={cn(\"text-white\", isPIP && \"text-white/100\")} />\n </PIPButton>\n </ControlTooltip>\n )\n}\n\nfunction SpeedControl() {\n const playbackRate = useMediaState(\"playbackRate\")\n const remote = useMediaRemote()\n const [open, setOpen] = React.useState(false)\n const l = useVideoLabels()\n\n const rates = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]\n\n return (\n <div className=\"relative\">\n <ControlTooltip label={l.speed}>\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className={controlBtnClass}\n >\n {playbackRate === 1 ? (\n <CycleIcon icon={Gauge} size=\"sm\" decorative className=\"text-white\" />\n ) : (\n <span className=\"text-xs font-mono font-semibold text-white\">{playbackRate}x</span>\n )}\n </button>\n </ControlTooltip>\n\n {open && (\n <>\n {/* Backdrop to close */}\n <div className=\"fixed inset-0 z-40\" onClick={() => setOpen(false)} />\n\n <div className=\"absolute bottom-full right-0 z-50 mb-2 min-w-[120px] rounded-lg border border-white/10 bg-black/90 backdrop-blur-md p-1 shadow-xl\">\n {rates.map((rate) => (\n <button\n key={rate}\n type=\"button\"\n onClick={() => {\n remote.changePlaybackRate(rate)\n setOpen(false)\n }}\n className={cn(\n \"flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-sm text-white/80 transition-colors hover:bg-white/10 hover:text-white\",\n playbackRate === rate && \"text-white font-medium\"\n )}\n >\n <span className=\"size-4 flex items-center justify-center\">\n {playbackRate === rate && <CycleIcon icon={Check} size=\"2xs\" decorative className=\"text-white\" />}\n </span>\n <span className=\"font-mono\">{rate === 1 ? l.speedNormal : `${rate}x`}</span>\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n )\n}\n\nfunction QualityControl() {\n const options = useVideoQualityOptions({ auto: true, sort: \"descending\" })\n const [open, setOpen] = React.useState(false)\n const l = useVideoLabels()\n\n const currentLabel = options.selectedValue === \"auto\"\n ? `Auto${options.selectedQuality ? ` (${options.selectedQuality.height}p)` : \"\"}`\n : options.selectedQuality\n ? `${options.selectedQuality.height}p`\n : \"Auto\"\n\n if (options.disabled) return null\n\n return (\n <div className=\"relative\">\n <ControlTooltip label={l.quality}>\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className={controlBtnClass}\n >\n <CycleIcon icon={Settings} size=\"sm\" decorative className=\"text-white\" />\n </button>\n </ControlTooltip>\n\n {open && (\n <>\n <div className=\"fixed inset-0 z-40\" onClick={() => setOpen(false)} />\n\n <div className=\"absolute bottom-full right-0 z-50 mb-2 min-w-[140px] rounded-lg border border-white/10 bg-black/90 backdrop-blur-md p-1 shadow-xl\">\n <p className=\"px-3 py-1 text-[11px] font-semibold uppercase tracking-wider text-white/50\">\n {l.qualityMenu}\n </p>\n {options.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => {\n option.select()\n setOpen(false)\n }}\n className={cn(\n \"flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-sm text-white/80 transition-colors hover:bg-white/10 hover:text-white\",\n option.selected && \"text-white font-medium\"\n )}\n >\n <span className=\"size-4 flex items-center justify-center\">\n {option.selected && <CycleIcon icon={Check} size=\"2xs\" decorative className=\"text-white\" />}\n </span>\n <span className=\"font-mono\">{option.label}</span>\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n )\n}\n\nfunction FullscreenControl() {\n const isFullscreen = useMediaState(\"fullscreen\")\n const l = useVideoLabels()\n return (\n <ControlTooltip label={isFullscreen ? l.fullscreenExit : l.fullscreen}>\n <FullscreenButton className={controlBtnClass}>\n {isFullscreen ? (\n <CycleIcon icon={Minimize} size=\"sm\" decorative className=\"text-white\" />\n ) : (\n <CycleIcon icon={Maximize} size=\"sm\" decorative className=\"text-white\" />\n )}\n </FullscreenButton>\n </ControlTooltip>\n )\n}\n\nfunction LiveIndicator() {\n const isLive = useMediaState(\"live\")\n const isLiveEdge = useMediaState(\"liveEdge\")\n const l = useVideoLabels()\n\n if (!isLive) return null\n\n return (\n <LiveButton\n className={cn(\n \"inline-flex cursor-pointer items-center gap-1.5 rounded-md px-2 py-1 text-xs font-semibold uppercase tracking-wider transition-colors\",\n isLiveEdge\n ? \"text-destructive\"\n : \"text-white/60 hover:text-white\"\n )}\n >\n <span\n className={cn(\n \"size-2 rounded-full\",\n isLiveEdge ? \"bg-destructive animate-pulse\" : \"bg-white/40\"\n )}\n />\n {l.live}\n </LiveButton>\n )\n}\n\n\n/* ─── Gesture helpers ─── */\n\ntype SeekDirection = \"backward\" | \"forward\"\n\nconst DOUBLE_TAP_THRESHOLD = 300\n\n/** Double-tap left/right edges to seek ±10s. z-10 so it doesn't block controls (z-20). */\nfunction SeekGestureZone({\n side,\n onSeekFeedback,\n}: {\n side: \"left\" | \"right\"\n onSeekFeedback: (direction: SeekDirection) => void\n}) {\n const remote = useMediaRemote()\n const currentTime = useMediaState(\"currentTime\")\n const lastTapRef = React.useRef(0)\n\n const handlePointerUp = React.useCallback(\n (e: React.PointerEvent) => {\n const now = Date.now()\n const delta = now - lastTapRef.current\n lastTapRef.current = now\n\n if (delta < DOUBLE_TAP_THRESHOLD) {\n e.stopPropagation()\n const seconds = side === \"left\" ? -10 : 10\n remote.seek(currentTime + seconds)\n onSeekFeedback(side === \"left\" ? \"backward\" : \"forward\")\n }\n },\n [remote, currentTime, side, onSeekFeedback]\n )\n\n return (\n <div\n className={cn(\n \"absolute top-0 z-10 block h-full w-1/5\",\n side === \"left\" ? \"left-0\" : \"right-0\"\n )}\n onPointerUp={handlePointerUp}\n />\n )\n}\n\nfunction SeekFeedbackOverlay({\n direction,\n visible,\n seconds,\n}: {\n direction: SeekDirection\n visible: boolean\n seconds: number\n}) {\n const isBackward = direction === \"backward\"\n\n return (\n <div\n className={cn(\n \"pointer-events-none absolute top-0 z-[35] flex h-full w-2/5 items-center transition-opacity duration-200\",\n isBackward ? \"left-0 justify-center\" : \"right-0 justify-center\",\n visible ? \"opacity-100\" : \"opacity-0\"\n )}\n >\n <div\n className={cn(\n \"flex flex-col items-center gap-1 transition-transform duration-300\",\n visible ? \"scale-100\" : \"scale-75\"\n )}\n >\n <div className=\"flex size-12 items-center justify-center rounded-full bg-white/20 backdrop-blur-sm\">\n <CycleIcon\n icon={isBackward ? RotateCcw : RotateCw}\n size=\"sm\"\n decorative\n className=\"text-white\"\n />\n </div>\n <span className=\"text-xs font-semibold text-white drop-shadow-md\">\n {seconds}s\n </span>\n </div>\n </div>\n )\n}\n\n\n/* ─── Hook: detect desktop via pointer capability ─── */\n/* Uses pointer: fine (mouse/trackpad) instead of viewport width.\n This way mobile devices keep the touch-optimized DefaultVideoLayout\n even when fullscreen in landscape exceeds the sm breakpoint. */\n\nfunction useIsDesktop() {\n const [isDesktop, setIsDesktop] = React.useState(false)\n\n React.useEffect(() => {\n const mq = window.matchMedia(\"(pointer: fine)\")\n setIsDesktop(mq.matches)\n const handler = (e: MediaQueryListEvent) => setIsDesktop(e.matches)\n mq.addEventListener(\"change\", handler)\n return () => mq.removeEventListener(\"change\", handler)\n }, [])\n\n return isDesktop\n}\n\n/* ─── Main component ─── */\n\nexport const VideoPlayer = React.forwardRef<VideoPlayerRef, VideoPlayerProps>(\n function VideoPlayer(\n {\n src,\n poster,\n posterAlt = \"\",\n thumbnails,\n chapters,\n captions,\n showBuffering = true,\n announcer = true,\n autoPlay = false,\n muted = false,\n loop = false,\n startTime,\n locale = \"pt-BR\",\n labels,\n onTimeUpdate,\n onEnded,\n className,\n },\n ref\n ) {\n const resolvedLabels = React.useMemo(\n () => resolveVideoLabels(locale, labels),\n [locale, labels]\n )\n const vidstackTranslations = React.useMemo(\n () => resolveVidstackTranslations(locale, labels),\n [locale, labels]\n )\n const player = React.useRef<MediaPlayerInstance>(null)\n const resolvedSrc = React.useMemo(() => resolveVideoSrc(src), [src])\n\n React.useImperativeHandle(ref, () => ({\n play() {\n player.current?.play()\n },\n pause() {\n player.current?.pause()\n },\n get currentTime() {\n return player.current?.currentTime ?? 0\n },\n get duration() {\n return player.current?.duration ?? 0\n },\n }))\n\n const handleTimeUpdate = React.useCallback(\n (detail: { currentTime: number }) => {\n if (onTimeUpdate && player.current) {\n onTimeUpdate(detail.currentTime, player.current.duration)\n }\n },\n [onTimeUpdate]\n )\n\n const handleEnded = React.useCallback(() => {\n onEnded?.()\n }, [onEnded])\n\n // Resume position: seek to startTime once the player is ready\n const hasAppliedStartTime = React.useRef(false)\n const handleCanPlay = React.useCallback(() => {\n if (startTime && startTime > 0 && !hasAppliedStartTime.current && player.current) {\n player.current.currentTime = startTime\n hasAppliedStartTime.current = true\n }\n }, [startTime])\n\n const playerEvents = {\n onCanPlay: handleCanPlay,\n ...(onTimeUpdate ? { onTimeUpdate: handleTimeUpdate } : {}),\n ...(onEnded ? { onEnded: handleEnded } : {}),\n }\n const isDesktop = useIsDesktop()\n\n // Seek feedback state with accumulation (like YouTube)\n const [seekFeedback, setSeekFeedback] = React.useState<SeekDirection | null>(null)\n const [seekAccumulated, setSeekAccumulated] = React.useState(0)\n const feedbackTimeout = React.useRef<ReturnType<typeof setTimeout>>(undefined)\n\n const handleSeekFeedback = React.useCallback((direction: SeekDirection) => {\n clearTimeout(feedbackTimeout.current)\n\n setSeekFeedback((prev) => {\n if (prev === direction) {\n setSeekAccumulated((s) => s + 10)\n } else {\n setSeekAccumulated(10)\n }\n return direction\n })\n\n feedbackTimeout.current = setTimeout(() => {\n setSeekFeedback(null)\n setSeekAccumulated(0)\n }, 700)\n }, [])\n\n // Mobile: listen for seek requests from DefaultVideoLayout gestures\n React.useEffect(() => {\n const el = player.current?.el\n if (!el || isDesktop) return\n\n const handler = (e: Event) => {\n const seekTo = (e as CustomEvent<number>).detail\n const current = player.current?.currentTime ?? 0\n const delta = seekTo - current\n // Only show feedback for gesture seeks (~±10s), not slider scrubs\n if (Math.abs(Math.abs(delta) - 10) < 2) {\n handleSeekFeedback(delta < 0 ? \"backward\" : \"forward\")\n }\n }\n\n el.addEventListener(\"media-seek-request\", handler)\n return () => el.removeEventListener(\"media-seek-request\", handler)\n }, [isDesktop, handleSeekFeedback])\n\n React.useEffect(() => {\n return () => clearTimeout(feedbackTimeout.current)\n }, [])\n\n return (\n <VideoLabelsContext.Provider value={resolvedLabels}>\n <MediaPlayer\n ref={player}\n src={resolvedSrc}\n autoPlay={autoPlay}\n muted={muted}\n loop={loop}\n playsInline\n crossOrigin=\"\"\n className={cn(\n \"group relative aspect-video w-full overflow-hidden bg-black text-white\",\n isDesktop ? \"rounded-[16px]\" : \"rounded-none\",\n className\n )}\n {...playerEvents}\n >\n <MediaProvider>\n {poster && (\n <Poster\n className={cn(\"absolute inset-0 block h-full w-full object-cover opacity-0 transition-opacity data-[visible]:opacity-100\", isDesktop && \"rounded-[16px]\")}\n src={poster}\n alt={posterAlt}\n />\n )}\n\n {/* ─── Chapters track (VTT) ─── */}\n {chapters && (\n <Track\n src={chapters}\n kind=\"chapters\"\n language=\"en\"\n default\n />\n )}\n\n {/* ─── Caption/subtitle tracks (VTT) ─── */}\n {captions?.map((track) => (\n <Track\n key={track.language}\n src={track.src}\n kind=\"subtitles\"\n language={track.language}\n label={track.label}\n default={track.default}\n />\n ))}\n </MediaProvider>\n\n {/* ─── Accessibility: screen reader announcements ─── */}\n {announcer && <MediaAnnouncer />}\n\n {/* ─── Buffering spinner ─── */}\n {showBuffering && <BufferingIndicator />}\n\n {/* ─── Seek feedback indicators (both mobile & desktop) ─── */}\n <SeekFeedbackOverlay direction=\"backward\" visible={seekFeedback === \"backward\"} seconds={seekAccumulated} />\n <SeekFeedbackOverlay direction=\"forward\" visible={seekFeedback === \"forward\"} seconds={seekAccumulated} />\n\n {/* ─── MOBILE: Vidstack DefaultVideoLayout (touch, gestos, menus nativos) ─── */}\n {/* O layout default do Vidstack traz affordances que não fazem sentido num\n player de aula e que chegaram como bug do QA (ClickUp 86ajtqjc9):\n - noAudioGain: o submenu \"Áudio\" só tinha o slider \"Amplificar 300%\".\n Sem o slider e com uma única faixa de áudio, o DefaultAudioMenu\n retorna null e o submenu inteiro desaparece.\n - noKeyboardAnimations: o toggle \"Animações de teclado\" é config de\n demo, não de aluno.\n - googleCastButton: null — o Cast nunca completa (precisa de receiver\n app id + mídia pública); um botão que não funciona é pior que\n nenhum. AirPlay segue (o Safari resolve nativamente).\n O item \"Avisos\" do menu Acessibilidade não tem prop no Vidstack — é\n escondido por CSS em `styles/tokens.css`. */}\n {!isDesktop && (\n <DefaultVideoLayout\n icons={defaultLayoutIcons}\n thumbnails={thumbnails}\n colorScheme=\"dark\"\n translations={vidstackTranslations}\n noAudioGain\n noKeyboardAnimations\n slots={{ googleCastButton: null }}\n />\n )}\n\n {/* ─── DESKTOP: Controles customizados do Cycle Design ─── */}\n {isDesktop && (\n <>\n {/* Captions overlay.\n `aria-hidden:*` é obrigatório: ao desligar a legenda o <Captions>\n do Vidstack só marca aria-hidden=\"true\" e para de atualizar o\n renderer — quem apaga a caixa é a folha\n `@vidstack/react/player/styles/default/captions.css`\n (`opacity: 0; visibility: hidden`), que este layout não usa\n porque estiliza o overlay com classes próprias. Sem isso o último\n cue fica congelado na tela até o fim do vídeo (ClickUp 86ajtpear). */}\n <Captions className=\"absolute inset-x-0 bottom-8 z-10 flex flex-col items-center select-none break-words text-center transition-[bottom] duration-200 ease-in-out group-data-[started]:group-hover:bottom-[72px] group-data-[paused]:bottom-[72px] media-preview:opacity-0 aria-hidden:invisible aria-hidden:opacity-0 [&>[data-part=cue]]:inline [&>[data-part=cue]]:rounded-md [&>[data-part=cue]]:bg-black/95 [&>[data-part=cue]]:px-4 [&>[data-part=cue]]:py-1.5 [&>[data-part=cue]]:text-[15px] [&>[data-part=cue]]:leading-snug [&>[data-part=cue]]:text-white [&>[data-part=cue]]:drop-shadow-[0_1px_3px_rgba(0,0,0,0.8)]\" />\n\n {/* Play overlay (paused state — big play button) */}\n <PlayOverlay />\n\n {/* Gestures: click to pause, double-click fullscreen */}\n <Gesture className=\"absolute inset-0 z-0 block h-full w-full\" event=\"pointerup\" action=\"toggle:paused\" />\n <Gesture className=\"absolute inset-0 z-0 block h-full w-full\" event=\"dblpointerup\" action=\"toggle:fullscreen\" />\n\n {/* Double-tap seek zones on edges */}\n <SeekGestureZone side=\"left\" onSeekFeedback={handleSeekFeedback} />\n <SeekGestureZone side=\"right\" onSeekFeedback={handleSeekFeedback} />\n\n {/* Controls overlay (hover to show) */}\n <Controls.Root className=\"absolute inset-0 z-20 flex h-full w-full flex-col bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-0 transition-opacity duration-200 group-data-[started]:group-hover:opacity-100 group-data-[paused]:opacity-100\">\n <div className=\"flex-1\" />\n\n {/* Seek bar */}\n <Controls.Group className=\"flex w-full items-center px-3\">\n <SeekBar thumbnails={thumbnails} chapters={!!chapters} />\n </Controls.Group>\n\n {/* Bottom bar */}\n <Controls.Group className=\"@container flex w-full items-center gap-1 px-2 pb-2\">\n <PlayControl />\n <SeekBackwardControl />\n <SeekForwardControl />\n <MuteControl />\n <VolumeControl />\n <TimeDisplay />\n <LiveIndicator />\n\n <div className=\"flex-1\" />\n\n <CaptionControl />\n <SpeedControl />\n <QualityControl />\n <PIPControl />\n <FullscreenControl />\n </Controls.Group>\n </Controls.Root>\n </>\n )}\n </MediaPlayer>\n </VideoLabelsContext.Provider>\n )\n }\n)\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/video-player.tsx"],"names":["forwardRef","CaptionsIcon","VideoPlayer","_a"],"mappings":"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","file":"chunk-QXZRH3HU.js","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport {\n MediaPlayer,\n MediaProvider,\n Poster,\n Controls,\n Gesture,\n TimeSlider,\n VolumeSlider,\n Time,\n PlayButton,\n MuteButton,\n FullscreenButton,\n CaptionButton,\n PIPButton,\n SeekButton,\n Captions,\n Spinner,\n Track,\n Tooltip,\n Menu,\n LiveButton,\n MediaAnnouncer,\n useMediaState,\n useMediaRemote,\n useVideoQualityOptions,\n useCaptionOptions,\n type MediaPlayerInstance,\n type PlayerSrc,\n} from \"@vidstack/react\"\n// Desktop-only controls use the above. Mobile uses DefaultVideoLayout below.\nimport {\n DefaultVideoLayout,\n defaultLayoutIcons,\n} from \"@vidstack/react/player/layouts/default\"\nimport \"@vidstack/react/player/styles/base.css\"\nimport \"@vidstack/react/player/styles/default/theme.css\"\nimport \"@vidstack/react/player/styles/default/layouts/video.css\"\nimport {\n Play,\n Pause,\n Volume2,\n VolumeX,\n Volume1,\n Maximize,\n Minimize,\n Captions as CaptionsIcon,\n CaptionsOff,\n PictureInPicture2,\n RotateCcw,\n RotateCw,\n Gauge,\n Settings,\n Check,\n} from \"lucide-react\"\nimport { CycleIcon } from \"@/components/icons\"\nimport { cn } from \"@/lib/utils\"\nimport {\n type PlayerLocale,\n type VideoDesktopLabels,\n resolveVideoLabels,\n resolveVidstackTranslations,\n} from \"@/components/ui/player-i18n\"\n\n/* ─── Types ─── */\n\nexport interface CaptionTrack {\n /** URL do arquivo VTT de legenda */\n src: string\n /** Codigo do idioma (BCP 47, ex: \"pt-BR\", \"en\", \"es\") */\n language: string\n /** Label exibido no seletor de legendas (ex: \"Portugues\", \"English\") */\n label: string\n /** Se true, esta faixa sera ativada por padrao */\n default?: boolean\n}\n\nexport interface VideoPlayerRef {\n play(): void\n pause(): void\n readonly currentTime: number\n readonly duration: number\n}\n\n/** @deprecated Use `Partial<VideoDesktopLabels>` — kept for backward compatibility */\nexport type VideoPlayerLabels = Partial<VideoDesktopLabels>\n\n/** Fonte de video: URL string ou objeto com MIME type explicito.\n O Vidstack infere o tipo pela EXTENSAO no path da URL — quando ela nao\n existe (blob: de arquivo local, endpoints sem extensao), o provider\n nao carrega. Nesses casos, passar { src, type } (ex: type do File.type\n local ou o ContentType salvo no upload). */\nexport type VideoPlayerSrc = string | { src: string; type: string }\n\n/** blob: → \"video/object\" (unica rota que o isVideoSrc do Vidstack aceita\n para blob). Demais objetos passam direto — cast porque o runtime aceita\n mais MIME types que a uniao VideoMimeType dos tipos. */\nfunction resolveVideoSrc(src: VideoPlayerSrc): PlayerSrc {\n if (typeof src === \"string\") return src\n if (src.src.startsWith(\"blob:\")) return { src: src.src, type: \"video/object\" }\n return src as PlayerSrc\n}\n\nexport interface VideoPlayerProps {\n /** Fonte do video: URL (mp4, webm, m3u8 para HLS) ou { src, type } para blob:/URL sem extensao */\n src: VideoPlayerSrc\n /** URL da imagem de poster */\n poster?: string\n /** Alt text do poster */\n posterAlt?: string\n /** URL do arquivo de thumbnails (VTT sprite sheet) */\n thumbnails?: string\n /** URL do arquivo VTT de chapters (marcadores de seção no timeline) */\n chapters?: string\n /** Faixas de legenda/subtitles (VTT). Suporta multiplos idiomas. */\n captions?: CaptionTrack[]\n /** Exibir spinner durante buffering (default: true) */\n showBuffering?: boolean\n /** Habilitar anuncios de acessibilidade para screen readers (default: true) */\n announcer?: boolean\n /** Iniciar automaticamente */\n autoPlay?: boolean\n /** Iniciar mutado */\n muted?: boolean\n /** Repetir ao terminar */\n loop?: boolean\n /** Tempo inicial em segundos — usado para retomar de onde o usuario parou (resume position) */\n startTime?: number\n /** Idioma dos controles (default: \"pt-BR\"). 13 locales pre-configurados. */\n locale?: PlayerLocale\n /** Overrides pontuais de labels — aplicados em cima do locale selecionado */\n labels?: VideoPlayerLabels\n /** Callback com progresso do video (currentTime em segundos, duration em segundos) */\n onTimeUpdate?: (currentTime: number, duration: number) => void\n /** Callback disparado quando o video termina */\n onEnded?: () => void\n className?: string\n}\n\n/* ─── Labels context ─── */\n\nconst VideoLabelsContext = React.createContext<VideoDesktopLabels>(\n resolveVideoLabels(\"pt-BR\")\n)\nfunction useVideoLabels() {\n return React.useContext(VideoLabelsContext)\n}\n\n/* ─── Shared styles ─── */\n\nconst controlBtnClass =\n \"group inline-flex size-9 cursor-pointer items-center justify-center rounded-md text-white outline-none transition-colors hover:bg-white/20 focus-visible:ring-2 focus-visible:ring-white/50\"\n\n/* SEM `animate-in`/`animate-out` aqui — de propósito.\n O Popper do Vidstack esconde o tooltip assim: `if (hasAnimation(content))`\n (= `getComputedStyle(el).animationName !== \"none\"`) ele NÃO aplica\n `display: none` na hora; espera um evento `animationend`. As utilities\n `animate-in` deixam `animation-name: enter` permanente no elemento, e o\n par `data-[state=closed]:animate-out` é convenção do Radix — o Vidstack\n marca `data-visible`, nunca `data-state`. Resultado: depois que a animação\n de entrada termina, nenhum `animationend` novo dispara, o `display: none`\n nunca chega e o tooltip fica congelado na tela (ClickUp 86ajtpear).\n Transition não entra no `animationName`, então o hide volta a ser síncrono. */\nconst tooltipClass =\n \"z-50 rounded bg-black/90 px-2 py-1 text-xs font-medium text-white shadow-lg transition-opacity duration-150\"\n\n/** Wraps a control button with a Vidstack tooltip. Desktop only (no hover on mobile). */\nfunction ControlTooltip({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <Tooltip.Root>\n <Tooltip.Trigger asChild>{children}</Tooltip.Trigger>\n <Tooltip.Content className={tooltipClass} placement=\"top\">\n {label}\n </Tooltip.Content>\n </Tooltip.Root>\n )\n}\n\n/** Play, Pause e Volume usam icones filled (solid) no player — igual YouTube */\nconst filledIconClass = \"text-white fill-current !stroke-transparent\"\n\n/* ─── Sub-components (controles customizados) ─── */\n\nfunction PlayOverlay() {\n const isPaused = useMediaState(\"paused\")\n const hasStarted = useMediaState(\"started\")\n\n if (!isPaused && hasStarted) return null\n\n return (\n <PlayButton className=\"absolute inset-0 z-10 flex cursor-pointer items-center justify-center bg-black/30 transition-opacity\">\n <div className=\"flex size-16 items-center justify-center rounded-full bg-white/20 backdrop-blur-sm transition-transform hover:scale-110\">\n <CycleIcon icon={Play} size=\"lg\" decorative className={cn(filledIconClass, \"ml-1\")} />\n </div>\n </PlayButton>\n )\n}\n\nfunction PlayControl() {\n const isPaused = useMediaState(\"paused\")\n const l = useVideoLabels()\n return (\n <ControlTooltip label={isPaused ? l.play : l.pause}>\n <PlayButton className={controlBtnClass}>\n {isPaused ? (\n <CycleIcon icon={Play} size=\"sm\" decorative className={filledIconClass} />\n ) : (\n <CycleIcon icon={Pause} size=\"sm\" decorative className={filledIconClass} />\n )}\n </PlayButton>\n </ControlTooltip>\n )\n}\n\nfunction SeekBackwardControl() {\n const l = useVideoLabels()\n return (\n <ControlTooltip label={l.seekBackward}>\n <SeekButton className={controlBtnClass} seconds={-10}>\n <CycleIcon icon={RotateCcw} size=\"sm\" decorative className=\"text-white\" />\n </SeekButton>\n </ControlTooltip>\n )\n}\n\nfunction SeekForwardControl() {\n const l = useVideoLabels()\n return (\n <ControlTooltip label={l.seekForward}>\n <SeekButton className={controlBtnClass} seconds={10}>\n <CycleIcon icon={RotateCw} size=\"sm\" decorative className=\"text-white\" />\n </SeekButton>\n </ControlTooltip>\n )\n}\n\nfunction MuteControl() {\n const volume = useMediaState(\"volume\")\n const isMuted = useMediaState(\"muted\")\n const l = useVideoLabels()\n\n const Icon = isMuted || volume === 0 ? VolumeX : volume < 0.5 ? Volume1 : Volume2\n const label = isMuted || volume === 0 ? l.unmute : l.mute\n\n return (\n <ControlTooltip label={label}>\n <MuteButton className={controlBtnClass}>\n <CycleIcon icon={Icon} size=\"sm\" decorative className={filledIconClass} />\n </MuteButton>\n </ControlTooltip>\n )\n}\n\nfunction VolumeControl() {\n return (\n <VolumeSlider.Root className=\"group relative hidden h-9 w-20 shrink-0 cursor-pointer touch-none select-none items-center outline-none @[480px]:inline-flex\">\n <VolumeSlider.Track className=\"relative h-[4px] w-full rounded-full bg-white/30\">\n <VolumeSlider.TrackFill className=\"absolute h-full w-[var(--slider-fill)] rounded-full bg-white\" />\n </VolumeSlider.Track>\n <VolumeSlider.Thumb className=\"absolute left-[var(--slider-fill)] top-1/2 size-3 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white opacity-0 transition-opacity group-data-[active]:opacity-100 group-data-[dragging]:opacity-100\" />\n </VolumeSlider.Root>\n )\n}\n\nfunction BufferingIndicator() {\n return (\n <div className=\"pointer-events-none absolute inset-0 z-[35] flex items-center justify-center media-buffering:opacity-100 media-can-play:opacity-0 opacity-0 transition-opacity duration-300\">\n <Spinner.Root className=\"size-16 text-white\" size={64}>\n <Spinner.Track className=\"opacity-25\" width={4} />\n <Spinner.TrackFill className=\"opacity-75\" width={4} />\n </Spinner.Root>\n </div>\n )\n}\n\nfunction SeekBar({ thumbnails, chapters }: { thumbnails?: string; chapters?: boolean }) {\n const trackContent = (\n <>\n <TimeSlider.Track className=\"relative h-[4px] w-full rounded-full bg-white/30\">\n <TimeSlider.Progress className=\"absolute h-full w-[var(--slider-progress)] rounded-full bg-white/50\" />\n <TimeSlider.TrackFill className=\"absolute h-full w-[var(--slider-fill)] rounded-full bg-white\" />\n </TimeSlider.Track>\n </>\n )\n\n return (\n <TimeSlider.Root className=\"group relative inline-flex h-9 w-full cursor-pointer touch-none select-none items-center outline-none\">\n {chapters ? (\n <TimeSlider.Chapters className=\"relative flex w-full items-center\">\n {(cues, forwardRef) =>\n cues.map((cue) => (\n <div\n className=\"relative flex h-full w-full items-center last:mr-0 mr-0.5\"\n key={cue.startTime}\n ref={forwardRef}\n >\n {trackContent}\n </div>\n ))\n }\n </TimeSlider.Chapters>\n ) : (\n trackContent\n )}\n\n <TimeSlider.Thumb className=\"absolute left-[var(--slider-fill)] top-1/2 size-3 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white opacity-0 transition-opacity group-data-[active]:opacity-100 group-data-[dragging]:opacity-100\" />\n\n {/* Thumbnail preview on hover */}\n {thumbnails && (\n <TimeSlider.Preview className=\"pointer-events-none flex flex-col items-center gap-1 opacity-0 transition-opacity duration-200 data-[visible]:opacity-100\">\n <TimeSlider.Thumbnail.Root\n src={thumbnails}\n className=\"block h-[var(--thumbnail-height)] max-h-[160px] min-h-[80px] w-[var(--thumbnail-width)] min-w-[120px] max-w-[200px] overflow-hidden rounded-md border-2 border-white bg-black\"\n >\n <TimeSlider.Thumbnail.Img />\n </TimeSlider.Thumbnail.Root>\n {chapters && <TimeSlider.ChapterTitle className=\"text-[11px] text-white/80\" />}\n <TimeSlider.Value className=\"rounded bg-black/80 px-1.5 py-0.5 text-[11px] font-mono text-white\" />\n </TimeSlider.Preview>\n )}\n\n {/* Time preview (no thumbnails) */}\n {!thumbnails && (\n <TimeSlider.Preview className=\"pointer-events-none flex flex-col items-center opacity-0 transition-opacity duration-200 data-[visible]:opacity-100\">\n {chapters && <TimeSlider.ChapterTitle className=\"text-[11px] text-white/80 mb-0.5\" />}\n <TimeSlider.Value className=\"rounded bg-black/80 px-1.5 py-0.5 text-[11px] font-mono text-white\" />\n </TimeSlider.Preview>\n )}\n </TimeSlider.Root>\n )\n}\n\nfunction TimeDisplay() {\n return (\n <div className=\"flex shrink-0 items-center gap-1 text-xs font-mono text-white/80 tabular-nums whitespace-nowrap\">\n <Time type=\"current\" />\n <span>/</span>\n <Time type=\"duration\" />\n </div>\n )\n}\n\nfunction CaptionControl() {\n const track = useMediaState(\"textTrack\")\n const hasCaptions = useMediaState(\"hasCaptions\")\n const options = useCaptionOptions()\n const l = useVideoLabels()\n\n // Single track or none: simple toggle button (native CaptionButton behavior)\n if (options.length <= 2) {\n return (\n <ControlTooltip label={track ? l.captionsOn : l.captionsOff}>\n <CaptionButton className={cn(controlBtnClass, !hasCaptions && \"opacity-50 pointer-events-none\")}>\n {track ? (\n <CycleIcon icon={CaptionsIcon} size=\"sm\" decorative className=\"text-white\" />\n ) : (\n <CycleIcon icon={CaptionsOff} size=\"sm\" decorative className=\"text-white\" />\n )}\n </CaptionButton>\n </ControlTooltip>\n )\n }\n\n // Multiple tracks: menu with language selection (native Vidstack Menu behavior)\n return (\n <Menu.Root>\n <ControlTooltip label={l.captions}>\n <Menu.Button className={controlBtnClass}>\n {track ? (\n <CycleIcon icon={CaptionsIcon} size=\"sm\" decorative className=\"text-white\" />\n ) : (\n <CycleIcon icon={CaptionsOff} size=\"sm\" decorative className=\"text-white\" />\n )}\n </Menu.Button>\n </ControlTooltip>\n\n <Menu.Content\n className=\"absolute bottom-full right-0 z-50 mb-2 min-w-[140px] rounded-lg border border-white/10 bg-black/90 backdrop-blur-md p-1 shadow-xl\"\n placement=\"top\"\n >\n <p className=\"px-3 py-1 text-[11px] font-semibold uppercase tracking-wider text-white/50\">\n {l.captions}\n </p>\n <Menu.RadioGroup value={options.selectedValue}>\n {options.map((option) => (\n <Menu.Radio\n key={option.value}\n value={option.value}\n onSelect={option.select}\n className={cn(\n \"flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-sm text-white/80 transition-colors hover:bg-white/10 hover:text-white cursor-pointer\",\n option.selected && \"text-white font-medium\"\n )}\n >\n <span className=\"size-4 flex items-center justify-center\">\n {option.selected && <CycleIcon icon={Check} size=\"2xs\" decorative className=\"text-white\" />}\n </span>\n <span>{option.label}</span>\n </Menu.Radio>\n ))}\n </Menu.RadioGroup>\n </Menu.Content>\n </Menu.Root>\n )\n}\n\nfunction PIPControl() {\n const isPIP = useMediaState(\"pictureInPicture\")\n const canPIP = useMediaState(\"canPictureInPicture\")\n const l = useVideoLabels()\n\n if (!canPIP) return null\n\n return (\n <ControlTooltip label={isPIP ? l.pipExit : l.pip}>\n <PIPButton className={controlBtnClass}>\n <CycleIcon icon={PictureInPicture2} size=\"sm\" decorative className={cn(\"text-white\", isPIP && \"text-white/100\")} />\n </PIPButton>\n </ControlTooltip>\n )\n}\n\nfunction SpeedControl() {\n const playbackRate = useMediaState(\"playbackRate\")\n const remote = useMediaRemote()\n const [open, setOpen] = React.useState(false)\n const l = useVideoLabels()\n\n const rates = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]\n\n return (\n <div className=\"relative\">\n <ControlTooltip label={l.speed}>\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className={controlBtnClass}\n >\n {playbackRate === 1 ? (\n <CycleIcon icon={Gauge} size=\"sm\" decorative className=\"text-white\" />\n ) : (\n <span className=\"text-xs font-mono font-semibold text-white\">{playbackRate}x</span>\n )}\n </button>\n </ControlTooltip>\n\n {open && (\n <>\n {/* Backdrop to close */}\n <div className=\"fixed inset-0 z-40\" onClick={() => setOpen(false)} />\n\n <div className=\"absolute bottom-full right-0 z-50 mb-2 min-w-[120px] rounded-lg border border-white/10 bg-black/90 backdrop-blur-md p-1 shadow-xl\">\n {rates.map((rate) => (\n <button\n key={rate}\n type=\"button\"\n onClick={() => {\n remote.changePlaybackRate(rate)\n setOpen(false)\n }}\n className={cn(\n \"flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-sm text-white/80 transition-colors hover:bg-white/10 hover:text-white\",\n playbackRate === rate && \"text-white font-medium\"\n )}\n >\n <span className=\"size-4 flex items-center justify-center\">\n {playbackRate === rate && <CycleIcon icon={Check} size=\"2xs\" decorative className=\"text-white\" />}\n </span>\n <span className=\"font-mono\">{rate === 1 ? l.speedNormal : `${rate}x`}</span>\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n )\n}\n\nfunction QualityControl() {\n const options = useVideoQualityOptions({ auto: true, sort: \"descending\" })\n const [open, setOpen] = React.useState(false)\n const l = useVideoLabels()\n\n const currentLabel = options.selectedValue === \"auto\"\n ? `Auto${options.selectedQuality ? ` (${options.selectedQuality.height}p)` : \"\"}`\n : options.selectedQuality\n ? `${options.selectedQuality.height}p`\n : \"Auto\"\n\n if (options.disabled) return null\n\n return (\n <div className=\"relative\">\n <ControlTooltip label={l.quality}>\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className={controlBtnClass}\n >\n <CycleIcon icon={Settings} size=\"sm\" decorative className=\"text-white\" />\n </button>\n </ControlTooltip>\n\n {open && (\n <>\n <div className=\"fixed inset-0 z-40\" onClick={() => setOpen(false)} />\n\n <div className=\"absolute bottom-full right-0 z-50 mb-2 min-w-[140px] rounded-lg border border-white/10 bg-black/90 backdrop-blur-md p-1 shadow-xl\">\n <p className=\"px-3 py-1 text-[11px] font-semibold uppercase tracking-wider text-white/50\">\n {l.qualityMenu}\n </p>\n {options.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => {\n option.select()\n setOpen(false)\n }}\n className={cn(\n \"flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-sm text-white/80 transition-colors hover:bg-white/10 hover:text-white\",\n option.selected && \"text-white font-medium\"\n )}\n >\n <span className=\"size-4 flex items-center justify-center\">\n {option.selected && <CycleIcon icon={Check} size=\"2xs\" decorative className=\"text-white\" />}\n </span>\n <span className=\"font-mono\">{option.label}</span>\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n )\n}\n\nfunction FullscreenControl() {\n const isFullscreen = useMediaState(\"fullscreen\")\n const l = useVideoLabels()\n return (\n <ControlTooltip label={isFullscreen ? l.fullscreenExit : l.fullscreen}>\n <FullscreenButton className={controlBtnClass}>\n {isFullscreen ? (\n <CycleIcon icon={Minimize} size=\"sm\" decorative className=\"text-white\" />\n ) : (\n <CycleIcon icon={Maximize} size=\"sm\" decorative className=\"text-white\" />\n )}\n </FullscreenButton>\n </ControlTooltip>\n )\n}\n\nfunction LiveIndicator() {\n const isLive = useMediaState(\"live\")\n const isLiveEdge = useMediaState(\"liveEdge\")\n const l = useVideoLabels()\n\n if (!isLive) return null\n\n return (\n <LiveButton\n className={cn(\n \"inline-flex cursor-pointer items-center gap-1.5 rounded-md px-2 py-1 text-xs font-semibold uppercase tracking-wider transition-colors\",\n isLiveEdge\n ? \"text-destructive\"\n : \"text-white/60 hover:text-white\"\n )}\n >\n <span\n className={cn(\n \"size-2 rounded-full\",\n isLiveEdge ? \"bg-destructive animate-pulse\" : \"bg-white/40\"\n )}\n />\n {l.live}\n </LiveButton>\n )\n}\n\n\n/* ─── Gesture helpers ─── */\n\ntype SeekDirection = \"backward\" | \"forward\"\n\nconst DOUBLE_TAP_THRESHOLD = 300\n\n/** Double-tap left/right edges to seek ±10s. z-10 so it doesn't block controls (z-20). */\nfunction SeekGestureZone({\n side,\n onSeekFeedback,\n}: {\n side: \"left\" | \"right\"\n onSeekFeedback: (direction: SeekDirection) => void\n}) {\n const remote = useMediaRemote()\n const currentTime = useMediaState(\"currentTime\")\n const lastTapRef = React.useRef(0)\n\n const handlePointerUp = React.useCallback(\n (e: React.PointerEvent) => {\n const now = Date.now()\n const delta = now - lastTapRef.current\n lastTapRef.current = now\n\n if (delta < DOUBLE_TAP_THRESHOLD) {\n e.stopPropagation()\n const seconds = side === \"left\" ? -10 : 10\n remote.seek(currentTime + seconds)\n onSeekFeedback(side === \"left\" ? \"backward\" : \"forward\")\n }\n },\n [remote, currentTime, side, onSeekFeedback]\n )\n\n return (\n <div\n className={cn(\n \"absolute top-0 z-10 block h-full w-1/5\",\n side === \"left\" ? \"left-0\" : \"right-0\"\n )}\n onPointerUp={handlePointerUp}\n />\n )\n}\n\nfunction SeekFeedbackOverlay({\n direction,\n visible,\n seconds,\n}: {\n direction: SeekDirection\n visible: boolean\n seconds: number\n}) {\n const isBackward = direction === \"backward\"\n\n return (\n <div\n className={cn(\n \"pointer-events-none absolute top-0 z-[35] flex h-full w-2/5 items-center transition-opacity duration-200\",\n isBackward ? \"left-0 justify-center\" : \"right-0 justify-center\",\n visible ? \"opacity-100\" : \"opacity-0\"\n )}\n >\n <div\n className={cn(\n \"flex flex-col items-center gap-1 transition-transform duration-300\",\n visible ? \"scale-100\" : \"scale-75\"\n )}\n >\n <div className=\"flex size-12 items-center justify-center rounded-full bg-white/20 backdrop-blur-sm\">\n <CycleIcon\n icon={isBackward ? RotateCcw : RotateCw}\n size=\"sm\"\n decorative\n className=\"text-white\"\n />\n </div>\n <span className=\"text-xs font-semibold text-white drop-shadow-md\">\n {seconds}s\n </span>\n </div>\n </div>\n )\n}\n\n\n/* ─── Hook: detect desktop via pointer capability ─── */\n/* Uses pointer: fine (mouse/trackpad) instead of viewport width.\n This way mobile devices keep the touch-optimized DefaultVideoLayout\n even when fullscreen in landscape exceeds the sm breakpoint. */\n\nfunction useIsDesktop() {\n const [isDesktop, setIsDesktop] = React.useState(false)\n\n React.useEffect(() => {\n const mq = window.matchMedia(\"(pointer: fine)\")\n setIsDesktop(mq.matches)\n const handler = (e: MediaQueryListEvent) => setIsDesktop(e.matches)\n mq.addEventListener(\"change\", handler)\n return () => mq.removeEventListener(\"change\", handler)\n }, [])\n\n return isDesktop\n}\n\n/* ─── Main component ─── */\n\nexport const VideoPlayer = React.forwardRef<VideoPlayerRef, VideoPlayerProps>(\n function VideoPlayer(\n {\n src,\n poster,\n posterAlt = \"\",\n thumbnails,\n chapters,\n captions,\n showBuffering = true,\n announcer = true,\n autoPlay = false,\n muted = false,\n loop = false,\n startTime,\n locale = \"pt-BR\",\n labels,\n onTimeUpdate,\n onEnded,\n className,\n },\n ref\n ) {\n const resolvedLabels = React.useMemo(\n () => resolveVideoLabels(locale, labels),\n [locale, labels]\n )\n const vidstackTranslations = React.useMemo(\n () => resolveVidstackTranslations(locale, labels),\n [locale, labels]\n )\n const player = React.useRef<MediaPlayerInstance>(null)\n const resolvedSrc = React.useMemo(() => resolveVideoSrc(src), [src])\n\n React.useImperativeHandle(ref, () => ({\n play() {\n player.current?.play()\n },\n pause() {\n player.current?.pause()\n },\n get currentTime() {\n return player.current?.currentTime ?? 0\n },\n get duration() {\n return player.current?.duration ?? 0\n },\n }))\n\n const handleTimeUpdate = React.useCallback(\n (detail: { currentTime: number }) => {\n if (onTimeUpdate && player.current) {\n onTimeUpdate(detail.currentTime, player.current.duration)\n }\n },\n [onTimeUpdate]\n )\n\n const handleEnded = React.useCallback(() => {\n onEnded?.()\n }, [onEnded])\n\n // Resume position: seek to startTime once the player is ready\n const hasAppliedStartTime = React.useRef(false)\n const handleCanPlay = React.useCallback(() => {\n if (startTime && startTime > 0 && !hasAppliedStartTime.current && player.current) {\n player.current.currentTime = startTime\n hasAppliedStartTime.current = true\n }\n }, [startTime])\n\n const playerEvents = {\n onCanPlay: handleCanPlay,\n ...(onTimeUpdate ? { onTimeUpdate: handleTimeUpdate } : {}),\n ...(onEnded ? { onEnded: handleEnded } : {}),\n }\n const isDesktop = useIsDesktop()\n\n // Seek feedback state with accumulation (like YouTube)\n const [seekFeedback, setSeekFeedback] = React.useState<SeekDirection | null>(null)\n const [seekAccumulated, setSeekAccumulated] = React.useState(0)\n const feedbackTimeout = React.useRef<ReturnType<typeof setTimeout>>(undefined)\n\n const handleSeekFeedback = React.useCallback((direction: SeekDirection) => {\n clearTimeout(feedbackTimeout.current)\n\n setSeekFeedback((prev) => {\n if (prev === direction) {\n setSeekAccumulated((s) => s + 10)\n } else {\n setSeekAccumulated(10)\n }\n return direction\n })\n\n feedbackTimeout.current = setTimeout(() => {\n setSeekFeedback(null)\n setSeekAccumulated(0)\n }, 700)\n }, [])\n\n // Mobile: listen for seek requests from DefaultVideoLayout gestures\n React.useEffect(() => {\n const el = player.current?.el\n if (!el || isDesktop) return\n\n const handler = (e: Event) => {\n const seekTo = (e as CustomEvent<number>).detail\n const current = player.current?.currentTime ?? 0\n const delta = seekTo - current\n // Only show feedback for gesture seeks (~±10s), not slider scrubs\n if (Math.abs(Math.abs(delta) - 10) < 2) {\n handleSeekFeedback(delta < 0 ? \"backward\" : \"forward\")\n }\n }\n\n el.addEventListener(\"media-seek-request\", handler)\n return () => el.removeEventListener(\"media-seek-request\", handler)\n }, [isDesktop, handleSeekFeedback])\n\n React.useEffect(() => {\n return () => clearTimeout(feedbackTimeout.current)\n }, [])\n\n return (\n <VideoLabelsContext.Provider value={resolvedLabels}>\n <MediaPlayer\n ref={player}\n src={resolvedSrc}\n autoPlay={autoPlay}\n muted={muted}\n loop={loop}\n playsInline\n crossOrigin=\"\"\n className={cn(\n \"group relative aspect-video w-full overflow-hidden bg-black text-white\",\n isDesktop ? \"rounded-[16px]\" : \"rounded-none\",\n className\n )}\n {...playerEvents}\n >\n <MediaProvider>\n {poster && (\n <Poster\n className={cn(\"absolute inset-0 block h-full w-full object-cover opacity-0 transition-opacity data-[visible]:opacity-100\", isDesktop && \"rounded-[16px]\")}\n src={poster}\n alt={posterAlt}\n />\n )}\n\n {/* ─── Chapters track (VTT) ─── */}\n {chapters && (\n <Track\n src={chapters}\n kind=\"chapters\"\n language=\"en\"\n default\n />\n )}\n\n {/* ─── Caption/subtitle tracks (VTT) ─── */}\n {captions?.map((track) => (\n <Track\n key={track.language}\n src={track.src}\n kind=\"subtitles\"\n language={track.language}\n label={track.label}\n default={track.default}\n />\n ))}\n </MediaProvider>\n\n {/* ─── Accessibility: screen reader announcements ─── */}\n {announcer && <MediaAnnouncer />}\n\n {/* ─── Buffering spinner ─── */}\n {showBuffering && <BufferingIndicator />}\n\n {/* ─── Seek feedback indicators (both mobile & desktop) ─── */}\n <SeekFeedbackOverlay direction=\"backward\" visible={seekFeedback === \"backward\"} seconds={seekAccumulated} />\n <SeekFeedbackOverlay direction=\"forward\" visible={seekFeedback === \"forward\"} seconds={seekAccumulated} />\n\n {/* ─── MOBILE: Vidstack DefaultVideoLayout (touch, gestos, menus nativos) ─── */}\n {/* O layout default do Vidstack traz affordances que não fazem sentido num\n player de aula e que chegaram como bug do QA (ClickUp 86ajtqjc9):\n - noAudioGain: o submenu \"Áudio\" só tinha o slider \"Amplificar 300%\".\n Sem o slider e com uma única faixa de áudio, o DefaultAudioMenu\n retorna null e o submenu inteiro desaparece.\n - noKeyboardAnimations: o toggle \"Animações de teclado\" é config de\n demo, não de aluno.\n - googleCastButton: null — o Cast nunca completa (precisa de receiver\n app id + mídia pública); um botão que não funciona é pior que\n nenhum. AirPlay segue (o Safari resolve nativamente).\n O item \"Avisos\" do menu Acessibilidade não tem prop no Vidstack — é\n escondido por CSS em `styles/tokens.css`. */}\n {!isDesktop && (\n <DefaultVideoLayout\n icons={defaultLayoutIcons}\n thumbnails={thumbnails}\n colorScheme=\"dark\"\n translations={vidstackTranslations}\n noAudioGain\n noKeyboardAnimations\n slots={{ googleCastButton: null }}\n />\n )}\n\n {/* ─── DESKTOP: Controles customizados do Cycle Design ─── */}\n {isDesktop && (\n <>\n {/* Captions overlay.\n `aria-hidden:*` é obrigatório: ao desligar a legenda o <Captions>\n do Vidstack só marca aria-hidden=\"true\" e para de atualizar o\n renderer — quem apaga a caixa é a folha\n `@vidstack/react/player/styles/default/captions.css`\n (`opacity: 0; visibility: hidden`), que este layout não usa\n porque estiliza o overlay com classes próprias. Sem isso o último\n cue fica congelado na tela até o fim do vídeo (ClickUp 86ajtpear).\n O estilo do cue usa combinador DESCENDENTE (`[&_[data-part=cue]]`),\n não filho: a lib media-captions insere `[data-part=cue-display]`\n como filho direto do overlay e o `[data-part=cue]` fica um nível\n abaixo (issue #20 — com `>` as classes nunca casavam e o visual\n vinha dos defaults do Vidstack por acidente). */}\n <Captions className=\"absolute inset-x-0 bottom-8 z-10 flex flex-col items-center select-none break-words text-center transition-[bottom] duration-200 ease-in-out group-data-[started]:group-hover:bottom-[72px] group-data-[paused]:bottom-[72px] media-preview:opacity-0 aria-hidden:invisible aria-hidden:opacity-0 [&_[data-part=cue]]:inline [&_[data-part=cue]]:rounded-md [&_[data-part=cue]]:bg-black/95 [&_[data-part=cue]]:px-4 [&_[data-part=cue]]:py-1.5 [&_[data-part=cue]]:text-[15px] [&_[data-part=cue]]:leading-snug [&_[data-part=cue]]:text-white [&_[data-part=cue]]:drop-shadow-[0_1px_3px_rgba(0,0,0,0.8)]\" />\n\n {/* Play overlay (paused state — big play button) */}\n <PlayOverlay />\n\n {/* Gestures: click to pause, double-click fullscreen */}\n <Gesture className=\"absolute inset-0 z-0 block h-full w-full\" event=\"pointerup\" action=\"toggle:paused\" />\n <Gesture className=\"absolute inset-0 z-0 block h-full w-full\" event=\"dblpointerup\" action=\"toggle:fullscreen\" />\n\n {/* Double-tap seek zones on edges */}\n <SeekGestureZone side=\"left\" onSeekFeedback={handleSeekFeedback} />\n <SeekGestureZone side=\"right\" onSeekFeedback={handleSeekFeedback} />\n\n {/* Controls overlay (hover to show) */}\n <Controls.Root className=\"absolute inset-0 z-20 flex h-full w-full flex-col bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-0 transition-opacity duration-200 group-data-[started]:group-hover:opacity-100 group-data-[paused]:opacity-100\">\n <div className=\"flex-1\" />\n\n {/* Seek bar */}\n <Controls.Group className=\"flex w-full items-center px-3\">\n <SeekBar thumbnails={thumbnails} chapters={!!chapters} />\n </Controls.Group>\n\n {/* Bottom bar */}\n <Controls.Group className=\"@container flex w-full items-center gap-1 px-2 pb-2\">\n <PlayControl />\n <SeekBackwardControl />\n <SeekForwardControl />\n <MuteControl />\n <VolumeControl />\n <TimeDisplay />\n <LiveIndicator />\n\n <div className=\"flex-1\" />\n\n <CaptionControl />\n <SpeedControl />\n <QualityControl />\n <PIPControl />\n <FullscreenControl />\n </Controls.Group>\n </Controls.Root>\n </>\n )}\n </MediaPlayer>\n </VideoLabelsContext.Provider>\n )\n }\n)\n"]}
|
|
@@ -126,6 +126,8 @@ interface ChatThreadProps extends Omit<React.ComponentProps<"div">, "onChange">
|
|
|
126
126
|
userAvatar?: string;
|
|
127
127
|
/** Nome do usuario (usado para iniciais no fallback do avatar e alt da imagem). */
|
|
128
128
|
userName?: string;
|
|
129
|
+
/** Classe de tema das bolhas do user (pass-through pro ChatMessage). Default "theme-positive". */
|
|
130
|
+
userMessageTheme?: string;
|
|
129
131
|
/** Default: "Sem conexao. Tentando reconectar..." */
|
|
130
132
|
offlineBannerText?: string;
|
|
131
133
|
/** Default: "Tentar novamente" */
|
|
@@ -137,6 +139,6 @@ interface ChatThreadProps extends Omit<React.ComponentProps<"div">, "onChange">
|
|
|
137
139
|
/** Default: "Desculpe, nao consegui responder." */
|
|
138
140
|
defaultAiErrorText?: string;
|
|
139
141
|
}
|
|
140
|
-
declare function ChatThread({ messages, state, initialThinking, onSendText, onSendAudio, onRetryMessage, onRegenerateResponse, onStopResponse, onLoadMore, onStartRecording, onPauseRecording, onResumeRecording, onCancelRecording, onTogglePlay, onSeekPlayback, recordingStream, recordingDuration, isPlaying, playbackProgress, offline, rateLimitedUntil, rateLimitBannerText, quotaExhausted, quotaExhaustedConfig, onRate, ratingLabels, placeholder, maxLength, audioOnlyMode, maxRecordingDuration, warnAtSecondsLeft, secondsLeftLabel, onMaxDurationReached, userAvatar, userName, offlineBannerText, retryButtonText, regenerateButtonText, stopResponseText, defaultAiErrorText, className, ...props }: ChatThreadProps): react_jsx_runtime.JSX.Element;
|
|
142
|
+
declare function ChatThread({ messages, state, initialThinking, onSendText, onSendAudio, onRetryMessage, onRegenerateResponse, onStopResponse, onLoadMore, onStartRecording, onPauseRecording, onResumeRecording, onCancelRecording, onTogglePlay, onSeekPlayback, recordingStream, recordingDuration, isPlaying, playbackProgress, offline, rateLimitedUntil, rateLimitBannerText, quotaExhausted, quotaExhaustedConfig, onRate, ratingLabels, placeholder, maxLength, audioOnlyMode, maxRecordingDuration, warnAtSecondsLeft, secondsLeftLabel, onMaxDurationReached, userAvatar, userName, userMessageTheme, offlineBannerText, retryButtonText, regenerateButtonText, stopResponseText, defaultAiErrorText, className, ...props }: ChatThreadProps): react_jsx_runtime.JSX.Element;
|
|
141
143
|
|
|
142
144
|
export { ChatThread, type ChatThreadMessage, type ChatThreadMessageStatus, type ChatThreadPersona, type ChatThreadProps, type ChatThreadState, type QuotaExhaustedConfig };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
export { ChatThread } from '../chunk-
|
|
2
|
+
export { ChatThread } from '../chunk-CLMO3IRS.js';
|
|
3
3
|
import '../chunk-2KFWBA76.js';
|
|
4
|
-
import '../chunk-
|
|
4
|
+
import '../chunk-KSEDDFGG.js';
|
|
5
5
|
import '../chunk-RPU3FY62.js';
|
|
6
6
|
import '../chunk-YIOXPV2N.js';
|
|
7
|
-
import '../chunk-
|
|
7
|
+
import '../chunk-JPEQ4BYK.js';
|
|
8
8
|
import '../chunk-T2TJG24M.js';
|
|
9
9
|
import '../chunk-N2F3ZG2S.js';
|
|
10
10
|
import '../chunk-KLX547KZ.js';
|
package/dist/index.js
CHANGED
|
@@ -14,16 +14,16 @@ export { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTi
|
|
|
14
14
|
export { Skeleton } from './chunk-7QFXFNTZ.js';
|
|
15
15
|
export { LiveWaiting } from './chunk-NKBTC4IF.js';
|
|
16
16
|
export { AudioPlayer } from './chunk-GKJ45JXA.js';
|
|
17
|
-
export { VideoPlayer } from './chunk-
|
|
17
|
+
export { VideoPlayer } from './chunk-QXZRH3HU.js';
|
|
18
18
|
export { playerLocales } from './chunk-EFT7BHN7.js';
|
|
19
19
|
export { Toaster, cycleToast } from './chunk-7ZSICZXA.js';
|
|
20
20
|
export { Alert, AlertAction, AlertClose, AlertDescription, AlertTitle, alertVariants } from './chunk-PS3MV5G7.js';
|
|
21
|
-
export { ChatThread } from './chunk-
|
|
21
|
+
export { ChatThread } from './chunk-CLMO3IRS.js';
|
|
22
22
|
export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger } from './chunk-2KFWBA76.js';
|
|
23
|
-
export { ChatAudio, ChatMessage, chatMessageVariants } from './chunk-
|
|
23
|
+
export { ChatAudio, ChatMessage, chatMessageVariants } from './chunk-KSEDDFGG.js';
|
|
24
24
|
export { LikeDislike, likeDislikeVariants } from './chunk-RPU3FY62.js';
|
|
25
25
|
export { MessageRating } from './chunk-YIOXPV2N.js';
|
|
26
|
-
export { MessageBar } from './chunk-
|
|
26
|
+
export { MessageBar } from './chunk-JPEQ4BYK.js';
|
|
27
27
|
export { SelectorBar } from './chunk-SKBY6OZL.js';
|
|
28
28
|
export { ChatPanel } from './chunk-OLYW5LVG.js';
|
|
29
29
|
import './chunk-7FJ7LRSV.js';
|
|
@@ -31,6 +31,13 @@ interface ChatMessageProps extends Omit<React.ComponentProps<"div">, "content">,
|
|
|
31
31
|
onFeedbackChange?: (value: LikeDislikeValue) => void;
|
|
32
32
|
/** Estado de loading: mostra typing indicator ("...") */
|
|
33
33
|
loading?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Classe de tema da bolha do user (bubble, audio e badge de velocidade herdam
|
|
36
|
+
* `bg-accent`/`bg-primary` dela). Default `"theme-positive"` — verde, leitura
|
|
37
|
+
* familiar de "mensagem enviada" (WhatsApp); nao colide com critical nem disputa
|
|
38
|
+
* com os botoes brand. So tem efeito em `persona="user"`. Ex.: `theme="theme-class"`.
|
|
39
|
+
*/
|
|
40
|
+
theme?: string;
|
|
34
41
|
}
|
|
35
42
|
interface ChatAudioProps extends React.ComponentProps<"div"> {
|
|
36
43
|
/** URL do audio */
|
|
@@ -38,8 +45,9 @@ interface ChatAudioProps extends React.ComponentProps<"div"> {
|
|
|
38
45
|
/**
|
|
39
46
|
* Variante visual:
|
|
40
47
|
* - `neutral`: container `bg-muted` (cinza claro) — usado em AI messages
|
|
41
|
-
* - `brand`: container `bg-accent`
|
|
42
|
-
*
|
|
48
|
+
* - `brand`: container `bg-accent` tematizado — usado em User messages.
|
|
49
|
+
* A cor vem do wrapper `.theme-*` do componente pai (ChatMessage aplica
|
|
50
|
+
* `theme-positive` por default; nome mantido por retrocompatibilidade)
|
|
43
51
|
*/
|
|
44
52
|
variant?: "neutral" | "brand";
|
|
45
53
|
/**
|
|
@@ -57,6 +65,6 @@ interface ChatAudioProps extends React.ComponentProps<"div"> {
|
|
|
57
65
|
}
|
|
58
66
|
declare function ChatAudio({ src, variant, peaks: providedPeaks, barCount, className, ...props }: ChatAudioProps): react_jsx_runtime.JSX.Element;
|
|
59
67
|
|
|
60
|
-
declare function ChatMessage({ persona, text, audioSrc, avatar, author, showFeedback, feedbackValue, onFeedbackChange, loading, className, ...props }: ChatMessageProps): react_jsx_runtime.JSX.Element;
|
|
68
|
+
declare function ChatMessage({ persona, text, audioSrc, avatar, author, showFeedback, feedbackValue, onFeedbackChange, loading, theme, className, ...props }: ChatMessageProps): react_jsx_runtime.JSX.Element;
|
|
61
69
|
|
|
62
70
|
export { ChatAudio, type ChatAudioProps, ChatMessage, type ChatMessageProps, chatMessageVariants };
|
package/dist/ui/chat-message.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
export { ChatAudio, ChatMessage, chatMessageVariants } from '../chunk-
|
|
2
|
+
export { ChatAudio, ChatMessage, chatMessageVariants } from '../chunk-KSEDDFGG.js';
|
|
3
3
|
import '../chunk-RPU3FY62.js';
|
|
4
4
|
import '../chunk-T2TJG24M.js';
|
|
5
5
|
import '../chunk-N2F3ZG2S.js';
|
package/dist/ui/message-bar.d.ts
CHANGED
|
@@ -54,6 +54,10 @@ interface MessageBarProps extends Omit<React.ComponentProps<"div">, "onChange">
|
|
|
54
54
|
* Progresso do playback do audio gravado (0-1), usado durante state=paused.
|
|
55
55
|
* Quando fornecido, o waveform mostra barras tocadas/nao tocadas + dot verde
|
|
56
56
|
* sincronizado. Sem isso, o waveform mostra todas as barras como nao tocadas.
|
|
57
|
+
*
|
|
58
|
+
* Alimente via `requestAnimationFrame` enquanto o audio toca, NAO so via
|
|
59
|
+
* `timeupdate` — esse evento dispara ~4x/s (250ms) e o dot pula em stop motion.
|
|
60
|
+
* Ver exemplo na doc do MessageBar.
|
|
57
61
|
*/
|
|
58
62
|
playbackProgress?: number;
|
|
59
63
|
/**
|
package/dist/ui/message-bar.js
CHANGED
package/dist/ui/video-player.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/composites/chat-thread.tsx"],"names":[],"mappings":"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","file":"chunk-EAVNA2RW.js","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { ChevronDown, Square } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChatMessage } from \"@/components/ui/chat-message\"\nimport {\n MessageBar,\n type MessageBarState,\n} from \"@/components/ui/message-bar\"\nimport {\n MessageRating,\n DEFAULT_MESSAGE_RATING_LABELS,\n type MessageRatingValue,\n type MessageRatingLabels,\n type RatingLabel,\n} from \"@/components/ui/message-rating\"\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from \"@/components/ui/alert-dialog\"\n\n/* ─── Types ───────────────────────────────────────────────────── */\n\nexport type ChatThreadMessageStatus = \"sent\" | \"pending\" | \"failed\"\nexport type ChatThreadPersona = \"ai\" | \"user\" | \"system\"\n\nexport interface ChatThreadMessage {\n id: string\n persona: ChatThreadPersona\n status?: ChatThreadMessageStatus\n text?: string\n audioSrc?: string\n audioPeaks?: number[]\n /** Mensagem de erro pra exibir quando `persona=\"ai\"` e `status=\"failed\"` */\n errorText?: string\n /**\n * Quando true em uma mensagem da IA, renderiza o `MessageRating` (5 emojis) logo\n * abaixo da bubble — alinhado com a IA, parte da mesma \"linha visual\" da mensagem.\n * Apos o usuario responder, o rating some automaticamente (fade-out + slide-down).\n *\n * Usado quando a IA pede avaliacao da atividade: o consumer adiciona a msg da IA\n * com este campo `true` no array `messages` e ouve `onRate` para receber a resposta.\n */\n requestRating?: boolean\n}\n\nexport type ChatThreadState = \"idle\" | \"sending\" | \"thinking\" | \"error\"\n\nexport interface QuotaExhaustedConfig {\n title?: string\n description?: string\n ctaLabel?: string\n cancelLabel?: string\n onCta?: () => void\n onCancel?: () => void\n}\n\nexport interface ChatThreadProps extends Omit<React.ComponentProps<\"div\">, \"onChange\"> {\n /** Lista de mensagens da conversa */\n messages: ChatThreadMessage[]\n /** Estado global da conversa (controlled) */\n state?: ChatThreadState\n /** Quando true e thread vazio, monta direto em thinking (cenario Class — IA fala primeiro) */\n initialThinking?: boolean\n\n /* ─── Callbacks essenciais ─── */\n onSendText?: (text: string) => void\n /** Disparado quando user confirma envio do audio gravado (MessageBar dispara apos release/lock).\n * Consumer gerencia MediaRecorder e tem acesso ao Blob no momento que isso for chamado. */\n onSendAudio?: () => void\n /** Retry de mensagem do usuario que falhou enviar (B2) */\n onRetryMessage?: (messageId: string) => void\n /** Regenerar resposta da IA com erro (B3) */\n onRegenerateResponse?: () => void\n /** Cancelar resposta da IA mid-thinking (F1). Passar este callback **ativa** o botao\n * \"Parar resposta\" no rodape durante o estado `thinking`. Se omitido, o MessageBar\n * some com animacao de saida quando a IA esta pensando e volta com animacao de entrada\n * quando termina — o consumer indica que nao quer expor cancelamento. */\n onStopResponse?: () => void\n /** Carregar mensagens antigas (G1 — scroll infinito) */\n onLoadMore?: () => Promise<void> | void\n\n /* ─── Callbacks do MessageBar (pass-through) ─── */\n /** Dispara quando o user pressiona o mic. Consumer chama getUserMedia + MediaRecorder. */\n onStartRecording?: () => void\n /** Dispara quando o user pausa a gravacao. Consumer faz recorder.stop() + cria Blob. */\n onPauseRecording?: () => void\n /** Dispara quando o user retoma gravacao apos pause. */\n onResumeRecording?: () => void\n /** Dispara quando o user cancela a gravacao. Consumer cleanup do MediaRecorder. */\n onCancelRecording?: () => void\n /** Toggle play/pause do audio gravado durante o estado `paused` do MessageBar. */\n onTogglePlay?: () => void\n /** Callback de seek no waveform do audio gravado (durante paused). */\n onSeekPlayback?: (progress: number) => void\n\n /* ─── State do MessageBar (pass-through) ─── */\n /** Stream do microfone durante recording — usado pelo MessageBar pra renderizar o live waveform. */\n recordingStream?: MediaStream | null\n /** Duracao da gravacao em segundos (controlado pelo consumer via setInterval). */\n recordingDuration?: number\n /** Indica se o audio gravado esta tocando (durante paused). */\n isPlaying?: boolean\n /** Progresso de playback (0-1) — usado pra sincronizar dot verde no waveform. */\n playbackProgress?: number\n\n /* ─── Erro states (configuravel) ─── */\n /** Mostra banner de offline + disabled MessageBar (C1) */\n offline?: boolean\n /** Timestamp epoch ate quando bloquear envio (C2). null/undefined = sem rate limit */\n rateLimitedUntil?: number | null\n /** Texto do banner de rate limit. Default: \"Aguarde {s}s antes de enviar nova mensagem\" */\n rateLimitBannerText?: (secondsRemaining: number) => string\n /** Modal de cota esgotada (C3) */\n quotaExhausted?: boolean\n quotaExhaustedConfig?: QuotaExhaustedConfig\n\n /* ─── Rating (J) ─── */\n /**\n * Callback disparado quando o usuario responde um rating de uma mensagem com `requestRating=true`.\n * Recebe:\n * - `messageId`: id da mensagem da IA que pediu avaliacao\n * - `value`: numero 1-5\n * - `label`: objeto com emoji/title/subtitle correspondente ao value\n *\n * O consumer tipicamente usa esses dados para adicionar uma nova mensagem do usuario no array\n * `messages` com o texto da escolha (ex: `label.subtitle` em PT-BR). O `MessageRating` some\n * imediatamente apos o clique (sem estado \"selecionado\" visual).\n */\n onRate?: (messageId: string, value: MessageRatingValue, label: RatingLabel) => void\n /**\n * Labels customizadas do `MessageRating` (sobrescreve PT-BR defaults).\n * Passado pro componente E usado no callback `onRate` ao montar o `label`.\n */\n ratingLabels?: Partial<MessageRatingLabels>\n\n /* ─── Configuracoes do MessageBar ─── */\n placeholder?: string\n maxLength?: number\n /** Modo so audio — passa pro MessageBar como state base */\n audioOnlyMode?: boolean\n\n /* ─── Limite de duracao da gravacao de audio ─── */\n /**\n * Limite de duracao da gravacao em segundos (configurado pelo consumer).\n * Quando atingido, o ChatThread auto-pausa a gravacao (vai pro paused state com\n * preview play/cancel/send) — a menos que `onMaxDurationReached` seja passado,\n * caso em que o consumer assume controle. Sem essa prop, sem limite.\n */\n maxRecordingDuration?: number\n /** Quantos segundos antes do limite ativar o warning visual (timer destructive\n * + label \"Xs restantes\"). Default 10. Ignorado sem `maxRecordingDuration`. */\n warnAtSecondsLeft?: number\n /** Label do warning. Default pt-BR: `(s) => \\`${s}s restantes\\``. */\n secondsLeftLabel?: (secondsLeft: number) => string\n /**\n * Callback opcional disparado ao atingir o limite. Se omitido, ChatThread\n * auto-pausa internamente. Se passado, **substitui** o auto-pause — o consumer\n * decide o que fazer (ex: mostrar toast antes de pausar manualmente).\n */\n onMaxDurationReached?: () => void\n\n /* ─── Identidade do usuario ─── */\n /** URL da imagem do avatar do usuario (aparece em todas as msgs do user no desktop). */\n userAvatar?: string\n /** Nome do usuario (usado para iniciais no fallback do avatar e alt da imagem). */\n userName?: string\n\n /* ─── i18n / texto customizavel ─── */\n /** Default: \"Sem conexao. Tentando reconectar...\" */\n offlineBannerText?: string\n /** Default: \"Tentar novamente\" */\n retryButtonText?: string\n /** Default: \"Regenerar resposta\" */\n regenerateButtonText?: string\n /** Default: \"Parar resposta\" */\n stopResponseText?: string\n /** Default: \"Desculpe, nao consegui responder.\" */\n defaultAiErrorText?: string\n}\n\n/* ─── Constantes ──────────────────────────────────────────────── */\n\nconst SCROLL_BOTTOM_THRESHOLD = 100 // px do bottom pra considerar \"no fundo\"\nconst LOAD_MORE_THRESHOLD = 200 // px do topo pra disparar onLoadMore\n\n/* ─── Sub-componentes internos ────────────────────────────────── */\n\n/** Banner persistente no topo (offline, rate limit, etc.) */\nfunction ChatThreadBanner({\n variant,\n children,\n}: {\n variant: \"offline\" | \"rate-limit\"\n children: React.ReactNode\n}) {\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className={cn(\n \"shrink-0 flex items-center gap-2 px-4 py-2 text-sm border-b\",\n variant === \"offline\" &&\n \"bg-destructive/10 text-destructive border-destructive/20\",\n variant === \"rate-limit\" &&\n \"bg-muted text-muted-foreground border-border\"\n )}\n >\n {children}\n </div>\n )\n}\n\n/** Conta segundos restantes ate `until` (timestamp epoch). */\nfunction useCountdown(until: number | null | undefined): number {\n const [now, setNow] = React.useState(() => Date.now())\n\n React.useEffect(() => {\n if (!until || until <= Date.now()) return\n const id = setInterval(() => setNow(Date.now()), 1000)\n return () => clearInterval(id)\n }, [until])\n\n if (!until) return 0\n const remainingMs = until - now\n return Math.max(0, Math.ceil(remainingMs / 1000))\n}\n\n/** Botao \"Parar resposta\" — substitui MessageBar durante thinking (F1) */\nfunction StopResponseButton({\n onClick,\n label = \"Parar resposta\",\n}: {\n onClick?: () => void\n label?: string\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"w-full flex items-center justify-center gap-2 h-12 rounded-2xl bg-muted text-neutral-foreground hover:bg-muted/80 transition-colors focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n aria-label={label}\n >\n <Square className=\"size-4\" fill=\"currentColor\" strokeWidth={0} />\n <span className=\"text-sm font-medium\">{label}</span>\n </button>\n )\n}\n\n/** Botao flutuante \"↓ Nova mensagem\" — aparece quando ha msg fora do viewport */\nfunction ScrollToBottomButton({\n onClick,\n hasNewMessage,\n}: {\n onClick?: () => void\n hasNewMessage: boolean\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"absolute bottom-2 left-1/2 -translate-x-1/2 z-10 inline-flex items-center justify-center size-10 rounded-full bg-background border border-border shadow-md hover:bg-muted/50 transition-all focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n aria-label={hasNewMessage ? \"Nova mensagem — ir para o fim\" : \"Ir para o fim\"}\n >\n <ChevronDown className=\"size-5 text-neutral-foreground\" />\n {hasNewMessage && (\n <span\n className=\"absolute top-1 right-1 size-2 rounded-full bg-primary theme-brand\"\n aria-hidden=\"true\"\n />\n )}\n </button>\n )\n}\n\n/** Bubble wrapper com animacao de entrada (E1: fade-in + slide-up 8px, 200ms) */\nfunction MessageBubbleAnimated({\n children,\n enableAnimation,\n}: {\n children: React.ReactNode\n enableAnimation: boolean\n}) {\n return (\n <div\n className={cn(\n \"transition-[opacity,transform] duration-200 ease-out\",\n enableAnimation ? \"animate-thread-msg-enter\" : \"\"\n )}\n >\n {children}\n </div>\n )\n}\n\n/* ─── Bottom slot: gerencia animacao sequencial entre MessageBar / StopButton / hidden ─── */\n\ntype BottomSlotKind = \"messagebar\" | \"stop\" | \"hidden\"\nconst LEAVE_DURATION_MS = 150\n\n/**\n * Slot que alterna entre 3 estados com animacao sequencial (sem cross-fade):\n * o conteudo atual anima saida (`thread-msg-leave`, 150ms), troca o conteudo,\n * e o novo anima entrada (`thread-msg-enter`, 200ms). Similar ao\n * AnimatePresence mode=\"wait\" do Framer Motion, mas em CSS puro.\n */\nfunction BottomSlot({\n kind,\n messageBar,\n stopButton,\n}: {\n kind: BottomSlotKind\n messageBar: React.ReactNode\n stopButton: React.ReactNode\n}) {\n const [rendered, setRendered] = React.useState<BottomSlotKind>(kind)\n const [phase, setPhase] = React.useState<\"enter\" | \"leave\">(\"enter\")\n\n React.useEffect(() => {\n if (rendered === kind) return\n setPhase(\"leave\")\n const t = setTimeout(() => {\n setRendered(kind)\n setPhase(\"enter\")\n }, LEAVE_DURATION_MS)\n return () => clearTimeout(t)\n }, [kind, rendered])\n\n return (\n <div className=\"shrink-0 px-4 pb-4 pt-2\">\n {rendered !== \"hidden\" && (\n <div\n key={rendered}\n className={\n phase === \"enter\" ? \"animate-thread-msg-enter\" : \"animate-thread-msg-leave\"\n }\n >\n {rendered === \"messagebar\" ? messageBar : stopButton}\n </div>\n )}\n </div>\n )\n}\n\n/* ─── Component principal ─────────────────────────────────────── */\n\nfunction ChatThread({\n messages,\n state = \"idle\",\n initialThinking = false,\n onSendText,\n onSendAudio,\n onRetryMessage,\n onRegenerateResponse,\n onStopResponse,\n onLoadMore,\n onStartRecording,\n onPauseRecording,\n onResumeRecording,\n onCancelRecording,\n onTogglePlay,\n onSeekPlayback,\n recordingStream,\n recordingDuration,\n isPlaying,\n playbackProgress,\n offline = false,\n rateLimitedUntil = null,\n rateLimitBannerText,\n quotaExhausted = false,\n quotaExhaustedConfig,\n onRate,\n ratingLabels,\n placeholder,\n maxLength,\n audioOnlyMode = false,\n maxRecordingDuration,\n warnAtSecondsLeft,\n secondsLeftLabel,\n onMaxDurationReached,\n userAvatar,\n userName,\n offlineBannerText = \"Sem conexao. Tentando reconectar...\",\n retryButtonText = \"Tentar novamente\",\n regenerateButtonText = \"Regenerar resposta\",\n stopResponseText = \"Parar resposta\",\n defaultAiErrorText = \"Desculpe, nao consegui responder.\",\n className,\n ...props\n}: ChatThreadProps) {\n /* ─── State derivado ─── */\n const rateLimitSecondsLeft = useCountdown(rateLimitedUntil)\n const isRateLimited = rateLimitSecondsLeft > 0\n const isThinking =\n state === \"thinking\" || (initialThinking && messages.length === 0)\n const isDisabled = offline || isRateLimited || quotaExhausted\n\n /* ─── Refs e scroll inteligente (D1) ─── */\n const scrollRef = React.useRef<HTMLDivElement>(null)\n const [isAtBottom, setIsAtBottom] = React.useState(true)\n const [hasNewBelow, setHasNewBelow] = React.useState(false)\n const prevMessageCountRef = React.useRef(messages.length)\n const loadMoreInFlightRef = React.useRef(false)\n const [isLoadingMore, setIsLoadingMore] = React.useState(false)\n // Marca de quando o componente montou — usada para suprimir animacao das mensagens iniciais\n const mountedRef = React.useRef(false)\n React.useEffect(() => {\n mountedRef.current = true\n }, [])\n\n const checkScrollPosition = React.useCallback(() => {\n const el = scrollRef.current\n if (!el) return\n const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight\n const atBottom = distanceFromBottom <= SCROLL_BOTTOM_THRESHOLD\n setIsAtBottom(atBottom)\n if (atBottom) setHasNewBelow(false)\n }, [])\n\n const scrollToBottom = React.useCallback((smooth = true) => {\n const el = scrollRef.current\n if (!el) return\n el.scrollTo({\n top: el.scrollHeight,\n behavior: smooth ? \"smooth\" : \"auto\",\n })\n setHasNewBelow(false)\n }, [])\n\n /* ─── Auto-scroll quando chega nova mensagem ─── */\n React.useEffect(() => {\n const prev = prevMessageCountRef.current\n const curr = messages.length\n prevMessageCountRef.current = curr\n\n if (curr <= prev) return\n\n if (isAtBottom) {\n // Esta no fundo → scroll suave pra nova msg\n requestAnimationFrame(() => scrollToBottom(true))\n } else {\n // Usuario subiu → mostra botao\n setHasNewBelow(true)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [messages.length])\n\n /* ─── Scroll handler (detecta posicao + paginacao) ─── */\n React.useEffect(() => {\n const el = scrollRef.current\n if (!el) return\n const handler = () => {\n checkScrollPosition()\n // Paginacao: se chegou perto do topo e ha onLoadMore, dispara\n if (\n onLoadMore &&\n !loadMoreInFlightRef.current &&\n el.scrollTop <= LOAD_MORE_THRESHOLD\n ) {\n loadMoreInFlightRef.current = true\n setIsLoadingMore(true)\n const prevScrollHeight = el.scrollHeight\n Promise.resolve(onLoadMore())\n .then(() => {\n // Preserva posicao visual apos prepend de mensagens antigas\n requestAnimationFrame(() => {\n const newScrollHeight = el.scrollHeight\n el.scrollTop = newScrollHeight - prevScrollHeight\n })\n })\n .finally(() => {\n loadMoreInFlightRef.current = false\n setIsLoadingMore(false)\n })\n }\n }\n el.addEventListener(\"scroll\", handler, { passive: true })\n // Inicial: garante scroll no fundo\n requestAnimationFrame(() => scrollToBottom(false))\n return () => el.removeEventListener(\"scroll\", handler)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [onLoadMore])\n\n /* ─── Aria-live announce de nova msg da IA (H1) ─── */\n const lastAiMessage = React.useMemo(() => {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].persona === \"ai\") return messages[i]\n }\n return null\n }, [messages])\n\n /* ─── Rating per-message: rastreia IDs cujo rating foi respondido (auto-dismiss imediato) ─── */\n const [ratedMessageIds, setRatedMessageIds] = React.useState<Set<string>>(() => new Set())\n\n // Merge dos labels customizados com defaults PT-BR. Usado pra renderizar E pra montar o callback.\n const mergedRatingLabels: MessageRatingLabels = React.useMemo(\n () => ({ ...DEFAULT_MESSAGE_RATING_LABELS, ...ratingLabels }),\n [ratingLabels]\n )\n\n const handleRateMessage = React.useCallback(\n (messageId: string, value: MessageRatingValue) => {\n // Marca como respondido IMEDIATAMENTE — re-render remove o rating do DOM antes\n // do paint visual de \"selected\", entao o usuario nao ve o estado intermediario.\n setRatedMessageIds((prev) => {\n const next = new Set(prev)\n next.add(messageId)\n return next\n })\n // Dispara callback com label completo (emoji/title/subtitle).\n onRate?.(messageId, value, mergedRatingLabels[value])\n },\n [onRate, mergedRatingLabels]\n )\n\n /* ─── MessageBar state interno (state machine de gravacao) ─── */\n const baseMessageBarState: MessageBarState = audioOnlyMode ? \"audio-only\" : \"default\"\n const [internalRecordingState, setInternalRecordingState] = React.useState<\n \"idle\" | \"recording\" | \"paused\"\n >(\"idle\")\n\n // Reset pra idle quando muda audioOnlyMode e nao esta gravando\n React.useEffect(() => {\n if (internalRecordingState === \"idle\") return\n // mantem o state se gravacao em andamento\n }, [audioOnlyMode, internalRecordingState])\n\n // State final do MessageBar — combina base, recording state e disabled\n const messageBarState: MessageBarState = isDisabled\n ? \"disabled\"\n : internalRecordingState === \"recording\"\n ? \"recording\"\n : internalRecordingState === \"paused\"\n ? \"paused\"\n : baseMessageBarState\n\n /* Wrappers dos callbacks: atualizam state interno + chamam consumer */\n const handleStartRecordingInternal = React.useCallback(() => {\n setInternalRecordingState(\"recording\")\n onStartRecording?.()\n }, [onStartRecording])\n\n const handlePauseRecordingInternal = React.useCallback(() => {\n setInternalRecordingState(\"paused\")\n onPauseRecording?.()\n }, [onPauseRecording])\n\n const handleResumeRecordingInternal = React.useCallback(() => {\n setInternalRecordingState(\"recording\")\n onResumeRecording?.()\n }, [onResumeRecording])\n\n const handleCancelRecordingInternal = React.useCallback(() => {\n setInternalRecordingState(\"idle\")\n onCancelRecording?.()\n }, [onCancelRecording])\n\n const handleSendAudioInternal = React.useCallback(() => {\n setInternalRecordingState(\"idle\")\n onSendAudio?.()\n }, [onSendAudio])\n\n /* Auto-pause ao atingir limite de duracao. Se consumer passou onMaxDurationReached,\n delega controle pra ele (sem auto-pause). */\n const handleMaxDurationInternal = React.useCallback(() => {\n if (onMaxDurationReached) {\n onMaxDurationReached()\n } else {\n handlePauseRecordingInternal()\n }\n }, [onMaxDurationReached, handlePauseRecordingInternal])\n\n /* Input controlled — sem isso o MessageBar fica \"engessado\" em value=\"\"\n (o consumer recebe o texto via onSendText, mas nao precisa controlar o input). */\n const [inputValue, setInputValue] = React.useState(\"\")\n const handleSendTextInternal = React.useCallback(\n (text: string) => {\n setInputValue(\"\")\n onSendText?.(text)\n },\n [onSendText]\n )\n\n /* ─── Render ──────────────────────────────────────── */\n return (\n <div\n data-slot=\"chat-thread\"\n className={cn(\"relative flex flex-col h-full bg-background\", className)}\n {...props}\n >\n {/* Banners de erro (topo) */}\n {offline && (\n <ChatThreadBanner variant=\"offline\">\n <span aria-hidden=\"true\">⚠</span>\n <span>{offlineBannerText}</span>\n </ChatThreadBanner>\n )}\n {isRateLimited && (\n <ChatThreadBanner variant=\"rate-limit\">\n <span aria-hidden=\"true\">⏱</span>\n <span>\n {rateLimitBannerText\n ? rateLimitBannerText(rateLimitSecondsLeft)\n : `Aguarde ${rateLimitSecondsLeft}s antes de enviar nova mensagem`}\n </span>\n </ChatThreadBanner>\n )}\n\n {/* Thread scrollavel */}\n <div\n ref={scrollRef}\n className=\"flex-1 overflow-y-auto px-4 py-4 space-y-4\"\n role=\"log\"\n aria-live=\"polite\"\n aria-atomic=\"false\"\n >\n {/* Spinner de paginacao no topo (G2) */}\n {isLoadingMore && (\n <div className=\"flex justify-center py-2\" aria-label=\"Carregando mensagens anteriores\">\n <span className=\"inline-block size-5 border-2 border-muted-foreground/30 border-t-muted-foreground rounded-full animate-spin\" />\n </div>\n )}\n\n {messages.map((msg, idx) => {\n // Suprime animacao das mensagens que ja existiam no mount inicial\n const enableAnim =\n mountedRef.current && idx >= prevMessageCountRef.current - 1\n\n const isFailedUser = msg.persona === \"user\" && msg.status === \"failed\"\n const isFailedAi = msg.persona === \"ai\" && msg.status === \"failed\"\n const isPendingUser = msg.persona === \"user\" && msg.status === \"pending\"\n\n return (\n <MessageBubbleAnimated key={msg.id} enableAnimation={enableAnim}>\n <ChatMessage\n persona={msg.persona}\n text={msg.text}\n audioSrc={msg.audioSrc}\n avatar={msg.persona === \"user\" ? userAvatar : undefined}\n author={msg.persona === \"user\" ? userName : undefined}\n // Indicador de pending: typing dots no lugar do conteudo normal e visual sutil\n loading={isPendingUser && !msg.text && !msg.audioSrc}\n className={cn(\n isPendingUser && \"opacity-80\",\n isFailedUser && \"[&_[data-slot=chat-message-bubble]]:border-2 [&_[data-slot=chat-message-bubble]]:border-destructive\"\n )}\n />\n {/* Retry inline pra msg do user que falhou (B2) */}\n {isFailedUser && (\n <div className=\"mt-2 flex justify-end\">\n <button\n type=\"button\"\n onClick={() => onRetryMessage?.(msg.id)}\n className=\"inline-flex items-center gap-1 text-xs text-destructive hover:underline focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 rounded\"\n >\n ↻ {retryButtonText}\n </button>\n </div>\n )}\n {/* Bubble de erro pra resposta da IA (B3) */}\n {isFailedAi && (\n /* Alinhado com a bubble da IA: offset = badge 32px + gap 12px = 44px (desktop).\n Mobile sem offset porque o badge fica oculto no ChatMessage AI. */\n <div className=\"mt-2 sm:pl-11 flex flex-col items-start gap-2\">\n <div className=\"text-sm text-destructive\">\n {msg.errorText || defaultAiErrorText}\n </div>\n <button\n type=\"button\"\n onClick={onRegenerateResponse}\n className=\"inline-flex items-center gap-1 text-xs text-primary hover:underline focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 rounded\"\n >\n ↻ {regenerateButtonText}\n </button>\n </div>\n )}\n {/* MessageRating inline na mensagem da IA que pede avaliacao (J).\n Alinhado com a bubble da IA (offset 44px desktop, 0 mobile).\n value={null} mantem o componente sem estado \"selecionado\" visual —\n ao clicar, o ChatThread marca como rated imediatamente (re-render remove\n do DOM antes do paint), e o consumer recebe (messageId, value, label). */}\n {msg.persona === \"ai\" && msg.requestRating && !ratedMessageIds.has(msg.id) && (\n <div className=\"mt-3 sm:pl-11 animate-thread-msg-enter\">\n <MessageRating\n value={null}\n labels={ratingLabels}\n onChange={(value) => handleRateMessage(msg.id, value)}\n />\n </div>\n )}\n </MessageBubbleAnimated>\n )\n })}\n\n {/* Typing indicator da IA durante thinking */}\n {isThinking && (\n <MessageBubbleAnimated enableAnimation>\n <ChatMessage persona=\"ai\" loading />\n </MessageBubbleAnimated>\n )}\n\n {/* Aria-live oculto pra anunciar ultima msg da IA */}\n <div className=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\">\n {lastAiMessage?.text || \"\"}\n </div>\n </div>\n\n {/* Scroll-to-bottom button (D1) */}\n {!isAtBottom && (\n <ScrollToBottomButton\n onClick={() => scrollToBottom(true)}\n hasNewMessage={hasNewBelow}\n />\n )}\n\n {/* Bottom area: MessageBar / StopResponse / hidden.\n O botao \"Parar resposta\" so aparece durante thinking E quando o consumer passa\n `onStopResponse` — quem nao implementa cancelamento ve o MessageBar sumir com\n animacao de saida e voltar com animacao de entrada quando a IA termina. */}\n <BottomSlot\n kind={\n isThinking\n ? onStopResponse\n ? \"stop\"\n : \"hidden\"\n : \"messagebar\"\n }\n messageBar={\n <MessageBar\n state={messageBarState}\n value={inputValue}\n onChange={setInputValue}\n onSendText={handleSendTextInternal}\n onSendAudio={handleSendAudioInternal}\n onStartRecording={handleStartRecordingInternal}\n onPauseRecording={handlePauseRecordingInternal}\n onResumeRecording={handleResumeRecordingInternal}\n onCancelRecording={handleCancelRecordingInternal}\n onTogglePlay={onTogglePlay}\n onSeekPlayback={onSeekPlayback}\n recordingStream={recordingStream}\n recordingDuration={recordingDuration}\n isPlaying={isPlaying}\n playbackProgress={playbackProgress}\n placeholder={placeholder}\n maxRecordingDuration={maxRecordingDuration}\n warnAtSecondsLeft={warnAtSecondsLeft}\n secondsLeftLabel={secondsLeftLabel}\n onMaxDurationReached={handleMaxDurationInternal}\n />\n }\n stopButton={\n <StopResponseButton onClick={onStopResponse} label={stopResponseText} />\n }\n />\n\n {/* Quota exhausted modal (C3) */}\n {quotaExhausted && (\n <AlertDialog open>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {quotaExhaustedConfig?.title || \"Limite atingido\"}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {quotaExhaustedConfig?.description ||\n \"Voce atingiu o limite de mensagens do seu plano. Faca upgrade para continuar.\"}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n {quotaExhaustedConfig?.onCancel && (\n <AlertDialogCancel onClick={quotaExhaustedConfig.onCancel}>\n {quotaExhaustedConfig.cancelLabel || \"Cancelar\"}\n </AlertDialogCancel>\n )}\n <AlertDialogAction onClick={quotaExhaustedConfig?.onCta}>\n {quotaExhaustedConfig?.ctaLabel || \"Fazer upgrade\"}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n )}\n </div>\n )\n}\n\nexport { ChatThread }\n"]}
|