Input.vue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <template>
  2. <div
  3. class="input"
  4. :class="{
  5. disabled: disabled,
  6. focused: focused,
  7. simple: simple
  8. }"
  9. >
  10. <span class="prefix">
  11. <slot name="prefix"></slot>
  12. </span>
  13. <input
  14. type="text"
  15. ref="inputRef"
  16. :disabled="disabled"
  17. :value="value"
  18. :placeholder="placeholder"
  19. @input="$event => handleInput($event)"
  20. @focus="$event => handleFocus($event)"
  21. @blur="$event => handleBlur($event)"
  22. @change="$event => emit('change', $event)"
  23. @keydown.enter="$event => emit('enter', $event)"
  24. />
  25. <span class="suffix">
  26. <slot name="suffix"></slot>
  27. </span>
  28. </div>
  29. </template>
  30. <script lang="ts" setup>
  31. import { ref } from "vue"
  32. withDefaults(
  33. defineProps<{
  34. value: string
  35. disabled?: boolean
  36. placeholder?: string
  37. simple?: boolean
  38. }>(),
  39. {
  40. disabled: false,
  41. placeholder: "",
  42. simple: false
  43. }
  44. )
  45. const emit = defineEmits<{
  46. (event: "update:value", payload: string): void
  47. (event: "input", payload: Event): void
  48. (event: "change", payload: Event): void
  49. (event: "blur", payload: Event): void
  50. (event: "focus", payload: Event): void
  51. (event: "enter", payload: Event): void
  52. }>()
  53. const focused = ref(false)
  54. const handleInput = (e: Event) => {
  55. emit("update:value", (e.target as HTMLInputElement).value)
  56. }
  57. const handleBlur = (e: Event) => {
  58. focused.value = false
  59. emit("blur", e)
  60. }
  61. const handleFocus = (e: Event) => {
  62. focused.value = true
  63. emit("focus", e)
  64. }
  65. const inputRef = ref<HTMLInputElement>()
  66. const focus = () => {
  67. if (inputRef.value) inputRef.value.focus()
  68. }
  69. defineExpose({
  70. focus
  71. })
  72. </script>
  73. <style lang="scss" scoped>
  74. .input {
  75. background-color: #fff;
  76. border: 1px solid #dedede;
  77. padding: 0 5px;
  78. border-radius: $borderRadius;
  79. transition: border-color 0.25s;
  80. font-size: 13px;
  81. display: flex;
  82. input {
  83. min-width: 0;
  84. height: 30px;
  85. outline: 0;
  86. border: 0;
  87. line-height: 30px;
  88. vertical-align: top;
  89. color: $textColor;
  90. padding: 0 5px;
  91. flex: 1;
  92. font-size: 13px;
  93. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji",
  94. "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
  95. &::placeholder {
  96. color: #bfbfbf;
  97. }
  98. }
  99. &:not(.disabled):hover,
  100. &.focused {
  101. border-color: $themeColor;
  102. }
  103. &.disabled {
  104. background-color: #f5f5f5;
  105. border-color: #dcdcdc;
  106. color: #b7b7b7;
  107. input {
  108. color: #b7b7b7;
  109. }
  110. }
  111. &.simple {
  112. border: 0;
  113. }
  114. .prefix,
  115. .suffix {
  116. display: flex;
  117. justify-content: center;
  118. align-items: center;
  119. line-height: 30px;
  120. user-select: none;
  121. }
  122. }
  123. </style>