diff --git a/.all-contributorsrc b/.all-contributorsrc index fc422a1..d50495d 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -72,6 +72,17 @@ "contributions": [ "doc" ] + }, + { + "login": "GeKorm", + "name": "George Kormaris", + "avatar_url": "https://avatars3.githubusercontent.com/u/6104345?v=4", + "profile": "http://www.gekorm.com", + "contributions": [ + "code", + "doc", + "ideas" + ] } ], "repoType": "github" diff --git a/README.md b/README.md index fb80361..a2e49fa 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-7-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-8-orange.svg?style=flat-square)](#contributors) [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] @@ -48,6 +48,8 @@ Read the [introduction](introduction.md). - [theme](#theme) - [threshold](#threshold) - [width](#width) + - [observer](#observer) + - [children](#children) - [Other Solutions](#other-solutions) - [Contributors](#contributors) - [LICENSE](#license) @@ -73,6 +75,7 @@ Example for create-react-app (you need v2 for macros) based project ```js import React from 'react' import lqip from 'lqip.macro' +import Waypoint from 'react-waypoint' import IdealImage from 'react-ideal-image' import image from './images/doggo.jpg' @@ -85,6 +88,7 @@ const App = () => ( alt="doggo" width={3500} height={2095} + observer={Waypoint} /> ) ``` @@ -217,6 +221,33 @@ Tells how much to wait in milliseconds until consider the download to be slow. Width of the image in px. +### observer + +> `function({onEnter, onLeave, children})` | optional + +A visibility observer component, like react-waypoint, used for lazy-loading. + +### children + +> `function({onEnter, onLeave, children}) | React.Element` | optional + +Observer, used instead of the `observer` prop. Can either be a render prop or a React element + +```js + + // onEnter and onLeave are passed automatically + +``` + +If neither `observer` nor `children` is passed, the image will be treated as visible in the viewport + ## Other Solutions - [react-progressive-image](https://github.com/FormidableLabs/react-progressive-image) @@ -239,7 +270,7 @@ Thanks goes to these people ([emoji key][emojis]): | [
stereobooster](https://github.com/stereobooster)
[💻](https://github.com/stereobooster/react-ideal-image/commits?author=stereobooster "Code") [📖](https://github.com/stereobooster/react-ideal-image/commits?author=stereobooster "Documentation") [🚇](#infra-stereobooster "Infrastructure (Hosting, Build-Tools, etc)") [⚠️](https://github.com/stereobooster/react-ideal-image/commits?author=stereobooster "Tests") | [
Ivan Babak](https://github.com/sompylasar)
[📖](https://github.com/stereobooster/react-ideal-image/commits?author=sompylasar "Documentation") | [
Arun Kumar](https://github.com/palerdot)
[📖](https://github.com/stereobooster/react-ideal-image/commits?author=palerdot "Documentation") | [
Andrew Lisowski](http://hipstersmoothie.com)
[💻](https://github.com/stereobooster/react-ideal-image/commits?author=hipstersmoothie "Code") | [
Timothy Vernon](https://github.com/tvthatsme)
[⚠️](https://github.com/stereobooster/react-ideal-image/commits?author=tvthatsme "Tests") | [
vishalShinde](http://vs1682.github.io)
[📖](https://github.com/stereobooster/react-ideal-image/commits?author=vs1682 "Documentation") | [
Evgeniy Kumachev](https://github.com/EvgeniyKumachev)
[📖](https://github.com/stereobooster/react-ideal-image/commits?author=EvgeniyKumachev "Documentation") | | :---: | :---: | :---: | :---: | :---: | :---: | :---: | - +| [
George Kormaris](http://www.gekorm.com)
[💻](https://github.com/stereobooster/react-ideal-image/commits?author=GeKorm "Code") [📖](https://github.com/stereobooster/react-ideal-image/commits?author=GeKorm "Documentation") [🤔](#ideas-GeKorm "Ideas, Planning, & Feedback") | This project follows the [all-contributors][all-contributors] specification. diff --git a/src/components/IdealImage/index.js b/src/components/IdealImage/index.js index 778de3e..ec201ce 100644 --- a/src/components/IdealImage/index.js +++ b/src/components/IdealImage/index.js @@ -1,6 +1,5 @@ -import React, {Component} from 'react' +import React, {Component, cloneElement} from 'react' import PropTypes from 'prop-types' -import Waypoint from 'react-waypoint' import Media from '../Media' import {icons, loadStates} from '../constants' import {xhrLoader, imageLoader, timeout, combineCancel} from '../loaders' @@ -162,6 +161,10 @@ export default class IdealImage extends Component { icons: PropTypes.object.isRequired, /** theme object - CSS Modules or React styles */ theme: PropTypes.object.isRequired, + /** visibility observer component, like react-waypoint */ + observer: PropTypes.func, + /** visibility observer component, like react-waypoint */ + children: PropTypes.oneOfType([PropTypes.func, PropTypes.element]), } static defaultProps = { @@ -320,8 +323,10 @@ export default class IdealImage extends Component { ...this.state, size: pickedSrc.size, }) - this.setState({pickedSrc, shouldAutoDownload, url}) - if (shouldAutoDownload) this.load(false) + this.setState( + {pickedSrc, shouldAutoDownload, url}, + shouldAutoDownload ? () => this.load(false) : undefined, + ) } onLeave = () => { @@ -332,20 +337,41 @@ export default class IdealImage extends Component { } render() { + const {children, observer} = this.props const icon = this.props.getIcon(this.state) const message = this.props.getMessage(icon, this.state) - return ( - - this.setState({dimensions})} - message={message} - /> - + const observerMethod = observer || children + const media = ( + + this.setState( + {dimensions}, + observerMethod ? undefined : this.onEnter, + ) + } + message={message} + /> ) + + if (observer || typeof children === 'function') { + return ( + + {media} + + ) + } else if (children) { + return cloneElement( + children, + {onEnter: this.onEnter, onLeave: this.onLeave}, + media, + ) + } else { + return media + } } }