├── .babelrc ├── src ├── index.js ├── ResizeDetector.jsx └── OverflowDetector.jsx ├── .npmignore ├── .gitignore ├── .eslintrc ├── README.md ├── LICENSE └── package.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-1", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export OverflowDetector from './OverflowDetector'; 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | node_modules/ 3 | playground/ 4 | npm-debug.log 5 | **/.* 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | node_modules/ 3 | playground/ 4 | npm-debug.log 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "airbnb", 3 | "parser": "babel-eslint", 4 | "rules": { 5 | "comma-dangle": ["error", { 6 | "arrays": "always-multiline", 7 | "objects": "always-multiline", 8 | "imports": "always-multiline", 9 | "exports": "always-multiline", 10 | "functions": "never" 11 | }], 12 | "react/forbid-prop-types": "off", 13 | "react/require-default-props": "off", 14 | "react/no-did-mount-set-state": "off", 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-overflow 2 | 3 | [![npm version](https://badge.fury.io/js/react-overflow.svg)](https://badge.fury.io/js/react-overflow) 4 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nickuraltsev/react-overflow/master/LICENSE) 5 | 6 | A React component that detects when it's overflowed by its content. 7 | 8 | ## Installation 9 | 10 | Install `react-overflow` using [npm](https://www.npmjs.org/): 11 | 12 | ``` 13 | npm install --save react-overflow 14 | ``` 15 | 16 | ## Usage 17 | 18 | ```jsx 19 | import { OverflowDetector } from 'react-overflow'; 20 | 21 | function handleOverflowChange(isOverflowed) { 22 | console.log(isOverflowed); 23 | } 24 | 25 | 29 |
Overflowing
30 |
31 | ``` 32 | 33 | ## License 34 | 35 | [MIT](https://github.com/nickuraltsev/react-overflow/blob/master/LICENSE) 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 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. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-overflow", 3 | "version": "0.2.1", 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": "nick.uraltsev@gmail.com" 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 | "dependencies": { 23 | "prop-types": "15.6.0" 24 | }, 25 | "devDependencies": { 26 | "babel-cli": "^6.26.0", 27 | "babel-core": "^6.26.0", 28 | "babel-preset-es2015": "^6.24.1", 29 | "babel-preset-stage-1": "^6.24.1", 30 | "babel-preset-react": "^6.24.1", 31 | "eslint": "^4.11.0", 32 | "eslint-config-airbnb": "^16.1.0", 33 | "eslint-plugin-import": "^2.8.0", 34 | "eslint-plugin-react": "^7.4.0", 35 | "eslint-plugin-jsx-a11y": "^6.0.2", 36 | "babel-eslint": "^8.0.2", 37 | "rimraf": "^2.6.2" 38 | }, 39 | "peerDependencies": { 40 | "react": ">=15" 41 | }, 42 | "prettier": { 43 | "useTabs": false, 44 | "semi": true, 45 | "singleQuote": true, 46 | "trailingComma": "es5", 47 | "bracketSpacing": true 48 | }, 49 | "scripts": { 50 | "clean": "rimraf lib", 51 | "build": "npm run clean && babel src --out-dir lib", 52 | "lint": "eslint src --ext .js,.jsx" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/ResizeDetector.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable jsx-a11y/alt-text */ 2 | import React, { Component } from 'react'; 3 | import PropTypes from 'prop-types'; 4 | 5 | const OBJECT_STYLE = { 6 | display: 'block', 7 | position: 'absolute', 8 | top: 0, 9 | left: 0, 10 | height: '100%', 11 | width: '100%', 12 | overflow: 'hidden', 13 | pointerEvents: 'none', 14 | zIndex: -1, 15 | }; 16 | 17 | export default class ResizeDetector extends Component { 18 | static propTypes = { 19 | onResize: PropTypes.func.isRequired, 20 | }; 21 | 22 | constructor(props) { 23 | super(props); 24 | this.state = { 25 | isMounted: false, 26 | }; 27 | this.setDOMElement = this.setDOMElement.bind(this); 28 | this.handleLoad = this.handleLoad.bind(this); 29 | } 30 | 31 | componentDidMount() { 32 | this.setState({ 33 | isMounted: true, 34 | }); 35 | } 36 | 37 | componentWillUnmount() { 38 | if (this.domElement.contentDocument) { 39 | this.domElement.contentDocument.defaultView.removeEventListener( 40 | 'resize', 41 | this.props.onResize 42 | ); 43 | } 44 | } 45 | 46 | setDOMElement(domElement) { 47 | this.domElement = domElement; 48 | } 49 | 50 | handleLoad() { 51 | this.domElement.contentDocument.defaultView.addEventListener( 52 | 'resize', 53 | this.props.onResize 54 | ); 55 | } 56 | 57 | render() { 58 | return ( 59 | 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/OverflowDetector.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import ResizeDetector from './ResizeDetector'; 4 | 5 | export default class OverflowDetector extends Component { 6 | static propTypes = { 7 | onOverflowChange: PropTypes.func, 8 | children: PropTypes.node, 9 | style: PropTypes.object, 10 | className: PropTypes.string, 11 | }; 12 | 13 | static defaultProps = { 14 | style: {}, 15 | }; 16 | 17 | constructor(props) { 18 | super(props); 19 | this.isOverflowed = false; 20 | this.domElement = null; 21 | this.setDOMElement = this.setDOMElement.bind(this); 22 | this.checkOverflow = this.checkOverflow.bind(this); 23 | } 24 | 25 | componentDidMount() { 26 | this.checkOverflow(); 27 | } 28 | 29 | componentDidUpdate() { 30 | this.checkOverflow(); 31 | } 32 | 33 | setDOMElement(domElement) { 34 | this.domElement = domElement; 35 | } 36 | 37 | checkOverflow() { 38 | const isOverflowed = 39 | this.domElement.scrollWidth > this.domElement.clientWidth || 40 | this.domElement.scrollHeight > this.domElement.clientHeight; 41 | 42 | if (isOverflowed !== this.isOverflowed) { 43 | this.isOverflowed = isOverflowed; 44 | if (this.props.onOverflowChange) { 45 | this.props.onOverflowChange(isOverflowed); 46 | } 47 | } 48 | } 49 | 50 | render() { 51 | const { style, className, children } = this.props; 52 | return ( 53 |
58 | {children} 59 | 60 |
61 | ); 62 | } 63 | } 64 | --------------------------------------------------------------------------------