93 lines
2.5 KiB
Vue
93 lines
2.5 KiB
Vue
<template>
|
|
<div class="field-input-group">
|
|
<label class="field-input-group__label">
|
|
{{ label }}<span v-if="required" class="field-input-group__req">*</span>
|
|
</label>
|
|
<textarea
|
|
v-if="type === 'textarea'"
|
|
:value="modelValue"
|
|
class="field-input-group__ctrl"
|
|
:class="{ 'is-invalid': error }"
|
|
:placeholder="placeholder"
|
|
:rows="rows"
|
|
@input="$emit('update:modelValue', $event.target.value)"
|
|
/>
|
|
<select
|
|
v-else-if="type === 'select'"
|
|
:value="modelValue"
|
|
class="field-input-group__ctrl"
|
|
:class="{ 'is-invalid': error }"
|
|
@change="$emit('update:modelValue', $event.target.value)"
|
|
>
|
|
<slot />
|
|
</select>
|
|
<input
|
|
v-else
|
|
:value="modelValue"
|
|
:type="type"
|
|
class="field-input-group__ctrl"
|
|
:class="{ 'is-invalid': error }"
|
|
:placeholder="placeholder"
|
|
:min="min"
|
|
:step="step"
|
|
@input="$emit('update:modelValue', $event.target.value)"
|
|
/>
|
|
<span v-if="error" class="field-input-group__error">{{ error }}</span>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { defineProps, defineEmits } from "vue";
|
|
|
|
defineProps({
|
|
modelValue: { type: [String, Number], default: "" },
|
|
label: { type: String, required: true },
|
|
type: { type: String, default: "text" },
|
|
placeholder:{ type: String, default: "" },
|
|
required: { type: Boolean, default: false },
|
|
error: { type: String, default: "" },
|
|
rows: { type: Number, default: 3 },
|
|
min: { type: [String, Number], default: undefined },
|
|
step: { type: [String, Number], default: undefined },
|
|
});
|
|
defineEmits(["update:modelValue"]);
|
|
</script>
|
|
|
|
<style scoped>
|
|
.field-input-group { display: flex; flex-direction: column; gap: 5px; }
|
|
|
|
.field-input-group__label {
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
color: #6b7280;
|
|
}
|
|
.field-input-group__req { color: #dc2626; margin-left: 2px; }
|
|
|
|
.field-input-group__ctrl {
|
|
font-size: 14px;
|
|
color: #111827;
|
|
background: #fff;
|
|
border: 1px solid #d1d5db;
|
|
border-radius: 6px;
|
|
padding: 8px 11px;
|
|
width: 100%;
|
|
font-family: inherit;
|
|
outline: none;
|
|
transition: border-color 0.15s, box-shadow 0.15s;
|
|
appearance: none;
|
|
}
|
|
.field-input-group__ctrl:focus {
|
|
border-color: #5e72e4;
|
|
box-shadow: 0 0 0 3px rgba(94, 114, 228, 0.18);
|
|
}
|
|
.field-input-group__ctrl.is-invalid { border-color: #dc2626; }
|
|
.field-input-group__ctrl.is-invalid:focus { box-shadow: 0 0 0 3px rgba(220,38,38,0.08); }
|
|
|
|
.field-input-group__error {
|
|
font-size: 12px;
|
|
color: #dc2626;
|
|
}
|
|
</style>
|