diff --git a/README.md b/README.md index 46f31088..8465b40e 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,7 @@ images | array | undefined | Required. Array of image objects See image options imageCountSeparator | String | ' of ' | Customize separator in the image count isOpen | bool | false | Whether or not the lightbox is displayed leftArrowTitle | string | ' Previous (Left arrow key) ' | Customize of left arrow title +loop | bool | false | Allows looping the gallery onClickPrev | func | undefined | Fired on request of the previous image onClickNext | func | undefined | Fired on request of the next image onClose | func | undefined | Required. Handle closing of the lightbox diff --git a/dist/react-images.es.js b/dist/react-images.es.js index ee38960a..c7d5e132 100644 --- a/dist/react-images.es.js +++ b/dist/react-images.es.js @@ -1124,11 +1124,12 @@ var Lightbox = function (_Component) { value: function gotoNext(event) { var _props = this.props, currentImage = _props.currentImage, - images = _props.images; + images = _props.images, + loop = _props.loop; var imageLoaded = this.state.imageLoaded; - if (!imageLoaded || currentImage === images.length - 1) return; + if (!imageLoaded || !loop && currentImage === images.length - 1) return; if (event) { event.preventDefault(); @@ -1140,11 +1141,13 @@ var Lightbox = function (_Component) { }, { key: 'gotoPrev', value: function gotoPrev(event) { - var currentImage = this.props.currentImage; + var _props2 = this.props, + currentImage = _props2.currentImage, + loop = _props2.loop; var imageLoaded = this.state.imageLoaded; - if (!imageLoaded || currentImage === 0) return; + if (!imageLoaded || !loop && currentImage === 0) return; if (event) { event.preventDefault(); @@ -1193,7 +1196,7 @@ var Lightbox = function (_Component) { }, { key: 'renderArrowPrev', value: function renderArrowPrev() { - if (this.props.currentImage === 0) return null; + if (!this.props.loop && this.props.currentImage === 0) return null; return React.createElement(Arrow, { direction: 'left', @@ -1206,7 +1209,7 @@ var Lightbox = function (_Component) { }, { key: 'renderArrowNext', value: function renderArrowNext() { - if (this.props.currentImage === this.props.images.length - 1) return null; + if (!this.props.loop && this.props.currentImage === this.props.images.length - 1) return null; return React.createElement(Arrow, { direction: 'right', @@ -1219,11 +1222,11 @@ var Lightbox = function (_Component) { }, { key: 'renderDialog', value: function renderDialog() { - var _props2 = this.props, - backdropClosesModal = _props2.backdropClosesModal, - isOpen = _props2.isOpen, - showThumbnails = _props2.showThumbnails, - width = _props2.width; + var _props3 = this.props, + backdropClosesModal = _props3.backdropClosesModal, + isOpen = _props3.isOpen, + showThumbnails = _props3.showThumbnails, + width = _props3.width; var imageLoaded = this.state.imageLoaded; @@ -1262,11 +1265,11 @@ var Lightbox = function (_Component) { }, { key: 'renderImages', value: function renderImages() { - var _props3 = this.props, - currentImage = _props3.currentImage, - images = _props3.images, - onClickImage = _props3.onClickImage, - showThumbnails = _props3.showThumbnails; + var _props4 = this.props, + currentImage = _props4.currentImage, + images = _props4.images, + onClickImage = _props4.onClickImage, + showThumbnails = _props4.showThumbnails; var imageLoaded = this.state.imageLoaded; @@ -1299,12 +1302,12 @@ var Lightbox = function (_Component) { }, { key: 'renderThumbnails', value: function renderThumbnails() { - var _props4 = this.props, - images = _props4.images, - currentImage = _props4.currentImage, - onClickThumbnail = _props4.onClickThumbnail, - showThumbnails = _props4.showThumbnails, - thumbnailOffset = _props4.thumbnailOffset; + var _props5 = this.props, + images = _props5.images, + currentImage = _props5.currentImage, + onClickThumbnail = _props5.onClickThumbnail, + showThumbnails = _props5.showThumbnails, + thumbnailOffset = _props5.thumbnailOffset; if (!showThumbnails) return; @@ -1319,11 +1322,11 @@ var Lightbox = function (_Component) { }, { key: 'renderHeader', value: function renderHeader() { - var _props5 = this.props, - closeButtonTitle = _props5.closeButtonTitle, - customControls = _props5.customControls, - onClose = _props5.onClose, - showCloseButton = _props5.showCloseButton; + var _props6 = this.props, + closeButtonTitle = _props6.closeButtonTitle, + customControls = _props6.customControls, + onClose = _props6.onClose, + showCloseButton = _props6.showCloseButton; return React.createElement(Header, { @@ -1336,11 +1339,11 @@ var Lightbox = function (_Component) { }, { key: 'renderFooter', value: function renderFooter() { - var _props6 = this.props, - currentImage = _props6.currentImage, - images = _props6.images, - imageCountSeparator = _props6.imageCountSeparator, - showImageCount = _props6.showImageCount; + var _props7 = this.props, + currentImage = _props7.currentImage, + images = _props7.images, + imageCountSeparator = _props7.imageCountSeparator, + showImageCount = _props7.showImageCount; if (!images || !images.length) return null; @@ -1356,10 +1359,10 @@ var Lightbox = function (_Component) { }, { key: 'renderSpinner', value: function renderSpinner() { - var _props7 = this.props, - spinner = _props7.spinner, - spinnerColor = _props7.spinnerColor, - spinnerSize = _props7.spinnerSize; + var _props8 = this.props, + spinner = _props8.spinner, + spinnerColor = _props8.spinnerColor, + spinnerSize = _props8.spinnerSize; var imageLoaded = this.state.imageLoaded; var Spinner$$1 = spinner; @@ -1424,6 +1427,7 @@ Lightbox.defaultProps = { enableKeyboardInput: true, imageCountSeparator: ' of ', leftArrowTitle: 'Previous (Left arrow key)', + loop: false, onClickShowNextImage: true, preloadNextImage: true, preventScroll: true, diff --git a/dist/react-images.js b/dist/react-images.js index 6c169f74..c4de9169 100644 --- a/dist/react-images.js +++ b/dist/react-images.js @@ -1126,11 +1126,12 @@ var Lightbox = function (_Component) { value: function gotoNext(event) { var _props = this.props, currentImage = _props.currentImage, - images = _props.images; + images = _props.images, + loop = _props.loop; var imageLoaded = this.state.imageLoaded; - if (!imageLoaded || currentImage === images.length - 1) return; + if (!imageLoaded || !loop && currentImage === images.length - 1) return; if (event) { event.preventDefault(); @@ -1142,11 +1143,13 @@ var Lightbox = function (_Component) { }, { key: 'gotoPrev', value: function gotoPrev(event) { - var currentImage = this.props.currentImage; + var _props2 = this.props, + currentImage = _props2.currentImage, + loop = _props2.loop; var imageLoaded = this.state.imageLoaded; - if (!imageLoaded || currentImage === 0) return; + if (!imageLoaded || !loop && currentImage === 0) return; if (event) { event.preventDefault(); @@ -1195,7 +1198,7 @@ var Lightbox = function (_Component) { }, { key: 'renderArrowPrev', value: function renderArrowPrev() { - if (this.props.currentImage === 0) return null; + if (!this.props.loop && this.props.currentImage === 0) return null; return React__default.createElement(Arrow, { direction: 'left', @@ -1208,7 +1211,7 @@ var Lightbox = function (_Component) { }, { key: 'renderArrowNext', value: function renderArrowNext() { - if (this.props.currentImage === this.props.images.length - 1) return null; + if (!this.props.loop && this.props.currentImage === this.props.images.length - 1) return null; return React__default.createElement(Arrow, { direction: 'right', @@ -1221,11 +1224,11 @@ var Lightbox = function (_Component) { }, { key: 'renderDialog', value: function renderDialog() { - var _props2 = this.props, - backdropClosesModal = _props2.backdropClosesModal, - isOpen = _props2.isOpen, - showThumbnails = _props2.showThumbnails, - width = _props2.width; + var _props3 = this.props, + backdropClosesModal = _props3.backdropClosesModal, + isOpen = _props3.isOpen, + showThumbnails = _props3.showThumbnails, + width = _props3.width; var imageLoaded = this.state.imageLoaded; @@ -1264,11 +1267,11 @@ var Lightbox = function (_Component) { }, { key: 'renderImages', value: function renderImages() { - var _props3 = this.props, - currentImage = _props3.currentImage, - images = _props3.images, - onClickImage = _props3.onClickImage, - showThumbnails = _props3.showThumbnails; + var _props4 = this.props, + currentImage = _props4.currentImage, + images = _props4.images, + onClickImage = _props4.onClickImage, + showThumbnails = _props4.showThumbnails; var imageLoaded = this.state.imageLoaded; @@ -1301,12 +1304,12 @@ var Lightbox = function (_Component) { }, { key: 'renderThumbnails', value: function renderThumbnails() { - var _props4 = this.props, - images = _props4.images, - currentImage = _props4.currentImage, - onClickThumbnail = _props4.onClickThumbnail, - showThumbnails = _props4.showThumbnails, - thumbnailOffset = _props4.thumbnailOffset; + var _props5 = this.props, + images = _props5.images, + currentImage = _props5.currentImage, + onClickThumbnail = _props5.onClickThumbnail, + showThumbnails = _props5.showThumbnails, + thumbnailOffset = _props5.thumbnailOffset; if (!showThumbnails) return; @@ -1321,11 +1324,11 @@ var Lightbox = function (_Component) { }, { key: 'renderHeader', value: function renderHeader() { - var _props5 = this.props, - closeButtonTitle = _props5.closeButtonTitle, - customControls = _props5.customControls, - onClose = _props5.onClose, - showCloseButton = _props5.showCloseButton; + var _props6 = this.props, + closeButtonTitle = _props6.closeButtonTitle, + customControls = _props6.customControls, + onClose = _props6.onClose, + showCloseButton = _props6.showCloseButton; return React__default.createElement(Header, { @@ -1338,11 +1341,11 @@ var Lightbox = function (_Component) { }, { key: 'renderFooter', value: function renderFooter() { - var _props6 = this.props, - currentImage = _props6.currentImage, - images = _props6.images, - imageCountSeparator = _props6.imageCountSeparator, - showImageCount = _props6.showImageCount; + var _props7 = this.props, + currentImage = _props7.currentImage, + images = _props7.images, + imageCountSeparator = _props7.imageCountSeparator, + showImageCount = _props7.showImageCount; if (!images || !images.length) return null; @@ -1358,10 +1361,10 @@ var Lightbox = function (_Component) { }, { key: 'renderSpinner', value: function renderSpinner() { - var _props7 = this.props, - spinner = _props7.spinner, - spinnerColor = _props7.spinnerColor, - spinnerSize = _props7.spinnerSize; + var _props8 = this.props, + spinner = _props8.spinner, + spinnerColor = _props8.spinnerColor, + spinnerSize = _props8.spinnerSize; var imageLoaded = this.state.imageLoaded; var Spinner$$1 = spinner; @@ -1426,6 +1429,7 @@ Lightbox.defaultProps = { enableKeyboardInput: true, imageCountSeparator: ' of ', leftArrowTitle: 'Previous (Left arrow key)', + loop: false, onClickShowNextImage: true, preloadNextImage: true, preventScroll: true, diff --git a/dist/react-images.min.js b/dist/react-images.min.js index 8ffe03a8..cad60303 100644 --- a/dist/react-images.min.js +++ b/dist/react-images.min.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("prop-types"),require("react"),require("aphrodite"),require("react-scrolllock"),require("aphrodite/no-important"),require("react-transition-group"),require("react-dom")):"function"==typeof define&&define.amd?define(["prop-types","react","aphrodite","react-scrolllock","aphrodite/no-important","react-transition-group","react-dom"],t):e.Lightbox=t(e.PropTypes,e.React,e.aphrodite,e.ScrollLock,e.aphrodite,e.ReactTransitionGroup,e.ReactDOM)}(this,function(e,t,n,r,o,i,a){"use strict";function s(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=Object.assign({},e);return Object.keys(t).forEach(function(r){"object"===v(t[r])&&t[r]&&e[r]?n[r]=s(e[r],t[r]):n[r]=t[r]}),n}function l(e,t){var n=t.theme,r=e.direction,i=e.icon,a=e.onClick,l=e.size,c=x(e,["direction","icon","onClick","size"]),u=o.StyleSheet.create(s(S,n));return f.createElement("button",w({type:"button",className:o.css(u.arrow,u["arrow__direction__"+r],l&&u["arrow__size__"+l]),onClick:a,onTouchEnd:a},c),f.createElement(E,{fill:!!n.arrow&&n.arrow.fill||g.arrow.fill,type:i}))}function c(e,t){var n=t.theme,r=x(e,[]),i=o.StyleSheet.create(s(_,n));return f.createElement("div",w({id:"lightboxBackdrop",className:o.css(i.container)},r))}function u(e,t){var n=t.theme,r=e.caption,i=e.countCurrent,a=e.countSeparator,l=e.countTotal,c=e.showCount,u=x(e,["caption","countCurrent","countSeparator","countTotal","showCount"]);if(!r&&!c)return null;var h=o.StyleSheet.create(s(L,n)),p=c?f.createElement("div",{className:o.css(h.footerCount)},i,a,l):f.createElement("span",null);return f.createElement("div",w({className:o.css(h.footer)},u),r?f.createElement("figcaption",{className:o.css(h.footerCaption)},r):f.createElement("span",null),p)}function h(e,t){var n=t.theme,r=e.customControls,i=e.onClose,a=e.showCloseButton,l=e.closeButtonTitle,c=x(e,["customControls","onClose","showCloseButton","closeButtonTitle"]),u=o.StyleSheet.create(s(T,n));return f.createElement("div",w({className:o.css(u.header)},c),r||f.createElement("span",null),!!a&&f.createElement("button",{title:l,className:o.css(u.close),onClick:i},f.createElement(E,{fill:!!n.close&&n.close.fill||g.close.fill,type:"close"})))}function p(e,t){var n=e.index,r=e.src,i=e.thumbnail,a=e.active,l=e.onClick,c=t.theme,u=i||r,h=o.StyleSheet.create(s(z,c));return f.createElement("div",{className:o.css(h.thumbnail,a&&h.thumbnail__active),onClick:function(e){e.preventDefault(),e.stopPropagation(),l(n)},style:{backgroundImage:'url("'+u+'")'}})}function d(e){var t=this;e.forEach(function(e){return t[e]=t[e].bind(t)})}function m(e){var t=e.srcSet||e.srcset;return Array.isArray(t)?t.join():t}e=e&&e.hasOwnProperty("default")?e.default:e;var f="default"in t?t.default:t;r=r&&r.hasOwnProperty("default")?r.default:r;var g={};g.container={background:"rgba(0, 0, 0, 0.8)",gutter:{horizontal:10,vertical:10},zIndex:2001},g.header={height:40},g.close={fill:"white"},g.footer={color:"white",count:{color:"rgba(255, 255, 255, 0.75)",fontSize:"0.85em"},height:40,gutter:{horizontal:0,vertical:5}},g.thumbnail={activeBorderColor:"white",size:50,gutter:2},g.arrow={background:"none",fill:"white",height:120};var v="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},y=(function(){function e(e){this.value=e}function t(t){function n(o,i){try{var a=t[o](i),s=a.value;s instanceof e?Promise.resolve(s.value).then(function(e){n("next",e)},function(e){n("throw",e)}):r(a.done?"return":"normal",a.value)}catch(e){r("throw",e)}}function r(e,t){switch(e){case"return":o.resolve({value:t,done:!0});break;case"throw":o.reject(t);break;default:o.resolve({value:t,done:!1})}(o=o.next)?n(o.key,o.arg):i=null}var o,i;this._invoke=function(e,t){return new Promise(function(r,a){var s={key:e,arg:t,resolve:r,reject:a,next:null};i?i=i.next=s:(o=i=s,n(e,t))})},"function"!=typeof t.return&&(this.return=void 0)}"function"==typeof Symbol&&Symbol.asyncIterator&&(t.prototype[Symbol.asyncIterator]=function(){return this}),t.prototype.next=function(e){return this._invoke("next",e)},t.prototype.throw=function(e){return this._invoke("throw",e)},t.prototype.return=function(e){return this._invoke("return",e)}}(),function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}),b=function(){function e(e,t){for(var n=0;n=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n},C=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t},I={arrowLeft:function(e){return'\n\t\t\n\t'},arrowRight:function(e){return'\n\t\t\n\t'},close:function(e){return'\n\t\t\n\t'}},E=function(e){var t=e.fill,n=e.type,r=x(e,["fill","type"]),o=I[n];return f.createElement("span",w({dangerouslySetInnerHTML:{__html:o(t)}},r))};E.defaultProps={fill:"white"},l.defaultProps={size:"medium"},l.contextTypes={theme:e.object.isRequired};var S={arrow:{background:"none",border:"none",borderRadius:4,cursor:"pointer",outline:"none",padding:10,position:"absolute",top:"50%",WebkitTouchCallout:"none",userSelect:"none"},arrow__size__medium:{height:g.arrow.height,marginTop:g.arrow.height/-2,width:40,"@media (min-width: 768px)":{width:70}},arrow__size__small:{height:g.thumbnail.size,marginTop:g.thumbnail.size/-2,width:30,"@media (min-width: 500px)":{width:40}},arrow__direction__right:{right:g.container.gutter.horizontal},arrow__direction__left:{left:g.container.gutter.horizontal}};c.contextTypes={theme:e.object.isRequired};var _={container:{alignItems:"center",backgroundColor:g.container.background,boxSizing:"border-box",display:"flex",height:"100%",justifyContent:"center",left:0,paddingBottom:g.container.gutter.vertical,paddingLeft:g.container.gutter.horizontal,paddingRight:g.container.gutter.horizontal,paddingTop:g.container.gutter.vertical,position:"fixed",top:0,width:"100%",zIndex:g.container.zIndex}};u.contextTypes={theme:e.object.isRequired};var L={footer:{boxSizing:"border-box",color:g.footer.color,cursor:"auto",display:"flex",justifyContent:"space-between",left:0,lineHeight:1.3,paddingBottom:g.footer.gutter.vertical,paddingLeft:g.footer.gutter.horizontal,paddingRight:g.footer.gutter.horizontal,paddingTop:g.footer.gutter.vertical},footerCount:{color:g.footer.count.color,fontSize:g.footer.count.fontSize,paddingLeft:"1em"},footerCaption:{flex:"1 1 0"}};h.contextTypes={theme:e.object.isRequired};var T={header:{display:"flex",justifyContent:"space-between",height:g.header.height},close:{background:"none",border:"none",cursor:"pointer",outline:"none",position:"relative",top:0,verticalAlign:"bottom",zIndex:1,height:40,marginRight:-10,padding:10,width:40}};p.contextTypes={theme:e.object.isRequired};var z={thumbnail:{backgroundPosition:"center",backgroundSize:"cover",borderRadius:2,boxShadow:"inset 0 0 0 1px hsla(0,0%,100%,.2)",cursor:"pointer",display:"inline-block",height:g.thumbnail.size,margin:g.thumbnail.gutter,overflow:"hidden",width:g.thumbnail.size},thumbnail__active:{boxShadow:"inset 0 0 0 2px "+g.thumbnail.activeBorderColor}},P=o.StyleSheet.create({paginatedThumbnails:{bottom:g.container.gutter.vertical,height:g.thumbnail.size,padding:"0 50px",position:"absolute",textAlign:"center",whiteSpace:"nowrap",left:"50%",transform:"translateX(-50%)"}}),N={height:g.thumbnail.size+2*g.thumbnail.gutter,width:40},O=function(e){function t(e){y(this,t);var n=C(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return n.state={hasCustomPage:!1},n.gotoPrev=n.gotoPrev.bind(n),n.gotoNext=n.gotoNext.bind(n),n}return k(t,e),b(t,[{key:"componentWillReceiveProps",value:function(e){e.currentImage!==this.props.currentImage&&this.setState({hasCustomPage:!1})}},{key:"getFirst",value:function(){var e=this.props,t=e.currentImage,n=e.offset;return this.state.hasCustomPage?this.clampFirst(this.state.first):this.clampFirst(t-n)}},{key:"setFirst",value:function(e,t){var n=this.state.first;e&&(e.preventDefault(),e.stopPropagation()),n!==t&&this.setState({hasCustomPage:!0,first:t})}},{key:"gotoPrev",value:function(e){this.setFirst(e,this.getFirst()-this.props.offset)}},{key:"gotoNext",value:function(e){this.setFirst(e,this.getFirst()+this.props.offset)}},{key:"clampFirst",value:function(e){var t=this.props,n=t.images,r=2*t.offset+1;return e<0?0:e+r>n.length?n.length-r:e}},{key:"renderArrowPrev",value:function(){return this.getFirst()<=0?null:f.createElement(l,{direction:"left",size:"small",icon:"arrowLeft",onClick:this.gotoPrev,style:N,title:"Previous (Left arrow key)",type:"button"})}},{key:"renderArrowNext",value:function(){var e=this.props,t=e.offset,n=e.images,r=2*t+1;return this.getFirst()+r>=n.length?null:f.createElement(l,{direction:"right",size:"small",icon:"arrowRight",onClick:this.gotoNext,style:N,title:"Next (Right arrow key)",type:"button"})}},{key:"render",value:function(){var e=this.props,t=e.images,n=e.currentImage,r=e.onClickThumbnail,i=2*e.offset+1,a=[],s=0;return t.length<=i?a=t:(s=this.getFirst(),a=t.slice(s,s+i)),f.createElement("div",{className:o.css(P.paginatedThumbnails)},this.renderArrowPrev(),a.map(function(e,t){return f.createElement(p,w({key:s+t},e,{index:s+t,onClick:r,active:s+t===n}))}),this.renderArrowNext())}}]),t}(t.Component),j=function(e){function n(){return y(this,n),C(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return k(n,e),b(n,[{key:"getChildContext",value:function(){return this.props.context}},{key:"render",value:function(){return t.Children.only(this.props.children)}}]),n}(t.Component);j.childContextTypes={theme:e.object};var R=function(e){function t(){y(this,t);var e=C(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.portalElement=null,e}return k(t,e),b(t,[{key:"componentDidMount",value:function(){var e=document.createElement("div");document.body.appendChild(e),this.portalElement=e,this.componentDidUpdate()}},{key:"componentDidUpdate",value:function(){a.render(f.createElement(j,{context:this.context},f.createElement("div",null,f.createElement("style",null,"\n\t\t\t\t.fade-enter { opacity: 0.01; }\n\t\t\t\t.fade-enter.fade-enter-active { opacity: 1; transition: opacity 200ms; }\n\t\t\t\t.fade-leave { opacity: 1; }\n\t\t\t\t.fade-leave.fade-leave-active { opacity: 0.01; transition: opacity 200ms; }\n\t\t"),f.createElement(i.TransitionGroup,this.props,f.createElement(i.CSSTransition,{timeout:{enter:200,exit:200},classNames:"fade"},this.props.children)))),this.portalElement)}},{key:"componentWillUnmount",value:function(){a.unmountComponentAtNode(this.portalElement),document.body.removeChild(this.portalElement)}},{key:"render",value:function(){return null}}]),t}(t.Component);R.contextTypes={theme:e.object.isRequired};var B={"0%":{top:"50%",left:"50%",width:0,height:0,opacity:1},"100%":{top:0,left:0,width:"100%",height:"100%",opacity:0}},A=function(e){var t=e.color,n=e.size;return{spinner:{display:"inline-block",position:"relative",width:n,height:n},ripple:{position:"absolute",border:"4px solid "+t,opacity:1,borderRadius:"50%",animationName:B,animationDuration:"1s",animationTimingFunction:"cubic-bezier(0, 0.2, 0.8, 1)",animationIterationCount:"infinite"}}},F=!("undefined"==typeof window||!window.document||!window.document.createElement),D=function(e){function t(e){y(this,t);var r=C(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return r.theme=s(g,e.theme),r.classes=n.StyleSheet.create(s(q,r.theme)),r.state={imageLoaded:!1},d.call(r,["gotoNext","gotoPrev","closeBackdrop","handleKeyboardInput","handleImageLoaded"]),r}return k(t,e),b(t,[{key:"getChildContext",value:function(){return{theme:this.theme}}},{key:"componentDidMount",value:function(){this.props.isOpen&&(this.props.enableKeyboardInput&&window.addEventListener("keydown",this.handleKeyboardInput),"number"==typeof this.props.currentImage&&this.preloadImage(this.props.currentImage,this.handleImageLoaded))}},{key:"componentWillReceiveProps",value:function(e){if(F){if(e.preloadNextImage){var t=this.props.currentImage,n=e.currentImage+1,r=e.currentImage-1,o=void 0;t&&e.currentImage>t?o=n:t&&e.currentImage=0||Object.prototype.hasOwnProperty.call(e,o)&&(n[o]=e[o]);return n},f=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t};function g(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=Object.assign({},e);return Object.keys(t).forEach(function(o){"object"===c(t[o])&&t[o]&&e[o]?n[o]=g(e[o],t[o]):n[o]=t[o]}),n}var v={arrowLeft:function(e){return'\n\t\t\n\t'},arrowRight:function(e){return'\n\t\t\n\t'},close:function(e){return'\n\t\t\n\t'}},y=function(e){var t=e.fill,n=e.type,o=m(e,["fill","type"]),r=v[n];return s.createElement("span",p({dangerouslySetInnerHTML:{__html:r(t)}},o))};function b(e,t){var n=t.theme,o=e.direction,i=e.icon,a=e.onClick,c=e.size,u=m(e,["direction","icon","onClick","size"]),h=r.StyleSheet.create(g(w,n));return s.createElement("button",p({type:"button",className:r.css(h.arrow,h["arrow__direction__"+o],c&&h["arrow__size__"+c]),onClick:a,onTouchEnd:a},u),s.createElement(y,{fill:!!n.arrow&&n.arrow.fill||l.arrow.fill,type:i}))}y.defaultProps={fill:"white"},b.defaultProps={size:"medium"},b.contextTypes={theme:e.object.isRequired};var w={arrow:{background:"none",border:"none",borderRadius:4,cursor:"pointer",outline:"none",padding:10,position:"absolute",top:"50%",WebkitTouchCallout:"none",userSelect:"none"},arrow__size__medium:{height:l.arrow.height,marginTop:l.arrow.height/-2,width:40,"@media (min-width: 768px)":{width:70}},arrow__size__small:{height:l.thumbnail.size,marginTop:l.thumbnail.size/-2,width:30,"@media (min-width: 500px)":{width:40}},arrow__direction__right:{right:l.container.gutter.horizontal},arrow__direction__left:{left:l.container.gutter.horizontal}};function k(e,t){var n=t.theme,o=m(e,[]),i=r.StyleSheet.create(g(x,n));return s.createElement("div",p({id:"lightboxBackdrop",className:r.css(i.container)},o))}k.contextTypes={theme:e.object.isRequired};var x={container:{alignItems:"center",backgroundColor:l.container.background,boxSizing:"border-box",display:"flex",height:"100%",justifyContent:"center",left:0,paddingBottom:l.container.gutter.vertical,paddingLeft:l.container.gutter.horizontal,paddingRight:l.container.gutter.horizontal,paddingTop:l.container.gutter.vertical,position:"fixed",top:0,width:"100%",zIndex:l.container.zIndex}};function C(e,t){var n=t.theme,o=e.caption,i=e.countCurrent,a=e.countSeparator,l=e.countTotal,c=e.showCount,u=m(e,["caption","countCurrent","countSeparator","countTotal","showCount"]);if(!o&&!c)return null;var h=r.StyleSheet.create(g(I,n)),d=c?s.createElement("div",{className:r.css(h.footerCount)},i,a,l):s.createElement("span",null);return s.createElement("div",p({className:r.css(h.footer)},u),o?s.createElement("figcaption",{className:r.css(h.footerCaption)},o):s.createElement("span",null),d)}C.contextTypes={theme:e.object.isRequired};var I={footer:{boxSizing:"border-box",color:l.footer.color,cursor:"auto",display:"flex",justifyContent:"space-between",left:0,lineHeight:1.3,paddingBottom:l.footer.gutter.vertical,paddingLeft:l.footer.gutter.horizontal,paddingRight:l.footer.gutter.horizontal,paddingTop:l.footer.gutter.vertical},footerCount:{color:l.footer.count.color,fontSize:l.footer.count.fontSize,paddingLeft:"1em"},footerCaption:{flex:"1 1 0"}};function E(e,t){var n=t.theme,o=e.customControls,i=e.onClose,a=e.showCloseButton,c=e.closeButtonTitle,u=m(e,["customControls","onClose","showCloseButton","closeButtonTitle"]),h=r.StyleSheet.create(g(S,n));return s.createElement("div",p({className:r.css(h.header)},u),o||s.createElement("span",null),!!a&&s.createElement("button",{title:c,className:r.css(h.close),onClick:i},s.createElement(y,{fill:!!n.close&&n.close.fill||l.close.fill,type:"close"})))}E.contextTypes={theme:e.object.isRequired};var S={header:{display:"flex",justifyContent:"space-between",height:l.header.height},close:{background:"none",border:"none",cursor:"pointer",outline:"none",position:"relative",top:0,verticalAlign:"bottom",zIndex:1,height:40,marginRight:-10,padding:10,width:40}};function _(e,t){var n=e.index,o=e.src,i=e.thumbnail,a=e.active,l=e.onClick,c=t.theme,u=i||o,h=r.StyleSheet.create(g(L,c));return s.createElement("div",{className:r.css(h.thumbnail,a&&h.thumbnail__active),onClick:function(e){e.preventDefault(),e.stopPropagation(),l(n)},style:{backgroundImage:'url("'+u+'")'}})}_.contextTypes={theme:e.object.isRequired};var L={thumbnail:{backgroundPosition:"center",backgroundSize:"cover",borderRadius:2,boxShadow:"inset 0 0 0 1px hsla(0,0%,100%,.2)",cursor:"pointer",display:"inline-block",height:l.thumbnail.size,margin:l.thumbnail.gutter,overflow:"hidden",width:l.thumbnail.size},thumbnail__active:{boxShadow:"inset 0 0 0 2px "+l.thumbnail.activeBorderColor}},T=r.StyleSheet.create({paginatedThumbnails:{bottom:l.container.gutter.vertical,height:l.thumbnail.size,padding:"0 50px",position:"absolute",textAlign:"center",whiteSpace:"nowrap",left:"50%",transform:"translateX(-50%)"}}),z={height:l.thumbnail.size+2*l.thumbnail.gutter,width:40},P=function(e){function t(e){u(this,t);var n=f(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return n.state={hasCustomPage:!1},n.gotoPrev=n.gotoPrev.bind(n),n.gotoNext=n.gotoNext.bind(n),n}return d(t,e),h(t,[{key:"componentWillReceiveProps",value:function(e){e.currentImage!==this.props.currentImage&&this.setState({hasCustomPage:!1})}},{key:"getFirst",value:function(){var e=this.props,t=e.currentImage,n=e.offset;return this.state.hasCustomPage?this.clampFirst(this.state.first):this.clampFirst(t-n)}},{key:"setFirst",value:function(e,t){var n=this.state.first;e&&(e.preventDefault(),e.stopPropagation()),n!==t&&this.setState({hasCustomPage:!0,first:t})}},{key:"gotoPrev",value:function(e){this.setFirst(e,this.getFirst()-this.props.offset)}},{key:"gotoNext",value:function(e){this.setFirst(e,this.getFirst()+this.props.offset)}},{key:"clampFirst",value:function(e){var t=this.props,n=t.images,o=2*t.offset+1;return e<0?0:e+o>n.length?n.length-o:e}},{key:"renderArrowPrev",value:function(){return this.getFirst()<=0?null:s.createElement(b,{direction:"left",size:"small",icon:"arrowLeft",onClick:this.gotoPrev,style:z,title:"Previous (Left arrow key)",type:"button"})}},{key:"renderArrowNext",value:function(){var e=this.props,t=e.offset,n=e.images,o=2*t+1;return this.getFirst()+o>=n.length?null:s.createElement(b,{direction:"right",size:"small",icon:"arrowRight",onClick:this.gotoNext,style:z,title:"Next (Right arrow key)",type:"button"})}},{key:"render",value:function(){var e=this.props,t=e.images,n=e.currentImage,o=e.onClickThumbnail,i=2*e.offset+1,a=[],l=0;return t.length<=i?a=t:(l=this.getFirst(),a=t.slice(l,l+i)),s.createElement("div",{className:r.css(T.paginatedThumbnails)},this.renderArrowPrev(),a.map(function(e,t){return s.createElement(_,p({key:l+t},e,{index:l+t,onClick:o,active:l+t===n}))}),this.renderArrowNext())}}]),t}(t.Component),N=function(e){function n(){return u(this,n),f(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return d(n,e),h(n,[{key:"getChildContext",value:function(){return this.props.context}},{key:"render",value:function(){return t.Children.only(this.props.children)}}]),n}(t.Component);N.childContextTypes={theme:e.object};var O=function(e){function t(){u(this,t);var e=f(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e.portalElement=null,e}return d(t,e),h(t,[{key:"componentDidMount",value:function(){var e=document.createElement("div");document.body.appendChild(e),this.portalElement=e,this.componentDidUpdate()}},{key:"componentDidUpdate",value:function(){a.render(s.createElement(N,{context:this.context},s.createElement("div",null,s.createElement("style",null,"\n\t\t\t\t.fade-enter { opacity: 0.01; }\n\t\t\t\t.fade-enter.fade-enter-active { opacity: 1; transition: opacity 200ms; }\n\t\t\t\t.fade-leave { opacity: 1; }\n\t\t\t\t.fade-leave.fade-leave-active { opacity: 0.01; transition: opacity 200ms; }\n\t\t"),s.createElement(i.TransitionGroup,this.props,s.createElement(i.CSSTransition,{timeout:{enter:200,exit:200},classNames:"fade"},this.props.children)))),this.portalElement)}},{key:"componentWillUnmount",value:function(){a.unmountComponentAtNode(this.portalElement),document.body.removeChild(this.portalElement)}},{key:"render",value:function(){return null}}]),t}(t.Component);O.contextTypes={theme:e.object.isRequired};var j={"0%":{top:"50%",left:"50%",width:0,height:0,opacity:1},"100%":{top:0,left:0,width:"100%",height:"100%",opacity:0}},R=function(e){var t=e.color,n=e.size;return{spinner:{display:"inline-block",position:"relative",width:n,height:n},ripple:{position:"absolute",border:"4px solid "+t,opacity:1,borderRadius:"50%",animationName:j,animationDuration:"1s",animationTimingFunction:"cubic-bezier(0, 0.2, 0.8, 1)",animationIterationCount:"infinite"}}};var B=!("undefined"==typeof window||!window.document||!window.document.createElement);function A(e){var t=e.srcSet||e.srcset;return Array.isArray(t)?t.join():t}var F=function(e){function t(e){u(this,t);var o=f(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return o.theme=g(l,e.theme),o.classes=n.StyleSheet.create(g(D,o.theme)),o.state={imageLoaded:!1},function(e){var t=this;e.forEach(function(e){return t[e]=t[e].bind(t)})}.call(o,["gotoNext","gotoPrev","closeBackdrop","handleKeyboardInput","handleImageLoaded"]),o}return d(t,e),h(t,[{key:"getChildContext",value:function(){return{theme:this.theme}}},{key:"componentDidMount",value:function(){this.props.isOpen&&(this.props.enableKeyboardInput&&window.addEventListener("keydown",this.handleKeyboardInput),"number"==typeof this.props.currentImage&&this.preloadImage(this.props.currentImage,this.handleImageLoaded))}},{key:"componentWillReceiveProps",value:function(e){if(B){if(e.preloadNextImage){var t=this.props.currentImage,n=e.currentImage+1,o=e.currentImage-1,r=void 0;t&&e.currentImage>t?r=n:t&&e.currentImage + }))} loop />

With Thumbnails

({ diff --git a/examples/src/components/Gallery.js b/examples/src/components/Gallery.js index f826ecf8..dd9588e2 100644 --- a/examples/src/components/Gallery.js +++ b/examples/src/components/Gallery.js @@ -33,14 +33,18 @@ class Gallery extends Component { }); } gotoPrevious () { - this.setState({ - currentImage: this.state.currentImage - 1, - }); + let prevImage = this.state.currentImage - 1; + + if (this.props.loop && this.state.currentImage === 0) prevImage = this.props.images.length - 1; + + this.gotoImage(prevImage); } gotoNext () { - this.setState({ - currentImage: this.state.currentImage + 1, - }); + let nextImage = this.state.currentImage + 1; + + if (this.props.loop && this.state.currentImage === this.props.images.length - 1) nextImage = 0; + + this.gotoImage(nextImage); } gotoImage (index) { this.setState({ @@ -48,7 +52,7 @@ class Gallery extends Component { }); } handleClickImage () { - if (this.state.currentImage === this.props.images.length - 1) return; + if (!this.props.loop && this.state.currentImage === this.props.images.length - 1) return; this.gotoNext(); } @@ -86,6 +90,7 @@ class Gallery extends Component { currentImage={this.state.currentImage} images={this.props.images} isOpen={this.state.lightboxIsOpen} + loop={this.props.loop} onClickImage={this.handleClickImage} onClickNext={this.gotoNext} onClickPrev={this.gotoPrevious} diff --git a/lib/Lightbox.js b/lib/Lightbox.js index 84ef8469..31a233cd 100644 --- a/lib/Lightbox.js +++ b/lib/Lightbox.js @@ -198,11 +198,12 @@ var Lightbox = function (_Component) { value: function gotoNext(event) { var _props = this.props, currentImage = _props.currentImage, - images = _props.images; + images = _props.images, + loop = _props.loop; var imageLoaded = this.state.imageLoaded; - if (!imageLoaded || currentImage === images.length - 1) return; + if (!imageLoaded || !loop && currentImage === images.length - 1) return; if (event) { event.preventDefault(); @@ -214,11 +215,13 @@ var Lightbox = function (_Component) { }, { key: 'gotoPrev', value: function gotoPrev(event) { - var currentImage = this.props.currentImage; + var _props2 = this.props, + currentImage = _props2.currentImage, + loop = _props2.loop; var imageLoaded = this.state.imageLoaded; - if (!imageLoaded || currentImage === 0) return; + if (!imageLoaded || !loop && currentImage === 0) return; if (event) { event.preventDefault(); @@ -267,7 +270,7 @@ var Lightbox = function (_Component) { }, { key: 'renderArrowPrev', value: function renderArrowPrev() { - if (this.props.currentImage === 0) return null; + if (!this.props.loop && this.props.currentImage === 0) return null; return _react2.default.createElement(_Arrow2.default, { direction: 'left', @@ -280,7 +283,7 @@ var Lightbox = function (_Component) { }, { key: 'renderArrowNext', value: function renderArrowNext() { - if (this.props.currentImage === this.props.images.length - 1) return null; + if (!this.props.loop && this.props.currentImage === this.props.images.length - 1) return null; return _react2.default.createElement(_Arrow2.default, { direction: 'right', @@ -293,11 +296,11 @@ var Lightbox = function (_Component) { }, { key: 'renderDialog', value: function renderDialog() { - var _props2 = this.props, - backdropClosesModal = _props2.backdropClosesModal, - isOpen = _props2.isOpen, - showThumbnails = _props2.showThumbnails, - width = _props2.width; + var _props3 = this.props, + backdropClosesModal = _props3.backdropClosesModal, + isOpen = _props3.isOpen, + showThumbnails = _props3.showThumbnails, + width = _props3.width; var imageLoaded = this.state.imageLoaded; @@ -336,11 +339,11 @@ var Lightbox = function (_Component) { }, { key: 'renderImages', value: function renderImages() { - var _props3 = this.props, - currentImage = _props3.currentImage, - images = _props3.images, - onClickImage = _props3.onClickImage, - showThumbnails = _props3.showThumbnails; + var _props4 = this.props, + currentImage = _props4.currentImage, + images = _props4.images, + onClickImage = _props4.onClickImage, + showThumbnails = _props4.showThumbnails; var imageLoaded = this.state.imageLoaded; @@ -373,12 +376,12 @@ var Lightbox = function (_Component) { }, { key: 'renderThumbnails', value: function renderThumbnails() { - var _props4 = this.props, - images = _props4.images, - currentImage = _props4.currentImage, - onClickThumbnail = _props4.onClickThumbnail, - showThumbnails = _props4.showThumbnails, - thumbnailOffset = _props4.thumbnailOffset; + var _props5 = this.props, + images = _props5.images, + currentImage = _props5.currentImage, + onClickThumbnail = _props5.onClickThumbnail, + showThumbnails = _props5.showThumbnails, + thumbnailOffset = _props5.thumbnailOffset; if (!showThumbnails) return; @@ -393,11 +396,11 @@ var Lightbox = function (_Component) { }, { key: 'renderHeader', value: function renderHeader() { - var _props5 = this.props, - closeButtonTitle = _props5.closeButtonTitle, - customControls = _props5.customControls, - onClose = _props5.onClose, - showCloseButton = _props5.showCloseButton; + var _props6 = this.props, + closeButtonTitle = _props6.closeButtonTitle, + customControls = _props6.customControls, + onClose = _props6.onClose, + showCloseButton = _props6.showCloseButton; return _react2.default.createElement(_Header2.default, { @@ -410,11 +413,11 @@ var Lightbox = function (_Component) { }, { key: 'renderFooter', value: function renderFooter() { - var _props6 = this.props, - currentImage = _props6.currentImage, - images = _props6.images, - imageCountSeparator = _props6.imageCountSeparator, - showImageCount = _props6.showImageCount; + var _props7 = this.props, + currentImage = _props7.currentImage, + images = _props7.images, + imageCountSeparator = _props7.imageCountSeparator, + showImageCount = _props7.showImageCount; if (!images || !images.length) return null; @@ -430,10 +433,10 @@ var Lightbox = function (_Component) { }, { key: 'renderSpinner', value: function renderSpinner() { - var _props7 = this.props, - spinner = _props7.spinner, - spinnerColor = _props7.spinnerColor, - spinnerSize = _props7.spinnerSize; + var _props8 = this.props, + spinner = _props8.spinner, + spinnerColor = _props8.spinnerColor, + spinnerSize = _props8.spinnerSize; var imageLoaded = this.state.imageLoaded; var Spinner = spinner; @@ -499,6 +502,7 @@ Lightbox.defaultProps = { enableKeyboardInput: true, imageCountSeparator: ' of ', leftArrowTitle: 'Previous (Left arrow key)', + loop: false, onClickShowNextImage: true, preloadNextImage: true, preventScroll: true, diff --git a/package.json b/package.json index 222ee3a3..1dbef3f5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-images", - "version": "0.5.19", + "version": "0.5.21", "description": "A simple, responsive lightbox component for displaying an array of images with React.js", "main": "lib/Lightbox.js", "jsnext:main": "dist/react-images.es.js", diff --git a/src/Lightbox.js b/src/Lightbox.js index 42601033..8072a51d 100644 --- a/src/Lightbox.js +++ b/src/Lightbox.js @@ -126,10 +126,10 @@ class Lightbox extends Component { return img; } gotoNext (event) { - const { currentImage, images } = this.props; + const { currentImage, images, loop } = this.props; const { imageLoaded } = this.state; - if (!imageLoaded || currentImage === (images.length - 1)) return; + if (!imageLoaded || (!loop && currentImage === (images.length - 1))) return; if (event) { event.preventDefault(); @@ -139,10 +139,10 @@ class Lightbox extends Component { this.props.onClickNext(); } gotoPrev (event) { - const { currentImage } = this.props; + const { currentImage, loop } = this.props; const { imageLoaded } = this.state; - if (!imageLoaded || currentImage === 0) return; + if (!imageLoaded || (!loop && currentImage === 0)) return; if (event) { event.preventDefault(); @@ -181,7 +181,7 @@ class Lightbox extends Component { // ============================== renderArrowPrev () { - if (this.props.currentImage === 0) return null; + if (!this.props.loop && this.props.currentImage === 0) return null; return (