@gravity-ui/uikit
Version:
Gravity UI base styling and components
90 lines (89 loc) • 4.4 kB
JavaScript
'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from 'react';
import { useControlledState, useForkRef, useUniqId } from "../../../hooks/index.js";
import { useFormResetHandler } from "../../../hooks/private/index.js";
import { block } from "../../utils/cn.js";
import { ClearButton, mapTextInputSizeToButtonSize } from "../common/index.js";
import { OuterAdditionalContent } from "../common/OuterAdditionalContent/OuterAdditionalContent.js";
import { errorPropsMapper, getInputControlState, prepareAutoComplete } from "../utils.js";
import { TextAreaControl } from "./TextAreaControl.js";
import "./TextArea.css";
const b = block('text-area');
export const TextArea = React.forwardRef(function TextArea(props, ref) {
const { view = 'normal', size = 'm', pin = 'round-round', name, value, defaultValue, disabled, readOnly, hasClear = false, error, errorMessage: errorMessageProp, validationState: validationStateProp, autoComplete, id: idProp, tabIndex, style, className, qa, controlProps, note, onUpdate, onChange, } = props;
const { errorMessage, validationState } = errorPropsMapper({
error,
errorMessage: errorMessageProp,
validationState: validationStateProp,
});
const [inputValue, setInputValue] = useControlledState(value, defaultValue ?? '', onUpdate);
const innerControlRef = React.useRef(null);
const fieldRef = useFormResetHandler({ initialValue: inputValue, onReset: setInputValue });
const handleRef = useForkRef(props.controlRef, innerControlRef, fieldRef);
const [hasVerticalScrollbar, setHasVerticalScrollbar] = React.useState(false);
const state = getInputControlState(validationState);
const innerId = useUniqId();
const isErrorMsgVisible = validationState === 'invalid' && Boolean(errorMessage);
const isClearControlVisible = Boolean(hasClear && !disabled && !readOnly && inputValue);
const id = idProp || innerId;
const errorMessageId = useUniqId();
const noteId = useUniqId();
const ariaDescribedBy = [
controlProps?.['aria-describedby'],
note ? noteId : undefined,
isErrorMsgVisible ? errorMessageId : undefined,
]
.filter(Boolean)
.join(' ');
const commonProps = {
id,
tabIndex,
name,
onChange(event) {
setInputValue(event.target.value);
if (onChange) {
onChange(event);
}
},
autoComplete: prepareAutoComplete(autoComplete),
controlProps: {
...controlProps,
'aria-describedby': ariaDescribedBy || undefined,
'aria-invalid': validationState === 'invalid' || undefined,
},
};
const handleClear = (event) => {
const control = innerControlRef.current;
if (control) {
control.focus();
const syntheticEvent = Object.create(event);
syntheticEvent.target = control;
syntheticEvent.currentTarget = control;
control.value = '';
if (onChange) {
onChange(syntheticEvent);
}
}
setInputValue('');
};
React.useEffect(() => {
const control = innerControlRef.current;
if (control) {
const currHasVerticalScrollbar = control.scrollHeight > control.clientHeight;
if (hasVerticalScrollbar !== currHasVerticalScrollbar) {
setHasVerticalScrollbar(currHasVerticalScrollbar);
}
}
}, [inputValue, hasVerticalScrollbar]);
return (_jsxs("span", { ref: ref, style: style, className: b({
view,
size,
disabled,
state,
pin: view === 'clear' ? undefined : pin,
'has-clear': isClearControlVisible,
'has-scrollbar': hasVerticalScrollbar,
}, className), "data-qa": qa, children: [_jsxs("span", { className: b('content'), children: [_jsx(TextAreaControl, { ...props, ...commonProps, controlRef: handleRef }), isClearControlVisible && (_jsx(ClearButton, { className: b('clear', { size }), size: mapTextInputSizeToButtonSize(size), onClick: handleClear }))] }), _jsx(OuterAdditionalContent, { errorMessage: isErrorMsgVisible ? errorMessage : null, errorMessageId: errorMessageId, note: note, noteId: noteId })] }));
});
//# sourceMappingURL=TextArea.js.map