Skip to content

Commit 0577820

Browse files
committed
Fixes autocomplete showing when input is not focused
1 parent d3348af commit 0577820

File tree

1 file changed

+28
-39
lines changed

1 file changed

+28
-39
lines changed

src/webviews/apps/shared/components/search/search-input.ts

Lines changed: 28 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,7 @@ export class GlSearchInput extends GlElement {
323323
@state() private autocompleteOpen = false;
324324
@state() private autocompleteItems: SearchCompletionItem[] = [];
325325
@state() private cursorOperator?: SearchCompletionOperator;
326-
private autocompleteStartPos = 0;
327-
private autocompleteEndPos = 0;
326+
private cursorPosition: [number, number] = [0, 0];
328327

329328
@query('gl-autocomplete') private autocomplete?: GlAutocomplete;
330329

@@ -333,6 +332,10 @@ export class GlSearchInput extends GlElement {
333332
// Track last search to avoid re-searching on Enter when query hasn't changed
334333
private _lastSearch: SearchQuery | undefined = undefined;
335334

335+
private get inputFocused(): boolean {
336+
return this.renderRoot instanceof ShadowRoot ? this.renderRoot.activeElement === this.input : false;
337+
}
338+
336339
private get label() {
337340
return this.filter ? 'Filter' : 'Search';
338341
}
@@ -415,7 +418,7 @@ export class GlSearchInput extends GlElement {
415418

416419
// When searching state changes in NL mode, ensure autocomplete is open to show progress
417420
if (changedProperties.has('searching') && this.naturalLanguage) {
418-
this.autocompleteOpen = true;
421+
this.autocompleteOpen = this.inputFocused;
419422
}
420423

421424
super.updated(changedProperties);
@@ -489,7 +492,7 @@ export class GlSearchInput extends GlElement {
489492
if (this.naturalLanguage) {
490493
this.autocompleteItems = [];
491494
this.cursorOperator = undefined;
492-
this.autocompleteOpen = true;
495+
this.autocompleteOpen = this.inputFocused;
493496
return;
494497
}
495498

@@ -508,10 +511,9 @@ export class GlSearchInput extends GlElement {
508511
this.autocompleteItems = [naturalLanguageSearchAutocompleteCommand, ...operators];
509512

510513
this.cursorOperator = undefined;
511-
this.autocompleteStartPos = 0;
512-
this.autocompleteEndPos = 0;
513-
this.autocompleteOpen = true;
514+
this.cursorPosition = [0, 0];
514515
this.autocomplete?.resetSelection();
516+
this.autocompleteOpen = this.inputFocused;
515517
return;
516518
}
517519

@@ -559,10 +561,9 @@ export class GlSearchInput extends GlElement {
559561
this.cursorOperator = completeValue.description
560562
? { ...metadata, description: completeValue.description, example: undefined }
561563
: metadata;
562-
this.autocompleteStartPos = start;
563-
this.autocompleteEndPos = end;
564-
this.autocompleteOpen = true;
564+
this.cursorPosition = [start, end];
565565
this.autocomplete?.resetSelection();
566+
this.autocompleteOpen = this.inputFocused;
566567
return;
567568
}
568569

@@ -587,20 +588,18 @@ export class GlSearchInput extends GlElement {
587588
matches.sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
588589
this.autocompleteItems = matches;
589590
this.cursorOperator = metadata; // Show operator description
590-
this.autocompleteStartPos = start + opPart.length;
591-
this.autocompleteEndPos = end;
592-
this.autocompleteOpen = true;
591+
this.cursorPosition = [start + opPart.length, end];
593592
this.autocomplete?.resetSelection();
593+
this.autocompleteOpen = this.inputFocused;
594594
return;
595595
}
596596

597597
// Default: show operator help text
598598
this.autocompleteItems = [];
599599
this.cursorOperator = metadata;
600-
this.autocompleteStartPos = start;
601-
this.autocompleteEndPos = end;
602-
this.autocompleteOpen = true;
600+
this.cursorPosition = [start, end];
603601
this.autocomplete?.resetSelection();
602+
this.autocompleteOpen = this.inputFocused;
604603
return;
605604
}
606605
}
@@ -627,8 +626,7 @@ export class GlSearchInput extends GlElement {
627626
}) satisfies SearchCompletionItem,
628627
);
629628
this.cursorOperator = metadata; // Show operator description
630-
this.autocompleteStartPos = start + longForm.length;
631-
this.autocompleteEndPos = end;
629+
this.cursorPosition = [start + longForm.length, end];
632630
this.autocompleteOpen = true;
633631
this.autocomplete?.resetSelection();
634632
return;
@@ -637,8 +635,7 @@ export class GlSearchInput extends GlElement {
637635
// Default: show operator help text
638636
this.autocompleteItems = [];
639637
this.cursorOperator = metadata;
640-
this.autocompleteStartPos = start;
641-
this.autocompleteEndPos = end;
638+
this.cursorPosition = [start, end];
642639
this.autocompleteOpen = true;
643640
this.autocomplete?.resetSelection();
644641
return;
@@ -686,8 +683,7 @@ export class GlSearchInput extends GlElement {
686683
if (!this.naturalLanguage) {
687684
this.autocompleteItems = [naturalLanguageSearchAutocompleteCommand];
688685
this.cursorOperator = undefined;
689-
this.autocompleteStartPos = start;
690-
this.autocompleteEndPos = end;
686+
this.cursorPosition = [start, end];
691687
this.autocompleteOpen = true;
692688
this.autocomplete?.resetSelection();
693689
} else {
@@ -707,8 +703,7 @@ export class GlSearchInput extends GlElement {
707703

708704
this.autocompleteItems = newItems;
709705
this.cursorOperator = undefined;
710-
this.autocompleteStartPos = start;
711-
this.autocompleteEndPos = end;
706+
this.cursorPosition = [start, end];
712707
this.autocompleteOpen = true;
713708
this.autocomplete?.resetSelection();
714709
}
@@ -739,60 +734,54 @@ export class GlSearchInput extends GlElement {
739734
const value = this.value;
740735

741736
// Determine what to insert:
742-
// - If it's a value completion, insert just the value (autocompleteStartPos is already after the operator)
737+
// - If it's a value completion, insert just the value (cursorPosition[0] is already after the operator)
743738
// - Otherwise, insert the operator
744739
const insertText = 'value' in selected.item ? selected.item.value : operator;
745740

746-
// Replace the entire token (from autocompleteStartPos to autocompleteEndPos) with the selected text
741+
// Replace the entire token (from cursorPosition[0] to cursorPosition[1]) with the selected text
747742
// This ensures we don't leave partial text when cursor is in the middle of a token
748743
const newValue =
749-
value.substring(0, this.autocompleteStartPos) + insertText + value.substring(this.autocompleteEndPos);
744+
value.substring(0, this.cursorPosition[0]) + insertText + value.substring(this.cursorPosition[1]);
750745

751746
// Update the input value directly
752747
this.input.value = newValue;
753748
this._value = newValue;
754749

755750
// Position cursor after the inserted text
756-
const cursorPos = this.autocompleteStartPos + insertText.length;
751+
const cursorPos = this.cursorPosition[0] + insertText.length;
757752
this.input.focus();
758753
this.input.selectionStart = cursorPos;
759754
this.input.selectionEnd = cursorPos;
760755

761756
// Update autocomplete in the next frame to ensure input is updated
762-
window.requestAnimationFrame(() => {
763-
this.updateAutocomplete();
764-
});
757+
window.requestAnimationFrame(() => this.updateAutocomplete());
765758
}
766759

767760
private handleMatchAll(_e: Event) {
768761
this.matchAll = !this.matchAll;
769-
// Only trigger search if there's a query value
770762
if (this.value) {
771-
this.onSearchChanged(true); // Force search when options change
763+
this.onSearchChanged(true);
772764
}
773765
}
774766

775767
private handleMatchCase(_e: Event) {
776768
this.matchCase = !this.matchCase;
777-
// Only trigger search if there's a query value
778769
if (this.value) {
779-
this.onSearchChanged(true); // Force search when options change
770+
this.onSearchChanged(true);
780771
}
781772
}
782773

783774
private handleMatchRegex(_e: Event) {
784775
this.matchRegex = !this.matchRegex;
785-
// Only trigger search if there's a query value
786776
if (this.value) {
787-
this.onSearchChanged(true); // Force search when options change
777+
this.onSearchChanged(true);
788778
}
789779
}
790780

791781
private handleMatchWholeWord(_e: Event) {
792782
this.matchWholeWord = !this.matchWholeWord;
793-
// Only trigger search if there's a query value
794783
if (this.value) {
795-
this.onSearchChanged(true); // Force search when options change
784+
this.onSearchChanged(true);
796785
}
797786
}
798787

0 commit comments

Comments
 (0)