import isArray from 'shared/isArray';
import {checkControlledValueProps} from '../shared/ReactControlledValuePropTypes';
import {getCurrentFiberOwnerNameInDevOrNull} from 'react-reconciler/src/ReactCurrentFiber';
import {getToStringValue, toString} from './ToStringValue';
import type {ToStringValue} from './ToStringValue';
import {disableTextareaChildren} from 'shared/ReactFeatureFlags';
let didWarnValDefaultVal = false;
type TextAreaWithWrapperState = HTMLTextAreaElement & {
_wrapperState: {initialValue: ToStringValue},
};
export function getHostProps(element: Element, props: Object): Object {
const node = ((element: any): TextAreaWithWrapperState);
if (props.dangerouslySetInnerHTML != null) {
throw new Error(
'`dangerouslySetInnerHTML` does not make sense on <textarea>.',
);
}
const hostProps = {
...props,
value: undefined,
defaultValue: undefined,
children: toString(node._wrapperState.initialValue),
};
return hostProps;
}
export function initWrapperState(element: Element, props: Object) {
const node = ((element: any): TextAreaWithWrapperState);
if (__DEV__) {
checkControlledValueProps('textarea', props);
if (
props.value !== undefined &&
props.defaultValue !== undefined &&
!didWarnValDefaultVal
) {
console.error(
'%s contains a textarea with both value and defaultValue props. ' +
'Textarea elements must be either controlled or uncontrolled ' +
'(specify either the value prop, or the defaultValue prop, but not ' +
'both). Decide between using a controlled or uncontrolled textarea ' +
'and remove one of these props. More info: ' +
'https://reactjs.org/link/controlled-components',
getCurrentFiberOwnerNameInDevOrNull() || 'A component',
);
didWarnValDefaultVal = true;
}
}
let initialValue = props.value;
if (initialValue == null) {
let {children, defaultValue} = props;
if (children != null) {
if (__DEV__) {
console.error(
'Use the `defaultValue` or `value` props instead of setting ' +
'children on <textarea>.',
);
}
if (!disableTextareaChildren) {
if (defaultValue != null) {
throw new Error(
'If you supply `defaultValue` on a <textarea>, do not pass children.',
);
}
if (isArray(children)) {
if (children.length > 1) {
throw new Error('<textarea> can only have at most one child.');
}
children = children[0];
}
defaultValue = children;
}
}
if (defaultValue == null) {
defaultValue = '';
}
initialValue = defaultValue;
}
node._wrapperState = {
initialValue: getToStringValue(initialValue),
};
}
export function updateWrapper(element: Element, props: Object) {
const node = ((element: any): TextAreaWithWrapperState);
const value = getToStringValue(props.value);
const defaultValue = getToStringValue(props.defaultValue);
if (value != null) {
const newValue = toString(value);
if (newValue !== node.value) {
node.value = newValue;
}
if (props.defaultValue == null && node.defaultValue !== newValue) {
node.defaultValue = newValue;
}
}
if (defaultValue != null) {
node.defaultValue = toString(defaultValue);
}
}
export function postMountWrapper(element: Element, props: Object) {
const node = ((element: any): TextAreaWithWrapperState);
const textContent = node.textContent;
if (textContent === node._wrapperState.initialValue) {
if (textContent !== '' && textContent !== null) {
node.value = textContent;
}
}
}
export function restoreControlledState(element: Element, props: Object) {
updateWrapper(element, props);
}