react-measure
Advanced tools
Comparing version 0.3.5 to 0.4.0
{ | ||
"name": "react-measure", | ||
"version": "0.3.5", | ||
"version": "0.4.0", | ||
"homepage": "https://github.com/souporserious/react-measure", | ||
@@ -15,3 +15,6 @@ "authors": [ | ||
"measurements", | ||
"dimensions" | ||
"dimensions", | ||
"element-queries", | ||
"container-queries", | ||
"size" | ||
], | ||
@@ -18,0 +21,0 @@ "license": "MIT", |
## CHANGELOG | ||
### 0.4.0 | ||
Moved away from MutationObserver's in favor of [element-resize-detector](https://github.com/wnr/element-resize-detector) | ||
Added a more convenient API by allowing child functions [#11](https://github.com/souporserious/react-measure/issues/11) | ||
`measure` is now a public method available on the Measure component | ||
`accurate` prop now returns both cloned element width and height | ||
`shouldMeasure` now accepts only a boolean | ||
Removed `lodash.debounce` dependency | ||
### 0.3.5 | ||
@@ -3,0 +18,0 @@ |
(function webpackUniversalModuleDefinition(root, factory) { | ||
if(typeof exports === 'object' && typeof module === 'object') | ||
module.exports = factory(require("React"), require("ReactDOM")); | ||
module.exports = factory(require("React"), require("ReactDOM"), require("createResizeDetector")); | ||
else if(typeof define === 'function' && define.amd) | ||
define(["React", "ReactDOM"], factory); | ||
define(["React", "ReactDOM", "createResizeDetector"], factory); | ||
else if(typeof exports === 'object') | ||
exports["Measure"] = factory(require("React"), require("ReactDOM")); | ||
exports["Measure"] = factory(require("React"), require("ReactDOM"), require("createResizeDetector")); | ||
else | ||
root["Measure"] = factory(root["React"], root["ReactDOM"]); | ||
})(this, function(__WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_3__) { | ||
root["Measure"] = factory(root["React"], root["ReactDOM"], root["createResizeDetector"]); | ||
})(this, function(__WEBPACK_EXTERNAL_MODULE_2__, __WEBPACK_EXTERNAL_MODULE_3__, __WEBPACK_EXTERNAL_MODULE_5__) { | ||
return /******/ (function(modules) { // webpackBootstrap | ||
@@ -84,3 +84,3 @@ /******/ // The module cache | ||
var _get = function get(_x3, _x4, _x5) { var _again = true; _function: while (_again) { var object = _x3, property = _x4, receiver = _x5; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x3 = parent; _x4 = property; _x5 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
var _get = function get(_x4, _x5, _x6) { var _again = true; _function: while (_again) { var object = _x4, property = _x5, receiver = _x6; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x4 = parent; _x5 = property; _x6 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
@@ -101,16 +101,10 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _ResizeHandler = __webpack_require__(4); | ||
var _resizeDetector = __webpack_require__(4); | ||
var _ResizeHandler2 = _interopRequireDefault(_ResizeHandler); | ||
var _resizeDetector2 = _interopRequireDefault(_resizeDetector); | ||
var _diffConfig = __webpack_require__(7); | ||
var _getNodeDimensions = __webpack_require__(6); | ||
var _diffConfig2 = _interopRequireDefault(_diffConfig); | ||
var _getNodeDimensions = __webpack_require__(8); | ||
var _getNodeDimensions2 = _interopRequireDefault(_getNodeDimensions); | ||
var resizeHandler = new _ResizeHandler2['default'](); | ||
var Measure = (function (_Component) { | ||
@@ -126,23 +120,29 @@ _inherits(Measure, _Component); | ||
this._observer = null; | ||
this.state = { | ||
dimensions: {} | ||
}; | ||
this._node = null; | ||
this._properties = this._getProperties(this.props); | ||
this._propsToMeasure = this._getPropsToMeasure(this.props); | ||
this._lastDimensions = {}; | ||
this._measure = function (mutations) { | ||
var shouldMeasure = _this.props.shouldMeasure(mutations); | ||
this.measure = function () { | ||
var accurate = arguments.length <= 0 || arguments[0] === undefined ? _this.props.accurate : arguments[0]; | ||
// bail out if we shouldn't measure | ||
if (!shouldMeasure) return; | ||
if (!_this.props.shouldMeasure) return; | ||
var dimensions = _this.getDimensions(_this._node, _this.props.accurate); | ||
var dimensions = _this.getDimensions(_this._node, accurate); | ||
var isChildFunction = typeof _this.props.children === 'function'; | ||
// determine if we need to update our callback with new dimensions or not | ||
_this._properties.some(function (prop) { | ||
_this._propsToMeasure.some(function (prop) { | ||
if (dimensions[prop] !== _this._lastDimensions[prop]) { | ||
// if we've found a dimension that has changed, update our callback | ||
// we also allow shouldMeasure to return any values so the end user | ||
// doesn't have to recalculate anything | ||
_this.props.onMeasure(dimensions, mutations, shouldMeasure); | ||
// update our callback if we've found a dimension that has changed | ||
_this.props.onMeasure(dimensions); | ||
// update state to send dimensions to child function | ||
if (isChildFunction) { | ||
_this.setState({ dimensions: dimensions }); | ||
} | ||
// store last dimensions to compare changes | ||
@@ -161,12 +161,13 @@ _this._lastDimensions = dimensions; | ||
value: function componentDidMount() { | ||
var _this2 = this; | ||
this._node = _reactDom2['default'].findDOMNode(this); | ||
// set up mutation observer | ||
this._connectObserver(this.props.config); | ||
// measure on first render | ||
this._measure(null); | ||
this.measure(); | ||
// add component to resize handler to detect changes on resize | ||
resizeHandler.add(this); | ||
// add component to resize detector to detect changes on resize | ||
(0, _resizeDetector2['default'])().listenTo(this._node, function () { | ||
return _this2.measure(); | ||
}); | ||
} | ||
@@ -180,12 +181,6 @@ }, { | ||
// disconnect the old observer and reconnect with new config if changed | ||
if ((0, _diffConfig2['default'])(this.props.config, config)) { | ||
this._disconnectObserver(); | ||
this._connectObserver(config); | ||
} | ||
// we store the properties ourselves so we need to update them if the | ||
// whitelist or blacklist props have changed | ||
if (this.props.whitelist !== whitelist || this.props.blacklist !== blacklist) { | ||
this._properties = this._getProperties({ whitelist: whitelist, blacklist: blacklist }); | ||
this._propsToMeasure = this._getPropsToMeasure({ whitelist: whitelist, blacklist: blacklist }); | ||
} | ||
@@ -196,4 +191,3 @@ } | ||
value: function componentWillUnmount() { | ||
this._disconnectObserver(); | ||
resizeHandler.remove(this); | ||
(0, _resizeDetector2['default'])().removeAllListeners(this._node); | ||
} | ||
@@ -209,15 +203,4 @@ }, { | ||
}, { | ||
key: '_connectObserver', | ||
value: function _connectObserver(config) { | ||
this._observer = new MutationObserver(this._measure); | ||
this._observer.observe(this._node, config); | ||
} | ||
}, { | ||
key: '_disconnectObserver', | ||
value: function _disconnectObserver() { | ||
this._observer.disconnect(); | ||
} | ||
}, { | ||
key: '_getProperties', | ||
value: function _getProperties(_ref2) { | ||
key: '_getPropsToMeasure', | ||
value: function _getPropsToMeasure(_ref2) { | ||
var whitelist = _ref2.whitelist; | ||
@@ -233,3 +216,5 @@ var blacklist = _ref2.blacklist; | ||
value: function render() { | ||
return _react.Children.only(this.props.children); | ||
var children = this.props.children; | ||
return _react.Children.only(typeof children === 'function' ? children(this.state.dimensions) : children); | ||
} | ||
@@ -239,7 +224,6 @@ }], [{ | ||
value: { | ||
config: _react.PropTypes.object, | ||
accurate: _react.PropTypes.bool, | ||
whitelist: _react.PropTypes.array, | ||
blacklist: _react.PropTypes.array, | ||
shouldMeasure: _react.PropTypes.func, | ||
shouldMeasure: _react.PropTypes.bool, | ||
onMeasure: _react.PropTypes.func | ||
@@ -251,12 +235,6 @@ }, | ||
value: { | ||
config: { | ||
childList: true, | ||
attributes: true | ||
}, | ||
accurate: false, | ||
whitelist: ['width', 'height', 'top', 'right', 'bottom', 'left'], | ||
blacklist: [], | ||
shouldMeasure: function shouldMeasure() { | ||
return true; | ||
}, | ||
shouldMeasure: true, | ||
onMeasure: function onMeasure() { | ||
@@ -296,57 +274,21 @@ return null; | ||
}); | ||
exports['default'] = resizeDetector; | ||
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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
var _elementResizeDetector = __webpack_require__(5); | ||
var _lodashDebounce = __webpack_require__(5); | ||
var _elementResizeDetector2 = _interopRequireDefault(_elementResizeDetector); | ||
var _lodashDebounce2 = _interopRequireDefault(_lodashDebounce); | ||
var instance = null; | ||
var ResizeHandler = (function () { | ||
function ResizeHandler() { | ||
_classCallCheck(this, ResizeHandler); | ||
this._queue = []; | ||
this.update = (0, _lodashDebounce2['default'])(this.update.bind(this), 150); | ||
if (typeof window !== 'undefined') { | ||
window.addEventListener('resize', this.update); | ||
} | ||
function resizeDetector() { | ||
if (!instance) { | ||
instance = (0, _elementResizeDetector2['default'])({ | ||
strategy: 'scroll' | ||
}); | ||
} | ||
return instance; | ||
} | ||
_createClass(ResizeHandler, [{ | ||
key: 'destroy', | ||
value: function destroy() { | ||
if (typeof window !== 'undefined') { | ||
window.removeEventListener('resize', this.update); | ||
} | ||
} | ||
}, { | ||
key: 'add', | ||
value: function add(component) { | ||
this._queue.push(component); | ||
} | ||
}, { | ||
key: 'remove', | ||
value: function remove(component) { | ||
var pos = this._queue.indexOf(component); | ||
if (pos > -1) { | ||
this._queue.splice(pos, 1); | ||
} | ||
} | ||
}, { | ||
key: 'update', | ||
value: function update() { | ||
for (var i = this._queue.length; i--;) { | ||
this._queue[i]._measure(); | ||
} | ||
} | ||
}]); | ||
return ResizeHandler; | ||
})(); | ||
exports['default'] = ResizeHandler; | ||
module.exports = exports['default']; | ||
@@ -356,419 +298,8 @@ | ||
/* 5 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
/***/ function(module, exports) { | ||
/** | ||
* lodash 3.1.1 (Custom Build) <https://lodash.com/> | ||
* Build: `lodash modern modularize exports="npm" -o ./` | ||
* Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/> | ||
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> | ||
* Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors | ||
* Available under MIT license <https://lodash.com/license> | ||
*/ | ||
'use strict'; | ||
module.exports = __WEBPACK_EXTERNAL_MODULE_5__; | ||
var getNative = __webpack_require__(6); | ||
/** Used as the `TypeError` message for "Functions" methods. */ | ||
var FUNC_ERROR_TEXT = 'Expected a function'; | ||
/* Native method references for those with the same name as other `lodash` methods. */ | ||
var nativeMax = Math.max, | ||
nativeNow = getNative(Date, 'now'); | ||
/** | ||
* Gets the number of milliseconds that have elapsed since the Unix epoch | ||
* (1 January 1970 00:00:00 UTC). | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @category Date | ||
* @example | ||
* | ||
* _.defer(function(stamp) { | ||
* console.log(_.now() - stamp); | ||
* }, _.now()); | ||
* // => logs the number of milliseconds it took for the deferred function to be invoked | ||
*/ | ||
var now = nativeNow || function () { | ||
return new Date().getTime(); | ||
}; | ||
/** | ||
* Creates a debounced function that delays invoking `func` until after `wait` | ||
* milliseconds have elapsed since the last time the debounced function was | ||
* invoked. The debounced function comes with a `cancel` method to cancel | ||
* delayed invocations. Provide an options object to indicate that `func` | ||
* should be invoked on the leading and/or trailing edge of the `wait` timeout. | ||
* Subsequent calls to the debounced function return the result of the last | ||
* `func` invocation. | ||
* | ||
* **Note:** If `leading` and `trailing` options are `true`, `func` is invoked | ||
* on the trailing edge of the timeout only if the the debounced function is | ||
* invoked more than once during the `wait` timeout. | ||
* | ||
* See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) | ||
* for details over the differences between `_.debounce` and `_.throttle`. | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @category Function | ||
* @param {Function} func The function to debounce. | ||
* @param {number} [wait=0] The number of milliseconds to delay. | ||
* @param {Object} [options] The options object. | ||
* @param {boolean} [options.leading=false] Specify invoking on the leading | ||
* edge of the timeout. | ||
* @param {number} [options.maxWait] The maximum time `func` is allowed to be | ||
* delayed before it is invoked. | ||
* @param {boolean} [options.trailing=true] Specify invoking on the trailing | ||
* edge of the timeout. | ||
* @returns {Function} Returns the new debounced function. | ||
* @example | ||
* | ||
* // avoid costly calculations while the window size is in flux | ||
* jQuery(window).on('resize', _.debounce(calculateLayout, 150)); | ||
* | ||
* // invoke `sendMail` when the click event is fired, debouncing subsequent calls | ||
* jQuery('#postbox').on('click', _.debounce(sendMail, 300, { | ||
* 'leading': true, | ||
* 'trailing': false | ||
* })); | ||
* | ||
* // ensure `batchLog` is invoked once after 1 second of debounced calls | ||
* var source = new EventSource('/stream'); | ||
* jQuery(source).on('message', _.debounce(batchLog, 250, { | ||
* 'maxWait': 1000 | ||
* })); | ||
* | ||
* // cancel a debounced call | ||
* var todoChanges = _.debounce(batchLog, 1000); | ||
* Object.observe(models.todo, todoChanges); | ||
* | ||
* Object.observe(models, function(changes) { | ||
* if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) { | ||
* todoChanges.cancel(); | ||
* } | ||
* }, ['delete']); | ||
* | ||
* // ...at some point `models.todo` is changed | ||
* models.todo.completed = true; | ||
* | ||
* // ...before 1 second has passed `models.todo` is deleted | ||
* // which cancels the debounced `todoChanges` call | ||
* delete models.todo; | ||
*/ | ||
function debounce(func, wait, options) { | ||
var args, | ||
maxTimeoutId, | ||
result, | ||
stamp, | ||
thisArg, | ||
timeoutId, | ||
trailingCall, | ||
lastCalled = 0, | ||
maxWait = false, | ||
trailing = true; | ||
if (typeof func != 'function') { | ||
throw new TypeError(FUNC_ERROR_TEXT); | ||
} | ||
wait = wait < 0 ? 0 : +wait || 0; | ||
if (options === true) { | ||
var leading = true; | ||
trailing = false; | ||
} else if (isObject(options)) { | ||
leading = !!options.leading; | ||
maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); | ||
trailing = 'trailing' in options ? !!options.trailing : trailing; | ||
} | ||
function cancel() { | ||
if (timeoutId) { | ||
clearTimeout(timeoutId); | ||
} | ||
if (maxTimeoutId) { | ||
clearTimeout(maxTimeoutId); | ||
} | ||
lastCalled = 0; | ||
maxTimeoutId = timeoutId = trailingCall = undefined; | ||
} | ||
function complete(isCalled, id) { | ||
if (id) { | ||
clearTimeout(id); | ||
} | ||
maxTimeoutId = timeoutId = trailingCall = undefined; | ||
if (isCalled) { | ||
lastCalled = now(); | ||
result = func.apply(thisArg, args); | ||
if (!timeoutId && !maxTimeoutId) { | ||
args = thisArg = undefined; | ||
} | ||
} | ||
} | ||
function delayed() { | ||
var remaining = wait - (now() - stamp); | ||
if (remaining <= 0 || remaining > wait) { | ||
complete(trailingCall, maxTimeoutId); | ||
} else { | ||
timeoutId = setTimeout(delayed, remaining); | ||
} | ||
} | ||
function maxDelayed() { | ||
complete(trailing, timeoutId); | ||
} | ||
function debounced() { | ||
args = arguments; | ||
stamp = now(); | ||
thisArg = this; | ||
trailingCall = trailing && (timeoutId || !leading); | ||
if (maxWait === false) { | ||
var leadingCall = leading && !timeoutId; | ||
} else { | ||
if (!maxTimeoutId && !leading) { | ||
lastCalled = stamp; | ||
} | ||
var remaining = maxWait - (stamp - lastCalled), | ||
isCalled = remaining <= 0 || remaining > maxWait; | ||
if (isCalled) { | ||
if (maxTimeoutId) { | ||
maxTimeoutId = clearTimeout(maxTimeoutId); | ||
} | ||
lastCalled = stamp; | ||
result = func.apply(thisArg, args); | ||
} else if (!maxTimeoutId) { | ||
maxTimeoutId = setTimeout(maxDelayed, remaining); | ||
} | ||
} | ||
if (isCalled && timeoutId) { | ||
timeoutId = clearTimeout(timeoutId); | ||
} else if (!timeoutId && wait !== maxWait) { | ||
timeoutId = setTimeout(delayed, wait); | ||
} | ||
if (leadingCall) { | ||
isCalled = true; | ||
result = func.apply(thisArg, args); | ||
} | ||
if (isCalled && !timeoutId && !maxTimeoutId) { | ||
args = thisArg = undefined; | ||
} | ||
return result; | ||
} | ||
debounced.cancel = cancel; | ||
return debounced; | ||
} | ||
/** | ||
* Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. | ||
* (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @category Lang | ||
* @param {*} value The value to check. | ||
* @returns {boolean} Returns `true` if `value` is an object, else `false`. | ||
* @example | ||
* | ||
* _.isObject({}); | ||
* // => true | ||
* | ||
* _.isObject([1, 2, 3]); | ||
* // => true | ||
* | ||
* _.isObject(1); | ||
* // => false | ||
*/ | ||
function isObject(value) { | ||
// Avoid a V8 JIT bug in Chrome 19-20. | ||
// See https://code.google.com/p/v8/issues/detail?id=2291 for more details. | ||
var type = typeof value; | ||
return !!value && (type == 'object' || type == 'function'); | ||
} | ||
module.exports = debounce; | ||
/***/ }, | ||
/* 6 */ | ||
/***/ function(module, exports) { | ||
/** | ||
* lodash 3.9.1 (Custom Build) <https://lodash.com/> | ||
* Build: `lodash modern modularize exports="npm" -o ./` | ||
* Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/> | ||
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> | ||
* Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors | ||
* Available under MIT license <https://lodash.com/license> | ||
*/ | ||
/** `Object#toString` result references. */ | ||
'use strict'; | ||
var funcTag = '[object Function]'; | ||
/** Used to detect host constructors (Safari > 5). */ | ||
var reIsHostCtor = /^\[object .+?Constructor\]$/; | ||
/** | ||
* Checks if `value` is object-like. | ||
* | ||
* @private | ||
* @param {*} value The value to check. | ||
* @returns {boolean} Returns `true` if `value` is object-like, else `false`. | ||
*/ | ||
function isObjectLike(value) { | ||
return !!value && typeof value == 'object'; | ||
} | ||
/** Used for native method references. */ | ||
var objectProto = Object.prototype; | ||
/** Used to resolve the decompiled source of functions. */ | ||
var fnToString = Function.prototype.toString; | ||
/** Used to check objects for own properties. */ | ||
var hasOwnProperty = objectProto.hasOwnProperty; | ||
/** | ||
* Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) | ||
* of values. | ||
*/ | ||
var objToString = objectProto.toString; | ||
/** Used to detect if a method is native. */ | ||
var reIsNative = RegExp('^' + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&').replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'); | ||
/** | ||
* Gets the native function at `key` of `object`. | ||
* | ||
* @private | ||
* @param {Object} object The object to query. | ||
* @param {string} key The key of the method to get. | ||
* @returns {*} Returns the function if it's native, else `undefined`. | ||
*/ | ||
function getNative(object, key) { | ||
var value = object == null ? undefined : object[key]; | ||
return isNative(value) ? value : undefined; | ||
} | ||
/** | ||
* Checks if `value` is classified as a `Function` object. | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @category Lang | ||
* @param {*} value The value to check. | ||
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. | ||
* @example | ||
* | ||
* _.isFunction(_); | ||
* // => true | ||
* | ||
* _.isFunction(/abc/); | ||
* // => false | ||
*/ | ||
function isFunction(value) { | ||
// The use of `Object#toString` avoids issues with the `typeof` operator | ||
// in older versions of Chrome and Safari which return 'function' for regexes | ||
// and Safari 8 equivalents which return 'object' for typed array constructors. | ||
return isObject(value) && objToString.call(value) == funcTag; | ||
} | ||
/** | ||
* Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. | ||
* (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @category Lang | ||
* @param {*} value The value to check. | ||
* @returns {boolean} Returns `true` if `value` is an object, else `false`. | ||
* @example | ||
* | ||
* _.isObject({}); | ||
* // => true | ||
* | ||
* _.isObject([1, 2, 3]); | ||
* // => true | ||
* | ||
* _.isObject(1); | ||
* // => false | ||
*/ | ||
function isObject(value) { | ||
// Avoid a V8 JIT bug in Chrome 19-20. | ||
// See https://code.google.com/p/v8/issues/detail?id=2291 for more details. | ||
var type = typeof value; | ||
return !!value && (type == 'object' || type == 'function'); | ||
} | ||
/** | ||
* Checks if `value` is a native function. | ||
* | ||
* @static | ||
* @memberOf _ | ||
* @category Lang | ||
* @param {*} value The value to check. | ||
* @returns {boolean} Returns `true` if `value` is a native function, else `false`. | ||
* @example | ||
* | ||
* _.isNative(Array.prototype.push); | ||
* // => true | ||
* | ||
* _.isNative(_); | ||
* // => false | ||
*/ | ||
function isNative(value) { | ||
if (value == null) { | ||
return false; | ||
} | ||
if (isFunction(value)) { | ||
return reIsNative.test(fnToString.call(value)); | ||
} | ||
return isObjectLike(value) && reIsHostCtor.test(value); | ||
} | ||
module.exports = getNative; | ||
/***/ }, | ||
/* 7 */ | ||
/***/ function(module, exports) { | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
exports['default'] = diffConfig; | ||
var CONFIG_SHAPE = ['childList', 'attributes', 'characterData', 'subtree', 'attributeOldValue', 'characterDataOldValue', 'attributeFilter']; | ||
function diffConfig(prev, next) { | ||
for (var i = 7; i--;) { | ||
var config = CONFIG_SHAPE[i]; | ||
var prevConfig = prev[config]; | ||
var nextConfig = next[config]; | ||
// if equal continue to the next | ||
if (prevConfig === nextConfig) { | ||
continue; | ||
} | ||
var prevUndefined = typeof prevConfig === 'undefined'; | ||
var nextUndefined = typeof nextConfig === 'undefined'; | ||
// if attributeFilter, we know it needs to be a simple array, | ||
// so comparing lengths should be enough to know if it has changed | ||
if (prevUndefined && !nextUndefined || !prevUndefined && nextUndefined || config === 'attributeFilter' && prevConfig.length !== nextConfig.length) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
module.exports = exports['default']; | ||
/***/ }, | ||
/* 8 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
@@ -785,5 +316,5 @@ | ||
var _accurateHeight = __webpack_require__(9); | ||
var _getCloneDimensions = __webpack_require__(7); | ||
var _accurateHeight2 = _interopRequireDefault(_accurateHeight); | ||
var _getCloneDimensions2 = _interopRequireDefault(_getCloneDimensions); | ||
@@ -794,6 +325,14 @@ function getNodeDimensions(node) { | ||
var rect = node.getBoundingClientRect(); | ||
var width = rect.width; | ||
var height = rect.height; | ||
if (accurate) { | ||
var cloneDimensions = (0, _getCloneDimensions2['default'])(node); | ||
width = cloneDimensions.width; | ||
height = cloneDimensions.height; | ||
} | ||
return { | ||
width: rect.width, | ||
height: accurate ? (0, _accurateHeight2['default'])(node) : rect.height, | ||
width: width, | ||
height: height, | ||
top: rect.top, | ||
@@ -809,60 +348,5 @@ right: rect.right, | ||
/***/ }, | ||
/* 9 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
exports['default'] = accurateHeight; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _dataStore = __webpack_require__(10); | ||
var _dataStore2 = _interopRequireDefault(_dataStore); | ||
var _getCloneHeight = __webpack_require__(11); | ||
var _getCloneHeight2 = _interopRequireDefault(_getCloneHeight); | ||
function getStyle(node) { | ||
return (0, _dataStore2['default'])(node, 'style') || (0, _dataStore2['default'])(node, 'style', getComputedStyle(node)); | ||
} | ||
// inspired by http://stackoverflow.com/a/8235013/1461204 | ||
function accurateHeight(node) { | ||
var children = node.children; | ||
// if no children present on the node or an SVG element | ||
// we need to clone it to get a true height | ||
if (!children || children && children.length === 0 || node instanceof SVGElement) { | ||
return (0, _getCloneHeight2['default'])(node); | ||
} | ||
var firstChild = children[0]; | ||
var lastChild = children[children.length - 1]; | ||
var _getStyle = getStyle(firstChild); | ||
var marginTop = _getStyle.marginTop; | ||
var _getStyle2 = getStyle(lastChild); | ||
var marginBottom = _getStyle2.marginBottom; | ||
var offsetDiff = lastChild.offsetTop - firstChild.offsetTop; | ||
return parseInt(marginTop) + (offsetDiff + lastChild.offsetHeight) + parseInt(marginBottom); | ||
} | ||
module.exports = exports['default']; | ||
/***/ }, | ||
/* 10 */ | ||
/* 7 */ | ||
/***/ function(module, exports) { | ||
// inspired by https://github.com/julianshapiro/velocity/blob/master/velocity.js | ||
'use strict'; | ||
@@ -873,43 +357,5 @@ | ||
}); | ||
exports['default'] = dataStore; | ||
var expando = 'react-measure' + new Date().getTime(); | ||
var cache = {}; | ||
var uuid = 0; | ||
exports['default'] = getCloneDimensions; | ||
function dataStore(node, key, value) { | ||
if (value === undefined) { | ||
var id = node[expando]; | ||
var store = id && cache[id]; | ||
if (key === undefined) { | ||
return store; | ||
} else if (store) { | ||
if (key in store) { | ||
return store[key]; | ||
} | ||
} | ||
} else if (key !== undefined) { | ||
var id = node[expando] || (node[expando] = ++uuid); | ||
cache[id] = cache[id] || {}; | ||
cache[id][key] = value; | ||
return value; | ||
} | ||
} | ||
module.exports = exports['default']; | ||
/***/ }, | ||
/* 11 */ | ||
/***/ function(module, exports) { | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
exports['default'] = getCloneHeight; | ||
function getCloneHeight(node) { | ||
function getCloneDimensions(node) { | ||
var parentNode = node.parentNode; | ||
@@ -919,2 +365,3 @@ | ||
var clone = node.cloneNode(true); | ||
var width = 0; | ||
var height = 0; | ||
@@ -931,6 +378,4 @@ | ||
clone.setAttribute('name', ''); | ||
clone.setAttribute('data-reactid', ''); | ||
// set props to hide copy and get a true height calculation | ||
clone.style.boxSizing = 'border-box'; | ||
clone.style.height = 'auto'; | ||
@@ -946,3 +391,4 @@ clone.style.position = 'absolute'; | ||
// get height | ||
// get accurate width and height | ||
width = clone.scrollWidth; | ||
height = clone.scrollHeight; | ||
@@ -953,3 +399,3 @@ | ||
return height; | ||
return { width: width, height: height }; | ||
} | ||
@@ -956,0 +402,0 @@ |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("React"),require("ReactDOM")):"function"==typeof define&&define.amd?define(["React","ReactDOM"],t):"object"==typeof exports?exports.Measure=t(require("React"),require("ReactDOM")):e.Measure=t(e.React,e.ReactDOM)}(this,function(e,t){return function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="dist/",t(0)}([function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(t,"__esModule",{value:!0});var o=n(1),i=r(o);t["default"]=i["default"],e.exports=t["default"]},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(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)}Object.defineProperty(t,"__esModule",{value:!0});var u=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e,t,n){for(var r=!0;r;){var o=e,i=t,u=n;a=l=s=void 0,r=!1,null===o&&(o=Function.prototype);var a=Object.getOwnPropertyDescriptor(o,i);if(void 0!==a){if("value"in a)return a.value;var s=a.get;return void 0===s?void 0:s.call(u)}var l=Object.getPrototypeOf(o);if(null===l)return void 0;e=l,t=i,n=u,r=!0}},s=n(2),l=(r(s),n(3)),c=r(l),f=n(4),p=r(f),d=n(7),v=r(d),h=n(8),y=r(h),b=new p["default"],Measure=function(e){function Measure(){var e=this;o(this,Measure),a(Object.getPrototypeOf(Measure.prototype),"constructor",this).apply(this,arguments),this._observer=null,this._node=null,this._properties=this._getProperties(this.props),this._lastDimensions={},this._measure=function(t){var n=e.props.shouldMeasure(t);if(n){var r=e.getDimensions(e._node,e.props.accurate);e._properties.some(function(o){return r[o]!==e._lastDimensions[o]?(e.props.onMeasure(r,t,n),e._lastDimensions=r,!0):void 0})}}}return i(Measure,e),u(Measure,[{key:"componentDidMount",value:function(){this._node=c["default"].findDOMNode(this),this._connectObserver(this.props.config),this._measure(null),b.add(this)}},{key:"componentWillReceiveProps",value:function(e){var t=e.config,n=e.whitelist,r=e.blacklist;v["default"](this.props.config,t)&&(this._disconnectObserver(),this._connectObserver(t)),(this.props.whitelist!==n||this.props.blacklist!==r)&&(this._properties=this._getProperties({whitelist:n,blacklist:r}))}},{key:"componentWillUnmount",value:function(){this._disconnectObserver(),b.remove(this)}},{key:"getDimensions",value:function(){var e=arguments.length<=0||void 0===arguments[0]?this._node:arguments[0],t=arguments.length<=1||void 0===arguments[1]?!0:arguments[1];return y["default"](e,t)}},{key:"_connectObserver",value:function(e){this._observer=new MutationObserver(this._measure),this._observer.observe(this._node,e)}},{key:"_disconnectObserver",value:function(){this._observer.disconnect()}},{key:"_getProperties",value:function(e){var t=e.whitelist,n=e.blacklist;return t.filter(function(e){return n.indexOf(e)<0})}},{key:"render",value:function(){return s.Children.only(this.props.children)}}],[{key:"propTypes",value:{config:s.PropTypes.object,accurate:s.PropTypes.bool,whitelist:s.PropTypes.array,blacklist:s.PropTypes.array,shouldMeasure:s.PropTypes.func,onMeasure:s.PropTypes.func},enumerable:!0},{key:"defaultProps",value:{config:{childList:!0,attributes:!0},accurate:!1,whitelist:["width","height","top","right","bottom","left"],blacklist:[],shouldMeasure:function(){return!0},onMeasure:function(){return null}},enumerable:!0}]),Measure}(s.Component);t["default"]=Measure,e.exports=t["default"]},function(t,n){t.exports=e},function(e,n){e.exports=t},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),u=n(5),a=r(u),s=function(){function e(){o(this,e),this._queue=[],this.update=a["default"](this.update.bind(this),150),"undefined"!=typeof window&&window.addEventListener("resize",this.update)}return i(e,[{key:"destroy",value:function(){"undefined"!=typeof window&&window.removeEventListener("resize",this.update)}},{key:"add",value:function(e){this._queue.push(e)}},{key:"remove",value:function(e){var t=this._queue.indexOf(e);t>-1&&this._queue.splice(t,1)}},{key:"update",value:function(){for(var e=this._queue.length;e--;)this._queue[e]._measure()}}]),e}();t["default"]=s,e.exports=t["default"]},function(e,t,n){"use strict";function r(e,t,n){function r(){b&&clearTimeout(b),d&&clearTimeout(d),g=0,d=b=m=void 0}function i(t,n){n&&clearTimeout(n),d=b=m=void 0,t&&(g=l(),v=e.apply(y,p),b||d||(p=y=void 0))}function s(){var e=t-(l()-h);0>=e||e>t?i(m,d):b=setTimeout(s,e)}function c(){i(O,b)}function f(){if(p=arguments,h=l(),y=this,m=O&&(b||!w),_===!1)var n=w&&!b;else{d||w||(g=h);var r=_-(h-g),o=0>=r||r>_;o?(d&&(d=clearTimeout(d)),g=h,v=e.apply(y,p)):d||(d=setTimeout(c,r))}return o&&b?b=clearTimeout(b):b||t===_||(b=setTimeout(s,t)),n&&(o=!0,v=e.apply(y,p)),!o||b||d||(p=y=void 0),v}var p,d,v,h,y,b,m,g=0,_=!1,O=!0;if("function"!=typeof e)throw new TypeError(u);if(t=0>t?0:+t||0,n===!0){var w=!0;O=!1}else o(n)&&(w=!!n.leading,_="maxWait"in n&&a(+n.maxWait||0,t),O="trailing"in n?!!n.trailing:O);return f.cancel=r,f}function o(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}var i=n(6),u="Expected a function",a=Math.max,s=i(Date,"now"),l=s||function(){return(new Date).getTime()};e.exports=r},function(e,t){"use strict";function n(e){return!!e&&"object"==typeof e}function r(e,t){var n=null==e?void 0:e[t];return u(n)?n:void 0}function o(e){return i(e)&&p.call(e)==a}function i(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function u(e){return null==e?!1:o(e)?d.test(c.call(e)):n(e)&&s.test(e)}var a="[object Function]",s=/^\[object .+?Constructor\]$/,l=Object.prototype,c=Function.prototype.toString,f=l.hasOwnProperty,p=l.toString,d=RegExp("^"+c.call(f).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");e.exports=r},function(e,t){"use strict";function n(e,t){for(var n=7;n--;){var o=r[n],i=e[o],u=t[o];if(i!==u){var a="undefined"==typeof i,s="undefined"==typeof u;if(a&&!s||!a&&s||"attributeFilter"===o&&i.length!==u.length)return!0}}return!1}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=n;var r=["childList","attributes","characterData","subtree","attributeOldValue","characterDataOldValue","attributeFilter"];e.exports=t["default"]},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function o(e){var t=arguments.length<=1||void 0===arguments[1]?!1:arguments[1],n=e.getBoundingClientRect();return{width:n.width,height:t?u["default"](e):n.height,top:n.top,right:n.right,bottom:n.bottom,left:n.left}}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=o;var i=n(9),u=r(i);e.exports=t["default"]},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function o(e){return a["default"](e,"style")||a["default"](e,"style",getComputedStyle(e))}function i(e){var t=e.children;if(!t||t&&0===t.length||e instanceof SVGElement)return l["default"](e);var n=t[0],r=t[t.length-1],i=o(n),u=i.marginTop,a=o(r),s=a.marginBottom,c=r.offsetTop-n.offsetTop;return parseInt(u)+(c+r.offsetHeight)+parseInt(s)}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=i;var u=n(10),a=r(u),s=n(11),l=r(s);e.exports=t["default"]},function(e,t){"use strict";function n(e,t,n){if(void 0===n){var u=e[r],a=u&&o[u];if(void 0===t)return a;if(a&&t in a)return a[t]}else if(void 0!==t){var u=e[r]||(e[r]=++i);return o[u]=o[u]||{},o[u][t]=n,n}}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=n;var r="react-measure"+(new Date).getTime(),o={},i=0;e.exports=t["default"]},function(e,t){"use strict";function n(e){var t=e.parentNode,n=document.createElement("div"),r=e.cloneNode(!0),o=0;return n.style.height=0,n.style.position="relative",n.style.overflow="hidden",r.setAttribute("id",""),r.setAttribute("name",""),r.setAttribute("data-reactid",""),r.style.boxSizing="border-box",r.style.height="auto",r.style.position="absolute",r.style.visibility="hidden",n.appendChild(r),t.appendChild(n),o=r.scrollHeight,t.removeChild(n),o}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=n,e.exports=t["default"]}])}); | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("React"),require("ReactDOM"),require("createResizeDetector")):"function"==typeof define&&define.amd?define(["React","ReactDOM","createResizeDetector"],t):"object"==typeof exports?exports.Measure=t(require("React"),require("ReactDOM"),require("createResizeDetector")):e.Measure=t(e.React,e.ReactDOM,e.createResizeDetector)}(this,function(e,t,r){return function(e){function t(o){if(r[o])return r[o].exports;var n=r[o]={exports:{},id:o,loaded:!1};return e[o].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var r={};return t.m=e,t.c=r,t.p="dist/",t(0)}([function(e,t,r){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(t,"__esModule",{value:!0});var n=r(1),i=o(n);t["default"]=i["default"],e.exports=t["default"]},function(e,t,r){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(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)}Object.defineProperty(t,"__esModule",{value:!0});var u=function(){function e(e,t){for(var r=0;r<t.length;r++){var o=t[r];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,r,o){return r&&e(t.prototype,r),o&&e(t,o),t}}(),s=function(e,t,r){for(var o=!0;o;){var n=e,i=t,u=r;s=l=a=void 0,o=!1,null===n&&(n=Function.prototype);var s=Object.getOwnPropertyDescriptor(n,i);if(void 0!==s){if("value"in s)return s.value;var a=s.get;return void 0===a?void 0:a.call(u)}var l=Object.getPrototypeOf(n);if(null===l)return void 0;e=l,t=i,r=u,o=!0}},a=r(2),l=(o(a),r(3)),c=o(l),f=r(4),p=o(f),d=r(6),h=o(d),Measure=function(e){function Measure(){var e=this;n(this,Measure),s(Object.getPrototypeOf(Measure.prototype),"constructor",this).apply(this,arguments),this.state={dimensions:{}},this._node=null,this._propsToMeasure=this._getPropsToMeasure(this.props),this._lastDimensions={},this.measure=function(){var t=arguments.length<=0||void 0===arguments[0]?e.props.accurate:arguments[0];if(e.props.shouldMeasure){var r=e.getDimensions(e._node,t),o="function"==typeof e.props.children;e._propsToMeasure.some(function(t){return r[t]!==e._lastDimensions[t]?(e.props.onMeasure(r),o&&e.setState({dimensions:r}),e._lastDimensions=r,!0):void 0})}}}return i(Measure,e),u(Measure,[{key:"componentDidMount",value:function(){var e=this;this._node=c["default"].findDOMNode(this),this.measure(),p["default"]().listenTo(this._node,function(){return e.measure()})}},{key:"componentWillReceiveProps",value:function(e){var t=(e.config,e.whitelist),r=e.blacklist;(this.props.whitelist!==t||this.props.blacklist!==r)&&(this._propsToMeasure=this._getPropsToMeasure({whitelist:t,blacklist:r}))}},{key:"componentWillUnmount",value:function(){p["default"]().removeAllListeners(this._node)}},{key:"getDimensions",value:function(){var e=arguments.length<=0||void 0===arguments[0]?this._node:arguments[0],t=arguments.length<=1||void 0===arguments[1]?!0:arguments[1];return h["default"](e,t)}},{key:"_getPropsToMeasure",value:function(e){var t=e.whitelist,r=e.blacklist;return t.filter(function(e){return r.indexOf(e)<0})}},{key:"render",value:function(){var e=this.props.children;return a.Children.only("function"==typeof e?e(this.state.dimensions):e)}}],[{key:"propTypes",value:{accurate:a.PropTypes.bool,whitelist:a.PropTypes.array,blacklist:a.PropTypes.array,shouldMeasure:a.PropTypes.bool,onMeasure:a.PropTypes.func},enumerable:!0},{key:"defaultProps",value:{accurate:!1,whitelist:["width","height","top","right","bottom","left"],blacklist:[],shouldMeasure:!0,onMeasure:function(){return null}},enumerable:!0}]),Measure}(a.Component);t["default"]=Measure,e.exports=t["default"]},function(t,r){t.exports=e},function(e,r){e.exports=t},function(e,t,r){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function n(){return s||(s=u["default"]({strategy:"scroll"})),s}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=n;var i=r(5),u=o(i),s=null;e.exports=t["default"]},function(e,t){e.exports=r},function(e,t,r){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function n(e){var t=arguments.length<=1||void 0===arguments[1]?!1:arguments[1],r=e.getBoundingClientRect(),o=r.width,n=r.height;if(t){var i=u["default"](e);o=i.width,n=i.height}return{width:o,height:n,top:r.top,right:r.right,bottom:r.bottom,left:r.left}}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=n;var i=r(7),u=o(i);e.exports=t["default"]},function(e,t){"use strict";function r(e){var t=e.parentNode,r=document.createElement("div"),o=e.cloneNode(!0),n=0,i=0;return r.style.height=0,r.style.position="relative",r.style.overflow="hidden",o.setAttribute("id",""),o.setAttribute("name",""),o.style.height="auto",o.style.position="absolute",o.style.visibility="hidden",r.appendChild(o),t.appendChild(r),n=o.scrollWidth,i=o.scrollHeight,t.removeChild(r),{width:n,height:i}}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=r,e.exports=t["default"]}])}); |
@@ -11,3 +11,4 @@ import React, { Component, Children, PropTypes } from 'react' | ||
state = { | ||
showContent: false | ||
showChildSlideable: false, | ||
showChildContent: false | ||
} | ||
@@ -21,3 +22,3 @@ | ||
const { item, style } = this.props | ||
const { showContent } = this.state | ||
const { showChildSlideable, showChildContent } = this.state | ||
@@ -30,18 +31,30 @@ return( | ||
> | ||
<div> | ||
<button | ||
onClick={e => { | ||
e.stopPropagation() | ||
this.setState({showContent: !this.state.showContent}) | ||
}} | ||
> | ||
Toggle Extra Content | ||
</button> | ||
<Slideable show={showContent}> | ||
<div style={{background: 'red'}}> | ||
<p style={{margin: 0, padding: 12}}>Just another paragraph to test out height animations.</p> | ||
<p style={{margin: 0, marginTop: 12, padding: 12}}>Just another paragraph to test out height animations.</p> | ||
</div> | ||
</Slideable> | ||
</div> | ||
<button | ||
onClick={e => { | ||
e.stopPropagation() | ||
this.setState({showChildSlideable: !showChildSlideable}) | ||
}} | ||
> | ||
Toggle Child Slideable | ||
</button> | ||
<Slideable show={showChildSlideable}> | ||
<div style={{background: 'red'}}> | ||
<p style={{margin: 0, padding: 12}}>Just another paragraph to test out height animations.</p> | ||
<p style={{margin: 0, marginTop: 12, padding: 12}}>Just another paragraph to test out height animations.</p> | ||
</div> | ||
</Slideable> | ||
<button | ||
onClick={e => { | ||
e.stopPropagation() | ||
this.setState({showChildContent: !showChildContent}) | ||
}} | ||
> | ||
Toggle Child Content | ||
</button> | ||
{ showChildContent && | ||
<div style={{background: 'orange'}}> | ||
<p style={{margin: 0, padding: 12}}>Just another paragraph to test out height animations.</p> | ||
<p style={{margin: 0, marginTop: 12, padding: 12}}>Just another paragraph to test out height animations.</p> | ||
</div> | ||
} | ||
{item.contents.map((content, i) => <p key={i}>{content}</p>)} | ||
@@ -116,3 +129,3 @@ </div> | ||
return( | ||
return ( | ||
Object.keys(dimensions).map((dimension, i) => | ||
@@ -173,2 +186,22 @@ <li key={i}>{dimension}: {dimensions[dimension]}</li> | ||
class AnimatingChild extends Component { | ||
render() { | ||
const { animate } = this.props | ||
return ( | ||
<Measure> | ||
{dimensions => | ||
<div className={`square ${animate ? 'animate' : ''}`}> | ||
<strong> | ||
{animate ? 'Click to stop animating' : 'Click to animate'} | ||
</strong> | ||
{Object.keys(dimensions).map((dimension, i) => | ||
<div key={i}>{dimension}: {dimensions[dimension]}</div> | ||
)} | ||
</div> | ||
} | ||
</Measure> | ||
) | ||
} | ||
} | ||
class App extends Component { | ||
@@ -201,3 +234,3 @@ state = { | ||
render() { | ||
const { items, active, showSVG } = this.state; | ||
const { items, active, showSVG, animate } = this.state | ||
const currentSelected = active === null ? 'Nothing selected' : items[active].title; | ||
@@ -215,2 +248,8 @@ | ||
</Slideable> | ||
<Slideable show={!showSVG}> | ||
<svg width="36px" height="36px" viewBox="0 0 36 36"> | ||
<circle fill="#373D3F" cx="18" cy="18" r="18"/> | ||
<polygon fill="#CDD7DB" points="14,11 26,18 14,25"/> | ||
</svg> | ||
</Slideable> | ||
</div> | ||
@@ -224,7 +263,10 @@ <strong>Current Selected:</strong> {currentSelected} | ||
<Paragraphs /> | ||
<div onClick={() => this.setState({ animate: !animate })}> | ||
<AnimatingChild animate={animate}/> | ||
</div> | ||
</div> | ||
); | ||
) | ||
} | ||
} | ||
ReactDOM.render(<App />, document.getElementById('app')); | ||
ReactDOM.render(<App />, document.getElementById('app')) |
@@ -1,215 +0,70 @@ | ||
import React, { Component, PropTypes, createElement } from 'react' | ||
import ReactDOM from 'react-dom' | ||
import shallowCompare from 'react-addons-shallow-compare' | ||
import React, { Component, PropTypes, Children, cloneElement } from 'react' | ||
import { findDOMNode } from 'react-dom' | ||
import { Motion, spring, presets } from 'react-motion' | ||
import Measure from '../src/react-measure' | ||
// PARENT always knows about children | ||
// should change data attribute saying it is now a child | ||
// data-slideable-child=true | ||
const stopParentSlideables = (el) => { | ||
while (el !== document.body) { | ||
el = el.parentNode | ||
const slideable = el.getAttribute('data-slideable') | ||
if (slideable && slideable !== 'stop') { | ||
el.setAttribute('data-slideable', 'stop') | ||
} | ||
class Slideable extends Component { | ||
static propTypes = { | ||
show: PropTypes.bool.isRequired, | ||
springConfig: React.PropTypes.objectOf(React.PropTypes.number), | ||
children: PropTypes.node.isRequired | ||
} | ||
} | ||
class Store { | ||
constructor() { | ||
this.slideables = {} | ||
static defaultProps = { | ||
springConfig: presets.noWobble | ||
} | ||
getSlideables() { | ||
return this.slideables | ||
} | ||
add(slideable) { | ||
} | ||
remove() { | ||
} | ||
onChange() { | ||
} | ||
} | ||
class Slideable extends Component { | ||
state = { | ||
height: -1, | ||
instant: false | ||
height: -1 | ||
} | ||
_isAnimating = false | ||
componentWillReceiveProps({show}) { | ||
// if we're toggling "show", measure and set state | ||
// so we can animate from an accurate measurement | ||
if(this.props.show !== show) { | ||
const { height } = this.refs['measure'].getDimensions() | ||
this.setState({height}) | ||
} | ||
} | ||
_instant = false | ||
_measureComponent = null | ||
_node = null | ||
shouldComponentUpdate(nextProps, nextState) { | ||
return shallowCompare(this, nextProps, nextState) | ||
} | ||
componentDidUpdate() { | ||
const { stopped, instant } = this.state | ||
if(instant) { | ||
this.setState({instant: false}) | ||
componentWillReceiveProps(nextProps) { | ||
// force measure so we can animate from an accurate measurement | ||
if (this.props.show !== nextProps.show) { | ||
this._measureComponent.measure(true) | ||
this._instant = false | ||
} | ||
} | ||
// check if any children are animating | ||
_shouldMeasure = (mutations) => { | ||
// we need to build a set of rules | ||
// the last triggered Slideable always takes precedence over any others | ||
// | ||
// it needs to notify any parents as well as children that it is animating | ||
// reasons why include | ||
// 1. if a parent is in the middle of animating it needs to notify that parent to stop | ||
// we can change a data attribute on it and it will recieve the notification | ||
// to stop | ||
// | ||
// Mock API | ||
// call methods by changing data attributes | ||
// data-slideable={['measure', 'stop', 'animateTo', 'animateFrom']} | ||
// [measure] - measure the component and set it's height instantly - would stop any current animations as well | ||
// [stop] - stop animating and set height to 'auto' | ||
// [animateTo] - animate to the last known value it has | ||
// [animateFrom] - animate from the last known value it has | ||
// maybe we have a needsMeasure state? We need to measure when the show prop | ||
// has changed so something like | ||
// show prop changes -> | ||
// set something to not animate height just yet -> | ||
// grab height, set that prop to false so we can animate now -> | ||
// we've now moved from a current height | ||
// when I fire, stop all current animations, measure myself and | ||
// go to whatever value I was at that moment in time | ||
// we need to measure at least once before we receive a mutation | ||
if (!mutations) return true | ||
// we may need to go through each mutation for instance if 3 slideables | ||
// are all triggered at once how do we handle that | ||
const { target, attributeName } = mutations[0] | ||
const slideable = target.getAttribute('data-slideable') | ||
const isSliding = target.getAttribute('data-sliding') | ||
// stop slideables if that's what we wanted | ||
if(slideable === 'stop') { | ||
this.stop() | ||
} | ||
// stop all parent slideables | ||
stopParentSlideables(target) | ||
// if the mutation happened to this component we need | ||
// to update the children so they will stop animating | ||
if (this._node === target && isSliding) { | ||
return true | ||
} | ||
// check if the target is a child of this node | ||
if (this._node !== target) { | ||
const isSliding = target.getAttribute('data-sliding') | ||
// if it has finished sliding then we need to query for height | ||
if(isSliding === 'false') { | ||
return { target, isSliding } | ||
} | ||
// if this node and is a mutation from data-sliding, don't update | ||
} else if (attributeName === 'data-sliding') { | ||
return false | ||
} | ||
_onMeasure = ({ height }) => { | ||
this.setState({ height }) | ||
} | ||
_onMeasure = ({height}, mutations, data) => { | ||
//if (!mutations) return this.setState({height}) | ||
this.setState({height}) | ||
//const { target, attributeName } = mutations[0] | ||
//const isSliding = target.getAttribute('data-sliding') | ||
// if (attributeName === 'data-slideable') { | ||
// const slideable = target.getAttribute('data-slideable') | ||
// // stop slideables if that's what we wanted | ||
// if (slideable === 'stop') { | ||
// this.stop() | ||
// return | ||
// } | ||
// } | ||
//stopParentSlideables(target) | ||
// stop all parent slideables | ||
// stopParentSlideables(target, anyStopped => { | ||
// // if any slideables were stopped we can't animate yet | ||
// // since they need to finish | ||
// if (anyStopped) { | ||
// } else { | ||
// } | ||
// }) | ||
// set height if this was a child and has finished sliding | ||
// if (this._node !== target && isSliding === 'false') { | ||
// this.setState({height, instant: true}) | ||
// } | ||
} | ||
// stops a Slideable if in the middle of animating and moves to its value | ||
// instantly, good way to prime the slideable height without animating to it | ||
stop() { | ||
this.setState({instant: true}) | ||
} | ||
render() { | ||
const { show, children } = this.props | ||
const { instant } = this.state | ||
const child = React.Children.only(children) | ||
const { style } = child.props | ||
const { show, rmConfig, children } = this.props | ||
const child = Children.only(children) | ||
const childStyles = child.props.style || {} | ||
const rmHeight = show ? this.state.height : 0 | ||
const rmConfig = presets.noWobble//[60, 22] | ||
return( | ||
return ( | ||
<Measure | ||
ref="measure" | ||
config={{ | ||
childList: true, | ||
subtree: true, | ||
attributes: true, | ||
attributeFilter: ['data-slideable', 'data-sliding'] | ||
}} | ||
accurate | ||
ref={c => this._measureComponent = c} | ||
// we only need to be accurate if the show prop has changed, | ||
// otherwise something else is effecting the height change | ||
accurate={!this._instant} | ||
whitelist={['height']} | ||
shouldMeasure={this._shouldMeasure} | ||
onMeasure={this._onMeasure} | ||
> | ||
<Motion | ||
defaultStyle={{height: 0}} | ||
defaultStyle={{ height: 0 }} | ||
style={{ | ||
height: instant ? rmHeight : spring(rmHeight, rmConfig) | ||
height: this._instant | ||
? rmHeight | ||
: spring(rmHeight, { precision: 0.5, ...rmConfig }) | ||
}} | ||
onRest={() => { | ||
this._instant = true | ||
}} | ||
> | ||
{({height}) => { | ||
const destHeight = parseFloat(this.state.height).toFixed(2) | ||
const currHeight = parseFloat(height).toFixed(2) | ||
let rmStyle = {} | ||
{({ height }) => { | ||
let rmStyles = {} | ||
if (destHeight !== currHeight && !instant) { | ||
rmStyle = { | ||
// only animate when necessary | ||
// don't always apply style values so height works responsively | ||
if (!show || (!this._instant && rmHeight !== height)) { | ||
rmStyles = { | ||
height, | ||
@@ -219,23 +74,3 @@ overflow: 'hidden' | ||
} | ||
if (destHeight === currHeight || height === 0) { | ||
this._isAnimating = false | ||
} else { | ||
this._isAnimating = true | ||
} | ||
return( | ||
React.cloneElement( | ||
React.Children.only(children), | ||
{ | ||
ref: c => this._node = ReactDOM.findDOMNode(c), | ||
style: { | ||
...rmStyle, | ||
...style | ||
}, | ||
'data-sliding': this._isAnimating, | ||
'data-slideable': true | ||
} | ||
) | ||
) | ||
return cloneElement(child, { style: { ...rmStyles, ...childStyles } }) | ||
}} | ||
@@ -248,2 +83,2 @@ </Motion> | ||
export default Slideable | ||
export default Slideable |
@@ -10,5 +10,5 @@ 'use strict'; | ||
var _accurateHeight = require('./accurate-height'); | ||
var _getCloneDimensions = require('./get-clone-dimensions'); | ||
var _accurateHeight2 = _interopRequireDefault(_accurateHeight); | ||
var _getCloneDimensions2 = _interopRequireDefault(_getCloneDimensions); | ||
@@ -19,6 +19,14 @@ function getNodeDimensions(node) { | ||
var rect = node.getBoundingClientRect(); | ||
var width = rect.width; | ||
var height = rect.height; | ||
if (accurate) { | ||
var cloneDimensions = (0, _getCloneDimensions2['default'])(node); | ||
width = cloneDimensions.width; | ||
height = cloneDimensions.height; | ||
} | ||
return { | ||
width: rect.width, | ||
height: accurate ? (0, _accurateHeight2['default'])(node) : rect.height, | ||
width: width, | ||
height: height, | ||
top: rect.top, | ||
@@ -25,0 +33,0 @@ right: rect.right, |
@@ -9,3 +9,3 @@ 'use strict'; | ||
var _get = function get(_x3, _x4, _x5) { var _again = true; _function: while (_again) { var object = _x3, property = _x4, receiver = _x5; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x3 = parent; _x4 = property; _x5 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
var _get = function get(_x4, _x5, _x6) { var _again = true; _function: while (_again) { var object = _x4, property = _x5, receiver = _x6; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x4 = parent; _x5 = property; _x6 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
@@ -26,10 +26,6 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _ResizeHandler = require('./Resize-Handler'); | ||
var _resizeDetector = require('./resize-detector'); | ||
var _ResizeHandler2 = _interopRequireDefault(_ResizeHandler); | ||
var _resizeDetector2 = _interopRequireDefault(_resizeDetector); | ||
var _diffConfig = require('./diff-config'); | ||
var _diffConfig2 = _interopRequireDefault(_diffConfig); | ||
var _getNodeDimensions = require('./get-node-dimensions'); | ||
@@ -39,4 +35,2 @@ | ||
var resizeHandler = new _ResizeHandler2['default'](); | ||
var Measure = (function (_Component) { | ||
@@ -52,23 +46,29 @@ _inherits(Measure, _Component); | ||
this._observer = null; | ||
this.state = { | ||
dimensions: {} | ||
}; | ||
this._node = null; | ||
this._properties = this._getProperties(this.props); | ||
this._propsToMeasure = this._getPropsToMeasure(this.props); | ||
this._lastDimensions = {}; | ||
this._measure = function (mutations) { | ||
var shouldMeasure = _this.props.shouldMeasure(mutations); | ||
this.measure = function () { | ||
var accurate = arguments.length <= 0 || arguments[0] === undefined ? _this.props.accurate : arguments[0]; | ||
// bail out if we shouldn't measure | ||
if (!shouldMeasure) return; | ||
if (!_this.props.shouldMeasure) return; | ||
var dimensions = _this.getDimensions(_this._node, _this.props.accurate); | ||
var dimensions = _this.getDimensions(_this._node, accurate); | ||
var isChildFunction = typeof _this.props.children === 'function'; | ||
// determine if we need to update our callback with new dimensions or not | ||
_this._properties.some(function (prop) { | ||
_this._propsToMeasure.some(function (prop) { | ||
if (dimensions[prop] !== _this._lastDimensions[prop]) { | ||
// if we've found a dimension that has changed, update our callback | ||
// we also allow shouldMeasure to return any values so the end user | ||
// doesn't have to recalculate anything | ||
_this.props.onMeasure(dimensions, mutations, shouldMeasure); | ||
// update our callback if we've found a dimension that has changed | ||
_this.props.onMeasure(dimensions); | ||
// update state to send dimensions to child function | ||
if (isChildFunction) { | ||
_this.setState({ dimensions: dimensions }); | ||
} | ||
// store last dimensions to compare changes | ||
@@ -87,12 +87,13 @@ _this._lastDimensions = dimensions; | ||
value: function componentDidMount() { | ||
var _this2 = this; | ||
this._node = _reactDom2['default'].findDOMNode(this); | ||
// set up mutation observer | ||
this._connectObserver(this.props.config); | ||
// measure on first render | ||
this._measure(null); | ||
this.measure(); | ||
// add component to resize handler to detect changes on resize | ||
resizeHandler.add(this); | ||
// add component to resize detector to detect changes on resize | ||
(0, _resizeDetector2['default'])().listenTo(this._node, function () { | ||
return _this2.measure(); | ||
}); | ||
} | ||
@@ -106,12 +107,6 @@ }, { | ||
// disconnect the old observer and reconnect with new config if changed | ||
if ((0, _diffConfig2['default'])(this.props.config, config)) { | ||
this._disconnectObserver(); | ||
this._connectObserver(config); | ||
} | ||
// we store the properties ourselves so we need to update them if the | ||
// whitelist or blacklist props have changed | ||
if (this.props.whitelist !== whitelist || this.props.blacklist !== blacklist) { | ||
this._properties = this._getProperties({ whitelist: whitelist, blacklist: blacklist }); | ||
this._propsToMeasure = this._getPropsToMeasure({ whitelist: whitelist, blacklist: blacklist }); | ||
} | ||
@@ -122,4 +117,3 @@ } | ||
value: function componentWillUnmount() { | ||
this._disconnectObserver(); | ||
resizeHandler.remove(this); | ||
(0, _resizeDetector2['default'])().removeAllListeners(this._node); | ||
} | ||
@@ -135,15 +129,4 @@ }, { | ||
}, { | ||
key: '_connectObserver', | ||
value: function _connectObserver(config) { | ||
this._observer = new MutationObserver(this._measure); | ||
this._observer.observe(this._node, config); | ||
} | ||
}, { | ||
key: '_disconnectObserver', | ||
value: function _disconnectObserver() { | ||
this._observer.disconnect(); | ||
} | ||
}, { | ||
key: '_getProperties', | ||
value: function _getProperties(_ref2) { | ||
key: '_getPropsToMeasure', | ||
value: function _getPropsToMeasure(_ref2) { | ||
var whitelist = _ref2.whitelist; | ||
@@ -159,3 +142,5 @@ var blacklist = _ref2.blacklist; | ||
value: function render() { | ||
return _react.Children.only(this.props.children); | ||
var children = this.props.children; | ||
return _react.Children.only(typeof children === 'function' ? children(this.state.dimensions) : children); | ||
} | ||
@@ -165,7 +150,6 @@ }], [{ | ||
value: { | ||
config: _react.PropTypes.object, | ||
accurate: _react.PropTypes.bool, | ||
whitelist: _react.PropTypes.array, | ||
blacklist: _react.PropTypes.array, | ||
shouldMeasure: _react.PropTypes.func, | ||
shouldMeasure: _react.PropTypes.bool, | ||
onMeasure: _react.PropTypes.func | ||
@@ -177,12 +161,6 @@ }, | ||
value: { | ||
config: { | ||
childList: true, | ||
attributes: true | ||
}, | ||
accurate: false, | ||
whitelist: ['width', 'height', 'top', 'right', 'bottom', 'left'], | ||
blacklist: [], | ||
shouldMeasure: function shouldMeasure() { | ||
return true; | ||
}, | ||
shouldMeasure: true, | ||
onMeasure: function onMeasure() { | ||
@@ -189,0 +167,0 @@ return null; |
{ | ||
"name": "react-measure", | ||
"version": "0.3.5", | ||
"version": "0.4.0", | ||
"description": "Compute measurements of React components.", | ||
@@ -24,3 +24,6 @@ "main": "lib/react-measure.js", | ||
"measurements", | ||
"dimensions" | ||
"dimensions", | ||
"element-queries", | ||
"container-queries", | ||
"size" | ||
], | ||
@@ -34,3 +37,3 @@ "author": "Travis Arnold <travis@souporserious.com> (http://souporserious.com)", | ||
"dependencies": { | ||
"lodash.debounce": "^3.1.1" | ||
"element-resize-detector": "^1.1.4" | ||
}, | ||
@@ -47,3 +50,3 @@ "devDependencies": { | ||
"react-addons-shallow-compare": "^0.14.0", | ||
"react-motion": "^0.3.1", | ||
"react-motion": "^0.4.2", | ||
"sass-loader": "^1.0.2", | ||
@@ -50,0 +53,0 @@ "style-loader": "^0.12.3", |
## React Measure | ||
Compute measurements of React components. Uses a [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver#MutationObserverInit) to detect changes of an element and return the new measurements after that mutation. | ||
Compute measurements of React components. Uses [element-resize-detector](https://github.com/wnr/element-resize-detector) to detect changes of an element and return the new dimensions. | ||
@@ -11,3 +11,3 @@ ## Install | ||
## Example Usage | ||
## Example Usage w/ state | ||
@@ -24,16 +24,6 @@ ```javascript | ||
const { height } = this.state.dimensions | ||
return( | ||
return ( | ||
<Measure | ||
whitelist={['height']} | ||
shouldMeasure={(mutations) => { | ||
// don't update unless we have mutations available | ||
if(mutations) { | ||
return mutations[0].target | ||
} else { | ||
return false | ||
} | ||
}} | ||
// notice how target gets passed into onMeasure now | ||
onMeasure={(dimensions, mutations, target) => { | ||
onMeasure={(dimensions) => { | ||
this.setState({dimensions}) | ||
@@ -51,11 +41,29 @@ }} | ||
## Props | ||
## Example Usage w/ child function | ||
#### `config`: PropTypes.object | ||
```javascript | ||
import Measure from 'react-measure'; | ||
Accepts a [MutationObserver configuration](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver#MutationObserverInit). | ||
class ItemToMeasure extends Component { | ||
render() { | ||
return ( | ||
<Measure> | ||
{dimensions => | ||
<div> | ||
{Object.keys(dimensions).map((dimension, i) => | ||
<div key={i}>{dimension}: {dimensions[dimension]}</div> | ||
)} | ||
</div> | ||
} | ||
</Measure> | ||
) | ||
} | ||
} | ||
``` | ||
## Props | ||
#### `accurate`: PropTypes.bool | ||
Tries to give the most accurate measure. Currently only works with height. Measures the content rather than the actual box of the element. | ||
Tries to give the most accurate measure by cloning the element and measuring it. Use if you your item is hidden or you want know to find out what height/width you need to get to. | ||
@@ -70,9 +78,9 @@ #### `whitelist`: PropTypes.array | ||
#### `shouldMeasure`: PropTypes.func | ||
#### `shouldMeasure`: PropTypes.bool | ||
Determines whether or not a measurement should occur. Return `true`, `false` or a value you want returned in `onMeasure`. | ||
Determines whether or not a measurement should occur. Useful if you only need to measure in certain cases. | ||
#### `onMeasure`: PropTypes.func | ||
Callback when the component has been mutated. Receives `dimensions`, `mutations`, and anything passed to `shouldMeasure`. | ||
Callback when the component has been mutated. Receives the new `dimensions` of your component. | ||
@@ -84,5 +92,2 @@ ## Good to knows | ||
## Browser Support | ||
All modern browsers supported. IE 9 & 10 support with a MutationObserver polyfill. I recommend this [one](https://github.com/megawac/MutationObserver.js) | ||
## Run Example | ||
@@ -89,0 +94,0 @@ |
@@ -1,9 +0,17 @@ | ||
import accurateHeight from './accurate-height' | ||
import getCloneDimensions from './get-clone-dimensions' | ||
export default function getNodeDimensions(node, accurate = false) { | ||
const rect = node.getBoundingClientRect() | ||
let width = rect.width | ||
let height = rect.height | ||
if (accurate) { | ||
const cloneDimensions = getCloneDimensions(node) | ||
width = cloneDimensions.width | ||
height = cloneDimensions.height | ||
} | ||
return { | ||
width: rect.width, | ||
height: accurate ? accurateHeight(node) : rect.height, | ||
width, | ||
height, | ||
top: rect.top, | ||
@@ -10,0 +18,0 @@ right: rect.right, |
import React, { Component, Children, PropTypes, createElement, cloneElement } from 'react' | ||
import ReactDOM from 'react-dom' | ||
import ResizeHandler from './Resize-Handler' | ||
import diffConfig from './diff-config' | ||
import resizeDetector from './resize-detector' | ||
import getNodeDimensions from './get-node-dimensions' | ||
const resizeHandler = new ResizeHandler() | ||
class Measure extends Component { | ||
static propTypes = { | ||
config: PropTypes.object, | ||
accurate: PropTypes.bool, | ||
whitelist: PropTypes.array, | ||
blacklist: PropTypes.array, | ||
shouldMeasure: PropTypes.func, | ||
shouldMeasure: PropTypes.bool, | ||
onMeasure: PropTypes.func | ||
@@ -20,16 +16,15 @@ } | ||
static defaultProps = { | ||
config: { | ||
childList: true, | ||
attributes: true | ||
}, | ||
accurate: false, | ||
whitelist: ['width', 'height', 'top', 'right', 'bottom', 'left'], | ||
blacklist: [], | ||
shouldMeasure: () => true, | ||
shouldMeasure: true, | ||
onMeasure: () => null | ||
} | ||
_observer = null | ||
state = { | ||
dimensions: {} | ||
} | ||
_node = null | ||
_properties = this._getProperties(this.props) | ||
_propsToMeasure = this._getPropsToMeasure(this.props) | ||
_lastDimensions = {} | ||
@@ -40,19 +35,10 @@ | ||
// set up mutation observer | ||
this._connectObserver(this.props.config) | ||
// measure on first render | ||
this._measure(null) | ||
this.measure() | ||
// add component to resize handler to detect changes on resize | ||
resizeHandler.add(this) | ||
// add component to resize detector to detect changes on resize | ||
resizeDetector().listenTo(this._node, () => this.measure()) | ||
} | ||
componentWillReceiveProps({config, whitelist, blacklist}) { | ||
// disconnect the old observer and reconnect with new config if changed | ||
if (diffConfig(this.props.config, config)) { | ||
this._disconnectObserver() | ||
this._connectObserver(config) | ||
} | ||
// we store the properties ourselves so we need to update them if the | ||
@@ -62,3 +48,3 @@ // whitelist or blacklist props have changed | ||
this.props.blacklist !== blacklist) { | ||
this._properties = this._getProperties({whitelist, blacklist}) | ||
this._propsToMeasure = this._getPropsToMeasure({whitelist, blacklist}) | ||
} | ||
@@ -68,4 +54,3 @@ } | ||
componentWillUnmount() { | ||
this._disconnectObserver() | ||
resizeHandler.remove(this) | ||
resizeDetector().removeAllListeners(this._node) | ||
} | ||
@@ -77,18 +62,24 @@ | ||
_measure = (mutations) => { | ||
const shouldMeasure = this.props.shouldMeasure(mutations) | ||
_getPropsToMeasure({ whitelist, blacklist }) { | ||
return whitelist.filter(prop => blacklist.indexOf(prop) < 0) | ||
} | ||
measure = (accurate = this.props.accurate) => { | ||
// bail out if we shouldn't measure | ||
if(!shouldMeasure) return | ||
if (!this.props.shouldMeasure) return | ||
const dimensions = this.getDimensions(this._node, this.props.accurate) | ||
const dimensions = this.getDimensions(this._node, accurate) | ||
const isChildFunction = (typeof this.props.children === 'function') | ||
// determine if we need to update our callback with new dimensions or not | ||
this._properties.some(prop => { | ||
if(dimensions[prop] !== this._lastDimensions[prop]) { | ||
// if we've found a dimension that has changed, update our callback | ||
// we also allow shouldMeasure to return any values so the end user | ||
// doesn't have to recalculate anything | ||
this.props.onMeasure(dimensions, mutations, shouldMeasure) | ||
this._propsToMeasure.some(prop => { | ||
if (dimensions[prop] !== this._lastDimensions[prop]) { | ||
// update our callback if we've found a dimension that has changed | ||
this.props.onMeasure(dimensions) | ||
// update state to send dimensions to child function | ||
if (isChildFunction) { | ||
this.setState({ dimensions }) | ||
} | ||
// store last dimensions to compare changes | ||
@@ -103,17 +94,9 @@ this._lastDimensions = dimensions | ||
_connectObserver(config) { | ||
this._observer = new MutationObserver(this._measure) | ||
this._observer.observe(this._node, config) | ||
} | ||
_disconnectObserver() { | ||
this._observer.disconnect() | ||
} | ||
_getProperties({whitelist, blacklist}) { | ||
return whitelist.filter(prop => blacklist.indexOf(prop) < 0) | ||
} | ||
render() { | ||
return Children.only(this.props.children) | ||
const { children } = this.props | ||
return Children.only( | ||
typeof children === 'function' | ||
? children(this.state.dimensions) | ||
: children | ||
) | ||
} | ||
@@ -120,0 +103,0 @@ } |
@@ -28,3 +28,4 @@ var path = require('path'); | ||
'react': 'React', | ||
'react-dom': 'ReactDOM' | ||
'react-dom': 'ReactDOM', | ||
'element-resize-detector': 'createResizeDetector' | ||
}, | ||
@@ -41,3 +42,3 @@ }; | ||
mangle: { | ||
except: ['React', 'ReactDOM', 'Measure'] | ||
except: ['React', 'ReactDOM', 'Measure', 'createResizeDetector'] | ||
} | ||
@@ -47,2 +48,2 @@ })); | ||
module.exports = config; | ||
module.exports = config; |
Sorry, the diff of this file is not supported yet
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
107
60897
316341
29
1226
+ Addedbatch-processor@1.0.0(transitive)
+ Addedelement-resize-detector@1.2.4(transitive)
- Removedlodash.debounce@^3.1.1
- Removedlodash._getnative@3.9.1(transitive)
- Removedlodash.debounce@3.1.1(transitive)