ResizableTextArea.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import _mergeJSXProps from 'babel-helper-vue-jsx-merge-props';
  2. import _defineProperty from 'babel-runtime/helpers/defineProperty';
  3. import _extends from 'babel-runtime/helpers/extends';
  4. import ResizeObserver from '../vc-resize-observer';
  5. import omit from 'omit.js';
  6. import classNames from 'classnames';
  7. import calculateNodeHeight from './calculateNodeHeight';
  8. import raf from '../_util/raf';
  9. import warning from '../_util/warning';
  10. import BaseMixin from '../_util/BaseMixin';
  11. import inputProps from './inputProps';
  12. import PropTypes from '../_util/vue-types';
  13. import { getOptionProps, getListeners } from '../_util/props-util';
  14. var RESIZE_STATUS_NONE = 0;
  15. var RESIZE_STATUS_RESIZING = 1;
  16. var RESIZE_STATUS_RESIZED = 2;
  17. var TextAreaProps = _extends({}, inputProps, {
  18. autosize: PropTypes.oneOfType([Object, Boolean]),
  19. autoSize: PropTypes.oneOfType([Object, Boolean])
  20. });
  21. var ResizableTextArea = {
  22. name: 'ResizableTextArea',
  23. props: TextAreaProps,
  24. data: function data() {
  25. return {
  26. textareaStyles: {},
  27. resizeStatus: RESIZE_STATUS_NONE
  28. };
  29. },
  30. mixins: [BaseMixin],
  31. mounted: function mounted() {
  32. var _this = this;
  33. this.$nextTick(function () {
  34. _this.resizeTextarea();
  35. });
  36. },
  37. beforeDestroy: function beforeDestroy() {
  38. raf.cancel(this.nextFrameActionId);
  39. raf.cancel(this.resizeFrameId);
  40. },
  41. watch: {
  42. value: function value() {
  43. var _this2 = this;
  44. this.$nextTick(function () {
  45. _this2.resizeTextarea();
  46. });
  47. }
  48. },
  49. methods: {
  50. handleResize: function handleResize(size) {
  51. var resizeStatus = this.$data.resizeStatus;
  52. var autoSize = this.$props.autoSize;
  53. if (resizeStatus !== RESIZE_STATUS_NONE) {
  54. return;
  55. }
  56. this.$emit('resize', size);
  57. if (autoSize) {
  58. this.resizeOnNextFrame();
  59. }
  60. },
  61. resizeOnNextFrame: function resizeOnNextFrame() {
  62. raf.cancel(this.nextFrameActionId);
  63. this.nextFrameActionId = raf(this.resizeTextarea);
  64. },
  65. resizeTextarea: function resizeTextarea() {
  66. var _this3 = this;
  67. var autoSize = this.$props.autoSize || this.$props.autosize;
  68. if (!autoSize || !this.$refs.textArea) {
  69. return;
  70. }
  71. var minRows = autoSize.minRows,
  72. maxRows = autoSize.maxRows;
  73. var textareaStyles = calculateNodeHeight(this.$refs.textArea, false, minRows, maxRows);
  74. this.setState({ textareaStyles: textareaStyles, resizeStatus: RESIZE_STATUS_RESIZING }, function () {
  75. raf.cancel(_this3.resizeFrameId);
  76. _this3.resizeFrameId = raf(function () {
  77. _this3.setState({ resizeStatus: RESIZE_STATUS_RESIZED }, function () {
  78. _this3.resizeFrameId = raf(function () {
  79. _this3.setState({ resizeStatus: RESIZE_STATUS_NONE });
  80. _this3.fixFirefoxAutoScroll();
  81. });
  82. });
  83. });
  84. });
  85. },
  86. // https://github.com/ant-design/ant-design/issues/21870
  87. fixFirefoxAutoScroll: function fixFirefoxAutoScroll() {
  88. try {
  89. if (document.activeElement === this.$refs.textArea) {
  90. var currentStart = this.$refs.textArea.selectionStart;
  91. var currentEnd = this.$refs.textArea.selectionEnd;
  92. this.$refs.textArea.setSelectionRange(currentStart, currentEnd);
  93. }
  94. } catch (e) {
  95. // Fix error in Chrome:
  96. // Failed to read the 'selectionStart' property from 'HTMLInputElement'
  97. // http://stackoverflow.com/q/21177489/3040605
  98. }
  99. },
  100. renderTextArea: function renderTextArea() {
  101. var h = this.$createElement;
  102. var props = getOptionProps(this);
  103. var prefixCls = props.prefixCls,
  104. autoSize = props.autoSize,
  105. autosize = props.autosize,
  106. disabled = props.disabled;
  107. var _$data = this.$data,
  108. textareaStyles = _$data.textareaStyles,
  109. resizeStatus = _$data.resizeStatus;
  110. warning(autosize === undefined, 'Input.TextArea', 'autosize is deprecated, please use autoSize instead.');
  111. var otherProps = omit(props, ['prefixCls', 'autoSize', 'autosize', 'defaultValue', 'allowClear', 'type', 'lazy', 'value']);
  112. var cls = classNames(prefixCls, _defineProperty({}, prefixCls + '-disabled', disabled));
  113. var domProps = {};
  114. // Fix https://github.com/ant-design/ant-design/issues/6776
  115. // Make sure it could be reset when using form.getFieldDecorator
  116. if ('value' in props) {
  117. domProps.value = props.value || '';
  118. }
  119. var style = _extends({}, textareaStyles, resizeStatus === RESIZE_STATUS_RESIZING ? { overflowX: 'hidden', overflowY: 'hidden' } : null);
  120. var textareaProps = {
  121. attrs: otherProps,
  122. domProps: domProps,
  123. style: style,
  124. 'class': cls,
  125. on: omit(getListeners(this), 'pressEnter'),
  126. directives: [{
  127. name: 'ant-input'
  128. }]
  129. };
  130. return h(
  131. ResizeObserver,
  132. {
  133. on: {
  134. 'resize': this.handleResize
  135. },
  136. attrs: { disabled: !(autoSize || autosize) }
  137. },
  138. [h('textarea', _mergeJSXProps([textareaProps, { ref: 'textArea' }]))]
  139. );
  140. }
  141. },
  142. render: function render() {
  143. return this.renderTextArea();
  144. }
  145. };
  146. export default ResizableTextArea;