@@ -5,6 +5,9 @@ import {showLoading} from "../../../services/dom";
55import { MentionNode } from "@lexical/link/LexicalMentionNode" ;
66import { debounce } from "../../../services/util" ;
77import { $createTextNode } from "lexical" ;
8+ import { KeyboardNavigationHandler } from "../../../services/keyboard-navigation" ;
9+
10+ import searchIcon from "@icons/search.svg" ;
811
912function userClickHandler ( onSelect : ( id : number , name : string , slug : string ) => void ) : ( event : PointerEvent ) => void {
1013 return ( event : PointerEvent ) => {
@@ -51,7 +54,7 @@ function handleUserListLoading(selectList: HTMLElement) {
5154
5255 const updateUserList = async ( searchTerm : string ) => {
5356 // Empty list
54- for ( const child of [ ...selectList . children ] . slice ( 1 ) ) {
57+ for ( const child of [ ...selectList . children ] ) {
5558 child . remove ( ) ;
5659 }
5760
@@ -60,7 +63,7 @@ function handleUserListLoading(selectList: HTMLElement) {
6063 if ( cache . has ( searchTerm ) ) {
6164 responseHtml = cache . get ( searchTerm ) || '' ;
6265 } else {
63- const loadingWrap = el ( 'li' ) ;
66+ const loadingWrap = el ( 'div' , { class : 'flex-container-row items-center dropdown-search-item' } ) ;
6467 showLoading ( loadingWrap ) ;
6568 selectList . appendChild ( loadingWrap ) ;
6669
@@ -71,18 +74,17 @@ function handleUserListLoading(selectList: HTMLElement) {
7174 }
7275
7376 const doc = htmlToDom ( responseHtml ) ;
74- const toInsert = doc . querySelectorAll ( 'li' ) ;
77+ const toInsert = doc . body . children ;
7578 for ( const listEl of toInsert ) {
7679 const adopted = window . document . adoptNode ( listEl ) as HTMLElement ;
7780 selectList . appendChild ( adopted ) ;
7881 }
79-
8082 } ;
8183
8284 // Initial load
8385 updateUserList ( '' ) ;
8486
85- const input = selectList . querySelector ( 'input' ) as HTMLInputElement ;
87+ const input = selectList . parentElement ?. querySelector ( 'input' ) as HTMLInputElement ;
8688 const updateUserListDebounced = debounce ( updateUserList , 200 , false ) ;
8789 input . addEventListener ( 'input' , ( ) => {
8890 const searchTerm = input . value ;
@@ -92,8 +94,15 @@ function handleUserListLoading(selectList: HTMLElement) {
9294
9395function buildAndShowUserSelectorAtElement ( context : EditorUiContext , mentionDOM : HTMLElement ) : HTMLElement {
9496 const searchInput = el ( 'input' , { type : 'text' } ) ;
95- const searchItem = el ( 'li' , { } , [ searchInput ] ) ;
96- const userSelect = el ( 'ul' , { class : 'suggestion-box dropdown-menu' } , [ searchItem ] ) ;
97+ const list = el ( 'div' , { class : 'dropdown-search-list' } ) ;
98+ const iconWrap = el ( 'div' ) ;
99+ iconWrap . innerHTML = searchIcon ;
100+ const icon = iconWrap . children [ 0 ] as HTMLElement ;
101+ icon . classList . add ( 'svg-icon' ) ;
102+ const userSelect = el ( 'div' , { class : 'dropdown-search-dropdown compact card' } , [
103+ el ( 'div' , { class : 'dropdown-search-search' } , [ icon , searchInput ] ) ,
104+ list ,
105+ ] ) ;
97106
98107 context . containerDOM . appendChild ( userSelect ) ;
99108
@@ -111,28 +120,32 @@ function buildAndShowUserSelectorAtElement(context: EditorUiContext, mentionDOM:
111120}
112121
113122export class MentionDecorator extends EditorDecorator {
114- protected completedSetup : boolean = false ;
115123 protected abortController : AbortController | null = null ;
116- protected selectList : HTMLElement | null = null ;
124+ protected dropdownContainer : HTMLElement | null = null ;
117125 protected mentionElement : HTMLElement | null = null ;
118126
119127 setup ( element : HTMLElement ) {
120128 this . mentionElement = element ;
121- this . completedSetup = true ;
129+
130+ element . addEventListener ( 'click' , ( event : PointerEvent ) => {
131+ this . showSelection ( ) ;
132+ event . preventDefault ( ) ;
133+ event . stopPropagation ( ) ;
134+ } ) ;
122135 }
123136
124137 showSelection ( ) {
125- if ( ! this . mentionElement ) {
138+ if ( ! this . mentionElement || this . dropdownContainer ) {
126139 return ;
127140 }
128141
129142 this . hideSelection ( ) ;
130143 this . abortController = new AbortController ( ) ;
131144
132- this . selectList = buildAndShowUserSelectorAtElement ( this . context , this . mentionElement ) ;
133- handleUserListLoading ( this . selectList ) ;
145+ this . dropdownContainer = buildAndShowUserSelectorAtElement ( this . context , this . mentionElement ) ;
146+ handleUserListLoading ( this . dropdownContainer . querySelector ( '.dropdown-search-list' ) as HTMLElement ) ;
134147
135- this . selectList . addEventListener ( 'click' , userClickHandler ( ( id , name , slug ) => {
148+ this . dropdownContainer . addEventListener ( 'click' , userClickHandler ( ( id , name , slug ) => {
136149 this . context . editor . update ( ( ) => {
137150 const mentionNode = this . getNode ( ) as MentionNode ;
138151 this . hideSelection ( ) ;
@@ -141,12 +154,22 @@ export class MentionDecorator extends EditorDecorator {
141154 } ) ;
142155 } ) , { signal : this . abortController . signal } ) ;
143156
144- handleUserSelectCancel ( this . context , this . selectList , this . abortController , this . revertMention . bind ( this ) ) ;
157+ handleUserSelectCancel ( this . context , this . dropdownContainer , this . abortController , ( ) => {
158+ if ( ( this . getNode ( ) as MentionNode ) . hasUserSet ( ) ) {
159+ this . hideSelection ( )
160+ } else {
161+ this . revertMention ( ) ;
162+ }
163+ } ) ;
164+
165+ new KeyboardNavigationHandler ( this . dropdownContainer ) ;
145166 }
146167
147168 hideSelection ( ) {
148169 this . abortController ?. abort ( ) ;
149- this . selectList ?. remove ( ) ;
170+ this . dropdownContainer ?. remove ( ) ;
171+ this . abortController = null ;
172+ this . dropdownContainer = null ;
150173 }
151174
152175 revertMention ( ) {
@@ -158,15 +181,7 @@ export class MentionDecorator extends EditorDecorator {
158181 } ) ;
159182 }
160183
161- update ( ) {
162- //
163- }
164-
165184 render ( element : HTMLElement ) : void {
166- if ( this . completedSetup ) {
167- this . update ( ) ;
168- } else {
169- this . setup ( element ) ;
170- }
185+ this . setup ( element ) ;
171186 }
172187}
0 commit comments