@@ -9,6 +9,7 @@ type UseComposerAutocompleteStateArgs = {
99 selectionStart : number | null ;
1010 disabled : boolean ;
1111 skills : Skill [ ] ;
12+ files : string [ ] ;
1213 textareaRef : React . RefObject < HTMLTextAreaElement | null > ;
1314 setText : ( next : string ) => void ;
1415 setSelectionStart : ( next : number | null ) => void ;
@@ -19,6 +20,7 @@ export function useComposerAutocompleteState({
1920 selectionStart,
2021 disabled,
2122 skills,
23+ files,
2224 textareaRef,
2325 setText,
2426 setSelectionStart,
@@ -34,9 +36,22 @@ export function useComposerAutocompleteState({
3436 [ skills ] ,
3537 ) ;
3638
39+ const fileItems = useMemo < AutocompleteItem [ ] > (
40+ ( ) =>
41+ files . map ( ( path ) => ( {
42+ id : path ,
43+ label : path ,
44+ insertText : path ,
45+ } ) ) ,
46+ [ files ] ,
47+ ) ;
48+
3749 const triggers = useMemo (
38- ( ) => [ { trigger : "$" , items : skillItems } ] ,
39- [ skillItems ] ,
50+ ( ) => [
51+ { trigger : "$" , items : skillItems } ,
52+ { trigger : "@" , items : fileItems } ,
53+ ] ,
54+ [ fileItems , skillItems ] ,
4055 ) ;
4156
4257 const {
@@ -58,19 +73,28 @@ export function useComposerAutocompleteState({
5873 if ( ! autocompleteRange ) {
5974 return ;
6075 }
61- const before = text . slice ( 0 , autocompleteRange . start ) ;
76+ const triggerIndex = Math . max ( 0 , autocompleteRange . start - 1 ) ;
77+ const triggerChar = text [ triggerIndex ] ?? "" ;
78+ const before =
79+ triggerChar === "@"
80+ ? text . slice ( 0 , triggerIndex )
81+ : text . slice ( 0 , autocompleteRange . start ) ;
6282 const after = text . slice ( autocompleteRange . end ) ;
6383 const insert = item . insertText ?? item . label ;
84+ const actualInsert = triggerChar === "@"
85+ ? insert . replace ( / ^ @ + / , "" )
86+ : insert ;
6487 const needsSpace = after . length === 0 ? true : ! / ^ \s / . test ( after ) ;
65- const nextText = `${ before } ${ insert } ${ needsSpace ? " " : "" } ${ after } ` ;
88+ const nextText = `${ before } ${ actualInsert } ${ needsSpace ? " " : "" } ${ after } ` ;
6689 setText ( nextText ) ;
6790 closeAutocomplete ( ) ;
6891 requestAnimationFrame ( ( ) => {
6992 const textarea = textareaRef . current ;
7093 if ( ! textarea ) {
7194 return ;
7295 }
73- const cursor = before . length + insert . length + ( needsSpace ? 1 : 0 ) ;
96+ const cursor =
97+ before . length + actualInsert . length + ( needsSpace ? 1 : 0 ) ;
7498 textarea . focus ( ) ;
7599 textarea . setSelectionRange ( cursor , cursor ) ;
76100 setSelectionStart ( cursor ) ;
0 commit comments