Files
wehub-resource-sync e30e75b5d4
Changesets / Create Version PR (push) Has been cancelled
Deploy Shadcn Registry / Deploy Production (push) Has been cancelled
Template Metrics / LOC + Bundle Size (push) Has been cancelled
Code Quality / Oxlint + Oxfmt (push) Has been cancelled
Code Quality / Template Sync (push) Has been cancelled
Code Quality / Build Changed Packages (push) Has been cancelled
Code Quality / Test Changed Packages (push) Has been cancelled
Deploy Expo Example / Deploy Production (push) Has been cancelled
Deploy Ink Example / Deploy Production (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.12) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:40:13 +08:00

78 lines
2.2 KiB
TypeScript

"use client";
import type { FormEvent, KeyboardEvent } from "react";
import { cn } from "@/lib/utils";
import { ArrowUp, Square } from "lucide-react";
type ComposerProps = {
value: string;
onChange: (value: string) => void;
onSubmit: () => void;
isRunning: boolean;
onCancel?: () => void;
};
export function Composer({
value,
onChange,
onSubmit,
isRunning,
onCancel,
}: ComposerProps) {
const handleSubmit = (e: FormEvent) => {
e.preventDefault();
if (value.trim() && !isRunning) {
onSubmit();
}
};
const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
if (value.trim() && !isRunning) {
onSubmit();
}
}
};
return (
<form onSubmit={handleSubmit} className="p-4 pt-2">
<div className="bg-background flex items-end gap-2 rounded-2xl border px-3 py-2 shadow-sm">
<textarea
value={value}
onChange={(e) => onChange(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="Send a message..."
className="placeholder:text-muted-foreground max-h-32 min-h-8 flex-1 resize-none bg-transparent py-1 text-sm leading-normal outline-none"
rows={1}
autoFocus
/>
{isRunning ? (
<button
type="button"
onClick={onCancel}
className="bg-destructive text-destructive-foreground hover:bg-destructive/90 flex size-8 shrink-0 items-center justify-center rounded-full transition-colors"
aria-label="Stop generating"
>
<Square className="size-3 fill-current" />
</button>
) : (
<button
type="submit"
disabled={!value.trim()}
className={cn(
"flex size-8 shrink-0 items-center justify-center rounded-full transition-colors",
value.trim()
? "bg-primary text-primary-foreground hover:bg-primary/90"
: "bg-muted text-muted-foreground",
)}
aria-label="Send message"
>
<ArrowUp className="size-4" />
</button>
)}
</div>
</form>
);
}