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
78 lines
2.2 KiB
TypeScript
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>
|
|
);
|
|
}
|