Skip to content

Commit c2b048b

Browse files
committed
First commit
0 parents  commit c2b048b

10 files changed

+241
-0
lines changed

.babelrc

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"presets": ["es2015", "stage-1", "react"]
3+
}

.eslintrc

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "airbnb",
3+
"parser": "babel-eslint",
4+
"rules": {
5+
"react/forbid-prop-types": "off",
6+
"react/require-default-props": "off",
7+
"react/no-did-mount-set-state": "off"
8+
}
9+
}

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
lib/
2+
node_modules/
3+
playground/
4+
npm-debug.log
5+
.DS_Store

.npmignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
src/
2+
node_modules/
3+
playground/
4+
npm-debug.log
5+
**/.*

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2017-present Nick Uraltsev
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.md

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# react-overflow
2+
3+
A React component that detects when it's overflowed by its content.
4+
5+
## Installation
6+
7+
Install `react-overflow` using [npm](https://www.npmjs.org/):
8+
9+
```
10+
npm install --save react-overflow
11+
```
12+
13+
## Usage
14+
15+
```jsx
16+
import { OverflowDetector } from 'react-overflow';
17+
18+
function handleOverflowChange(isOverflowed) {
19+
console.log(isOverflowed);
20+
}
21+
22+
<OverflowDetector
23+
onOverflowChange={handleOverflowChange}
24+
style={{ width: '100px' }}
25+
>
26+
<div style={{ width: '200px' }}>Overflowing</div>
27+
</OverflowDetector>
28+
```
29+
30+
## License
31+
32+
[MIT](https://github.com/nickuraltsev/react-overflow/blob/master/LICENSE)

package.json

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"name": "react-overflow",
3+
"version": "0.1.0",
4+
"description": "A React component that detects when it's overflowed by its content",
5+
"keywords": [
6+
"react",
7+
"overflow"
8+
],
9+
"author": {
10+
"name": "Nick Uraltsev",
11+
"email": "[email protected]"
12+
},
13+
"repository": {
14+
"type": "git",
15+
"url": "https://github.com/nickuraltsev/react-overflow.git"
16+
},
17+
"bugs": {
18+
"url": "https://github.com/nickuraltsev/react-overflow/issues"
19+
},
20+
"license": "MIT",
21+
"main": "lib/index.js",
22+
"devDependencies": {
23+
"babel-cli": "^6.24.0",
24+
"babel-core": "^6.24.0",
25+
"babel-preset-es2015": "^6.24.0",
26+
"babel-preset-stage-1": "^6.22.0",
27+
"babel-preset-react": "^6.24.1",
28+
"eslint": "^3.18.0",
29+
"eslint-config-airbnb": "^14.1.0",
30+
"eslint-plugin-import": "^2.2.0",
31+
"eslint-plugin-react": "^6.10.3",
32+
"eslint-plugin-jsx-a11y": "^4.0.0",
33+
"babel-eslint": "^7.2.1",
34+
"rimraf": "^2.6.1"
35+
},
36+
"peerDependencies": {
37+
"react": "^15.0.0",
38+
"react-dom": "^15.0.0"
39+
},
40+
"scripts": {
41+
"clean": "rimraf lib",
42+
"build": "npm run clean && babel src --out-dir lib",
43+
"lint": "eslint src --ext .js,.jsx"
44+
}
45+
}

src/OverflowDetector.jsx

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import React, { Component, PropTypes } from 'react';
2+
import ResizeDetector from './ResizeDetector';
3+
4+
export default class OverflowDetector extends Component {
5+
static propTypes = {
6+
onOverflowChange: PropTypes.func,
7+
children: PropTypes.node,
8+
style: PropTypes.object,
9+
className: PropTypes.string,
10+
};
11+
12+
static defaultProps = {
13+
style: {},
14+
};
15+
16+
constructor(props) {
17+
super(props);
18+
this.isOverflowed = false;
19+
this.domElement = null;
20+
this.setDOMElement = this.setDOMElement.bind(this);
21+
this.checkOverflow = this.checkOverflow.bind(this);
22+
}
23+
24+
componentDidMount() {
25+
this.checkOverflow();
26+
}
27+
28+
componentDidUpdate() {
29+
this.checkOverflow();
30+
}
31+
32+
setDOMElement(domElement) {
33+
this.domElement = domElement;
34+
}
35+
36+
checkOverflow() {
37+
const isOverflowed =
38+
this.domElement.scrollWidth > this.domElement.clientWidth ||
39+
this.domElement.scrollHeight > this.domElement.scrollHeight;
40+
41+
if (isOverflowed !== this.isOverflowed) {
42+
this.isOverflowed = isOverflowed;
43+
if (this.props.onOverflowChange) {
44+
this.props.onOverflowChange(isOverflowed);
45+
}
46+
}
47+
}
48+
49+
render() {
50+
const { style, className, children } = this.props;
51+
return (
52+
<div
53+
ref={this.setDOMElement}
54+
style={{ ...style, position: 'relative' }}
55+
className={className}
56+
>
57+
{children}
58+
<ResizeDetector onResize={this.checkOverflow} />
59+
</div>
60+
);
61+
}
62+
}

src/ResizeDetector.jsx

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React, { Component, PropTypes } from 'react';
2+
3+
const OBJECT_STYLE = {
4+
display: 'block',
5+
position: 'absolute',
6+
top: 0,
7+
left: 0,
8+
height: '100%',
9+
width: '100%',
10+
overflow: 'hidden',
11+
pointerEvents: 'none',
12+
zIndex: -1,
13+
};
14+
15+
export default class ResizeDetector extends Component {
16+
static propTypes = {
17+
onResize: PropTypes.func.isRequired,
18+
};
19+
20+
constructor(props) {
21+
super(props);
22+
this.state = {
23+
isMounted: false,
24+
};
25+
this.setDOMElement = this.setDOMElement.bind(this);
26+
this.handleLoad = this.handleLoad.bind(this);
27+
}
28+
29+
componentDidMount() {
30+
this.setState({
31+
isMounted: true,
32+
});
33+
}
34+
35+
componentWillUnmount() {
36+
this.domElement.contentDocument.defaultView.removeEventListener('resize', this.props.onResize);
37+
}
38+
39+
setDOMElement(domElement) {
40+
this.domElement = domElement;
41+
}
42+
43+
handleLoad() {
44+
this.domElement.contentDocument.defaultView.addEventListener('resize', this.props.onResize);
45+
}
46+
47+
render() {
48+
return (
49+
<object
50+
style={OBJECT_STYLE}
51+
type="text/html"
52+
data={this.state.isMounted ? 'about:blank' : null}
53+
ref={this.setDOMElement}
54+
onLoad={this.handleLoad}
55+
/>
56+
);
57+
}
58+
}

src/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export OverflowDetector from './OverflowDetector';

0 commit comments

Comments
 (0)