@@ -29,7 +29,7 @@ export const MentionTextarea = forwardRef<HTMLDivElement, MentionTextareaProps>(
2929
3030 // Rotating placeholder
3131 const [ placeholderIndex , setPlaceholderIndex ] = useState ( 0 )
32- const placeholders = [ 'Ask Anything !' , 'Tip: Use @ to mention tables or models' ]
32+ const placeholders = [ 'Ask anything !' , 'Tip: Use @ to mention any tables or models' ]
3333
3434 useEffect ( ( ) => {
3535 const interval = setInterval ( ( ) => {
@@ -91,19 +91,23 @@ export const MentionTextarea = forwardRef<HTMLDivElement, MentionTextareaProps>(
9191 const getCursorPosition = useCallback ( ( ) => {
9292 const sel = window . getSelection ( )
9393 if ( ! sel ?. rangeCount || ! editableRef . current ) return 0
94-
94+
9595 const range = sel . getRangeAt ( 0 ) . cloneRange ( )
9696 range . selectNodeContents ( editableRef . current )
9797 range . setEnd ( sel . getRangeAt ( 0 ) . startContainer , sel . getRangeAt ( 0 ) . startOffset )
98- return range . toString ( ) . length
98+
99+ // Create a temporary div to get innerText (consistent with getTextContent)
100+ const tempDiv = document . createElement ( 'div' )
101+ tempDiv . appendChild ( range . cloneContents ( ) )
102+ return ( tempDiv . innerText || tempDiv . textContent || '' ) . length
99103 } , [ ] )
100104
101105 // Update content with highlighted mentions
102106 const updateContent = useCallback ( ( text : string ) => {
103107 if ( ! editableRef . current ) return
104108
105109 // If text is empty, clear innerHTML to show placeholder
106- if ( ! text . trim ( ) ) {
110+ if ( text . length === 0 ) {
107111 editableRef . current . innerHTML = ''
108112 return
109113 }
@@ -140,11 +144,29 @@ export const MentionTextarea = forwardRef<HTMLDivElement, MentionTextareaProps>(
140144 editableRef . current . innerHTML = html
141145 } , [ mentionItems ] )
142146
147+ // Handle paste events for immediate formatting
148+ const handlePaste = useCallback ( ( _e : React . ClipboardEvent < HTMLDivElement > ) => {
149+ // Let the paste happen first, then immediately format
150+ setTimeout ( ( ) => {
151+ const newValue = getTextContent ( )
152+ const cursorPosition = getCursorPosition ( )
153+
154+ // Call original onChange
155+ if ( onChange ) {
156+ onChange ( { target : { value : newValue } } )
157+ }
158+
159+ // Immediately update content for paste
160+ updateContent ( newValue )
161+ setCursorPosition ( cursorPosition )
162+ } , 0 )
163+ } , [ getTextContent , getCursorPosition , onChange , updateContent , setCursorPosition ] )
164+
143165 // Handle input changes
144- const handleInput = useCallback ( ( e : React . FormEvent < HTMLDivElement > ) => {
166+ const handleInput = useCallback ( ( _e : React . FormEvent < HTMLDivElement > ) => {
145167 const newValue = getTextContent ( )
146168 const cursorPosition = getCursorPosition ( )
147-
169+
148170 // Call original onChange
149171 if ( onChange ) {
150172 onChange ( { target : { value : newValue } } )
@@ -258,14 +280,14 @@ export const MentionTextarea = forwardRef<HTMLDivElement, MentionTextareaProps>(
258280
259281 // Call original onKeyDown
260282 if ( onKeyDown ) {
261- onKeyDown ( e )
283+ onKeyDown ( e as unknown as React . KeyboardEvent < HTMLTextAreaElement > )
262284 }
263285 } , [ showDropdown , filteredItems , selectedIndex , handleMentionSelect , onKeyDown ] )
264286
265287 // Update content when value prop changes (only if not focused)
266288 useEffect ( ( ) => {
267289 if ( value !== undefined && editableRef . current && document . activeElement !== editableRef . current ) {
268- updateContent ( value )
290+ updateContent ( String ( value ) )
269291 }
270292 } , [ value , updateContent ] )
271293
@@ -308,6 +330,7 @@ export const MentionTextarea = forwardRef<HTMLDivElement, MentionTextareaProps>(
308330 suppressContentEditableWarning
309331 onInput = { handleInput }
310332 onKeyDown = { handleKeyDown }
333+ onPaste = { handlePaste }
311334 minH = "48px"
312335 maxHeight = { 300 }
313336 overflow = "auto"
0 commit comments