Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-photo-gallery

Package Overview
Dependencies
Maintainers
1
Versions
97
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-photo-gallery - npm Package Compare versions

Comparing version 6.0.29 to 6.1.0

coverage/.coveralls.yml

8

__test__/Gallery.test.js

@@ -24,2 +24,10 @@ import React from 'react';

it('renders correctly with direction set to column', () => {
const component = mount(
<Gallery photos={photos} onClick={handleClick} direction={'column'}/>
);
component.setState({containerWidth: '1139'})
expect(component).toMatchSnapshot();
});
it('unmounts', () => {

@@ -26,0 +34,0 @@ const wrapper = mount(<Gallery photos={photos} />);

4

docs/examples/local-app.md

@@ -6,4 +6,4 @@ There is an example app that comes with the project. To build the examples locally [clone the repo](https://github.com/neptunian/react-photo-gallery), cd into the project directory and run:

```
npm install
npm start
yarn install
yarn start
```

@@ -10,0 +10,0 @@

@@ -16,2 +16,3 @@ ---

* Uses actual image elements, optionally pass in srcSet and sizes attributes
* Supports row or column direction layout
* Supports passing in a custom image component for implementation of things like image selection, favorites, captions, or whatever your little heart desires!

@@ -37,3 +38,4 @@ * SSR app compatible

* [Basic](https://codesandbox.io/s/9yx911wl9y)
* [Basic Row Layout](https://codesandbox.io/s/9yx911wl9y)
* [Basic Column Layout](https://codesandbox.io/s/r09k1xj614)
* [With Lightbox](https://codesandbox.io/s/5vn3lvz2n4)

@@ -90,2 +92,3 @@ * [Dynamic Columns](https://codesandbox.io/s/ll7ym48027)

margin | number | 2 | optional; number of margin pixels around each entire image
direction | string | 'row' | optional; column or row based layout
ImageComponent | function | default component | optional; use a different image component than the default provided to display your photo

@@ -112,5 +115,8 @@

:-----------------------|:--------------|:--------------
margin | string | margin prop optionally passed into Gallery by user
index | number | the index of the photo within the Gallery
photo | object | the individual object passed into Gallery's `photos` array prop, with all the same props except recalculated height and width
onClick | function | the onClick function optionally passsed into Gallery by user
margin | string | optional; margin prop optionally passed into Gallery by user
index | number | required; the index of the photo within the Gallery
photo | object | required; the individual object passed into Gallery's `photos` array prop, with all the same props except recalculated height and width
direction | string | optional; direction passed into Gallery
top | number | required if direction is 'column'; top position of this image, only passed if direction prop was 'column'
left | number | required if direction is 'column'; left position of this image, only passed if direction prop was 'column'
onClick | function | optional; the onClick function optionally passsed into Gallery by user

@@ -5,3 +5,4 @@ # Summary

* Examples
* [Basic](examples/basic.md)
* [Basic (Rows)](examples/basic-rows.md)
* [Basic (Columns)](examples/basic-columns.md)
* [srcSet and sizes](examples/srcset-and-sizes.md)

@@ -13,2 +14,2 @@ * [Dynamic Columns](examples/dynamic-columns.md)

* [Local app](examples/local-app.md)
* [srcSet and sizes](api/srcset-and-sizes.md)
* [srcSet and sizes](srcset-and-sizes.md)

@@ -82,5 +82,6 @@ import React from 'react';

return <div ref={measureRef} className="App">
<ExampleBasic columns={columns} photos={this.state.photos.slice(0,6)} />
<ExampleWithLightbox columns={columns} photos={this.state.photos.slice(6,12)} />
<ExampleCustomComponentSelection columns={columns} photos={this.state.photos.slice(12,18)} />
<ExampleBasic title={'Basic Row Layout'} columns={columns} photos={this.state.photos.slice(0,6)} />
<ExampleBasic title={'Basic Column Layout'} direction="column" columns={columns} photos={this.state.photos.slice(6, 12)} />
<ExampleWithLightbox columns={columns} photos={this.state.photos.slice(12, 18)} />
<ExampleCustomComponentSelection columns={columns} photos={this.state.photos.slice(18, 26)} />
<ExampleDynamicLoading columns={columns} photos={this.state.photos} />

@@ -87,0 +88,0 @@ </div>

import React from 'react';
import Gallery from 'react-photo-gallery';
const ExampleBasic = ({photos, columns}) => {
const ExampleBasic = ({photos, columns, title, direction}) => {
return (
<div>
<h2>Basic</h2>
<Gallery photos={photos} columns={columns} />
<h2>{title}</h2>
<Gallery photos={photos} columns={columns} direction={direction}/>
</div>

@@ -10,0 +10,0 @@ );

@@ -53,4 +53,4 @@ import React from 'react';

<div>
<h2>Loading Photos Dynamically</h2>
<Gallery photos={this.state.photos} columns={this.props.columns} />
<h2>Loading Photos Dynamically in Column Layout</h2>
<Gallery photos={this.state.photos} columns={this.props.columns} direction={'column'} />
{!this.state.loadedAll && <div className="loading-msg" id="msg-loading-more">Loading</div>}

@@ -57,0 +57,0 @@ </div>

@@ -18,3 +18,3 @@ import React from 'react';

const SelectedImage = ({ index, onClick, photo, margin}) => {
const SelectedImage = ({ index, onClick, photo, margin, direction, top, left}) => {
//calculate x,y scale

@@ -25,4 +25,9 @@ const sx = (100 - ((30 / photo.width) * 100)) / 100;

if (direction === 'column'){
cont.position = 'absolute';
cont.left = left;
cont.top = top;
}
return (
<div style={{margin, width:photo.width, ...cont}} className={(!photo.selected ? 'not-selected' : '')}>
<div style={{margin, height: photo.height, width:photo.width, ...cont}} className={(!photo.selected ? 'not-selected' : '')}>
<Checkmark selected={photo.selected ? true : false}/>

@@ -29,0 +34,0 @@ <img style={photo.selected ? {...imgStyle, ...selectedImgStyle} : {...imgStyle}} {...photo} onClick={(e) => onClick(e, {index, photo})} />

@@ -29,2 +29,4 @@ 'use strict';

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -91,10 +93,22 @@

var width = this.state.containerWidth - 1;
var _props = this.props,
photos = _props.photos,
columns = _props.columns,
margin = _props.margin,
onClick = _props.onClick;
onClick = _props.onClick,
direction = _props.direction;
var thumbs = (0, _utils.computeSizes)({ width: width, columns: columns, margin: margin, photos: photos });
var photos = this.props.photos;
var width = this.state.containerWidth - 1;
var galleryStyle = void 0,
thumbs = void 0;
if (direction === 'row') {
galleryStyle = { display: 'flex', flexWrap: 'wrap', flexDirection: 'row' };
thumbs = (0, _utils.computeSizes)({ width: width, columns: columns, margin: margin, photos: photos });
}
if (direction === 'column') {
galleryStyle = { position: 'relative' };
thumbs = (0, _utils.computeSizesColumns)({ width: width, columns: columns, margin: margin, photos: photos });
galleryStyle.height = thumbs[thumbs.length - 1].containerHeight;
}
return _react2.default.createElement(

@@ -107,4 +121,9 @@ 'div',

return _this3._gallery = c;
}, style: { display: 'flex', flexWrap: 'wrap' } },
}, style: galleryStyle },
thumbs.map(function (photo, index) {
var left = photo.left,
top = photo.top,
containerHeight = photo.containerHeight,
rest = _objectWithoutProperties(photo, ['left', 'top', 'containerHeight']);
return _react2.default.createElement(ImageComponent, {

@@ -114,3 +133,6 @@ key: photo.key || photo.src,

index: index,
photo: photo,
photo: rest,
direction: direction,
left: left,
top: top,
onClick: onClick ? _this3.handleClick : null

@@ -129,2 +151,3 @@ });

photos: _propTypes2.default.arrayOf(_Photo.photoPropType).isRequired,
direction: _propTypes2.default.string,
onClick: _propTypes2.default.func,

@@ -138,5 +161,6 @@ columns: _propTypes2.default.number,

columns: 3,
margin: 2
margin: 2,
direction: 'row'
};
exports.default = Gallery;

@@ -26,5 +26,13 @@ 'use strict';

photo = _ref.photo,
margin = _ref.margin;
margin = _ref.margin,
direction = _ref.direction,
top = _ref.top,
left = _ref.left;
var imgStyle = { margin: margin };
if (direction === 'column') {
imgStyle.position = 'absolute';
imgStyle.left = left;
imgStyle.top = top;
}

@@ -53,7 +61,19 @@ var handleClick = function handleClick(event) {

Photo.propTypes = {
index: _propTypes2.default.number,
index: _propTypes2.default.number.isRequired,
onClick: _propTypes2.default.func,
photo: photoPropType
photo: photoPropType.isRequired,
margin: _propTypes2.default.number,
top: function top(props) {
if (props.direction === 'column' && typeof props.top !== 'number') {
return new Error('top is a required number when direction is set to `column`');
}
},
left: function left(props) {
if (props.direction === 'column' && typeof props.left !== 'number') {
return new Error('left is a required number when direction is set to `column`');
}
},
direction: _propTypes2.default.string
};
exports.default = Photo;

@@ -12,2 +12,3 @@ 'use strict';

exports.computeSizes = computeSizes;
exports.computeSizesColumns = computeSizesColumns;

@@ -49,3 +50,2 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

}, []);
// calculate total ratio of each row, and adjust each cell height and width

@@ -75,2 +75,52 @@ // accordingly.

}, []);
}
function computeSizesColumns(_ref3) {
var photos = _ref3.photos,
columns = _ref3.columns,
width = _ref3.width,
margin = _ref3.margin;
// calculate each colWidth based on total width and column amount
var colWidth = (width - margin * 2 * columns) / columns;
// loop through each photo to assign adjusted height and width based on colWidth
var photosWithSizes = photos.map(function (photo) {
var newHeight = photo.height / photo.width * colWidth;
return _extends({}, photo, {
width: round(colWidth, 1),
height: round(newHeight, 1)
});
});
// store all possible left positions
// and current top positions for each column
var colLeftPositions = [];
var colCurrTopPositions = [];
for (var i = 0; i < columns; i++) {
colLeftPositions[i] = round(i * (colWidth + margin * 2), 1);
colCurrTopPositions[i] = 0;
}
// loop through each photo, then loop thru each "column"
// find column with the smallest height and assign to photo's 'top'
// update that column's height with this photo's height
var photosPositioned = photosWithSizes.map(function (photo) {
var smallestCol = colCurrTopPositions.reduce(function (acc, item, i) {
acc = item < colCurrTopPositions[acc] ? i : acc;
return acc;
}, 0);
photo.top = colCurrTopPositions[smallestCol];
photo.left = colLeftPositions[smallestCol];
colCurrTopPositions[smallestCol] = colCurrTopPositions[smallestCol] + photo.height + margin * 2;
// store the tallest col to use for gallery height because of abs positioned elements
var tallestCol = colCurrTopPositions.reduce(function (acc, item, i) {
acc = item > colCurrTopPositions[acc] ? i : acc;
return acc;
}, 0);
photo.containerHeight = colCurrTopPositions[tallestCol];
return photo;
});
return photosPositioned;
}
{
"name": "react-photo-gallery",
"version": "6.0.29",
"version": "6.1.0",
"description": "Responsive React Photo Gallery Component",

@@ -5,0 +5,0 @@ "main": "lib/Gallery.js",

@@ -12,2 +12,3 @@ # React Photo Gallery

* Uses actual image elements, optionally pass in srcSet and sizes attributes
* Supports row or column direction layout
* Supports passing in a custom image component for implementation of things like image selection, favorites, captions, or whatever your little heart desires!

@@ -33,3 +34,4 @@ * SSR app compatible

* [Basic](https://codesandbox.io/s/9yx911wl9y)
* [Basic Row Layout](https://codesandbox.io/s/9yx911wl9y)
* [Basic Column Layout](https://codesandbox.io/s/r09k1xj614)
* [With Lightbox](https://codesandbox.io/s/5vn3lvz2n4)

@@ -86,2 +88,3 @@ * [Dynamic Columns](https://codesandbox.io/s/ll7ym48027)

margin | number | 2 | optional; number of margin pixels around each entire image
direction | string | 'row' | optional; column or row based layout
ImageComponent | function | default component | optional; use a different image component than the default provided to display your photo

@@ -108,5 +111,8 @@

:-----------------------|:--------------|:--------------
margin | string | margin prop optionally passed into Gallery by user
index | number | the index of the photo within the Gallery
photo | object | the individual object passed into Gallery's `photos` array prop, with all the same props except recalculated height and width
onClick | function | the onClick function optionally passsed into Gallery by user
margin | string | optional; margin prop optionally passed into Gallery by user
index | number | required; the index of the photo within the Gallery
photo | object | required; the individual object passed into Gallery's `photos` array prop, with all the same props except recalculated height and width
direction | string | optional; direction passed into Gallery
top | number | required if direction is 'column'; top position of this image, only passed if direction prop was 'column'
left | number | required if direction is 'column'; left position of this image, only passed if direction prop was 'column'
onClick | function | optional; the onClick function optionally passsed into Gallery by user

@@ -5,3 +5,3 @@ import React from 'react';

import Photo, { photoPropType } from './Photo';
import { computeSizes } from './utils';
import { computeSizes, computeSizesColumns } from './utils';

@@ -34,9 +34,21 @@ class Gallery extends React.Component {

// 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;
const { photos, columns, margin, onClick } = this.props;
const thumbs = computeSizes({ width, columns, margin, photos });
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={{ display: 'flex', flexWrap: 'wrap' }}>
<div ref={c => (this._gallery = c)} style={galleryStyle}>
{thumbs.map((photo, index) => {
const { left, top, containerHeight, ...rest } = photo;
return (

@@ -47,3 +59,6 @@ <ImageComponent

index={index}
photo={photo}
photo={rest}
direction={direction}
left={left}
top={top}
onClick={onClick ? this.handleClick : null}

@@ -61,2 +76,3 @@ />

photos: PropTypes.arrayOf(photoPropType).isRequired,
direction: PropTypes.string,
onClick: PropTypes.func,

@@ -71,4 +87,5 @@ columns: PropTypes.number,

margin: 2,
direction: 'row',
};
export default Gallery;

@@ -6,4 +6,9 @@ import React from 'react';

const Photo = ({ index, onClick, photo, margin }) => {
const Photo = ({ index, onClick, photo, margin, direction, top, left }) => {
const imgStyle = { margin: margin };
if (direction === 'column') {
imgStyle.position = 'absolute';
imgStyle.left = left;
imgStyle.top = top;
}

@@ -34,7 +39,19 @@ const handleClick = event => {

Photo.propTypes = {
index: PropTypes.number,
index: PropTypes.number.isRequired,
onClick: PropTypes.func,
photo: photoPropType,
photo: photoPropType.isRequired,
margin: PropTypes.number,
top: props => {
if (props.direction === 'column' && typeof props.top !== 'number') {
return new Error('top is a required number when direction is set to `column`');
}
},
left: props => {
if (props.direction === 'column' && typeof props.left !== 'number') {
return new Error('left is a required number when direction is set to `column`');
}
},
direction: PropTypes.string,
};
export default Photo;

@@ -26,3 +26,2 @@ export function round(value, decimals) {

}, []);
// calculate total ratio of each row, and adjust each cell height and width

@@ -49,1 +48,47 @@ // accordingly.

}
export function computeSizesColumns({ photos, columns, width, margin }) {
// calculate each colWidth based on total width and column amount
let colWidth = (width - margin * 2 * columns) / columns;
// loop through each photo to assign adjusted height and width based on colWidth
const photosWithSizes = photos.map(photo => {
const newHeight = photo.height / photo.width * colWidth;
return {
...photo,
width: round(colWidth, 1),
height: round(newHeight, 1),
};
});
// store all possible left positions
// and current top positions for each column
const colLeftPositions = [];
const colCurrTopPositions = [];
for (var i = 0; i < columns; i++) {
colLeftPositions[i] = round(i * (colWidth + margin * 2), 1);
colCurrTopPositions[i] = 0;
}
// loop through each photo, then loop thru each "column"
// find column with the smallest height and assign to photo's 'top'
// update that column's height with this photo's height
const photosPositioned = photosWithSizes.map(photo => {
const smallestCol = colCurrTopPositions.reduce((acc, item, i) => {
acc = item < colCurrTopPositions[acc] ? i : acc;
return acc;
}, 0);
photo.top = colCurrTopPositions[smallestCol];
photo.left = colLeftPositions[smallestCol];
colCurrTopPositions[smallestCol] = colCurrTopPositions[smallestCol] + photo.height + margin * 2;
// store the tallest col to use for gallery height because of abs positioned elements
const tallestCol = colCurrTopPositions.reduce((acc, item, i) => {
acc = item > colCurrTopPositions[acc] ? i : acc;
return acc;
}, 0);
photo.containerHeight = colCurrTopPositions[tallestCol];
return photo;
});
return photosPositioned;
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc