@@ -29,6 +29,11 @@ export function MarkdownCombo({ value = "", onChange, ...props }: MDEditorProps)
2929 end : ta . selectionEnd ?? 0 ,
3030 } ;
3131 } ;
32+ const getSelection = ( ) : string => {
33+ updateSelection ( ) ;
34+ const { start, end } = selectionRef . current ;
35+ return value . slice ( start , end ) ;
36+ }
3237 const setSelection = ( start : number , end : number ) => {
3338 requestAnimationFrame ( ( ) => {
3439 const ta = textareaRef . current ;
@@ -38,6 +43,16 @@ export function MarkdownCombo({ value = "", onChange, ...props }: MDEditorProps)
3843 selectionRef . current = { start : start , end : end } ;
3944 } ) ;
4045 } ;
46+ const replaceSelection = ( replaceText : string ) => {
47+ updateSelection ( ) ;
48+ const { start, end } = selectionRef . current ;
49+
50+ const nextValue = value . slice ( 0 , start ) + replaceText + value . slice ( end ) ;
51+ onChange ?.( nextValue ) ;
52+
53+ const nextCursor = start + replaceText . length ;
54+ setSelection ( nextCursor , nextCursor ) ;
55+ }
4156
4257 useEffect ( ( ) => {
4358 const root = editorRef . current ;
@@ -93,20 +108,14 @@ export function MarkdownCombo({ value = "", onChange, ...props }: MDEditorProps)
93108 // handle pasting http urls (for auto hyperlink)
94109 const pasteText = e . clipboardData ?. getData ( "text/plain" ) ;
95110 if ( pasteText ?. startsWith ( "https://" ) ) {
96- updateSelection ( ) ;
97- const { start, end } = selectionRef . current ;
98111
99112 // only do special handling if there was text selected
100113 // otherwise use the normal handling, so the undo/redo is preserved
101- const selectedText = value . slice ( start , end ) ;
114+ const selectedText = getSelection ( ) ;
102115 if ( selectedText ) {
103116 e . preventDefault ( ) ;
104- const replaceText = `[${ selectedText } ](${ pasteText } )` ;
105- const nextValue = value . slice ( 0 , start ) + replaceText + value . slice ( end ) ;
106- onChange ?.( nextValue ) ;
107-
108- const nextCursor = start + replaceText . length ;
109- setSelection ( nextCursor , nextCursor ) ;
117+ const replacementText = `[${ selectedText } ](${ pasteText } )` ;
118+ replaceSelection ( replacementText ) ;
110119 return ;
111120 }
112121 }
@@ -115,7 +124,6 @@ export function MarkdownCombo({ value = "", onChange, ...props }: MDEditorProps)
115124 const items = [ ...( allItems ?? [ ] ) ] . filter ( ( i ) => i . type . startsWith ( "image/" ) ) ;
116125 if ( ! items . length ) return ;
117126
118-
119127 setUploading ( true ) ;
120128
121129 for ( const item of items ) {
@@ -128,8 +136,9 @@ export function MarkdownCombo({ value = "", onChange, ...props }: MDEditorProps)
128136 {
129137 onSuccess : ( image ) => {
130138 const baseUrl = window . location . origin ;
131- const inserted = `\n\n` ;
132- onChange ?.( `${ value } ${ inserted } ` ) ;
139+ const selectedText = getSelection ( ) || "pasted image" ;
140+ const replacementText = `` ;
141+ replaceSelection ( replacementText ) ;
133142 } ,
134143 onError : ( ) => toast . error ( "Failed" , { description : "Probably an unsupported file type" } ) ,
135144 onSettled : ( ) => setUploading ( false ) ,
@@ -145,19 +154,8 @@ export function MarkdownCombo({ value = "", onChange, ...props }: MDEditorProps)
145154 const toggleEmojiSelector = ( ) => setEmojiOpen ( ( v ) => ! v ) ;
146155
147156 const handleEmojiClick = ( emojiData : EmojiClickData ) => {
148- const emoji = emojiData . emoji ;
149-
150- updateSelection ( ) ;
151-
152- const { start, end } = selectionRef . current ;
153-
154- const nextValue = value . slice ( 0 , start ) + emoji + value . slice ( end ) ;
155-
156- onChange ?.( nextValue ) ;
157+ replaceSelection ( emojiData . emoji ) ;
157158 setEmojiOpen ( false ) ;
158-
159- const nextCursor = start + emoji . length ;
160- setSelection ( nextCursor , nextCursor ) ;
161159 } ;
162160
163161 return (
0 commit comments