2023-08-14 09:23:39 +00:00
|
|
|
<template>
|
2023-10-12 15:56:11 +02:00
|
|
|
<WordCounter
|
|
|
|
|
:id="intId"
|
|
|
|
|
class="ck-word-count"
|
|
|
|
|
/>
|
|
|
|
|
<textarea
|
|
|
|
|
ref="textarea"
|
|
|
|
|
:id="intId"
|
|
|
|
|
:class="`input-text-auto-component ${intClass}`"
|
|
|
|
|
:name="intName"
|
|
|
|
|
:aria-describedby="intAriaDescribedby"
|
|
|
|
|
:placeholder="intPlaceholder"
|
|
|
|
|
:required="intRequired"
|
|
|
|
|
@input="onInput"
|
|
|
|
|
@blur="onBlur"
|
|
|
|
|
v-model="intValue"
|
|
|
|
|
/>
|
2023-08-14 09:23:39 +00:00
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script lang="ts">
|
|
|
|
|
import { defineComponent, ref } from "vue";
|
|
|
|
|
import trans from "../../modules/trans";
|
|
|
|
|
import WordCounter from "./WordCounterComponent.vue";
|
|
|
|
|
|
|
|
|
|
const textarea = ref<HTMLTextAreaElement | null>(null);
|
|
|
|
|
|
|
|
|
|
export default defineComponent({
|
|
|
|
|
inheritAttrs: false,
|
|
|
|
|
mixins: [trans],
|
|
|
|
|
components: {
|
|
|
|
|
WordCounter,
|
|
|
|
|
},
|
|
|
|
|
setup() {
|
|
|
|
|
return { textarea };
|
|
|
|
|
},
|
|
|
|
|
beforeMount() {
|
|
|
|
|
if (!this.$attrs.json) {
|
|
|
|
|
throw new Error("this component requires json");
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
mounted() {
|
|
|
|
|
const json = String(this.$attrs.json ?? "{}"),
|
|
|
|
|
data = JSON.parse(json);
|
|
|
|
|
this.intId = String(data.id);
|
|
|
|
|
this.intClass = String(data.class);
|
|
|
|
|
this.intName = String(data.name);
|
|
|
|
|
this.intPlaceholder = String(data.placeholder);
|
|
|
|
|
this.intAriaDescribedby = String(data.ariaDescribedby);
|
|
|
|
|
this.intValue = String(data.value);
|
|
|
|
|
if (data.required) {
|
|
|
|
|
this.intRequired = true;
|
|
|
|
|
}
|
|
|
|
|
if (this.textarea) {
|
|
|
|
|
// Default input init
|
|
|
|
|
this.textarea.setAttribute("style", "height: 1rem;overflow-y: hidden;");
|
|
|
|
|
}
|
|
|
|
|
// * Init input
|
|
|
|
|
this.$nextTick(this.onInput);
|
|
|
|
|
},
|
|
|
|
|
data(): {
|
|
|
|
|
intId: string;
|
|
|
|
|
intClass: string;
|
|
|
|
|
intName: string;
|
|
|
|
|
intPlaceholder: string;
|
|
|
|
|
intAriaDescribedby: string;
|
|
|
|
|
intRequired: boolean;
|
|
|
|
|
intValue: string;
|
|
|
|
|
} {
|
|
|
|
|
return {
|
|
|
|
|
intId: "",
|
|
|
|
|
intClass: "",
|
|
|
|
|
intName: "",
|
|
|
|
|
intPlaceholder: "",
|
|
|
|
|
intAriaDescribedby: "",
|
|
|
|
|
intRequired: false,
|
|
|
|
|
intValue: "",
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
2023-10-12 15:56:11 +02:00
|
|
|
onBlur() {
|
|
|
|
|
const el = textarea.value;
|
|
|
|
|
if (!el) {
|
|
|
|
|
throw new Error("undefined textarea element");
|
|
|
|
|
}
|
|
|
|
|
// * Remove every new line char
|
|
|
|
|
el.value = el.value.replace(/[\n\r]/g, "");
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
el.style.height = "auto";
|
|
|
|
|
el.style.height = `${el.scrollHeight}px`;
|
|
|
|
|
});
|
|
|
|
|
},
|
2023-08-14 09:23:39 +00:00
|
|
|
onInput() {
|
|
|
|
|
const el = textarea.value;
|
|
|
|
|
if (!el) {
|
|
|
|
|
throw new Error("undefined textarea element");
|
|
|
|
|
}
|
|
|
|
|
el.style.height = "auto";
|
|
|
|
|
el.style.height = `${el.scrollHeight}px`;
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="scss">
|
2023-10-12 15:56:11 +02:00
|
|
|
.input-text-auto-component {
|
2023-08-14 09:23:39 +00:00
|
|
|
resize: none;
|
|
|
|
|
}
|
|
|
|
|
</style>
|