1
0
mirror of https://github.com/robonen/lorem-blog.git synced 2026-03-20 10:54:38 +00:00

feat(ui): add Input, Textarea, Button, and Badge components with styles and props

This commit is contained in:
2025-06-15 15:37:29 +07:00
parent fc7eacffbd
commit e528230264
12 changed files with 240 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
import { clamp } from '@robonen/stdlib';
import { nextTick, onMounted, onUnmounted, ref, type TemplateRef, watch } from 'vue';
export function useTextAreaAutosize(textareaRef: TemplateRef<HTMLTextAreaElement | null>) {
const minHeight = ref(0);
const maxHeight = ref(Infinity);
const resize = () => nextTick(() => {
const textarea = textareaRef.value;
if (!textarea)
return;
textarea.style.height = 'auto';
const newHeight = clamp(textarea.scrollHeight, minHeight.value, maxHeight.value);
textarea.style.height = `${newHeight}px`;
textarea.style.overflowY = newHeight >= maxHeight.value ? 'auto' : 'hidden';
});
const handleInput = () => {
resize();
};
onMounted(() => {
const textarea = textareaRef.value;
if (textarea) {
minHeight.value = textarea.offsetHeight;
textarea.addEventListener('input', handleInput);
textarea.addEventListener('paste', handleInput);
resize();
}
});
onUnmounted(() => {
const textarea = textareaRef.value;
if (textarea) {
textarea.removeEventListener('input', handleInput);
textarea.removeEventListener('paste', handleInput);
}
});
watch(textareaRef, (newTextarea) => {
if (newTextarea) {
minHeight.value = newTextarea.offsetHeight;
resize();
}
});
const setMinHeight = (height: number) => {
minHeight.value = height;
resize();
};
const setMaxHeight = (height: number) => {
maxHeight.value = height;
resize();
};
return {
resize,
setMinHeight,
setMaxHeight,
};
}