feat(SelectMenu): use UInput in search to handle props like icon

Resolves #2021
This commit is contained in:
Benjamin Canac
2024-11-10 23:22:44 +01:00
parent b0be26d67f
commit ff1e0798d3
6 changed files with 501 additions and 115 deletions

View File

@@ -36,9 +36,10 @@ export interface SelectMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends M
/**
* Wether to display the search input or not.
* Can be an object to pass additional props to the input.
* @defaultValue { placeholder: 'Search...' }
* `{ placeholder: 'Search...', variant: 'none' }`{lang="ts-type"}
* @defaultValue true
*/
searchInput?: boolean | { placeholder?: string }
searchInput?: boolean | InputProps
color?: SelectMenuVariants['color']
variant?: SelectMenuVariants['variant']
size?: SelectMenuVariants['size']
@@ -131,12 +132,13 @@ import { get, escapeRegExp } from '../utils'
import UIcon from './Icon.vue'
import UAvatar from './Avatar.vue'
import UChip from './Chip.vue'
import UInput from './Input.vue'
const props = withDefaults(defineProps<SelectMenuProps<T, I, V, M>>(), {
search: true,
portal: true,
autofocusDelay: 0,
searchInput: () => ({ placeholder: 'Search...' }),
searchInput: true,
filter: () => ['label'],
labelKey: 'label' as never
})
@@ -152,6 +154,7 @@ const { t } = useLocale()
const rootProps = useForwardPropsEmits(reactivePick(props, 'modelValue', 'defaultValue', 'selectedValue', 'open', 'defaultOpen', 'resetSearchTermOnBlur'), emits)
const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, position: 'popper' }) as ComboboxContentProps)
const arrowProps = toRef(() => props.arrow as ComboboxArrowProps)
const searchInputProps = toRef(() => defu(props.searchInput, { placeholder: 'Search...', variant: 'none' }) as InputProps)
// This is a hack due to generic boolean casting (see https://github.com/nuxt/ui/issues/2541)
const multiple = toRef(() => typeof props.multiple === 'string' ? true : props.multiple)
@@ -276,13 +279,9 @@ function onUpdateOpen(value: boolean) {
<ComboboxPortal :disabled="!portal">
<ComboboxContent :class="ui.content({ class: props.ui?.content })" v-bind="contentProps">
<ComboboxInput
v-if="!!searchInput"
autofocus
autocomplete="off"
v-bind="typeof searchInput === 'object' ? searchInput : {}"
:class="ui.input({ class: props.ui?.input })"
/>
<ComboboxInput v-if="!!searchInput" as-child>
<UInput autofocus autocomplete="off" v-bind="searchInputProps" :class="ui.input({ class: props.ui?.input })" />
</ComboboxInput>
<ComboboxEmpty :class="ui.empty({ class: props.ui?.empty })">
<slot name="empty" :search-term="searchTerm">

View File

@@ -7,26 +7,7 @@ export default (options: Required<ModuleOptions>) => {
slots: {
value: 'truncate',
placeholder: 'truncate text-[var(--ui-text-dimmed)]',
input: 'placeholder:text-[var(--ui-text-dimmed)] border-0 border-b border-[var(--ui-border)] focus:outline-none'
},
variants: {
size: {
xs: {
input: 'text-xs px-2 py-1'
},
sm: {
input: 'text-xs px-2.5 py-1.5'
},
md: {
input: 'text-sm px-2.5 py-1.5'
},
lg: {
input: 'text-sm px-3 py-2'
},
xl: {
input: 'text-base px-3 py-2'
}
}
input: 'border-b border-[var(--ui-border)]'
}
}, select(options))
}