feat: Add auto-resize on text input
This commit is contained in:
parent
52bd4e4ce4
commit
5288e09b27
28
src/lib/components/ui/textarea/index.ts
Normal file
28
src/lib/components/ui/textarea/index.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import Root from "./textarea.svelte";
|
||||
|
||||
type FormTextareaEvent<T extends Event = Event> = T & {
|
||||
currentTarget: EventTarget & HTMLTextAreaElement;
|
||||
};
|
||||
|
||||
type TextareaEvents = {
|
||||
blur: FormTextareaEvent<FocusEvent>;
|
||||
change: FormTextareaEvent<Event>;
|
||||
click: FormTextareaEvent<MouseEvent>;
|
||||
focus: FormTextareaEvent<FocusEvent>;
|
||||
keydown: FormTextareaEvent<KeyboardEvent>;
|
||||
keypress: FormTextareaEvent<KeyboardEvent>;
|
||||
keyup: FormTextareaEvent<KeyboardEvent>;
|
||||
mouseover: FormTextareaEvent<MouseEvent>;
|
||||
mouseenter: FormTextareaEvent<MouseEvent>;
|
||||
mouseleave: FormTextareaEvent<MouseEvent>;
|
||||
paste: FormTextareaEvent<ClipboardEvent>;
|
||||
input: FormTextareaEvent<InputEvent>;
|
||||
};
|
||||
|
||||
export {
|
||||
Root,
|
||||
//
|
||||
Root as Textarea,
|
||||
type TextareaEvents,
|
||||
type FormTextareaEvent,
|
||||
};
|
43
src/lib/components/ui/textarea/textarea.svelte
Normal file
43
src/lib/components/ui/textarea/textarea.svelte
Normal file
@ -0,0 +1,43 @@
|
||||
<script lang="ts">
|
||||
import { cn } from '$lib/utils.js';
|
||||
import type { HTMLTextareaAttributes } from 'svelte/elements';
|
||||
import type { TextareaEvents } from './index.js';
|
||||
|
||||
// Note: The autoResize directive is NOT part of the shadcn-svelte package,
|
||||
// it just has to be added directly to the root component because of a
|
||||
// Svelte limitation.
|
||||
import { autoResize } from '$lib/functions/autoresize.svelte';
|
||||
|
||||
type $$Props = HTMLTextareaAttributes;
|
||||
type $$Events = TextareaEvents;
|
||||
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let value: $$Props['value'] = undefined;
|
||||
export { className as class };
|
||||
|
||||
// Workaround for https://github.com/sveltejs/svelte/issues/9305
|
||||
// Fixed in Svelte 5, but not backported to 4.x.
|
||||
export let readonly: $$Props['readonly'] = undefined;
|
||||
</script>
|
||||
|
||||
<textarea
|
||||
class={cn(
|
||||
'flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
|
||||
className,
|
||||
)}
|
||||
bind:value
|
||||
{readonly}
|
||||
on:blur
|
||||
on:change
|
||||
on:click
|
||||
on:focus
|
||||
on:keydown
|
||||
on:keypress
|
||||
on:keyup
|
||||
on:mouseover
|
||||
on:mouseenter
|
||||
on:mouseleave
|
||||
on:paste
|
||||
on:input
|
||||
use:autoResize
|
||||
{...$$restProps}></textarea>
|
14
src/lib/functions/autoresize.svelte.ts
Normal file
14
src/lib/functions/autoresize.svelte.ts
Normal file
@ -0,0 +1,14 @@
|
||||
export function autoResize(node: HTMLElement) {
|
||||
function resize() {
|
||||
node.style.height = 'auto';
|
||||
node.style.height = node.scrollHeight + 'px';
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
resize();
|
||||
node.addEventListener('input', resize);
|
||||
return () => {
|
||||
node.removeEventListener('input', resize);
|
||||
};
|
||||
});
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
import { page } from '$app/state';
|
||||
import Message from '$lib/components/message.svelte';
|
||||
import { Button } from '$lib/components/ui/button/index';
|
||||
import { Input } from '$lib/components/ui/input/index';
|
||||
import Textarea from '$lib/components/ui/textarea/textarea.svelte';
|
||||
import Websocket from '$lib/functions/clientWebsocket.svelte';
|
||||
import type { TypeMessage } from '$lib/types';
|
||||
import Send from 'lucide-svelte/icons/send';
|
||||
@ -10,6 +10,7 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import type { PageData } from './$types';
|
||||
import { autoResize } from '$lib/functions/autoresize.svelte';
|
||||
|
||||
const { data }: { data: PageData } = $props();
|
||||
|
||||
@ -50,7 +51,7 @@
|
||||
socket?.sendMessage(user!, msg);
|
||||
msg = '';
|
||||
}}>
|
||||
<Input type="text" placeholder="Type Here" bind:value={msg} />
|
||||
<Button class="h-9 w-14" type="submit"><Send class="size-full" /></Button>
|
||||
<Textarea placeholder="Type Here" bind:value={msg} />
|
||||
<Button class="h-full w-14" type="submit"><Send class="size-full" /></Button>
|
||||
</form>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user