forked from noxious/client
60 lines
1.8 KiB
Vue
60 lines
1.8 KiB
Vue
<template>
|
||
<div class="flex flex-wrap items-center input-field gap-1">
|
||
<div v-for="(chip, i) in internalValue" :key="i" class="flex gap-2.5 items-center bg-cyan rounded py-1 px-2">
|
||
<span class="text-xs">{{ chip }}</span>
|
||
<button type="button" class="text-xs cursor-pointer text-white font-light font-default not-italic hover:text-gray-50" @click="deleteChip(i)" aria-label="Remove chip">×</button>
|
||
</div>
|
||
<input class="outline-none border-none p-1" placeholder="Tag name" v-model="currentInput" @keypress.enter.prevent="addChip" @keydown.backspace="handleBackspace" />
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, watch } from 'vue'
|
||
import type { Ref } from 'vue'
|
||
|
||
interface Props {
|
||
modelValue?: string[]
|
||
}
|
||
|
||
const props = withDefaults(defineProps<Props>(), {
|
||
modelValue: () => []
|
||
})
|
||
|
||
const emit = defineEmits<{
|
||
(e: 'update:modelValue', value: string[]): void
|
||
}>()
|
||
|
||
const currentInput: Ref<string> = ref('')
|
||
const internalValue = ref<string[]>([])
|
||
|
||
// Initialize internalValue with props.modelValue
|
||
watch(
|
||
() => props.modelValue,
|
||
(newValue) => {
|
||
internalValue.value = newValue ? [...newValue] : []
|
||
},
|
||
{ immediate: true }
|
||
)
|
||
|
||
const addChip = () => {
|
||
const trimmedInput = currentInput.value.trim()
|
||
if (trimmedInput && !internalValue.value.includes(trimmedInput)) {
|
||
internalValue.value.push(trimmedInput)
|
||
emit('update:modelValue', internalValue.value)
|
||
currentInput.value = ''
|
||
}
|
||
}
|
||
|
||
const deleteChip = (index: number) => {
|
||
internalValue.value.splice(index, 1)
|
||
emit('update:modelValue', internalValue.value)
|
||
}
|
||
|
||
const handleBackspace = (event: KeyboardEvent) => {
|
||
if (event.key === 'Backspace' && currentInput.value === '' && internalValue.value.length > 0) {
|
||
internalValue.value.pop()
|
||
emit('update:modelValue', internalValue.value)
|
||
}
|
||
}
|
||
</script>
|