react-sticky
Advanced tools
Comparing version 4.0.0-rc9 to 4.0.1-rc1
@@ -7,4 +7,2 @@ 'use strict'; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _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; }; }(); | ||
@@ -16,5 +14,5 @@ | ||
var _sticky = require('./sticky'); | ||
var _reactDom = require('react-dom'); | ||
var _sticky2 = _interopRequireDefault(_sticky); | ||
var _reactDom2 = _interopRequireDefault(_reactDom); | ||
@@ -38,3 +36,4 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
_this.state = { | ||
topCorrection: 0 | ||
offset: 0, | ||
rect: {} | ||
}; | ||
@@ -48,22 +47,24 @@ return _this; | ||
var container = this; | ||
var topCorrection = (this.context.topCorrection || 0) + this.state.topCorrection; | ||
var offset = topCorrection - this.state.topCorrection; | ||
return { container: container, topCorrection: topCorrection, offset: offset }; | ||
var totalOffset = (this.context.totalOffset || 0) + this.state.offset; | ||
var offset = totalOffset - this.state.offset; | ||
var rect = this.state.node ? this.state.node.getBoundingClientRect() : {}; | ||
return { container: container, totalOffset: totalOffset, offset: offset, rect: rect }; | ||
} | ||
}, { | ||
key: 'updateTopCorrection', | ||
value: function updateTopCorrection(topCorrection) { | ||
this.setState({ topCorrection: topCorrection }); | ||
key: 'componentDidMount', | ||
value: function componentDidMount() { | ||
var node = _reactDom2.default.findDOMNode(this); | ||
this.setState({ node: node }); | ||
} | ||
}, { | ||
key: 'updateOffset', | ||
value: function updateOffset(offset) { | ||
this.setState({ offset: offset }); | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render() { | ||
var style = _extends({}, this.props.style || {}); | ||
var paddingTop = style.paddingTop || 0; | ||
style.paddingTop = paddingTop + this.state.topCorrection; | ||
return _react2.default.createElement( | ||
'div', | ||
_extends({}, this.props, { style: style }), | ||
this.props, | ||
this.props.children | ||
@@ -79,10 +80,11 @@ ); | ||
container: _react2.default.PropTypes.any, | ||
topCorrection: _react2.default.PropTypes.number | ||
totalOffset: _react2.default.PropTypes.number | ||
}; | ||
Container.childContextTypes = { | ||
container: _react2.default.PropTypes.any, | ||
topCorrection: _react2.default.PropTypes.number, | ||
offset: _react2.default.PropTypes.number | ||
totalOffset: _react2.default.PropTypes.number, | ||
offset: _react2.default.PropTypes.number, | ||
rect: _react2.default.PropTypes.any | ||
}; | ||
exports.default = Container; | ||
module.exports = exports['default']; |
@@ -19,6 +19,2 @@ 'use strict'; | ||
var _watcher = require('./watcher'); | ||
var _watcher2 = _interopRequireDefault(_watcher); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -41,29 +37,9 @@ | ||
_this.onScroll = function () { | ||
var isSticky = _this.stickyConditionsMet(); | ||
var pageY = window.pageYOffset; | ||
var isSticky = _this.isSticky(pageY, _this.state.origin); | ||
var hasChanged = _this.state.isSticky !== isSticky; | ||
var topCorrection = 0; | ||
var stickyStyle = {}; | ||
if (isSticky) { | ||
var offset = _this.context.offset || 0; | ||
var containerRect = _reactDom2.default.findDOMNode(_this.context.container).getBoundingClientRect(); | ||
stickyStyle = { | ||
position: 'fixed', | ||
top: offset, | ||
left: containerRect.left, | ||
width: containerRect.width | ||
}; | ||
topCorrection = _this.state.height; | ||
_this.setState({ isSticky: isSticky }); | ||
_this.context.container.updateOffset(isSticky ? _this.state.height : 0); | ||
var bottomLimit = containerRect.bottom - _this.state.height - _this.props.bottomOffset; | ||
if (offset > bottomLimit) { | ||
stickyStyle.top = bottomLimit; | ||
} | ||
} | ||
// Update state | ||
_this.setState({ isSticky: isSticky, stickyStyle: stickyStyle }); | ||
_this.context.container.updateTopCorrection(topCorrection); | ||
// Publish sticky state change | ||
if (hasChanged) _this.props.onStickyStateChange(isSticky); | ||
@@ -73,10 +49,9 @@ }; | ||
_this.onResize = function () { | ||
_this.updateOrigin(); | ||
// emit a scroll event to re-calculate container top offsets | ||
Sticky.scrollWatcher.emit(); | ||
var height = _reactDom2.default.findDOMNode(_this).getBoundingClientRect().height; | ||
var origin = _this.refs.placeholder.getBoundingClientRect().top + window.pageYOffset; | ||
_this.setState({ height: height, origin: origin }); | ||
}; | ||
_this.state = { | ||
height: 0, | ||
stickyStyle: {} | ||
isSticky: false | ||
}; | ||
@@ -89,65 +64,45 @@ return _this; | ||
value: function componentDidMount() { | ||
this.updateOrigin(); | ||
this.updateHeight(); | ||
Sticky.resizeWatcher.on(this.onResize); | ||
Sticky.scrollWatcher.on(this.onScroll); | ||
this.update(); | ||
this.on(['scroll', 'touchstart', 'touchmove', 'touchend'], this.onScroll); | ||
this.on(['resize'], this.onResize); | ||
} | ||
}, { | ||
key: 'componentWillReceiveProps', | ||
value: function componentWillReceiveProps() { | ||
this.update(); | ||
} | ||
}, { | ||
key: 'componentWillUnmount', | ||
value: function componentWillUnmount() { | ||
Sticky.resizeWatcher.off(this.onResize); | ||
Sticky.scrollWatcher.off(this.onScroll); | ||
this.off(['scroll', 'touchstart', 'touchmove', 'touchend'], this.onScroll); | ||
this.off(['resize'], this.onResize); | ||
} | ||
/* | ||
* Anytime new props are received, force re-evaluation | ||
*/ | ||
}, { | ||
key: 'componentWillReceiveProps', | ||
value: function componentWillReceiveProps() { | ||
this.updateHeight(); | ||
key: 'update', | ||
value: function update() { | ||
var height = _reactDom2.default.findDOMNode(this).getBoundingClientRect().height; | ||
var pageY = window.pageYOffset; | ||
var origin = this.refs.placeholder.getBoundingClientRect().top + pageY; | ||
var isSticky = this.isSticky(pageY, origin); | ||
this.setState({ height: height, origin: origin, isSticky: isSticky }); | ||
} | ||
}, { | ||
key: 'pageOffset', | ||
value: function pageOffset() { | ||
return window.pageYOffset || document.documentElement.scrollTop; | ||
key: 'isSticky', | ||
value: function isSticky(pageY, origin) { | ||
return pageY + this.context.offset - this.props.topOffset >= origin && this.context.offset <= (this.context.rect.bottom || 0) - this.props.bottomOffset; | ||
} | ||
/* | ||
* Returns true/false depending on if this should be sticky. | ||
*/ | ||
}, { | ||
key: 'stickyConditionsMet', | ||
value: function stickyConditionsMet() { | ||
var offset = this.pageOffset(); | ||
var origin = this.state.origin - (this.context.offset || 0); | ||
var containerNode = _reactDom2.default.findDOMNode(this.context.container); | ||
// check conditions | ||
var stickyTopConditionsMet = offset >= origin + this.props.topOffset; | ||
var stickyBottomConditionsMet = offset + this.props.bottomOffset < origin + containerNode.getBoundingClientRect().height; | ||
return stickyTopConditionsMet && stickyBottomConditionsMet; | ||
key: 'on', | ||
value: function on(events, callback) { | ||
events.forEach(function (evt) { | ||
window.addEventListener(evt, callback); | ||
}); | ||
} | ||
}, { | ||
key: 'updateOrigin', | ||
value: function updateOrigin() { | ||
var node = _react2.default.findDOMNode(this); | ||
// Do some DOM manipulation to where this element's non-sticky position would be | ||
var previousPosition = node.style.position; | ||
node.style.position = ''; | ||
var origin = node.getBoundingClientRect().top + this.pageOffset(); | ||
node.style.position = previousPosition; | ||
this.setState({ origin: origin }); | ||
key: 'off', | ||
value: function off(events, callback) { | ||
events.forEach(function (evt) { | ||
window.removeEventListener(evt, callback); | ||
}); | ||
} | ||
}, { | ||
key: 'updateHeight', | ||
value: function updateHeight() { | ||
var height = _reactDom2.default.findDOMNode(this).getBoundingClientRect().height; | ||
this.setState({ height: height }); | ||
} | ||
@@ -161,7 +116,23 @@ /* | ||
value: function render() { | ||
var className = this.props.className + ' ' + (this.state.isSticky ? this.props.stickyClass : ''); | ||
var isSticky = this.state.isSticky; | ||
var className = this.props.className; | ||
if (isSticky) className += ' ' + this.props.stickyClassName; | ||
var style = this.props.style; | ||
if (this.state.isSticky) { | ||
style = _extends({}, this.props.style, this.state.stickyStyle, this.props.stickyStyle); | ||
if (isSticky) { | ||
var placeholderRect = this.refs.placeholder.getBoundingClientRect(); | ||
var stickyStyle = { | ||
position: 'fixed', | ||
top: this.context.offset, | ||
left: placeholderRect.left, | ||
width: placeholderRect.width | ||
}; | ||
var bottomLimit = (this.context.rect.bottom || 0) - this.state.height - this.props.bottomOffset; | ||
if (this.context.offset > bottomLimit) { | ||
stickyStyle.top = bottomLimit; | ||
} | ||
style = _extends({}, this.props.style, stickyStyle, this.props.stickyStyle); | ||
} | ||
@@ -171,4 +142,9 @@ | ||
'div', | ||
{ className: className, style: style }, | ||
this.props.children | ||
null, | ||
_react2.default.createElement('div', { ref: 'placeholder', style: { paddingBottom: isSticky ? this.state.height : 0 } }), | ||
_react2.default.createElement( | ||
'div', | ||
_extends({}, this.props, { className: className, style: style }), | ||
this.props.children | ||
) | ||
); | ||
@@ -183,3 +159,4 @@ } | ||
container: _react2.default.PropTypes.any, | ||
offset: _react2.default.PropTypes.number | ||
offset: _react2.default.PropTypes.number, | ||
rect: _react2.default.PropTypes.object | ||
}; | ||
@@ -189,3 +166,3 @@ Sticky.defaultProps = { | ||
style: {}, | ||
stickyClass: 'sticky', | ||
stickyClassName: 'sticky', | ||
stickyStyle: {}, | ||
@@ -196,5 +173,3 @@ topOffset: 0, | ||
}; | ||
Sticky.scrollWatcher = new _watcher2.default(['scroll', 'touchstart', 'touchend']); | ||
Sticky.resizeWatcher = new _watcher2.default(['resize']); | ||
exports.default = Sticky; | ||
module.exports = exports['default']; |
{ | ||
"name": "react-sticky", | ||
"version": "4.0.0-rc9", | ||
"version": "4.0.1-rc1", | ||
"description": "Sticky component for React", | ||
@@ -12,3 +12,3 @@ "main": "lib/index.js", | ||
"prepublish": "npm run clean && npm run build", | ||
"test": "NODE_ENV=test mocha --compilers js:babel-core/register" | ||
"test": "mocha --compilers js:babel-core/register test/unit" | ||
}, | ||
@@ -31,6 +31,4 @@ "repository": { | ||
"dependencies": { | ||
"raf": "^3.2.0", | ||
"react": "^0.14.0", | ||
"react-dom": "^0.14.0", | ||
"simple-signal": "0.0.2" | ||
"react-dom": "^0.14.0" | ||
}, | ||
@@ -47,8 +45,9 @@ "devDependencies": { | ||
"jsdom": "8.0.4", | ||
"lodash": "^3.10.1", | ||
"mocha": "^2.2.5", | ||
"mocha-phantomjs": "^4.0.2", | ||
"react-addons-test-utils": "^0.14.0", | ||
"rimraf": "^2.5.2", | ||
"webpack": "^1.12.14" | ||
"webpack": "^1.12.14", | ||
"zombie": "^4.2.1" | ||
} | ||
} |
react-sticky [![Build Status](https://travis-ci.org/captivationsoftware/react-sticky.svg?branch=master)](https://travis-ci.org/captivationsoftware/react-sticky) | ||
============ | ||
### [Demo](https://captivationsoftware.github.io/react-sticky) | ||
NOTE: Version 4.0.0 is in progress and unavailable on npm -- 3.0.0 [source](https://github.com/captivationsoftware/react-sticky/tree/3.0.0)/[demo](http://www.captivationsoftware.com/react-sticky/) was the last stable version. | ||
NOTE: Version 4.0.0 is in progress -- [3.0.0](https://github.com/captivationsoftware/react-sticky/tree/3.0.0) | ||
was the last stable version. | ||
The most powerful Sticky library available for React! | ||
##### Highlights: | ||
#### Demos | ||
- [Basic](http://rawgit.com/captivationsoftware/react-sticky/master/examples/basic/index.html) | ||
- [Timeline](http://rawgit.com/captivationsoftware/react-sticky/master/examples/timeline/index.html) | ||
#### Highlights | ||
- Fully-nestable, allowing you to build awesome layouts with familiar syntax | ||
@@ -28,3 +29,3 @@ - Sane defaults so you spend less time configuring | ||
The elements you actually want to "stick" should be wrapped in the, you guessed it, `<Sticky />` tag. The full list of props are available below, but typical usage will look something like so: | ||
The elements you actually want to "stick" should be wrapped in the `<Sticky />` tag. The full list of props are available below, but typical usage will look something like so: | ||
@@ -68,7 +69,4 @@ app.jsx | ||
`<StickyContainer />` passes along all props you provide to it without interference*. That's right - no restrictions - go nuts! | ||
`<StickyContainer />` passes along all props you provide to it without interference. That's right - no restrictions - go nuts! | ||
* IMPORTANT: The `style` attribute `padding-top` is managed by React, so avoid setting it with CSS rules. | ||
### `<Sticky />` Props | ||
@@ -90,3 +88,3 @@ | ||
#### stickyClass _(default: 'sticky')_ | ||
#### stickyClassName _(default: 'sticky')_ | ||
You can also specify a class name to be applied when the element becomes sticky: | ||
@@ -98,3 +96,3 @@ | ||
... | ||
<Sticky stickyClass={customClassName}> | ||
<Sticky stickyClassName={customClassName}> | ||
<header /> | ||
@@ -181,7 +179,1 @@ </Sticky> | ||
``` | ||
## License | ||
MIT License | ||
### [![Captivation Software](http://www.captivationsoftware.com/images/logo-dark.png)](http://www.captivationsoftware.com/) |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
2
28514
15
10
490
175
1
- Removedraf@^3.2.0
- Removedsimple-signal@0.0.2
- Removedperformance-now@2.1.0(transitive)
- Removedraf@3.4.1(transitive)
- Removedsimple-signal@0.0.2(transitive)