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>