69 lines
2.2 KiB
TypeScript
69 lines
2.2 KiB
TypeScript
"use client";
|
||
/**
|
||
* ChatInputBar 输入栏
|
||
*
|
||
* 原始 Dart: lib/ui/chat/widgets/chat_input_bar.dart(121 行)
|
||
*
|
||
* 状态:
|
||
* - input:受控文本
|
||
* - isFocused:是否聚焦(控制外层 pink-bg / box-shadow / padding-top)
|
||
* - hasContent:是否有 trim 内容(决定发送按钮是否启用)
|
||
*
|
||
* 容器层次(与 Dart 一致):
|
||
* - 外层 `.bar`:focused 时 `padding-top: md` + 粉色背景 + 阴影
|
||
* - 内层 `.row`:白底 + `border-radius: 32` + focused 时 accent 边框
|
||
* - Row:[ChatInputTextField (Expanded), ChatSendButton]
|
||
*
|
||
* 行为:
|
||
* - send 后清空 input + 保持 textarea 焦点(与 Dart `_focusNode.requestFocus()` 一致)
|
||
*
|
||
* 注意:Dart 源里的 `ImageUploadButton` 已被注释(`// const ImageUploadButton()`),
|
||
* `ChatMoreButton` / `FunctionButtonBar` 不存在于 Dart 源;本组件仅保留与 Dart 一致的部分。
|
||
*/
|
||
import { useRef, useState } from "react";
|
||
|
||
import { useChatDispatch } from "@/stores/chat/chat-context";
|
||
|
||
import { ChatInputTextField } from "./chat-input-text-field";
|
||
import { ChatSendButton } from "./chat-send-button";
|
||
import styles from "./chat-input-bar.module.css";
|
||
|
||
export interface ChatInputBarProps {
|
||
disabled?: boolean;
|
||
}
|
||
|
||
export function ChatInputBar({ disabled = false }: ChatInputBarProps) {
|
||
const dispatch = useChatDispatch();
|
||
const [input, setInput] = useState("");
|
||
const [isFocused, setIsFocused] = useState(false);
|
||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||
|
||
const hasContent = input.trim().length > 0;
|
||
|
||
const handleSend = () => {
|
||
if (!hasContent) return;
|
||
dispatch({ type: "ChatSendMessage", content: input });
|
||
setInput("");
|
||
textareaRef.current?.focus();
|
||
};
|
||
|
||
return (
|
||
<div className={`${styles.bar} ${isFocused ? styles.barFocused : ""}`}>
|
||
<div className={`${styles.row} ${isFocused ? styles.rowFocused : ""}`}>
|
||
<ChatInputTextField
|
||
ref={textareaRef}
|
||
value={input}
|
||
onChange={setInput}
|
||
onSubmit={handleSend}
|
||
onFocusChange={setIsFocused}
|
||
disabled={disabled}
|
||
/>
|
||
<ChatSendButton
|
||
disabled={!hasContent || disabled}
|
||
onClick={handleSend}
|
||
/>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|