How to hide text field floating suggestions when field is left, but not if a suggestion is clicked?

I made a vue component (my first ever!) that aims to show suggestions for options as you type:

const AutoCompleteComponent = {
    data()  {
        return {
            open: false,
            current: 0,
            /** @type {string[]} **/
            suggestions: ["first", "ble", "hello"],
            fieldWidth: 0,
        }
    },
    mounted() {
        this.fieldWidth = this.$refs.inputField.clientWidth;
    },
    methods: {

        focus() {
            console.log("Focus activated");
            this.open = true;
        },

        blur() {
            console.log("Focus deactivated")
            // when I do this, the suggestions dissappear the frame before they are
            // clicked, causing the suggestionClick to not be called
            this.open = false;
        },
    
        //For highlighting element
        isActive(index) {
            return index === this.current;
        },
    
        //When the user changes input
        change() {
            this.loadSuggestions();
            //console.log("change()");
            if (this.open == false) {
                this.open = true;
                this.current = 0;
            }
        },
    
        //When one of the suggestion is clicked
        suggestionClick(index) {
            this.currentText = this.matches[index];
            console.log("Clicked suggestion: ", index, this.matches[index]);
            this.open = false;
        },
    },
    computed: {
    
        /**
         * Filtering the suggestion based on the input
         * @this {ReturnType<AutoCompleteComponent["data"]>}
         */
        matches() {
            console.log("computed.matches() str=", this.currentText, " suggestions=", this.suggestions);
            return this.suggestions.filter((str) => {
                const withoutAccents = str.toLowerCase();
                return withoutAccents.indexOf(this.currentText.toLowerCase()) >= 0;
            });
        },
    
        //The flag
        openSuggestion() {
            return this.currentText !== "" &&
                   this.matches.length != 0 &&
                   this.open === true;
        },

        copiedWidth() {
            return this.fieldWidth + "px";
        }
    },
    template: "#vue-auto-complete-template"
};

This is it’s HTML template:

    <template id="vue-auto-complete-template">
      <div v-bind:class="{'open':openSuggestion}" class="auto-complete-field">
        <div class="field-wrapper">
          <input class="form-control" type="text" v-model="currentText" @keydown.enter='enter' @keydown.down='down'
          @keydown.up='up' @input='change' @focus="focus" @blur="blur" ref="inputField" />
        </div>

        <div class="suggestions-wrapper">
          <ul class="field-suggestions" :style="{ width: copiedWidth }" >
            <li v-for="(suggestion, suggestion_index) in matches" v-bind:class="{'active': isActive(suggestion_index)}"
              @click="suggestionClick(suggestion_index)">
              {{ suggestion }}
            </li>
          </ul>
        </div>
      </div>
    </template>

So then I create it like this:

<AutoCompleteComponent class="some class names"></AutoCompleteComponent>

To make it appear under the field, the following CSS is applied:

.auto-complete-field {
    display:inline-block;
}
.auto-complete-field .suggestions-wrapper {
    display:block;
    position: relative;
}

.auto-complete-field.open ul {
    display:initial;
}

.auto-complete-field ul {
    list-style:none;
    padding:0;
    margin:0;

    display: none;

    position: absolute;
    top:0px;
    left: 0px;

    border-bottom: 1px solid black;
}
.auto-complete-field ul li {
    background-color: white;
    border: 1px solid black;
    border-bottom: none;
}

Now the problem is if you look onto the blur() function, it sets open to false which in turn hides the suggestions ul.field-suggestions using the active class name.

Because of the order in which events are handled, blur event on the field hides the .auto-complete-field.open ul before the click event is created, causing it to instead be invoked on whatever was under it.

Quick and dirty remedy to this would be setTimeout(()=>{this.open=false}, 100). I think for this to work, the timeout must actually be two render frames at least. It didn’t work as a microtask nor RequestAnimationFrame. I don’t want to use timeout, especially a big one, because it can cause GUI flickering with fast clicks.

I am looking for a more solid solution to this. I’d hope Vue has something for this. Plain JS solution to this is usually reimplementing blur event by listening on multiple events on Window, and checking where they occured. I’d rather avoid that.