TextArea.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
  3. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  4. import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
  5. import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
  6. import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
  7. var _excluded = ["defaultValue", "value", "onFocus", "onBlur", "onChange", "allowClear", "maxLength", "onCompositionStart", "onCompositionEnd", "suffix", "prefixCls", "showCount", "count", "className", "style", "disabled", "hidden", "classNames", "styles", "onResize", "onClear", "onPressEnter", "readOnly", "autoSize", "onKeyDown"];
  8. import clsx from 'classnames';
  9. import { BaseInput } from 'rc-input';
  10. import useCount from "rc-input/es/hooks/useCount";
  11. import { resolveOnChange } from "rc-input/es/utils/commonUtils";
  12. import useMergedState from "rc-util/es/hooks/useMergedState";
  13. import React, { useEffect, useImperativeHandle, useRef } from 'react';
  14. import ResizableTextArea from "./ResizableTextArea";
  15. var TextArea = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
  16. var _countConfig$max;
  17. var defaultValue = _ref.defaultValue,
  18. customValue = _ref.value,
  19. onFocus = _ref.onFocus,
  20. onBlur = _ref.onBlur,
  21. onChange = _ref.onChange,
  22. allowClear = _ref.allowClear,
  23. maxLength = _ref.maxLength,
  24. onCompositionStart = _ref.onCompositionStart,
  25. onCompositionEnd = _ref.onCompositionEnd,
  26. suffix = _ref.suffix,
  27. _ref$prefixCls = _ref.prefixCls,
  28. prefixCls = _ref$prefixCls === void 0 ? 'rc-textarea' : _ref$prefixCls,
  29. showCount = _ref.showCount,
  30. count = _ref.count,
  31. className = _ref.className,
  32. style = _ref.style,
  33. disabled = _ref.disabled,
  34. hidden = _ref.hidden,
  35. classNames = _ref.classNames,
  36. styles = _ref.styles,
  37. onResize = _ref.onResize,
  38. onClear = _ref.onClear,
  39. onPressEnter = _ref.onPressEnter,
  40. readOnly = _ref.readOnly,
  41. autoSize = _ref.autoSize,
  42. onKeyDown = _ref.onKeyDown,
  43. rest = _objectWithoutProperties(_ref, _excluded);
  44. var _useMergedState = useMergedState(defaultValue, {
  45. value: customValue,
  46. defaultValue: defaultValue
  47. }),
  48. _useMergedState2 = _slicedToArray(_useMergedState, 2),
  49. value = _useMergedState2[0],
  50. setValue = _useMergedState2[1];
  51. var formatValue = value === undefined || value === null ? '' : String(value);
  52. var _React$useState = React.useState(false),
  53. _React$useState2 = _slicedToArray(_React$useState, 2),
  54. focused = _React$useState2[0],
  55. setFocused = _React$useState2[1];
  56. var compositionRef = React.useRef(false);
  57. var _React$useState3 = React.useState(null),
  58. _React$useState4 = _slicedToArray(_React$useState3, 2),
  59. textareaResized = _React$useState4[0],
  60. setTextareaResized = _React$useState4[1];
  61. // =============================== Ref ================================
  62. var holderRef = useRef(null);
  63. var resizableTextAreaRef = useRef(null);
  64. var getTextArea = function getTextArea() {
  65. var _resizableTextAreaRef;
  66. return (_resizableTextAreaRef = resizableTextAreaRef.current) === null || _resizableTextAreaRef === void 0 ? void 0 : _resizableTextAreaRef.textArea;
  67. };
  68. var focus = function focus() {
  69. getTextArea().focus();
  70. };
  71. useImperativeHandle(ref, function () {
  72. var _holderRef$current;
  73. return {
  74. resizableTextArea: resizableTextAreaRef.current,
  75. focus: focus,
  76. blur: function blur() {
  77. getTextArea().blur();
  78. },
  79. nativeElement: ((_holderRef$current = holderRef.current) === null || _holderRef$current === void 0 ? void 0 : _holderRef$current.nativeElement) || getTextArea()
  80. };
  81. });
  82. useEffect(function () {
  83. setFocused(function (prev) {
  84. return !disabled && prev;
  85. });
  86. }, [disabled]);
  87. // =========================== Select Range ===========================
  88. var _React$useState5 = React.useState(null),
  89. _React$useState6 = _slicedToArray(_React$useState5, 2),
  90. selection = _React$useState6[0],
  91. setSelection = _React$useState6[1];
  92. React.useEffect(function () {
  93. if (selection) {
  94. var _getTextArea;
  95. (_getTextArea = getTextArea()).setSelectionRange.apply(_getTextArea, _toConsumableArray(selection));
  96. }
  97. }, [selection]);
  98. // ============================== Count ===============================
  99. var countConfig = useCount(count, showCount);
  100. var mergedMax = (_countConfig$max = countConfig.max) !== null && _countConfig$max !== void 0 ? _countConfig$max : maxLength;
  101. // Max length value
  102. var hasMaxLength = Number(mergedMax) > 0;
  103. var valueLength = countConfig.strategy(formatValue);
  104. var isOutOfRange = !!mergedMax && valueLength > mergedMax;
  105. // ============================== Change ==============================
  106. var triggerChange = function triggerChange(e, currentValue) {
  107. var cutValue = currentValue;
  108. if (!compositionRef.current && countConfig.exceedFormatter && countConfig.max && countConfig.strategy(currentValue) > countConfig.max) {
  109. cutValue = countConfig.exceedFormatter(currentValue, {
  110. max: countConfig.max
  111. });
  112. if (currentValue !== cutValue) {
  113. setSelection([getTextArea().selectionStart || 0, getTextArea().selectionEnd || 0]);
  114. }
  115. }
  116. setValue(cutValue);
  117. resolveOnChange(e.currentTarget, e, onChange, cutValue);
  118. };
  119. // =========================== Value Update ===========================
  120. var onInternalCompositionStart = function onInternalCompositionStart(e) {
  121. compositionRef.current = true;
  122. onCompositionStart === null || onCompositionStart === void 0 || onCompositionStart(e);
  123. };
  124. var onInternalCompositionEnd = function onInternalCompositionEnd(e) {
  125. compositionRef.current = false;
  126. triggerChange(e, e.currentTarget.value);
  127. onCompositionEnd === null || onCompositionEnd === void 0 || onCompositionEnd(e);
  128. };
  129. var onInternalChange = function onInternalChange(e) {
  130. triggerChange(e, e.target.value);
  131. };
  132. var handleKeyDown = function handleKeyDown(e) {
  133. if (e.key === 'Enter' && onPressEnter) {
  134. onPressEnter(e);
  135. }
  136. onKeyDown === null || onKeyDown === void 0 || onKeyDown(e);
  137. };
  138. var handleFocus = function handleFocus(e) {
  139. setFocused(true);
  140. onFocus === null || onFocus === void 0 || onFocus(e);
  141. };
  142. var handleBlur = function handleBlur(e) {
  143. setFocused(false);
  144. onBlur === null || onBlur === void 0 || onBlur(e);
  145. };
  146. // ============================== Reset ===============================
  147. var handleReset = function handleReset(e) {
  148. setValue('');
  149. focus();
  150. resolveOnChange(getTextArea(), e, onChange);
  151. };
  152. var suffixNode = suffix;
  153. var dataCount;
  154. if (countConfig.show) {
  155. if (countConfig.showFormatter) {
  156. dataCount = countConfig.showFormatter({
  157. value: formatValue,
  158. count: valueLength,
  159. maxLength: mergedMax
  160. });
  161. } else {
  162. dataCount = "".concat(valueLength).concat(hasMaxLength ? " / ".concat(mergedMax) : '');
  163. }
  164. suffixNode = /*#__PURE__*/React.createElement(React.Fragment, null, suffixNode, /*#__PURE__*/React.createElement("span", {
  165. className: clsx("".concat(prefixCls, "-data-count"), classNames === null || classNames === void 0 ? void 0 : classNames.count),
  166. style: styles === null || styles === void 0 ? void 0 : styles.count
  167. }, dataCount));
  168. }
  169. var handleResize = function handleResize(size) {
  170. var _getTextArea2;
  171. onResize === null || onResize === void 0 || onResize(size);
  172. if ((_getTextArea2 = getTextArea()) !== null && _getTextArea2 !== void 0 && _getTextArea2.style.height) {
  173. setTextareaResized(true);
  174. }
  175. };
  176. var isPureTextArea = !autoSize && !showCount && !allowClear;
  177. return /*#__PURE__*/React.createElement(BaseInput, {
  178. ref: holderRef,
  179. value: formatValue,
  180. allowClear: allowClear,
  181. handleReset: handleReset,
  182. suffix: suffixNode,
  183. prefixCls: prefixCls,
  184. classNames: _objectSpread(_objectSpread({}, classNames), {}, {
  185. affixWrapper: clsx(classNames === null || classNames === void 0 ? void 0 : classNames.affixWrapper, _defineProperty(_defineProperty({}, "".concat(prefixCls, "-show-count"), showCount), "".concat(prefixCls, "-textarea-allow-clear"), allowClear))
  186. }),
  187. disabled: disabled,
  188. focused: focused,
  189. className: clsx(className, isOutOfRange && "".concat(prefixCls, "-out-of-range")),
  190. style: _objectSpread(_objectSpread({}, style), textareaResized && !isPureTextArea ? {
  191. height: 'auto'
  192. } : {}),
  193. dataAttrs: {
  194. affixWrapper: {
  195. 'data-count': typeof dataCount === 'string' ? dataCount : undefined
  196. }
  197. },
  198. hidden: hidden,
  199. readOnly: readOnly,
  200. onClear: onClear
  201. }, /*#__PURE__*/React.createElement(ResizableTextArea, _extends({}, rest, {
  202. autoSize: autoSize,
  203. maxLength: maxLength,
  204. onKeyDown: handleKeyDown,
  205. onChange: onInternalChange,
  206. onFocus: handleFocus,
  207. onBlur: handleBlur,
  208. onCompositionStart: onInternalCompositionStart,
  209. onCompositionEnd: onInternalCompositionEnd,
  210. className: clsx(classNames === null || classNames === void 0 ? void 0 : classNames.textarea),
  211. style: _objectSpread(_objectSpread({}, styles === null || styles === void 0 ? void 0 : styles.textarea), {}, {
  212. resize: style === null || style === void 0 ? void 0 : style.resize
  213. }),
  214. disabled: disabled,
  215. prefixCls: prefixCls,
  216. onResize: handleResize,
  217. ref: resizableTextAreaRef,
  218. readOnly: readOnly
  219. })));
  220. });
  221. export default TextArea;