'use strict'; var React = require('react'); var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; 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 _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 inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; var slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); /** * Detect Element Resize. * https://github.com/sdecima/javascript-detect-element-resize * Sebastian Decima * * Forked from version 0.5.3; includes the following modifications: * 1) Guard against unsafe 'window' and 'document' references (to support SSR). * 2) Defer initialization code via a top-level function wrapper (to support SSR). * 3) Avoid unnecessary reflows by not measuring size for scroll events bubbling from children. * 4) Add nonce for style element. **/ // Check `document` and `window` in case of server-side rendering var windowObject = void 0; if (typeof window !== 'undefined') { windowObject = window; // eslint-disable-next-line no-restricted-globals } else if (typeof self !== 'undefined') { // eslint-disable-next-line no-restricted-globals windowObject = self; } else { windowObject = global; } var cancelFrame = null; var requestFrame = null; var TIMEOUT_DURATION = 20; var clearTimeoutFn = windowObject.clearTimeout; var setTimeoutFn = windowObject.setTimeout; var cancelAnimationFrameFn = windowObject.cancelAnimationFrame || windowObject.mozCancelAnimationFrame || windowObject.webkitCancelAnimationFrame; var requestAnimationFrameFn = windowObject.requestAnimationFrame || windowObject.mozRequestAnimationFrame || windowObject.webkitRequestAnimationFrame; if (cancelAnimationFrameFn == null || requestAnimationFrameFn == null) { // For environments that don't support animation frame, // fallback to a setTimeout based approach. cancelFrame = clearTimeoutFn; requestFrame = function requestAnimationFrameViaSetTimeout(callback) { return setTimeoutFn(callback, TIMEOUT_DURATION); }; } else { // Counter intuitively, environments that support animation frames can be trickier. // Chrome's "Throttle non-visible cross-origin iframes" flag can prevent rAFs from being called. // In this case, we should fallback to a setTimeout() implementation. cancelFrame = function cancelFrame(_ref) { var _ref2 = slicedToArray(_ref, 2), animationFrameID = _ref2[0], timeoutID = _ref2[1]; cancelAnimationFrameFn(animationFrameID); clearTimeoutFn(timeoutID); }; requestFrame = function requestAnimationFrameWithSetTimeoutFallback(callback) { var animationFrameID = requestAnimationFrameFn(function animationFrameCallback() { clearTimeoutFn(timeoutID); callback(); }); var timeoutID = setTimeoutFn(function timeoutCallback() { cancelAnimationFrameFn(animationFrameID); callback(); }, TIMEOUT_DURATION); return [animationFrameID, timeoutID]; }; } function createDetectElementResize(nonce) { var animationKeyframes = void 0; var animationName = void 0; var animationStartEvent = void 0; var animationStyle = void 0; var checkTriggers = void 0; var resetTriggers = void 0; var scrollListener = void 0; var attachEvent = typeof document !== 'undefined' && document.attachEvent; if (!attachEvent) { resetTriggers = function resetTriggers(element) { var triggers = element.__resizeTriggers__, expand = triggers.firstElementChild, contract = triggers.lastElementChild, expandChild = expand.firstElementChild; contract.scrollLeft = contract.scrollWidth; contract.scrollTop = contract.scrollHeight; expandChild.style.width = expand.offsetWidth + 1 + 'px'; expandChild.style.height = expand.offsetHeight + 1 + 'px'; expand.scrollLeft = expand.scrollWidth; expand.scrollTop = expand.scrollHeight; }; checkTriggers = function checkTriggers(element) { return element.offsetWidth !== element.__resizeLast__.width || element.offsetHeight !== element.__resizeLast__.height; }; scrollListener = function scrollListener(e) { // Don't measure (which forces) reflow for scrolls that happen inside of children! if (e.target.className && typeof e.target.className.indexOf === 'function' && e.target.className.indexOf('contract-trigger') < 0 && e.target.className.indexOf('expand-trigger') < 0) { return; } var element = this; resetTriggers(this); if (this.__resizeRAF__) { cancelFrame(this.__resizeRAF__); } this.__resizeRAF__ = requestFrame(function animationFrame() { if (checkTriggers(element)) { element.__resizeLast__.width = element.offsetWidth; element.__resizeLast__.height = element.offsetHeight; element.__resizeListeners__.forEach(function forEachResizeListener(fn) { fn.call(element, e); }); } }); }; /* Detect CSS Animations support to detect element display/re-attach */ var animation = false; var keyframeprefix = ''; animationStartEvent = 'animationstart'; var domPrefixes = 'Webkit Moz O ms'.split(' '); var startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '); var pfx = ''; { var elm = document.createElement('fakeelement'); if (elm.style.animationName !== undefined) { animation = true; } if (animation === false) { for (var i = 0; i < domPrefixes.length; i++) { if (elm.style[domPrefixes[i] + 'AnimationName'] !== undefined) { pfx = domPrefixes[i]; keyframeprefix = '-' + pfx.toLowerCase() + '-'; animationStartEvent = startEvents[i]; animation = true; break; } } } } animationName = 'resizeanim'; animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } '; animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; '; } var createStyles = function createStyles(doc) { if (!doc.getElementById('detectElementResize')) { //opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360 var css = (animationKeyframes ? animationKeyframes : '') + '.resize-triggers { ' + (animationStyle ? animationStyle : '') + 'visibility: hidden; opacity: 0; } ' + '.resize-triggers, .resize-triggers > div, .contract-trigger:before { content: " "; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; z-index: -1; } .resize-triggers > div { background: #eee; overflow: auto; } .contract-trigger:before { width: 200%; height: 200%; }', head = doc.head || doc.getElementsByTagName('head')[0], style = doc.createElement('style'); style.id = 'detectElementResize'; style.type = 'text/css'; if (nonce != null) { style.setAttribute('nonce', nonce); } if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(doc.createTextNode(css)); } head.appendChild(style); } }; var addResizeListener = function addResizeListener(element, fn) { if (attachEvent) { element.attachEvent('onresize', fn); } else { if (!element.__resizeTriggers__) { var doc = element.ownerDocument; var elementStyle = windowObject.getComputedStyle(element); if (elementStyle && elementStyle.position === 'static') { element.style.position = 'relative'; } createStyles(doc); element.__resizeLast__ = {}; element.__resizeListeners__ = []; (element.__resizeTriggers__ = doc.createElement('div')).className = 'resize-triggers'; var expandTrigger = doc.createElement('div'); expandTrigger.className = 'expand-trigger'; expandTrigger.appendChild(doc.createElement('div')); var contractTrigger = doc.createElement('div'); contractTrigger.className = 'contract-trigger'; element.__resizeTriggers__.appendChild(expandTrigger); element.__resizeTriggers__.appendChild(contractTrigger); element.appendChild(element.__resizeTriggers__); resetTriggers(element); element.addEventListener('scroll', scrollListener, true); /* Listen for a css animation to detect element display/re-attach */ if (animationStartEvent) { element.__resizeTriggers__.__animationListener__ = function animationListener(e) { if (e.animationName === animationName) { resetTriggers(element); } }; element.__resizeTriggers__.addEventListener(animationStartEvent, element.__resizeTriggers__.__animationListener__); } } element.__resizeListeners__.push(fn); } }; var removeResizeListener = function removeResizeListener(element, fn) { if (attachEvent) { element.detachEvent('onresize', fn); } else { element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1); if (!element.__resizeListeners__.length) { element.removeEventListener('scroll', scrollListener, true); if (element.__resizeTriggers__.__animationListener__) { element.__resizeTriggers__.removeEventListener(animationStartEvent, element.__resizeTriggers__.__animationListener__); element.__resizeTriggers__.__animationListener__ = null; } try { element.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__); } catch (e) { // Preact compat; see developit/preact-compat/issues/228 } } } }; return { addResizeListener: addResizeListener, removeResizeListener: removeResizeListener }; } var AutoSizer = function (_React$PureComponent) { inherits(AutoSizer, _React$PureComponent); function AutoSizer() { var _ref; var _temp, _this, _ret; classCallCheck(this, AutoSizer); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = possibleConstructorReturn(this, (_ref = AutoSizer.__proto__ || Object.getPrototypeOf(AutoSizer)).call.apply(_ref, [this].concat(args))), _this), _this.state = { height: _this.props.defaultHeight || 0, width: _this.props.defaultWidth || 0 }, _this._onResize = function () { var _this$props = _this.props, disableHeight = _this$props.disableHeight, disableWidth = _this$props.disableWidth, onResize = _this$props.onResize; if (_this._parentNode) { // Guard against AutoSizer component being removed from the DOM immediately after being added. // This can result in invalid style values which can result in NaN values if we don't handle them. // See issue #150 for more context. var _height = _this._parentNode.offsetHeight || 0; var _width = _this._parentNode.offsetWidth || 0; var _style = window.getComputedStyle(_this._parentNode) || {}; var paddingLeft = parseInt(_style.paddingLeft, 10) || 0; var paddingRight = parseInt(_style.paddingRight, 10) || 0; var paddingTop = parseInt(_style.paddingTop, 10) || 0; var paddingBottom = parseInt(_style.paddingBottom, 10) || 0; var newHeight = _height - paddingTop - paddingBottom; var newWidth = _width - paddingLeft - paddingRight; if (!disableHeight && _this.state.height !== newHeight || !disableWidth && _this.state.width !== newWidth) { _this.setState({ height: _height - paddingTop - paddingBottom, width: _width - paddingLeft - paddingRight }); onResize({ height: _height, width: _width }); } } }, _this._setRef = function (autoSizer) { _this._autoSizer = autoSizer; }, _temp), possibleConstructorReturn(_this, _ret); } createClass(AutoSizer, [{ key: 'componentDidMount', value: function componentDidMount() { var nonce = this.props.nonce; if (this._autoSizer && this._autoSizer.parentNode && this._autoSizer.parentNode.ownerDocument && this._autoSizer.parentNode.ownerDocument.defaultView && this._autoSizer.parentNode instanceof this._autoSizer.parentNode.ownerDocument.defaultView.HTMLElement) { // Delay access of parentNode until mount. // This handles edge-cases where the component has already been unmounted before its ref has been set, // As well as libraries like react-lite which have a slightly different lifecycle. this._parentNode = this._autoSizer.parentNode; // Defer requiring resize handler in order to support server-side rendering. // See issue #41 this._detectElementResize = createDetectElementResize(nonce); this._detectElementResize.addResizeListener(this._parentNode, this._onResize); this._onResize(); } } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { if (this._detectElementResize && this._parentNode) { this._detectElementResize.removeResizeListener(this._parentNode, this._onResize); } } }, { key: 'render', value: function render() { var _props = this.props, children = _props.children, className = _props.className, disableHeight = _props.disableHeight, disableWidth = _props.disableWidth, style = _props.style; var _state = this.state, height = _state.height, width = _state.width; // Outer div should not force width/height since that may prevent containers from shrinking. // Inner component should overflow and use calculated width/height. // See issue #68 for more information. var outerStyle = { overflow: 'visible' }; var childParams = {}; // Avoid rendering children before the initial measurements have been collected. // At best this would just be wasting cycles. var bailoutOnChildren = false; if (!disableHeight) { if (height === 0) { bailoutOnChildren = true; } outerStyle.height = 0; childParams.height = height; } if (!disableWidth) { if (width === 0) { bailoutOnChildren = true; } outerStyle.width = 0; childParams.width = width; } return React.createElement( 'div', { className: className, ref: this._setRef, style: _extends({}, outerStyle, style) }, !bailoutOnChildren && children(childParams) ); } }]); return AutoSizer; }(React.PureComponent); AutoSizer.defaultProps = { onResize: function onResize() {}, disableHeight: false, disableWidth: false, style: {} }; module.exports = AutoSizer;