UNPKG

@mskcc/carbon-react

Version:

Carbon react components for the MSKCC DSM

287 lines (279 loc) 10.7 kB
/** * MSKCC 2021, 2024 */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js'); var PropTypes = require('prop-types'); var React = require('react'); var cx = require('classnames'); var deprecate = require('../../prop-types/deprecate.js'); var usePrefix = require('../../internal/usePrefix.js'); require('../FluidForm/FluidForm.js'); var FormContext = require('../FluidForm/FormContext.js'); var useAnnouncer = require('../../internal/useAnnouncer.js'); var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js'); var useMergedRefs = require('../../internal/useMergedRefs.js'); var setupGetInstanceId = require('../../tools/setupGetInstanceId.js'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes); var React__default = /*#__PURE__*/_interopDefaultLegacy(React); var cx__default = /*#__PURE__*/_interopDefaultLegacy(cx); var _span, _span2; const getInstanceId = setupGetInstanceId["default"](); const TextArea = /*#__PURE__*/React__default["default"].forwardRef((props, forwardRef) => { const { className, id, labelText, hideLabel, onChange = () => {}, onClick = () => {}, invalid = false, invalidText = '', helperText = '', light, placeholder = '', enableCounter = false, maxCount, warn = false, warnText = '', rows = 4, ...other } = props; const prefix = usePrefix.usePrefix(); const { isFluid } = React.useContext(FormContext.FormContext); const { defaultValue, value, disabled } = other; const [textCount, setTextCount] = React.useState(defaultValue?.toString()?.length || value?.toString()?.length || 0); const { current: textAreaInstanceId } = React.useRef(getInstanceId()); React.useEffect(() => { setTextCount(defaultValue?.toString()?.length || value?.toString()?.length || 0); }, [value, defaultValue]); const textareaProps = { id, onChange: evt => { if (!other.disabled && onChange) { // delay textCount assignation to give the textarea element value time to catch up if is a controlled input setTimeout(() => { setTextCount(evt.target?.value?.length); }, 0); onChange(evt); } }, onClick: evt => { if (!other.disabled && onClick) { onClick(evt); } } }; if (enableCounter) { textareaProps.maxLength = maxCount; } const ariaAnnouncement = useAnnouncer.useAnnouncer(textCount, maxCount); const labelClasses = cx__default["default"](`${prefix}--label`, { [`${prefix}--visually-hidden`]: hideLabel && !isFluid, [`${prefix}--label--disabled`]: disabled }); const label = labelText ? /*#__PURE__*/React__default["default"].createElement("label", { htmlFor: id, className: labelClasses }, labelText) : null; const counterClasses = cx__default["default"](`${prefix}--label`, { [`${prefix}--label--disabled`]: disabled }); const counter = enableCounter && maxCount ? /*#__PURE__*/React__default["default"].createElement("div", { className: counterClasses }, `${textCount}/${maxCount}`) : null; const helperTextClasses = cx__default["default"](`${prefix}--form__helper-text`, { [`${prefix}--form__helper-text--disabled`]: other.disabled }); const helperId = !helperText ? undefined : `text-area-helper-text-${textAreaInstanceId}`; const helper = helperText ? /*#__PURE__*/React__default["default"].createElement("div", { id: helperId, className: helperTextClasses }, helperText) : null; const errorId = id + '-error-msg'; const error = invalid ? /*#__PURE__*/ // <div role='alert' className={`${prefix}--form-requirement`} id={errorId}> // {invalidText} // {isFluid && ( // <WarningFilled className={`${prefix}--text-area__invalid-icon`} /> // )} // </div> React__default["default"].createElement("div", { role: "alert", className: `msk-validation-msg` }, _span || (_span = /*#__PURE__*/React__default["default"].createElement("span", { className: `msk-validation-msg--icon msk-icon` }, "error")), /*#__PURE__*/React__default["default"].createElement("div", { className: `${prefix}--form-requirement` }, invalidText)) : null; const warning = warn ? /*#__PURE__*/ // <div role="alert" className={`${prefix}--form-requirement`}> // {warnText} // {isFluid && ( // <WarningAltFilled // className={`${prefix}--text-area__invalid-icon ${prefix}--text-area__invalid-icon--warning`} // /> // )} // </div> React__default["default"].createElement("div", { role: "alert", className: `msk-validation-msg` }, _span2 || (_span2 = /*#__PURE__*/React__default["default"].createElement("span", { className: `msk-validation-msg--icon msk-validation-msg--icon--warning msk-icon` }, "warning")), /*#__PURE__*/React__default["default"].createElement("div", { className: `${prefix}--form-requirement` }, warnText)) : null; const textareaClasses = cx__default["default"](`${prefix}--text-area`, { [`${prefix}--text-area--light`]: light, [`${prefix}--text-area--invalid`]: invalid, [`${prefix}--text-area--warn`]: warn }); const textareaRef = React.useRef(null); const ref = useMergedRefs.useMergedRefs([forwardRef, textareaRef]); useIsomorphicEffect["default"](() => { if (other.cols && textareaRef.current) { textareaRef.current.style.width = ''; textareaRef.current.style.resize = 'none'; } else if (textareaRef.current) { textareaRef.current.style.width = `100%`; } }, [other.cols]); let ariaDescribedBy; if (invalid) { ariaDescribedBy = errorId; } else if (!invalid && !warn && !isFluid && helperText) { ariaDescribedBy = helperId; } const input = /*#__PURE__*/React__default["default"].createElement("textarea", _rollupPluginBabelHelpers["extends"]({ rows: rows }, other, textareaProps, { placeholder: placeholder, className: textareaClasses, "aria-invalid": invalid, "aria-describedby": ariaDescribedBy, disabled: other.disabled, readOnly: other.readOnly, ref: ref })); return /*#__PURE__*/React__default["default"].createElement("div", { className: cx__default["default"](`${prefix}--form-item`, className) }, /*#__PURE__*/React__default["default"].createElement("div", { className: `${prefix}--text-area__label-wrapper` }, label, counter), /*#__PURE__*/React__default["default"].createElement("div", { className: cx__default["default"](`${prefix}--text-area__wrapper`, { [`${prefix}--text-area__wrapper--readonly`]: other.readOnly, [`${prefix}--text-area__wrapper--warn`]: warn }), "data-invalid": invalid || null }, input, /*#__PURE__*/React__default["default"].createElement("span", { className: `${prefix}--text-area__counter-alert`, role: "alert" }, ariaAnnouncement), isFluid && /*#__PURE__*/React__default["default"].createElement("hr", { className: `${prefix}--text-area__divider` }), isFluid && invalid ? error : null, isFluid && warn && !invalid ? warning : null), !invalid && !warn && !isFluid ? helper : null, invalid && !isFluid ? error : null, warn && !invalid && !isFluid ? warning : null); }); TextArea.displayName = 'TextArea'; TextArea.propTypes = { /** * Provide a custom className that is applied directly to the underlying * `<textarea>` node */ className: PropTypes__default["default"].string, /** * Specify the `cols` attribute for the underlying `<textarea>` node */ cols: PropTypes__default["default"].number, /** * Optionally provide the default value of the `<textarea>` */ defaultValue: PropTypes__default["default"].oneOfType([PropTypes__default["default"].string, PropTypes__default["default"].number]), /** * Specify whether the control is disabled */ disabled: PropTypes__default["default"].bool, /** * Specify whether to display the character counter */ enableCounter: PropTypes__default["default"].bool, /** * Provide text that is used alongside the control label for additional help */ helperText: PropTypes__default["default"].node, /** * Specify whether you want the underlying label to be visually hidden */ hideLabel: PropTypes__default["default"].bool, /** * Provide a unique identifier for the control */ id: PropTypes__default["default"].string, /** * Specify whether the control is currently invalid */ invalid: PropTypes__default["default"].bool, /** * Provide the text that is displayed when the control is in an invalid state */ invalidText: PropTypes__default["default"].node, /** * Provide the text that will be read by a screen reader when visiting this * control */ labelText: PropTypes__default["default"].node.isRequired, /** * `true` to use the light version. For use on $ui-01 backgrounds only. * Don't use this to make tile background color same as container background color. */ light: deprecate["default"](PropTypes__default["default"].bool, 'The `light` prop for `TextArea` has ' + 'been deprecated in favor of the new `Layer` component. It will be removed in the next major release.'), /** * Max character count allowed for the textarea. This is needed in order for enableCounter to display */ maxCount: PropTypes__default["default"].number, /** * Optionally provide an `onChange` handler that is called whenever `<textarea>` * is updated */ onChange: PropTypes__default["default"].func, /** * Optionally provide an `onClick` handler that is called whenever the * `<textarea>` is clicked */ onClick: PropTypes__default["default"].func, /** * Specify the placeholder attribute for the `<textarea>` */ placeholder: PropTypes__default["default"].string, /** * Whether the textarea should be read-only */ readOnly: PropTypes__default["default"].bool, /** * Specify the rows attribute for the `<textarea>` */ rows: PropTypes__default["default"].number, /** * Provide the current value of the `<textarea>` */ value: PropTypes__default["default"].oneOfType([PropTypes__default["default"].string, PropTypes__default["default"].number]), /** * Specify whether the control is currently in warning state */ warn: PropTypes__default["default"].bool, /** * Provide the text that is displayed when the control is in warning state */ warnText: PropTypes__default["default"].node }; exports["default"] = TextArea;