TextArea.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports.default = void 0;
  7. var _vue = require("vue");
  8. var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
  9. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
  10. var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
  11. var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
  12. var _ClearableLabeledInput = _interopRequireDefault(require("./ClearableLabeledInput"));
  13. var _ResizableTextArea = _interopRequireDefault(require("./ResizableTextArea"));
  14. var _inputProps = require("./inputProps");
  15. var _Input = require("./Input");
  16. var _classNames2 = _interopRequireDefault(require("../_util/classNames"));
  17. var _FormItemContext = require("../form/FormItemContext");
  18. var _useConfigInject2 = _interopRequireDefault(require("../_util/hooks/useConfigInject"));
  19. var _omit = _interopRequireDefault(require("../_util/omit"));
  20. function fixEmojiLength(value, maxLength) {
  21. return (0, _toConsumableArray2.default)(value || '').slice(0, maxLength).join('');
  22. }
  23. function setTriggerValue(isCursorInEnd, preValue, triggerValue, maxLength) {
  24. var newTriggerValue = triggerValue;
  25. if (isCursorInEnd) {
  26. // 光标在尾部,直接截断
  27. newTriggerValue = fixEmojiLength(triggerValue, maxLength);
  28. } else if ((0, _toConsumableArray2.default)(preValue || '').length < triggerValue.length && (0, _toConsumableArray2.default)(triggerValue || '').length > maxLength) {
  29. // 光标在中间,如果最后的值超过最大值,则采用原先的值
  30. newTriggerValue = preValue;
  31. }
  32. return newTriggerValue;
  33. }
  34. var _default = (0, _vue.defineComponent)({
  35. compatConfig: {
  36. MODE: 3
  37. },
  38. name: 'ATextarea',
  39. inheritAttrs: false,
  40. props: (0, _inputProps.textAreaProps)(),
  41. setup: function setup(props, _ref) {
  42. var attrs = _ref.attrs,
  43. expose = _ref.expose,
  44. emit = _ref.emit;
  45. var formItemContext = (0, _FormItemContext.useInjectFormItemContext)();
  46. var stateValue = (0, _vue.ref)(props.value === undefined ? props.defaultValue : props.value);
  47. var resizableTextArea = (0, _vue.ref)();
  48. var mergedValue = (0, _vue.ref)('');
  49. var _useConfigInject = (0, _useConfigInject2.default)('input', props),
  50. prefixCls = _useConfigInject.prefixCls,
  51. size = _useConfigInject.size,
  52. direction = _useConfigInject.direction;
  53. var showCount = (0, _vue.computed)(function () {
  54. return props.showCount === '' || props.showCount || false;
  55. });
  56. // Max length value
  57. var hasMaxLength = (0, _vue.computed)(function () {
  58. return Number(props.maxlength) > 0;
  59. });
  60. var compositing = (0, _vue.ref)(false);
  61. var oldCompositionValueRef = (0, _vue.ref)();
  62. var oldSelectionStartRef = (0, _vue.ref)(0);
  63. var onInternalCompositionStart = function onInternalCompositionStart(e) {
  64. compositing.value = true;
  65. // 拼音输入前保存一份旧值
  66. oldCompositionValueRef.value = mergedValue.value;
  67. // 保存旧的光标位置
  68. oldSelectionStartRef.value = e.currentTarget.selectionStart;
  69. emit('compositionstart', e);
  70. };
  71. var onInternalCompositionEnd = function onInternalCompositionEnd(e) {
  72. compositing.value = false;
  73. var triggerValue = e.currentTarget.value;
  74. if (hasMaxLength.value) {
  75. var _oldCompositionValueR;
  76. var isCursorInEnd = oldSelectionStartRef.value >= props.maxlength + 1 || oldSelectionStartRef.value === ((_oldCompositionValueR = oldCompositionValueRef.value) === null || _oldCompositionValueR === void 0 ? void 0 : _oldCompositionValueR.length);
  77. triggerValue = setTriggerValue(isCursorInEnd, oldCompositionValueRef.value, triggerValue, props.maxlength);
  78. }
  79. // Patch composition onChange when value changed
  80. if (triggerValue !== mergedValue.value) {
  81. setValue(triggerValue);
  82. (0, _Input.resolveOnChange)(e.currentTarget, e, triggerChange, triggerValue);
  83. }
  84. emit('compositionend', e);
  85. };
  86. var instance = (0, _vue.getCurrentInstance)();
  87. (0, _vue.watch)(function () {
  88. return props.value;
  89. }, function () {
  90. if ('value' in instance.vnode.props || {}) {
  91. var _props$value;
  92. stateValue.value = (_props$value = props.value) !== null && _props$value !== void 0 ? _props$value : '';
  93. }
  94. });
  95. var focus = function focus(option) {
  96. var _resizableTextArea$va;
  97. (0, _Input.triggerFocus)((_resizableTextArea$va = resizableTextArea.value) === null || _resizableTextArea$va === void 0 ? void 0 : _resizableTextArea$va.textArea, option);
  98. };
  99. var blur = function blur() {
  100. var _resizableTextArea$va2, _resizableTextArea$va3;
  101. (_resizableTextArea$va2 = resizableTextArea.value) === null || _resizableTextArea$va2 === void 0 ? void 0 : (_resizableTextArea$va3 = _resizableTextArea$va2.textArea) === null || _resizableTextArea$va3 === void 0 ? void 0 : _resizableTextArea$va3.blur();
  102. };
  103. var setValue = function setValue(value, callback) {
  104. if (stateValue.value === value) {
  105. return;
  106. }
  107. if (props.value === undefined) {
  108. stateValue.value = value;
  109. } else {
  110. (0, _vue.nextTick)(function () {
  111. if (resizableTextArea.value.textArea.value !== mergedValue.value) {
  112. var _resizableTextArea$va4, _resizableTextArea$va5, _resizableTextArea$va6;
  113. (_resizableTextArea$va4 = resizableTextArea.value) === null || _resizableTextArea$va4 === void 0 ? void 0 : (_resizableTextArea$va5 = (_resizableTextArea$va6 = _resizableTextArea$va4.instance).update) === null || _resizableTextArea$va5 === void 0 ? void 0 : _resizableTextArea$va5.call(_resizableTextArea$va6);
  114. }
  115. });
  116. }
  117. (0, _vue.nextTick)(function () {
  118. callback && callback();
  119. });
  120. };
  121. var handleKeyDown = function handleKeyDown(e) {
  122. if (e.keyCode === 13) {
  123. emit('pressEnter', e);
  124. }
  125. emit('keydown', e);
  126. };
  127. var onBlur = function onBlur(e) {
  128. var onBlur = props.onBlur;
  129. onBlur === null || onBlur === void 0 ? void 0 : onBlur(e);
  130. formItemContext.onFieldBlur();
  131. };
  132. var triggerChange = function triggerChange(e) {
  133. emit('update:value', e.target.value);
  134. emit('change', e);
  135. emit('input', e);
  136. formItemContext.onFieldChange();
  137. };
  138. var handleReset = function handleReset(e) {
  139. (0, _Input.resolveOnChange)(resizableTextArea.value.textArea, e, triggerChange);
  140. setValue('', function () {
  141. focus();
  142. });
  143. };
  144. var handleChange = function handleChange(e) {
  145. var composing = e.target.composing;
  146. var triggerValue = e.target.value;
  147. compositing.value = !!(e.isComposing || composing);
  148. if (compositing.value && props.lazy || stateValue.value === triggerValue) return;
  149. if (hasMaxLength.value) {
  150. // 1. 复制粘贴超过maxlength的情况 2.未超过maxlength的情况
  151. var target = e.target;
  152. var isCursorInEnd = target.selectionStart >= props.maxlength + 1 || target.selectionStart === triggerValue.length || !target.selectionStart;
  153. triggerValue = setTriggerValue(isCursorInEnd, mergedValue.value, triggerValue, props.maxlength);
  154. }
  155. (0, _Input.resolveOnChange)(e.currentTarget, e, triggerChange, triggerValue);
  156. setValue(triggerValue);
  157. };
  158. var renderTextArea = function renderTextArea() {
  159. var _class, _props$valueModifiers, _resizeProps$id;
  160. var style = attrs.style,
  161. customClass = attrs.class;
  162. var _props$bordered = props.bordered,
  163. bordered = _props$bordered === void 0 ? true : _props$bordered;
  164. var resizeProps = (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, (0, _omit.default)(props, ['allowClear'])), attrs), {}, {
  165. style: showCount.value ? {} : style,
  166. class: (_class = {}, (0, _defineProperty2.default)(_class, "".concat(prefixCls.value, "-borderless"), !bordered), (0, _defineProperty2.default)(_class, "".concat(customClass), customClass && !showCount.value), (0, _defineProperty2.default)(_class, "".concat(prefixCls.value, "-sm"), size.value === 'small'), (0, _defineProperty2.default)(_class, "".concat(prefixCls.value, "-lg"), size.value === 'large'), _class),
  167. showCount: null,
  168. prefixCls: prefixCls.value,
  169. onInput: handleChange,
  170. onChange: handleChange,
  171. onBlur: onBlur,
  172. onKeydown: handleKeyDown,
  173. onCompositionstart: onInternalCompositionStart,
  174. onCompositionend: onInternalCompositionEnd
  175. });
  176. if ((_props$valueModifiers = props.valueModifiers) !== null && _props$valueModifiers !== void 0 && _props$valueModifiers.lazy) {
  177. delete resizeProps.onInput;
  178. }
  179. return (0, _vue.createVNode)(_ResizableTextArea.default, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, resizeProps), {}, {
  180. "id": (_resizeProps$id = resizeProps.id) !== null && _resizeProps$id !== void 0 ? _resizeProps$id : formItemContext.id.value,
  181. "ref": resizableTextArea,
  182. "maxlength": props.maxlength
  183. }), null);
  184. };
  185. expose({
  186. focus: focus,
  187. blur: blur,
  188. resizableTextArea: resizableTextArea
  189. });
  190. (0, _vue.watchEffect)(function () {
  191. var val = (0, _Input.fixControlledValue)(stateValue.value);
  192. if (!compositing.value && hasMaxLength.value && (props.value === null || props.value === undefined)) {
  193. // fix #27612 将value转为数组进行截取,解决 '😂'.length === 2 等emoji表情导致的截取乱码的问题
  194. val = fixEmojiLength(val, props.maxlength);
  195. }
  196. mergedValue.value = val;
  197. });
  198. return function () {
  199. var maxlength = props.maxlength,
  200. _props$bordered2 = props.bordered,
  201. bordered = _props$bordered2 === void 0 ? true : _props$bordered2,
  202. hidden = props.hidden;
  203. var style = attrs.style,
  204. customClass = attrs.class;
  205. var inputProps = (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, props), attrs), {}, {
  206. prefixCls: prefixCls.value,
  207. inputType: 'text',
  208. handleReset: handleReset,
  209. direction: direction.value,
  210. bordered: bordered,
  211. style: showCount.value ? undefined : style
  212. });
  213. var textareaNode = (0, _vue.createVNode)(_ClearableLabeledInput.default, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, inputProps), {}, {
  214. "value": mergedValue.value
  215. }), {
  216. element: renderTextArea
  217. });
  218. if (showCount.value) {
  219. var valueLength = (0, _toConsumableArray2.default)(mergedValue.value).length;
  220. var dataCount = '';
  221. if ((0, _typeof2.default)(showCount.value) === 'object') {
  222. dataCount = showCount.value.formatter({
  223. count: valueLength,
  224. maxlength: maxlength
  225. });
  226. } else {
  227. dataCount = "".concat(valueLength).concat(hasMaxLength.value ? " / ".concat(maxlength) : '');
  228. }
  229. var _textareaNode = function () {
  230. return textareaNode;
  231. }();
  232. textareaNode = (0, _vue.createVNode)("div", {
  233. "hidden": hidden,
  234. "class": (0, _classNames2.default)("".concat(prefixCls.value, "-textarea"), (0, _defineProperty2.default)({}, "".concat(prefixCls.value, "-textarea-rtl"), direction.value === 'rtl'), "".concat(prefixCls.value, "-textarea-show-count"), customClass),
  235. "style": style,
  236. "data-count": (0, _typeof2.default)(dataCount) !== 'object' ? dataCount : undefined
  237. }, [textareaNode]);
  238. }
  239. return textareaNode;
  240. };
  241. }
  242. });
  243. exports.default = _default;