All files Gallery.js

92% Statements 23/25
82.35% Branches 14/17
87.5% Functions 7/8
92% Lines 23/25
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91                      4x     4x     1x     1x 1x                 7x   7x 7x 7x     7x 5x 5x   7x 2x 2x 2x   7x   11x   49x 49x                                     1x         8x               1x              
import React from 'react';
import PropTypes from 'prop-types';
import ResizeObserver from 'resize-observer-polyfill';
import Photo, { photoPropType } from './Photo';
import { computeSizes, computeSizesColumns } from './utils';
 
class Gallery extends React.Component {
  state = {
    containerWidth: 0,
  };
  componentDidMount() {
    this.observer = new ResizeObserver(() => {
      this.setState({ containerWidth: Math.floor(this._gallery.clientWidth) });
    });
    this.observer.observe(this._gallery);
  }
  componentWillUnmount() {
    this.observer.disconnect();
  }
  handleClick = (event, { index }) => {
    const { photos, onClick } = this.props;
    onClick(event, {
      index,
      photo: photos[index],
      previous: photos[index - 1] || null,
      next: photos[index + 1] || null,
    });
  };
 
  render() {
    const { ImageComponent = Photo } = this.props;
    // subtract 1 pixel because the browser may round up a pixel
    const { columns, margin, onClick, direction } = this.props;
    const photos = this.props.photos;
    const width = this.state.containerWidth - 1;
    let galleryStyle, thumbs;
 
    if (direction === 'row') {
      galleryStyle = { display: 'flex', flexWrap: 'wrap', flexDirection: 'row' };
      thumbs = computeSizes({ width, columns, margin, photos });
    }
    if (direction === 'column') {
      galleryStyle = { position: 'relative' };
      thumbs = computeSizesColumns({ width, columns, margin, photos });
      galleryStyle.height = thumbs[thumbs.length - 1].containerHeight;
    }
    return (
      <div className="react-photo-gallery--gallery">
        <div ref={c => (this._gallery = c)} style={galleryStyle}>
          {thumbs.map((photo, index) => {
            const { left, top, containerHeight, ...rest } = photo;
            return (
              <ImageComponent
                key={photo.key || photo.src}
                margin={margin}
                index={index}
                photo={rest}
                direction={direction}
                left={left}
                top={top}
                onClick={onClick ? this.handleClick : null}
              />
            );
          })}
        </div>
      </div>
    );
  }
}
 
Gallery.propTypes = {
  photos: PropTypes.arrayOf(photoPropType).isRequired,
  direction: PropTypes.string,
  onClick: PropTypes.func,
  columns: props => {
    Iif (props.photos.length < props.columns && typeof props.column !== 'number') {
      return new Error(`columns must be of type 'number' and must be less than photos.length`);
    }
  },
  margin: PropTypes.number,
  ImageComponent: PropTypes.func,
};
 
Gallery.defaultProps = {
  columns: 3,
  margin: 2,
  direction: 'row',
};
 
export default Gallery;