diff --git a/playgrounds/nuxt/app/pages/components/input-menu.vue b/playgrounds/nuxt/app/pages/components/input-menu.vue index 67f434d0c2..5c82a7a5fc 100644 --- a/playgrounds/nuxt/app/pages/components/input-menu.vue +++ b/playgrounds/nuxt/app/pages/components/input-menu.vue @@ -57,6 +57,20 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode lazy: true }) +const searchTermCreate = ref('') +const searchTermDebouncedCreate = refDebounced(searchTermCreate, 200) + +const { data: usersCreate, status: statusCreate } = await useFetch('https://jsonplaceholder.typicode.com/users', { + params: { q: searchTermDebouncedCreate }, + transform: (data: User[]) => { + return data?.map(user => ({ id: user.id, label: user.name, avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` } })) || [] + }, + lazy: true +}) +function onUserCreate(newStr: string) { + console.log('onUserCreate', newStr) +} + const value = ref('Apple') const valueMultiple = ref([fruits[0]!, vegetables[0]!]) @@ -120,6 +134,18 @@ const valueMultiple = ref([fruits[0]!, vegetables[0]!]) + { + return data?.map(user => ({ + id: user.id, + label: user.name, + avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` } + })) + }, + lazy: true +}) + +function onUserCreate(newStr: string) { + console.log('onUserCreate', newStr) +} + const value = ref('Apple') const valueMultiple = ref([fruits[0]!, vegetables[0]!]) @@ -120,6 +139,18 @@ const valueMultiple = ref([fruits[0]!, vegetables[0]!]) + props.items, + () => { + if (isDropdownOpened && props.ignoreFilter && createItem.value) { + comboboxRootRef.value?.highlightFirstItem?.() + } + }, + { + flush: 'post' + } +) +function onInputEnter(e: Event) { + // In case combobox has any focus, skip + if (comboboxRootRef.value?.highlightedElement?.isConnected) { + return + } + // In case we have items but our focus is not within the combobox, just bring the focus back + if (filteredItems.value.length > 0) { + comboboxRootRef.value?.highlightFirstItem?.() + e.preventDefault() + e.stopPropagation() + return + } + // In case creation is not allowed skip + if (!createItem.value) { + return + } + onCreate(e) +} + defineExpose({ inputRef: toRef(() => inputRef.value?.$el as HTMLInputElement), viewportRef: toRef(() => viewportRef.value) @@ -603,6 +637,7 @@ defineExpose({ @@ -664,6 +700,7 @@ defineExpose({ @focus="onFocus" @change.stop @update:model-value="onInputUpdate" + @keydown.enter="onInputEnter" /> diff --git a/src/runtime/components/SelectMenu.vue b/src/runtime/components/SelectMenu.vue index f1995ae087..3e3e07d729 100644 --- a/src/runtime/components/SelectMenu.vue +++ b/src/runtime/components/SelectMenu.vue @@ -225,7 +225,7 @@ export interface SelectMenuSlots<