104104 <v-text-field
105105 ref =" searchRef"
106106 v-model =" search"
107+ v-intersect =" onSearchIntersect"
107108 hide-details =" auto"
108109 prepend-inner-icon =" fa fa-search"
109110 :loading =" listCaller.isLoading"
@@ -548,13 +549,13 @@ const { inputBindAttrs, valueMeta, valueOwner } = useMetadataProps(props, (v) =>
548549
549550const search = ref (null as string | null );
550551const menuOpen = ref (false );
551- const menuOpenForced = ref (false );
552552const searchChanged = ref (new Date ());
553553const mainValue = ref (" " );
554554const createItemLoading = ref (false );
555555const createItemError = ref (" " as string | null );
556556const pendingSelection = ref (0 );
557557const selectionIndex = ref (- 1 );
558+ const pendingSearchSelect = ref (false );
558559
559560/** The models representing the current selected item(s)
560561 * in the case that only the PK was provided to the component.
@@ -1230,49 +1231,41 @@ function onIntersect(isIntersecting: boolean) {
12301231 }, 50 );
12311232}
12321233
1234+ async function onSearchIntersect (isIntersecting : boolean ) {
1235+ if (! isIntersecting) return ;
1236+
1237+ const input = searchRef .value ? .$el .querySelector (" input" ) as HTMLInputElement ;
1238+ if (! input) return ;
1239+
1240+ await nextTick ();
1241+ await new Promise ((resolve ) => setTimeout (resolve, 25 ));
1242+
1243+ input .focus ();
1244+
1245+ if (pendingSearchSelect .value ) {
1246+ input .select ();
1247+ pendingSearchSelect .value = false ;
1248+ }
1249+ }
1250+
12331251async function openMenu (select ?: boolean ): Promise<void> {
12341252 if (! isInteractive .value || forceClosed) return ;
12351253
1254+ if (menuOpen .value ) return ;
1255+ menuOpen .value = true ;
1256+ selectionIndex .value = - 1 ; // Reset selection index when menu opens
1257+
12361258 if (select == undefined ) {
12371259 // Select the whole search input if it hasn't changed recently.
12381260 // If it /has/ changed recently, it means the user is actively typing and probably
12391261 // doesn't want to use what they're typing.
12401262 select = new Date ().valueOf () - searchChanged .value .valueOf () > 1000 ;
12411263 }
12421264
1243- if (menuOpen .value ) return ;
1244- menuOpen .value = true ;
1245- selectionIndex .value = - 1 ; // Reset selection index when menu opens
1246-
12471265 if (props .reloadOnOpen ) listCaller ();
12481266
1249- await nextTick ();
1250- const input = searchRef .value ? .$el .querySelector (" input" ) as HTMLInputElement ;
1251-
1252- // Wait for the menu fade-in animation to unhide the content root
1253- // before we try to focus the search input, because otherwise it wont work.
1254- // https://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom
1255- const start = performance .now ();
1256-
1257- // Force the menu open while we wait, because otherwise if a user clicks and then rapidly types a character,
1258- // the typed character will process before the click, resulting in the click toggling the menu closed
1259- // after the typed character opened the menu.
1260- menuOpenForced .value = true ;
1261-
1262- while (
1263- // cap waiting
1264- start + 500 > performance .now () &&
1265- (! input .offsetParent || input != document .activeElement )
1266- ) {
1267- input .focus ();
1268- await new Promise ((resolve ) => setTimeout (resolve, 1 ));
1269- }
1270-
1271- menuOpenForced .value = false ;
1272-
1273- if (select) {
1274- input .select ();
1275- }
1267+ // Store the select preference for when the input becomes visible
1268+ pendingSearchSelect .value = select ?? false ;
12761269}
12771270
12781271let forceClosed = false ;
@@ -1283,9 +1276,7 @@ function closeMenu(force = false): void {
12831276 }
12841277
12851278 if (! menuOpen .value ) return ;
1286- if (menuOpenForced .value && ! force) return ;
12871279
1288- menuOpenForced .value = false ;
12891280 menuOpen .value = false ;
12901281 selectionIndex .value = - 1 ;
12911282 mainInputRef .value ? .focus ();
0 commit comments