parent
d6a72fbfc4
commit
4a43b45a99
@ -6,9 +6,11 @@
|
|||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:position="position"
|
:position="position"
|
||||||
:direction="direction"
|
:direction="direction"
|
||||||
@open="() => {
|
@open="
|
||||||
|
() => {
|
||||||
searchQuery = ''
|
searchQuery = ''
|
||||||
}"
|
}
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
<DropdownIcon class="h-5 w-5 text-secondary" />
|
<DropdownIcon class="h-5 w-5 text-secondary" />
|
||||||
@ -16,12 +18,20 @@
|
|||||||
<div class="iconified-input mb-2 w-full" v-if="search">
|
<div class="iconified-input mb-2 w-full" v-if="search">
|
||||||
<label for="search-input" hidden>Search...</label>
|
<label for="search-input" hidden>Search...</label>
|
||||||
<SearchIcon aria-hidden="true" />
|
<SearchIcon aria-hidden="true" />
|
||||||
<input id="search-input" v-model="searchQuery" placeholder="Search..." type="text" ref="searchInput" @keydown.enter="() => {
|
<input
|
||||||
|
id="search-input"
|
||||||
|
v-model="searchQuery"
|
||||||
|
placeholder="Search..."
|
||||||
|
type="text"
|
||||||
|
ref="searchInput"
|
||||||
|
@keydown.enter="
|
||||||
|
() => {
|
||||||
toggleOption(filteredOptions[0])
|
toggleOption(filteredOptions[0])
|
||||||
}" />
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ScrollablePanel
|
<ScrollablePanel v-if="search" class="h-[17rem]">
|
||||||
v-if="search" class="h-[17rem]">
|
|
||||||
<Button
|
<Button
|
||||||
v-for="(option, index) in filteredOptions"
|
v-for="(option, index) in filteredOptions"
|
||||||
:key="`option-${index}`"
|
:key="`option-${index}`"
|
||||||
@ -31,11 +41,13 @@
|
|||||||
:color="manyValues.includes(option) ? 'secondary' : 'default'"
|
:color="manyValues.includes(option) ? 'secondary' : 'default'"
|
||||||
>
|
>
|
||||||
<slot name="option" :option="option">{{ displayName(option) }}</slot>
|
<slot name="option" :option="option">{{ displayName(option) }}</slot>
|
||||||
<CheckIcon class="h-5 w-5 text-contrast ml-auto transition-opacity" :class="{ 'opacity-0': !manyValues.includes(option) }" />
|
<CheckIcon
|
||||||
|
class="h-5 w-5 text-contrast ml-auto transition-opacity"
|
||||||
|
:class="{ 'opacity-0': !manyValues.includes(option) }"
|
||||||
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</ScrollablePanel>
|
</ScrollablePanel>
|
||||||
<div
|
<div v-else class="flex flex-col gap-1">
|
||||||
v-else class="flex flex-col gap-1">
|
|
||||||
<Button
|
<Button
|
||||||
v-for="(option, index) in filteredOptions"
|
v-for="(option, index) in filteredOptions"
|
||||||
:key="`option-${index}`"
|
:key="`option-${index}`"
|
||||||
@ -45,7 +57,10 @@
|
|||||||
:color="manyValues.includes(option) ? 'secondary' : 'default'"
|
:color="manyValues.includes(option) ? 'secondary' : 'default'"
|
||||||
>
|
>
|
||||||
<slot name="option" :option="option">{{ displayName(option) }}</slot>
|
<slot name="option" :option="option">{{ displayName(option) }}</slot>
|
||||||
<CheckIcon class="h-5 w-5 text-contrast ml-auto transition-opacity" :class="{ 'opacity-0': !manyValues.includes(option) }" />
|
<CheckIcon
|
||||||
|
class="h-5 w-5 text-contrast ml-auto transition-opacity"
|
||||||
|
:class="{ 'opacity-0': !manyValues.includes(option) }"
|
||||||
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<slot name="footer" />
|
<slot name="footer" />
|
||||||
@ -63,12 +78,12 @@ type Option = string | number | object
|
|||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
modelValue: Option[],
|
modelValue: Option[]
|
||||||
options: Option[]
|
options: Option[]
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
position?: string
|
position?: string
|
||||||
direction?: string,
|
direction?: string
|
||||||
displayName?: (option: Option) => string,
|
displayName?: (option: Option) => string
|
||||||
search?: boolean
|
search?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
@ -80,9 +95,9 @@ const props = withDefaults(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'change']);
|
const emit = defineEmits(['update:modelValue', 'change'])
|
||||||
const selectedValues = ref(props.modelValue || [])
|
const selectedValues = ref(props.modelValue || [])
|
||||||
const searchInput = ref();
|
const searchInput = ref()
|
||||||
|
|
||||||
const searchQuery = ref('')
|
const searchQuery = ref('')
|
||||||
|
|
||||||
@ -98,7 +113,11 @@ const manyValues = computed({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const filteredOptions = computed(() => {
|
const filteredOptions = computed(() => {
|
||||||
return props.options.filter((x) => !searchQuery.value || props.displayName(x).toLowerCase().includes(searchQuery.value.toLowerCase()))
|
return props.options.filter(
|
||||||
|
(x) =>
|
||||||
|
!searchQuery.value ||
|
||||||
|
props.displayName(x).toLowerCase().includes(searchQuery.value.toLowerCase()),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -112,5 +131,4 @@ function toggleOption(id: Option) {
|
|||||||
manyValues.value = [...manyValues.value, id]
|
manyValues.value = [...manyValues.value, id]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user