react-grid-gallery
Advanced tools
Comparing version 0.5.6 to 1.0.0-alpha.0
'use strict'; | ||
var PropTypes = require('prop-types'); | ||
var React = require('react'); | ||
var Lightbox = require('react-images'); | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
var jsxRuntime = require('react/jsx-runtime'); | ||
var react = require('react'); | ||
var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes); | ||
var React__default = /*#__PURE__*/_interopDefaultLegacy(React); | ||
var Lightbox__default = /*#__PURE__*/_interopDefaultLegacy(Lightbox); | ||
function ownKeys(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
var symbols = Object.getOwnPropertySymbols(object); | ||
enumerableOnly && (symbols = symbols.filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
})), keys.push.apply(keys, symbols); | ||
} | ||
return keys; | ||
} | ||
function _objectSpread2(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = null != arguments[i] ? arguments[i] : {}; | ||
i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { | ||
_defineProperty(target, key, source[key]); | ||
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}); | ||
} | ||
return target; | ||
} | ||
function _classCallCheck(instance, Constructor) { | ||
if (!(instance instanceof Constructor)) { | ||
throw new TypeError("Cannot call a class as a function"); | ||
} | ||
} | ||
function _defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
function _createClass(Constructor, protoProps, staticProps) { | ||
if (protoProps) _defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) _defineProperties(Constructor, staticProps); | ||
Object.defineProperty(Constructor, "prototype", { | ||
writable: false | ||
}); | ||
return Constructor; | ||
} | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
function _extends() { | ||
_extends = Object.assign ? Object.assign.bind() : function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
const getStyle = (styleProp, fallback, context) => { | ||
if (typeof styleProp === "function") { | ||
return styleProp(context); | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
function _inherits(subClass, superClass) { | ||
if (typeof superClass !== "function" && superClass !== null) { | ||
throw new TypeError("Super expression must either be null or a function"); | ||
} | ||
subClass.prototype = Object.create(superClass && superClass.prototype, { | ||
constructor: { | ||
value: subClass, | ||
writable: true, | ||
configurable: true | ||
if (typeof styleProp === "object") { | ||
return styleProp; | ||
} | ||
}); | ||
Object.defineProperty(subClass, "prototype", { | ||
writable: false | ||
}); | ||
if (superClass) _setPrototypeOf(subClass, superClass); | ||
} | ||
function _getPrototypeOf(o) { | ||
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { | ||
return o.__proto__ || Object.getPrototypeOf(o); | ||
}; | ||
return _getPrototypeOf(o); | ||
} | ||
function _setPrototypeOf(o, p) { | ||
_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { | ||
o.__proto__ = p; | ||
return o; | ||
}; | ||
return _setPrototypeOf(o, p); | ||
} | ||
function _isNativeReflectConstruct() { | ||
if (typeof Reflect === "undefined" || !Reflect.construct) return false; | ||
if (Reflect.construct.sham) return false; | ||
if (typeof Proxy === "function") return true; | ||
try { | ||
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); | ||
return true; | ||
} catch (e) { | ||
return false; | ||
} | ||
} | ||
function _assertThisInitialized(self) { | ||
if (self === void 0) { | ||
throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); | ||
} | ||
return self; | ||
} | ||
function _possibleConstructorReturn(self, call) { | ||
if (call && (typeof call === "object" || typeof call === "function")) { | ||
return call; | ||
} else if (call !== void 0) { | ||
throw new TypeError("Derived constructors may only return object or undefined"); | ||
} | ||
return _assertThisInitialized(self); | ||
} | ||
function _createSuper(Derived) { | ||
var hasNativeReflectConstruct = _isNativeReflectConstruct(); | ||
return function _createSuperInternal() { | ||
var Super = _getPrototypeOf(Derived), | ||
result; | ||
if (hasNativeReflectConstruct) { | ||
var NewTarget = _getPrototypeOf(this).constructor; | ||
result = Reflect.construct(Super, arguments, NewTarget); | ||
} else { | ||
result = Super.apply(this, arguments); | ||
return fallback(context); | ||
}; | ||
const rotationTransformMap = { | ||
3: "rotate(180deg)", | ||
2: "rotateY(180deg)", | ||
4: "rotate(180deg) rotateY(180deg)", | ||
5: "rotate(270deg) rotateY(180deg)", | ||
6: "rotate(90deg)", | ||
7: "rotate(90deg) rotateY(180deg)", | ||
8: "rotate(270deg)", | ||
}; | ||
const SELECTION_MARGIN = 16; | ||
const thumbnail = ({ item }) => { | ||
const rotationTransformValue = rotationTransformMap[item.orientation]; | ||
const style = { | ||
cursor: "pointer", | ||
maxWidth: "none", | ||
width: item.scaledWidth, | ||
height: item.scaledHeight, | ||
marginLeft: item.marginLeft, | ||
marginTop: 0, | ||
transform: rotationTransformValue, | ||
}; | ||
if (item.isSelected) { | ||
const ratio = item.scaledWidth / item.scaledHeight; | ||
const viewportHeight = item.scaledHeight - SELECTION_MARGIN * 2; | ||
const viewportWidth = item.viewportWidth - SELECTION_MARGIN * 2; | ||
let height, width; | ||
if (item.scaledWidth > item.scaledHeight) { | ||
width = item.scaledWidth - SELECTION_MARGIN * 2; | ||
height = Math.floor(width / ratio); | ||
} | ||
else { | ||
height = item.scaledHeight - SELECTION_MARGIN * 2; | ||
width = Math.floor(height * ratio); | ||
} | ||
const marginTop = Math.abs(Math.floor((viewportHeight - height) / 2)); | ||
const marginLeft = Math.abs(Math.floor((viewportWidth - width) / 2)); | ||
style.width = width; | ||
style.height = height; | ||
style.marginLeft = marginLeft === 0 ? 0 : -marginLeft; | ||
style.marginTop = marginTop === 0 ? 0 : -marginTop; | ||
} | ||
return _possibleConstructorReturn(this, result); | ||
}; | ||
} | ||
var CheckButton = /*#__PURE__*/function (_Component) { | ||
_inherits(CheckButton, _Component); | ||
var _super = _createSuper(CheckButton); | ||
function CheckButton(props) { | ||
var _this; | ||
_classCallCheck(this, CheckButton); | ||
_this = _super.call(this, props); | ||
_this.state = { | ||
hover: _this.props.hover | ||
return style; | ||
}; | ||
const tileViewport = ({ item, }) => { | ||
const styles = { | ||
width: item.viewportWidth, | ||
height: item.scaledHeight, | ||
overflow: "hidden", | ||
}; | ||
_this.fill = _this.fill.bind(_assertThisInitialized(_this)); | ||
_this.visibility = _this.visibility.bind(_assertThisInitialized(_this)); | ||
return _this; | ||
} | ||
_createClass(CheckButton, [{ | ||
key: "fill", | ||
value: function fill() { | ||
if (this.props.isSelected) return this.props.selectedColor;else if (this.state.hover) return this.props.hoverColor; | ||
return this.props.color; | ||
if (item.nano) { | ||
styles.background = `url(${item.nano})`; | ||
styles.backgroundSize = "cover"; | ||
styles.backgroundPosition = "center center"; | ||
} | ||
}, { | ||
key: "visibility", | ||
value: function visibility() { | ||
if (this.props.isSelected || this.props.isSelectable && this.props.parentHover) return 'visible'; | ||
return 'hidden'; | ||
if (item.isSelected) { | ||
styles.width = item.viewportWidth - SELECTION_MARGIN * 2; | ||
styles.height = item.scaledHeight - SELECTION_MARGIN * 2; | ||
styles.margin = SELECTION_MARGIN; | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var _this2 = this; | ||
return styles; | ||
}; | ||
const customOverlay = ({ hover, }) => ({ | ||
pointerEvents: "none", | ||
opacity: hover ? 1 : 0, | ||
position: "absolute", | ||
height: "100%", | ||
width: "100%", | ||
}); | ||
const galleryItem = ({ margin }) => ({ | ||
margin, | ||
WebkitUserSelect: "none", | ||
position: "relative", | ||
float: "left", | ||
background: "#eee", | ||
padding: "0px", | ||
}); | ||
const tileOverlay = ({ showOverlay, }) => ({ | ||
pointerEvents: "none", | ||
opacity: 1, | ||
position: "absolute", | ||
height: "100%", | ||
width: "100%", | ||
background: showOverlay | ||
? "linear-gradient(to bottom,rgba(0,0,0,0.26),transparent 56px,transparent)" | ||
: "none", | ||
}); | ||
const tileIconBar = { | ||
pointerEvents: "none", | ||
opacity: 1, | ||
position: "absolute", | ||
height: "36px", | ||
width: "100%", | ||
}; | ||
const tileDescription = { | ||
background: "white", | ||
height: "100%", | ||
width: "100%", | ||
margin: 0, | ||
userSelect: "text", | ||
WebkitUserSelect: "text", | ||
MozUserSelect: "text", | ||
overflow: "hidden", | ||
}; | ||
const bottomBar = { | ||
padding: "2px", | ||
pointerEvents: "none", | ||
position: "absolute", | ||
minHeight: "0px", | ||
maxHeight: "160px", | ||
width: "100%", | ||
bottom: "0px", | ||
overflow: "hidden", | ||
}; | ||
const tagItemBlock = { | ||
display: "inline-block", | ||
cursor: "pointer", | ||
pointerEvents: "visible", | ||
margin: "2px", | ||
}; | ||
const tagItem = () => ({ | ||
display: "inline", | ||
padding: ".2em .6em .3em", | ||
fontSize: "75%", | ||
fontWeight: "600", | ||
lineHeight: "1", | ||
color: "yellow", | ||
background: "rgba(0,0,0,0.65)", | ||
textAlign: "center", | ||
whiteSpace: "nowrap", | ||
verticalAlign: "baseline", | ||
borderRadius: ".25em", | ||
}); | ||
const checkButton = ({ isVisible, }) => ({ | ||
visibility: isVisible ? "visible" : "hidden", | ||
background: "none", | ||
float: "left", | ||
width: 36, | ||
height: 36, | ||
border: "none", | ||
padding: 6, | ||
cursor: "pointer", | ||
pointerEvents: "visible", | ||
}); | ||
var circleStyle = { | ||
display: this.props.isSelected ? "block" : "none" | ||
}; | ||
return /*#__PURE__*/React__default["default"].createElement("div", { | ||
"data-testid": "grid-gallery-item_check-button", | ||
title: "Select", | ||
style: { | ||
visibility: this.visibility(), | ||
background: 'none', | ||
"float": 'left', | ||
width: '36px', | ||
height: '36px', | ||
border: 'none', | ||
padding: '6px', | ||
cursor: 'pointer', | ||
pointerEvents: 'visible' | ||
}, | ||
onClick: this.props.onClick ? function (e) { | ||
return _this2.props.onClick(_this2.props.index, e); | ||
} : null, | ||
onMouseOver: function onMouseOver(e) { | ||
return _this2.setState({ | ||
hover: true | ||
}); | ||
}, | ||
onMouseOut: function onMouseOut(e) { | ||
return _this2.setState({ | ||
hover: false | ||
}); | ||
} | ||
}, /*#__PURE__*/React__default["default"].createElement("svg", { | ||
fill: this.fill(), | ||
height: "24", | ||
viewBox: "0 0 24 24", | ||
width: "24", | ||
xmlns: "http://www.w3.org/2000/svg" | ||
}, /*#__PURE__*/React__default["default"].createElement("radialGradient", { | ||
id: "shadow", | ||
cx: "38", | ||
cy: "95.488", | ||
r: "10.488", | ||
gradientTransform: "matrix(1 0 0 -1 -26 109)", | ||
gradientUnits: "userSpaceOnUse" | ||
}, /*#__PURE__*/React__default["default"].createElement("stop", { | ||
offset: ".832", | ||
stopColor: "#010101" | ||
}), /*#__PURE__*/React__default["default"].createElement("stop", { | ||
offset: "1", | ||
stopColor: "#010101", | ||
stopOpacity: "0" | ||
})), /*#__PURE__*/React__default["default"].createElement("circle", { | ||
style: circleStyle, | ||
opacity: ".26", | ||
fill: "url(#shadow)", | ||
cx: "12", | ||
cy: "13.512", | ||
r: "10.488" | ||
}), /*#__PURE__*/React__default["default"].createElement("circle", { | ||
style: circleStyle, | ||
fill: "#FFF", | ||
cx: "12", | ||
cy: "12.2", | ||
r: "8.292" | ||
}), /*#__PURE__*/React__default["default"].createElement("path", { | ||
d: "M0 0h24v24H0z", | ||
fill: "none" | ||
}), /*#__PURE__*/React__default["default"].createElement("path", { | ||
d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" | ||
}))); | ||
} | ||
}]); | ||
return CheckButton; | ||
}(React.Component); | ||
CheckButton.propTypes = { | ||
index: PropTypes__default["default"].number, | ||
color: PropTypes__default["default"].string, | ||
isSelectable: PropTypes__default["default"].bool, | ||
isSelected: PropTypes__default["default"].bool, | ||
selectedColor: PropTypes__default["default"].string, | ||
parentHover: PropTypes__default["default"].bool, | ||
hover: PropTypes__default["default"].bool, | ||
hoverColor: PropTypes__default["default"].string, | ||
onClick: PropTypes__default["default"].func | ||
const CheckButton = (props) => { | ||
const { isSelected, isVisible, onClick } = props; | ||
const { selectedColor, hoverColor, color } = props; | ||
const [hover, setHover] = react.useState(false); | ||
const circleStyle = { display: isSelected ? "block" : "none" }; | ||
const fillColor = isSelected ? selectedColor : hover ? hoverColor : color; | ||
const handleMouseOver = () => setHover(true); | ||
const handleMouseOut = () => setHover(false); | ||
return (jsxRuntime.jsx("div", { "data-testid": "grid-gallery-item_check-button", title: "Select", style: checkButton({ isVisible }), onClick: onClick, onMouseOver: handleMouseOver, onMouseOut: handleMouseOut, children: jsxRuntime.jsxs("svg", { fill: fillColor, height: "24", viewBox: "0 0 24 24", width: "24", xmlns: "http://www.w3.org/2000/svg", children: [jsxRuntime.jsxs("radialGradient", { id: "shadow", cx: "38", cy: "95.488", r: "10.488", gradientTransform: "matrix(1 0 0 -1 -26 109)", gradientUnits: "userSpaceOnUse", children: [jsxRuntime.jsx("stop", { offset: ".832", stopColor: "#010101" }), jsxRuntime.jsx("stop", { offset: "1", stopColor: "#010101", stopOpacity: "0" })] }), jsxRuntime.jsx("circle", { style: circleStyle, opacity: ".26", fill: "url(#shadow)", cx: "12", cy: "13.512", r: "10.488" }), jsxRuntime.jsx("circle", { style: circleStyle, fill: "#FFF", cx: "12", cy: "12.2", r: "8.292" }), jsxRuntime.jsx("path", { d: "M0 0h24v24H0z", fill: "none" }), jsxRuntime.jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" })] }) })); | ||
}; | ||
CheckButton.defaultProps = { | ||
isSelectable: true, | ||
isSelected: false, | ||
parentHover: false, | ||
hover: false | ||
isSelected: false, | ||
isVisible: true, | ||
color: "#FFFFFFB2", | ||
selectedColor: "#4285F4FF", | ||
hoverColor: "#FFFFFFFF", | ||
}; | ||
var Image = /*#__PURE__*/function (_Component) { | ||
_inherits(Image, _Component); | ||
var _super = _createSuper(Image); | ||
function Image(props) { | ||
var _this; | ||
_classCallCheck(this, Image); | ||
_this = _super.call(this, props); | ||
_this.state = { | ||
hover: false | ||
const Image = (props) => { | ||
const { item, thumbnailImageComponent: ThumbnailImageComponent } = props; | ||
const styleContext = { item }; | ||
const [hover, setHover] = react.useState(false); | ||
const thumbnailProps = { | ||
key: props.index, | ||
"data-testid": "grid-gallery-item_thumbnail", | ||
src: item.src, | ||
alt: item.alt ? item.alt : "", | ||
title: typeof item.caption === "string" ? item.caption : null, | ||
style: getStyle(props.thumbnailStyle, thumbnail, styleContext), | ||
}; | ||
return _this; | ||
} | ||
_createClass(Image, [{ | ||
key: "tagStyle", | ||
value: function tagStyle() { | ||
if (this.props.tagStyle) return this.props.tagStyle; | ||
return { | ||
display: "inline", | ||
padding: ".2em .6em .3em", | ||
fontSize: "75%", | ||
fontWeight: "600", | ||
lineHeight: "1", | ||
color: "yellow", | ||
background: "rgba(0,0,0,0.65)", | ||
textAlign: "center", | ||
whiteSpace: "nowrap", | ||
verticalAlign: "baseline", | ||
borderRadius: ".25em" | ||
}; | ||
} | ||
}, { | ||
key: "tileViewportStyle", | ||
value: function tileViewportStyle() { | ||
if (this.props.tileViewportStyle) return this.props.tileViewportStyle.call(this); | ||
var nanoBase64Backgorund = {}; | ||
if (this.props.item.nano) { | ||
nanoBase64Backgorund = { | ||
background: "url(".concat(this.props.item.nano, ")"), | ||
backgroundSize: 'cover', | ||
backgroundPosition: 'center center' | ||
}; | ||
} | ||
if (this.props.item.isSelected) return Object.assign({ | ||
width: this.props.item.vwidth - 32, | ||
height: this.props.height - 32, | ||
margin: 16, | ||
overflow: "hidden" | ||
}, nanoBase64Backgorund); | ||
return Object.assign({ | ||
width: this.props.item.vwidth, | ||
height: this.props.height, | ||
overflow: "hidden" | ||
}, nanoBase64Backgorund); | ||
} | ||
}, { | ||
key: "thumbnailStyle", | ||
value: function thumbnailStyle() { | ||
if (this.props.thumbnailStyle) return this.props.thumbnailStyle.call(this); | ||
var rotationTransformValue = undefined; | ||
switch (this.props.item.orientation) { | ||
case 3: | ||
rotationTransformValue = "rotate(180deg)"; | ||
break; | ||
case 6: | ||
rotationTransformValue = "rotate(90deg)"; | ||
break; | ||
case 8: | ||
rotationTransformValue = "rotate(270deg)"; | ||
break; | ||
case 2: | ||
rotationTransformValue = "rotateY(180deg)"; | ||
break; | ||
case 4: | ||
rotationTransformValue = "rotate(180deg) rotateY(180deg)"; | ||
break; | ||
case 5: | ||
rotationTransformValue = "rotate(270deg) rotateY(180deg)"; | ||
break; | ||
case 7: | ||
rotationTransformValue = "rotate(90deg) rotateY(180deg)"; | ||
break; | ||
} | ||
if (this.props.item.isSelected) { | ||
var ratio = this.props.item.scaletwidth / this.props.height; | ||
var height = 0; | ||
var width = 0; | ||
var viewportHeight = this.props.height - 32; | ||
var viewportWidth = this.props.item.vwidth - 32; | ||
if (this.props.item.scaletwidth > this.props.height) { | ||
width = this.props.item.scaletwidth - 32; | ||
height = Math.floor(width / ratio); | ||
} else { | ||
height = this.props.height - 32; | ||
width = Math.floor(height * ratio); | ||
const handleCheckButtonClick = (event) => { | ||
if (!props.isSelectable) { | ||
return; | ||
} | ||
var marginTop = -Math.abs(Math.floor((viewportHeight - height) / 2)); | ||
var marginLeft = -Math.abs(Math.floor((viewportWidth - width) / 2)); | ||
return { | ||
cursor: 'pointer', | ||
width: width, | ||
height: height, | ||
marginLeft: marginLeft, | ||
marginTop: marginTop, | ||
transform: rotationTransformValue | ||
}; | ||
} | ||
return { | ||
cursor: 'pointer', | ||
width: this.props.item.scaletwidth, | ||
height: this.props.height, | ||
marginLeft: this.props.item.marginLeft, | ||
marginTop: 0, | ||
transform: rotationTransformValue | ||
}; | ||
} | ||
}, { | ||
key: "renderCheckButton", | ||
value: function renderCheckButton() { | ||
return /*#__PURE__*/React__default["default"].createElement(CheckButton, { | ||
key: "Select", | ||
index: this.props.index, | ||
color: "rgba(255, 255, 255, 0.7)", | ||
selectedColor: "#4285f4", | ||
hoverColor: "rgba(255, 255, 255, 1)", | ||
isSelected: this.props.item.isSelected, | ||
isSelectable: this.props.isSelectable, | ||
onClick: this.props.isSelectable ? this.props.onSelectImage : null, | ||
parentHover: this.state.hover | ||
}); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var _this2 = this; | ||
var alt = this.props.item.alt ? this.props.item.alt : ""; | ||
var tags = typeof this.props.item.tags === 'undefined' ? /*#__PURE__*/React__default["default"].createElement("noscript", null) : this.props.item.tags.map(function (tag) { | ||
var key = tag.key || (typeof tag.value === 'string' ? tag.value : null) || tag.title; | ||
return /*#__PURE__*/React__default["default"].createElement("div", { | ||
title: tag.title, | ||
key: "tag-" + key, | ||
style: { | ||
display: "inline-block", | ||
cursor: 'pointer', | ||
pointerEvents: 'visible', | ||
margin: "2px" | ||
} | ||
}, /*#__PURE__*/React__default["default"].createElement("span", { | ||
style: _this2.tagStyle() | ||
}, tag.value)); | ||
}); | ||
var customOverlay = typeof this.props.item.customOverlay === 'undefined' ? /*#__PURE__*/React__default["default"].createElement("noscript", null) : /*#__PURE__*/React__default["default"].createElement("div", { | ||
className: "ReactGridGallery_custom-overlay", | ||
key: "custom-overlay-" + this.props.index, | ||
style: { | ||
pointerEvents: "none", | ||
opacity: this.state.hover ? 1 : 0, | ||
position: "absolute", | ||
height: "100%", | ||
width: "100%" | ||
} | ||
}, this.props.item.customOverlay); | ||
var thumbnailProps = { | ||
key: "img-" + this.props.index, | ||
src: this.props.item.thumbnail, | ||
alt: alt, | ||
title: typeof this.props.item.caption === 'string' ? this.props.item.caption : null, | ||
style: this.thumbnailStyle(), | ||
'data-testid': "grid-gallery-item_thumbnail" | ||
}; | ||
var ThumbnailImageComponent = this.props.thumbnailImageComponent; | ||
return /*#__PURE__*/React__default["default"].createElement("div", { | ||
className: "ReactGridGallery_tile", | ||
"data-testid": "grid-gallery-item", | ||
key: "tile-" + this.props.index, | ||
onMouseEnter: function onMouseEnter(e) { | ||
return _this2.setState({ | ||
hover: true | ||
}); | ||
}, | ||
onMouseLeave: function onMouseLeave(e) { | ||
return _this2.setState({ | ||
hover: false | ||
}); | ||
}, | ||
style: { | ||
margin: this.props.margin, | ||
WebkitUserSelect: "none", | ||
position: "relative", | ||
"float": "left", | ||
background: "#eee", | ||
padding: "0px" | ||
} | ||
}, /*#__PURE__*/React__default["default"].createElement("div", { | ||
className: "ReactGridGallery_tile-icon-bar", | ||
key: "tile-icon-bar-" + this.props.index, | ||
style: { | ||
pointerEvents: "none", | ||
opacity: 1, | ||
position: "absolute", | ||
height: "36px", | ||
width: "100%" | ||
} | ||
}, this.renderCheckButton()), /*#__PURE__*/React__default["default"].createElement("div", { | ||
className: "ReactGridGallery_tile-bottom-bar", | ||
key: "tile-bottom-bar-" + this.props.index, | ||
style: { | ||
padding: "2px", | ||
pointerEvents: "none", | ||
position: "absolute", | ||
minHeight: "0px", | ||
maxHeight: "160px", | ||
width: "100%", | ||
bottom: "0px", | ||
overflow: "hidden" | ||
} | ||
}, tags), customOverlay, /*#__PURE__*/React__default["default"].createElement("div", { | ||
className: "ReactGridGallery_tile-overlay", | ||
key: "tile-overlay-" + this.props.index, | ||
style: { | ||
pointerEvents: "none", | ||
opacity: 1, | ||
position: "absolute", | ||
height: "100%", | ||
width: "100%", | ||
background: this.state.hover && !this.props.item.isSelected && this.props.isSelectable ? 'linear-gradient(to bottom,rgba(0,0,0,0.26),transparent 56px,transparent)' : 'none' | ||
} | ||
}), /*#__PURE__*/React__default["default"].createElement("div", { | ||
className: "ReactGridGallery_tile-viewport", | ||
"data-testid": "grid-gallery-item_viewport", | ||
style: this.tileViewportStyle(), | ||
key: "tile-viewport-" + this.props.index, | ||
onClick: this.props.onClick ? function (e) { | ||
return _this2.props.onClick.call(_this2, _this2.props.index, e); | ||
} : null | ||
}, ThumbnailImageComponent ? /*#__PURE__*/React__default["default"].createElement(ThumbnailImageComponent, _extends({}, this.props, { | ||
imageProps: thumbnailProps | ||
})) : /*#__PURE__*/React__default["default"].createElement("img", thumbnailProps)), this.props.item.thumbnailCaption && /*#__PURE__*/React__default["default"].createElement("div", { | ||
className: "ReactGridGallery_tile-description", | ||
style: { | ||
background: "white", | ||
height: "100%", | ||
width: "100%", | ||
margin: 0, | ||
userSelect: "text", | ||
WebkitUserSelect: "text", | ||
MozUserSelect: "text", | ||
overflow: "hidden" | ||
} | ||
}, this.props.item.thumbnailCaption)); | ||
} | ||
}]); | ||
return Image; | ||
}(React.Component); | ||
Image.propTypes = { | ||
item: PropTypes__default["default"].object, | ||
index: PropTypes__default["default"].number, | ||
margin: PropTypes__default["default"].number, | ||
height: PropTypes__default["default"].number, | ||
isSelectable: PropTypes__default["default"].bool, | ||
onClick: PropTypes__default["default"].func, | ||
onSelectImage: PropTypes__default["default"].func, | ||
tileViewportStyle: PropTypes__default["default"].func, | ||
thumbnailStyle: PropTypes__default["default"].func, | ||
tagStyle: PropTypes__default["default"].object, | ||
customOverlay: PropTypes__default["default"].element, | ||
thumbnailImageComponent: PropTypes__default["default"].func | ||
props.onSelect(props.index, event); | ||
}; | ||
const handleViewportClick = (event) => { | ||
props.onClick(props.index, event); | ||
}; | ||
return (jsxRuntime.jsxs("div", { className: "ReactGridGallery_tile", "data-testid": "grid-gallery-item", onMouseEnter: () => setHover(true), onMouseLeave: () => setHover(false), style: galleryItem({ margin: props.margin }), children: [jsxRuntime.jsx("div", { className: "ReactGridGallery_tile-icon-bar", style: tileIconBar, children: jsxRuntime.jsx(CheckButton, { isSelected: item.isSelected, isVisible: item.isSelected || (props.isSelectable && hover), onClick: handleCheckButtonClick }) }), !!item.tags && (jsxRuntime.jsx("div", { className: "ReactGridGallery_tile-bottom-bar", style: bottomBar, children: item.tags.map((tag, index) => (jsxRuntime.jsx("div", { title: tag.title, style: tagItemBlock, children: jsxRuntime.jsx("span", { style: getStyle(props.tagStyle, tagItem, styleContext), children: tag.value }) }, tag.key || index))) })), !!item.customOverlay && (jsxRuntime.jsx("div", { className: "ReactGridGallery_custom-overlay", style: customOverlay({ hover }), children: item.customOverlay })), jsxRuntime.jsx("div", { className: "ReactGridGallery_tile-overlay", style: tileOverlay({ | ||
showOverlay: hover && !item.isSelected && props.isSelectable, | ||
}) }), jsxRuntime.jsx("div", { className: "ReactGridGallery_tile-viewport", "data-testid": "grid-gallery-item_viewport", style: getStyle(props.tileViewportStyle, tileViewport, styleContext), onClick: handleViewportClick, children: ThumbnailImageComponent ? (jsxRuntime.jsx(ThumbnailImageComponent, { ...props, imageProps: thumbnailProps })) : (jsxRuntime.jsx("img", { ...thumbnailProps })) }), item.thumbnailCaption && (jsxRuntime.jsx("div", { className: "ReactGridGallery_tile-description", style: tileDescription, children: item.thumbnailCaption }))] })); | ||
}; | ||
Image.defaultProps = { | ||
isSelectable: true, | ||
hover: false | ||
isSelectable: true, | ||
}; | ||
var calculateCutOff = function calculateCutOff(len, delta, items) { | ||
var cutoff = []; | ||
var cutsum = 0; | ||
for (var i in items) { | ||
var item = items[i]; | ||
var fractOfLen = item.scaletwidth / len; | ||
cutoff[i] = Math.floor(fractOfLen * delta); | ||
cutsum += cutoff[i]; | ||
} | ||
var stillToCutOff = delta - cutsum; | ||
while (stillToCutOff > 0) { | ||
for (i in cutoff) { | ||
cutoff[i]++; | ||
stillToCutOff--; | ||
if (stillToCutOff < 0) break; | ||
} | ||
} | ||
return cutoff; | ||
const objectStyles = { | ||
position: "absolute", | ||
top: 0, | ||
left: 0, | ||
height: "100%", | ||
width: "100%", | ||
pointerEvents: "none", | ||
zIndex: -1, | ||
opacity: 0, | ||
}; | ||
const ResizeListener = ({ onResize, }) => { | ||
const objectRef = react.useRef(null); | ||
const onResizeRef = react.useRef(onResize); | ||
onResizeRef.current = onResize; | ||
const _onResize = react.useCallback(() => { | ||
onResizeRef.current(); | ||
}, []); | ||
const handleLoad = react.useCallback(() => { | ||
const obj = objectRef.current; | ||
if (obj && obj.contentDocument && obj.contentDocument.defaultView) { | ||
obj.contentDocument.defaultView.addEventListener("resize", _onResize); | ||
} | ||
}, []); | ||
react.useEffect(() => { | ||
return () => { | ||
const obj = objectRef.current; | ||
if (obj && obj.contentDocument && obj.contentDocument.defaultView) { | ||
obj.contentDocument.defaultView.removeEventListener("resize", _onResize); | ||
} | ||
}; | ||
}, []); | ||
return (jsxRuntime.jsx("object", { onLoad: handleLoad, ref: objectRef, tabIndex: -1, type: "text/html", data: "about:blank", title: "", style: objectStyles })); | ||
}; | ||
var buildImageRow = function buildImageRow(data, _ref) { | ||
var containerWidth = _ref.containerWidth, | ||
margin = _ref.margin; | ||
var row = []; | ||
var len = 0; | ||
var imgMargin = 2 * margin; | ||
while (data.items.length > 0 && len < containerWidth) { | ||
var item = data.items.shift(); | ||
row.push(item); | ||
len += item.scaletwidth + imgMargin; | ||
} | ||
var delta = len - containerWidth; | ||
if (row.length > 0 && delta > 0) { | ||
var cutoff = calculateCutOff(len, delta, row); | ||
for (var i in row) { | ||
var pixelsToRemove = cutoff[i]; | ||
item = row[i]; | ||
item.marginLeft = -Math.abs(Math.floor(pixelsToRemove / 2)); | ||
item.vwidth = item.scaletwidth - pixelsToRemove; | ||
const calculateCutOff = (items, totalRowWidth, protrudingWidth) => { | ||
const cutOff = []; | ||
let cutSum = 0; | ||
for (let i in items) { | ||
const item = items[i]; | ||
const fractionOfWidth = item.scaledWidth / totalRowWidth; | ||
cutOff[i] = Math.floor(fractionOfWidth * protrudingWidth); | ||
cutSum += cutOff[i]; | ||
} | ||
} else { | ||
for (var j in row) { | ||
item = row[j]; | ||
item.marginLeft = 0; | ||
item.vwidth = item.scaletwidth; | ||
let stillToCutOff = protrudingWidth - cutSum; | ||
while (stillToCutOff > 0) { | ||
for (let i in cutOff) { | ||
cutOff[i]++; | ||
stillToCutOff--; | ||
if (stillToCutOff < 0) | ||
break; | ||
} | ||
} | ||
} | ||
return row; | ||
return cutOff; | ||
}; | ||
var renderThumbs = function renderThumbs(images, _ref2) { | ||
var containerWidth = _ref2.containerWidth, | ||
maxRows = _ref2.maxRows, | ||
rowHeight = _ref2.rowHeight, | ||
margin = _ref2.margin; | ||
rowHeight = typeof rowHeight === "undefined" ? 180 : rowHeight; | ||
margin = typeof margin === "undefined" ? 2 : margin; | ||
if (!images) return []; | ||
if (!containerWidth) return []; | ||
var items = images.slice(); | ||
items = items.map(function (item) { | ||
return _objectSpread2(_objectSpread2({}, item), {}, { | ||
scaletwidth: Math.floor(rowHeight * (item.thumbnailWidth / item.thumbnailHeight)) | ||
}); | ||
}); | ||
var data = { | ||
items: items | ||
}; | ||
var thumbs = []; | ||
var rows = []; | ||
while (data.items.length > 0) { | ||
rows.push(buildImageRow(data, { | ||
containerWidth: containerWidth, | ||
margin: margin | ||
})); | ||
} | ||
for (var r in rows) { | ||
for (var i in rows[r]) { | ||
var item = _objectSpread2(_objectSpread2({}, rows[r][i]), {}, { | ||
rowIndex: parseInt(r) | ||
}); | ||
if (maxRows) { | ||
if (r < maxRows) { | ||
thumbs.push(item); | ||
const getRow = (images, { containerWidth, rowHeight, margin }) => { | ||
const row = []; | ||
const imgMargin = 2 * margin; | ||
const items = [...images]; | ||
let totalRowWidth = 0; | ||
while (items.length > 0 && totalRowWidth < containerWidth) { | ||
const item = items.shift(); | ||
const scaledWidth = Math.floor(rowHeight * (item.width / item.height)); | ||
const extendedItem = { | ||
...item, | ||
scaledHeight: rowHeight, | ||
scaledWidth, | ||
viewportWidth: scaledWidth, | ||
marginLeft: 0, | ||
}; | ||
row.push(extendedItem); | ||
totalRowWidth += extendedItem.scaledWidth + imgMargin; | ||
} | ||
const protrudingWidth = totalRowWidth - containerWidth; | ||
if (row.length > 0 && protrudingWidth > 0) { | ||
const cutoff = calculateCutOff(row, totalRowWidth, protrudingWidth); | ||
for (const i in row) { | ||
const pixelsToRemove = cutoff[i]; | ||
const item = row[i]; | ||
item.marginLeft = -Math.abs(Math.floor(pixelsToRemove / 2)); | ||
item.viewportWidth = item.scaledWidth - pixelsToRemove; | ||
} | ||
} else { | ||
thumbs.push(item); | ||
} | ||
} | ||
} | ||
return thumbs; | ||
return [row, items]; | ||
}; | ||
var Gallery = /*#__PURE__*/function (_Component) { | ||
_inherits(Gallery, _Component); | ||
var _super = _createSuper(Gallery); | ||
function Gallery(props) { | ||
var _this; | ||
_classCallCheck(this, Gallery); | ||
_this = _super.call(this, props); | ||
_this.state = { | ||
lightboxIsOpen: _this.props.isOpen, | ||
currentImage: _this.props.currentImage, | ||
containerWidth: _this.props.defaultContainerWidth | ||
}; | ||
_this.onResize = _this.onResize.bind(_assertThisInitialized(_this)); | ||
_this.closeLightbox = _this.closeLightbox.bind(_assertThisInitialized(_this)); | ||
_this.gotoImage = _this.gotoImage.bind(_assertThisInitialized(_this)); | ||
_this.gotoNext = _this.gotoNext.bind(_assertThisInitialized(_this)); | ||
_this.gotoPrevious = _this.gotoPrevious.bind(_assertThisInitialized(_this)); | ||
_this.onClickImage = _this.onClickImage.bind(_assertThisInitialized(_this)); | ||
_this.openLightbox = _this.openLightbox.bind(_assertThisInitialized(_this)); | ||
_this.onSelectImage = _this.onSelectImage.bind(_assertThisInitialized(_this)); | ||
return _this; | ||
} | ||
_createClass(Gallery, [{ | ||
key: "componentDidMount", | ||
value: function componentDidMount() { | ||
this.onResize(); | ||
const getRows = (images, options, rows = []) => { | ||
const [row, imagesLeft] = getRow(images, options); | ||
const nextRows = [...rows, row]; | ||
if (options.maxRows && nextRows.length >= options.maxRows) { | ||
return nextRows; | ||
} | ||
}, { | ||
key: "componentDidUpdate", | ||
value: function componentDidUpdate() { | ||
if (!this._gallery) return; | ||
if (this.getContainerWidth() !== this.state.containerWidth) { | ||
this.onResize(); | ||
} | ||
if (imagesLeft.length) { | ||
return getRows(imagesLeft, options, nextRows); | ||
} | ||
}, { | ||
key: "onResize", | ||
value: function onResize() { | ||
if (!this._gallery) return; | ||
var containerWidth = this.getContainerWidth(); | ||
this.setState({ | ||
containerWidth: containerWidth | ||
}); | ||
} | ||
}, { | ||
key: "getContainerWidth", | ||
value: function getContainerWidth() { | ||
var width = this._gallery.clientWidth; | ||
return nextRows; | ||
}; | ||
const buildLayout = (images, { containerWidth, maxRows, rowHeight, margin }) => { | ||
rowHeight = typeof rowHeight === "undefined" ? 180 : rowHeight; | ||
margin = typeof margin === "undefined" ? 2 : margin; | ||
if (!images) | ||
return []; | ||
if (!containerWidth) | ||
return []; | ||
const options = { containerWidth, maxRows, rowHeight, margin }; | ||
return getRows(images, options); | ||
}; | ||
const buildLayoutFlat = (images, options) => { | ||
const rows = buildLayout(images, options); | ||
return [].concat.apply([], rows); | ||
}; | ||
try { | ||
width = this._gallery.getBoundingClientRect().width; | ||
} catch (err) {} | ||
return Math.floor(width); | ||
} | ||
}, { | ||
key: "getCurrentImageIndex", | ||
value: function getCurrentImageIndex() { | ||
return Math.min(this.state.currentImage, this.props.images.length - 1); | ||
} | ||
}, { | ||
key: "openLightbox", | ||
value: function openLightbox(index, event) { | ||
if (event) { | ||
event.preventDefault(); | ||
} | ||
if (this.props.lightboxWillOpen) { | ||
this.props.lightboxWillOpen.call(this, index); | ||
} | ||
if (this.props.currentImageWillChange) { | ||
this.props.currentImageWillChange.call(this, index); | ||
} | ||
this.setState({ | ||
currentImage: index, | ||
lightboxIsOpen: true | ||
}); | ||
} | ||
}, { | ||
key: "closeLightbox", | ||
value: function closeLightbox() { | ||
if (this.props.lightboxWillClose) { | ||
this.props.lightboxWillClose.call(this); | ||
} | ||
if (this.props.currentImageWillChange) { | ||
this.props.currentImageWillChange.call(this, 0); | ||
} | ||
this.setState({ | ||
currentImage: 0, | ||
lightboxIsOpen: false | ||
}); | ||
} | ||
}, { | ||
key: "gotoPrevious", | ||
value: function gotoPrevious() { | ||
if (this.props.currentImageWillChange) { | ||
this.props.currentImageWillChange.call(this, this.getCurrentImageIndex() - 1); | ||
} | ||
this.setState({ | ||
currentImage: this.getCurrentImageIndex() - 1 | ||
}); | ||
} | ||
}, { | ||
key: "gotoNext", | ||
value: function gotoNext() { | ||
if (this.props.currentImageWillChange) { | ||
this.props.currentImageWillChange.call(this, this.getCurrentImageIndex() + 1); | ||
} | ||
this.setState({ | ||
currentImage: this.getCurrentImageIndex() + 1 | ||
}); | ||
} | ||
}, { | ||
key: "onClickImage", | ||
value: function onClickImage() { | ||
if (this.state.currentImage === this.props.images.length - 1) return; | ||
this.gotoNext(); | ||
} | ||
}, { | ||
key: "onSelectImage", | ||
value: function onSelectImage(index, event) { | ||
event.preventDefault(); | ||
if (this.props.onSelectImage) this.props.onSelectImage.call(this, index, this.props.images[index]); | ||
} | ||
}, { | ||
key: "gotoImage", | ||
value: function gotoImage(index) { | ||
if (this.props.currentImageWillChange) { | ||
this.props.currentImageWillChange.call(this, index); | ||
} | ||
this.setState({ | ||
currentImage: index | ||
}); | ||
} | ||
}, { | ||
key: "getOnClickThumbnailFn", | ||
value: function getOnClickThumbnailFn() { | ||
if (!this.props.onClickThumbnail && this.props.enableLightbox) return this.openLightbox; | ||
if (this.props.onClickThumbnail) return this.props.onClickThumbnail; | ||
return null; | ||
} | ||
}, { | ||
key: "getOnClickLightboxThumbnailFn", | ||
value: function getOnClickLightboxThumbnailFn() { | ||
if (!this.props.onClickLightboxThumbnail && this.props.showLightboxThumbnails) return this.gotoImage; | ||
if (this.props.onClickLightboxThumbnail && this.props.showLightboxThumbnails) return this.props.onClickLightboxThumbnail; | ||
return null; | ||
} | ||
}, { | ||
key: "getOnClickImageFn", | ||
value: function getOnClickImageFn() { | ||
if (this.props.onClickImage) return this.props.onClickImage; | ||
return this.onClickImage; | ||
} | ||
}, { | ||
key: "getOnClickPrevFn", | ||
value: function getOnClickPrevFn() { | ||
if (this.props.onClickPrev) return this.props.onClickPrev; | ||
return this.gotoPrevious; | ||
} | ||
}, { | ||
key: "getOnClickNextFn", | ||
value: function getOnClickNextFn() { | ||
if (this.props.onClickNext) return this.props.onClickNext; | ||
return this.gotoNext; | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var _this2 = this; | ||
var _this$props = this.props, | ||
maxRows = _this$props.maxRows, | ||
rowHeight = _this$props.rowHeight, | ||
margin = _this$props.margin; | ||
var containerWidth = this.state.containerWidth; | ||
var thumbnails = renderThumbs(this.props.images, { | ||
containerWidth: containerWidth, | ||
maxRows: maxRows, | ||
rowHeight: rowHeight, | ||
margin: margin | ||
}); | ||
var images = thumbnails.map(function (item, idx) { | ||
return /*#__PURE__*/React__default["default"].createElement(Image, { | ||
key: "Image-" + idx + "-" + item.src, | ||
item: item, | ||
index: idx, | ||
margin: _this2.props.margin, | ||
height: _this2.props.rowHeight, | ||
isSelectable: _this2.props.enableImageSelection, | ||
onClick: _this2.getOnClickThumbnailFn(), | ||
onSelectImage: _this2.onSelectImage, | ||
tagStyle: _this2.props.tagStyle, | ||
tileViewportStyle: _this2.props.tileViewportStyle, | ||
thumbnailStyle: _this2.props.thumbnailStyle, | ||
thumbnailImageComponent: _this2.props.thumbnailImageComponent | ||
}); | ||
}); | ||
var resizeIframeStyles = { | ||
height: 0, | ||
margin: 0, | ||
padding: 0, | ||
overflow: "hidden", | ||
borderWidth: 0, | ||
position: "fixed", | ||
backgroundColor: "transparent", | ||
width: "100%" | ||
}; | ||
return /*#__PURE__*/React__default["default"].createElement("div", { | ||
id: this.props.id, | ||
className: "ReactGridGallery", | ||
ref: function ref(c) { | ||
return _this2._gallery = c; | ||
const Gallery = (props) => { | ||
const galleryRef = react.useRef(null); | ||
const { maxRows, rowHeight, margin, enableImageSelection } = props; | ||
const { defaultContainerWidth, images } = props; | ||
const [containerWidth, setContainerWidth] = react.useState(defaultContainerWidth); | ||
const handleResize = react.useCallback(() => { | ||
if (!galleryRef.current) { | ||
return; | ||
} | ||
}, /*#__PURE__*/React__default["default"].createElement("iframe", { | ||
style: resizeIframeStyles, | ||
ref: function ref(c) { | ||
return c && c.contentWindow && c.contentWindow.addEventListener('resize', _this2.onResize); | ||
let width = galleryRef.current.clientWidth; | ||
try { | ||
width = galleryRef.current.getBoundingClientRect().width; | ||
} | ||
}), images, /*#__PURE__*/React__default["default"].createElement(Lightbox__default["default"], _extends({ | ||
images: this.props.images, | ||
backdropClosesModal: this.props.backdropClosesModal, | ||
currentImage: this.getCurrentImageIndex(), | ||
preloadNextImage: this.props.preloadNextImage, | ||
customControls: this.props.customControls, | ||
enableKeyboardInput: this.props.enableKeyboardInput, | ||
imageCountSeparator: this.props.imageCountSeparator, | ||
isOpen: this.state.lightboxIsOpen, | ||
onClickImage: this.getOnClickImageFn(), | ||
onClickNext: this.getOnClickNextFn(), | ||
onClickPrev: this.getOnClickPrevFn(), | ||
showCloseButton: this.props.showCloseButton, | ||
showImageCount: this.props.showImageCount, | ||
onClose: this.closeLightbox, | ||
width: this.props.lightboxWidth, | ||
theme: this.props.theme, | ||
onClickThumbnail: this.getOnClickLightboxThumbnailFn(), | ||
showThumbnails: this.props.showLightboxThumbnails | ||
}, this.props.lightBoxProps))); | ||
} | ||
}]); | ||
return Gallery; | ||
}(React.Component); | ||
Gallery.displayName = 'Gallery'; | ||
Gallery.propTypes = { | ||
images: PropTypes__default["default"].arrayOf(PropTypes__default["default"].shape({ | ||
src: PropTypes__default["default"].string.isRequired, | ||
nano: PropTypes__default["default"].string, | ||
alt: PropTypes__default["default"].string, | ||
thumbnail: PropTypes__default["default"].string.isRequired, | ||
srcset: PropTypes__default["default"].array, | ||
caption: PropTypes__default["default"].oneOfType([PropTypes__default["default"].string, PropTypes__default["default"].element]), | ||
tags: PropTypes__default["default"].arrayOf(PropTypes__default["default"].shape({ | ||
value: PropTypes__default["default"].oneOfType([PropTypes__default["default"].string, PropTypes__default["default"].element]).isRequired, | ||
title: PropTypes__default["default"].string.isRequired, | ||
key: PropTypes__default["default"].string | ||
})), | ||
thumbnailWidth: PropTypes__default["default"].number.isRequired, | ||
thumbnailHeight: PropTypes__default["default"].number.isRequired, | ||
isSelected: PropTypes__default["default"].bool, | ||
thumbnailCaption: PropTypes__default["default"].oneOfType([PropTypes__default["default"].string, PropTypes__default["default"].element]) | ||
})).isRequired, | ||
id: PropTypes__default["default"].string, | ||
enableImageSelection: PropTypes__default["default"].bool, | ||
onSelectImage: PropTypes__default["default"].func, | ||
rowHeight: PropTypes__default["default"].number, | ||
maxRows: PropTypes__default["default"].number, | ||
margin: PropTypes__default["default"].number, | ||
defaultContainerWidth: PropTypes__default["default"].number, | ||
onClickThumbnail: PropTypes__default["default"].func, | ||
lightboxWillOpen: PropTypes__default["default"].func, | ||
lightboxWillClose: PropTypes__default["default"].func, | ||
enableLightbox: PropTypes__default["default"].bool, | ||
backdropClosesModal: PropTypes__default["default"].bool, | ||
currentImage: PropTypes__default["default"].number, | ||
preloadNextImage: PropTypes__default["default"].bool, | ||
customControls: PropTypes__default["default"].arrayOf(PropTypes__default["default"].node), | ||
currentImageWillChange: PropTypes__default["default"].func, | ||
enableKeyboardInput: PropTypes__default["default"].bool, | ||
imageCountSeparator: PropTypes__default["default"].string, | ||
isOpen: PropTypes__default["default"].bool, | ||
onClickImage: PropTypes__default["default"].func, | ||
onClickNext: PropTypes__default["default"].func, | ||
onClickPrev: PropTypes__default["default"].func, | ||
onClose: PropTypes__default["default"].func, | ||
showCloseButton: PropTypes__default["default"].bool, | ||
showImageCount: PropTypes__default["default"].bool, | ||
lightboxWidth: PropTypes__default["default"].number, | ||
tileViewportStyle: PropTypes__default["default"].func, | ||
thumbnailStyle: PropTypes__default["default"].func, | ||
showLightboxThumbnails: PropTypes__default["default"].bool, | ||
onClickLightboxThumbnail: PropTypes__default["default"].func, | ||
tagStyle: PropTypes__default["default"].object, | ||
thumbnailImageComponent: PropTypes__default["default"].func, | ||
lightBoxProps: PropTypes__default["default"].object | ||
catch (err) { } | ||
setContainerWidth(Math.floor(width)); | ||
}, []); | ||
react.useEffect(() => { | ||
handleResize(); | ||
}, []); | ||
const thumbnails = buildLayoutFlat(images, { | ||
containerWidth, | ||
maxRows, | ||
rowHeight, | ||
margin, | ||
}); | ||
const handleSelect = (index, event) => { | ||
event.preventDefault(); | ||
props.onSelect(index, images[index], event); | ||
}; | ||
const handleClick = (index, event) => { | ||
props.onClick(index, images[index], event); | ||
}; | ||
return (jsxRuntime.jsxs("div", { id: props.id, className: "ReactGridGallery", ref: galleryRef, children: [jsxRuntime.jsx(ResizeListener, { onResize: handleResize }), thumbnails.map((item, index) => (jsxRuntime.jsx(Image, { item: item, index: index, margin: margin, height: rowHeight, isSelectable: enableImageSelection, onClick: handleClick, onSelect: handleSelect, tagStyle: props.tagStyle, tileViewportStyle: props.tileViewportStyle, thumbnailStyle: props.thumbnailStyle, thumbnailImageComponent: props.thumbnailImageComponent }, item.key || index)))] })); | ||
}; | ||
Gallery.displayName = "Gallery"; | ||
Gallery.defaultProps = { | ||
id: "ReactGridGallery", | ||
enableImageSelection: true, | ||
rowHeight: 180, | ||
margin: 2, | ||
defaultContainerWidth: 0, | ||
enableLightbox: true, | ||
backdropClosesModal: false, | ||
currentImage: 0, | ||
preloadNextImage: true, | ||
enableKeyboardInput: true, | ||
imageCountSeparator: ' of ', | ||
isOpen: false, | ||
showCloseButton: true, | ||
showImageCount: true, | ||
lightboxWidth: 1024, | ||
showLightboxThumbnails: false, | ||
lightBoxProps: {} | ||
id: "ReactGridGallery", | ||
enableImageSelection: true, | ||
rowHeight: 180, | ||
margin: 2, | ||
defaultContainerWidth: 0, | ||
onClick: () => { }, | ||
onSelect: () => { }, | ||
}; | ||
module.exports = Gallery; | ||
exports.CheckButton = CheckButton; | ||
exports.Gallery = Gallery; | ||
exports.buildLayout = buildLayout; | ||
exports.buildLayoutFlat = buildLayoutFlat; | ||
//# sourceMappingURL=react-grid-gallery.cjs.js.map |
@@ -1,1030 +0,360 @@ | ||
import PropTypes from 'prop-types'; | ||
import React, { Component } from 'react'; | ||
import Lightbox from 'react-images'; | ||
import { jsx, jsxs } from 'react/jsx-runtime'; | ||
import { useState, useRef, useCallback, useEffect } from 'react'; | ||
function ownKeys(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
var symbols = Object.getOwnPropertySymbols(object); | ||
enumerableOnly && (symbols = symbols.filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
})), keys.push.apply(keys, symbols); | ||
} | ||
return keys; | ||
} | ||
function _objectSpread2(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = null != arguments[i] ? arguments[i] : {}; | ||
i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { | ||
_defineProperty(target, key, source[key]); | ||
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}); | ||
} | ||
return target; | ||
} | ||
function _classCallCheck(instance, Constructor) { | ||
if (!(instance instanceof Constructor)) { | ||
throw new TypeError("Cannot call a class as a function"); | ||
} | ||
} | ||
function _defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
function _createClass(Constructor, protoProps, staticProps) { | ||
if (protoProps) _defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) _defineProperties(Constructor, staticProps); | ||
Object.defineProperty(Constructor, "prototype", { | ||
writable: false | ||
}); | ||
return Constructor; | ||
} | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
function _extends() { | ||
_extends = Object.assign ? Object.assign.bind() : function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
const getStyle = (styleProp, fallback, context) => { | ||
if (typeof styleProp === "function") { | ||
return styleProp(context); | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
function _inherits(subClass, superClass) { | ||
if (typeof superClass !== "function" && superClass !== null) { | ||
throw new TypeError("Super expression must either be null or a function"); | ||
} | ||
subClass.prototype = Object.create(superClass && superClass.prototype, { | ||
constructor: { | ||
value: subClass, | ||
writable: true, | ||
configurable: true | ||
if (typeof styleProp === "object") { | ||
return styleProp; | ||
} | ||
}); | ||
Object.defineProperty(subClass, "prototype", { | ||
writable: false | ||
}); | ||
if (superClass) _setPrototypeOf(subClass, superClass); | ||
} | ||
function _getPrototypeOf(o) { | ||
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { | ||
return o.__proto__ || Object.getPrototypeOf(o); | ||
}; | ||
return _getPrototypeOf(o); | ||
} | ||
function _setPrototypeOf(o, p) { | ||
_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { | ||
o.__proto__ = p; | ||
return o; | ||
}; | ||
return _setPrototypeOf(o, p); | ||
} | ||
function _isNativeReflectConstruct() { | ||
if (typeof Reflect === "undefined" || !Reflect.construct) return false; | ||
if (Reflect.construct.sham) return false; | ||
if (typeof Proxy === "function") return true; | ||
try { | ||
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); | ||
return true; | ||
} catch (e) { | ||
return false; | ||
} | ||
} | ||
function _assertThisInitialized(self) { | ||
if (self === void 0) { | ||
throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); | ||
} | ||
return self; | ||
} | ||
function _possibleConstructorReturn(self, call) { | ||
if (call && (typeof call === "object" || typeof call === "function")) { | ||
return call; | ||
} else if (call !== void 0) { | ||
throw new TypeError("Derived constructors may only return object or undefined"); | ||
} | ||
return _assertThisInitialized(self); | ||
} | ||
function _createSuper(Derived) { | ||
var hasNativeReflectConstruct = _isNativeReflectConstruct(); | ||
return function _createSuperInternal() { | ||
var Super = _getPrototypeOf(Derived), | ||
result; | ||
if (hasNativeReflectConstruct) { | ||
var NewTarget = _getPrototypeOf(this).constructor; | ||
result = Reflect.construct(Super, arguments, NewTarget); | ||
} else { | ||
result = Super.apply(this, arguments); | ||
return fallback(context); | ||
}; | ||
const rotationTransformMap = { | ||
3: "rotate(180deg)", | ||
2: "rotateY(180deg)", | ||
4: "rotate(180deg) rotateY(180deg)", | ||
5: "rotate(270deg) rotateY(180deg)", | ||
6: "rotate(90deg)", | ||
7: "rotate(90deg) rotateY(180deg)", | ||
8: "rotate(270deg)", | ||
}; | ||
const SELECTION_MARGIN = 16; | ||
const thumbnail = ({ item }) => { | ||
const rotationTransformValue = rotationTransformMap[item.orientation]; | ||
const style = { | ||
cursor: "pointer", | ||
maxWidth: "none", | ||
width: item.scaledWidth, | ||
height: item.scaledHeight, | ||
marginLeft: item.marginLeft, | ||
marginTop: 0, | ||
transform: rotationTransformValue, | ||
}; | ||
if (item.isSelected) { | ||
const ratio = item.scaledWidth / item.scaledHeight; | ||
const viewportHeight = item.scaledHeight - SELECTION_MARGIN * 2; | ||
const viewportWidth = item.viewportWidth - SELECTION_MARGIN * 2; | ||
let height, width; | ||
if (item.scaledWidth > item.scaledHeight) { | ||
width = item.scaledWidth - SELECTION_MARGIN * 2; | ||
height = Math.floor(width / ratio); | ||
} | ||
else { | ||
height = item.scaledHeight - SELECTION_MARGIN * 2; | ||
width = Math.floor(height * ratio); | ||
} | ||
const marginTop = Math.abs(Math.floor((viewportHeight - height) / 2)); | ||
const marginLeft = Math.abs(Math.floor((viewportWidth - width) / 2)); | ||
style.width = width; | ||
style.height = height; | ||
style.marginLeft = marginLeft === 0 ? 0 : -marginLeft; | ||
style.marginTop = marginTop === 0 ? 0 : -marginTop; | ||
} | ||
return _possibleConstructorReturn(this, result); | ||
}; | ||
} | ||
var CheckButton = /*#__PURE__*/function (_Component) { | ||
_inherits(CheckButton, _Component); | ||
var _super = _createSuper(CheckButton); | ||
function CheckButton(props) { | ||
var _this; | ||
_classCallCheck(this, CheckButton); | ||
_this = _super.call(this, props); | ||
_this.state = { | ||
hover: _this.props.hover | ||
return style; | ||
}; | ||
const tileViewport = ({ item, }) => { | ||
const styles = { | ||
width: item.viewportWidth, | ||
height: item.scaledHeight, | ||
overflow: "hidden", | ||
}; | ||
_this.fill = _this.fill.bind(_assertThisInitialized(_this)); | ||
_this.visibility = _this.visibility.bind(_assertThisInitialized(_this)); | ||
return _this; | ||
} | ||
_createClass(CheckButton, [{ | ||
key: "fill", | ||
value: function fill() { | ||
if (this.props.isSelected) return this.props.selectedColor;else if (this.state.hover) return this.props.hoverColor; | ||
return this.props.color; | ||
if (item.nano) { | ||
styles.background = `url(${item.nano})`; | ||
styles.backgroundSize = "cover"; | ||
styles.backgroundPosition = "center center"; | ||
} | ||
}, { | ||
key: "visibility", | ||
value: function visibility() { | ||
if (this.props.isSelected || this.props.isSelectable && this.props.parentHover) return 'visible'; | ||
return 'hidden'; | ||
if (item.isSelected) { | ||
styles.width = item.viewportWidth - SELECTION_MARGIN * 2; | ||
styles.height = item.scaledHeight - SELECTION_MARGIN * 2; | ||
styles.margin = SELECTION_MARGIN; | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var _this2 = this; | ||
return styles; | ||
}; | ||
const customOverlay = ({ hover, }) => ({ | ||
pointerEvents: "none", | ||
opacity: hover ? 1 : 0, | ||
position: "absolute", | ||
height: "100%", | ||
width: "100%", | ||
}); | ||
const galleryItem = ({ margin }) => ({ | ||
margin, | ||
WebkitUserSelect: "none", | ||
position: "relative", | ||
float: "left", | ||
background: "#eee", | ||
padding: "0px", | ||
}); | ||
const tileOverlay = ({ showOverlay, }) => ({ | ||
pointerEvents: "none", | ||
opacity: 1, | ||
position: "absolute", | ||
height: "100%", | ||
width: "100%", | ||
background: showOverlay | ||
? "linear-gradient(to bottom,rgba(0,0,0,0.26),transparent 56px,transparent)" | ||
: "none", | ||
}); | ||
const tileIconBar = { | ||
pointerEvents: "none", | ||
opacity: 1, | ||
position: "absolute", | ||
height: "36px", | ||
width: "100%", | ||
}; | ||
const tileDescription = { | ||
background: "white", | ||
height: "100%", | ||
width: "100%", | ||
margin: 0, | ||
userSelect: "text", | ||
WebkitUserSelect: "text", | ||
MozUserSelect: "text", | ||
overflow: "hidden", | ||
}; | ||
const bottomBar = { | ||
padding: "2px", | ||
pointerEvents: "none", | ||
position: "absolute", | ||
minHeight: "0px", | ||
maxHeight: "160px", | ||
width: "100%", | ||
bottom: "0px", | ||
overflow: "hidden", | ||
}; | ||
const tagItemBlock = { | ||
display: "inline-block", | ||
cursor: "pointer", | ||
pointerEvents: "visible", | ||
margin: "2px", | ||
}; | ||
const tagItem = () => ({ | ||
display: "inline", | ||
padding: ".2em .6em .3em", | ||
fontSize: "75%", | ||
fontWeight: "600", | ||
lineHeight: "1", | ||
color: "yellow", | ||
background: "rgba(0,0,0,0.65)", | ||
textAlign: "center", | ||
whiteSpace: "nowrap", | ||
verticalAlign: "baseline", | ||
borderRadius: ".25em", | ||
}); | ||
const checkButton = ({ isVisible, }) => ({ | ||
visibility: isVisible ? "visible" : "hidden", | ||
background: "none", | ||
float: "left", | ||
width: 36, | ||
height: 36, | ||
border: "none", | ||
padding: 6, | ||
cursor: "pointer", | ||
pointerEvents: "visible", | ||
}); | ||
var circleStyle = { | ||
display: this.props.isSelected ? "block" : "none" | ||
}; | ||
return /*#__PURE__*/React.createElement("div", { | ||
"data-testid": "grid-gallery-item_check-button", | ||
title: "Select", | ||
style: { | ||
visibility: this.visibility(), | ||
background: 'none', | ||
"float": 'left', | ||
width: '36px', | ||
height: '36px', | ||
border: 'none', | ||
padding: '6px', | ||
cursor: 'pointer', | ||
pointerEvents: 'visible' | ||
}, | ||
onClick: this.props.onClick ? function (e) { | ||
return _this2.props.onClick(_this2.props.index, e); | ||
} : null, | ||
onMouseOver: function onMouseOver(e) { | ||
return _this2.setState({ | ||
hover: true | ||
}); | ||
}, | ||
onMouseOut: function onMouseOut(e) { | ||
return _this2.setState({ | ||
hover: false | ||
}); | ||
} | ||
}, /*#__PURE__*/React.createElement("svg", { | ||
fill: this.fill(), | ||
height: "24", | ||
viewBox: "0 0 24 24", | ||
width: "24", | ||
xmlns: "http://www.w3.org/2000/svg" | ||
}, /*#__PURE__*/React.createElement("radialGradient", { | ||
id: "shadow", | ||
cx: "38", | ||
cy: "95.488", | ||
r: "10.488", | ||
gradientTransform: "matrix(1 0 0 -1 -26 109)", | ||
gradientUnits: "userSpaceOnUse" | ||
}, /*#__PURE__*/React.createElement("stop", { | ||
offset: ".832", | ||
stopColor: "#010101" | ||
}), /*#__PURE__*/React.createElement("stop", { | ||
offset: "1", | ||
stopColor: "#010101", | ||
stopOpacity: "0" | ||
})), /*#__PURE__*/React.createElement("circle", { | ||
style: circleStyle, | ||
opacity: ".26", | ||
fill: "url(#shadow)", | ||
cx: "12", | ||
cy: "13.512", | ||
r: "10.488" | ||
}), /*#__PURE__*/React.createElement("circle", { | ||
style: circleStyle, | ||
fill: "#FFF", | ||
cx: "12", | ||
cy: "12.2", | ||
r: "8.292" | ||
}), /*#__PURE__*/React.createElement("path", { | ||
d: "M0 0h24v24H0z", | ||
fill: "none" | ||
}), /*#__PURE__*/React.createElement("path", { | ||
d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" | ||
}))); | ||
} | ||
}]); | ||
return CheckButton; | ||
}(Component); | ||
CheckButton.propTypes = { | ||
index: PropTypes.number, | ||
color: PropTypes.string, | ||
isSelectable: PropTypes.bool, | ||
isSelected: PropTypes.bool, | ||
selectedColor: PropTypes.string, | ||
parentHover: PropTypes.bool, | ||
hover: PropTypes.bool, | ||
hoverColor: PropTypes.string, | ||
onClick: PropTypes.func | ||
const CheckButton = (props) => { | ||
const { isSelected, isVisible, onClick } = props; | ||
const { selectedColor, hoverColor, color } = props; | ||
const [hover, setHover] = useState(false); | ||
const circleStyle = { display: isSelected ? "block" : "none" }; | ||
const fillColor = isSelected ? selectedColor : hover ? hoverColor : color; | ||
const handleMouseOver = () => setHover(true); | ||
const handleMouseOut = () => setHover(false); | ||
return (jsx("div", { "data-testid": "grid-gallery-item_check-button", title: "Select", style: checkButton({ isVisible }), onClick: onClick, onMouseOver: handleMouseOver, onMouseOut: handleMouseOut, children: jsxs("svg", { fill: fillColor, height: "24", viewBox: "0 0 24 24", width: "24", xmlns: "http://www.w3.org/2000/svg", children: [jsxs("radialGradient", { id: "shadow", cx: "38", cy: "95.488", r: "10.488", gradientTransform: "matrix(1 0 0 -1 -26 109)", gradientUnits: "userSpaceOnUse", children: [jsx("stop", { offset: ".832", stopColor: "#010101" }), jsx("stop", { offset: "1", stopColor: "#010101", stopOpacity: "0" })] }), jsx("circle", { style: circleStyle, opacity: ".26", fill: "url(#shadow)", cx: "12", cy: "13.512", r: "10.488" }), jsx("circle", { style: circleStyle, fill: "#FFF", cx: "12", cy: "12.2", r: "8.292" }), jsx("path", { d: "M0 0h24v24H0z", fill: "none" }), jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" })] }) })); | ||
}; | ||
CheckButton.defaultProps = { | ||
isSelectable: true, | ||
isSelected: false, | ||
parentHover: false, | ||
hover: false | ||
isSelected: false, | ||
isVisible: true, | ||
color: "#FFFFFFB2", | ||
selectedColor: "#4285F4FF", | ||
hoverColor: "#FFFFFFFF", | ||
}; | ||
var Image = /*#__PURE__*/function (_Component) { | ||
_inherits(Image, _Component); | ||
var _super = _createSuper(Image); | ||
function Image(props) { | ||
var _this; | ||
_classCallCheck(this, Image); | ||
_this = _super.call(this, props); | ||
_this.state = { | ||
hover: false | ||
const Image = (props) => { | ||
const { item, thumbnailImageComponent: ThumbnailImageComponent } = props; | ||
const styleContext = { item }; | ||
const [hover, setHover] = useState(false); | ||
const thumbnailProps = { | ||
key: props.index, | ||
"data-testid": "grid-gallery-item_thumbnail", | ||
src: item.src, | ||
alt: item.alt ? item.alt : "", | ||
title: typeof item.caption === "string" ? item.caption : null, | ||
style: getStyle(props.thumbnailStyle, thumbnail, styleContext), | ||
}; | ||
return _this; | ||
} | ||
_createClass(Image, [{ | ||
key: "tagStyle", | ||
value: function tagStyle() { | ||
if (this.props.tagStyle) return this.props.tagStyle; | ||
return { | ||
display: "inline", | ||
padding: ".2em .6em .3em", | ||
fontSize: "75%", | ||
fontWeight: "600", | ||
lineHeight: "1", | ||
color: "yellow", | ||
background: "rgba(0,0,0,0.65)", | ||
textAlign: "center", | ||
whiteSpace: "nowrap", | ||
verticalAlign: "baseline", | ||
borderRadius: ".25em" | ||
}; | ||
} | ||
}, { | ||
key: "tileViewportStyle", | ||
value: function tileViewportStyle() { | ||
if (this.props.tileViewportStyle) return this.props.tileViewportStyle.call(this); | ||
var nanoBase64Backgorund = {}; | ||
if (this.props.item.nano) { | ||
nanoBase64Backgorund = { | ||
background: "url(".concat(this.props.item.nano, ")"), | ||
backgroundSize: 'cover', | ||
backgroundPosition: 'center center' | ||
}; | ||
} | ||
if (this.props.item.isSelected) return Object.assign({ | ||
width: this.props.item.vwidth - 32, | ||
height: this.props.height - 32, | ||
margin: 16, | ||
overflow: "hidden" | ||
}, nanoBase64Backgorund); | ||
return Object.assign({ | ||
width: this.props.item.vwidth, | ||
height: this.props.height, | ||
overflow: "hidden" | ||
}, nanoBase64Backgorund); | ||
} | ||
}, { | ||
key: "thumbnailStyle", | ||
value: function thumbnailStyle() { | ||
if (this.props.thumbnailStyle) return this.props.thumbnailStyle.call(this); | ||
var rotationTransformValue = undefined; | ||
switch (this.props.item.orientation) { | ||
case 3: | ||
rotationTransformValue = "rotate(180deg)"; | ||
break; | ||
case 6: | ||
rotationTransformValue = "rotate(90deg)"; | ||
break; | ||
case 8: | ||
rotationTransformValue = "rotate(270deg)"; | ||
break; | ||
case 2: | ||
rotationTransformValue = "rotateY(180deg)"; | ||
break; | ||
case 4: | ||
rotationTransformValue = "rotate(180deg) rotateY(180deg)"; | ||
break; | ||
case 5: | ||
rotationTransformValue = "rotate(270deg) rotateY(180deg)"; | ||
break; | ||
case 7: | ||
rotationTransformValue = "rotate(90deg) rotateY(180deg)"; | ||
break; | ||
} | ||
if (this.props.item.isSelected) { | ||
var ratio = this.props.item.scaletwidth / this.props.height; | ||
var height = 0; | ||
var width = 0; | ||
var viewportHeight = this.props.height - 32; | ||
var viewportWidth = this.props.item.vwidth - 32; | ||
if (this.props.item.scaletwidth > this.props.height) { | ||
width = this.props.item.scaletwidth - 32; | ||
height = Math.floor(width / ratio); | ||
} else { | ||
height = this.props.height - 32; | ||
width = Math.floor(height * ratio); | ||
const handleCheckButtonClick = (event) => { | ||
if (!props.isSelectable) { | ||
return; | ||
} | ||
var marginTop = -Math.abs(Math.floor((viewportHeight - height) / 2)); | ||
var marginLeft = -Math.abs(Math.floor((viewportWidth - width) / 2)); | ||
return { | ||
cursor: 'pointer', | ||
width: width, | ||
height: height, | ||
marginLeft: marginLeft, | ||
marginTop: marginTop, | ||
transform: rotationTransformValue | ||
}; | ||
} | ||
return { | ||
cursor: 'pointer', | ||
width: this.props.item.scaletwidth, | ||
height: this.props.height, | ||
marginLeft: this.props.item.marginLeft, | ||
marginTop: 0, | ||
transform: rotationTransformValue | ||
}; | ||
} | ||
}, { | ||
key: "renderCheckButton", | ||
value: function renderCheckButton() { | ||
return /*#__PURE__*/React.createElement(CheckButton, { | ||
key: "Select", | ||
index: this.props.index, | ||
color: "rgba(255, 255, 255, 0.7)", | ||
selectedColor: "#4285f4", | ||
hoverColor: "rgba(255, 255, 255, 1)", | ||
isSelected: this.props.item.isSelected, | ||
isSelectable: this.props.isSelectable, | ||
onClick: this.props.isSelectable ? this.props.onSelectImage : null, | ||
parentHover: this.state.hover | ||
}); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var _this2 = this; | ||
var alt = this.props.item.alt ? this.props.item.alt : ""; | ||
var tags = typeof this.props.item.tags === 'undefined' ? /*#__PURE__*/React.createElement("noscript", null) : this.props.item.tags.map(function (tag) { | ||
var key = tag.key || (typeof tag.value === 'string' ? tag.value : null) || tag.title; | ||
return /*#__PURE__*/React.createElement("div", { | ||
title: tag.title, | ||
key: "tag-" + key, | ||
style: { | ||
display: "inline-block", | ||
cursor: 'pointer', | ||
pointerEvents: 'visible', | ||
margin: "2px" | ||
} | ||
}, /*#__PURE__*/React.createElement("span", { | ||
style: _this2.tagStyle() | ||
}, tag.value)); | ||
}); | ||
var customOverlay = typeof this.props.item.customOverlay === 'undefined' ? /*#__PURE__*/React.createElement("noscript", null) : /*#__PURE__*/React.createElement("div", { | ||
className: "ReactGridGallery_custom-overlay", | ||
key: "custom-overlay-" + this.props.index, | ||
style: { | ||
pointerEvents: "none", | ||
opacity: this.state.hover ? 1 : 0, | ||
position: "absolute", | ||
height: "100%", | ||
width: "100%" | ||
} | ||
}, this.props.item.customOverlay); | ||
var thumbnailProps = { | ||
key: "img-" + this.props.index, | ||
src: this.props.item.thumbnail, | ||
alt: alt, | ||
title: typeof this.props.item.caption === 'string' ? this.props.item.caption : null, | ||
style: this.thumbnailStyle(), | ||
'data-testid': "grid-gallery-item_thumbnail" | ||
}; | ||
var ThumbnailImageComponent = this.props.thumbnailImageComponent; | ||
return /*#__PURE__*/React.createElement("div", { | ||
className: "ReactGridGallery_tile", | ||
"data-testid": "grid-gallery-item", | ||
key: "tile-" + this.props.index, | ||
onMouseEnter: function onMouseEnter(e) { | ||
return _this2.setState({ | ||
hover: true | ||
}); | ||
}, | ||
onMouseLeave: function onMouseLeave(e) { | ||
return _this2.setState({ | ||
hover: false | ||
}); | ||
}, | ||
style: { | ||
margin: this.props.margin, | ||
WebkitUserSelect: "none", | ||
position: "relative", | ||
"float": "left", | ||
background: "#eee", | ||
padding: "0px" | ||
} | ||
}, /*#__PURE__*/React.createElement("div", { | ||
className: "ReactGridGallery_tile-icon-bar", | ||
key: "tile-icon-bar-" + this.props.index, | ||
style: { | ||
pointerEvents: "none", | ||
opacity: 1, | ||
position: "absolute", | ||
height: "36px", | ||
width: "100%" | ||
} | ||
}, this.renderCheckButton()), /*#__PURE__*/React.createElement("div", { | ||
className: "ReactGridGallery_tile-bottom-bar", | ||
key: "tile-bottom-bar-" + this.props.index, | ||
style: { | ||
padding: "2px", | ||
pointerEvents: "none", | ||
position: "absolute", | ||
minHeight: "0px", | ||
maxHeight: "160px", | ||
width: "100%", | ||
bottom: "0px", | ||
overflow: "hidden" | ||
} | ||
}, tags), customOverlay, /*#__PURE__*/React.createElement("div", { | ||
className: "ReactGridGallery_tile-overlay", | ||
key: "tile-overlay-" + this.props.index, | ||
style: { | ||
pointerEvents: "none", | ||
opacity: 1, | ||
position: "absolute", | ||
height: "100%", | ||
width: "100%", | ||
background: this.state.hover && !this.props.item.isSelected && this.props.isSelectable ? 'linear-gradient(to bottom,rgba(0,0,0,0.26),transparent 56px,transparent)' : 'none' | ||
} | ||
}), /*#__PURE__*/React.createElement("div", { | ||
className: "ReactGridGallery_tile-viewport", | ||
"data-testid": "grid-gallery-item_viewport", | ||
style: this.tileViewportStyle(), | ||
key: "tile-viewport-" + this.props.index, | ||
onClick: this.props.onClick ? function (e) { | ||
return _this2.props.onClick.call(_this2, _this2.props.index, e); | ||
} : null | ||
}, ThumbnailImageComponent ? /*#__PURE__*/React.createElement(ThumbnailImageComponent, _extends({}, this.props, { | ||
imageProps: thumbnailProps | ||
})) : /*#__PURE__*/React.createElement("img", thumbnailProps)), this.props.item.thumbnailCaption && /*#__PURE__*/React.createElement("div", { | ||
className: "ReactGridGallery_tile-description", | ||
style: { | ||
background: "white", | ||
height: "100%", | ||
width: "100%", | ||
margin: 0, | ||
userSelect: "text", | ||
WebkitUserSelect: "text", | ||
MozUserSelect: "text", | ||
overflow: "hidden" | ||
} | ||
}, this.props.item.thumbnailCaption)); | ||
} | ||
}]); | ||
return Image; | ||
}(Component); | ||
Image.propTypes = { | ||
item: PropTypes.object, | ||
index: PropTypes.number, | ||
margin: PropTypes.number, | ||
height: PropTypes.number, | ||
isSelectable: PropTypes.bool, | ||
onClick: PropTypes.func, | ||
onSelectImage: PropTypes.func, | ||
tileViewportStyle: PropTypes.func, | ||
thumbnailStyle: PropTypes.func, | ||
tagStyle: PropTypes.object, | ||
customOverlay: PropTypes.element, | ||
thumbnailImageComponent: PropTypes.func | ||
props.onSelect(props.index, event); | ||
}; | ||
const handleViewportClick = (event) => { | ||
props.onClick(props.index, event); | ||
}; | ||
return (jsxs("div", { className: "ReactGridGallery_tile", "data-testid": "grid-gallery-item", onMouseEnter: () => setHover(true), onMouseLeave: () => setHover(false), style: galleryItem({ margin: props.margin }), children: [jsx("div", { className: "ReactGridGallery_tile-icon-bar", style: tileIconBar, children: jsx(CheckButton, { isSelected: item.isSelected, isVisible: item.isSelected || (props.isSelectable && hover), onClick: handleCheckButtonClick }) }), !!item.tags && (jsx("div", { className: "ReactGridGallery_tile-bottom-bar", style: bottomBar, children: item.tags.map((tag, index) => (jsx("div", { title: tag.title, style: tagItemBlock, children: jsx("span", { style: getStyle(props.tagStyle, tagItem, styleContext), children: tag.value }) }, tag.key || index))) })), !!item.customOverlay && (jsx("div", { className: "ReactGridGallery_custom-overlay", style: customOverlay({ hover }), children: item.customOverlay })), jsx("div", { className: "ReactGridGallery_tile-overlay", style: tileOverlay({ | ||
showOverlay: hover && !item.isSelected && props.isSelectable, | ||
}) }), jsx("div", { className: "ReactGridGallery_tile-viewport", "data-testid": "grid-gallery-item_viewport", style: getStyle(props.tileViewportStyle, tileViewport, styleContext), onClick: handleViewportClick, children: ThumbnailImageComponent ? (jsx(ThumbnailImageComponent, { ...props, imageProps: thumbnailProps })) : (jsx("img", { ...thumbnailProps })) }), item.thumbnailCaption && (jsx("div", { className: "ReactGridGallery_tile-description", style: tileDescription, children: item.thumbnailCaption }))] })); | ||
}; | ||
Image.defaultProps = { | ||
isSelectable: true, | ||
hover: false | ||
isSelectable: true, | ||
}; | ||
var calculateCutOff = function calculateCutOff(len, delta, items) { | ||
var cutoff = []; | ||
var cutsum = 0; | ||
for (var i in items) { | ||
var item = items[i]; | ||
var fractOfLen = item.scaletwidth / len; | ||
cutoff[i] = Math.floor(fractOfLen * delta); | ||
cutsum += cutoff[i]; | ||
} | ||
var stillToCutOff = delta - cutsum; | ||
while (stillToCutOff > 0) { | ||
for (i in cutoff) { | ||
cutoff[i]++; | ||
stillToCutOff--; | ||
if (stillToCutOff < 0) break; | ||
} | ||
} | ||
return cutoff; | ||
const objectStyles = { | ||
position: "absolute", | ||
top: 0, | ||
left: 0, | ||
height: "100%", | ||
width: "100%", | ||
pointerEvents: "none", | ||
zIndex: -1, | ||
opacity: 0, | ||
}; | ||
const ResizeListener = ({ onResize, }) => { | ||
const objectRef = useRef(null); | ||
const onResizeRef = useRef(onResize); | ||
onResizeRef.current = onResize; | ||
const _onResize = useCallback(() => { | ||
onResizeRef.current(); | ||
}, []); | ||
const handleLoad = useCallback(() => { | ||
const obj = objectRef.current; | ||
if (obj && obj.contentDocument && obj.contentDocument.defaultView) { | ||
obj.contentDocument.defaultView.addEventListener("resize", _onResize); | ||
} | ||
}, []); | ||
useEffect(() => { | ||
return () => { | ||
const obj = objectRef.current; | ||
if (obj && obj.contentDocument && obj.contentDocument.defaultView) { | ||
obj.contentDocument.defaultView.removeEventListener("resize", _onResize); | ||
} | ||
}; | ||
}, []); | ||
return (jsx("object", { onLoad: handleLoad, ref: objectRef, tabIndex: -1, type: "text/html", data: "about:blank", title: "", style: objectStyles })); | ||
}; | ||
var buildImageRow = function buildImageRow(data, _ref) { | ||
var containerWidth = _ref.containerWidth, | ||
margin = _ref.margin; | ||
var row = []; | ||
var len = 0; | ||
var imgMargin = 2 * margin; | ||
while (data.items.length > 0 && len < containerWidth) { | ||
var item = data.items.shift(); | ||
row.push(item); | ||
len += item.scaletwidth + imgMargin; | ||
} | ||
var delta = len - containerWidth; | ||
if (row.length > 0 && delta > 0) { | ||
var cutoff = calculateCutOff(len, delta, row); | ||
for (var i in row) { | ||
var pixelsToRemove = cutoff[i]; | ||
item = row[i]; | ||
item.marginLeft = -Math.abs(Math.floor(pixelsToRemove / 2)); | ||
item.vwidth = item.scaletwidth - pixelsToRemove; | ||
const calculateCutOff = (items, totalRowWidth, protrudingWidth) => { | ||
const cutOff = []; | ||
let cutSum = 0; | ||
for (let i in items) { | ||
const item = items[i]; | ||
const fractionOfWidth = item.scaledWidth / totalRowWidth; | ||
cutOff[i] = Math.floor(fractionOfWidth * protrudingWidth); | ||
cutSum += cutOff[i]; | ||
} | ||
} else { | ||
for (var j in row) { | ||
item = row[j]; | ||
item.marginLeft = 0; | ||
item.vwidth = item.scaletwidth; | ||
let stillToCutOff = protrudingWidth - cutSum; | ||
while (stillToCutOff > 0) { | ||
for (let i in cutOff) { | ||
cutOff[i]++; | ||
stillToCutOff--; | ||
if (stillToCutOff < 0) | ||
break; | ||
} | ||
} | ||
} | ||
return row; | ||
return cutOff; | ||
}; | ||
var renderThumbs = function renderThumbs(images, _ref2) { | ||
var containerWidth = _ref2.containerWidth, | ||
maxRows = _ref2.maxRows, | ||
rowHeight = _ref2.rowHeight, | ||
margin = _ref2.margin; | ||
rowHeight = typeof rowHeight === "undefined" ? 180 : rowHeight; | ||
margin = typeof margin === "undefined" ? 2 : margin; | ||
if (!images) return []; | ||
if (!containerWidth) return []; | ||
var items = images.slice(); | ||
items = items.map(function (item) { | ||
return _objectSpread2(_objectSpread2({}, item), {}, { | ||
scaletwidth: Math.floor(rowHeight * (item.thumbnailWidth / item.thumbnailHeight)) | ||
}); | ||
}); | ||
var data = { | ||
items: items | ||
}; | ||
var thumbs = []; | ||
var rows = []; | ||
while (data.items.length > 0) { | ||
rows.push(buildImageRow(data, { | ||
containerWidth: containerWidth, | ||
margin: margin | ||
})); | ||
} | ||
for (var r in rows) { | ||
for (var i in rows[r]) { | ||
var item = _objectSpread2(_objectSpread2({}, rows[r][i]), {}, { | ||
rowIndex: parseInt(r) | ||
}); | ||
if (maxRows) { | ||
if (r < maxRows) { | ||
thumbs.push(item); | ||
const getRow = (images, { containerWidth, rowHeight, margin }) => { | ||
const row = []; | ||
const imgMargin = 2 * margin; | ||
const items = [...images]; | ||
let totalRowWidth = 0; | ||
while (items.length > 0 && totalRowWidth < containerWidth) { | ||
const item = items.shift(); | ||
const scaledWidth = Math.floor(rowHeight * (item.width / item.height)); | ||
const extendedItem = { | ||
...item, | ||
scaledHeight: rowHeight, | ||
scaledWidth, | ||
viewportWidth: scaledWidth, | ||
marginLeft: 0, | ||
}; | ||
row.push(extendedItem); | ||
totalRowWidth += extendedItem.scaledWidth + imgMargin; | ||
} | ||
const protrudingWidth = totalRowWidth - containerWidth; | ||
if (row.length > 0 && protrudingWidth > 0) { | ||
const cutoff = calculateCutOff(row, totalRowWidth, protrudingWidth); | ||
for (const i in row) { | ||
const pixelsToRemove = cutoff[i]; | ||
const item = row[i]; | ||
item.marginLeft = -Math.abs(Math.floor(pixelsToRemove / 2)); | ||
item.viewportWidth = item.scaledWidth - pixelsToRemove; | ||
} | ||
} else { | ||
thumbs.push(item); | ||
} | ||
} | ||
} | ||
return thumbs; | ||
return [row, items]; | ||
}; | ||
var Gallery = /*#__PURE__*/function (_Component) { | ||
_inherits(Gallery, _Component); | ||
var _super = _createSuper(Gallery); | ||
function Gallery(props) { | ||
var _this; | ||
_classCallCheck(this, Gallery); | ||
_this = _super.call(this, props); | ||
_this.state = { | ||
lightboxIsOpen: _this.props.isOpen, | ||
currentImage: _this.props.currentImage, | ||
containerWidth: _this.props.defaultContainerWidth | ||
}; | ||
_this.onResize = _this.onResize.bind(_assertThisInitialized(_this)); | ||
_this.closeLightbox = _this.closeLightbox.bind(_assertThisInitialized(_this)); | ||
_this.gotoImage = _this.gotoImage.bind(_assertThisInitialized(_this)); | ||
_this.gotoNext = _this.gotoNext.bind(_assertThisInitialized(_this)); | ||
_this.gotoPrevious = _this.gotoPrevious.bind(_assertThisInitialized(_this)); | ||
_this.onClickImage = _this.onClickImage.bind(_assertThisInitialized(_this)); | ||
_this.openLightbox = _this.openLightbox.bind(_assertThisInitialized(_this)); | ||
_this.onSelectImage = _this.onSelectImage.bind(_assertThisInitialized(_this)); | ||
return _this; | ||
} | ||
_createClass(Gallery, [{ | ||
key: "componentDidMount", | ||
value: function componentDidMount() { | ||
this.onResize(); | ||
const getRows = (images, options, rows = []) => { | ||
const [row, imagesLeft] = getRow(images, options); | ||
const nextRows = [...rows, row]; | ||
if (options.maxRows && nextRows.length >= options.maxRows) { | ||
return nextRows; | ||
} | ||
}, { | ||
key: "componentDidUpdate", | ||
value: function componentDidUpdate() { | ||
if (!this._gallery) return; | ||
if (this.getContainerWidth() !== this.state.containerWidth) { | ||
this.onResize(); | ||
} | ||
if (imagesLeft.length) { | ||
return getRows(imagesLeft, options, nextRows); | ||
} | ||
}, { | ||
key: "onResize", | ||
value: function onResize() { | ||
if (!this._gallery) return; | ||
var containerWidth = this.getContainerWidth(); | ||
this.setState({ | ||
containerWidth: containerWidth | ||
}); | ||
} | ||
}, { | ||
key: "getContainerWidth", | ||
value: function getContainerWidth() { | ||
var width = this._gallery.clientWidth; | ||
return nextRows; | ||
}; | ||
const buildLayout = (images, { containerWidth, maxRows, rowHeight, margin }) => { | ||
rowHeight = typeof rowHeight === "undefined" ? 180 : rowHeight; | ||
margin = typeof margin === "undefined" ? 2 : margin; | ||
if (!images) | ||
return []; | ||
if (!containerWidth) | ||
return []; | ||
const options = { containerWidth, maxRows, rowHeight, margin }; | ||
return getRows(images, options); | ||
}; | ||
const buildLayoutFlat = (images, options) => { | ||
const rows = buildLayout(images, options); | ||
return [].concat.apply([], rows); | ||
}; | ||
try { | ||
width = this._gallery.getBoundingClientRect().width; | ||
} catch (err) {} | ||
return Math.floor(width); | ||
} | ||
}, { | ||
key: "getCurrentImageIndex", | ||
value: function getCurrentImageIndex() { | ||
return Math.min(this.state.currentImage, this.props.images.length - 1); | ||
} | ||
}, { | ||
key: "openLightbox", | ||
value: function openLightbox(index, event) { | ||
if (event) { | ||
event.preventDefault(); | ||
} | ||
if (this.props.lightboxWillOpen) { | ||
this.props.lightboxWillOpen.call(this, index); | ||
} | ||
if (this.props.currentImageWillChange) { | ||
this.props.currentImageWillChange.call(this, index); | ||
} | ||
this.setState({ | ||
currentImage: index, | ||
lightboxIsOpen: true | ||
}); | ||
} | ||
}, { | ||
key: "closeLightbox", | ||
value: function closeLightbox() { | ||
if (this.props.lightboxWillClose) { | ||
this.props.lightboxWillClose.call(this); | ||
} | ||
if (this.props.currentImageWillChange) { | ||
this.props.currentImageWillChange.call(this, 0); | ||
} | ||
this.setState({ | ||
currentImage: 0, | ||
lightboxIsOpen: false | ||
}); | ||
} | ||
}, { | ||
key: "gotoPrevious", | ||
value: function gotoPrevious() { | ||
if (this.props.currentImageWillChange) { | ||
this.props.currentImageWillChange.call(this, this.getCurrentImageIndex() - 1); | ||
} | ||
this.setState({ | ||
currentImage: this.getCurrentImageIndex() - 1 | ||
}); | ||
} | ||
}, { | ||
key: "gotoNext", | ||
value: function gotoNext() { | ||
if (this.props.currentImageWillChange) { | ||
this.props.currentImageWillChange.call(this, this.getCurrentImageIndex() + 1); | ||
} | ||
this.setState({ | ||
currentImage: this.getCurrentImageIndex() + 1 | ||
}); | ||
} | ||
}, { | ||
key: "onClickImage", | ||
value: function onClickImage() { | ||
if (this.state.currentImage === this.props.images.length - 1) return; | ||
this.gotoNext(); | ||
} | ||
}, { | ||
key: "onSelectImage", | ||
value: function onSelectImage(index, event) { | ||
event.preventDefault(); | ||
if (this.props.onSelectImage) this.props.onSelectImage.call(this, index, this.props.images[index]); | ||
} | ||
}, { | ||
key: "gotoImage", | ||
value: function gotoImage(index) { | ||
if (this.props.currentImageWillChange) { | ||
this.props.currentImageWillChange.call(this, index); | ||
} | ||
this.setState({ | ||
currentImage: index | ||
}); | ||
} | ||
}, { | ||
key: "getOnClickThumbnailFn", | ||
value: function getOnClickThumbnailFn() { | ||
if (!this.props.onClickThumbnail && this.props.enableLightbox) return this.openLightbox; | ||
if (this.props.onClickThumbnail) return this.props.onClickThumbnail; | ||
return null; | ||
} | ||
}, { | ||
key: "getOnClickLightboxThumbnailFn", | ||
value: function getOnClickLightboxThumbnailFn() { | ||
if (!this.props.onClickLightboxThumbnail && this.props.showLightboxThumbnails) return this.gotoImage; | ||
if (this.props.onClickLightboxThumbnail && this.props.showLightboxThumbnails) return this.props.onClickLightboxThumbnail; | ||
return null; | ||
} | ||
}, { | ||
key: "getOnClickImageFn", | ||
value: function getOnClickImageFn() { | ||
if (this.props.onClickImage) return this.props.onClickImage; | ||
return this.onClickImage; | ||
} | ||
}, { | ||
key: "getOnClickPrevFn", | ||
value: function getOnClickPrevFn() { | ||
if (this.props.onClickPrev) return this.props.onClickPrev; | ||
return this.gotoPrevious; | ||
} | ||
}, { | ||
key: "getOnClickNextFn", | ||
value: function getOnClickNextFn() { | ||
if (this.props.onClickNext) return this.props.onClickNext; | ||
return this.gotoNext; | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var _this2 = this; | ||
var _this$props = this.props, | ||
maxRows = _this$props.maxRows, | ||
rowHeight = _this$props.rowHeight, | ||
margin = _this$props.margin; | ||
var containerWidth = this.state.containerWidth; | ||
var thumbnails = renderThumbs(this.props.images, { | ||
containerWidth: containerWidth, | ||
maxRows: maxRows, | ||
rowHeight: rowHeight, | ||
margin: margin | ||
}); | ||
var images = thumbnails.map(function (item, idx) { | ||
return /*#__PURE__*/React.createElement(Image, { | ||
key: "Image-" + idx + "-" + item.src, | ||
item: item, | ||
index: idx, | ||
margin: _this2.props.margin, | ||
height: _this2.props.rowHeight, | ||
isSelectable: _this2.props.enableImageSelection, | ||
onClick: _this2.getOnClickThumbnailFn(), | ||
onSelectImage: _this2.onSelectImage, | ||
tagStyle: _this2.props.tagStyle, | ||
tileViewportStyle: _this2.props.tileViewportStyle, | ||
thumbnailStyle: _this2.props.thumbnailStyle, | ||
thumbnailImageComponent: _this2.props.thumbnailImageComponent | ||
}); | ||
}); | ||
var resizeIframeStyles = { | ||
height: 0, | ||
margin: 0, | ||
padding: 0, | ||
overflow: "hidden", | ||
borderWidth: 0, | ||
position: "fixed", | ||
backgroundColor: "transparent", | ||
width: "100%" | ||
}; | ||
return /*#__PURE__*/React.createElement("div", { | ||
id: this.props.id, | ||
className: "ReactGridGallery", | ||
ref: function ref(c) { | ||
return _this2._gallery = c; | ||
const Gallery = (props) => { | ||
const galleryRef = useRef(null); | ||
const { maxRows, rowHeight, margin, enableImageSelection } = props; | ||
const { defaultContainerWidth, images } = props; | ||
const [containerWidth, setContainerWidth] = useState(defaultContainerWidth); | ||
const handleResize = useCallback(() => { | ||
if (!galleryRef.current) { | ||
return; | ||
} | ||
}, /*#__PURE__*/React.createElement("iframe", { | ||
style: resizeIframeStyles, | ||
ref: function ref(c) { | ||
return c && c.contentWindow && c.contentWindow.addEventListener('resize', _this2.onResize); | ||
let width = galleryRef.current.clientWidth; | ||
try { | ||
width = galleryRef.current.getBoundingClientRect().width; | ||
} | ||
}), images, /*#__PURE__*/React.createElement(Lightbox, _extends({ | ||
images: this.props.images, | ||
backdropClosesModal: this.props.backdropClosesModal, | ||
currentImage: this.getCurrentImageIndex(), | ||
preloadNextImage: this.props.preloadNextImage, | ||
customControls: this.props.customControls, | ||
enableKeyboardInput: this.props.enableKeyboardInput, | ||
imageCountSeparator: this.props.imageCountSeparator, | ||
isOpen: this.state.lightboxIsOpen, | ||
onClickImage: this.getOnClickImageFn(), | ||
onClickNext: this.getOnClickNextFn(), | ||
onClickPrev: this.getOnClickPrevFn(), | ||
showCloseButton: this.props.showCloseButton, | ||
showImageCount: this.props.showImageCount, | ||
onClose: this.closeLightbox, | ||
width: this.props.lightboxWidth, | ||
theme: this.props.theme, | ||
onClickThumbnail: this.getOnClickLightboxThumbnailFn(), | ||
showThumbnails: this.props.showLightboxThumbnails | ||
}, this.props.lightBoxProps))); | ||
} | ||
}]); | ||
return Gallery; | ||
}(Component); | ||
Gallery.displayName = 'Gallery'; | ||
Gallery.propTypes = { | ||
images: PropTypes.arrayOf(PropTypes.shape({ | ||
src: PropTypes.string.isRequired, | ||
nano: PropTypes.string, | ||
alt: PropTypes.string, | ||
thumbnail: PropTypes.string.isRequired, | ||
srcset: PropTypes.array, | ||
caption: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), | ||
tags: PropTypes.arrayOf(PropTypes.shape({ | ||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired, | ||
title: PropTypes.string.isRequired, | ||
key: PropTypes.string | ||
})), | ||
thumbnailWidth: PropTypes.number.isRequired, | ||
thumbnailHeight: PropTypes.number.isRequired, | ||
isSelected: PropTypes.bool, | ||
thumbnailCaption: PropTypes.oneOfType([PropTypes.string, PropTypes.element]) | ||
})).isRequired, | ||
id: PropTypes.string, | ||
enableImageSelection: PropTypes.bool, | ||
onSelectImage: PropTypes.func, | ||
rowHeight: PropTypes.number, | ||
maxRows: PropTypes.number, | ||
margin: PropTypes.number, | ||
defaultContainerWidth: PropTypes.number, | ||
onClickThumbnail: PropTypes.func, | ||
lightboxWillOpen: PropTypes.func, | ||
lightboxWillClose: PropTypes.func, | ||
enableLightbox: PropTypes.bool, | ||
backdropClosesModal: PropTypes.bool, | ||
currentImage: PropTypes.number, | ||
preloadNextImage: PropTypes.bool, | ||
customControls: PropTypes.arrayOf(PropTypes.node), | ||
currentImageWillChange: PropTypes.func, | ||
enableKeyboardInput: PropTypes.bool, | ||
imageCountSeparator: PropTypes.string, | ||
isOpen: PropTypes.bool, | ||
onClickImage: PropTypes.func, | ||
onClickNext: PropTypes.func, | ||
onClickPrev: PropTypes.func, | ||
onClose: PropTypes.func, | ||
showCloseButton: PropTypes.bool, | ||
showImageCount: PropTypes.bool, | ||
lightboxWidth: PropTypes.number, | ||
tileViewportStyle: PropTypes.func, | ||
thumbnailStyle: PropTypes.func, | ||
showLightboxThumbnails: PropTypes.bool, | ||
onClickLightboxThumbnail: PropTypes.func, | ||
tagStyle: PropTypes.object, | ||
thumbnailImageComponent: PropTypes.func, | ||
lightBoxProps: PropTypes.object | ||
catch (err) { } | ||
setContainerWidth(Math.floor(width)); | ||
}, []); | ||
useEffect(() => { | ||
handleResize(); | ||
}, []); | ||
const thumbnails = buildLayoutFlat(images, { | ||
containerWidth, | ||
maxRows, | ||
rowHeight, | ||
margin, | ||
}); | ||
const handleSelect = (index, event) => { | ||
event.preventDefault(); | ||
props.onSelect(index, images[index], event); | ||
}; | ||
const handleClick = (index, event) => { | ||
props.onClick(index, images[index], event); | ||
}; | ||
return (jsxs("div", { id: props.id, className: "ReactGridGallery", ref: galleryRef, children: [jsx(ResizeListener, { onResize: handleResize }), thumbnails.map((item, index) => (jsx(Image, { item: item, index: index, margin: margin, height: rowHeight, isSelectable: enableImageSelection, onClick: handleClick, onSelect: handleSelect, tagStyle: props.tagStyle, tileViewportStyle: props.tileViewportStyle, thumbnailStyle: props.thumbnailStyle, thumbnailImageComponent: props.thumbnailImageComponent }, item.key || index)))] })); | ||
}; | ||
Gallery.displayName = "Gallery"; | ||
Gallery.defaultProps = { | ||
id: "ReactGridGallery", | ||
enableImageSelection: true, | ||
rowHeight: 180, | ||
margin: 2, | ||
defaultContainerWidth: 0, | ||
enableLightbox: true, | ||
backdropClosesModal: false, | ||
currentImage: 0, | ||
preloadNextImage: true, | ||
enableKeyboardInput: true, | ||
imageCountSeparator: ' of ', | ||
isOpen: false, | ||
showCloseButton: true, | ||
showImageCount: true, | ||
lightboxWidth: 1024, | ||
showLightboxThumbnails: false, | ||
lightBoxProps: {} | ||
id: "ReactGridGallery", | ||
enableImageSelection: true, | ||
rowHeight: 180, | ||
margin: 2, | ||
defaultContainerWidth: 0, | ||
onClick: () => { }, | ||
onSelect: () => { }, | ||
}; | ||
export { Gallery as default }; | ||
export { CheckButton, Gallery, buildLayout, buildLayoutFlat }; | ||
//# sourceMappingURL=react-grid-gallery.esm.js.map |
{ | ||
"name": "react-grid-gallery", | ||
"version": "0.5.6", | ||
"version": "1.0.0-alpha.0", | ||
"description": "Justified gallery component for React.", | ||
"types": "dist/react-grid-gallery.d.ts", | ||
"main": "dist/react-grid-gallery.cjs.js", | ||
@@ -10,11 +11,17 @@ "module": "dist/react-grid-gallery.esm.js", | ||
"dist", | ||
"lib", | ||
"src" | ||
], | ||
"exports": { | ||
"types": "./dist/react-grid-gallery.d.ts", | ||
"browser": "./dist/react-grid-gallery.umd.js", | ||
"import": "./dist/react-grid-gallery.esm.js", | ||
"require": "./dist/react-grid-gallery.cjs.js" | ||
}, | ||
"sideEffects": false, | ||
"scripts": { | ||
"build": "rollup -c", | ||
"prepublishOnly": "npm run build", | ||
"clean": "rimraf dist", | ||
"rollup:build": "rollup -c", | ||
"watch": "rollup -c -w", | ||
"build:examples": "rollup -c rollup.config.examples.js", | ||
"watch:examples": "rollup -c rollup.config.examples.js -w", | ||
"deploy:examples": "gh-pages -d ./examples/dist", | ||
"build": "npm run clean && npm run rollup:build", | ||
"test": "jest", | ||
@@ -25,32 +32,33 @@ "test:unit": "jest --testPathIgnorePatterns=\\.e2e\\.test\\.js", | ||
"peerDependencies": { | ||
"react": "^15.0 || ^16.0" | ||
"react": ">=16.14.0" | ||
}, | ||
"dependencies": { | ||
"prop-types": "^15.8.1", | ||
"react-images": "^0.5.16" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.18.9", | ||
"@babel/preset-env": "^7.18.9", | ||
"@babel/core": "^7.18.13", | ||
"@babel/preset-env": "^7.18.10", | ||
"@babel/preset-react": "^7.18.6", | ||
"@babel/preset-typescript": "^7.18.6", | ||
"@rollup/plugin-babel": "^5.3.1", | ||
"@rollup/plugin-commonjs": "^22.0.1", | ||
"@rollup/plugin-commonjs": "^22.0.2", | ||
"@rollup/plugin-node-resolve": "^13.3.0", | ||
"@rollup/plugin-replace": "^4.0.0", | ||
"@testing-library/jest-dom": "^5.16.4", | ||
"@testing-library/react": "^12.1.5", | ||
"@types/jest": "^28.1.6", | ||
"@types/react": "^16.14.30", | ||
"gh-pages": "^4.0.0", | ||
"@testing-library/jest-dom": "^5.16.5", | ||
"@testing-library/react": "^13.3.0", | ||
"@types/jest": "^29.0.0", | ||
"@types/jest-environment-puppeteer": "^5.0.2", | ||
"@types/jest-image-snapshot": "^5.1.0", | ||
"@types/react": "^18.0.18", | ||
"jest": "^28.1.3", | ||
"jest-environment-jsdom": "^28.1.3", | ||
"jest-image-snapshot": "^5.1.0", | ||
"jest-environment-jsdom": "^29.0.1", | ||
"jest-image-snapshot": "^5.1.1", | ||
"jest-puppeteer": "^6.1.1", | ||
"puppeteer": "^15.5.0", | ||
"react": "^16.14.0", | ||
"react-dom": "^16.14.0", | ||
"rollup": "^2.77.2", | ||
"rollup-plugin-copy": "^3.4.0", | ||
"rollup-plugin-livereload": "^2.0.5", | ||
"rollup-plugin-serve": "^2.0.0" | ||
"puppeteer": "^17.0.0", | ||
"react": "^18.2.0", | ||
"react-dom": "^18.2.0", | ||
"rimraf": "^3.0.2", | ||
"rollup": "^2.79.0", | ||
"rollup-plugin-dts": "^4.2.2", | ||
"rollup-plugin-peer-deps-external": "^2.2.4", | ||
"rollup-plugin-sourcemaps": "^0.6.3", | ||
"rollup-plugin-typescript2": "^0.33.0", | ||
"typescript": "^4.8.2" | ||
}, | ||
@@ -57,0 +65,0 @@ "repository": { |
189
README.md
# React Grid Gallery | ||
Justified image gallery component for [React](http://facebook.github.io/react/) inspired by [Google Photos](https://photos.google.com/) and based upon [React Images](https://github.com/jossmac/react-images). | ||
Justified image gallery component for [React](http://facebook.github.io/react/) inspired by [Google Photos](https://photos.google.com/). | ||
### :mega: Maintainers wanted :mega: | ||
> As react-grid-gallery continues to gain popularity and provide value to many users (over a million downloads from NPM alone) it requires maintainers to take care of issues and pull requsts, and to progress the software. If you're getting value from using this component or if you're just interested in becoming a maintainer, please let me know. | ||
### :tada: v1.0.0 is out! | ||
> A very big thankyou to [Isaev Igor (@itoldya)](https://github.com/itoldya) for taking on a substantial amount of work in smoothing out some (of the many) rough edges, and for bringing react-grid-gallery up to date. I really appreciate the care taken. Check out his site at [picryl.com](https://picryl.com/search) (a great example of react-grid-gallery in use). | ||
There are breaking changes with v0.5.x, check out the [migration guide](https://github.com/benhowell/react-grid-gallery/UPGRADE_GUIDE.md) to learn more. Documentation for v0.5.x is [here](https://github.com/benhowell/react-grid-gallery/tree/v0.5.6). | ||
### Note: | ||
> As of the release of [v0.5.4](https://github.com/benhowell/react-grid-gallery/releases/tag/v0.5.4) (2019-03-10) I will no longer be actively adding features and maintaining [react-grid-gallery](https://github.com/benhowell/react-grid-gallery). My online behavioral experiment platform [Psychstudio](https://www.psychstudio.com/) consumes all of my time and I am no longer capable of giving react-grid-gallery the attention it needs. A big thanks to [everyone who has contributed](https://github.com/benhowell/react-grid-gallery/blob/master/README.md#acknowledgements) over the last 5 years and thanks to everyone who has downloaded react-grid-gallery (hopefully it has been useful to you). | ||
## Live Demo & Examples | ||
@@ -22,3 +18,2 @@ | ||
* [Thumbnail Captions](https://benhowell.github.io/react-grid-gallery/#thumbnail-caption) | ||
* [Custom Lightbox Controls](https://benhowell.github.io/react-grid-gallery/#custom-controls) | ||
@@ -30,40 +25,38 @@ | ||
npm install --save react-grid-gallery | ||
```shell | ||
npm install --save react-grid-gallery | ||
``` | ||
## Quick (and dirty) Start | ||
## Quick Start | ||
```jsx | ||
import React from 'react'; | ||
import { render } from 'react-dom'; | ||
import Gallery from 'react-grid-gallery'; | ||
import { Gallery } from "react-grid-gallery"; | ||
const IMAGES = | ||
[{ | ||
src: "https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_b.jpg", | ||
thumbnail: "https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_n.jpg", | ||
thumbnailWidth: 320, | ||
thumbnailHeight: 174, | ||
isSelected: true, | ||
caption: "After Rain (Jeshu John - designerspics.com)" | ||
}, | ||
{ | ||
src: "https://c2.staticflickr.com/9/8356/28897120681_3b2c0f43e0_b.jpg", | ||
thumbnail: "https://c2.staticflickr.com/9/8356/28897120681_3b2c0f43e0_n.jpg", | ||
thumbnailWidth: 320, | ||
thumbnailHeight: 212, | ||
tags: [{value: "Ocean", title: "Ocean"}, {value: "People", title: "People"}], | ||
caption: "Boats (Jeshu John - designerspics.com)" | ||
}, | ||
const images = [ | ||
{ | ||
src: "https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_b.jpg", | ||
width: 320, | ||
height: 174, | ||
isSelected: true, | ||
caption: "After Rain (Jeshu John - designerspics.com)", | ||
}, | ||
{ | ||
src: "https://c2.staticflickr.com/9/8356/28897120681_3b2c0f43e0_b.jpg", | ||
width: 320, | ||
height: 212, | ||
tags: [ | ||
{ value: "Ocean", title: "Ocean" }, | ||
{ value: "People", title: "People" }, | ||
], | ||
alt: "Boats (Jeshu John - designerspics.com)", | ||
}, | ||
{ | ||
src: "https://c4.staticflickr.com/9/8887/28897124891_98c4fdd82b_b.jpg", | ||
thumbnail: "https://c4.staticflickr.com/9/8887/28897124891_98c4fdd82b_n.jpg", | ||
thumbnailWidth: 320, | ||
thumbnailHeight: 212 | ||
}] | ||
{ | ||
src: "https://c4.staticflickr.com/9/8887/28897124891_98c4fdd82b_b.jpg", | ||
width: 320, | ||
height: 212, | ||
}, | ||
]; | ||
render( | ||
<Gallery images={IMAGES}/>, | ||
document.getElementById('example-0') | ||
); | ||
<Gallery images={images} /> | ||
``` | ||
@@ -73,68 +66,35 @@ | ||
| Property | Type | Default | Description | | ||
|:-----------------|:--------------------|:----------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||
| src | string | undefined | Required. A string referring to any valid image resource (file, url, etc). | | ||
| thumbnail | string | undefined | Required. A string referring to any valid image resource (file, url, etc). | | ||
| thumbnailWidth | number | undefined | Required. Width of the thumbnail image. | | ||
| thumbnailHeight | number | undefined | Required. Height of the thumbnail image. | | ||
| nano | string:base64 | undefined | Optional. Thumbnail Base64 image will be injected to background under the main image. This provides a base64, 4x4 generated image whilst the image is beong loaded. | | ||
| alt | string | "" | Optional. Image alt attribute. | | ||
| tags | array | undefined | Optional. An array of objects containing tag attributes (value, title and key if value is element). e.g. `{value: "foo", title: "bar"}` or `{value: <a href={tag.url}>{tag.name}</a>, title: tag.title, key: tag.key}` | | ||
| isSelected | bool | undefined | Optional. The selected state of the image. | | ||
| caption | string|element | undefined | Optional. Image caption. | | ||
| srcSet | array | undefined | Optional. Array of srcSets for lightbox. | | ||
| customOverlay | element | undefined | Optional. A custom element to be rendered as a thumbnail overlay on hover. | | ||
| thumbnailCaption | string|element | undefined | Optional. A thumbnail caption shown below thumbnail. | | ||
| orientation | number | undefined | Optional. Orientation of the image. Many newer digital cameras (both dSLR and Point & Shoot digicams) have a built-in orientation sensor. The output of this sensor is used to set the EXIF orientation flag in the image file's metatdata to reflect the positioning of the camera with respect to the ground (See [EXIF Orientation Page](http://jpegclub.org/exif_orientation.html) for more info). | | ||
| Property | Type | Default | Description | | ||
|:-----------------|:------------------------|:----------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||
| src | string | undefined | Required. A string referring to any valid image resource (file, url, etc). | | ||
| width | number | undefined | Required. Width of the image. | | ||
| height | number | undefined | Required. Height of the image. | | ||
| nano | string:base64 | undefined | Optional. Thumbnail Base64 image will be injected to background under the main image. This provides a base64, 4x4 generated image whilst the image is being loaded. | | ||
| alt | string | "" | Optional. Image alt attribute. | | ||
| tags | array | undefined | Optional. An array of objects containing tag attributes (value, title and key if value is element). e.g. `{value: "foo", title: "bar"}` or `{value: <a href={tag.url}>{tag.name}</a>, title: tag.title, key: tag.key}` | | ||
| isSelected | bool | undefined | Optional. The selected state of the image. | | ||
| caption | string | ReactNode | undefined | Optional. Image caption. | | ||
| customOverlay | element | undefined | Optional. A custom element to be rendered as a thumbnail overlay on hover. | | ||
| thumbnailCaption | string | ReactNode | undefined | Optional. A thumbnail caption shown below thumbnail. | | ||
| orientation | number | undefined | Optional. Orientation of the image. Many newer digital cameras (both dSLR and Point & Shoot digicams) have a built-in orientation sensor. The output of this sensor is used to set the EXIF orientation flag in the image file's metatdata to reflect the positioning of the camera with respect to the ground (See [EXIF Orientation Page](http://jpegclub.org/exif_orientation.html) for more info). | | ||
## Gallery Options | ||
| Property | Type | Default | Description | | ||
|:------------------------|:----------------|:-------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||
| images | array | undefined | Required. An array of objects containing image properties (see Image Options above). | | ||
| id | string | "ReactGridGallery" | Optional. `id` attribute for `<Gallery>` tag. This prop may be useful for those who wish to discriminate between multiple galleries. | | ||
| enableImageSelection | bool | true | Optional. Allow images to be selectable. Setting this option to `false` whilst supplying images with `isSelected: true` will result in those images being permanently selected. | | ||
| onSelectImage | func | undefined | Optional. Function to execute when an image is selected. Allows access to image object using `this` (See [Programmers notes](#programmers-notes) for more info about implicit `this`). Optional args: index (index of selected image in images array), image (the selected image). This function is only executable when `enableImageSelection: true`. | | ||
| rowHeight | number | 180 | Optional. The height of each row in the gallery. | | ||
| maxRows | number | undefined | Optional. The maximum number of rows to show in the gallery. | | ||
| margin | number | 2 | Optional. The margin around each image in the gallery. | | ||
| enableLightbox | bool | true | Optional. Enable lightbox display of full size image when thumbnail clicked. | | ||
| onClickThumbnail | func | openLightbox | Optional. Function to execute when gallery thumbnail clicked. Allows access to image object using `this` (See [Programmers notes](#programmers-notes) for more info about implicit `this`). Optional args: index (index of selected image in images array), event (the click event). Overrides openLightbox. | | ||
| lightboxWillOpen | func | undefined | Optional. Function to be called before opening lightbox. Allows access to gallery object using `this` (See [Programmers notes](#programmers-notes) for more info about implicit `this`). Optional arg: index (index of selected image in images array). | | ||
| lightboxWillClose | func | undefined | Optional. Function to be called before closing lightbox. Allows access to gallery object using `this` (See [Programmers notes](#programmers-notes) for more info about implicit `this`). | | ||
| tagStyle | object | tagStyle | Optional. Style to pass to tag elements. Overrides internal tag style. | | ||
| tileViewportStyle | func | tileViewportStyle | Optional. Function to style the image tile viewport. Allows access to image object using `this` (See [Programmers notes](#programmers-notes) for more info about implicit `this`). Overrides internal tileViewportStyle function. | | ||
| thumbnailStyle | func | thumbnailStyle | Optional. Function to style the image thumbnail. Allows access to image object using `this` (See [Programmers notes](#programmers-notes) for more info about implicit `this`). Overrides internal thumbnailStyle function. | | ||
| thumbnailImageComponent | React component | undefined | Optional. Substitute in a React component that would get passed `imageProps` (the props that would have been passed to the `<img>` tag) and `item` (the original item in `images`) to be used to render thumbnails; useful for lazy loading. | | ||
| defaultContainerWidth | number | 0 | Optional. Set default width for the container. This option is useful during server-side rendering when we want to generate an initial markup before we can detect the actual container width. | | ||
| Property | Type | Default | Description | | ||
|:------------------------|:--------------------------|:-------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||
| images | array | undefined | Required. An array of objects containing image properties (see Image Options above). | | ||
| id | string | "ReactGridGallery" | Optional. `id` attribute for `<Gallery>` tag. This prop may be useful for those who wish to discriminate between multiple galleries. | | ||
| enableImageSelection | bool | true | Optional. Allow images to be selectable. Setting this option to `false` whilst supplying images with `isSelected: true` will result in those images being permanently selected. | | ||
| onSelect | func | undefined | Optional. Function to execute when an image is selected. Optional args: `index` (index of selected image in images array), `image` (the selected image), `event`. This function is only executable when `enableImageSelection: true`. | | ||
| rowHeight | number | 180 | Optional. The height of each row in the gallery. | | ||
| maxRows | number | undefined | Optional. The maximum number of rows to show in the gallery. | | ||
| margin | number | 2 | Optional. The margin around each image in the gallery. | | ||
| onClick | func | undefined | Optional. Function to execute when gallery image clicked. Optional args: `index` (index of selected image in images array), `image` (the clicked image), event (the click event). | | ||
| tagStyle | func | CSSProperties | tagStyle | Optional. Style or function that returns style to pass to tag elements. Optional args: `item` (the image item in `images`). Overrides internal tag style. | | ||
| tileViewportStyle | func | CSSProperties | tileViewportStyle | Optional. Style or function to style the image tile viewport. Optional args: `item` (the image item in `images`). Overrides internal tileViewportStyle function. | | ||
| thumbnailStyle | func | CSSProperties | thumbnailStyle | Optional. Style or function to style the image thumbnail. Optional args: `item` (the image item in `images`). Overrides internal thumbnailStyle function. | | ||
| thumbnailImageComponent | React component | undefined | Optional. Substitute in a React component that would get passed `imageProps` (the props that would have been passed to the `<img>` tag) and `item` (the original item in `images`) to be used to render thumbnails; useful for lazy loading. | | ||
| defaultContainerWidth | number | 0 | Optional. Set default width for the container. This option is useful during server-side rendering when we want to generate an initial markup before we can detect the actual container width. | | ||
## Lightbox Options | ||
NOTE: these options are passed inside the Gallery tag. | ||
e.g. | ||
```js | ||
<Gallery images={IMAGES} backdropClosesModal={true}/> | ||
``` | ||
| Property | Type | Default | Description | | ||
|:-------------------------|:-------|:-------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||
| backdropClosesModal | bool | false | Optional. Allow users to exit the lightbox by clicking the backdrop. | | ||
| currentImage | number | 0 | Optional. The index of the image to display initially (only relevant when used in conjunction with `isOpen: true` property). | | ||
| preloadNextImage | bool | true | Optional. Based on the direction the user is navigating, preload the next available image. | | ||
| customControls | array | undefined | Optional. An array of elements to display as custom controls on the top of lightbox. | | ||
| enableKeyboardInput | bool | true | Optional. Supports keyboard input - <code>esc</code>, <code>arrow left</code>, and <code>arrow right</code>. | | ||
| imageCountSeparator | string | ' of ' | Optional. Customize separator in the image count. | | ||
| isOpen | bool | false | Optional. Whether or not the lightbox is displayed when gallery first rendered (can be used in conjunction with `currentImage` property, otherwise the first image will be diplayed). | | ||
| showCloseButton | bool | true | Optional. Display a close "X" button in top right corner. | | ||
| showImageCount | bool | true | Optional. Display image index, e.g., "3 of 20". | | ||
| onClickImage | func | onClickImage | Optional. Function to execute when lightbox image clicked. Overrides internal implementation of onClickImage. | | ||
| onClickPrev | func | onClickPrev | Optional. Function to execute when lightbox left arrow clicked. Overrides internal implementation of onClickPrev. | | ||
| onClickNext | func | onClickNext | Optional. Function to execute when lightbox right arrow clicked. Overrides internal implementation of onClickNext. | | ||
| currentImageWillChange | func | undefined | Optional. Function to execute before lightbox image change. Useful for tracking current image shown in lightbox. Allows access to gallery object using `this` (See [Programmers notes](#programmers-notes) for more info about implicit `this`). | | ||
| showLightboxThumbnails | bool | false | Optional. Display thumbnails beneath the Lightbox image. | | ||
| onClickLightboxThumbnail | func | gotoImage | Optional. Function to execute when lightbox thumbnail clicked. Overrides internal function: gotoImage. | | ||
| lightboxWidth | number | 1024 | Optional. Maximum width of the lightbox carousel; defaults to 1024px. | | ||
| lightBoxProps | object | undefined | Optional. Object to pass props directly to LightBox. | | ||
### General Notes | ||
@@ -148,30 +108,5 @@ | ||
* Image Options: `thumbnail` can point to the same resource as `src`, bearing in mind the resultant data size of the gallery and page load cost. Thumbnails of whatever size will be scaled to match `rowHeight`. | ||
* If you don't know your `width` and `height` values, you can find these out using any number of [javascript hacks](http://stackoverflow.com/a/1944298), bearing in mind the load penalty associated with these methods. | ||
### Programmers Notes | ||
* User defined functions that allow access to `this` via [Function.prototype.call()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call) do not require you to declare or pass `this` as a parameter. `this` will be defined at the time the function is called. | ||
e.g. | ||
```js | ||
// somewhere in your code... | ||
function myTileViewportStyleFn() { | ||
if (this.props.item.isSelected) | ||
return { | ||
// something stylish... | ||
}; | ||
} | ||
<Gallery images={IMAGES} tileViewportStyle={myTileViewportStyleFn}/> | ||
// internally, within the react-grid-gallery component it will be called like so: | ||
myTileViewportStyleFn.call(this); // this now refers to the image to be styled | ||
``` | ||
* If you don't know your `thumbnailWidth` and `thumbnailHeight` values, you can find these out using any number of [javascript hacks](http://stackoverflow.com/a/1944298), bearing in mind the load penalty associated with these methods. | ||
### Contributing | ||
@@ -178,0 +113,0 @@ All contributions to [react-grid-gallery](https://github.com/benhowell/react-grid-gallery) are very welcome. Feature requests, issue reports and pull requests are greatly appreciated. Please follow the [contribution guidelines](https://github.com/benhowell/react-grid-gallery/blob/master/.github/contributing.md) |
Sorry, the diff of this file is too big to display
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
1
1
213462
28
18
1948
161
+ Addedreact@19.0.0(transitive)
- Removedprop-types@^15.8.1
- Removedreact-images@^0.5.16
- Removed@babel/runtime@7.26.0(transitive)
- Removedaphrodite@0.5.0(transitive)
- Removedasap@2.0.6(transitive)
- Removedbowser@1.9.4(transitive)
- Removeddom-helpers@3.4.0(transitive)
- Removedexenv@1.2.2(transitive)
- Removedhyphenate-style-name@1.1.0(transitive)
- Removedinline-style-prefixer@2.0.5(transitive)
- Removedjs-tokens@4.0.0(transitive)
- Removedloose-envify@1.4.0(transitive)
- Removedobject-assign@4.1.1(transitive)
- Removedprop-types@15.8.1(transitive)
- Removedreact@16.14.0(transitive)
- Removedreact-dom@16.14.0(transitive)
- Removedreact-images@0.5.19(transitive)
- Removedreact-is@16.13.1(transitive)
- Removedreact-lifecycles-compat@3.0.4(transitive)
- Removedreact-prop-toggle@1.0.2(transitive)
- Removedreact-scrolllock@2.0.7(transitive)
- Removedreact-transition-group@2.9.0(transitive)
- Removedregenerator-runtime@0.14.1(transitive)
- Removedscheduler@0.19.1(transitive)