diff --git a/src/components/forms/ChipsInput.vue b/src/components/forms/ChipsInput.vue index eb19f5f..10d5687 100644 --- a/src/components/forms/ChipsInput.vue +++ b/src/components/forms/ChipsInput.vue @@ -1,10 +1,10 @@ @@ -14,20 +14,29 @@ import type { Ref } from 'vue' interface Props { modelValue?: string[] + maxChips?: number + maxChipLength?: number + placeholder?: string + allowDuplicates?: boolean } const props = withDefaults(defineProps(), { - modelValue: () => [] + modelValue: () => [], + maxChips: 10, + maxChipLength: 20, + placeholder: 'Add tag', + allowDuplicates: false }) const emit = defineEmits<{ (e: 'update:modelValue', value: string[]): void + (e: 'error', message: string): void }>() const currentInput: Ref = ref('') const internalValue = ref([]) +const inputRef = ref(null) -// Initialize internalValue with props.modelValue watch( () => props.modelValue, (newValue) => { @@ -36,9 +45,27 @@ watch( { immediate: true } ) +const validateChip = (chip: string): boolean => { + if (!chip) { + return false + } + + if (!props.allowDuplicates && internalValue.value.includes(chip)) { + emit('error', 'Duplicate tags are not allowed') + return false + } + + if (internalValue.value.length >= props.maxChips) { + emit('error', `Maximum ${props.maxChips} tags allowed`) + return false + } + + return true +} + const addChip = () => { const trimmedInput = currentInput.value.trim() - if (trimmedInput && !internalValue.value.includes(trimmedInput)) { + if (validateChip(trimmedInput)) { internalValue.value.push(trimmedInput) emit('update:modelValue', internalValue.value) currentInput.value = '' @@ -50,10 +77,36 @@ const deleteChip = (index: number) => { 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) +const handleKeydown = (event: KeyboardEvent) => { + switch (event.key) { + case 'Enter': + event.preventDefault() + addChip() + break + case 'Backspace': + if (currentInput.value === '' && internalValue.value.length > 0) { + deleteChip(internalValue.value.length - 1) + } + break } } + +const handlePaste = (event: ClipboardEvent) => { + event.preventDefault() + const pastedText = event.clipboardData?.getData('text') + if (pastedText) { + const chips = pastedText + .split(/[,\n]/) + .map((chip) => chip.trim()) + .filter(Boolean) + chips.forEach((chip) => { + currentInput.value = chip + addChip() + }) + } +} + +const focusInput = () => { + inputRef.value?.focus() +}