react-images-texts-videos
Version:
A simple, responsive lightbox component for displaying an array of images, texts and videos with React.js
272 lines (240 loc) • 5.83 kB
JavaScript
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { css, StyleSheet } from 'aphrodite/no-important';
import Lightbox from 'react-images-texts-videos';
class Gallery extends Component {
constructor (props) {
super(props);
let itemType;
if (this.props.images) {
itemType = 'images'
} else if (this.props.texts) {
itemType = 'texts'
} else {
itemType = 'videos'
}
this.state = {
lightboxIsOpen: false,
currentItem: 0,
itemType: itemType,
};
this.closeLightbox = this.closeLightbox.bind(this);
this.gotoNext = this.gotoNext.bind(this);
this.gotoPrevious = this.gotoPrevious.bind(this);
this.gotoItem = this.gotoItem.bind(this);
this.handleClickItem = this.handleClickItem.bind(this);
this.openLightbox = this.openLightbox.bind(this);
}
openLightbox (index, event) {
event.preventDefault();
this.setState({
currentItem: index,
lightboxIsOpen: true,
});
}
closeLightbox () {
this.setState({
currentItem: 0,
lightboxIsOpen: false,
});
}
gotoPrevious () {
this.setState({
currentItem: this.state.currentItem - 1,
});
}
gotoNext () {
this.setState({
currentItem: this.state.currentItem + 1,
});
}
gotoItem (index) {
this.setState({
currentItem: index,
});
}
handleClickItem () {
if (this.state.currentItem === this.props[this.state.itemType].length - 1) return;
this.gotoNext();
}
renderGallery () {
if (this.state.itemType == 'images') {
const { images } = this.props;
if (!images) return;
const gallery = images.filter(i => i.useForDemo).map((obj, i) => {
return (
<a
href={obj.src}
className={css(classes.thumbnail, classes[obj.orientation])}
key={i}
onClick={(e) => this.openLightbox(i, e)}
>
<img src={obj.thumbnail} className={css(classes.source)} />
</a>
);
});
return (
<div className={css(classes.gallery)}>
{gallery}
</div>
);
} else if (this.state.itemType == 'texts') {
const { texts } = this.props;
if (!texts) return;
const gallery = texts.map((text, i) => {
return (
<p
className={css(classes.text_thumbail)}
key={i}
onClick={(e) => this.openLightbox(i, e)}
>
{text}
</p>
);
});
return (
<div className={css(classes.gallery)}>
{gallery}
</div>
);
} else {
const { videos } = this.props;
if (!videos) return;
const gallery = videos.map((videoId, i) => {
const videoThumbnail = `https://img.youtube.com/vi/${videoId}/0.jpg`;
return (
<a
className={css(classes.video_thumbnail)}
key={i}
onClick={(e) => this.openLightbox(i, e)}
>
<img src={videoThumbnail} className={css(classes.source_video)} />
<i className="material-icons">play_circle_outline</i>
</a>
);
});
return (
<div className={css(classes.gallery)}>
{gallery}
</div>
);
}
}
render () {
return (
<div className="section">
{this.props.heading && <h2>{this.props.heading}</h2>}
{this.props.subheading && <p>{this.props.subheading}</p>}
{this.renderGallery()}
<Lightbox
currentItem={this.state.currentItem}
items={{type:this.state.itemType,items:this.props[this.state.itemType]}}
isOpen={this.state.lightboxIsOpen}
onClickImage={this.handleClickItem}
onClickNext={this.gotoNext}
onClickPrev={this.gotoPrevious}
onClickThumbnail={this.gotoItem}
onClose={this.closeLightbox}
showThumbnails={this.props.showThumbnails}
theme={this.props.theme}
/>
</div>
);
}
}
Gallery.displayName = 'Gallery';
Gallery.propTypes = {
heading: PropTypes.string,
images: PropTypes.array,
texts: PropTypes.array,
showThumbnails: PropTypes.bool,
subheading: PropTypes.string,
};
const gutter = {
small: 2,
large: 4,
};
const classes = StyleSheet.create({
gallery: {
marginRight: -gutter.small,
overflow: 'hidden',
'@media (min-width: 500px)': {
marginRight: -gutter.large,
},
},
// anchor
thumbnail: {
boxSizing: 'border-box',
display: 'block',
float: 'left',
lineHeight: 0,
paddingRight: gutter.small,
paddingBottom: gutter.small,
overflow: 'hidden',
'@media (min-width: 500px)': {
paddingRight: gutter.large,
paddingBottom: gutter.large,
},
},
// anchor
video_thumbnail: {
width:'50%',
height: '258px',
boxSizing: 'border-box',
display: 'block',
float: 'left',
lineHeight: 0,
paddingRight: gutter.small,
paddingBottom: gutter.small,
overflow: 'hidden',
'@media (min-width: 500px)': {
paddingRight: gutter.large,
paddingBottom: gutter.large,
},
},
// anchor
text_thumbail: {
cursor: 'pointer',
height: '200px',
'text-align': 'justify',
'font-size': '16px',
width: '46%',
padding: '10px',
margin: '10px',
boxSizing: 'border-box',
display: 'block',
float: 'left',
overflow: 'scroll',
border: 'solid 1px #E6E6E8',
'border-radius': '4px',
color: 'darkgray',
'@media (min-width: 500px)': {
},
},
// orientation
landscape: {
width: '30%',
},
square: {
paddingBottom: 0,
width: '40%',
'@media (min-width: 500px)': {
paddingBottom: 0,
},
},
// actual <img />
source: {
border: 0,
display: 'block',
height: 'auto',
maxWidth: '100%',
width: 'auto',
},
source_video: {
border: 0,
height: 'auto',
maxWidth: '90%',
width: 'auto',
},
});
export default Gallery;