@@ -89,6 +89,8 @@ const EXAMPLES = [
8989 "prompt.example.25" ,
9090] as const
9191
92+ const NON_EMPTY_TEXT = / [ ^ \s \u200B ] /
93+
9294export const PromptInput : Component < PromptInputProps > = ( props ) => {
9395 const sdk = useSDK ( )
9496 const sync = useSync ( )
@@ -636,7 +638,9 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
636638 let buffer = ""
637639
638640 const flushText = ( ) => {
639- const content = buffer . replace ( / \r \n ? / g, "\n" ) . replace ( / \u200B / g, "" )
641+ let content = buffer
642+ if ( content . includes ( "\r" ) ) content = content . replace ( / \r \n ? / g, "\n" )
643+ if ( content . includes ( "\u200B" ) ) content = content . replace ( / \u200B / g, "" )
640644 buffer = ""
641645 if ( ! content ) return
642646 parts . push ( { type : "text" , content, start : position , end : position + content . length } )
@@ -714,10 +718,12 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
714718 const rawParts = parseFromDOM ( )
715719 const images = imageAttachments ( )
716720 const cursorPosition = getCursorPosition ( editorRef )
717- const rawText = rawParts . map ( ( p ) => ( "content" in p ? p . content : "" ) ) . join ( "" )
718- const trimmed = rawText . replace ( / \u200B / g, "" ) . trim ( )
721+ const rawText =
722+ rawParts . length === 1 && rawParts [ 0 ] ?. type === "text"
723+ ? rawParts [ 0 ] . content
724+ : rawParts . map ( ( p ) => ( "content" in p ? p . content : "" ) ) . join ( "" )
719725 const hasNonText = rawParts . some ( ( part ) => part . type !== "text" )
720- const shouldReset = trimmed . length === 0 && ! hasNonText && images . length === 0
726+ const shouldReset = ! NON_EMPTY_TEXT . test ( rawText ) && ! hasNonText && images . length === 0
721727
722728 if ( shouldReset ) {
723729 closePopover ( )
@@ -757,19 +763,31 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
757763 }
758764
759765 const addPart = ( part : ContentPart ) => {
766+ if ( part . type === "image" ) return false
767+
760768 const selection = window . getSelection ( )
761- if ( ! selection || selection . rangeCount === 0 ) return
769+ if ( ! selection ) return false
762770
763- const cursorPosition = getCursorPosition ( editorRef )
764- const currentPrompt = prompt . current ( )
765- const rawText = currentPrompt . map ( ( p ) => ( "content" in p ? p . content : "" ) ) . join ( "" )
766- const textBeforeCursor = rawText . substring ( 0 , cursorPosition )
767- const atMatch = textBeforeCursor . match ( / @ ( \S * ) $ / )
771+ if ( selection . rangeCount === 0 || ! editorRef . contains ( selection . anchorNode ) ) {
772+ editorRef . focus ( )
773+ const cursor = prompt . cursor ( ) ?? promptLength ( prompt . current ( ) )
774+ setCursorPosition ( editorRef , cursor )
775+ }
776+
777+ if ( selection . rangeCount === 0 ) return false
778+ const range = selection . getRangeAt ( 0 )
779+ if ( ! editorRef . contains ( range . startContainer ) ) return false
768780
769781 if ( part . type === "file" || part . type === "agent" ) {
782+ const cursorPosition = getCursorPosition ( editorRef )
783+ const rawText = prompt
784+ . current ( )
785+ . map ( ( p ) => ( "content" in p ? p . content : "" ) )
786+ . join ( "" )
787+ const textBeforeCursor = rawText . substring ( 0 , cursorPosition )
788+ const atMatch = textBeforeCursor . match ( / @ ( \S * ) $ / )
770789 const pill = createPill ( part )
771790 const gap = document . createTextNode ( " " )
772- const range = selection . getRangeAt ( 0 )
773791
774792 if ( atMatch ) {
775793 const start = atMatch . index ?? cursorPosition - atMatch [ 0 ] . length
@@ -784,8 +802,9 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
784802 range . collapse ( true )
785803 selection . removeAllRanges ( )
786804 selection . addRange ( range )
787- } else if ( part . type === "text" ) {
788- const range = selection . getRangeAt ( 0 )
805+ }
806+
807+ if ( part . type === "text" ) {
789808 const fragment = createTextFragment ( part . content )
790809 const last = fragment . lastChild
791810 range . deleteContents ( )
@@ -821,6 +840,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
821840
822841 handleInput ( )
823842 closePopover ( )
843+ return true
824844 }
825845
826846 const addToHistory = ( prompt : Prompt , mode : "normal" | "shell" ) => {
0 commit comments