Disabled select input fixes (#355)
This commit is contained in:
parent
9761351a26
commit
e7c7776bb1
|
|
@ -1,23 +1,20 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="v-select relative" :class="[{'w-0': multiple, 'min-w-full':multiple}]" ref="select">
|
<div class="v-select relative" :class="[{ 'w-0': multiple, 'min-w-full': multiple }]" ref="select">
|
||||||
<span class="inline-block w-full rounded-md">
|
<span class="inline-block w-full rounded-md">
|
||||||
<button type="button" aria-haspopup="listbox" aria-expanded="true" aria-labelledby="listbox-label"
|
<button type="button" aria-haspopup="listbox" aria-expanded="true" aria-labelledby="listbox-label"
|
||||||
class="cursor-pointer"
|
class="cursor-pointer" :style="inputStyle"
|
||||||
:style="inputStyle"
|
:class="[theme.SelectInput.input, { 'py-2': !multiple || loading, 'py-1': multiple, '!ring-red-500 !ring-2 !border-transparent': hasError, '!cursor-not-allowed !bg-gray-200': disabled }, inputClass]"
|
||||||
:class="[theme.SelectInput.input,{'py-2': !multiple || loading,'py-1': multiple, '!ring-red-500 !ring-2 !border-transparent': hasError, '!cursor-not-allowed !bg-gray-200': disabled}, inputClass]"
|
@click="toggleDropdown">
|
||||||
@click="toggleDropdown"
|
<div :class="{ 'h-6': !multiple, 'min-h-8': multiple && !loading }">
|
||||||
>
|
|
||||||
<div :class="{'h-6': !multiple, 'min-h-8': multiple && !loading}">
|
|
||||||
<transition name="fade" mode="out-in">
|
<transition name="fade" mode="out-in">
|
||||||
<Loader v-if="loading" key="loader" class="h-6 w-6 text-nt-blue mx-auto" />
|
<Loader v-if="loading" key="loader" class="h-6 w-6 text-nt-blue mx-auto" />
|
||||||
<div v-else-if="modelValue" key="value" class="flex" :class="{'min-h-8': multiple}">
|
<div v-else-if="modelValue" key="value" class="flex" :class="{ 'min-h-8': multiple }">
|
||||||
<slot name="selected" :option="modelValue" />
|
<slot name="selected" :option="modelValue" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else key="placeholder">
|
<div v-else key="placeholder">
|
||||||
<slot name="placeholder">
|
<slot name="placeholder">
|
||||||
<div class="text-gray-400 dark:text-gray-500 w-full text-left truncate pr-3"
|
<div class="text-gray-400 dark:text-gray-500 w-full text-left truncate pr-3"
|
||||||
:class="{'py-1': multiple && !loading}"
|
:class="{ 'py-1': multiple && !loading }">
|
||||||
>
|
|
||||||
{{ placeholder }}
|
{{ placeholder }}
|
||||||
</div>
|
</div>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
@ -32,27 +29,21 @@
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
<collapsible v-model="isOpen" @click-away="onClickAway"
|
<collapsible v-model="isOpen" @click-away="onClickAway"
|
||||||
class="absolute mt-1 rounded-md bg-white dark:bg-notion-dark-light shadow-xl z-10"
|
class="absolute mt-1 rounded-md bg-white dark:bg-notion-dark-light shadow-xl z-10" :class="dropdownClass">
|
||||||
:class="dropdownClass"
|
|
||||||
>
|
|
||||||
<ul tabindex="-1" role="listbox"
|
<ul tabindex="-1" role="listbox"
|
||||||
class="rounded-md text-base leading-6 shadow-xs overflow-auto focus:outline-none sm:text-sm sm:leading-5 relative"
|
class="rounded-md text-base leading-6 shadow-xs overflow-auto focus:outline-none sm:text-sm sm:leading-5 relative"
|
||||||
:class="{'max-h-42 py-1': !isSearchable,'max-h-48 pb-1': isSearchable}"
|
:class="{ 'max-h-42 py-1': !isSearchable, 'max-h-48 pb-1': isSearchable }">
|
||||||
>
|
|
||||||
<div v-if="isSearchable" class="px-2 pt-2 sticky top-0 bg-white dark-bg-notion-dark-light z-10">
|
<div v-if="isSearchable" class="px-2 pt-2 sticky top-0 bg-white dark-bg-notion-dark-light z-10">
|
||||||
<text-input v-model="searchTerm" name="search" :color="color" :theme="theme"
|
<text-input v-model="searchTerm" name="search" :color="color" :theme="theme" placeholder="Search..." />
|
||||||
placeholder="Search..."
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="loading" class="w-full py-2 flex justify-center">
|
<div v-if="loading" class="w-full py-2 flex justify-center">
|
||||||
<Loader class="h-6 w-6 text-nt-blue mx-auto" />
|
<Loader class="h-6 w-6 text-nt-blue mx-auto" />
|
||||||
</div>
|
</div>
|
||||||
<template v-if="filteredOptions.length > 0">
|
<template v-if="filteredOptions.length > 0">
|
||||||
<li v-for="item in filteredOptions" :key="item[optionKey]" role="option" :style="optionStyle"
|
<li v-for="item in filteredOptions" :key="item[optionKey]" role="option" :style="optionStyle"
|
||||||
:class="{'px-3 pr-9': multiple, 'px-3': !multiple}"
|
:class="{ 'px-3 pr-9': multiple, 'px-3': !multiple }"
|
||||||
class="text-gray-900 cursor-default select-none relative py-2 cursor-pointer group hover:text-white hover:bg-form-color focus:outline-none focus-text-white focus-nt-blue"
|
class="text-gray-900 cursor-default select-none relative py-2 cursor-pointer group hover:text-white hover:bg-form-color focus:outline-none focus-text-white focus-nt-blue"
|
||||||
@click="select(item)"
|
@click="select(item)">
|
||||||
>
|
|
||||||
<slot name="option" :option="item" :selected="isSelected(item)" />
|
<slot name="option" :option="item" :selected="isSelected(item)" />
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -60,10 +51,9 @@
|
||||||
{{ (allowCreation ? 'Type something to add an option' : 'No option available') }}.
|
{{ (allowCreation ? 'Type something to add an option' : 'No option available') }}.
|
||||||
</p>
|
</p>
|
||||||
<li v-if="allowCreation && searchTerm" role="option" :style="optionStyle"
|
<li v-if="allowCreation && searchTerm" role="option" :style="optionStyle"
|
||||||
:class="{'px-3 pr-9': multiple, 'px-3': !multiple}"
|
:class="{ 'px-3 pr-9': multiple, 'px-3': !multiple }"
|
||||||
class="text-gray-900 cursor-default select-none relative py-2 cursor-pointer group hover:text-white hover:bg-form-color focus:outline-none focus-text-white focus-nt-blue"
|
class="text-gray-900 cursor-default select-none relative py-2 cursor-pointer group hover:text-white hover:bg-form-color focus:outline-none focus-text-white focus-nt-blue"
|
||||||
@click="createOption(searchTerm)"
|
@click="createOption(searchTerm)">
|
||||||
>
|
|
||||||
Create <b class="px-1 bg-gray-300 rounded group-hover-text-black">{{ searchTerm }}</b>
|
Create <b class="px-1 bg-gray-300 rounded group-hover-text-black">{{ searchTerm }}</b>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -103,7 +93,7 @@ export default {
|
||||||
allowCreation: { type: Boolean, default: false },
|
allowCreation: { type: Boolean, default: false },
|
||||||
disabled: { type: Boolean, default: false }
|
disabled: { type: Boolean, default: false }
|
||||||
},
|
},
|
||||||
data () {
|
data() {
|
||||||
return {
|
return {
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
|
|
@ -111,23 +101,23 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
optionStyle () {
|
optionStyle() {
|
||||||
return {
|
return {
|
||||||
'--bg-form-color': this.color
|
'--bg-form-color': this.color
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
inputStyle () {
|
inputStyle() {
|
||||||
return {
|
return {
|
||||||
'--tw-ring-color': this.color
|
'--tw-ring-color': this.color
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
debouncedRemote () {
|
debouncedRemote() {
|
||||||
if (this.remote) {
|
if (this.remote) {
|
||||||
return debounce(this.remote, 300)
|
return debounce(this.remote, 300)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
filteredOptions () {
|
filteredOptions() {
|
||||||
if (!this.data) return []
|
if (!this.data) return []
|
||||||
if (!this.searchable || this.remote || this.searchTerm === '') {
|
if (!this.searchable || this.remote || this.searchTerm === '') {
|
||||||
return this.data
|
return this.data
|
||||||
|
|
@ -142,12 +132,12 @@ export default {
|
||||||
return res.item
|
return res.item
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
isSearchable () {
|
isSearchable() {
|
||||||
return this.searchable || this.remote !== null || this.allowCreation
|
return this.searchable || this.remote !== null || this.allowCreation
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
searchTerm (val) {
|
searchTerm(val) {
|
||||||
if (!this.debouncedRemote) return
|
if (!this.debouncedRemote) return
|
||||||
if ((this.remote && val) || (val === '' && !this.modelValue) || (val === '' && this.isOpen)) {
|
if ((this.remote && val) || (val === '' && !this.modelValue) || (val === '' && this.isOpen)) {
|
||||||
return this.debouncedRemote(val)
|
return this.debouncedRemote(val)
|
||||||
|
|
@ -155,13 +145,13 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onClickAway (event) {
|
onClickAway(event) {
|
||||||
// Check that event target isn't children of dropdown
|
// Check that event target isn't children of dropdown
|
||||||
if (this.$refs.select && !this.$refs.select.contains(event.target)) {
|
if (this.$refs.select && !this.$refs.select.contains(event.target)) {
|
||||||
this.isOpen = false
|
this.isOpen = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isSelected (value) {
|
isSelected(value) {
|
||||||
if (!this.modelValue) return false
|
if (!this.modelValue) return false
|
||||||
|
|
||||||
if (this.emitKey && value[this.emitKey]) {
|
if (this.emitKey && value[this.emitKey]) {
|
||||||
|
|
@ -173,16 +163,17 @@ export default {
|
||||||
}
|
}
|
||||||
return this.modelValue === value
|
return this.modelValue === value
|
||||||
},
|
},
|
||||||
toggleDropdown () {
|
toggleDropdown() {
|
||||||
if (this.disabled) {
|
if (this.disabled) {
|
||||||
this.isOpen = false
|
this.isOpen = false
|
||||||
}
|
} else {
|
||||||
this.isOpen = !this.isOpen
|
this.isOpen = !this.isOpen
|
||||||
|
}
|
||||||
if (!this.isOpen) {
|
if (!this.isOpen) {
|
||||||
this.searchTerm = ''
|
this.searchTerm = ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
select (value) {
|
select(value) {
|
||||||
if (!this.multiple) {
|
if (!this.multiple) {
|
||||||
// Close after select
|
// Close after select
|
||||||
this.toggleDropdown()
|
this.toggleDropdown()
|
||||||
|
|
@ -215,7 +206,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
createOption (newOption) {
|
createOption(newOption) {
|
||||||
if (newOption) {
|
if (newOption) {
|
||||||
const newItem = {
|
const newItem = {
|
||||||
name: newOption,
|
name: newOption,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue