Init Nicknames & Notes
This commit is contained in:
parent
ebecf2403f
commit
e26916702c
42 changed files with 1050 additions and 23 deletions
56
ts/components/AutoSizeTextArea.tsx
Normal file
56
ts/components/AutoSizeTextArea.tsx
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Copyright 2024 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
import type { ForwardedRef } from 'react';
|
||||
import React, { forwardRef, useEffect, useLayoutEffect, useRef } from 'react';
|
||||
import { mergeRefs } from '@react-aria/utils';
|
||||
import { strictAssert } from '../util/assert';
|
||||
import type { PropsType } from './Input';
|
||||
import { Input } from './Input';
|
||||
|
||||
export const AutoSizeTextArea = forwardRef(function AutoSizeTextArea(
|
||||
props: PropsType,
|
||||
ref: ForwardedRef<HTMLTextAreaElement>
|
||||
): JSX.Element {
|
||||
const ownRef = useRef<HTMLTextAreaElement | null>(null);
|
||||
const textareaRef = mergeRefs(ownRef, ref);
|
||||
|
||||
function update(textarea: HTMLTextAreaElement) {
|
||||
const styles = window.getComputedStyle(textarea);
|
||||
const { scrollHeight } = textarea;
|
||||
let height = 'calc(';
|
||||
height += `${scrollHeight}px`;
|
||||
if (styles.boxSizing === 'border-box') {
|
||||
height += ` + ${styles.borderTopWidth} + ${styles.borderBottomWidth}`;
|
||||
} else {
|
||||
height += ` - ${styles.paddingTop} - ${styles.paddingBottom}`;
|
||||
}
|
||||
height += ')';
|
||||
Object.assign(textarea.style, {
|
||||
height,
|
||||
overflow: 'hidden',
|
||||
resize: 'none',
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
strictAssert(ownRef.current, 'inputRef.current should be defined');
|
||||
const textarea = ownRef.current;
|
||||
function onInput() {
|
||||
textarea.style.height = 'auto';
|
||||
requestAnimationFrame(() => update(textarea));
|
||||
}
|
||||
textarea.addEventListener('input', onInput);
|
||||
return () => {
|
||||
textarea.removeEventListener('input', onInput);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
strictAssert(ownRef.current, 'inputRef.current should be defined');
|
||||
const textarea = ownRef.current;
|
||||
textarea.style.height = 'auto';
|
||||
update(textarea);
|
||||
}, [props.value]);
|
||||
|
||||
return <Input ref={textareaRef} {...props} forceTextarea />;
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue