Switch to composition API, Add custom names (#47)

* Switch to composition API, Add custom names

* Update package.json

* Update DropdownSelect.vue
This commit is contained in:
Adrian O.V
2023-05-03 17:50:39 -04:00
committed by GitHub
parent 1135852f25
commit 5fde3c53b8
3 changed files with 129 additions and 107 deletions

View File

@@ -23,6 +23,12 @@ const value = ref(null)
placeholder="Choose Frequency" placeholder="Choose Frequency"
disabled disabled
/> />
<DropdownSelect
v-model="value"
:options="['Daily', 'Weekly', 'Monthly', 'Tomorrow', 'Yesterday', 'Today', 'Biweekly', 'Tuesday', 'January']"
placeholder="Choose Frequency"
:display-name="(name) => name?.toUpperCase()"
/>
</DemoContainer> </DemoContainer>
```vue ```vue

View File

@@ -51,7 +51,7 @@
:value="option" :value="option"
:name="name" :name="name"
/> />
<label :for="`${name}-${index}`">{{ option }}</label> <label :for="`${name}-${index}`">{{ displayName(option) }}</label>
</div> </div>
</div> </div>
</transition> </transition>
@@ -59,9 +59,10 @@
</div> </div>
</template> </template>
<script> <script setup>
export default { import { computed, ref, watch } from 'vue'
props: {
const props = defineProps({
options: { options: {
type: Array, type: Array,
required: true, required: true,
@@ -90,72 +91,89 @@ export default {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
displayName: {
type: Function,
default: (option) => option,
}, },
emits: ['input', 'change', 'update:modelValue'], })
data() {
return { const emit = defineEmits(['input', 'change', 'update:modelValue'])
dropdownVisible: false,
selectedValue: this.modelValue || this.defaultValue, const dropdownVisible = ref(false)
focusedOptionIndex: null, const selectedValue = ref(props.modelValue || props.defaultValue)
} const focusedOptionIndex = ref(null)
}, const dropdown = ref(null)
computed: { const optionElements = ref(null)
selectedOption() {
return this.selectedValue || this.placeholder || 'Select an option' const selectedOption = computed(() => {
}, return props.displayName(selectedValue.value) || props.placeholder || 'Select an option'
radioValue: { })
const radioValue = computed({
get() { get() {
return this.modelValue || this.selectedValue return props.modelValue || selectedValue.value
}, },
set(newValue) { set(newValue) {
this.$emit('update:modelValue', newValue) emit('update:modelValue', newValue)
this.selectedValue = newValue selectedValue.value = newValue
}, },
}, })
},
methods: { watch(
toggleDropdown() { () => props.modelValue,
if (!this.disabled) { (newValue) => {
this.dropdownVisible = !this.dropdownVisible selectedValue.value = newValue
this.$refs.dropdown.focus()
} }
}, )
selectOption(option, index) {
this.radioValue = option const toggleDropdown = () => {
this.$emit('change', { option, index }) if (!props.disabled) {
this.dropdownVisible = false dropdownVisible.value = !dropdownVisible.value
}, dropdown.value.focus()
onFocus() {
if (!this.disabled) {
this.focusedOptionIndex = this.options.findIndex((option) => option === this.selectedValue)
this.dropdownVisible = true
} }
}, }
onBlur(event) {
if (!this.isChildOfDropdown(event.relatedTarget)) { const selectOption = (option, index) => {
this.dropdownVisible = false radioValue.value = option
emit('change', { option, index })
dropdownVisible.value = false
}
const onFocus = () => {
if (!props.disabled) {
focusedOptionIndex.value = props.options.findIndex((option) => option === selectedValue.value)
dropdownVisible.value = true
} }
}, }
focusPreviousOption() {
if (!this.disabled) { const onBlur = (event) => {
if (!this.dropdownVisible) { if (!isChildOfDropdown(event.relatedTarget)) {
this.toggleDropdown() dropdownVisible.value = false
} }
this.focusedOptionIndex = }
(this.focusedOptionIndex + this.options.length - 1) % this.options.length
this.$refs.optionElements[this.focusedOptionIndex].focus() const focusPreviousOption = () => {
if (!props.disabled) {
if (!dropdownVisible.value) {
toggleDropdown()
} }
}, focusedOptionIndex.value =
focusNextOptionOrOpen() { (focusedOptionIndex.value + props.options.length - 1) % props.options.length
if (!this.disabled) { optionElements.value[focusedOptionIndex.value].focus()
if (!this.dropdownVisible) {
this.toggleDropdown()
} }
this.focusedOptionIndex = (this.focusedOptionIndex + 1) % this.options.length }
this.$refs.optionElements[this.focusedOptionIndex].focus()
const focusNextOptionOrOpen = () => {
if (!props.disabled) {
if (!dropdownVisible.value) {
toggleDropdown()
} }
}, focusedOptionIndex.value = (focusedOptionIndex.value + 1) % props.options.length
isChildOfDropdown(element) { optionElements.value[focusedOptionIndex.value].focus()
}
}
const isChildOfDropdown = (element) => {
let currentNode = element let currentNode = element
while (currentNode) { while (currentNode) {
if (currentNode === this.$el) { if (currentNode === this.$el) {
@@ -164,8 +182,6 @@ export default {
currentNode = currentNode.parentNode currentNode = currentNode.parentNode
} }
return false return false
},
},
} }
</script> </script>

View File

@@ -1,7 +1,7 @@
{ {
"name": "omorphia", "name": "omorphia",
"type": "module", "type": "module",
"version": "0.4.12", "version": "0.4.13",
"files": [ "files": [
"dist" "dist"
], ],