- Change dynamic textarea to better height scale

This commit is contained in:
Infi
2025-10-01 19:49:58 +02:00
parent 9f5255d71b
commit 14336a9417
4 changed files with 40 additions and 17 deletions
@@ -1,6 +1,19 @@
<script lang="ts"> <script lang="ts">
import {onMount} from "svelte";
import {subscribe} from "$lib/utils.svelte";
import {chatInput} from "$lib/shared.svelte";
let textarea: HTMLTextAreaElement; let textarea: HTMLTextAreaElement;
let content: string = $state('');
subscribe(
() => chatInput,
(v) => {
// Input box has been reset to empty, so resize it back to smaller box
if (v.content === '') {
resize();
}
}
);
function preventNewlines(e: KeyboardEvent) { function preventNewlines(e: KeyboardEvent) {
if (e.key === 'Enter') { if (e.key === 'Enter') {
@@ -13,7 +26,6 @@
(e.currentTarget as HTMLTextAreaElement).closest('form')?.dispatchEvent(newEvent); (e.currentTarget as HTMLTextAreaElement).closest('form')?.dispatchEvent(newEvent);
} }
} }
} }
function resize() { function resize() {
@@ -21,13 +33,17 @@
return; return;
textarea.style.height = '1px'; textarea.style.height = '1px';
textarea.style.height = `${textarea.scrollHeight}px`; textarea.style.height = `${textarea.scrollHeight + 10}px`; // with +10px extra padding
} }
onMount(() => {
resize();
})
</script> </script>
<textarea <textarea
bind:this={textarea} bind:this={textarea}
bind:value={content} bind:value={chatInput.content}
oninput={() => resize()} oninput={() => resize()}
onkeydown={(e) => preventNewlines(e)} onkeydown={(e) => preventNewlines(e)}
@@ -52,6 +68,8 @@
} }
width: 100%; width: 100%;
padding: 5px 20px;
min-height: 2.5em;
line-height: 1.25;
} }
</style> </style>
+4 -12
View File
@@ -1,4 +1,4 @@
import { channelOptions, isChannelLocked, selectedTab, knownTabs } from "$lib/shared.svelte"; import { channelOptions, isChannelLocked, selectedTab, knownTabs, chatInput } from "$lib/shared.svelte";
import { source, type Source } from "sveltekit-sse"; import { source, type Source } from "sveltekit-sse";
interface ChatElements { interface ChatElements {
@@ -8,7 +8,6 @@ interface ChatElements {
timestampWidthProbe: HTMLElement | null, timestampWidthProbe: HTMLElement | null,
inputForm: Element | null, inputForm: Element | null,
chatInput: HTMLElement | null,
} }
// ref `DataStructure.Messages` // ref `DataStructure.Messages`
@@ -77,7 +76,6 @@ export class ChatTwoWeb {
timestampWidthProbe: document.getElementById('timestamp-width-probe'), timestampWidthProbe: document.getElementById('timestamp-width-probe'),
inputForm: document.querySelector('#input > form'), inputForm: document.querySelector('#input > form'),
chatInput: document.getElementById('chat-input')
}; };
// add indicator signaling more messages below // add indicator signaling more messages below
@@ -102,13 +100,8 @@ export class ChatTwoWeb {
// handle message sending // handle message sending
this.elements.inputForm?.addEventListener('submit', async (event) => { this.elements.inputForm?.addEventListener('submit', async (event) => {
if (this.elements.chatInput === null)
return;
event.preventDefault(); event.preventDefault();
// @ts-ignore if (chatInput.content.length > 500) {
const message = this.elements.chatInput.value;
if (message.length > 500) {
return; return;
} }
@@ -118,13 +111,12 @@ export class ChatTwoWeb {
'Accept': 'application/json', 'Accept': 'application/json',
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}, },
body: JSON.stringify({ message: message }) body: JSON.stringify({ message: chatInput.content })
}); });
// const content = await rawResponse.json(); // const content = await rawResponse.json();
// TODO: use the response // TODO: use the response
// @ts-ignore chatInput.content = '';
this.elements.chatInput.value = '';
}); });
} }
@@ -23,3 +23,5 @@ export function closeTabPane() {
tabPaneState.visible = false; tabPaneState.visible = false;
window.localStorage.setItem(persistentTabPabeStateKey, 'false'); window.localStorage.setItem(persistentTabPabeStateKey, 'false');
} }
export const chatInput: { content: string } = $state({ content: ''} );
@@ -0,0 +1,11 @@
import {writable} from "svelte/store";
// https://stackoverflow.com/a/79696571
export const subscribe = <T>(functionToState: () => T, callback: (v: T) => void) => {
let value = writable<T>(functionToState());
value.subscribe(callback);
$effect(() => {
value.set(functionToState());
});
};