@hitachivantara/uikit-react-core
Version:
Core React components for the NEXT Design System.
279 lines (278 loc) • 9.66 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const jsxRuntime = require("react/jsx-runtime");
const React = require("react");
const utils = require("@mui/material/utils");
const uikitReactUtils = require("@hitachivantara/uikit-react-utils");
const validations = require("../BaseInput/validations.cjs");
const LabelContainer = require("../FormElement/LabelContainer.cjs");
const useControlled = require("../hooks/useControlled.cjs");
const useUniqueId = require("../hooks/useUniqueId.cjs");
const setId = require("../utils/setId.cjs");
const TextArea_styles = require("./TextArea.styles.cjs");
const FormElement = require("../FormElement/FormElement.cjs");
const CharCounter = require("../FormElement/CharCounter/CharCounter.cjs");
const BaseInput = require("../BaseInput/BaseInput.cjs");
const utils$1 = require("../FormElement/utils.cjs");
const WarningText = require("../FormElement/WarningText/WarningText.cjs");
const InfoMessage = require("../FormElement/InfoMessage/InfoMessage.cjs");
const HvTextArea = React.forwardRef(function HvTextArea2(props, ref) {
const {
id,
className,
classes: classesProp,
name,
label,
description: descriptionProp,
placeholder,
status,
statusMessage,
infoMessage: infoMessageProp,
validationMessages,
maxCharQuantity,
minCharQuantity,
value: valueProp,
inputRef: inputRefProp,
rows = 1,
defaultValue = "",
middleCountLabel = "/",
countCharProps,
inputProps,
required,
readOnly,
disabled,
autoFocus,
resizable,
autoScroll,
hideCounter,
blockMax,
"aria-label": ariaLabel,
"aria-labelledby": ariaLabelledBy,
"aria-describedby": ariaDescribedBy,
"aria-errormessage": ariaErrorMessage,
validation,
onChange,
onBlur,
onFocus,
...others
} = uikitReactUtils.useDefaultProps("HvTextArea", props);
const { classes, cx } = TextArea_styles.useClasses(classesProp);
const elementId = useUniqueId.useUniqueId(id);
const { activeTheme } = uikitReactUtils.useTheme();
const isDirty = React.useRef(false);
const inputRef = React.useRef(null);
const forkedRef = utils.useForkRef(ref, inputRefProp, inputRef);
const [description, infoMessage] = activeTheme?.name === "pentahoPlus" ? [infoMessageProp, descriptionProp] : [descriptionProp, infoMessageProp];
const [focused, setFocused] = React.useState(false);
const [autoScrolling, setAutoScrolling] = React.useState(autoScroll);
const [validationState, setValidationState] = useControlled.useControlled(
status,
"standBy"
);
const [validationMessage, setValidationMessage] = useControlled.useControlled(
statusMessage,
""
);
const [value, setValue] = useControlled.useControlled(valueProp, defaultValue);
const isStateInvalid = utils$1.isInvalid(validationState);
const isEmptyValue = value == null || value === "";
const hasLabel = label != null;
const hasCounter = maxCharQuantity != null && !hideCounter;
const errorMessages = React.useMemo(
() => ({ ...validations.DEFAULT_ERROR_MESSAGES, ...validationMessages }),
[validationMessages]
);
const performValidation = React.useCallback(() => {
const inputValidity = validations.validateInput(
inputRef.current,
required,
minCharQuantity,
maxCharQuantity,
"none",
validation
);
setValidationState(validations.computeValidationState(inputValidity, isEmptyValue));
setValidationMessage(
validations.computeValidationMessage(inputValidity, errorMessages)
);
return inputValidity;
}, [
errorMessages,
inputRef,
isEmptyValue,
maxCharQuantity,
minCharQuantity,
required,
setValidationMessage,
setValidationState,
validation
]);
const limitValue = (currentValue) => {
if (currentValue === void 0 || !blockMax) return currentValue;
const isOverflow = maxCharQuantity == null ? false : currentValue.length > maxCharQuantity;
return !isOverflow ? currentValue : currentValue.substring(0, maxCharQuantity);
};
const onContainerBlurHandler = (event) => {
setFocused(false);
const inputValidity = performValidation();
onBlur?.(event, String(value), inputValidity);
};
const onChangeHandler = (event, currentValue) => {
isDirty.current = true;
const limitedValue = blockMax ? limitValue(currentValue) : currentValue;
setValue(limitedValue);
onChange?.(event, limitedValue);
};
const onFocusHandler = (event) => {
setFocused(true);
setValidationState("standBy");
onFocus?.(event, String(value));
};
const isScrolledDown = React.useCallback(() => {
const el = inputRef.current;
return el == null || el.offsetHeight + el.scrollTop >= el.scrollHeight;
}, [inputRef]);
const scrollDown = React.useCallback(() => {
const el = inputRef.current;
if (el != null) {
el.scrollTop = el.scrollHeight - el.clientHeight;
}
}, [inputRef]);
const addScrollListener = React.useCallback(() => {
const scrollHandler = {
handleEvent: () => {
setAutoScrolling(isScrolledDown());
}
};
inputRef.current?.addEventListener("scroll", scrollHandler);
}, [inputRef, isScrolledDown]);
React.useEffect(() => {
if (autoScroll) {
addScrollListener();
}
}, [autoScroll, addScrollListener]);
React.useEffect(() => {
if (autoScrolling) {
scrollDown();
}
}, [valueProp, autoScrolling, scrollDown]);
React.useEffect(() => {
if (focused || !isDirty.current && isEmptyValue) {
return;
}
performValidation();
}, [focused, isEmptyValue, performValidation]);
const canShowError = ariaErrorMessage == null && (status !== void 0 && statusMessage !== void 0 || status === void 0 && validations.hasBuiltInValidations(
required,
"none",
minCharQuantity,
// If blockMax is true maxCharQuantity will never produce an error
// unless the value is controlled, so we can't prevent it to overflow maxCharQuantity
maxCharQuantity != null && (blockMax !== true || value != null) ? maxCharQuantity : null,
validation,
inputProps
));
const willShowError = canShowError && isStateInvalid;
const canShowInfo = !!infoMessage && !willShowError;
let errorMessageId;
if (isStateInvalid) {
errorMessageId = canShowError ? setId.setId(elementId, "error") : ariaErrorMessage;
}
return /* @__PURE__ */ jsxRuntime.jsxs(
FormElement.HvFormElement,
{
id,
name,
status: validationState,
disabled,
required,
readOnly,
className: cx(
classes.root,
{
[classes.resizable]: resizable,
[classes.disabled]: disabled,
[classes.invalid]: isStateInvalid
},
className
),
onBlur: onContainerBlurHandler,
children: [
/* @__PURE__ */ jsxRuntime.jsx(
LabelContainer.HvLabelContainer,
{
label,
description,
inputId: setId.setId(elementId, "input"),
labelId: setId.setId(elementId, "label"),
descriptionId: setId.setId(elementId, "description"),
classes: {
root: classes.labelContainer,
label: classes.label,
description: classes.description
},
children: hasCounter && /* @__PURE__ */ jsxRuntime.jsx(
CharCounter.HvCharCounter,
{
disableGutter: true,
id: setId.setId(elementId, "charCounter"),
className: classes.characterCounter,
separator: middleCountLabel,
currentCharQuantity: String(value).length,
maxCharQuantity,
...countCharProps
}
)
}
),
/* @__PURE__ */ jsxRuntime.jsx(
BaseInput.HvBaseInput,
{
classes: {
root: classes.baseInput,
input: classes.input,
inputResizable: classes.inputResizable
},
id: hasLabel ? setId.setId(elementId, "input") : setId.setId(id, "input"),
name,
value,
required,
readOnly,
disabled,
onChange: onChangeHandler,
autoFocus,
onFocus: onFocusHandler,
placeholder,
invalid: isStateInvalid,
resizable,
multiline: true,
rows,
inputProps: {
"aria-label": ariaLabel,
"aria-labelledby": ariaLabelledBy,
"aria-invalid": isStateInvalid ? true : void 0,
"aria-errormessage": errorMessageId,
"aria-describedby": ariaDescribedBy != null ? ariaDescribedBy : description && setId.setId(elementId, "description") || void 0,
"aria-controls": maxCharQuantity ? setId.setId(elementId, "charCounter") : void 0,
...inputProps
},
inputRef: forkedRef,
...others
}
),
canShowError && /* @__PURE__ */ jsxRuntime.jsx(
WarningText.HvWarningText,
{
id: setId.setId(elementId, "error"),
className: classes.error,
disableBorder: true,
children: validationMessage
}
),
canShowInfo && /* @__PURE__ */ jsxRuntime.jsx(InfoMessage.HvInfoMessage, { disableGutter: true, variant: "caption1", children: infoMessage })
]
}
);
});
exports.textAreaClasses = TextArea_styles.staticClasses;
exports.HvTextArea = HvTextArea;