import { cn } from "./index3.js";
import { AnimatePresence } from "./index308.js";
import { motion } from "./index359.js";
import * as React from "react";
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
//#region src/components/organisms/ai/AIResponseStream/AIResponseStream.tsx
function useTextStream({ textStream, speed = 50, onComplete }) {
	const [displayedText, setDisplayedText] = React.useState("");
	const [isStreaming, setIsStreaming] = React.useState(false);
	const [isComplete, setIsComplete] = React.useState(false);
	const indexRef = React.useRef(0);
	const fullTextRef = React.useRef("");
	const delay = React.useMemo(() => {
		const minDelay = 5;
		const maxDelay = 100;
		return maxDelay - (speed - 1) / 99 * (maxDelay - minDelay);
	}, [speed]);
	const reset = React.useCallback(() => {
		setDisplayedText("");
		setIsStreaming(false);
		setIsComplete(false);
		indexRef.current = 0;
		fullTextRef.current = "";
	}, []);
	React.useEffect(() => {
		if (typeof textStream === "string") {
			fullTextRef.current = textStream;
			setIsStreaming(true);
			indexRef.current = 0;
			const interval = setInterval(() => {
				if (indexRef.current < fullTextRef.current.length) {
					setDisplayedText(fullTextRef.current.slice(0, indexRef.current + 1));
					indexRef.current++;
				} else {
					clearInterval(interval);
					setIsStreaming(false);
					setIsComplete(true);
					onComplete?.();
				}
			}, delay);
			return () => clearInterval(interval);
		}
		let cancelled = false;
		setIsStreaming(true);
		(async () => {
			try {
				for await (const chunk of textStream) {
					if (cancelled) break;
					fullTextRef.current += chunk;
					setDisplayedText(fullTextRef.current);
				}
				if (!cancelled) {
					setIsStreaming(false);
					setIsComplete(true);
					onComplete?.();
				}
			} catch (error) {
				console.error("Stream error:", error);
				setIsStreaming(false);
			}
		})();
		return () => {
			cancelled = true;
		};
	}, [
		textStream,
		delay,
		onComplete
	]);
	return {
		displayedText,
		isStreaming,
		isComplete,
		reset
	};
}
function TypewriterText({ text, className }) {
	return /* @__PURE__ */ jsxs("span", {
		className,
		children: [text, /* @__PURE__ */ jsx(motion.span, {
			className: "inline-block w-0.5 h-[1em] bg-muted ms-0.5 align-text-bottom motion-reduce:animate-none motion-reduce:opacity-100",
			animate: { opacity: [1, 0] },
			transition: {
				duration: .5,
				repeat: Number.POSITIVE_INFINITY
			},
			"aria-hidden": "true"
		})]
	});
}
TypewriterText.displayName = "TypewriterText";
function FadeText({ text, className }) {
	return /* @__PURE__ */ jsx("span", {
		className,
		children: /* @__PURE__ */ jsx(AnimatePresence, {
			mode: "popLayout",
			children: text.split(" ").map((word, index) => /* @__PURE__ */ jsx(motion.span, {
				initial: {
					opacity: 0,
					y: 5
				},
				animate: {
					opacity: 1,
					y: 0
				},
				transition: {
					duration: .2,
					delay: index * .05
				},
				className: "inline-block me-1 motion-reduce:!opacity-100 motion-reduce:!transform-none",
				children: word
			}, `${index}-${word}`))
		})
	});
}
FadeText.displayName = "FadeText";
function AIResponseStream({ textStream, mode = "typewriter", speed = 50, onComplete, showCursor = true, className }) {
	const { displayedText, isStreaming, isComplete } = useTextStream({
		textStream,
		speed,
		onComplete
	});
	const showTypingCursor = showCursor && isStreaming && mode === "typewriter";
	return /* @__PURE__ */ jsxs("div", {
		"data-slot": "ai-response-stream",
		role: "status",
		"aria-live": "polite",
		"aria-busy": isStreaming,
		className: cn("text-base text-foreground", className),
		children: [mode === "typewriter" ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", { children: displayedText }), showTypingCursor && /* @__PURE__ */ jsx(motion.span, {
			className: "inline-block w-0.5 h-[1em] bg-muted-foreground ms-0.5 align-text-bottom motion-reduce:animate-none motion-reduce:opacity-100",
			animate: { opacity: [1, 0] },
			transition: {
				duration: .5,
				repeat: Number.POSITIVE_INFINITY
			},
			"aria-hidden": "true"
		})] }) : /* @__PURE__ */ jsx(FadeText, { text: displayedText }), isComplete && !isStreaming && /* @__PURE__ */ jsx("span", {
			className: "sr-only",
			children: "Streaming complete"
		})]
	});
}
AIResponseStream.displayName = "AIResponseStream";
//#endregion
export { AIResponseStream, FadeText, TypewriterText, useTextStream };

//# sourceMappingURL=index433.js.map