import { useCallback, useEffect, useId, useState, useSyncExternalStore } from "react"; import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext"; import { useCellValue } from "@mdxeditor/gurx"; import { SidecarCard } from "../card"; import { widgets$ } from "../widget-options"; import type { FormEvent, KeyboardEvent } from "react"; import type { Research } from "@chopin/protocol"; import type { ResearchNode } from "@chopin/dialect"; import type { ResearchStore } from "../widget-options"; const STAGES: Record = { queued: "Queued", searching: "Searching", analyzing: "Analyzing", writing: "Writing", publishing: "Publishing", ready: "Research ready", failed: "Research failed", cancelled: "Research cancelled", }; export type ResearchComposerProps = { blocked?: string; busyLabel?: string; cancelDisabled?: boolean; cancelLabel?: string; dismissible?: boolean; error?: string; onCancel: () => void; onChange: (value: string) => void; onEscape?: () => void; onSubmit: () => void; question: string; questionLocked?: boolean; submitLabel?: string; submitting?: boolean; }; export function handleResearchComposerKey( event: Pick, onEscape: () => void, dismissible = true, ) { if (event.key !== "Escape") return; event.preventDefault(); event.stopPropagation(); if (dismissible) onEscape(); } export function ResearchComposer( { blocked, busyLabel = "Starting…", cancelDisabled, cancelLabel = "Cancel", dismissible = true, error, onCancel, onChange, onEscape, onSubmit, question, questionLocked, submitLabel = "Start research", submitting, }: ResearchComposerProps, ) { let id = useId(); let submit = (event: FormEvent) => { event.preventDefault(); onSubmit(); }; return (
handleResearchComposerKey(event, onEscape, dismissible) : undefined} onSubmit={submit} >