File size: 1,502 Bytes
52e990b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | <template>
<div class="relative">
<input
:class="inputClasses"
:type="type"
:placeholder="placeholder"
:disabled="disabled"
:value="modelValue"
@input="handleInput"
@focus="handleFocus"
@blur="handleBlur"
@keyup.enter="emit('enter')"
/>
<div v-if="$slots.suffix" class="absolute right-3 top-1/2 -translate-y-1/2">
<slot name="suffix" />
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
interface Props {
modelValue?: string
type?: 'text' | 'password' | 'email' | 'search'
placeholder?: string
disabled?: boolean
variant?: 'default' | 'search'
}
const props = withDefaults(defineProps<Props>(), {
type: 'text',
variant: 'default'
});
const emit = defineEmits<{
'update:modelValue': [value: string]
'focus': [event: FocusEvent]
'blur': [event: FocusEvent]
'enter': []
}>();
const inputClasses = computed(() => {
const baseClasses = 'input';
const variantClasses = {
default: '',
search: 'input-search'
};
return [
baseClasses,
variantClasses[props.variant],
props.disabled && 'opacity-50 cursor-not-allowed'
].filter(Boolean).join(' ');
});
const handleInput = (event: Event) => {
const target = event.target as HTMLInputElement;
emit('update:modelValue', target.value);
};
const handleFocus = (event: FocusEvent) => {
emit('focus', event);
};
const handleBlur = (event: FocusEvent) => {
emit('blur', event);
};
</script> |