├── .babelrc ├── .eslintrc.js ├── .gitignore ├── .npmignore ├── .travis.yml ├── .vscode └── settings.json ├── CHANGELOG.md ├── README.md ├── build ├── 0.d27f029f.js └── bundle.0ac048ec.js ├── index.html ├── jest.config.js ├── jest.init.js ├── package-lock.json ├── package.json ├── src ├── README.md └── index.js ├── styleguide.config.js ├── styles.css └── tests └── visible.test.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015","stage-0", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 'avraam', 'plugin:react/recommended' ], 3 | globals: { 4 | React: false, 5 | ReactDOM: false 6 | }, 7 | rules: { 8 | 'class-methods-use-this': 0, 9 | 'consistent-return': 0, 10 | 'no-return-assign': 0, 11 | 'max-len': 0, 12 | } 13 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | coverage -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | tests/ 3 | .eslintrc 4 | jest.* 5 | styleguide.config.js 6 | travis.yml -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | notifications: 3 | email: false 4 | language: node_js 5 | cache: 6 | directories: 7 | - node_modules 8 | node_js: 9 | - "8" 10 | before_script: 11 | - npm i 12 | script: 13 | - npm test 14 | after_success: 15 | - 'curl -Lo travis_after_all.py https://git.io/travis_after_all' 16 | - python travis_after_all.py 17 | - export $(cat .to_export_back) &> /dev/null 18 | branches: 19 | only: 20 | - master 21 | - /^greenkeeper/.*$/ -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "tslint.enable": false 3 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | #### 2.0.6 (2018-09-03) 2 | 3 | ##### Chores 4 | 5 | * **package:** 6 | * update enzyme-adapter-react-16 to version 1.3.1 ([#16](https://github.com/AvraamMavridis/react-intersection-visible/pull/16)) ([705d7b7e](https://github.com/AvraamMavridis/react-intersection-visible/commit/705d7b7eaf571bca2d309525c57ed371d74a821e)) 7 | * update babel-loader to version 8.0.0 ([#15](https://github.com/AvraamMavridis/react-intersection-visible/pull/15)) ([a51b605f](https://github.com/AvraamMavridis/react-intersection-visible/commit/a51b605f67c1124135b2ea1b5cfe36f17ca30995)) 8 | 9 | #### 2.0.5 (2018-08-28) 10 | 11 | ##### Chores 12 | 13 | * Update lock ([d752cbcf](https://github.com/AvraamMavridis/react-intersection-visible/commit/d752cbcf355507744b83c939a18daece666bb376)) 14 | * **package:** update babel-eslint to version 9.0.0 ([#14](https://github.com/AvraamMavridis/react-intersection-visible/pull/14)) ([a787547f](https://github.com/AvraamMavridis/react-intersection-visible/commit/a787547f067d56ac2bac6d4c7e49fc71c841c39e)) 15 | 16 | #### 2.0.4 (2018-08-26) 17 | 18 | ##### Chores 19 | 20 | * **package:** update enzyme to version 3.4.4 ([#12](https://github.com/AvraamMavridis/react-intersection-visible/pull/12)) ([b27bf91c](https://github.com/AvraamMavridis/react-intersection-visible/commit/b27bf91cac8d417c02e268a25104a67e1dd9f58e)) 21 | 22 | #### 2.0.3 (2018-08-21) 23 | 24 | ##### Documentation Changes 25 | 26 | * Update documentation page ([4f4c6a1a](https://github.com/AvraamMavridis/react-intersection-visible/commit/4f4c6a1acc875e0e628932f95b5194ad56e89c42)) 27 | 28 | #### 2.0.2 (2018-08-21) 29 | 30 | ##### Chores 31 | 32 | * Update package.json ([333417b5](https://github.com/AvraamMavridis/react-intersection-visible/commit/333417b56d51218727a03aabd87ebbda439e95f5)) 33 | * Add lock file ([c534fb04](https://github.com/AvraamMavridis/react-intersection-visible/commit/c534fb04140bd80747b15c9560e0f08e7d3c6d6a)) 34 | * Fix fork link on Documentation ([c6c6ed6d](https://github.com/AvraamMavridis/react-intersection-visible/commit/c6c6ed6da19424c685fdbf04975957bfc437ea23)) 35 | 36 | #### 2.0.1 (2018-08-16) 37 | 38 | ##### Chores 39 | 40 | * Remove conflicting depedency ([f6b8ca29](https://github.com/AvraamMavridis/react-intersection-visible/commit/f6b8ca29252edbabe5b246cecffe26084c34027d)) 41 | 42 | ##### Documentation Changes 43 | 44 | * Update documentation ([48059370](https://github.com/AvraamMavridis/react-intersection-visible/commit/48059370374135aafe26bf21b883da6e443373cb)) 45 | 46 | ## 2.0.0 (2018-08-16) 47 | 48 | ##### Chores 49 | 50 | * Update dependencies to enable Greenkeeper 🌴 ([#11](https://github.com/AvraamMavridis/react-intersection-visible/pull/11)) ([caac7653](https://github.com/AvraamMavridis/react-intersection-visible/commit/caac765317cbc3245dc18225390d56e4d4fa1df1)) 51 | * Remove yarn.lock ([f2613243](https://github.com/AvraamMavridis/react-intersection-visible/commit/f26132435ed5e9aaabc25b6360b490986ea6ecbb)) 52 | * Add yarn.lock ([96f8955b](https://github.com/AvraamMavridis/react-intersection-visible/commit/96f8955b1b96a7ea9d84996b0c3489edf95a6792)) 53 | * Add raf polyfill ([04d37d48](https://github.com/AvraamMavridis/react-intersection-visible/commit/04d37d48dcba13247f9aa5d1106334f2ad767c63)) 54 | * Rename file ([e1ec5c70](https://github.com/AvraamMavridis/react-intersection-visible/commit/e1ec5c70a479904764414bcedb5b87dd425e4cbb)) 55 | * fix type on the tests ([91efbbde](https://github.com/AvraamMavridis/react-intersection-visible/commit/91efbbdee20589c8333a67008b224f4535938352)) 56 | 57 | ##### Documentation Changes 58 | 59 | * Update Readme ([f18b6734](https://github.com/AvraamMavridis/react-intersection-visible/commit/f18b67349ba14e1848b111a33581a7cf2e45787e)) 60 | * Add demo ([7b5e2476](https://github.com/AvraamMavridis/react-intersection-visible/commit/7b5e2476a37ba1e21e388947fdcba765adff4081)) 61 | * Tidy the project, add docs/demo ([b399277f](https://github.com/AvraamMavridis/react-intersection-visible/commit/b399277f8129fd957e36a61b2fb8dbb88e5b5fcd)) 62 | 63 | ##### Bug Fixes 64 | 65 | * refs syntax to be compatible with latest react ([#6](https://github.com/AvraamMavridis/react-intersection-visible/pull/6)) ([6b8da705](https://github.com/AvraamMavridis/react-intersection-visible/commit/6b8da70598c7b6f20101e61064d4db53c1fcb113)) 66 | 67 | ##### Other Changes 68 | 69 | * Add travis badge ([c0dba190](https://github.com/AvraamMavridis/react-intersection-visible/commit/c0dba190c345e67a31c709ba3c30288f942c725f)) 70 | 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-intersection-visible 2 | HOC-wrapper Component that helps you track when an element enters in the viewport. It uses the new [IntersectionObserver API](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) 3 | with polyfill fallback 4 | 5 | [Demo](http://avraammavridis.github.io/react-intersection-visible/) 6 | 7 | [![Build Status](https://travis-ci.org/AvraamMavridis/react-intersection-visible.svg?branch=master)](https://travis-ci.org/AvraamMavridis/react-intersection-visible) [![Greenkeeper badge](https://badges.greenkeeper.io/AvraamMavridis/react-intersection-visible.svg)](https://greenkeeper.io/) 8 | 9 | ### How to use 10 | 11 | 1. Import `IntersectionVisible` hoc component 12 | 2. Wrap your main component with the `IntersectionVisible` 13 | 3. Provide the options and callbacks you want 14 | 15 | 16 | 17 | ### Example 18 | 19 | 20 | ```javascript 21 | import React, { Component } from 'react'; 22 | import ReactDOM from 'react-dom'; 23 | import IntersectionVisible from 'react-intersection-visible'; 24 | 25 | class YourComponent extends Component 26 | { 27 | 28 | onHide( entries ) 29 | { 30 | // do something 31 | } 32 | 33 | onShow( entries ) 34 | { 35 | // do something 36 | } 37 | 38 | onIntersect( entries ) 39 | { 40 | // do something 41 | } 42 | 43 | render(){ 44 | return ( this.onIntersect( e ) } 45 | onHide={ e => this.onHide( e ) } 46 | onShow={ e => this.onShow( e ) }> 47 |
48 | blah blah blah blah blah blah blah blah blah blah blah 49 | blah blah blah blah blah blah blah blah blah 50 |
51 |
); 52 | } 53 | } 54 | 55 | ``` 56 | 57 | ### Options: 58 | 59 | | Name | Description 60 | | ------------- |-------------:| 61 | | onIntersect | Function that is called when the visibility status of the element change | 62 | | onHide | Function that is called when the element becomes invisible | 63 | | onShow | Function that is called when the element becomes visible | 64 | | options | Object, with the extras options supported by the IntersectionObserver API (root, rootMargin, threshold)| 65 | 66 | More about the options [here](https://developers.google.com/web/updates/2016/04/intersectionobserver?hl=en) 67 | 68 | ### Contribute 69 | 70 | Any pull-request is more than welcome :boom: :smile: 71 | 72 | ### License 73 | 74 | MIT 75 | 76 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | IntersectionVisible
-------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | verbose: true, 3 | transform: { 4 | '^.+\\.js$': 'babel-jest' 5 | }, 6 | testURL: 'http://localhost', 7 | setupFiles: [ './jest.init.js' ], 8 | testMatch: [ '**/tests/**/*.js?(x)', '**/?(*.)(spec|test).js?(x)' ], 9 | modulePaths: [ '/src', '/test', '/node_modules' ], 10 | coverageDirectory: './coverage/', 11 | collectCoverage: true, 12 | collectCoverageFrom: [ 13 | '**/src/*.{js,jsx}', 14 | ] 15 | }; -------------------------------------------------------------------------------- /jest.init.js: -------------------------------------------------------------------------------- 1 | import Enzyme from 'enzyme'; 2 | import Adapter from 'enzyme-adapter-react-16'; 3 | import 'babel-polyfill'; 4 | import 'raf'; 5 | 6 | Enzyme.configure({ adapter: new Adapter() }); 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-intersection-visible", 3 | "version": "2.1.0", 4 | "homepage": "https://github.com/AvraamMavridis/react-intersection-visible", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/AvraamMavridis/react-intersection-visible" 8 | }, 9 | "author": "Avraam Mavridis ", 10 | "description": "react intersection visible", 11 | "scripts": { 12 | "start": "styleguidist server", 13 | "build": "styleguidist build", 14 | "release:major": "generate-changelog -M && git add CHANGELOG.md && git commit -m 'updated CHANGELOG.md' && npm version major && git push origin && git push origin --tags && npm publish", 15 | "release:minor": "generate-changelog -m && git add CHANGELOG.md && git commit -m 'updated CHANGELOG.md' && npm version minor && git push origin && git push origin --tags && npm publish", 16 | "release:patch": "generate-changelog -p && git add CHANGELOG.md && git commit -m 'updated CHANGELOG.md' && npm version patch && git push origin && git push origin --tags && npm publish", 17 | "prepublish": "npm run test && npm run compile", 18 | "compile": "./node_modules/.bin/babel ./src/ --out-dir ./lib/", 19 | "styleguide": "styleguidist server", 20 | "styleguide:build": "styleguidist build", 21 | "lint": "eslint ./src --fix", 22 | "test": "jest", 23 | "watch": "npm-scripts-watcher", 24 | "example": "webpack-dev-server" 25 | }, 26 | "main": "./lib/index.js", 27 | "watch": { 28 | "src/**/*.js": [ 29 | "compile" 30 | ] 31 | }, 32 | "keywords": [ 33 | "react", 34 | "visible", 35 | "intersection", 36 | "dom", 37 | "show", 38 | "hide" 39 | ], 40 | "license": "MIT", 41 | "peerDependencies": { 42 | "react": "^16.0.0", 43 | "react-dom": "^16.0.0" 44 | }, 45 | "devDependencies": { 46 | "babel-cli": "^6.9.0", 47 | "babel-core": "^6.7.4", 48 | "babel-eslint": "^9.0.0", 49 | "babel-jest": "^23.4.2", 50 | "babel-loader": "^8.0.0", 51 | "babel-preset-es2015": "^6.22.0", 52 | "babel-preset-react": "^6.22.0", 53 | "babel-preset-stage-0": "^6.1.18", 54 | "babel-register": "^6.6.0", 55 | "codecov": "^3.0.4", 56 | "enzyme": "^3.5.1", 57 | "enzyme-adapter-react-16": "^1.4.0", 58 | "eslint": "^5.3.0", 59 | "eslint-config-airbnb-base": "^13.0.0", 60 | "eslint-config-avraam": "^1.0.0", 61 | "eslint-plugin-import": "^2.13.0", 62 | "eslint-plugin-react": "^7.11.1", 63 | "generate-changelog": "^1.7.1", 64 | "jest": "^23.5.0", 65 | "mocha": "^5.2.0", 66 | "raf": "^3.4.0", 67 | "react": "^16.4.2", 68 | "react-addons-test-utils": "^15.4.2", 69 | "react-dom": "^16.4.2", 70 | "react-scripts": "latest", 71 | "react-styleguidist": "^8.0.0", 72 | "react-test-renderer": "^16.4.2" 73 | }, 74 | "dependencies": { 75 | "prop-types": "^15.6.1" 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | function setColor(color){ 3 | document.querySelector('body').style.backgroundColor = color 4 | document.querySelector('.rsg--root-1').style.backgroundColor = color 5 | } 6 | 7 | 8 | console.log(entries)} 10 | onShow={() => setColor('#FFA0FD')} 11 | onHide={() => setColor('#FFE1EA')} 12 | className="element" 13 | > 14 |
24 | The background color of the body changes depending on the visibility of this box. 25 | Scroll to see! 26 |
27 |
28 | ``` 29 | 30 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | /** 5 | * Track the visitibity of the wrapped components 6 | * 7 | *
8 | * [![codecov](https://codecov.io/gh/AvraamMavridis/react-intersection-visible/branch/master/graph/badge.svg)](https://codecov.io/gh/AvraamMavridis/react-intersection-visible) [![Build Status](https://travis-ci.org/AvraamMavridis/react-intersection-visible.svg?branch=master)](https://travis-ci.org/AvraamMavridis/react-intersection-visible) [![Greenkeeper badge](https://badges.greenkeeper.io/AvraamMavridis/react-intersection-visible.svg)](https://greenkeeper.io/) 9 | *
10 | * 11 | * @export 12 | * @class IntersectionVisible 13 | * @extends {Component} 14 | */ 15 | export default class IntersectionVisible extends Component { 16 | static propTypes = { 17 | /** Enable/disable the component */ 18 | active: PropTypes.bool, 19 | 20 | /** The wrapped component */ 21 | children: PropTypes.oneOfType([ PropTypes.node, PropTypes.func ]), 22 | 23 | /** Class passed to the wrapper */ 24 | className: PropTypes.string, 25 | 26 | /** 27 | * Gets called when the wrapped component is visible 28 | * 29 | * @param {IntersectionObserverEntry} entries - Read more... 30 | */ 31 | onHide: PropTypes.func, 32 | 33 | /** 34 | * Gets called when wrapped component interesects 35 | * 36 | * @param {IntersectionObserverEntry} entries - Read more... 37 | */ 38 | onIntersect: PropTypes.func.isRequired, 39 | 40 | /** 41 | * Gets called when the wrapped component is visible 42 | * 43 | * @param {IntersectionObserverEntry} entries - Read more... 44 | */ 45 | onShow: PropTypes.func, 46 | 47 | /** 48 | * Options passed to configure the listener 49 | */ 50 | options: PropTypes.shape({ 51 | /** The element that is used as the viewport for checking visiblity of the target. Must be the ancestor of the target. Defaults to the browser viewport if not specified or if null. */ 52 | root: PropTypes.node, 53 | 54 | /** 55 | * Margin around the root. Can have values similar to the CSS margin property, e.g. "10px 20px 30px 40px" (top, right, bottom, left). The values can be percentages. This set of values serves to grow or shrink each side of the root element's bounding box before computing intersections. Defaults to all zeros. 56 | */ 57 | rootMargin: PropTypes.string, 58 | /** 59 | * Either a single number or an array of numbers which indicate at what percentage of the target's visibility the observer's callback should be executed. If you only want to detect when visibility passes the 50% mark, you can use a value of 0.5. If you want the callback run every time visibility passes another 25%, you would specify the array [0, 0.25, 0.5, 0.75, 1]. The default is 0 (meaning as soon as even one pixel is visible, the callback will be run). A value of 1.0 means that the threshold isn't considered passed until every pixel is visible. 60 | */ 61 | threshold: PropTypes.oneOfType([ PropTypes.number, PropTypes.arrayOf(PropTypes.number) ]) 62 | }) 63 | }; 64 | 65 | static defaultProps = { 66 | active: true, 67 | className: 'intersection-visible-wrapper', 68 | onHide: () => null, 69 | onShow: () => null, 70 | onIntersect: () => null, 71 | }; 72 | 73 | /** 74 | * Handles the visibility changes 75 | * 76 | * @param {array} entries 77 | */ 78 | handleObserverUpdate = entries => { 79 | const { 80 | onIntersect, 81 | onShow, 82 | onHide 83 | } = this.props; 84 | const { 85 | intersectionRect 86 | } = entries[0]; 87 | const { 88 | top, 89 | left, 90 | bottom, 91 | right 92 | } = intersectionRect; 93 | 94 | if ([ top, bottom, left, right ].some(Boolean) && onShow) { 95 | onShow(entries); 96 | } else if (onHide) { 97 | onHide(entries); 98 | } 99 | 100 | onIntersect(entries); 101 | }; 102 | 103 | /** 104 | * Starts the observer 105 | */ 106 | startObserving() { 107 | this.observer.observe(this.node); 108 | } 109 | 110 | /** 111 | * Stops the observer 112 | */ 113 | stopObserving() { 114 | this.observer.unobserve(this.node); 115 | } 116 | 117 | /** 118 | * Start the observer when the component is mounted 119 | */ 120 | componentDidMount() { 121 | const { 122 | options 123 | } = this.props; 124 | this.observer = new IntersectionObserver(this.handleObserverUpdate, options); 125 | 126 | if (this.props.active) { 127 | this.startObserving(); 128 | } 129 | } 130 | 131 | /** 132 | * Update observer state on prop changes 133 | */ 134 | componentDidUpdate(prevProps) { 135 | if (this.props.active && !prevProps.active) { 136 | this.startObserving(); 137 | } 138 | 139 | if (!this.props.active && prevProps.active) { 140 | this.stopObserving(); 141 | } 142 | } 143 | 144 | /** 145 | * Stop the observer on unmounting 146 | */ 147 | componentWillUnmount() { 148 | this.observer.disconnect(); 149 | } 150 | 151 | /** 152 | * Render component 153 | * 154 | * @returns {JSX.Element} 155 | */ 156 | render() { 157 | const { 158 | className 159 | } = this.props; 160 | return
this.node = node}> 161 | {this.props.children} 162 |
; 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /styleguide.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | require: [ 5 | 'babel-polyfill', 6 | path.join(__dirname, './styles.css') 7 | ], 8 | components: 'src/index.js', 9 | exampleMode: 'expand', 10 | usageMode: 'expand', 11 | title: 'IntersectionVisible', 12 | styleguideDir: path.join(__dirname, '/'), 13 | ribbon: { 14 | // Link to open on the ribbon click (required) 15 | url: 'https://github.com/AvraamMavridis/react-intersection-visible', 16 | // Text to show on the ribbon (optional) 17 | text: 'Fork me on GitHub' 18 | }, 19 | showSidebar: false, 20 | theme: { 21 | color: { 22 | base: '#001514', 23 | light: '#001514', 24 | lightest: '#001514', 25 | name: '#001514', 26 | type: '#001514', 27 | error: '#001514', 28 | ribbonBackground: '#001514', 29 | link: '#001514', 30 | linkHover: '#001514', 31 | border: '#001514' 32 | } 33 | }, 34 | editorConfig: { 35 | theme: 'dracula', 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | svg, .rsg--pathline-28 { 2 | display: none; 3 | } 4 | 5 | body { 6 | height: 2000px; 7 | } -------------------------------------------------------------------------------- /tests/visible.test.js: -------------------------------------------------------------------------------- 1 | import { mount } from 'enzyme'; 2 | import React from 'react'; 3 | import Visible from '../src/index'; 4 | 5 | window.IntersectionObserver = jest.fn().mockImplementation(() => { 6 | return { 7 | observe: jest.fn(), 8 | unobserve: jest.fn(), 9 | disconnect: jest.fn(), 10 | }; 11 | }); 12 | 13 | describe('', () => { 14 | it('should have a wrapper div with the passed className', () => { 15 | const onIntersect = jest.fn(); 16 | const wrapper = mount(); 17 | const div = wrapper.find('div'); 18 | expect(div.length).toBe(1); 19 | expect(div.prop('className')).toBe('visible'); 20 | }); 21 | 22 | it('should have an observer', () => { 23 | const onIntersect = jest.fn(); 24 | const wrapper = mount(); 25 | const { observer } = wrapper.instance(); 26 | expect(observer).toBeDefined(); 27 | }); 28 | 29 | it('should start observing if active prop is true', () => { 30 | const onIntersect = jest.fn(); 31 | Visible.prototype.startObserving = jest.fn(); 32 | const wrapper = mount(); 33 | wrapper.instance().startObserving = jest.fn(); 34 | expect(Visible.prototype.startObserving).toHaveBeenCalled(); 35 | Visible.prototype.startObserving.mockReset(); 36 | }); 37 | 38 | it('should not start observing if active prop is false', () => { 39 | const onIntersect = jest.fn(); 40 | Visible.prototype.startObserving = jest.fn(); 41 | const wrapper = mount(); 42 | wrapper.instance().startObserving = jest.fn(); 43 | expect(Visible.prototype.startObserving).not.toHaveBeenCalled(); 44 | }); 45 | 46 | it('should disconect observer onComponentUnmount', () => { 47 | const onIntersect = jest.fn(); 48 | const wrapper = mount(); 49 | const instance = wrapper.instance(); 50 | wrapper.unmount(); 51 | expect(instance.observer.disconnect).toHaveBeenCalled(); 52 | }); 53 | 54 | it('should call unobserve of the observer, when stopObserving is called', () => { 55 | const onIntersect = jest.fn(); 56 | const wrapper = mount(); 57 | const instance = wrapper.instance(); 58 | instance.stopObserving(); 59 | expect(instance.observer.unobserve).toHaveBeenCalled(); 60 | }); 61 | 62 | it('should start observing on props change if active is true', () => { 63 | const onIntersect = jest.fn(); 64 | const wrapper = mount(); 65 | const instance = wrapper.instance(); 66 | instance.startObserving = jest.fn(); 67 | wrapper.setProps({ active: true }); 68 | expect(instance.startObserving).toHaveBeenCalled(); 69 | }); 70 | 71 | it('should stop observing on props change if active is false', () => { 72 | const onIntersect = jest.fn(); 73 | const wrapper = mount(); 74 | const instance = wrapper.instance(); 75 | instance.stopObserving = jest.fn(); 76 | wrapper.setProps({ active: false }); 77 | expect(instance.stopObserving).toHaveBeenCalled(); 78 | }); 79 | 80 | it('should stop observing on props change if active is false', () => { 81 | const onIntersect = jest.fn(); 82 | const onShow = jest.fn(); 83 | const wrapper = mount(); 84 | const instance = wrapper.instance(); 85 | instance.handleObserverUpdate([ { 86 | intersectionRect: { 87 | top: 1, bottom: 1, left: 1, right: 1 88 | } 89 | } ]); 90 | expect(onShow).toHaveBeenCalled(); 91 | }); 92 | 93 | it('should stop observing on props change if active is false', () => { 94 | const onIntersect = jest.fn(); 95 | const onHide = jest.fn(); 96 | const wrapper = mount(); 97 | const instance = wrapper.instance(); 98 | instance.handleObserverUpdate([ { 99 | intersectionRect: { 100 | top: 0, bottom: 0, left: 0, right: 0 101 | } 102 | } ]); 103 | expect(onHide).toHaveBeenCalled(); 104 | }); 105 | 106 | it('should stop observing on props change if active is false', () => { 107 | const onIntersect = jest.fn(); 108 | const wrapper = mount(); 109 | const instance = wrapper.instance(); 110 | instance.handleObserverUpdate([ { 111 | intersectionRect: { 112 | top: 0, bottom: 0, left: 0, right: 0 113 | } 114 | } ]); 115 | expect(onIntersect).toHaveBeenCalled(); 116 | }); 117 | }); 118 | --------------------------------------------------------------------------------