fix(stage-web): fix textarea behaviors (#72)

This commit is contained in:
junkwarrior87
2025-03-12 17:41:34 +08:00
committed by GitHub
parent b1b6071df4
commit 6d5f9760c3
2 changed files with 16 additions and 50 deletions
@@ -198,7 +198,7 @@ onAfterSend(async () => {
:placeholder="t('stage.message')"
text="primary-300 hover:primary-500 dark:primary-300/50 dark:hover:primary-500 placeholder:primary-300 placeholder:hover:primary-500 placeholder:dark:primary-300/50 placeholder:dark:hover:primary-500"
bg="primary-100 dark:primary-400/20"
min-h="[100px]" w-full
min-h="[100px]" max-h="[300px]" w-full
rounded-t-xl p-4 font-medium
outline-none transition="all duration-250 ease-in-out placeholder:all placeholder:duration-250 placeholder:ease-in-out"
@submit="handleSend"
@@ -1,7 +1,5 @@
<script setup lang="ts" generic="T extends any, O extends any">
import type { CSSProperties } from 'vue'
import { nextTick, onMounted, ref } from 'vue'
<script setup lang="ts">
import { ref, watch } from 'vue'
const events = defineEmits<{
(event: 'submit', message: string): void
@@ -12,65 +10,33 @@ const input = defineModel<string>({
})
const textareaRef = ref<HTMLTextAreaElement>()
const textareaStyle = ref<CSSProperties>({
height: 'auto',
overflowY: 'hidden',
})
const textareaHeight = ref('auto')
// javascript - Creating a textarea with auto-resize - Stack Overflow
// https://stackoverflow.com/questions/454202/creating-a-textarea-with-auto-resize
function onInput(e: Event) {
if (!(e.target instanceof HTMLTextAreaElement))
return
e.target.style.height = 'auto'
e.target.style.height = `${e.target.scrollHeight}px`
}
// javascript - How do I detect "shift+enter" and generate a new line in Textarea? - Stack Overflow
// https://stackoverflow.com/questions/6014702/how-do-i-detect-shiftenter-and-generate-a-new-line-in-textarea
function onKeyDown(e: KeyboardEvent) {
if (!(e.target instanceof HTMLTextAreaElement))
return
if (e.code === 'Enter' && e.shiftKey) {
e.preventDefault()
const start = e.target?.selectionStart
const end = e.target?.selectionEnd
input.value = `${input.value.substring(0, start)}\n${input.value.substring(end)}`
// javascript - height of textarea increases when value increased but does not reduce when value is decreased - Stack Overflow
// https://stackoverflow.com/questions/10722058/height-of-textarea-increases-when-value-increased-but-does-not-reduce-when-value
textareaStyle.value.height = '0'
nextTick().then(() => {
if (!textareaRef.value)
return
textareaRef.value.selectionStart = textareaRef.value.selectionEnd = start + 1
textareaStyle.value.height = `${textareaRef.value.scrollHeight}px`
})
}
else if (e.code === 'Enter') { // block enter
if (e.code === 'Enter' && !e.shiftKey) { // just block Enter is enough, Shift+Enter by default generates a newline
e.preventDefault()
events('submit', input.value)
}
}
onMounted(() => {
if (!textareaRef.value)
return
// javascript - Creating a textarea with auto-resize - Stack Overflow
// https://stackoverflow.com/questions/454202/creating-a-textarea-with-auto-resize
watch(input, () => {
textareaHeight.value = 'auto'
requestAnimationFrame(() => {
if (!textareaRef.value)
return
textareaStyle.value.height = `${textareaRef.value.scrollHeight}px`
})
textareaHeight.value = `${textareaRef.value.scrollHeight}px`
})
}, { immediate: true })
</script>
<template>
<textarea
ref="textareaRef"
v-model="input"
:style="textareaStyle"
@input="onInput"
:style="{ height: textareaHeight }"
@keydown="onKeyDown"
/>
</template>