| <script lang="ts"> |
| import { onMount, tick } from 'svelte'; |
| |
| export let value = ''; |
| export let placeholder = ''; |
| export let rows = 1; |
| export let minSize = null; |
| export let maxSize = null; |
| export let required = false; |
| export let readonly = false; |
| export let className = |
| 'w-full rounded-lg px-3.5 py-2 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-hidden h-full'; |
| export let ariaLabel = null; |
| |
| export let onInput = () => {}; |
| export let onBlur = () => {}; |
| |
| let textareaElement; |
| |
| |
| onMount(async () => { |
| await tick(); |
| resize(); |
| |
| requestAnimationFrame(() => { |
| |
| const interval = setInterval(() => { |
| if (textareaElement) { |
| clearInterval(interval); |
| resize(); |
| } |
| }, 100); |
| }); |
| }); |
| |
| const resize = () => { |
| if (textareaElement) { |
| |
| |
| |
| let activeScrollParents = []; |
| let p = textareaElement.parentNode; |
| while (p && p !== document.body) { |
| if (p instanceof HTMLElement && p.scrollTop > 0) { |
| activeScrollParents.push({ el: p, top: p.scrollTop }); |
| } |
| p = p.parentNode; |
| } |
| const windowScrollY = window.scrollY; |
| |
| textareaElement.style.height = ''; |
| |
| let height = textareaElement.scrollHeight; |
| if (maxSize && height > maxSize) { |
| height = maxSize; |
| } |
| if (minSize && height < minSize) { |
| height = minSize; |
| } |
| |
| textareaElement.style.height = `${height}px`; |
| |
| |
| |
| activeScrollParents.forEach((p) => { |
| if (p.el.scrollTop !== p.top) p.el.scrollTop = p.top; |
| }); |
| if (window.scrollY !== windowScrollY) { |
| window.scrollTo(window.scrollX, windowScrollY); |
| } |
| } |
| }; |
| </script> |
|
|
| <textarea |
| bind:this={textareaElement} |
| bind:value |
| {placeholder} |
| aria-label={ariaLabel || placeholder} |
| class={className} |
| style="field-sizing: content;" |
| {rows} |
| {required} |
| {readonly} |
| on:input={(e) => { |
| resize(); |
|
|
| onInput(e); |
| }} |
| on:focus={() => { |
| resize(); |
| }} |
| on:blur={onBlur} |
| /> |
|
|