react-measure
Advanced tools
Comparing version 0.0.1 to 0.0.2
{ | ||
"name": "react-measure", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"homepage": "https://github.com/souporserious/react-measure", | ||
@@ -8,3 +8,3 @@ "authors": [ | ||
], | ||
"description": "React component to compute measurements of a component.", | ||
"description": "Compute measurements of React components.", | ||
"main": ["./dist/react-measure.js"], | ||
@@ -11,0 +11,0 @@ "keywords": [ |
@@ -7,5 +7,5 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
else if(typeof exports === 'object') | ||
exports["ReactMotionSlider"] = factory(require("React")); | ||
exports["Measure"] = factory(require("React")); | ||
else | ||
root["ReactMotionSlider"] = factory(root["React"]); | ||
root["Measure"] = factory(root["React"]); | ||
})(this, function(__WEBPACK_EXTERNAL_MODULE_2__) { | ||
@@ -70,3 +70,4 @@ return /******/ (function(modules) { // webpackBootstrap | ||
exports.Measure = _Measure2['default']; | ||
exports['default'] = _Measure2['default']; | ||
module.exports = exports['default']; | ||
@@ -85,3 +86,3 @@ /***/ }, | ||
var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; 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 { _x2 = parent; _x3 = property; _x4 = 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(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; 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 { _x = parent; _x2 = property; _x3 = 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); } } }; | ||
@@ -98,46 +99,35 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
function _throttle(fn, threshhold, scope) { | ||
if (threshhold === undefined) threshhold = 250; | ||
var _throttle = __webpack_require__(3); | ||
threshhold || (threshhold = 250); | ||
var last = undefined, | ||
deferTimer = undefined; | ||
return function () { | ||
var context = scope || this; | ||
var now = +new Date(), | ||
args = arguments; | ||
if (last && now < last + threshhold) { | ||
// hold on to it | ||
clearTimeout(deferTimer); | ||
deferTimer = setTimeout(function () { | ||
last = now; | ||
fn.apply(context, args); | ||
}, threshhold); | ||
} else { | ||
last = now; | ||
fn.apply(context, args); | ||
} | ||
}; | ||
} | ||
var _throttle2 = _interopRequireDefault(_throttle); | ||
function _debounce(fn) { | ||
var delay = arguments[1] === undefined ? 250 : arguments[1]; | ||
var _debounce = __webpack_require__(4); | ||
var timer = null; | ||
return function () { | ||
var context = this, | ||
args = arguments; | ||
clearTimeout(timer); | ||
timer = setTimeout(function () { | ||
fn.apply(context, args); | ||
}, delay); | ||
}; | ||
} | ||
var _debounce2 = _interopRequireDefault(_debounce); | ||
var registeredComponents = []; | ||
// force rerender on window resize so we can grab dimensions again | ||
window.addEventListener('resize', function () { | ||
registeredComponents.forEach(function (c) { | ||
return c._forceMeasure(); | ||
}); | ||
}); | ||
var Measure = (function (_Component) { | ||
function Measure(props) { | ||
function Measure() { | ||
var _this = this; | ||
_classCallCheck(this, Measure); | ||
_get(Object.getPrototypeOf(Measure.prototype), 'constructor', this).call(this, props); | ||
this.state = { height: 0 }; | ||
_get(Object.getPrototypeOf(Measure.prototype), 'constructor', this).apply(this, arguments); | ||
this.state = { | ||
width: null, | ||
height: null, | ||
top: null, | ||
right: null, | ||
bottom: null, | ||
left: null | ||
}; | ||
this._node = null; | ||
@@ -147,4 +137,6 @@ this._nodeCopy = null; | ||
this._copyAppended = false; | ||
this._debounceDelay = 350; | ||
this._forceMeasure = this._forceMeasure.bind(this); | ||
this._forceMeasure = function () { | ||
_this.forceUpdate(); | ||
}; | ||
} | ||
@@ -157,4 +149,5 @@ | ||
value: function componentWillMount() { | ||
this._removeClone = _debounce(this._removeClone, this._debounceDelay); | ||
this._forceMeasure = _throttle(this._forceMeasure, 300); | ||
this._removeClone = (0, _debounce2['default'])(this._removeClone, 300); | ||
this._forceMeasure = (0, _throttle2['default'])(this._forceMeasure, 300); | ||
this._setMeasure = (0, _throttle2['default'])(this._setMeasure, 300); | ||
} | ||
@@ -166,5 +159,6 @@ }, { | ||
this._parentNode = this._node.parentNode; | ||
this.setState({ height: this._calcHeight(this._node) }); | ||
this.setState(this._measure(this._node)); | ||
window.addEventListener('resize', this._forceMeasure); | ||
// store registered components | ||
registeredComponents.push(this); | ||
} | ||
@@ -174,6 +168,8 @@ }, { | ||
value: function componentDidUpdate(prevProps, prevState) { | ||
var height = this._calcHeight(this._node); | ||
var dimensions = this._measure(this._node); | ||
if (+prevState.height !== +height) { | ||
this.setState({ height: height }); | ||
// we can use JSON stringify to compare objects since they are simple structures | ||
// used to determine if we need to update our state with new dimensions or not | ||
if (JSON.stringify(prevState) !== JSON.stringify(dimensions)) { | ||
this._setMeasure(dimensions); | ||
} | ||
@@ -184,13 +180,16 @@ } | ||
value: function componentWillUnmount() { | ||
window.removeEventListener('resize', this._forceMeasure); | ||
var pos = registeredComponents.indexOf(this); | ||
if (pos > -1) { | ||
registeredComponents.splice(pos, 1); | ||
} | ||
} | ||
}, { | ||
key: '_forceMeasure', | ||
value: function _forceMeasure() { | ||
this.forceUpdate(); | ||
key: '_setMeasure', | ||
value: function _setMeasure(dimensions) { | ||
this.setState(dimensions); | ||
} | ||
}, { | ||
key: '_calcHeight', | ||
value: function _calcHeight(node) { | ||
var height = undefined; | ||
key: '_measure', | ||
value: function _measure(node) { | ||
var dimensions = undefined; | ||
@@ -202,3 +201,7 @@ if (!this._copyAppended) { | ||
// give the node some context to measure off of | ||
// height and overflow prevent scrollbars from copy | ||
context.style.height = 0; | ||
context.style.position = 'relative'; | ||
context.style.overflow = 'hidden'; | ||
//copy.style.transform = 'translateY(-100%)'; | ||
@@ -219,2 +222,3 @@ // remove name from all children inputs so they don't conflict with current ones | ||
// set props to hide copy and get true dimensions | ||
copy.style.boxSizing = 'border-box'; | ||
copy.style.height = 'auto'; | ||
@@ -236,4 +240,4 @@ copy.style.width = '100%'; | ||
// grab height of node | ||
height = +this._nodeCopy.offsetHeight; | ||
// grab dimensions of node | ||
dimensions = this._nodeCopy.getBoundingClientRect(); | ||
@@ -243,3 +247,10 @@ // remove the copy after getting it's height | ||
return height; | ||
return { | ||
width: dimensions.width, | ||
height: dimensions.height, | ||
top: dimensions.top, | ||
right: dimensions.right, | ||
bottom: dimensions.bottom, | ||
left: dimensions.left | ||
}; | ||
} | ||
@@ -272,2 +283,66 @@ }, { | ||
/***/ }, | ||
/* 3 */ | ||
/***/ function(module, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports["default"] = _throttle; | ||
function _throttle(fn, threshhold, scope) { | ||
if (threshhold === undefined) threshhold = 250; | ||
threshhold || (threshhold = 250); | ||
var last = undefined, | ||
deferTimer = undefined; | ||
return function () { | ||
var context = scope || this; | ||
var now = +new Date(), | ||
args = arguments; | ||
if (last && now < last + threshhold) { | ||
// hold on to it | ||
clearTimeout(deferTimer); | ||
deferTimer = setTimeout(function () { | ||
last = now; | ||
fn.apply(context, args); | ||
}, threshhold); | ||
} else { | ||
last = now; | ||
fn.apply(context, args); | ||
} | ||
}; | ||
} | ||
module.exports = exports["default"]; | ||
/***/ }, | ||
/* 4 */ | ||
/***/ function(module, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports["default"] = _debounce; | ||
function _debounce(fn) { | ||
var delay = arguments[1] === undefined ? 250 : arguments[1]; | ||
var timer = null; | ||
return function () { | ||
var context = this, | ||
args = arguments; | ||
clearTimeout(timer); | ||
timer = setTimeout(function () { | ||
fn.apply(context, args); | ||
}, delay); | ||
}; | ||
} | ||
module.exports = exports["default"]; | ||
/***/ } | ||
@@ -274,0 +349,0 @@ /******/ ]) |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("React")):"function"==typeof define&&define.amd?define(["React"],t):"object"==typeof exports?exports.ReactMotionSlider=t(require("React")):e.ReactMotionSlider=t(e.React)}(this,function(e){return function(e){function t(n){if(o[n])return o[n].exports;var r=o[n]={exports:{},id:n,loaded:!1};return e[n].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var o={};return t.m=e,t.c=o,t.p="dist/",t(0)}([function(e,t,o){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(t,"__esModule",{value:!0});var r=o(1),i=n(r);t.Measure=i["default"]},function(e,t,o){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function r(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&&(e.__proto__=t)}function u(e,t,o){void 0===t&&(t=250),t||(t=250);var n=void 0,r=void 0;return function(){var i=o||this,u=+new Date,a=arguments;n&&n+t>u?(clearTimeout(r),r=setTimeout(function(){n=u,e.apply(i,a)},t)):(n=u,e.apply(i,a))}}function a(e){var t=void 0===arguments[1]?250:arguments[1],o=null;return function(){var n=this,r=arguments;clearTimeout(o),o=setTimeout(function(){e.apply(n,r)},t)}}Object.defineProperty(t,"__esModule",{value:!0});var s=function(){function e(e,t){for(var o=0;o<t.length;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}}(),l=function(e,t,o){for(var n=!0;n;){var r=e,i=t,u=o;a=l=s=void 0,n=!1,null===r&&(r=Function.prototype);var a=Object.getOwnPropertyDescriptor(r,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(r);if(null===l)return void 0;e=l,t=i,o=u,n=!0}},c=o(2),d=n(c),Measure=function(e){function Measure(e){r(this,Measure),l(Object.getPrototypeOf(Measure.prototype),"constructor",this).call(this,e),this.state={height:0},this._node=null,this._nodeCopy=null,this._nodeParent=null,this._copyAppended=!1,this._debounceDelay=350,this._forceMeasure=this._forceMeasure.bind(this)}return i(Measure,e),s(Measure,[{key:"componentWillMount",value:function(){this._removeClone=a(this._removeClone,this._debounceDelay),this._forceMeasure=u(this._forceMeasure,300)}},{key:"componentDidMount",value:function(){this._node=d["default"].findDOMNode(this),this._parentNode=this._node.parentNode,this.setState({height:this._calcHeight(this._node)}),window.addEventListener("resize",this._forceMeasure)}},{key:"componentDidUpdate",value:function(e,t){var o=this._calcHeight(this._node);+t.height!==+o&&this.setState({height:o})}},{key:"componentWillUnmount",value:function(){window.removeEventListener("resize",this._forceMeasure)}},{key:"_forceMeasure",value:function(){this.forceUpdate()}},{key:"_calcHeight",value:function(e){var t=void 0;if(!this._copyAppended){var o=document.createElement("div"),n=e.cloneNode(!0);o.style.position="relative";for(var r=n.querySelectorAll("input"),i=r.length;i--;)r[i].setAttribute("name","");var u=n.querySelectorAll("[data-reactid]");n.setAttribute("data-reactid","");for(var a=u.length;a--;)u[a].setAttribute("data-reactid","");n.style.height="auto",n.style.width="100%",n.style.position="absolute",n.style.visibility="hidden",o.appendChild(n),this._parentNode.appendChild(o),this._copyAppended=!0,this._nodeCopy=n}return t=+this._nodeCopy.offsetHeight,this._removeClone(),t}},{key:"_removeClone",value:function(){this._parentNode.removeChild(this._nodeCopy.parentNode),this._copyAppended=!1}},{key:"render",value:function(){return c.Children.only(this.props.children(this.state))}}]),Measure}(c.Component);t["default"]=Measure,e.exports=t["default"]},function(t,o){t.exports=e}])}); | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("React")):"function"==typeof define&&define.amd?define(["React"],t):"object"==typeof exports?exports.Measure=t(require("React")):e.Measure=t(e.React)}(this,function(e){return function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={exports:{},id:o,loaded:!1};return e[o].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="dist/",t(0)}([function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(1),i=o(r);t["default"]=i["default"],e.exports=t["default"]},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function r(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&&(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 o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),a=function(e,t,n){for(var o=!0;o;){var r=e,i=t,u=n;a=l=s=void 0,o=!1,null===r&&(r=Function.prototype);var a=Object.getOwnPropertyDescriptor(r,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(r);if(null===l)return void 0;e=l,t=i,n=u,o=!0}},s=n(2),l=o(s),d=n(3),c=o(d),f=n(4),p=o(f),h=[];window.addEventListener("resize",function(){h.forEach(function(e){return e._forceMeasure()})});var Measure=function(e){function Measure(){var e=this;r(this,Measure),a(Object.getPrototypeOf(Measure.prototype),"constructor",this).apply(this,arguments),this.state={width:null,height:null,top:null,right:null,bottom:null,left:null},this._node=null,this._nodeCopy=null,this._nodeParent=null,this._copyAppended=!1,this._forceMeasure=function(){e.forceUpdate()}}return i(Measure,e),u(Measure,[{key:"componentWillMount",value:function(){this._removeClone=p["default"](this._removeClone,300),this._forceMeasure=c["default"](this._forceMeasure,300),this._setMeasure=c["default"](this._setMeasure,300)}},{key:"componentDidMount",value:function(){this._node=l["default"].findDOMNode(this),this._parentNode=this._node.parentNode,this.setState(this._measure(this._node)),h.push(this)}},{key:"componentDidUpdate",value:function(e,t){var n=this._measure(this._node);JSON.stringify(t)!==JSON.stringify(n)&&this._setMeasure(n)}},{key:"componentWillUnmount",value:function(){var e=h.indexOf(this);e>-1&&h.splice(e,1)}},{key:"_setMeasure",value:function(e){this.setState(e)}},{key:"_measure",value:function(e){var t=void 0;if(!this._copyAppended){var n=document.createElement("div"),o=e.cloneNode(!0);n.style.height=0,n.style.position="relative",n.style.overflow="hidden";for(var r=o.querySelectorAll("input"),i=r.length;i--;)r[i].setAttribute("name","");var u=o.querySelectorAll("[data-reactid]");o.setAttribute("data-reactid","");for(var a=u.length;a--;)u[a].setAttribute("data-reactid","");o.style.boxSizing="border-box",o.style.height="auto",o.style.width="100%",o.style.position="absolute",o.style.visibility="hidden",n.appendChild(o),this._parentNode.appendChild(n),this._copyAppended=!0,this._nodeCopy=o}return t=this._nodeCopy.getBoundingClientRect(),this._removeClone(),{width:t.width,height:t.height,top:t.top,right:t.right,bottom:t.bottom,left:t.left}}},{key:"_removeClone",value:function(){this._parentNode.removeChild(this._nodeCopy.parentNode),this._copyAppended=!1}},{key:"render",value:function(){return s.Children.only(this.props.children(this.state))}}]),Measure}(s.Component);t["default"]=Measure,e.exports=t["default"]},function(t,n){t.exports=e},function(e,t){"use strict";function n(e,t,n){void 0===t&&(t=250),t||(t=250);var o=void 0,r=void 0;return function(){var i=n||this,u=+new Date,a=arguments;o&&o+t>u?(clearTimeout(r),r=setTimeout(function(){o=u,e.apply(i,a)},t)):(o=u,e.apply(i,a))}}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=n,e.exports=t["default"]},function(e,t){"use strict";function n(e){var t=void 0===arguments[1]?250:arguments[1],n=null;return function(){var o=this,r=arguments;clearTimeout(n),n=setTimeout(function(){e.apply(o,r)},t)}}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=n,e.exports=t["default"]}])}); |
@@ -1,33 +0,93 @@ | ||
import React, { Component, PropTypes } from 'react'; | ||
import React, { Component, Children, PropTypes } from 'react'; | ||
import { Spring } from 'react-motion'; | ||
import { Measure } from '../src/index'; | ||
import Measure from '../src/react-measure'; | ||
import './main.scss'; | ||
class App extends Component { | ||
class Accordion extends Component { | ||
_handleClick(item) { | ||
this.props.onClick(item); | ||
} | ||
render() { | ||
const { items, active } = this.props; | ||
return( | ||
<div> | ||
<Measure> | ||
{({height}) => | ||
<Spring | ||
defaultValue={0} | ||
endValue={height} | ||
<ul className="accordion__items"> | ||
{items.map(item => | ||
<li | ||
className="accordion__item" key={item.id} | ||
onClick={this._handleClick.bind(this, item)} | ||
> | ||
{(rmHeight) => | ||
<div | ||
style={{ | ||
height: rmHeight, | ||
padding: 28, | ||
backgroundColor: '#b4da55', | ||
overflow: 'hidden' | ||
}} | ||
> | ||
<h3>height = {Math.ceil(rmHeight)}px</h3> | ||
<p>Look, just because I don't be givin' no man a foot massage don't make it right for Marsellus to throw Antwone into a glass motherfuckin' house, fuckin' up the way the nigger talks. Motherfucker do that shit to me, he better paralyze my ass, 'cause I'll kill the motherfucker, know what I'm sayin'?</p> | ||
</div> | ||
} | ||
</Spring> | ||
<h2 className="accordion__item__title">{item.title}</h2> | ||
<Measure> | ||
{({height}) => | ||
<Spring | ||
endValue={{ | ||
val: { | ||
height: active === item.id ? height : 0, | ||
opacity: active === item.id ? 1 : 0, | ||
scale: active === item.id ? 1 : 0.95 | ||
} | ||
}} | ||
> | ||
{({val: {height, opacity, scale}}) => | ||
<div | ||
className="accordion__item__content" | ||
style={{height, opacity, transform: `scale(${scale})`}} | ||
> | ||
{item.contents.map((content, i) => <p key={i}>{content}</p>)} | ||
</div> | ||
} | ||
</Spring> | ||
} | ||
</Measure> | ||
</li> | ||
)} | ||
</ul> | ||
); | ||
} | ||
} | ||
class App extends Component { | ||
constructor() { | ||
super(); | ||
this._handleAccordionClick = this._handleAccordionClick.bind(this); | ||
this.state = { | ||
items: [ | ||
{ | ||
id: 0, | ||
title: 'What is a dog?', | ||
contents: ['A dog is a type of domesticated animal. Known for its loyalty and faithfulness, it can be found as a welcome guest in many households across the world.'] | ||
}, { | ||
id: 1, | ||
title: 'What kinds of dogs are there?', | ||
contents: ['There are many breeds of dogs. Each breed varies in size and temperament. Owners often select a breed of dog that they find to be compatible with their own lifestyle and desires from a companion.'] | ||
}, { | ||
id: 2, | ||
title: 'How do you acquire a dog?', | ||
contents: ['Three common ways for a prospective owner to acquire a dog is from pet shops, private owners, or shelters.', 'A pet shop may be the most convenient way to buy a dog. Buying a dog from a private owner allows you to assess the pedigree and upbringing of your dog before choosing to take it home. Lastly, finding your dog from a shelter, helps give a good home to a dog who may not find one so readily.'] | ||
} | ||
</Measure> | ||
], | ||
active: 1 | ||
} | ||
} | ||
_handleAccordionClick({id}) { | ||
const active = (id === this.state.active) ? null : id; | ||
this.setState({active}); | ||
} | ||
render() { | ||
const { items, active } = this.state; | ||
const currentSelected = active === null ? 'Nothing selected' : items[active].title; | ||
return( | ||
<div className="app"> | ||
<strong>Current Selected:</strong> {currentSelected} | ||
<Accordion | ||
items={items} | ||
active={active} | ||
onClick={this._handleAccordionClick} | ||
/> | ||
</div> | ||
@@ -34,0 +94,0 @@ ); |
{ | ||
"name": "react-measure", | ||
"version": "0.0.1", | ||
"description": "React component to compute measurements of a component.", | ||
"main": "lib/index.js", | ||
"version": "0.0.2", | ||
"description": "Compute measurements of React components.", | ||
"main": "lib/react-measure.js", | ||
"scripts": { | ||
@@ -7,0 +7,0 @@ "build": "npm run build:lib && NODE_ENV=production webpack --config webpack.prod.config.js", |
@@ -1,3 +0,18 @@ | ||
## React Measure 0.0.1 | ||
## React Measure 0.0.2 | ||
Compute measurements of a component. | ||
Compute measurements of React components. | ||
## Example Usage | ||
```javascript | ||
import Measure from 'react-measure'; | ||
<Measure> | ||
{({width, height, top, right, bottom, left}) => | ||
<div> | ||
{/* do cool stuff with my dimensions */} | ||
</div> | ||
} | ||
</Measure> | ||
``` |
import React, { Component, Children, PropTypes } from 'react'; | ||
import throttle from './throttle'; | ||
import debounce from './debounce'; | ||
function _throttle(fn, threshhold = 250, scope) { | ||
threshhold || (threshhold = 250); | ||
let last, | ||
deferTimer; | ||
return function () { | ||
let context = scope || this; | ||
let now = +new Date, | ||
args = arguments; | ||
if(last && now < last + threshhold) { | ||
// hold on to it | ||
clearTimeout(deferTimer); | ||
deferTimer = setTimeout(function () { | ||
last = now; | ||
fn.apply(context, args); | ||
}, threshhold); | ||
} else { | ||
last = now; | ||
fn.apply(context, args); | ||
} | ||
}; | ||
} | ||
let registeredComponents = []; | ||
function _debounce(fn, delay = 250) { | ||
let timer = null; | ||
return function () { | ||
const context = this, args = arguments; | ||
clearTimeout(timer); | ||
timer = setTimeout(function () { | ||
fn.apply(context, args); | ||
}, delay); | ||
}; | ||
} | ||
// force rerender on window resize so we can grab dimensions again | ||
window.addEventListener('resize', () => { | ||
registeredComponents.forEach(c => c._forceMeasure()); | ||
}); | ||
class Measure extends Component { | ||
constructor(props) { | ||
super(props) | ||
this.state = { height: 0 } | ||
this._node = null | ||
this._nodeCopy = null | ||
this._nodeParent = null | ||
this._copyAppended = false | ||
this._debounceDelay = 350 | ||
this._forceMeasure = this._forceMeasure.bind(this) | ||
state = { | ||
width: null, | ||
height: null, | ||
top: null, | ||
right: null, | ||
bottom: null, | ||
left: null | ||
} | ||
_node = null | ||
_nodeCopy = null | ||
_nodeParent = null | ||
_copyAppended = false | ||
componentWillMount() { | ||
this._removeClone = _debounce(this._removeClone, this._debounceDelay); | ||
this._forceMeasure = _throttle(this._forceMeasure, 300); | ||
this._removeClone = debounce(this._removeClone, 300); | ||
this._forceMeasure = throttle(this._forceMeasure, 300); | ||
this._setMeasure = throttle(this._setMeasure, 300); | ||
} | ||
@@ -56,35 +35,49 @@ | ||
this._parentNode = this._node.parentNode | ||
this.setState({height: this._calcHeight(this._node)}); | ||
window.addEventListener('resize', this._forceMeasure); | ||
this.setState(this._measure(this._node)); | ||
// store registered components | ||
registeredComponents.push(this); | ||
} | ||
componentDidUpdate(prevProps, prevState) { | ||
let height = this._calcHeight(this._node); | ||
const dimensions = this._measure(this._node); | ||
if(+prevState.height !== +height) { | ||
this.setState({height}); | ||
// we can use JSON stringify to compare objects since they are simple structures | ||
// used to determine if we need to update our state with new dimensions or not | ||
if(JSON.stringify(prevState) !== JSON.stringify(dimensions)) { | ||
this._setMeasure(dimensions); | ||
} | ||
} | ||
componentWillUnmount() { | ||
window.removeEventListener('resize', this._forceMeasure); | ||
const pos = registeredComponents.indexOf(this); | ||
if(pos > -1) { | ||
registeredComponents.splice(pos, 1); | ||
} | ||
} | ||
_forceMeasure() { | ||
_forceMeasure = () => { | ||
this.forceUpdate(); | ||
} | ||
_calcHeight(node) { | ||
let height | ||
_setMeasure(dimensions) { | ||
this.setState(dimensions); | ||
} | ||
_measure(node) { | ||
let dimensions | ||
if(!this._copyAppended) { | ||
const context = document.createElement('div'); | ||
const copy = node.cloneNode(true); | ||
const context = document.createElement('div') | ||
const copy = node.cloneNode(true) | ||
// give the node some context to measure off of | ||
context.style.position = 'relative'; | ||
// height and overflow prevent scrollbars from copy | ||
context.style.height = 0 | ||
context.style.position = 'relative' | ||
context.style.overflow = 'hidden' | ||
//copy.style.transform = 'translateY(-100%)'; | ||
// remove name from all children inputs so they don't conflict with current ones | ||
const inputNodes = copy.querySelectorAll('input'); | ||
const inputNodes = copy.querySelectorAll('input') | ||
for(let i = inputNodes.length; i--;) { | ||
@@ -95,4 +88,4 @@ inputNodes[i].setAttribute('name', '') | ||
// remove copy and children react id's so it doesn't conflict with current ones | ||
const reactNodes = copy.querySelectorAll('[data-reactid]'); | ||
copy.setAttribute('data-reactid', ''); | ||
const reactNodes = copy.querySelectorAll('[data-reactid]') | ||
copy.setAttribute('data-reactid', '') | ||
for(let j = reactNodes.length; j--;) { | ||
@@ -103,25 +96,33 @@ reactNodes[j].setAttribute('data-reactid', '') | ||
// set props to hide copy and get true dimensions | ||
copy.style.height = 'auto'; | ||
copy.style.width = '100%'; | ||
copy.style.position = 'absolute'; | ||
copy.style.visibility = 'hidden'; | ||
copy.style.boxSizing = 'border-box' | ||
copy.style.height = 'auto' | ||
copy.style.width = '100%' | ||
copy.style.position = 'absolute' | ||
copy.style.visibility = 'hidden' | ||
// append copy to context | ||
context.appendChild(copy); | ||
context.appendChild(copy) | ||
// append context to DOM so we can measure | ||
this._parentNode.appendChild(context) | ||
this._copyAppended = true | ||
// store node so we can calculate on it and remove it later | ||
this._nodeCopy = copy; | ||
this._nodeCopy = copy | ||
} | ||
// grab height of node | ||
height = +this._nodeCopy.offsetHeight | ||
// grab dimensions of node | ||
dimensions = this._nodeCopy.getBoundingClientRect(); | ||
// remove the copy after getting it's height | ||
this._removeClone(); | ||
return height | ||
return { | ||
width: dimensions.width, | ||
height: dimensions.height, | ||
top: dimensions.top, | ||
right: dimensions.right, | ||
bottom: dimensions.bottom, | ||
left: dimensions.left | ||
} | ||
} | ||
@@ -128,0 +129,0 @@ |
@@ -7,3 +7,3 @@ var path = require('path'); | ||
entry: { | ||
index: './src/index.js', | ||
index: './src/react-measure.js', | ||
}, | ||
@@ -15,3 +15,3 @@ output: { | ||
sourceMapFilename: 'react-measure.sourcemap.js', | ||
library: 'ReactMotionSlider', | ||
library: 'Measure', | ||
libraryTarget: 'umd' | ||
@@ -18,0 +18,0 @@ }, |
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
29221
16
586
18