1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', { value: true });
|
4 |
|
5 | var _extends = require('@babel/runtime/helpers/extends');
|
6 | var _objectWithoutPropertiesLoose = require('@babel/runtime/helpers/objectWithoutPropertiesLoose');
|
7 | var React = require('react');
|
8 | var useLatest = require('use-latest');
|
9 | var useComposedRef = require('use-composed-ref');
|
10 |
|
11 | function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
12 |
|
13 | var useLatest__default = _interopDefault(useLatest);
|
14 | var useComposedRef__default = _interopDefault(useComposedRef);
|
15 |
|
16 | var HIDDEN_TEXTAREA_STYLE = {
|
17 | 'min-height': '0',
|
18 | 'max-height': 'none',
|
19 | height: '0',
|
20 | visibility: 'hidden',
|
21 | overflow: 'hidden',
|
22 | position: 'absolute',
|
23 | 'z-index': '-1000',
|
24 | top: '0',
|
25 | right: '0'
|
26 | };
|
27 |
|
28 | var forceHiddenStyles = function forceHiddenStyles(node) {
|
29 | Object.keys(HIDDEN_TEXTAREA_STYLE).forEach(function (key) {
|
30 | node.style.setProperty(key, HIDDEN_TEXTAREA_STYLE[key], 'important');
|
31 | });
|
32 | };
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | var hiddenTextarea = null;
|
38 |
|
39 | var getHeight = function getHeight(node, sizingData) {
|
40 | var height = node.scrollHeight;
|
41 |
|
42 | if (sizingData.sizingStyle.boxSizing === 'border-box') {
|
43 |
|
44 | return height + sizingData.borderSize;
|
45 | }
|
46 |
|
47 |
|
48 | return height - sizingData.paddingSize;
|
49 | };
|
50 |
|
51 | function calculateNodeHeight(sizingData, value, minRows, maxRows) {
|
52 | if (minRows === void 0) {
|
53 | minRows = 1;
|
54 | }
|
55 |
|
56 | if (maxRows === void 0) {
|
57 | maxRows = Infinity;
|
58 | }
|
59 |
|
60 | if (!hiddenTextarea) {
|
61 | hiddenTextarea = document.createElement('textarea');
|
62 | hiddenTextarea.setAttribute('tabindex', '-1');
|
63 | hiddenTextarea.setAttribute('aria-hidden', 'true');
|
64 | forceHiddenStyles(hiddenTextarea);
|
65 | }
|
66 |
|
67 | if (hiddenTextarea.parentNode === null) {
|
68 | document.body.appendChild(hiddenTextarea);
|
69 | }
|
70 |
|
71 | var paddingSize = sizingData.paddingSize,
|
72 | borderSize = sizingData.borderSize,
|
73 | sizingStyle = sizingData.sizingStyle;
|
74 | var boxSizing = sizingStyle.boxSizing;
|
75 | Object.keys(sizingStyle).forEach(function (_key) {
|
76 | var key = _key;
|
77 | hiddenTextarea.style[key] = sizingStyle[key];
|
78 | });
|
79 | forceHiddenStyles(hiddenTextarea);
|
80 | hiddenTextarea.value = value;
|
81 | var height = getHeight(hiddenTextarea, sizingData);
|
82 |
|
83 | hiddenTextarea.value = 'x';
|
84 | var rowHeight = hiddenTextarea.scrollHeight - paddingSize;
|
85 | var minHeight = rowHeight * minRows;
|
86 |
|
87 | if (boxSizing === 'border-box') {
|
88 | minHeight = minHeight + paddingSize + borderSize;
|
89 | }
|
90 |
|
91 | height = Math.max(minHeight, height);
|
92 | var maxHeight = rowHeight * maxRows;
|
93 |
|
94 | if (boxSizing === 'border-box') {
|
95 | maxHeight = maxHeight + paddingSize + borderSize;
|
96 | }
|
97 |
|
98 | height = Math.min(maxHeight, height);
|
99 | return [height, rowHeight];
|
100 | }
|
101 |
|
102 | var noop = function noop() {};
|
103 | var pick = function pick(props, obj) {
|
104 | return props.reduce(function (acc, prop) {
|
105 | acc[prop] = obj[prop];
|
106 | return acc;
|
107 | }, {});
|
108 | };
|
109 |
|
110 | var SIZING_STYLE = ['borderBottomWidth', 'borderLeftWidth', 'borderRightWidth', 'borderTopWidth', 'boxSizing', 'fontFamily', 'fontSize', 'fontStyle', 'fontWeight', 'letterSpacing', 'lineHeight', 'paddingBottom', 'paddingLeft', 'paddingRight', 'paddingTop',
|
111 | 'tabSize', 'textIndent',
|
112 | 'textRendering', 'textTransform', 'width', 'wordBreak'];
|
113 | var isIE = !!document.documentElement.currentStyle ;
|
114 |
|
115 | var getSizingData = function getSizingData(node) {
|
116 | var style = window.getComputedStyle(node);
|
117 |
|
118 | if (style === null) {
|
119 | return null;
|
120 | }
|
121 |
|
122 | var sizingStyle = pick(SIZING_STYLE, style);
|
123 | var boxSizing = sizingStyle.boxSizing;
|
124 |
|
125 | if (boxSizing === '') {
|
126 | return null;
|
127 | }
|
128 |
|
129 |
|
130 |
|
131 | if (isIE && boxSizing === 'border-box') {
|
132 | sizingStyle.width = parseFloat(sizingStyle.width) + parseFloat(sizingStyle.borderRightWidth) + parseFloat(sizingStyle.borderLeftWidth) + parseFloat(sizingStyle.paddingRight) + parseFloat(sizingStyle.paddingLeft) + 'px';
|
133 | }
|
134 |
|
135 | var paddingSize = parseFloat(sizingStyle.paddingBottom) + parseFloat(sizingStyle.paddingTop);
|
136 | var borderSize = parseFloat(sizingStyle.borderBottomWidth) + parseFloat(sizingStyle.borderTopWidth);
|
137 | return {
|
138 | sizingStyle: sizingStyle,
|
139 | paddingSize: paddingSize,
|
140 | borderSize: borderSize
|
141 | };
|
142 | };
|
143 |
|
144 | var useWindowResizeListener = function useWindowResizeListener(listener) {
|
145 | var latestListener = useLatest__default['default'](listener);
|
146 | React.useLayoutEffect(function () {
|
147 | var handler = function handler(event) {
|
148 | latestListener.current(event);
|
149 | };
|
150 |
|
151 | window.addEventListener('resize', handler);
|
152 | return function () {
|
153 | window.removeEventListener('resize', handler);
|
154 | };
|
155 | }, []);
|
156 | };
|
157 |
|
158 | var TextareaAutosize = function TextareaAutosize(_ref, userRef) {
|
159 | var cacheMeasurements = _ref.cacheMeasurements,
|
160 | maxRows = _ref.maxRows,
|
161 | minRows = _ref.minRows,
|
162 | _ref$onChange = _ref.onChange,
|
163 | onChange = _ref$onChange === void 0 ? noop : _ref$onChange,
|
164 | _ref$onHeightChange = _ref.onHeightChange,
|
165 | onHeightChange = _ref$onHeightChange === void 0 ? noop : _ref$onHeightChange,
|
166 | props = _objectWithoutPropertiesLoose(_ref, ["cacheMeasurements", "maxRows", "minRows", "onChange", "onHeightChange"]);
|
167 |
|
168 | if (process.env.NODE_ENV !== 'production' && props.style) {
|
169 | if ('maxHeight' in props.style) {
|
170 | throw new Error('Using `style.maxHeight` for <TextareaAutosize/> is not supported. Please use `maxRows`.');
|
171 | }
|
172 |
|
173 | if ('minHeight' in props.style) {
|
174 | throw new Error('Using `style.minHeight` for <TextareaAutosize/> is not supported. Please use `minRows`.');
|
175 | }
|
176 | }
|
177 |
|
178 | var isControlled = props.value !== undefined;
|
179 | var libRef = React.useRef(null);
|
180 | var ref = useComposedRef__default['default'](libRef, userRef);
|
181 | var heightRef = React.useRef(0);
|
182 | var measurementsCacheRef = React.useRef();
|
183 |
|
184 | var resizeTextarea = function resizeTextarea() {
|
185 | var node = libRef.current;
|
186 | var nodeSizingData = cacheMeasurements && measurementsCacheRef.current ? measurementsCacheRef.current : getSizingData(node);
|
187 |
|
188 | if (!nodeSizingData) {
|
189 | return;
|
190 | }
|
191 |
|
192 | measurementsCacheRef.current = nodeSizingData;
|
193 |
|
194 | var _calculateNodeHeight = calculateNodeHeight(nodeSizingData, node.value || node.placeholder || 'x', minRows, maxRows),
|
195 | height = _calculateNodeHeight[0],
|
196 | rowHeight = _calculateNodeHeight[1];
|
197 |
|
198 | if (heightRef.current !== height) {
|
199 | heightRef.current = height;
|
200 | node.style.setProperty('height', height + "px", 'important');
|
201 | onHeightChange(height, {
|
202 | rowHeight: rowHeight
|
203 | });
|
204 | }
|
205 | };
|
206 |
|
207 | var handleChange = function handleChange(event) {
|
208 | if (!isControlled) {
|
209 | resizeTextarea();
|
210 | }
|
211 |
|
212 | onChange(event);
|
213 | };
|
214 |
|
215 | {
|
216 | React.useLayoutEffect(resizeTextarea);
|
217 | useWindowResizeListener(resizeTextarea);
|
218 | }
|
219 |
|
220 | return React.createElement("textarea", _extends({}, props, {
|
221 | onChange: handleChange,
|
222 | ref: ref
|
223 | }));
|
224 | };
|
225 |
|
226 | var index = React.forwardRef(TextareaAutosize);
|
227 |
|
228 | exports.default = index;
|