import Box from "@mui/material/Box"; import Typography from "@mui/material/Typography"; import Chip from "@mui/material/Chip"; import { motion, useReducedMotion, type Variants } from "framer-motion"; import type { ChatTurn } from "./types"; import OdinMark from "./OdinMark"; const MotionBox = motion.create(Box); // Staggered hero entrance (skipped under prefers-reduced-motion). const heroContainer: Variants = { hidden: {}, show: { transition: { staggerChildren: 0.12, delayChildren: 0.06 } }, }; const heroItem: Variants = { hidden: { opacity: 0, y: 14 }, show: { opacity: 1, y: 0, transition: { duration: 0.55, ease: [0.16, 1, 0.3, 1] }, }, }; interface OdinThreadProps { turns: ChatTurn[]; busy: boolean; loading: boolean; greetingPhrase?: string; userName?: string; threadRef: React.RefObject; } /** Small Odin avatar shown to the left of assistant bubbles. */ function OdinAvatar({ size = 28 }: { size?: number }) { return ( O ); } export default function OdinThread({ turns, busy, loading, greetingPhrase, userName, threadRef, }: OdinThreadProps) { const reduce = useReducedMotion(); const containerMotion = reduce ? {} : { variants: heroContainer, initial: "hidden", animate: "show" }; const itemMotion = reduce ? {} : { variants: heroItem }; return ( {/* Loading state — history is being fetched */} {loading && ( Načítám… )} {/* Empty state */} {turns.length === 0 && !busy && !loading && ( {greetingPhrase || "Dobrý den"} {userName && ( <> ,{" "} ({ fontStyle: "italic", backgroundImage: `linear-gradient(120deg, ${t.vars!.palette.primary.light}, ${t.vars!.palette.primary.main})`, WebkitBackgroundClip: "text", backgroundClip: "text", WebkitTextFillColor: "transparent", })} > {userName} )} Zeptejte se na cokoli, nebo přiložte fakturu — Odin ji přečte a připraví k uložení. )} {/* Message bubbles */} {turns.map((t, i) => { const isUser = t.role === "user"; return ( {!isUser && } {/* Tools the assistant consulted for this turn (Phase 2a). */} {!isUser && t.tools && t.tools.length > 0 && ( {t.tools.map((tool, j) => ( ))} )} {/* Color MUST sit on the Typography: GlobalStyles pins `p` to text.secondary, which beats a color merely inherited from the Box. An sx class on the element wins over that element rule. */} {t.content} ); })} {/* Busy indicator */} {busy && ( Pracuji… )} ); }