react-textarea-autosize
Advanced tools
Comparing version 4.3.2 to 5.0.0
@@ -10,15 +10,5 @@ (function (global, factory) { | ||
/** | ||
* calculateNodeHeight(uiTextNode, useCache = false) | ||
*/ | ||
var browser = typeof window !== 'undefined' && typeof document !== 'undefined'; | ||
var isIE = browser ? !!document.documentElement.currentStyle : false; | ||
var boxSizingProp = function () { | ||
if (!browser) { | ||
return 'box-sizing'; | ||
} | ||
var documentStyle = window.getComputedStyle(document.documentElement); | ||
// TODO: remove prefixed - they are probably obsolete, were introduced in by df79cf502630744d40233b64cad01770e5584610 in 2014 | ||
return documentStyle.getPropertyValue('box-sizing') ? 'box-sizing' : documentStyle.getPropertyValue('-moz-box-sizing') ? '-moz-box-sizing' : documentStyle.getPropertyValue('-webkit-box-sizing') ? '-webkit-box-sizing' : 'box-sizing'; | ||
}(); | ||
var hiddenTextarea = browser && document.createElement('textarea'); | ||
@@ -37,17 +27,14 @@ var HIDDEN_TEXTAREA_STYLE = { | ||
var SIZING_STYLE = ['letter-spacing', 'line-height', 'font-family', 'font-weight', 'font-size', 'text-rendering', 'text-transform', 'width', 'text-indent', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width', boxSizingProp]; | ||
var SIZING_STYLE = ['letter-spacing', 'line-height', 'font-family', 'font-weight', 'font-size', 'text-rendering', 'text-transform', 'width', 'text-indent', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width', 'box-sizing']; | ||
var computedStyleCache = {}; | ||
var hiddenTextarea = void 0; | ||
function calculateNodeHeight(uiTextNode) { | ||
var useCache = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
var minRows = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; | ||
var maxRows = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; | ||
function calculateNodeHeight(uiTextNode, uid) { | ||
var useCache = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; | ||
var minRows = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; | ||
var maxRows = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; | ||
if (!hiddenTextarea) { | ||
hiddenTextarea = document.createElement('textarea'); | ||
if (hiddenTextarea.parentNode === null) { | ||
document.body.appendChild(hiddenTextarea); | ||
} else if (hiddenTextarea.parentNode === null) { | ||
document.body.appendChild(hiddenTextarea); | ||
} | ||
@@ -69,6 +56,6 @@ | ||
Object.keys(sizingStyle).map(function (key) { | ||
Object.keys(sizingStyle).forEach(function (key) { | ||
hiddenTextarea.style[key] = sizingStyle[key]; | ||
}); | ||
Object.keys(HIDDEN_TEXTAREA_STYLE).map(function (key) { | ||
Object.keys(HIDDEN_TEXTAREA_STYLE).forEach(function (key) { | ||
hiddenTextarea.style.setProperty(key, HIDDEN_TEXTAREA_STYLE[key], 'important'); | ||
@@ -90,6 +77,7 @@ }); | ||
// measure height of a textarea with a single row | ||
hiddenTextarea.value = 'x'; | ||
var singleRowHeight = hiddenTextarea.scrollHeight - paddingSize; | ||
if (minRows !== null || maxRows !== null) { | ||
// measure height of a textarea with a single row | ||
hiddenTextarea.value = 'x'; | ||
var singleRowHeight = hiddenTextarea.scrollHeight - paddingSize; | ||
if (minRows !== null) { | ||
@@ -110,13 +98,13 @@ minHeight = singleRowHeight * minRows; | ||
} | ||
return { height: height, minHeight: minHeight, maxHeight: maxHeight }; | ||
var rowCount = Math.floor(height / singleRowHeight); | ||
return { height: height, minHeight: minHeight, maxHeight: maxHeight, rowCount: rowCount }; | ||
} | ||
function calculateNodeStyling(node) { | ||
var useCache = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
function calculateNodeStyling(node, uid) { | ||
var useCache = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; | ||
// TODO: generate id in constructor + clear cache in componentWillUnmount | ||
var nodeRef = node.getAttribute('id') || node.getAttribute('data-reactid') || node.getAttribute('name'); | ||
if (useCache && computedStyleCache[nodeRef]) { | ||
return computedStyleCache[nodeRef]; | ||
if (useCache && computedStyleCache[uid]) { | ||
return computedStyleCache[uid]; | ||
} | ||
@@ -131,3 +119,3 @@ | ||
var boxSizing = sizingStyle[boxSizingProp]; | ||
var boxSizing = sizingStyle['box-sizing']; | ||
@@ -151,4 +139,4 @@ // IE (Edge has already correct behaviour) returns content width as computed width | ||
if (useCache && nodeRef) { | ||
computedStyleCache[nodeRef] = nodeInfo; | ||
if (useCache) { | ||
computedStyleCache[uid] = nodeInfo; | ||
} | ||
@@ -159,18 +147,16 @@ | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
return typeof obj; | ||
} : function (obj) { | ||
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; | ||
var purgeCache = function purgeCache(uid) { | ||
return delete computedStyleCache[uid]; | ||
}; | ||
function autoInc() { | ||
var seed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; | ||
return function () { | ||
return ++seed; | ||
}; | ||
} | ||
var uid = autoInc(); | ||
var classCallCheck = function (instance, Constructor) { | ||
@@ -182,19 +168,3 @@ if (!(instance instanceof Constructor)) { | ||
var createClass = function () { | ||
function defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
return function (Constructor, protoProps, staticProps) { | ||
if (protoProps) defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
}; | ||
}(); | ||
@@ -221,3 +191,3 @@ | ||
var get$1 = function get$1(object, property, receiver) { | ||
var get = function get(object, property, receiver) { | ||
if (object === null) object = Function.prototype; | ||
@@ -232,3 +202,3 @@ var desc = Object.getOwnPropertyDescriptor(object, property); | ||
} else { | ||
return get$1(parent, property, receiver); | ||
return get(parent, property, receiver); | ||
} | ||
@@ -294,3 +264,3 @@ } else if ("value" in desc) { | ||
var set$1 = function set$1(object, property, value, receiver) { | ||
var set = function set(object, property, value, receiver) { | ||
var desc = Object.getOwnPropertyDescriptor(object, property); | ||
@@ -302,3 +272,3 @@ | ||
if (parent !== null) { | ||
set$1(parent, property, value, receiver); | ||
set(parent, property, value, receiver); | ||
} | ||
@@ -324,2 +294,6 @@ } else if ("value" in desc && desc.writable) { | ||
var _ref = window.requestAnimationFrame ? [window.requestAnimationFrame, window.cancelAnimationFrame] : [setTimeout, clearTimeout]; | ||
var onNextFrame = _ref[0]; | ||
var clearNextFrameAction = _ref[1]; | ||
var TextareaAutosize = function (_React$Component) { | ||
@@ -335,3 +309,6 @@ inherits(TextareaAutosize, _React$Component); | ||
_this._rootDOMNode = node; | ||
if (_this.props.inputRef) _this.props.inputRef(node); | ||
if (_this.props.inputRef) { | ||
_this.props.inputRef(node); | ||
} | ||
}; | ||
@@ -343,23 +320,18 @@ | ||
} | ||
var _this$props = _this.props, | ||
valueLink = _this$props.valueLink, | ||
onChange = _this$props.onChange; | ||
if (valueLink) { | ||
valueLink.requestChange(event.target.value); | ||
} else { | ||
onChange(event); | ||
} | ||
_this.props.onChange(event); | ||
}; | ||
_this._resizeComponent = function () { | ||
if (!_this._rootDOMNode) { | ||
if (typeof _this._rootDOMNode === 'undefined') { | ||
return; | ||
} | ||
var _calculateNodeHeight = calculateNodeHeight(_this._rootDOMNode, _this.props.useCacheForDOMMeasurements, _this.props.rows || _this.props.minRows, _this.props.maxRows), | ||
var _calculateNodeHeight = calculateNodeHeight(_this._rootDOMNode, _this._uid, _this.props.useCacheForDOMMeasurements, _this.props.minRows, _this.props.maxRows), | ||
height = _calculateNodeHeight.height, | ||
minHeight = _calculateNodeHeight.minHeight, | ||
maxHeight = _calculateNodeHeight.maxHeight; | ||
maxHeight = _calculateNodeHeight.maxHeight, | ||
rowCount = _calculateNodeHeight.rowCount; | ||
_this.rowCount = rowCount; | ||
if (_this.state.height !== height || _this.state.minHeight !== minHeight || _this.state.maxHeight !== maxHeight) { | ||
@@ -376,2 +348,3 @@ _this.setState({ height: height, minHeight: minHeight, maxHeight: maxHeight }); | ||
_this._uid = uid(); | ||
_this._controlled = typeof props.value === 'string'; | ||
@@ -383,3 +356,2 @@ return _this; | ||
var _props = this.props, | ||
valueLink = _props.valueLink, | ||
_minRows = _props.minRows, | ||
@@ -390,9 +362,5 @@ _maxRows = _props.maxRows, | ||
_inputRef = _props.inputRef, | ||
props = objectWithoutProperties(_props, ['valueLink', 'minRows', 'maxRows', 'onHeightChange', 'useCacheForDOMMeasurements', 'inputRef']); | ||
props = objectWithoutProperties(_props, ['minRows', 'maxRows', 'onHeightChange', 'useCacheForDOMMeasurements', 'inputRef']); | ||
if ((typeof valueLink === 'undefined' ? 'undefined' : _typeof(valueLink)) === 'object') { | ||
props.value = valueLink.value; | ||
} | ||
props.style = _extends({}, props.style, { | ||
@@ -420,3 +388,2 @@ height: this.state.height | ||
TextareaAutosize.prototype.componentWillReceiveProps = function componentWillReceiveProps() { | ||
// Re-render with the new content then recalculate the height as required. | ||
this._clearNextFrame(); | ||
@@ -427,5 +394,4 @@ this._onNextFrameActionId = onNextFrame(this._resizeComponent); | ||
TextareaAutosize.prototype.componentDidUpdate = function componentDidUpdate(prevProps, prevState) { | ||
// Invoke callback when old height does not equal to new one. | ||
if (this.state.height !== prevState.height) { | ||
this.props.onHeightChange(this.state.height); | ||
this.props.onHeightChange(this.state.height, this); | ||
} | ||
@@ -435,85 +401,11 @@ }; | ||
TextareaAutosize.prototype.componentWillUnmount = function componentWillUnmount() { | ||
// Remove any scheduled events to prevent manipulating the node after it's | ||
// been unmounted. | ||
this._clearNextFrame(); | ||
window.removeEventListener('resize', this._resizeComponent); | ||
purgeCache(this._uid); | ||
}; | ||
TextareaAutosize.prototype._clearNextFrame = function _clearNextFrame() { | ||
if (this._onNextFrameActionId) { | ||
clearNextFrameAction(this._onNextFrameActionId); | ||
} | ||
clearNextFrameAction(this._onNextFrameActionId); | ||
}; | ||
/** | ||
* Put focus on a <textarea /> DOM element. | ||
*/ | ||
TextareaAutosize.prototype.focus = function focus() { | ||
this._rootDOMNode.focus(); | ||
}; | ||
/** | ||
* Shifts focus away from a <textarea /> DOM element. | ||
*/ | ||
TextareaAutosize.prototype.blur = function blur() { | ||
this._rootDOMNode.blur(); | ||
}; | ||
createClass(TextareaAutosize, [{ | ||
key: 'value', | ||
/** | ||
* Read the current value of <textarea /> from DOM. | ||
*/ | ||
get: function get() { | ||
return this._rootDOMNode.value; | ||
} | ||
/** | ||
* Set the current value of <textarea /> DOM node. | ||
*/ | ||
, | ||
set: function set(val) { | ||
this._rootDOMNode.value = val; | ||
} | ||
/** | ||
* Read the current selectionStart of <textarea /> from DOM. | ||
*/ | ||
}, { | ||
key: 'selectionStart', | ||
get: function get() { | ||
return this._rootDOMNode.selectionStart; | ||
} | ||
/** | ||
* Set the current selectionStart of <textarea /> DOM node. | ||
*/ | ||
, | ||
set: function set(selectionStart) { | ||
this._rootDOMNode.selectionStart = selectionStart; | ||
} | ||
/** | ||
* Read the current selectionEnd of <textarea /> from DOM. | ||
*/ | ||
}, { | ||
key: 'selectionEnd', | ||
get: function get() { | ||
return this._rootDOMNode.selectionEnd; | ||
} | ||
/** | ||
* Set the current selectionEnd of <textarea /> DOM node. | ||
*/ | ||
, | ||
set: function set(selectionEnd) { | ||
this._rootDOMNode.selectionEnd = selectionEnd; | ||
} | ||
}]); | ||
return TextareaAutosize; | ||
@@ -523,44 +415,8 @@ }(React.Component); | ||
TextareaAutosize.propTypes = { | ||
/** | ||
* Current textarea value. | ||
*/ | ||
value: PropTypes.string, | ||
/** | ||
* Callback on value change. | ||
*/ | ||
onChange: PropTypes.func, | ||
/** | ||
* Callback on height changes. | ||
*/ | ||
onHeightChange: PropTypes.func, | ||
/** | ||
* Try to cache DOM measurements performed by component so that we don't | ||
* touch DOM when it's not needed. | ||
* | ||
* This optimization doesn't work if we dynamically style <textarea /> | ||
* component. | ||
*/ | ||
useCacheForDOMMeasurements: PropTypes.bool, | ||
/** | ||
* Minimal numbder of rows to show. | ||
*/ | ||
rows: PropTypes.number, | ||
/** | ||
* Alias for `rows`. | ||
*/ | ||
minRows: PropTypes.number, | ||
/** | ||
* Maximum number of rows to show. | ||
*/ | ||
maxRows: PropTypes.number, | ||
/** | ||
* Allows an owner to retrieve the DOM node. | ||
*/ | ||
inputRef: PropTypes.func | ||
@@ -573,19 +429,5 @@ }; | ||
}; | ||
function onNextFrame(cb) { | ||
if (window.requestAnimationFrame) { | ||
return window.requestAnimationFrame(cb); | ||
} | ||
return window.setTimeout(cb, 1); | ||
} | ||
function clearNextFrameAction(nextFrameId) { | ||
if (window.cancelAnimationFrame) { | ||
window.cancelAnimationFrame(nextFrameId); | ||
} else { | ||
window.clearTimeout(nextFrameId); | ||
} | ||
} | ||
return TextareaAutosize; | ||
}))); |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("react"),require("prop-types")):"function"==typeof define&&define.amd?define(["react","prop-types"],t):e.TextareaAutosize=t(e.React,e.PropTypes)}(this,function(e,t){"use strict";function o(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null;h?null===h.parentNode&&document.body.appendChild(h):(h=document.createElement("textarea"),document.body.appendChild(h));var r=n(e,t),a=r.paddingSize,s=r.borderSize,u=r.boxSizing,l=r.sizingStyle;Object.keys(l).map(function(e){h.style[e]=l[e]}),Object.keys(p).map(function(e){h.style.setProperty(e,p[e],"important")}),h.value=e.value||e.placeholder||"x";var d=-1/0,c=1/0,f=h.scrollHeight;if("border-box"===u?f+=s:"content-box"===u&&(f-=a),null!==o||null!==i){h.value="x";var g=h.scrollHeight-a;null!==o&&(d=g*o,"border-box"===u&&(d=d+a+s),f=Math.max(d,f)),null!==i&&(c=g*i,"border-box"===u&&(c=c+a+s),f=Math.min(c,f))}return{height:f,minHeight:d,maxHeight:c}}function n(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=e.getAttribute("id")||e.getAttribute("data-reactid")||e.getAttribute("name");if(t&&d[o])return d[o];var n=window.getComputedStyle(e),i=l.reduce(function(e,t){return e[t]=n.getPropertyValue(t),e},{}),r=i[u];s&&"border-box"===r&&(i.width=parseFloat(i.width)+parseFloat(n["border-right-width"])+parseFloat(n["border-left-width"])+parseFloat(n["padding-right"])+parseFloat(n["padding-left"])+"px");var a=parseFloat(i["padding-bottom"])+parseFloat(i["padding-top"]),p=parseFloat(i["border-bottom-width"])+parseFloat(i["border-top-width"]),h={sizingStyle:i,paddingSize:a,borderSize:p,boxSizing:r};return t&&o&&(d[o]=h),h}function i(e){return window.requestAnimationFrame?window.requestAnimationFrame(e):window.setTimeout(e,1)}function r(e){window.cancelAnimationFrame?window.cancelAnimationFrame(e):window.clearTimeout(e)}e="default"in e?e.default:e,t="default"in t?t.default:t;var a="undefined"!=typeof window&&"undefined"!=typeof document,s=!!a&&!!document.documentElement.currentStyle,u=function(){if(!a)return"box-sizing";var e=window.getComputedStyle(document.documentElement);return e.getPropertyValue("box-sizing")?"box-sizing":e.getPropertyValue("-moz-box-sizing")?"-moz-box-sizing":e.getPropertyValue("-webkit-box-sizing")?"-webkit-box-sizing":"box-sizing"}(),p={"min-height":"0","max-height":"none",height:"0",visibility:"hidden",overflow:"hidden",position:"absolute","z-index":"-1000",top:"0",right:"0"},l=["letter-spacing","line-height","font-family","font-weight","font-size","text-rendering","text-transform","width","text-indent","padding-top","padding-right","padding-bottom","padding-left","border-top-width","border-right-width","border-bottom-width","border-left-width",u],d={},h=void 0,c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},f=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},g=function(){function e(e,t){for(var o=0;t.length>o;o++){var n=t[o];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,o,n){return o&&e(t.prototype,o),n&&e(t,n),t}}(),m=Object.assign||function(e){for(var t=1;arguments.length>t;t++){var o=arguments[t];for(var n in o)Object.prototype.hasOwnProperty.call(o,n)&&(e[n]=o[n])}return e},b=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)},y=function(e,t){var o={};for(var n in e)0>t.indexOf(n)&&Object.prototype.hasOwnProperty.call(e,n)&&(o[n]=e[n]);return o},w=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t},v=function(){},x=function(t){function n(e){f(this,n);var i=w(this,t.call(this,e));return i._onRootDOMNode=function(e){i._rootDOMNode=e,i.props.inputRef&&i.props.inputRef(e)},i._onChange=function(e){i._controlled||i._resizeComponent();var t=i.props,o=t.valueLink,n=t.onChange;o?o.requestChange(e.target.value):n(e)},i._resizeComponent=function(){if(i._rootDOMNode){var e=o(i._rootDOMNode,i.props.useCacheForDOMMeasurements,i.props.rows||i.props.minRows,i.props.maxRows),t=e.height,n=e.minHeight,r=e.maxHeight;i.state.height===t&&i.state.minHeight===n&&i.state.maxHeight===r||i.setState({height:t,minHeight:n,maxHeight:r})}},i.state={height:e.style&&e.style.height||0,minHeight:-1/0,maxHeight:1/0},i._controlled="string"==typeof e.value,i}return b(n,t),n.prototype.render=function(){var t=this.props,o=t.valueLink,n=y(t,["valueLink","minRows","maxRows","onHeightChange","useCacheForDOMMeasurements","inputRef"]);return"object"===(void 0===o?"undefined":c(o))&&(n.value=o.value),n.style=m({},n.style,{height:this.state.height}),this.state.height>Math.max(n.style.maxHeight||1/0,this.state.maxHeight)&&(n.style.overflow="hidden"),e.createElement("textarea",m({},n,{onChange:this._onChange,ref:this._onRootDOMNode}))},n.prototype.componentDidMount=function(){this._resizeComponent(),window.addEventListener("resize",this._resizeComponent)},n.prototype.componentWillReceiveProps=function(){this._clearNextFrame(),this._onNextFrameActionId=i(this._resizeComponent)},n.prototype.componentDidUpdate=function(e,t){this.state.height!==t.height&&this.props.onHeightChange(this.state.height)},n.prototype.componentWillUnmount=function(){this._clearNextFrame(),window.removeEventListener("resize",this._resizeComponent)},n.prototype._clearNextFrame=function(){this._onNextFrameActionId&&r(this._onNextFrameActionId)},n.prototype.focus=function(){this._rootDOMNode.focus()},n.prototype.blur=function(){this._rootDOMNode.blur()},g(n,[{key:"value",get:function(){return this._rootDOMNode.value},set:function(e){this._rootDOMNode.value=e}},{key:"selectionStart",get:function(){return this._rootDOMNode.selectionStart},set:function(e){this._rootDOMNode.selectionStart=e}},{key:"selectionEnd",get:function(){return this._rootDOMNode.selectionEnd},set:function(e){this._rootDOMNode.selectionEnd=e}}]),n}(e.Component);return x.propTypes={value:t.string,onChange:t.func,onHeightChange:t.func,useCacheForDOMMeasurements:t.bool,rows:t.number,minRows:t.number,maxRows:t.number,inputRef:t.func},x.defaultProps={onChange:v,onHeightChange:v,useCacheForDOMMeasurements:!1},x}); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("react"),require("prop-types")):"function"==typeof define&&define.amd?define(["react","prop-types"],t):e.TextareaAutosize=t(e.React,e.PropTypes)}(this,function(e,t){"use strict";function o(e,t){var o=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null;null===a.parentNode&&document.body.appendChild(a);var h=n(e,o),p=h.paddingSize,u=h.borderSize,d=h.boxSizing,l=h.sizingStyle;Object.keys(l).forEach(function(e){a.style[e]=l[e]}),Object.keys(s).forEach(function(e){a.style.setProperty(e,s[e],"important")}),a.value=e.value||e.placeholder||"x";var c=-1/0,f=1/0,g=a.scrollHeight;"border-box"===d?g+=u:"content-box"===d&&(g-=p),a.value="x";var m=a.scrollHeight-p;return null===i&&null===r||(null!==i&&(c=m*i,"border-box"===d&&(c=c+p+u),g=Math.max(c,g)),null!==r&&(f=m*r,"border-box"===d&&(f=f+p+u),g=Math.min(f,g))),{height:g,minHeight:c,maxHeight:f,rowCount:Math.floor(g/m)}}function n(e,t){var o=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(o&&p[t])return p[t];var n=window.getComputedStyle(e),i=h.reduce(function(e,t){return e[t]=n.getPropertyValue(t),e},{}),a=i["box-sizing"];r&&"border-box"===a&&(i.width=parseFloat(i.width)+parseFloat(n["border-right-width"])+parseFloat(n["border-left-width"])+parseFloat(n["padding-right"])+parseFloat(n["padding-left"])+"px");var s=parseFloat(i["padding-bottom"])+parseFloat(i["padding-top"]),u=parseFloat(i["border-bottom-width"])+parseFloat(i["border-top-width"]),d={sizingStyle:i,paddingSize:s,borderSize:u,boxSizing:a};return o&&(p[t]=d),d}e="default"in e?e.default:e,t="default"in t?t.default:t;var i="undefined"!=typeof window&&"undefined"!=typeof document,r=!!i&&!!document.documentElement.currentStyle,a=i&&document.createElement("textarea"),s={"min-height":"0","max-height":"none",height:"0",visibility:"hidden",overflow:"hidden",position:"absolute","z-index":"-1000",top:"0",right:"0"},h=["letter-spacing","line-height","font-family","font-weight","font-size","text-rendering","text-transform","width","text-indent","padding-top","padding-right","padding-bottom","padding-left","border-top-width","border-right-width","border-bottom-width","border-left-width","box-sizing"],p={},u=function(e){return delete p[e]},d=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;return function(){return++e}}(),l=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},c=Object.assign||function(e){for(var t=1;arguments.length>t;t++){var o=arguments[t];for(var n in o)Object.prototype.hasOwnProperty.call(o,n)&&(e[n]=o[n])}return e},f=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)},g=function(e,t){var o={};for(var n in e)0>t.indexOf(n)&&Object.prototype.hasOwnProperty.call(e,n)&&(o[n]=e[n]);return o},m=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t},b=function(){},y=window.requestAnimationFrame?[window.requestAnimationFrame,window.cancelAnimationFrame]:[setTimeout,clearTimeout],w=y[0],x=y[1],v=function(t){function n(e){l(this,n);var i=m(this,t.call(this,e));return i._onRootDOMNode=function(e){i._rootDOMNode=e,i.props.inputRef&&i.props.inputRef(e)},i._onChange=function(e){i._controlled||i._resizeComponent(),i.props.onChange(e)},i._resizeComponent=function(){if(void 0!==i._rootDOMNode){var e=o(i._rootDOMNode,i._uid,i.props.useCacheForDOMMeasurements,i.props.minRows,i.props.maxRows),t=e.height,n=e.minHeight,r=e.maxHeight;i.rowCount=e.rowCount,i.state.height===t&&i.state.minHeight===n&&i.state.maxHeight===r||i.setState({height:t,minHeight:n,maxHeight:r})}},i.state={height:e.style&&e.style.height||0,minHeight:-1/0,maxHeight:1/0},i._uid=d(),i._controlled="string"==typeof e.value,i}return f(n,t),n.prototype.render=function(){var t=this.props,o=g(t,["minRows","maxRows","onHeightChange","useCacheForDOMMeasurements","inputRef"]);return o.style=c({},o.style,{height:this.state.height}),this.state.height>Math.max(o.style.maxHeight||1/0,this.state.maxHeight)&&(o.style.overflow="hidden"),e.createElement("textarea",c({},o,{onChange:this._onChange,ref:this._onRootDOMNode}))},n.prototype.componentDidMount=function(){this._resizeComponent(),window.addEventListener("resize",this._resizeComponent)},n.prototype.componentWillReceiveProps=function(){this._clearNextFrame(),this._onNextFrameActionId=w(this._resizeComponent)},n.prototype.componentDidUpdate=function(e,t){this.state.height!==t.height&&this.props.onHeightChange(this.state.height,this)},n.prototype.componentWillUnmount=function(){this._clearNextFrame(),window.removeEventListener("resize",this._resizeComponent),u(this._uid)},n.prototype._clearNextFrame=function(){x(this._onNextFrameActionId)},n}(e.Component);return v.propTypes={value:t.string,onChange:t.func,onHeightChange:t.func,useCacheForDOMMeasurements:t.bool,minRows:t.number,maxRows:t.number,inputRef:t.func},v.defaultProps={onChange:b,onHeightChange:b,useCacheForDOMMeasurements:!1},v}); |
@@ -1,14 +0,4 @@ | ||
/** | ||
* calculateNodeHeight(uiTextNode, useCache = false) | ||
*/ | ||
var browser = typeof window !== 'undefined' && typeof document !== 'undefined'; | ||
var isIE = browser ? !!document.documentElement.currentStyle : false; | ||
var boxSizingProp = function () { | ||
if (!browser) { | ||
return 'box-sizing'; | ||
} | ||
var documentStyle = window.getComputedStyle(document.documentElement); | ||
// TODO: remove prefixed - they are probably obsolete, were introduced in by df79cf502630744d40233b64cad01770e5584610 in 2014 | ||
return documentStyle.getPropertyValue('box-sizing') ? 'box-sizing' : documentStyle.getPropertyValue('-moz-box-sizing') ? '-moz-box-sizing' : documentStyle.getPropertyValue('-webkit-box-sizing') ? '-webkit-box-sizing' : 'box-sizing'; | ||
}(); | ||
var hiddenTextarea = browser && document.createElement('textarea'); | ||
@@ -27,17 +17,14 @@ var HIDDEN_TEXTAREA_STYLE = { | ||
var SIZING_STYLE = ['letter-spacing', 'line-height', 'font-family', 'font-weight', 'font-size', 'text-rendering', 'text-transform', 'width', 'text-indent', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width', boxSizingProp]; | ||
var SIZING_STYLE = ['letter-spacing', 'line-height', 'font-family', 'font-weight', 'font-size', 'text-rendering', 'text-transform', 'width', 'text-indent', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width', 'box-sizing']; | ||
var computedStyleCache = {}; | ||
var hiddenTextarea = void 0; | ||
export default function calculateNodeHeight(uiTextNode) { | ||
var useCache = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
var minRows = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; | ||
var maxRows = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; | ||
export default function calculateNodeHeight(uiTextNode, uid) { | ||
var useCache = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; | ||
var minRows = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; | ||
var maxRows = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; | ||
if (!hiddenTextarea) { | ||
hiddenTextarea = document.createElement('textarea'); | ||
if (hiddenTextarea.parentNode === null) { | ||
document.body.appendChild(hiddenTextarea); | ||
} else if (hiddenTextarea.parentNode === null) { | ||
document.body.appendChild(hiddenTextarea); | ||
} | ||
@@ -59,6 +46,6 @@ | ||
Object.keys(sizingStyle).map(function (key) { | ||
Object.keys(sizingStyle).forEach(function (key) { | ||
hiddenTextarea.style[key] = sizingStyle[key]; | ||
}); | ||
Object.keys(HIDDEN_TEXTAREA_STYLE).map(function (key) { | ||
Object.keys(HIDDEN_TEXTAREA_STYLE).forEach(function (key) { | ||
hiddenTextarea.style.setProperty(key, HIDDEN_TEXTAREA_STYLE[key], 'important'); | ||
@@ -80,6 +67,7 @@ }); | ||
// measure height of a textarea with a single row | ||
hiddenTextarea.value = 'x'; | ||
var singleRowHeight = hiddenTextarea.scrollHeight - paddingSize; | ||
if (minRows !== null || maxRows !== null) { | ||
// measure height of a textarea with a single row | ||
hiddenTextarea.value = 'x'; | ||
var singleRowHeight = hiddenTextarea.scrollHeight - paddingSize; | ||
if (minRows !== null) { | ||
@@ -100,13 +88,13 @@ minHeight = singleRowHeight * minRows; | ||
} | ||
return { height: height, minHeight: minHeight, maxHeight: maxHeight }; | ||
var rowCount = Math.floor(height / singleRowHeight); | ||
return { height: height, minHeight: minHeight, maxHeight: maxHeight, rowCount: rowCount }; | ||
} | ||
function calculateNodeStyling(node) { | ||
var useCache = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
function calculateNodeStyling(node, uid) { | ||
var useCache = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; | ||
// TODO: generate id in constructor + clear cache in componentWillUnmount | ||
var nodeRef = node.getAttribute('id') || node.getAttribute('data-reactid') || node.getAttribute('name'); | ||
if (useCache && computedStyleCache[nodeRef]) { | ||
return computedStyleCache[nodeRef]; | ||
if (useCache && computedStyleCache[uid]) { | ||
return computedStyleCache[uid]; | ||
} | ||
@@ -121,3 +109,3 @@ | ||
var boxSizing = sizingStyle[boxSizingProp]; | ||
var boxSizing = sizingStyle['box-sizing']; | ||
@@ -141,7 +129,11 @@ // IE (Edge has already correct behaviour) returns content width as computed width | ||
if (useCache && nodeRef) { | ||
computedStyleCache[nodeRef] = nodeInfo; | ||
if (useCache) { | ||
computedStyleCache[uid] = nodeInfo; | ||
} | ||
return nodeInfo; | ||
} | ||
} | ||
export var purgeCache = function purgeCache(uid) { | ||
return delete computedStyleCache[uid]; | ||
}; |
180
es/index.js
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } | ||
@@ -21,6 +17,11 @@ | ||
import PropTypes from 'prop-types'; | ||
import calculateNodeHeight from './calculateNodeHeight'; | ||
import calculateNodeHeight, { purgeCache } from './calculateNodeHeight'; | ||
import uid from './uid'; | ||
var noop = function noop() {}; | ||
var _ref = window.requestAnimationFrame ? [window.requestAnimationFrame, window.cancelAnimationFrame] : [setTimeout, clearTimeout], | ||
onNextFrame = _ref[0], | ||
clearNextFrameAction = _ref[1]; | ||
var TextareaAutosize = function (_React$Component) { | ||
@@ -36,3 +37,6 @@ _inherits(TextareaAutosize, _React$Component); | ||
_this._rootDOMNode = node; | ||
if (_this.props.inputRef) _this.props.inputRef(node); | ||
if (_this.props.inputRef) { | ||
_this.props.inputRef(node); | ||
} | ||
}; | ||
@@ -44,23 +48,18 @@ | ||
} | ||
var _this$props = _this.props, | ||
valueLink = _this$props.valueLink, | ||
onChange = _this$props.onChange; | ||
if (valueLink) { | ||
valueLink.requestChange(event.target.value); | ||
} else { | ||
onChange(event); | ||
} | ||
_this.props.onChange(event); | ||
}; | ||
_this._resizeComponent = function () { | ||
if (!_this._rootDOMNode) { | ||
if (typeof _this._rootDOMNode === 'undefined') { | ||
return; | ||
} | ||
var _calculateNodeHeight = calculateNodeHeight(_this._rootDOMNode, _this.props.useCacheForDOMMeasurements, _this.props.rows || _this.props.minRows, _this.props.maxRows), | ||
var _calculateNodeHeight = calculateNodeHeight(_this._rootDOMNode, _this._uid, _this.props.useCacheForDOMMeasurements, _this.props.minRows, _this.props.maxRows), | ||
height = _calculateNodeHeight.height, | ||
minHeight = _calculateNodeHeight.minHeight, | ||
maxHeight = _calculateNodeHeight.maxHeight; | ||
maxHeight = _calculateNodeHeight.maxHeight, | ||
rowCount = _calculateNodeHeight.rowCount; | ||
_this.rowCount = rowCount; | ||
if (_this.state.height !== height || _this.state.minHeight !== minHeight || _this.state.maxHeight !== maxHeight) { | ||
@@ -77,2 +76,3 @@ _this.setState({ height: height, minHeight: minHeight, maxHeight: maxHeight }); | ||
_this._uid = uid(); | ||
_this._controlled = typeof props.value === 'string'; | ||
@@ -84,3 +84,2 @@ return _this; | ||
var _props = this.props, | ||
valueLink = _props.valueLink, | ||
_minRows = _props.minRows, | ||
@@ -91,8 +90,4 @@ _maxRows = _props.maxRows, | ||
_inputRef = _props.inputRef, | ||
props = _objectWithoutProperties(_props, ['valueLink', 'minRows', 'maxRows', 'onHeightChange', 'useCacheForDOMMeasurements', 'inputRef']); | ||
props = _objectWithoutProperties(_props, ['minRows', 'maxRows', 'onHeightChange', 'useCacheForDOMMeasurements', 'inputRef']); | ||
if ((typeof valueLink === 'undefined' ? 'undefined' : _typeof(valueLink)) === 'object') { | ||
props.value = valueLink.value; | ||
} | ||
props.style = _extends({}, props.style, { | ||
@@ -120,3 +115,2 @@ height: this.state.height | ||
TextareaAutosize.prototype.componentWillReceiveProps = function componentWillReceiveProps() { | ||
// Re-render with the new content then recalculate the height as required. | ||
this._clearNextFrame(); | ||
@@ -127,5 +121,4 @@ this._onNextFrameActionId = onNextFrame(this._resizeComponent); | ||
TextareaAutosize.prototype.componentDidUpdate = function componentDidUpdate(prevProps, prevState) { | ||
// Invoke callback when old height does not equal to new one. | ||
if (this.state.height !== prevState.height) { | ||
this.props.onHeightChange(this.state.height); | ||
this.props.onHeightChange(this.state.height, this); | ||
} | ||
@@ -135,86 +128,11 @@ }; | ||
TextareaAutosize.prototype.componentWillUnmount = function componentWillUnmount() { | ||
// Remove any scheduled events to prevent manipulating the node after it's | ||
// been unmounted. | ||
this._clearNextFrame(); | ||
window.removeEventListener('resize', this._resizeComponent); | ||
purgeCache(this._uid); | ||
}; | ||
TextareaAutosize.prototype._clearNextFrame = function _clearNextFrame() { | ||
if (this._onNextFrameActionId) { | ||
clearNextFrameAction(this._onNextFrameActionId); | ||
} | ||
clearNextFrameAction(this._onNextFrameActionId); | ||
}; | ||
/** | ||
* Put focus on a <textarea /> DOM element. | ||
*/ | ||
TextareaAutosize.prototype.focus = function focus() { | ||
this._rootDOMNode.focus(); | ||
}; | ||
/** | ||
* Shifts focus away from a <textarea /> DOM element. | ||
*/ | ||
TextareaAutosize.prototype.blur = function blur() { | ||
this._rootDOMNode.blur(); | ||
}; | ||
_createClass(TextareaAutosize, [{ | ||
key: 'value', | ||
/** | ||
* Read the current value of <textarea /> from DOM. | ||
*/ | ||
get: function get() { | ||
return this._rootDOMNode.value; | ||
} | ||
/** | ||
* Set the current value of <textarea /> DOM node. | ||
*/ | ||
, | ||
set: function set(val) { | ||
this._rootDOMNode.value = val; | ||
} | ||
/** | ||
* Read the current selectionStart of <textarea /> from DOM. | ||
*/ | ||
}, { | ||
key: 'selectionStart', | ||
get: function get() { | ||
return this._rootDOMNode.selectionStart; | ||
} | ||
/** | ||
* Set the current selectionStart of <textarea /> DOM node. | ||
*/ | ||
, | ||
set: function set(selectionStart) { | ||
this._rootDOMNode.selectionStart = selectionStart; | ||
} | ||
/** | ||
* Read the current selectionEnd of <textarea /> from DOM. | ||
*/ | ||
}, { | ||
key: 'selectionEnd', | ||
get: function get() { | ||
return this._rootDOMNode.selectionEnd; | ||
} | ||
/** | ||
* Set the current selectionEnd of <textarea /> DOM node. | ||
*/ | ||
, | ||
set: function set(selectionEnd) { | ||
this._rootDOMNode.selectionEnd = selectionEnd; | ||
} | ||
}]); | ||
return TextareaAutosize; | ||
@@ -224,44 +142,8 @@ }(React.Component); | ||
TextareaAutosize.propTypes = { | ||
/** | ||
* Current textarea value. | ||
*/ | ||
value: PropTypes.string, | ||
/** | ||
* Callback on value change. | ||
*/ | ||
onChange: PropTypes.func, | ||
/** | ||
* Callback on height changes. | ||
*/ | ||
onHeightChange: PropTypes.func, | ||
/** | ||
* Try to cache DOM measurements performed by component so that we don't | ||
* touch DOM when it's not needed. | ||
* | ||
* This optimization doesn't work if we dynamically style <textarea /> | ||
* component. | ||
*/ | ||
useCacheForDOMMeasurements: PropTypes.bool, | ||
/** | ||
* Minimal numbder of rows to show. | ||
*/ | ||
rows: PropTypes.number, | ||
/** | ||
* Alias for `rows`. | ||
*/ | ||
minRows: PropTypes.number, | ||
/** | ||
* Maximum number of rows to show. | ||
*/ | ||
maxRows: PropTypes.number, | ||
/** | ||
* Allows an owner to retrieve the DOM node. | ||
*/ | ||
inputRef: PropTypes.func | ||
@@ -274,18 +156,2 @@ }; | ||
}; | ||
export default TextareaAutosize; | ||
function onNextFrame(cb) { | ||
if (window.requestAnimationFrame) { | ||
return window.requestAnimationFrame(cb); | ||
} | ||
return window.setTimeout(cb, 1); | ||
} | ||
function clearNextFrameAction(nextFrameId) { | ||
if (window.cancelAnimationFrame) { | ||
window.cancelAnimationFrame(nextFrameId); | ||
} else { | ||
window.clearTimeout(nextFrameId); | ||
} | ||
} | ||
export default TextareaAutosize; |
@@ -5,15 +5,5 @@ 'use strict'; | ||
exports.default = calculateNodeHeight; | ||
/** | ||
* calculateNodeHeight(uiTextNode, useCache = false) | ||
*/ | ||
var browser = typeof window !== 'undefined' && typeof document !== 'undefined'; | ||
var isIE = browser ? !!document.documentElement.currentStyle : false; | ||
var boxSizingProp = function () { | ||
if (!browser) { | ||
return 'box-sizing'; | ||
} | ||
var documentStyle = window.getComputedStyle(document.documentElement); | ||
// TODO: remove prefixed - they are probably obsolete, were introduced in by df79cf502630744d40233b64cad01770e5584610 in 2014 | ||
return documentStyle.getPropertyValue('box-sizing') ? 'box-sizing' : documentStyle.getPropertyValue('-moz-box-sizing') ? '-moz-box-sizing' : documentStyle.getPropertyValue('-webkit-box-sizing') ? '-webkit-box-sizing' : 'box-sizing'; | ||
}(); | ||
var hiddenTextarea = browser && document.createElement('textarea'); | ||
@@ -32,17 +22,14 @@ var HIDDEN_TEXTAREA_STYLE = { | ||
var SIZING_STYLE = ['letter-spacing', 'line-height', 'font-family', 'font-weight', 'font-size', 'text-rendering', 'text-transform', 'width', 'text-indent', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width', boxSizingProp]; | ||
var SIZING_STYLE = ['letter-spacing', 'line-height', 'font-family', 'font-weight', 'font-size', 'text-rendering', 'text-transform', 'width', 'text-indent', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width', 'box-sizing']; | ||
var computedStyleCache = {}; | ||
var hiddenTextarea = void 0; | ||
function calculateNodeHeight(uiTextNode) { | ||
var useCache = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
var minRows = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; | ||
var maxRows = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; | ||
function calculateNodeHeight(uiTextNode, uid) { | ||
var useCache = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; | ||
var minRows = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; | ||
var maxRows = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; | ||
if (!hiddenTextarea) { | ||
hiddenTextarea = document.createElement('textarea'); | ||
if (hiddenTextarea.parentNode === null) { | ||
document.body.appendChild(hiddenTextarea); | ||
} else if (hiddenTextarea.parentNode === null) { | ||
document.body.appendChild(hiddenTextarea); | ||
} | ||
@@ -64,6 +51,6 @@ | ||
Object.keys(sizingStyle).map(function (key) { | ||
Object.keys(sizingStyle).forEach(function (key) { | ||
hiddenTextarea.style[key] = sizingStyle[key]; | ||
}); | ||
Object.keys(HIDDEN_TEXTAREA_STYLE).map(function (key) { | ||
Object.keys(HIDDEN_TEXTAREA_STYLE).forEach(function (key) { | ||
hiddenTextarea.style.setProperty(key, HIDDEN_TEXTAREA_STYLE[key], 'important'); | ||
@@ -85,6 +72,7 @@ }); | ||
// measure height of a textarea with a single row | ||
hiddenTextarea.value = 'x'; | ||
var singleRowHeight = hiddenTextarea.scrollHeight - paddingSize; | ||
if (minRows !== null || maxRows !== null) { | ||
// measure height of a textarea with a single row | ||
hiddenTextarea.value = 'x'; | ||
var singleRowHeight = hiddenTextarea.scrollHeight - paddingSize; | ||
if (minRows !== null) { | ||
@@ -105,13 +93,13 @@ minHeight = singleRowHeight * minRows; | ||
} | ||
return { height: height, minHeight: minHeight, maxHeight: maxHeight }; | ||
var rowCount = Math.floor(height / singleRowHeight); | ||
return { height: height, minHeight: minHeight, maxHeight: maxHeight, rowCount: rowCount }; | ||
} | ||
function calculateNodeStyling(node) { | ||
var useCache = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
function calculateNodeStyling(node, uid) { | ||
var useCache = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; | ||
// TODO: generate id in constructor + clear cache in componentWillUnmount | ||
var nodeRef = node.getAttribute('id') || node.getAttribute('data-reactid') || node.getAttribute('name'); | ||
if (useCache && computedStyleCache[nodeRef]) { | ||
return computedStyleCache[nodeRef]; | ||
if (useCache && computedStyleCache[uid]) { | ||
return computedStyleCache[uid]; | ||
} | ||
@@ -126,3 +114,3 @@ | ||
var boxSizing = sizingStyle[boxSizingProp]; | ||
var boxSizing = sizingStyle['box-sizing']; | ||
@@ -146,7 +134,11 @@ // IE (Edge has already correct behaviour) returns content width as computed width | ||
if (useCache && nodeRef) { | ||
computedStyleCache[nodeRef] = nodeInfo; | ||
if (useCache) { | ||
computedStyleCache[uid] = nodeInfo; | ||
} | ||
return nodeInfo; | ||
} | ||
} | ||
var purgeCache = exports.purgeCache = function purgeCache(uid) { | ||
return delete computedStyleCache[uid]; | ||
}; |
181
lib/index.js
@@ -7,6 +7,2 @@ 'use strict'; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var _react = require('react'); | ||
@@ -24,2 +20,6 @@ | ||
var _uid = require('./uid'); | ||
var _uid2 = _interopRequireDefault(_uid); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -39,2 +39,6 @@ | ||
var _ref = window.requestAnimationFrame ? [window.requestAnimationFrame, window.cancelAnimationFrame] : [setTimeout, clearTimeout], | ||
onNextFrame = _ref[0], | ||
clearNextFrameAction = _ref[1]; | ||
var TextareaAutosize = function (_React$Component) { | ||
@@ -50,3 +54,6 @@ _inherits(TextareaAutosize, _React$Component); | ||
_this._rootDOMNode = node; | ||
if (_this.props.inputRef) _this.props.inputRef(node); | ||
if (_this.props.inputRef) { | ||
_this.props.inputRef(node); | ||
} | ||
}; | ||
@@ -58,23 +65,18 @@ | ||
} | ||
var _this$props = _this.props, | ||
valueLink = _this$props.valueLink, | ||
onChange = _this$props.onChange; | ||
if (valueLink) { | ||
valueLink.requestChange(event.target.value); | ||
} else { | ||
onChange(event); | ||
} | ||
_this.props.onChange(event); | ||
}; | ||
_this._resizeComponent = function () { | ||
if (!_this._rootDOMNode) { | ||
if (typeof _this._rootDOMNode === 'undefined') { | ||
return; | ||
} | ||
var _calculateNodeHeight = (0, _calculateNodeHeight3.default)(_this._rootDOMNode, _this.props.useCacheForDOMMeasurements, _this.props.rows || _this.props.minRows, _this.props.maxRows), | ||
var _calculateNodeHeight = (0, _calculateNodeHeight3.default)(_this._rootDOMNode, _this._uid, _this.props.useCacheForDOMMeasurements, _this.props.minRows, _this.props.maxRows), | ||
height = _calculateNodeHeight.height, | ||
minHeight = _calculateNodeHeight.minHeight, | ||
maxHeight = _calculateNodeHeight.maxHeight; | ||
maxHeight = _calculateNodeHeight.maxHeight, | ||
rowCount = _calculateNodeHeight.rowCount; | ||
_this.rowCount = rowCount; | ||
if (_this.state.height !== height || _this.state.minHeight !== minHeight || _this.state.maxHeight !== maxHeight) { | ||
@@ -91,2 +93,3 @@ _this.setState({ height: height, minHeight: minHeight, maxHeight: maxHeight }); | ||
_this._uid = (0, _uid2.default)(); | ||
_this._controlled = typeof props.value === 'string'; | ||
@@ -98,3 +101,2 @@ return _this; | ||
var _props = this.props, | ||
valueLink = _props.valueLink, | ||
_minRows = _props.minRows, | ||
@@ -105,8 +107,4 @@ _maxRows = _props.maxRows, | ||
_inputRef = _props.inputRef, | ||
props = _objectWithoutProperties(_props, ['valueLink', 'minRows', 'maxRows', 'onHeightChange', 'useCacheForDOMMeasurements', 'inputRef']); | ||
props = _objectWithoutProperties(_props, ['minRows', 'maxRows', 'onHeightChange', 'useCacheForDOMMeasurements', 'inputRef']); | ||
if ((typeof valueLink === 'undefined' ? 'undefined' : _typeof(valueLink)) === 'object') { | ||
props.value = valueLink.value; | ||
} | ||
props.style = _extends({}, props.style, { | ||
@@ -134,3 +132,2 @@ height: this.state.height | ||
TextareaAutosize.prototype.componentWillReceiveProps = function componentWillReceiveProps() { | ||
// Re-render with the new content then recalculate the height as required. | ||
this._clearNextFrame(); | ||
@@ -141,5 +138,4 @@ this._onNextFrameActionId = onNextFrame(this._resizeComponent); | ||
TextareaAutosize.prototype.componentDidUpdate = function componentDidUpdate(prevProps, prevState) { | ||
// Invoke callback when old height does not equal to new one. | ||
if (this.state.height !== prevState.height) { | ||
this.props.onHeightChange(this.state.height); | ||
this.props.onHeightChange(this.state.height, this); | ||
} | ||
@@ -149,86 +145,11 @@ }; | ||
TextareaAutosize.prototype.componentWillUnmount = function componentWillUnmount() { | ||
// Remove any scheduled events to prevent manipulating the node after it's | ||
// been unmounted. | ||
this._clearNextFrame(); | ||
window.removeEventListener('resize', this._resizeComponent); | ||
(0, _calculateNodeHeight2.purgeCache)(this._uid); | ||
}; | ||
TextareaAutosize.prototype._clearNextFrame = function _clearNextFrame() { | ||
if (this._onNextFrameActionId) { | ||
clearNextFrameAction(this._onNextFrameActionId); | ||
} | ||
clearNextFrameAction(this._onNextFrameActionId); | ||
}; | ||
/** | ||
* Put focus on a <textarea /> DOM element. | ||
*/ | ||
TextareaAutosize.prototype.focus = function focus() { | ||
this._rootDOMNode.focus(); | ||
}; | ||
/** | ||
* Shifts focus away from a <textarea /> DOM element. | ||
*/ | ||
TextareaAutosize.prototype.blur = function blur() { | ||
this._rootDOMNode.blur(); | ||
}; | ||
_createClass(TextareaAutosize, [{ | ||
key: 'value', | ||
/** | ||
* Read the current value of <textarea /> from DOM. | ||
*/ | ||
get: function get() { | ||
return this._rootDOMNode.value; | ||
} | ||
/** | ||
* Set the current value of <textarea /> DOM node. | ||
*/ | ||
, | ||
set: function set(val) { | ||
this._rootDOMNode.value = val; | ||
} | ||
/** | ||
* Read the current selectionStart of <textarea /> from DOM. | ||
*/ | ||
}, { | ||
key: 'selectionStart', | ||
get: function get() { | ||
return this._rootDOMNode.selectionStart; | ||
} | ||
/** | ||
* Set the current selectionStart of <textarea /> DOM node. | ||
*/ | ||
, | ||
set: function set(selectionStart) { | ||
this._rootDOMNode.selectionStart = selectionStart; | ||
} | ||
/** | ||
* Read the current selectionEnd of <textarea /> from DOM. | ||
*/ | ||
}, { | ||
key: 'selectionEnd', | ||
get: function get() { | ||
return this._rootDOMNode.selectionEnd; | ||
} | ||
/** | ||
* Set the current selectionEnd of <textarea /> DOM node. | ||
*/ | ||
, | ||
set: function set(selectionEnd) { | ||
this._rootDOMNode.selectionEnd = selectionEnd; | ||
} | ||
}]); | ||
return TextareaAutosize; | ||
@@ -238,44 +159,8 @@ }(_react2.default.Component); | ||
TextareaAutosize.propTypes = { | ||
/** | ||
* Current textarea value. | ||
*/ | ||
value: _propTypes2.default.string, | ||
/** | ||
* Callback on value change. | ||
*/ | ||
onChange: _propTypes2.default.func, | ||
/** | ||
* Callback on height changes. | ||
*/ | ||
onHeightChange: _propTypes2.default.func, | ||
/** | ||
* Try to cache DOM measurements performed by component so that we don't | ||
* touch DOM when it's not needed. | ||
* | ||
* This optimization doesn't work if we dynamically style <textarea /> | ||
* component. | ||
*/ | ||
useCacheForDOMMeasurements: _propTypes2.default.bool, | ||
/** | ||
* Minimal numbder of rows to show. | ||
*/ | ||
rows: _propTypes2.default.number, | ||
/** | ||
* Alias for `rows`. | ||
*/ | ||
minRows: _propTypes2.default.number, | ||
/** | ||
* Maximum number of rows to show. | ||
*/ | ||
maxRows: _propTypes2.default.number, | ||
/** | ||
* Allows an owner to retrieve the DOM node. | ||
*/ | ||
inputRef: _propTypes2.default.func | ||
@@ -288,18 +173,2 @@ }; | ||
}; | ||
exports.default = TextareaAutosize; | ||
function onNextFrame(cb) { | ||
if (window.requestAnimationFrame) { | ||
return window.requestAnimationFrame(cb); | ||
} | ||
return window.setTimeout(cb, 1); | ||
} | ||
function clearNextFrameAction(nextFrameId) { | ||
if (window.cancelAnimationFrame) { | ||
window.cancelAnimationFrame(nextFrameId); | ||
} else { | ||
window.clearTimeout(nextFrameId); | ||
} | ||
} | ||
exports.default = TextareaAutosize; |
{ | ||
"name": "react-textarea-autosize", | ||
"description": "textarea component for React which grows with content", | ||
"version": "4.3.2", | ||
"version": "5.0.0", | ||
"keywords": "autosize, grow, react, react-component, textarea", | ||
@@ -6,0 +6,0 @@ "repository": "andreypopp/react-textarea-autosize", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
11
44689
787