99 lines
2.2 KiB
Vue
99 lines
2.2 KiB
Vue
<template>
|
|
<form @submit.prevent="submit">
|
|
<div class="field">
|
|
<span class="field-title" v-if="titleComponent"
|
|
><component :is="titleComponent"
|
|
/></span>
|
|
<VueTextareaAutosize
|
|
v-if="textArea"
|
|
v-model="value"
|
|
:placeholder="placeholder"
|
|
:maxHeight="maxHeight"
|
|
@blur="blur"
|
|
ref="field"
|
|
/>
|
|
<input
|
|
v-else
|
|
type="text"
|
|
v-model="value"
|
|
:placeholder="placeholder"
|
|
:class="{ fullWidth: !title }"
|
|
@blur="blur"
|
|
ref="field"
|
|
/>
|
|
</div>
|
|
</form>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import "components/common/fields.css";
|
|
import type { CoercableComponent } from "features/feature";
|
|
import { computeOptionalComponent } from "util/vue";
|
|
import { computed, onMounted, shallowRef, toRef, unref } from "vue";
|
|
import VueTextareaAutosize from "vue-textarea-autosize";
|
|
|
|
const props = defineProps<{
|
|
title?: CoercableComponent;
|
|
modelValue?: string;
|
|
textArea?: boolean;
|
|
placeholder?: string;
|
|
maxHeight?: number;
|
|
submitOnBlur?: boolean;
|
|
}>();
|
|
const emit = defineEmits<{
|
|
(e: "update:modelValue", value: string): void;
|
|
(e: "submit"): void;
|
|
(e: "cancel"): void;
|
|
}>();
|
|
|
|
const titleComponent = computeOptionalComponent(toRef(props, "title"), "span");
|
|
|
|
const field = shallowRef<HTMLElement | null>(null);
|
|
onMounted(() => {
|
|
field.value?.focus();
|
|
});
|
|
|
|
const value = computed({
|
|
get() {
|
|
return unref(props.modelValue) ?? "";
|
|
},
|
|
set(value: string) {
|
|
emit("update:modelValue", value);
|
|
}
|
|
});
|
|
|
|
function submit() {
|
|
emit("submit");
|
|
}
|
|
|
|
function blur() {
|
|
if (props.submitOnBlur !== false) {
|
|
emit("submit");
|
|
} else {
|
|
emit("cancel");
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
form {
|
|
margin: 0;
|
|
width: 100%;
|
|
}
|
|
|
|
.field > * {
|
|
margin: 0;
|
|
}
|
|
|
|
input {
|
|
width: 50%;
|
|
outline: none;
|
|
border: solid 1px var(--outline);
|
|
background-color: unset;
|
|
border-radius: var(--border-radius);
|
|
}
|
|
|
|
.fullWidth {
|
|
width: 100%;
|
|
}
|
|
</style>
|