From 223da3f5aeabd6214b583ddf57ddafe847fe3b3b Mon Sep 17 00:00:00 2001 From: liliana <liliana.sanfilippo@uni-bielefeld.de> Date: Sat, 29 Jun 2024 18:11:06 +0200 Subject: [PATCH] fix salad --- README.md | 10 +- src/components/photo-grid.tsx | 4 +- src/components/react-grid-gallery/LICENSE | 21 + src/components/react-grid-gallery/README.md | 162 +++++++ .../dist/react-grid-gallery.cjs.js | 317 ++++++++++++++ .../dist/react-grid-gallery.cjs.js.map | 1 + .../dist/react-grid-gallery.d.ts | 97 +++++ .../dist/react-grid-gallery.esm.js | 310 ++++++++++++++ .../dist/react-grid-gallery.esm.js.map | 1 + .../dist/react-grid-gallery.umd.js | 405 ++++++++++++++++++ .../dist/react-grid-gallery.umd.js.map | 1 + .../react-grid-gallery/package.json | 90 ++++ .../react-grid-gallery/src/Gallery.tsx | 67 +++ .../react-grid-gallery/src/Image.tsx | 119 +++++ .../react-grid-gallery/src/buildLayout.ts | 110 +++++ .../react-grid-gallery/src/index.ts | 3 + .../react-grid-gallery/src/styles.ts | 201 +++++++++ .../react-grid-gallery/src/types.ts | 107 +++++ .../src/useContainerWidth.ts | 35 ++ 19 files changed, 2058 insertions(+), 3 deletions(-) create mode 100755 src/components/react-grid-gallery/LICENSE create mode 100755 src/components/react-grid-gallery/README.md create mode 100644 src/components/react-grid-gallery/dist/react-grid-gallery.cjs.js create mode 100644 src/components/react-grid-gallery/dist/react-grid-gallery.cjs.js.map create mode 100644 src/components/react-grid-gallery/dist/react-grid-gallery.d.ts create mode 100644 src/components/react-grid-gallery/dist/react-grid-gallery.esm.js create mode 100644 src/components/react-grid-gallery/dist/react-grid-gallery.esm.js.map create mode 100644 src/components/react-grid-gallery/dist/react-grid-gallery.umd.js create mode 100644 src/components/react-grid-gallery/dist/react-grid-gallery.umd.js.map create mode 100644 src/components/react-grid-gallery/package.json create mode 100755 src/components/react-grid-gallery/src/Gallery.tsx create mode 100755 src/components/react-grid-gallery/src/Image.tsx create mode 100644 src/components/react-grid-gallery/src/buildLayout.ts create mode 100644 src/components/react-grid-gallery/src/index.ts create mode 100644 src/components/react-grid-gallery/src/styles.ts create mode 100644 src/components/react-grid-gallery/src/types.ts create mode 100644 src/components/react-grid-gallery/src/useContainerWidth.ts diff --git a/README.md b/README.md index 5878e33e..04a886c5 100644 --- a/README.md +++ b/README.md @@ -83,4 +83,12 @@ yarn add react-simple-maps npm -i @types/react-simple-maps yarn add react-grid-gallery -yarn add react-select \ No newline at end of file +yarn add react-select + + + +Argument of type 'ImageExtendedRow<T>[]' is not assignable to parameter of type 'ConcatArray<never>[]'. + Type 'ImageExtendedRow<T>' is not assignable to type 'ConcatArray<never>'. + The types returned by 'slice(...)' are incompatible between these types. + Type 'ImageExtended<T>[]' is not assignable to type 'never[]'. + Type 'ImageExtended<T>' is not assignable to type 'never'. \ No newline at end of file diff --git a/src/components/photo-grid.tsx b/src/components/photo-grid.tsx index 70b43c9f..3b6e9f80 100644 --- a/src/components/photo-grid.tsx +++ b/src/components/photo-grid.tsx @@ -1,6 +1,6 @@ /* */ -import { Gallery} from 'react-grid-gallery' -import { ThumbnailImageProps } from 'react-grid-gallery' +import { Gallery } from './react-grid-gallery/dist/react-grid-gallery'; +import { ThumbnailImageProps } from './react-grid-gallery/dist/react-grid-gallery'; const images = [ {src:"https://static.igem.wiki/teams/5247/photos/meetup/badges.jpeg", width: 320, height: 212}, {src:"https://static.igem.wiki/teams/5247/photos/meetup/joern.jpeg", width: 320, height: 212}, diff --git a/src/components/react-grid-gallery/LICENSE b/src/components/react-grid-gallery/LICENSE new file mode 100755 index 00000000..f908db52 --- /dev/null +++ b/src/components/react-grid-gallery/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016-2018 Ben Howell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/components/react-grid-gallery/README.md b/src/components/react-grid-gallery/README.md new file mode 100755 index 00000000..446725d8 --- /dev/null +++ b/src/components/react-grid-gallery/README.md @@ -0,0 +1,162 @@ +# React Grid Gallery + +Justified image gallery component for [React](http://facebook.github.io/react/) inspired by [Google Photos](https://photos.google.com/). + +### :tada: v1.0.0 is out! + +There are breaking changes with v0.5.x, check out the [migration guide](https://github.com/benhowell/react-grid-gallery/blob/master/UPGRADE_GUIDE.md) to learn more. Documentation for v0.5.x is [here](https://github.com/benhowell/react-grid-gallery/tree/v0.5.6). + +## Live Demo & Examples + +https://benhowell.github.io/react-grid-gallery/ +* [Image Selection](https://benhowell.github.io/react-grid-gallery/examples/selection) +* [Custom Overlay](https://benhowell.github.io/react-grid-gallery/examples/custom-overlay) +* [Thumbnail Captions](https://benhowell.github.io/react-grid-gallery/examples/captions) +* [Custom Image Component](https://benhowell.github.io/react-grid-gallery/examples/custom-image-component) +* [Lightbox integration `react-image-lightbox`](https://benhowell.github.io/react-grid-gallery/examples/with-react-image-lightbox) +* [Lightbox integration `yet-another-react-lightbox`](https://benhowell.github.io/react-grid-gallery/examples/with-yet-another-react-lightbox) + + +## Installation + +Using [npm](https://www.npmjs.com/): + +```shell +npm install --save react-grid-gallery +``` + +## Quick Start + +```jsx +import { Gallery } from "react-grid-gallery"; + +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", + width: 320, + height: 212, + }, +]; + +<Gallery images={images} /> +``` + +## Image Options + +| Property | Type | Description | +|:-----------------|:------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| src | string | Required. A string referring to any valid image resource (file, url, etc). | +| width | number | Required. Width of the image. | +| height | number | Required. Height of the image. | +| nano | string:base64 | 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 | 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 | Optional. The selected state of the image. | +| caption | string | ReactNode | Optional. Image caption. | +| customOverlay | element | Optional. A custom element to be rendered as a thumbnail overlay on hover. | +| thumbnailCaption | string | ReactNode | Optional. A thumbnail caption shown below thumbnail. | +| orientation | number | 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 | Description | +|:------------------------|:--------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| images | array | Required. An array of objects containing image properties (see Image Options above). | +| id | string | Optional, default `ReactGridGallery`. `id` attribute for `<Gallery>` tag. This prop may be useful for those who wish to discriminate between multiple galleries. | +| enableImageSelection | bool | Optional, default `true`. 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 | 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 | Optional, default `180`. The height of each row in the gallery. | +| maxRows | number | Optional. The maximum number of rows to show in the gallery. | +| margin | number | Optional, default `2`. The margin around each image in the gallery. | +| onClick | func | 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 | 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 | 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 | Optional. Style or function to style the image thumbnail. Optional args: `item` (the image item in `images`). Overrides internal thumbnailStyle function. | +| thumbnailImageComponent | React component | 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 | 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. | + + +### General Notes + + * [react-grid-gallery](https://github.com/benhowell/react-grid-gallery) is built for modern browsers and therefore IE support is limited to IE 11 and newer. + + * As the inspiration for this component comes from [Google Photos](https://photos.google.com/), very small thumbnails may not be the most aesthetically pleasing due to the border size applied when selected. A sensible rowHeight default of 180px has been chosen, but rowHeights down to 100px are still reasonable. + + * Gallery width is determined by the containing element. Therefore your containing element must have a width (%, em, px, whatever) **_before_** the gallery is loaded! + + * 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. + + +### Contributing +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) + + +### License +React Grid Gallery is free to use for personal and commercial projects under the [MIT License](https://github.com/benhowell/react-grid-gallery/blob/master/LICENSE). Attribution is not required, but appreciated. + + +### Acknowledgements + * [itoldya](https://github.com/itoldya) for the large overhaul of the code base to bring the library to its v1 release. + + * Visual design inspired by [Google Photos](https://photos.google.com/). + + * Thumbnail viewport implementation inspired by [GPlusGallery](http://fmaul.de/gallery-grid-example/) by Florian Maul. + + * Backend lightbox functionality via [React Images](https://github.com/jossmac/react-images) by [jossmac](https://github.com/jossmac). + + * The following gallery functions were obtained from the [React Images example](https://github.com/jossmac/react-images/blob/b85bd83ae651d0fd373bb495ac88670ee4dfadab/examples/src/components/Gallery.js) demo: closeLightbox, gotoNext, gotoPrevious, handleClickImage, openLightbox. + + * [cust0dian](https://github.com/cust0dian) for critical bug fixes in [PR 6](https://github.com/benhowell/react-grid-gallery/pull/6) and [PR 7](https://github.com/benhowell/react-grid-gallery/pull/7). + + * [ValYouW](https://github.com/ValYouW) for lightboxWillOpen and lightBoxWillClose functionality [PR 20](https://github.com/benhowell/react-grid-gallery/pull/20) and customOverlay option: [PR 22](https://github.com/benhowell/react-grid-gallery/pull/22). + + * [danalloway](https://github.com/danalloway) for theme pass-through prop [PR 27](https://github.com/benhowell/react-grid-gallery/pull/27) + + * [SimeonC](https://github.com/SimeonC) for _update thumbnails when maxRows changes_ [PR 35](https://github.com/benhowell/react-grid-gallery/pull/35) and _resize on scrollbar presence change_ [PR 40](https://github.com/benhowell/react-grid-gallery/pull/40) + + * [jakub-tucek](https://github.com/jakub-tucek) for thumbnailCaption functionality [PR 42](https://github.com/benhowell/react-grid-gallery/pull/42) + + * [mis94](https://github.com/mis94) for EXIF image rotation functionality [PR 67](https://github.com/benhowell/react-grid-gallery/pull/67) + + * [forforf](https://github.com/forforf) for contentWindow check [PR 77](https://github.com/benhowell/react-grid-gallery/pull/77) + +* [ScottMRafferty](https://github.com/ScottMRafferty) for preloadNextImage not propagating to Lightbox fix [PR 78](https://github.com/benhowell/react-grid-gallery/pull/78) + +* [Approximator](https://github.com/approximator) for currentImageWillChange (Function to execute before lightbox image change) [PR 97](https://github.com/benhowell/react-grid-gallery/pull/97). + +* [Vadimuz](https://github.com/vadimuz) for nano image props and functionality [PR 101](https://github.com/benhowell/react-grid-gallery/pull/101). + +* [pxpeterxu](https://github.com/pxpeterxu) for adding functionality to inject a custom thumbnail image component (for lazy-loading) [PR 104](https://github.com/benhowell/react-grid-gallery/pull/104). + +* [lryta](https://github.com/lryta) for fixing crash when this.props.images.length - 1 < this.state.currentImage [PR #111](https://github.com/benhowell/react-grid-gallery/pull/111). + +* [jimishf](https://github.com/JimishF) for lightBoxProps option to assign any prop directly to lightbox [PR #121](https://github.com/benhowell/react-grid-gallery/pull/121). + +* [kym6464](https://github.com/kym6464) for replacing deprecated defaultProps and for clearing of rollup cache on build [PR #298](https://github.com/benhowell/react-grid-gallery/pull/298) + + + * Demo stock photos: + * [Jeshu John - designerspics.com](https://designerspics.com) + * [Gratisography](https://gratisography.com) + * [Tom Eversley - isorepublic.com](https://isorepublic.com) + * [Jan Vasek - jeshoots.com](https://unsplash.com/) + * [moveast.me](https://moveast.me) + * [è´èŽ‰å„¿ NG. - unsplash.com](https://unsplash.com/) + * [Matthew Wiebe. - unsplash.com](https://unsplash.com/) diff --git a/src/components/react-grid-gallery/dist/react-grid-gallery.cjs.js b/src/components/react-grid-gallery/dist/react-grid-gallery.cjs.js new file mode 100644 index 00000000..aab8a158 --- /dev/null +++ b/src/components/react-grid-gallery/dist/react-grid-gallery.cjs.js @@ -0,0 +1,317 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +var jsxRuntime = require('react/jsx-runtime'); +var react = require('react'); + +const getStyle = (styleProp, fallback, context) => { + if (typeof styleProp === "function") { + return styleProp(context); + } + if (typeof styleProp === "object") { + return styleProp; + } + 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 gallery = { + display: "flex", + flexWrap: "wrap", +}; +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 style; +}; +const tileViewport = ({ item, }) => { + const styles = { + width: item.viewportWidth, + height: item.scaledHeight, + overflow: "hidden", + }; + if (item.nano) { + styles.background = `url(${item.nano})`; + styles.backgroundSize = "cover"; + styles.backgroundPosition = "center center"; + } + if (item.isSelected) { + styles.width = item.viewportWidth - SELECTION_MARGIN * 2; + styles.height = item.scaledHeight - SELECTION_MARGIN * 2; + styles.margin = SELECTION_MARGIN; + } + 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", + 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", + 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 Image = ({ item, thumbnailImageComponent: ThumbnailImageComponent, isSelectable = true, thumbnailStyle, tagStyle, tileViewportStyle, margin, index, onSelect, onClick, }) => { + const styleContext = { item }; + const [hover, setHover] = react.useState(false); + const thumbnailProps = { + key: index, + "data-testid": "grid-gallery-item_thumbnail", + src: item.src, + alt: item.alt ? item.alt : "", + style: getStyle(thumbnailStyle, thumbnail, styleContext), + }; + const handleCheckButtonClick = (event) => { + if (!isSelectable) { + return; + } + onSelect(index, event); + }; + const handleViewportClick = (event) => { + onClick(index, event); + }; + const thumbnailImageProps = { + item, + index, + margin, + onSelect, + onClick, + isSelectable, + tileViewportStyle, + thumbnailStyle, + tagStyle, + }; + return (jsxRuntime.jsxs("div", { className: "ReactGridGallery_tile", "data-testid": "grid-gallery-item", onMouseEnter: () => setHover(true), onMouseLeave: () => setHover(false), style: galleryItem({ margin }), children: [jsxRuntime.jsx("div", { className: "ReactGridGallery_tile-icon-bar", style: tileIconBar, children: jsxRuntime.jsx(CheckButton, { isSelected: item.isSelected, isVisible: item.isSelected || (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", { style: tagItemBlock, children: jsxRuntime.jsx("span", { style: getStyle(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 && isSelectable, + }) }), jsxRuntime.jsx("div", { className: "ReactGridGallery_tile-viewport", "data-testid": "grid-gallery-item_viewport", style: getStyle(tileViewportStyle, tileViewport, styleContext), onClick: handleViewportClick, children: ThumbnailImageComponent ? (jsxRuntime.jsx(ThumbnailImageComponent, { ...thumbnailImageProps, imageProps: thumbnailProps })) : (jsxRuntime.jsx("img", { ...thumbnailProps })) }), item.thumbnailCaption && (jsxRuntime.jsx("div", { className: "ReactGridGallery_tile-description", style: tileDescription, children: item.thumbnailCaption }))] })); +}; + +function useContainerWidth(defaultContainerWidth) { + const ref = react.useRef(null); + const observerRef = react.useRef(); + const [containerWidth, setContainerWidth] = react.useState(defaultContainerWidth); + const containerRef = react.useCallback((node) => { + var _a; + (_a = observerRef.current) === null || _a === void 0 ? void 0 : _a.disconnect(); + observerRef.current = undefined; + ref.current = node; + const updateWidth = () => { + if (!ref.current) { + return; + } + let width = ref.current.clientWidth; + try { + width = ref.current.getBoundingClientRect().width; + } + catch (err) { } + setContainerWidth(Math.floor(width)); + }; + updateWidth(); + if (node && typeof ResizeObserver !== "undefined") { + observerRef.current = new ResizeObserver(updateWidth); + observerRef.current.observe(node); + } + }, []); + return { containerRef, containerWidth }; +} + +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]; + } + let stillToCutOff = protrudingWidth - cutSum; + while (stillToCutOff > 0) { + for (let i in cutOff) { + cutOff[i]++; + stillToCutOff--; + if (stillToCutOff < 0) + break; + } + } + return cutOff; +}; +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; + } + } + return [row, items]; +}; +const getRows = (images, options, rows = []) => { + const [row, imagesLeft] = getRow(images, options); + const nextRows = [...rows, row]; + if (options.maxRows && nextRows.length >= options.maxRows) { + return nextRows; + } + if (imagesLeft.length) { + return getRows(imagesLeft, options, nextRows); + } + 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); +}; + +const Gallery = ({ images, id = "ReactGridGallery", enableImageSelection = true, onSelect = () => { }, rowHeight = 180, maxRows, margin = 2, defaultContainerWidth = 0, onClick = () => { }, tileViewportStyle, thumbnailStyle, tagStyle, thumbnailImageComponent, }) => { + const { containerRef, containerWidth } = useContainerWidth(defaultContainerWidth); + const thumbnails = buildLayoutFlat(images, { + containerWidth, + maxRows, + rowHeight, + margin, + }); + const handleSelect = (index, event) => { + event.preventDefault(); + onSelect(index, images[index], event); + }; + const handleClick = (index, event) => { + onClick(index, images[index], event); + }; + return (jsxRuntime.jsx("div", { id: id, className: "ReactGridGallery", ref: containerRef, children: jsxRuntime.jsx("div", { style: gallery, children: thumbnails.map((item, index) => (jsxRuntime.jsx(Image, { item: item, index: index, margin: margin, height: rowHeight, isSelectable: enableImageSelection, onClick: handleClick, onSelect: handleSelect, tagStyle: tagStyle, tileViewportStyle: tileViewportStyle, thumbnailStyle: thumbnailStyle, thumbnailImageComponent: thumbnailImageComponent }, item.key || index))) }) })); +}; +Gallery.displayName = "Gallery"; + +exports.CheckButton = CheckButton; +exports.Gallery = Gallery; +exports.buildLayout = buildLayout; +exports.buildLayoutFlat = buildLayoutFlat; +//# sourceMappingURL=react-grid-gallery.cjs.js.map diff --git a/src/components/react-grid-gallery/dist/react-grid-gallery.cjs.js.map b/src/components/react-grid-gallery/dist/react-grid-gallery.cjs.js.map new file mode 100644 index 00000000..d4fc1c02 --- /dev/null +++ b/src/components/react-grid-gallery/dist/react-grid-gallery.cjs.js.map @@ -0,0 +1 @@ +{"version":3,"file":"react-grid-gallery.cjs.js","sources":["../src/styles.ts","../src/CheckButton.tsx","../src/Image.tsx","../src/useContainerWidth.ts","../src/buildLayout.ts","../src/Gallery.tsx"],"sourcesContent":["import { CSSProperties } from \"react\";\nimport {\n ImageExtended,\n StyleFunction,\n StyleFunctionContext,\n StyleProp,\n} from \"./types\";\n\nexport const getStyle = (\n styleProp: StyleProp | undefined,\n fallback: StyleFunction,\n context: StyleFunctionContext\n): CSSProperties => {\n if (typeof styleProp === \"function\") {\n return styleProp(context);\n }\n if (typeof styleProp === \"object\") {\n return styleProp;\n }\n return fallback(context);\n};\n\nconst rotationTransformMap: Record<number, string> = {\n 3: \"rotate(180deg)\",\n 2: \"rotateY(180deg)\",\n 4: \"rotate(180deg) rotateY(180deg)\",\n 5: \"rotate(270deg) rotateY(180deg)\",\n 6: \"rotate(90deg)\",\n 7: \"rotate(90deg) rotateY(180deg)\",\n 8: \"rotate(270deg)\",\n};\n\nconst SELECTION_MARGIN = 16;\n\nexport const gallery: CSSProperties = {\n display: \"flex\",\n flexWrap: \"wrap\",\n};\n\nexport const thumbnail = ({ item }: { item: ImageExtended }): CSSProperties => {\n const rotationTransformValue = rotationTransformMap[item.orientation];\n\n const style = {\n cursor: \"pointer\",\n maxWidth: \"none\",\n width: item.scaledWidth,\n height: item.scaledHeight,\n marginLeft: item.marginLeft,\n marginTop: 0,\n transform: rotationTransformValue,\n };\n\n if (item.isSelected) {\n const ratio = item.scaledWidth / item.scaledHeight;\n const viewportHeight = item.scaledHeight - SELECTION_MARGIN * 2;\n const viewportWidth = item.viewportWidth - SELECTION_MARGIN * 2;\n\n let height, width;\n if (item.scaledWidth > item.scaledHeight) {\n width = item.scaledWidth - SELECTION_MARGIN * 2;\n height = Math.floor(width / ratio);\n } else {\n height = item.scaledHeight - SELECTION_MARGIN * 2;\n width = Math.floor(height * ratio);\n }\n\n const marginTop = Math.abs(Math.floor((viewportHeight - height) / 2));\n const marginLeft = Math.abs(Math.floor((viewportWidth - width) / 2));\n\n style.width = width;\n style.height = height;\n style.marginLeft = marginLeft === 0 ? 0 : -marginLeft;\n style.marginTop = marginTop === 0 ? 0 : -marginTop;\n }\n\n return style;\n};\n\nexport const tileViewport = ({\n item,\n}: {\n item: ImageExtended;\n}): CSSProperties => {\n const styles: CSSProperties = {\n width: item.viewportWidth,\n height: item.scaledHeight,\n overflow: \"hidden\",\n };\n if (item.nano) {\n styles.background = `url(${item.nano})`;\n styles.backgroundSize = \"cover\";\n styles.backgroundPosition = \"center center\";\n }\n if (item.isSelected) {\n styles.width = item.viewportWidth - SELECTION_MARGIN * 2;\n styles.height = item.scaledHeight - SELECTION_MARGIN * 2;\n styles.margin = SELECTION_MARGIN;\n }\n return styles;\n};\n\nexport const customOverlay = ({\n hover,\n}: {\n hover: boolean;\n}): CSSProperties => ({\n pointerEvents: \"none\",\n opacity: hover ? 1 : 0,\n position: \"absolute\",\n height: \"100%\",\n width: \"100%\",\n});\n\nexport const galleryItem = ({ margin }: { margin: number }): CSSProperties => ({\n margin,\n WebkitUserSelect: \"none\",\n position: \"relative\",\n background: \"#eee\",\n padding: \"0px\",\n});\n\nexport const tileOverlay = ({\n showOverlay,\n}: {\n showOverlay: boolean;\n}): CSSProperties => ({\n pointerEvents: \"none\",\n opacity: 1,\n position: \"absolute\",\n height: \"100%\",\n width: \"100%\",\n background: showOverlay\n ? \"linear-gradient(to bottom,rgba(0,0,0,0.26),transparent 56px,transparent)\"\n : \"none\",\n});\n\nexport const tileIconBar: CSSProperties = {\n pointerEvents: \"none\",\n opacity: 1,\n position: \"absolute\",\n height: \"36px\",\n width: \"100%\",\n};\n\nexport const tileDescription: CSSProperties = {\n background: \"white\",\n width: \"100%\",\n margin: 0,\n userSelect: \"text\",\n WebkitUserSelect: \"text\",\n MozUserSelect: \"text\",\n overflow: \"hidden\",\n};\n\nexport const bottomBar: CSSProperties = {\n padding: \"2px\",\n pointerEvents: \"none\",\n position: \"absolute\",\n minHeight: \"0px\",\n maxHeight: \"160px\",\n width: \"100%\",\n bottom: \"0px\",\n overflow: \"hidden\",\n};\n\nexport const tagItemBlock: CSSProperties = {\n display: \"inline-block\",\n cursor: \"pointer\",\n pointerEvents: \"visible\",\n margin: \"2px\",\n};\n\nexport const tagItem = (): CSSProperties => ({\n display: \"inline\",\n padding: \".2em .6em .3em\",\n fontSize: \"75%\",\n fontWeight: \"600\",\n lineHeight: \"1\",\n color: \"yellow\",\n background: \"rgba(0,0,0,0.65)\",\n textAlign: \"center\",\n whiteSpace: \"nowrap\",\n verticalAlign: \"baseline\",\n borderRadius: \".25em\",\n});\n\nexport const checkButton = ({\n isVisible,\n}: {\n isVisible: boolean;\n}): CSSProperties => ({\n visibility: isVisible ? \"visible\" : \"hidden\",\n background: \"none\",\n float: \"left\",\n width: 36,\n height: 36,\n border: \"none\",\n padding: 6,\n cursor: \"pointer\",\n pointerEvents: \"visible\",\n});\n","import { useState } from \"react\";\nimport * as styles from \"./styles\";\nimport { CheckButtonProps } from \"./types\";\n\nexport const CheckButton = ({\n isSelected = false,\n isVisible = true,\n onClick,\n color = \"#FFFFFFB2\",\n selectedColor = \"#4285F4FF\",\n hoverColor = \"#FFFFFFFF\",\n}: CheckButtonProps): JSX.Element => {\n const [hover, setHover] = useState(false);\n\n const circleStyle = { display: isSelected ? \"block\" : \"none\" };\n const fillColor = isSelected ? selectedColor : hover ? hoverColor : color;\n\n const handleMouseOver = () => setHover(true);\n const handleMouseOut = () => setHover(false);\n\n return (\n <div\n data-testid=\"grid-gallery-item_check-button\"\n title=\"Select\"\n style={styles.checkButton({ isVisible })}\n onClick={onClick}\n onMouseOver={handleMouseOver}\n onMouseOut={handleMouseOut}\n >\n <svg\n fill={fillColor}\n height=\"24\"\n viewBox=\"0 0 24 24\"\n width=\"24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <radialGradient\n id=\"shadow\"\n cx=\"38\"\n cy=\"95.488\"\n r=\"10.488\"\n gradientTransform=\"matrix(1 0 0 -1 -26 109)\"\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop offset=\".832\" stopColor=\"#010101\"></stop>\n <stop offset=\"1\" stopColor=\"#010101\" stopOpacity=\"0\"></stop>\n </radialGradient>\n\n <circle\n style={circleStyle}\n opacity=\".26\"\n fill=\"url(#shadow)\"\n cx=\"12\"\n cy=\"13.512\"\n r=\"10.488\"\n />\n <circle style={circleStyle} fill=\"#FFF\" cx=\"12\" cy=\"12.2\" r=\"8.292\" />\n <path d=\"M0 0h24v24H0z\" fill=\"none\" />\n <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\" />\n </svg>\n </div>\n );\n};\n","import { useState, MouseEvent } from \"react\";\nimport { CheckButton } from \"./CheckButton\";\nimport { ImageExtended, ImageProps } from \"./types\";\nimport * as styles from \"./styles\";\nimport { getStyle } from \"./styles\";\n\nexport const Image = <T extends ImageExtended>({\n item,\n thumbnailImageComponent: ThumbnailImageComponent,\n isSelectable = true,\n thumbnailStyle,\n tagStyle,\n tileViewportStyle,\n margin,\n index,\n onSelect,\n onClick,\n}: ImageProps<T>): JSX.Element => {\n const styleContext = { item };\n\n const [hover, setHover] = useState(false);\n\n const thumbnailProps = {\n key: index,\n \"data-testid\": \"grid-gallery-item_thumbnail\",\n src: item.src,\n alt: item.alt ? item.alt : \"\",\n title: typeof item.caption === \"string\" ? item.caption : null,\n style: getStyle(thumbnailStyle, styles.thumbnail, styleContext),\n };\n\n const handleCheckButtonClick = (event: MouseEvent<HTMLElement>) => {\n if (!isSelectable) {\n return;\n }\n onSelect(index, event);\n };\n\n const handleViewportClick = (event: MouseEvent<HTMLElement>) => {\n onClick(index, event);\n };\n\n const thumbnailImageProps = {\n item,\n index,\n margin,\n onSelect,\n onClick,\n isSelectable,\n tileViewportStyle,\n thumbnailStyle,\n tagStyle,\n };\n\n return (\n <div\n className=\"ReactGridGallery_tile\"\n data-testid=\"grid-gallery-item\"\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={styles.galleryItem({ margin })}\n >\n <div\n className=\"ReactGridGallery_tile-icon-bar\"\n style={styles.tileIconBar}\n >\n <CheckButton\n isSelected={item.isSelected}\n isVisible={item.isSelected || (isSelectable && hover)}\n onClick={handleCheckButtonClick}\n />\n </div>\n\n {!!item.tags && (\n <div\n className=\"ReactGridGallery_tile-bottom-bar\"\n style={styles.bottomBar}\n >\n {item.tags.map((tag, index) => (\n <div\n key={tag.key || index}\n title={tag.title}\n style={styles.tagItemBlock}\n >\n <span style={getStyle(tagStyle, styles.tagItem, styleContext)}>\n {tag.value}\n </span>\n </div>\n ))}\n </div>\n )}\n\n {!!item.customOverlay && (\n <div\n className=\"ReactGridGallery_custom-overlay\"\n style={styles.customOverlay({ hover })}\n >\n {item.customOverlay}\n </div>\n )}\n\n <div\n className=\"ReactGridGallery_tile-overlay\"\n style={styles.tileOverlay({\n showOverlay: hover && !item.isSelected && isSelectable,\n })}\n />\n\n <div\n className=\"ReactGridGallery_tile-viewport\"\n data-testid=\"grid-gallery-item_viewport\"\n style={getStyle(tileViewportStyle, styles.tileViewport, styleContext)}\n onClick={handleViewportClick}\n >\n {ThumbnailImageComponent ? (\n <ThumbnailImageComponent\n {...thumbnailImageProps}\n imageProps={thumbnailProps}\n />\n ) : (\n <img {...thumbnailProps} />\n )}\n </div>\n {item.thumbnailCaption && (\n <div\n className=\"ReactGridGallery_tile-description\"\n style={styles.tileDescription}\n >\n {item.thumbnailCaption}\n </div>\n )}\n </div>\n );\n};\n","import { useRef, useCallback, useState } from \"react\";\n\nexport function useContainerWidth(defaultContainerWidth: number) {\n const ref = useRef<HTMLElement | null>(null);\n const observerRef = useRef<ResizeObserver>();\n\n const [containerWidth, setContainerWidth] = useState(defaultContainerWidth);\n\n const containerRef = useCallback((node: HTMLElement | null) => {\n observerRef.current?.disconnect();\n observerRef.current = undefined;\n\n ref.current = node;\n\n const updateWidth = () => {\n if (!ref.current) {\n return;\n }\n let width = ref.current.clientWidth;\n try {\n width = ref.current.getBoundingClientRect().width;\n } catch (err) {}\n setContainerWidth(Math.floor(width));\n };\n\n updateWidth();\n\n if (node && typeof ResizeObserver !== \"undefined\") {\n observerRef.current = new ResizeObserver(updateWidth);\n observerRef.current.observe(node);\n }\n }, []);\n\n return { containerRef, containerWidth };\n}\n","import {\n ImageExtended,\n Image,\n BuildLayoutOptions,\n ImageExtendedRow,\n} from \"./types\";\n\nconst calculateCutOff = <T extends ImageExtended = ImageExtended>(\n items: T[],\n totalRowWidth: number,\n protrudingWidth: number\n) => {\n const cutOff: number[] = [];\n let cutSum = 0;\n for (let i in items) {\n const item = items[i];\n const fractionOfWidth = item.scaledWidth / totalRowWidth;\n cutOff[i] = Math.floor(fractionOfWidth * protrudingWidth);\n cutSum += cutOff[i];\n }\n\n let stillToCutOff = protrudingWidth - cutSum;\n while (stillToCutOff > 0) {\n for (let i in cutOff) {\n cutOff[i]++;\n stillToCutOff--;\n if (stillToCutOff < 0) break;\n }\n }\n return cutOff;\n};\n\nconst getRow = <T extends Image = Image>(\n images: T[],\n { containerWidth, rowHeight, margin }: BuildLayoutOptions\n): [ImageExtendedRow<T>, T[]] => {\n const row: ImageExtendedRow<T> = [];\n const imgMargin = 2 * margin;\n const items = [...images];\n\n let totalRowWidth = 0;\n while (items.length > 0 && totalRowWidth < containerWidth) {\n const item = items.shift();\n const scaledWidth = Math.floor(rowHeight * (item.width / item.height));\n const extendedItem: ImageExtended<T> = {\n ...item,\n scaledHeight: rowHeight,\n scaledWidth,\n viewportWidth: scaledWidth,\n marginLeft: 0,\n };\n row.push(extendedItem);\n totalRowWidth += extendedItem.scaledWidth + imgMargin;\n }\n\n const protrudingWidth = totalRowWidth - containerWidth;\n if (row.length > 0 && protrudingWidth > 0) {\n const cutoff = calculateCutOff(row, totalRowWidth, protrudingWidth);\n for (const i in row) {\n const pixelsToRemove = cutoff[i];\n const item = row[i];\n item.marginLeft = -Math.abs(Math.floor(pixelsToRemove / 2));\n item.viewportWidth = item.scaledWidth - pixelsToRemove;\n }\n }\n\n return [row, items];\n};\n\nconst getRows = <T extends Image = Image>(\n images: T[],\n options: BuildLayoutOptions,\n rows: ImageExtendedRow<T>[] = []\n): ImageExtendedRow<T>[] => {\n const [row, imagesLeft] = getRow(images, options);\n const nextRows = [...rows, row];\n\n if (options.maxRows && nextRows.length >= options.maxRows) {\n return nextRows;\n }\n if (imagesLeft.length) {\n return getRows(imagesLeft, options, nextRows);\n }\n return nextRows;\n};\n\nexport const buildLayout = <T extends Image = Image>(\n images: T[],\n { containerWidth, maxRows, rowHeight, margin }: BuildLayoutOptions\n): ImageExtendedRow<T>[] => {\n rowHeight = typeof rowHeight === \"undefined\" ? 180 : rowHeight;\n margin = typeof margin === \"undefined\" ? 2 : margin;\n\n if (!images) return [];\n if (!containerWidth) return [];\n\n const options = { containerWidth, maxRows, rowHeight, margin };\n return getRows(images, options);\n};\n\nexport const buildLayoutFlat = <T extends Image = Image>(\n images: T[],\n options: BuildLayoutOptions\n): ImageExtendedRow<T> => {\n const rows = buildLayout(images, options);\n return [].concat.apply([], rows);\n};\n","import { MouseEvent } from \"react\";\nimport { Image } from \"./Image\";\nimport { useContainerWidth } from \"./useContainerWidth\";\nimport { buildLayoutFlat } from \"./buildLayout\";\nimport { Image as ImageInterface, GalleryProps } from \"./types\";\nimport * as styles from \"./styles\";\n\nexport const Gallery = <T extends ImageInterface>({\n images,\n id = \"ReactGridGallery\",\n enableImageSelection = true,\n onSelect = () => {},\n rowHeight = 180,\n maxRows,\n margin = 2,\n defaultContainerWidth = 0,\n onClick = () => {},\n tileViewportStyle,\n thumbnailStyle,\n tagStyle,\n thumbnailImageComponent,\n}: GalleryProps<T>): JSX.Element => {\n const { containerRef, containerWidth } = useContainerWidth(\n defaultContainerWidth\n );\n\n const thumbnails = buildLayoutFlat<T>(images, {\n containerWidth,\n maxRows,\n rowHeight,\n margin,\n });\n\n const handleSelect = (index: number, event: MouseEvent<HTMLElement>) => {\n event.preventDefault();\n onSelect(index, images[index], event);\n };\n\n const handleClick = (index: number, event: MouseEvent<HTMLElement>) => {\n onClick(index, images[index], event);\n };\n\n return (\n <div id={id} className=\"ReactGridGallery\" ref={containerRef}>\n <div style={styles.gallery}>\n {thumbnails.map((item, index) => (\n <Image\n key={item.key || index}\n item={item}\n index={index}\n margin={margin}\n height={rowHeight}\n isSelectable={enableImageSelection}\n onClick={handleClick}\n onSelect={handleSelect}\n tagStyle={tagStyle}\n tileViewportStyle={tileViewportStyle}\n thumbnailStyle={thumbnailStyle}\n thumbnailImageComponent={thumbnailImageComponent}\n />\n ))}\n </div>\n </div>\n );\n};\n\nGallery.displayName = \"Gallery\";\n"],"names":["useState","_jsx","styles.checkButton","_jsxs","styles.thumbnail","styles.galleryItem","styles.tileIconBar","styles.bottomBar","styles.tagItemBlock","styles.tagItem","styles.customOverlay","styles.tileOverlay","styles.tileViewport","styles.tileDescription","useRef","useCallback","styles.gallery"],"mappings":"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"} \ No newline at end of file diff --git a/src/components/react-grid-gallery/dist/react-grid-gallery.d.ts b/src/components/react-grid-gallery/dist/react-grid-gallery.d.ts new file mode 100644 index 00000000..d955cf70 --- /dev/null +++ b/src/components/react-grid-gallery/dist/react-grid-gallery.d.ts @@ -0,0 +1,97 @@ +import { ReactNode, MouseEvent, CSSProperties, ComponentType } from 'react'; + +type Key = string | number; +interface ImageTag { + value: ReactNode; + key?: Key; +} +interface Image { + key?: Key; + src: string; + width: number; + height: number; + nano?: string; + alt?: string; + tags?: ImageTag[]; + isSelected?: boolean; + caption?: ReactNode; + customOverlay?: ReactNode; + thumbnailCaption?: ReactNode; + orientation?: number; +} +type ImageExtended<T extends Image = Image> = T & { + scaledWidth: number; + scaledHeight: number; + viewportWidth: number; + marginLeft: number; +}; +interface BuildLayoutOptions { + containerWidth: number; + maxRows?: number; + rowHeight?: number; + margin?: number; +} +type ImageExtendedRow<T extends Image = Image> = ImageExtended<T>[]; +type EventHandler<T extends Image = Image> = (index: number, item: T, event: MouseEvent<HTMLElement>) => void; +type StyleFunctionContext<T extends Image = Image> = { + item: T; +}; +type StyleFunction<T extends Image = Image> = (context: StyleFunctionContext) => CSSProperties; +type StyleProp<T extends Image = Image> = CSSProperties | StyleFunction<T>; +interface ImageProps<T extends ImageExtended = ImageExtended> { + item: T; + index: number; + margin: number; + isSelectable: boolean; + onClick: (index: number, event: MouseEvent<HTMLElement>) => void; + onSelect: (index: number, event: MouseEvent<HTMLElement>) => void; + tileViewportStyle: StyleProp<T>; + thumbnailStyle: StyleProp<T>; + tagStyle: StyleProp<T>; + height?: number; + thumbnailImageComponent?: ComponentType<ThumbnailImageProps>; +} +interface ThumbnailImageComponentImageProps { + key: string | number; + src: string; + alt: string; + style: CSSProperties; +} +type ThumbnailImageProps<T extends ImageExtended = ImageExtended> = ImageProps<T> & { + imageProps: ThumbnailImageComponentImageProps; +}; +interface GalleryProps<T extends Image = Image> { + images: T[]; + id?: string; + enableImageSelection?: boolean; + onSelect?: EventHandler<T>; + rowHeight?: number; + maxRows?: number; + margin?: number; + defaultContainerWidth?: number; + onClick?: EventHandler<T>; + tileViewportStyle?: StyleProp<T>; + thumbnailStyle?: StyleProp<T>; + tagStyle?: StyleProp<T>; + thumbnailImageComponent?: ComponentType<ThumbnailImageProps>; +} +interface CheckButtonProps { + isSelected: boolean; + isVisible: boolean; + onClick: (event: MouseEvent<HTMLElement>) => void; + color?: string; + selectedColor?: string; + hoverColor?: string; +} + +declare const Gallery: { + <T extends Image>({ images, id, enableImageSelection, onSelect, rowHeight, maxRows, margin, defaultContainerWidth, onClick, tileViewportStyle, thumbnailStyle, tagStyle, thumbnailImageComponent, }: GalleryProps<T>): JSX.Element; + displayName: string; +}; + +declare const CheckButton: ({ isSelected, isVisible, onClick, color, selectedColor, hoverColor, }: CheckButtonProps) => JSX.Element; + +declare const buildLayout: <T extends Image = Image>(images: T[], { containerWidth, maxRows, rowHeight, margin }: BuildLayoutOptions) => ImageExtendedRow<T>[]; +declare const buildLayoutFlat: <T extends Image = Image>(images: T[], options: BuildLayoutOptions) => ImageExtendedRow<T>; + +export { BuildLayoutOptions, CheckButton, CheckButtonProps, EventHandler, Gallery, GalleryProps, Image, ImageExtended, ImageExtendedRow, ImageProps, ImageTag, StyleFunction, StyleFunctionContext, StyleProp, ThumbnailImageComponentImageProps, ThumbnailImageProps, buildLayout, buildLayoutFlat }; diff --git a/src/components/react-grid-gallery/dist/react-grid-gallery.esm.js b/src/components/react-grid-gallery/dist/react-grid-gallery.esm.js new file mode 100644 index 00000000..d94a204e --- /dev/null +++ b/src/components/react-grid-gallery/dist/react-grid-gallery.esm.js @@ -0,0 +1,310 @@ +import { jsx, jsxs } from 'react/jsx-runtime'; +import { useState, useRef, useCallback } from 'react'; + +const getStyle = (styleProp, fallback, context) => { + if (typeof styleProp === "function") { + return styleProp(context); + } + if (typeof styleProp === "object") { + return styleProp; + } + 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 gallery = { + display: "flex", + flexWrap: "wrap", +}; +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 style; +}; +const tileViewport = ({ item, }) => { + const styles = { + width: item.viewportWidth, + height: item.scaledHeight, + overflow: "hidden", + }; + if (item.nano) { + styles.background = `url(${item.nano})`; + styles.backgroundSize = "cover"; + styles.backgroundPosition = "center center"; + } + if (item.isSelected) { + styles.width = item.viewportWidth - SELECTION_MARGIN * 2; + styles.height = item.scaledHeight - SELECTION_MARGIN * 2; + styles.margin = SELECTION_MARGIN; + } + 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", + 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", + 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", +}); +c + + +const Image = ({ item, thumbnailImageComponent: ThumbnailImageComponent, isSelectable = true, thumbnailStyle, tagStyle, tileViewportStyle, margin, index, onSelect, onClick, }) => { + const styleContext = { item }; + const [hover, setHover] = useState(false); + const thumbnailProps = { + key: index, + "data-testid": "grid-gallery-item_thumbnail", + src: item.src, + alt: item.alt ? item.alt : "", + style: getStyle(thumbnailStyle, thumbnail, styleContext), + }; + const handleCheckButtonClick = (event) => { + if (!isSelectable) { + return; + } + onSelect(index, event); + }; + const handleViewportClick = (event) => { + onClick(index, event); + }; + const thumbnailImageProps = { + item, + index, + margin, + onSelect, + onClick, + isSelectable, + tileViewportStyle, + thumbnailStyle, + tagStyle, + }; + return (jsxs("div", { className: "ReactGridGallery_tile", "data-testid": "grid-gallery-item", onMouseEnter: () => setHover(true), onMouseLeave: () => setHover(false), style: galleryItem({ margin }), children: [jsx("div", { className: "ReactGridGallery_tile-icon-bar", style: tileIconBar, children: jsx(CheckButton, { isSelected: item.isSelected, isVisible: item.isSelected || (isSelectable && hover), onClick: handleCheckButtonClick }) }), !!item.tags && (jsx("div", { className: "ReactGridGallery_tile-bottom-bar", style: bottomBar, children: item.tags.map((tag, index) => (jsx("div", { style: tagItemBlock, children: jsx("span", { style: getStyle(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 && isSelectable, + }) }), jsx("div", { className: "ReactGridGallery_tile-viewport", "data-testid": "grid-gallery-item_viewport", style: getStyle(tileViewportStyle, tileViewport, styleContext), onClick: handleViewportClick, children: ThumbnailImageComponent ? (jsx(ThumbnailImageComponent, { ...thumbnailImageProps, imageProps: thumbnailProps })) : (jsx("img", { ...thumbnailProps })) }), item.thumbnailCaption && (jsx("div", { className: "ReactGridGallery_tile-description", style: tileDescription, children: item.thumbnailCaption }))] })); +}; + +function useContainerWidth(defaultContainerWidth) { + const ref = useRef(null); + const observerRef = useRef(); + const [containerWidth, setContainerWidth] = useState(defaultContainerWidth); + const containerRef = useCallback((node) => { + var _a; + (_a = observerRef.current) === null || _a === void 0 ? void 0 : _a.disconnect(); + observerRef.current = undefined; + ref.current = node; + const updateWidth = () => { + if (!ref.current) { + return; + } + let width = ref.current.clientWidth; + try { + width = ref.current.getBoundingClientRect().width; + } + catch (err) { } + setContainerWidth(Math.floor(width)); + }; + updateWidth(); + if (node && typeof ResizeObserver !== "undefined") { + observerRef.current = new ResizeObserver(updateWidth); + observerRef.current.observe(node); + } + }, []); + return { containerRef, containerWidth }; +} + +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]; + } + let stillToCutOff = protrudingWidth - cutSum; + while (stillToCutOff > 0) { + for (let i in cutOff) { + cutOff[i]++; + stillToCutOff--; + if (stillToCutOff < 0) + break; + } + } + return cutOff; +}; +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; + } + } + return [row, items]; +}; +const getRows = (images, options, rows = []) => { + const [row, imagesLeft] = getRow(images, options); + const nextRows = [...rows, row]; + if (options.maxRows && nextRows.length >= options.maxRows) { + return nextRows; + } + if (imagesLeft.length) { + return getRows(imagesLeft, options, nextRows); + } + 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); +}; + +const Gallery = ({ images, id = "ReactGridGallery", enableImageSelection = true, onSelect = () => { }, rowHeight = 180, maxRows, margin = 2, defaultContainerWidth = 0, onClick = () => { }, tileViewportStyle, thumbnailStyle, tagStyle, thumbnailImageComponent, }) => { + const { containerRef, containerWidth } = useContainerWidth(defaultContainerWidth); + const thumbnails = buildLayoutFlat(images, { + containerWidth, + maxRows, + rowHeight, + margin, + }); + const handleSelect = (index, event) => { + event.preventDefault(); + onSelect(index, images[index], event); + }; + const handleClick = (index, event) => { + onClick(index, images[index], event); + }; + return (jsx("div", { id: id, className: "ReactGridGallery", ref: containerRef, children: jsx("div", { style: gallery, children: thumbnails.map((item, index) => (jsx(Image, { item: item, index: index, margin: margin, height: rowHeight, isSelectable: enableImageSelection, onClick: handleClick, onSelect: handleSelect, tagStyle: tagStyle, tileViewportStyle: tileViewportStyle, thumbnailStyle: thumbnailStyle, thumbnailImageComponent: thumbnailImageComponent }, item.key || index))) }) })); +}; +Gallery.displayName = "Gallery"; + +export { CheckButton, Gallery, buildLayout, buildLayoutFlat }; +//# sourceMappingURL=react-grid-gallery.esm.js.map diff --git a/src/components/react-grid-gallery/dist/react-grid-gallery.esm.js.map b/src/components/react-grid-gallery/dist/react-grid-gallery.esm.js.map new file mode 100644 index 00000000..d64388d4 --- /dev/null +++ b/src/components/react-grid-gallery/dist/react-grid-gallery.esm.js.map @@ -0,0 +1 @@ +{"version":3,"file":"react-grid-gallery.esm.js","sources":["../src/styles.ts","../src/CheckButton.tsx","../src/Image.tsx","../src/useContainerWidth.ts","../src/buildLayout.ts","../src/Gallery.tsx"],"sourcesContent":["import { CSSProperties } from \"react\";\nimport {\n ImageExtended,\n StyleFunction,\n StyleFunctionContext,\n StyleProp,\n} from \"./types\";\n\nexport const getStyle = (\n styleProp: StyleProp | undefined,\n fallback: StyleFunction,\n context: StyleFunctionContext\n): CSSProperties => {\n if (typeof styleProp === \"function\") {\n return styleProp(context);\n }\n if (typeof styleProp === \"object\") {\n return styleProp;\n }\n return fallback(context);\n};\n\nconst rotationTransformMap: Record<number, string> = {\n 3: \"rotate(180deg)\",\n 2: \"rotateY(180deg)\",\n 4: \"rotate(180deg) rotateY(180deg)\",\n 5: \"rotate(270deg) rotateY(180deg)\",\n 6: \"rotate(90deg)\",\n 7: \"rotate(90deg) rotateY(180deg)\",\n 8: \"rotate(270deg)\",\n};\n\nconst SELECTION_MARGIN = 16;\n\nexport const gallery: CSSProperties = {\n display: \"flex\",\n flexWrap: \"wrap\",\n};\n\nexport const thumbnail = ({ item }: { item: ImageExtended }): CSSProperties => {\n const rotationTransformValue = rotationTransformMap[item.orientation];\n\n const style = {\n cursor: \"pointer\",\n maxWidth: \"none\",\n width: item.scaledWidth,\n height: item.scaledHeight,\n marginLeft: item.marginLeft,\n marginTop: 0,\n transform: rotationTransformValue,\n };\n\n if (item.isSelected) {\n const ratio = item.scaledWidth / item.scaledHeight;\n const viewportHeight = item.scaledHeight - SELECTION_MARGIN * 2;\n const viewportWidth = item.viewportWidth - SELECTION_MARGIN * 2;\n\n let height, width;\n if (item.scaledWidth > item.scaledHeight) {\n width = item.scaledWidth - SELECTION_MARGIN * 2;\n height = Math.floor(width / ratio);\n } else {\n height = item.scaledHeight - SELECTION_MARGIN * 2;\n width = Math.floor(height * ratio);\n }\n\n const marginTop = Math.abs(Math.floor((viewportHeight - height) / 2));\n const marginLeft = Math.abs(Math.floor((viewportWidth - width) / 2));\n\n style.width = width;\n style.height = height;\n style.marginLeft = marginLeft === 0 ? 0 : -marginLeft;\n style.marginTop = marginTop === 0 ? 0 : -marginTop;\n }\n\n return style;\n};\n\nexport const tileViewport = ({\n item,\n}: {\n item: ImageExtended;\n}): CSSProperties => {\n const styles: CSSProperties = {\n width: item.viewportWidth,\n height: item.scaledHeight,\n overflow: \"hidden\",\n };\n if (item.nano) {\n styles.background = `url(${item.nano})`;\n styles.backgroundSize = \"cover\";\n styles.backgroundPosition = \"center center\";\n }\n if (item.isSelected) {\n styles.width = item.viewportWidth - SELECTION_MARGIN * 2;\n styles.height = item.scaledHeight - SELECTION_MARGIN * 2;\n styles.margin = SELECTION_MARGIN;\n }\n return styles;\n};\n\nexport const customOverlay = ({\n hover,\n}: {\n hover: boolean;\n}): CSSProperties => ({\n pointerEvents: \"none\",\n opacity: hover ? 1 : 0,\n position: \"absolute\",\n height: \"100%\",\n width: \"100%\",\n});\n\nexport const galleryItem = ({ margin }: { margin: number }): CSSProperties => ({\n margin,\n WebkitUserSelect: \"none\",\n position: \"relative\",\n background: \"#eee\",\n padding: \"0px\",\n});\n\nexport const tileOverlay = ({\n showOverlay,\n}: {\n showOverlay: boolean;\n}): CSSProperties => ({\n pointerEvents: \"none\",\n opacity: 1,\n position: \"absolute\",\n height: \"100%\",\n width: \"100%\",\n background: showOverlay\n ? \"linear-gradient(to bottom,rgba(0,0,0,0.26),transparent 56px,transparent)\"\n : \"none\",\n});\n\nexport const tileIconBar: CSSProperties = {\n pointerEvents: \"none\",\n opacity: 1,\n position: \"absolute\",\n height: \"36px\",\n width: \"100%\",\n};\n\nexport const tileDescription: CSSProperties = {\n background: \"white\",\n width: \"100%\",\n margin: 0,\n userSelect: \"text\",\n WebkitUserSelect: \"text\",\n MozUserSelect: \"text\",\n overflow: \"hidden\",\n};\n\nexport const bottomBar: CSSProperties = {\n padding: \"2px\",\n pointerEvents: \"none\",\n position: \"absolute\",\n minHeight: \"0px\",\n maxHeight: \"160px\",\n width: \"100%\",\n bottom: \"0px\",\n overflow: \"hidden\",\n};\n\nexport const tagItemBlock: CSSProperties = {\n display: \"inline-block\",\n cursor: \"pointer\",\n pointerEvents: \"visible\",\n margin: \"2px\",\n};\n\nexport const tagItem = (): CSSProperties => ({\n display: \"inline\",\n padding: \".2em .6em .3em\",\n fontSize: \"75%\",\n fontWeight: \"600\",\n lineHeight: \"1\",\n color: \"yellow\",\n background: \"rgba(0,0,0,0.65)\",\n textAlign: \"center\",\n whiteSpace: \"nowrap\",\n verticalAlign: \"baseline\",\n borderRadius: \".25em\",\n});\n\nexport const checkButton = ({\n isVisible,\n}: {\n isVisible: boolean;\n}): CSSProperties => ({\n visibility: isVisible ? \"visible\" : \"hidden\",\n background: \"none\",\n float: \"left\",\n width: 36,\n height: 36,\n border: \"none\",\n padding: 6,\n cursor: \"pointer\",\n pointerEvents: \"visible\",\n});\n","import { useState } from \"react\";\nimport * as styles from \"./styles\";\nimport { CheckButtonProps } from \"./types\";\n\nexport const CheckButton = ({\n isSelected = false,\n isVisible = true,\n onClick,\n color = \"#FFFFFFB2\",\n selectedColor = \"#4285F4FF\",\n hoverColor = \"#FFFFFFFF\",\n}: CheckButtonProps): JSX.Element => {\n const [hover, setHover] = useState(false);\n\n const circleStyle = { display: isSelected ? \"block\" : \"none\" };\n const fillColor = isSelected ? selectedColor : hover ? hoverColor : color;\n\n const handleMouseOver = () => setHover(true);\n const handleMouseOut = () => setHover(false);\n\n return (\n <div\n data-testid=\"grid-gallery-item_check-button\"\n title=\"Select\"\n style={styles.checkButton({ isVisible })}\n onClick={onClick}\n onMouseOver={handleMouseOver}\n onMouseOut={handleMouseOut}\n >\n <svg\n fill={fillColor}\n height=\"24\"\n viewBox=\"0 0 24 24\"\n width=\"24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <radialGradient\n id=\"shadow\"\n cx=\"38\"\n cy=\"95.488\"\n r=\"10.488\"\n gradientTransform=\"matrix(1 0 0 -1 -26 109)\"\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop offset=\".832\" stopColor=\"#010101\"></stop>\n <stop offset=\"1\" stopColor=\"#010101\" stopOpacity=\"0\"></stop>\n </radialGradient>\n\n <circle\n style={circleStyle}\n opacity=\".26\"\n fill=\"url(#shadow)\"\n cx=\"12\"\n cy=\"13.512\"\n r=\"10.488\"\n />\n <circle style={circleStyle} fill=\"#FFF\" cx=\"12\" cy=\"12.2\" r=\"8.292\" />\n <path d=\"M0 0h24v24H0z\" fill=\"none\" />\n <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\" />\n </svg>\n </div>\n );\n};\n","import { useState, MouseEvent } from \"react\";\nimport { CheckButton } from \"./CheckButton\";\nimport { ImageExtended, ImageProps } from \"./types\";\nimport * as styles from \"./styles\";\nimport { getStyle } from \"./styles\";\n\nexport const Image = <T extends ImageExtended>({\n item,\n thumbnailImageComponent: ThumbnailImageComponent,\n isSelectable = true,\n thumbnailStyle,\n tagStyle,\n tileViewportStyle,\n margin,\n index,\n onSelect,\n onClick,\n}: ImageProps<T>): JSX.Element => {\n const styleContext = { item };\n\n const [hover, setHover] = useState(false);\n\n const thumbnailProps = {\n key: index,\n \"data-testid\": \"grid-gallery-item_thumbnail\",\n src: item.src,\n alt: item.alt ? item.alt : \"\",\n title: typeof item.caption === \"string\" ? item.caption : null,\n style: getStyle(thumbnailStyle, styles.thumbnail, styleContext),\n };\n\n const handleCheckButtonClick = (event: MouseEvent<HTMLElement>) => {\n if (!isSelectable) {\n return;\n }\n onSelect(index, event);\n };\n\n const handleViewportClick = (event: MouseEvent<HTMLElement>) => {\n onClick(index, event);\n };\n\n const thumbnailImageProps = {\n item,\n index,\n margin,\n onSelect,\n onClick,\n isSelectable,\n tileViewportStyle,\n thumbnailStyle,\n tagStyle,\n };\n\n return (\n <div\n className=\"ReactGridGallery_tile\"\n data-testid=\"grid-gallery-item\"\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={styles.galleryItem({ margin })}\n >\n <div\n className=\"ReactGridGallery_tile-icon-bar\"\n style={styles.tileIconBar}\n >\n <CheckButton\n isSelected={item.isSelected}\n isVisible={item.isSelected || (isSelectable && hover)}\n onClick={handleCheckButtonClick}\n />\n </div>\n\n {!!item.tags && (\n <div\n className=\"ReactGridGallery_tile-bottom-bar\"\n style={styles.bottomBar}\n >\n {item.tags.map((tag, index) => (\n <div\n key={tag.key || index}\n title={tag.title}\n style={styles.tagItemBlock}\n >\n <span style={getStyle(tagStyle, styles.tagItem, styleContext)}>\n {tag.value}\n </span>\n </div>\n ))}\n </div>\n )}\n\n {!!item.customOverlay && (\n <div\n className=\"ReactGridGallery_custom-overlay\"\n style={styles.customOverlay({ hover })}\n >\n {item.customOverlay}\n </div>\n )}\n\n <div\n className=\"ReactGridGallery_tile-overlay\"\n style={styles.tileOverlay({\n showOverlay: hover && !item.isSelected && isSelectable,\n })}\n />\n\n <div\n className=\"ReactGridGallery_tile-viewport\"\n data-testid=\"grid-gallery-item_viewport\"\n style={getStyle(tileViewportStyle, styles.tileViewport, styleContext)}\n onClick={handleViewportClick}\n >\n {ThumbnailImageComponent ? (\n <ThumbnailImageComponent\n {...thumbnailImageProps}\n imageProps={thumbnailProps}\n />\n ) : (\n <img {...thumbnailProps} />\n )}\n </div>\n {item.thumbnailCaption && (\n <div\n className=\"ReactGridGallery_tile-description\"\n style={styles.tileDescription}\n >\n {item.thumbnailCaption}\n </div>\n )}\n </div>\n );\n};\n","import { useRef, useCallback, useState } from \"react\";\n\nexport function useContainerWidth(defaultContainerWidth: number) {\n const ref = useRef<HTMLElement | null>(null);\n const observerRef = useRef<ResizeObserver>();\n\n const [containerWidth, setContainerWidth] = useState(defaultContainerWidth);\n\n const containerRef = useCallback((node: HTMLElement | null) => {\n observerRef.current?.disconnect();\n observerRef.current = undefined;\n\n ref.current = node;\n\n const updateWidth = () => {\n if (!ref.current) {\n return;\n }\n let width = ref.current.clientWidth;\n try {\n width = ref.current.getBoundingClientRect().width;\n } catch (err) {}\n setContainerWidth(Math.floor(width));\n };\n\n updateWidth();\n\n if (node && typeof ResizeObserver !== \"undefined\") {\n observerRef.current = new ResizeObserver(updateWidth);\n observerRef.current.observe(node);\n }\n }, []);\n\n return { containerRef, containerWidth };\n}\n","import {\n ImageExtended,\n Image,\n BuildLayoutOptions,\n ImageExtendedRow,\n} from \"./types\";\n\nconst calculateCutOff = <T extends ImageExtended = ImageExtended>(\n items: T[],\n totalRowWidth: number,\n protrudingWidth: number\n) => {\n const cutOff: number[] = [];\n let cutSum = 0;\n for (let i in items) {\n const item = items[i];\n const fractionOfWidth = item.scaledWidth / totalRowWidth;\n cutOff[i] = Math.floor(fractionOfWidth * protrudingWidth);\n cutSum += cutOff[i];\n }\n\n let stillToCutOff = protrudingWidth - cutSum;\n while (stillToCutOff > 0) {\n for (let i in cutOff) {\n cutOff[i]++;\n stillToCutOff--;\n if (stillToCutOff < 0) break;\n }\n }\n return cutOff;\n};\n\nconst getRow = <T extends Image = Image>(\n images: T[],\n { containerWidth, rowHeight, margin }: BuildLayoutOptions\n): [ImageExtendedRow<T>, T[]] => {\n const row: ImageExtendedRow<T> = [];\n const imgMargin = 2 * margin;\n const items = [...images];\n\n let totalRowWidth = 0;\n while (items.length > 0 && totalRowWidth < containerWidth) {\n const item = items.shift();\n const scaledWidth = Math.floor(rowHeight * (item.width / item.height));\n const extendedItem: ImageExtended<T> = {\n ...item,\n scaledHeight: rowHeight,\n scaledWidth,\n viewportWidth: scaledWidth,\n marginLeft: 0,\n };\n row.push(extendedItem);\n totalRowWidth += extendedItem.scaledWidth + imgMargin;\n }\n\n const protrudingWidth = totalRowWidth - containerWidth;\n if (row.length > 0 && protrudingWidth > 0) {\n const cutoff = calculateCutOff(row, totalRowWidth, protrudingWidth);\n for (const i in row) {\n const pixelsToRemove = cutoff[i];\n const item = row[i];\n item.marginLeft = -Math.abs(Math.floor(pixelsToRemove / 2));\n item.viewportWidth = item.scaledWidth - pixelsToRemove;\n }\n }\n\n return [row, items];\n};\n\nconst getRows = <T extends Image = Image>(\n images: T[],\n options: BuildLayoutOptions,\n rows: ImageExtendedRow<T>[] = []\n): ImageExtendedRow<T>[] => {\n const [row, imagesLeft] = getRow(images, options);\n const nextRows = [...rows, row];\n\n if (options.maxRows && nextRows.length >= options.maxRows) {\n return nextRows;\n }\n if (imagesLeft.length) {\n return getRows(imagesLeft, options, nextRows);\n }\n return nextRows;\n};\n\nexport const buildLayout = <T extends Image = Image>(\n images: T[],\n { containerWidth, maxRows, rowHeight, margin }: BuildLayoutOptions\n): ImageExtendedRow<T>[] => {\n rowHeight = typeof rowHeight === \"undefined\" ? 180 : rowHeight;\n margin = typeof margin === \"undefined\" ? 2 : margin;\n\n if (!images) return [];\n if (!containerWidth) return [];\n\n const options = { containerWidth, maxRows, rowHeight, margin };\n return getRows(images, options);\n};\n\nexport const buildLayoutFlat = <T extends Image = Image>(\n images: T[],\n options: BuildLayoutOptions\n): ImageExtendedRow<T> => {\n const rows = buildLayout(images, options);\n return [].concat.apply([], rows);\n};\n","import { MouseEvent } from \"react\";\nimport { Image } from \"./Image\";\nimport { useContainerWidth } from \"./useContainerWidth\";\nimport { buildLayoutFlat } from \"./buildLayout\";\nimport { Image as ImageInterface, GalleryProps } from \"./types\";\nimport * as styles from \"./styles\";\n\nexport const Gallery = <T extends ImageInterface>({\n images,\n id = \"ReactGridGallery\",\n enableImageSelection = true,\n onSelect = () => {},\n rowHeight = 180,\n maxRows,\n margin = 2,\n defaultContainerWidth = 0,\n onClick = () => {},\n tileViewportStyle,\n thumbnailStyle,\n tagStyle,\n thumbnailImageComponent,\n}: GalleryProps<T>): JSX.Element => {\n const { containerRef, containerWidth } = useContainerWidth(\n defaultContainerWidth\n );\n\n const thumbnails = buildLayoutFlat<T>(images, {\n containerWidth,\n maxRows,\n rowHeight,\n margin,\n });\n\n const handleSelect = (index: number, event: MouseEvent<HTMLElement>) => {\n event.preventDefault();\n onSelect(index, images[index], event);\n };\n\n const handleClick = (index: number, event: MouseEvent<HTMLElement>) => {\n onClick(index, images[index], event);\n };\n\n return (\n <div id={id} className=\"ReactGridGallery\" ref={containerRef}>\n <div style={styles.gallery}>\n {thumbnails.map((item, index) => (\n <Image\n key={item.key || index}\n item={item}\n index={index}\n margin={margin}\n height={rowHeight}\n isSelectable={enableImageSelection}\n onClick={handleClick}\n onSelect={handleSelect}\n tagStyle={tagStyle}\n tileViewportStyle={tileViewportStyle}\n thumbnailStyle={thumbnailStyle}\n thumbnailImageComponent={thumbnailImageComponent}\n />\n ))}\n </div>\n </div>\n );\n};\n\nGallery.displayName = \"Gallery\";\n"],"names":["_jsx","styles.checkButton","_jsxs","styles.thumbnail","styles.galleryItem","styles.tileIconBar","styles.bottomBar","styles.tagItemBlock","styles.tagItem","styles.customOverlay","styles.tileOverlay","styles.tileViewport","styles.tileDescription","styles.gallery"],"mappings":"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"} \ No newline at end of file diff --git a/src/components/react-grid-gallery/dist/react-grid-gallery.umd.js b/src/components/react-grid-gallery/dist/react-grid-gallery.umd.js new file mode 100644 index 00000000..3a4a5f37 --- /dev/null +++ b/src/components/react-grid-gallery/dist/react-grid-gallery.umd.js @@ -0,0 +1,405 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) : + typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactGridGallery = {}, global.React)); +})(this, (function (exports, require$$0) { 'use strict'; + + function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } + + var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0); + + /****************************************************************************** + Copyright (c) Microsoft Corporation. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + ***************************************************************************** */ + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + function __spreadArray(to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); + } + + typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; + }; + + var jsxRuntime = {exports: {}}; + + var reactJsxRuntime_production_min = {}; + + /** + * @license React + * react-jsx-runtime.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + + var hasRequiredReactJsxRuntime_production_min; + + function requireReactJsxRuntime_production_min () { + if (hasRequiredReactJsxRuntime_production_min) return reactJsxRuntime_production_min; + hasRequiredReactJsxRuntime_production_min = 1; + var f=require$$0__default["default"],k=Symbol.for("react.element"),l=Symbol.for("react.fragment"),m=Object.prototype.hasOwnProperty,n=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,p={key:!0,ref:!0,__self:!0,__source:!0}; + function q(c,a,g){var b,d={},e=null,h=null;void 0!==g&&(e=""+g);void 0!==a.key&&(e=""+a.key);void 0!==a.ref&&(h=a.ref);for(b in a)m.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return {$$typeof:k,type:c,key:e,ref:h,props:d,_owner:n.current}}reactJsxRuntime_production_min.Fragment=l;reactJsxRuntime_production_min.jsx=q;reactJsxRuntime_production_min.jsxs=q; + return reactJsxRuntime_production_min; + } + + { + jsxRuntime.exports = requireReactJsxRuntime_production_min(); + } + + var jsxRuntimeExports = jsxRuntime.exports; + + var getStyle = function (styleProp, fallback, context) { + if (typeof styleProp === "function") { + return styleProp(context); + } + if (typeof styleProp === "object") { + return styleProp; + } + return fallback(context); + }; + var 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)", + }; + var SELECTION_MARGIN = 16; + var gallery = { + display: "flex", + flexWrap: "wrap", + }; + var thumbnail = function (_a) { + var item = _a.item; + var rotationTransformValue = rotationTransformMap[item.orientation]; + var style = { + cursor: "pointer", + maxWidth: "none", + width: item.scaledWidth, + height: item.scaledHeight, + marginLeft: item.marginLeft, + marginTop: 0, + transform: rotationTransformValue, + }; + if (item.isSelected) { + var ratio = item.scaledWidth / item.scaledHeight; + var viewportHeight = item.scaledHeight - SELECTION_MARGIN * 2; + var viewportWidth = item.viewportWidth - SELECTION_MARGIN * 2; + var height = void 0, width = void 0; + 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); + } + var marginTop = Math.abs(Math.floor((viewportHeight - height) / 2)); + var 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 style; + }; + var tileViewport = function (_a) { + var item = _a.item; + var styles = { + width: item.viewportWidth, + height: item.scaledHeight, + overflow: "hidden", + }; + if (item.nano) { + styles.background = "url(".concat(item.nano, ")"); + styles.backgroundSize = "cover"; + styles.backgroundPosition = "center center"; + } + if (item.isSelected) { + styles.width = item.viewportWidth - SELECTION_MARGIN * 2; + styles.height = item.scaledHeight - SELECTION_MARGIN * 2; + styles.margin = SELECTION_MARGIN; + } + return styles; + }; + var customOverlay = function (_a) { + var hover = _a.hover; + return ({ + pointerEvents: "none", + opacity: hover ? 1 : 0, + position: "absolute", + height: "100%", + width: "100%", + }); + }; + var galleryItem = function (_a) { + var margin = _a.margin; + return ({ + margin: margin, + WebkitUserSelect: "none", + position: "relative", + background: "#eee", + padding: "0px", + }); + }; + var tileOverlay = function (_a) { + var showOverlay = _a.showOverlay; + return ({ + 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", + }); + }; + var tileIconBar = { + pointerEvents: "none", + opacity: 1, + position: "absolute", + height: "36px", + width: "100%", + }; + var tileDescription = { + background: "white", + width: "100%", + margin: 0, + userSelect: "text", + WebkitUserSelect: "text", + MozUserSelect: "text", + overflow: "hidden", + }; + var bottomBar = { + padding: "2px", + pointerEvents: "none", + position: "absolute", + minHeight: "0px", + maxHeight: "160px", + width: "100%", + bottom: "0px", + overflow: "hidden", + }; + var tagItemBlock = { + display: "inline-block", + cursor: "pointer", + pointerEvents: "visible", + margin: "2px", + }; + var tagItem = function () { 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", + }); }; + + + + var Image = function (_a) { + var item = _a.item, ThumbnailImageComponent = _a.thumbnailImageComponent, _b = _a.isSelectable, isSelectable = _b === void 0 ? true : _b, thumbnailStyle = _a.thumbnailStyle, tagStyle = _a.tagStyle, tileViewportStyle = _a.tileViewportStyle, margin = _a.margin, index = _a.index, onSelect = _a.onSelect, onClick = _a.onClick; + var styleContext = { item: item }; + var _c = require$$0.useState(false), hover = _c[0], setHover = _c[1]; + var thumbnailProps = { + key: index, + "data-testid": "grid-gallery-item_thumbnail", + src: item.src, + alt: item.alt ? item.alt : "", + style: getStyle(thumbnailStyle, thumbnail, styleContext), + }; + var handleCheckButtonClick = function (event) { + if (!isSelectable) { + return; + } + onSelect(index, event); + }; + var handleViewportClick = function (event) { + onClick(index, event); + }; + var thumbnailImageProps = { + item: item, + index: index, + margin: margin, + onSelect: onSelect, + onClick: onClick, + isSelectable: isSelectable, + tileViewportStyle: tileViewportStyle, + thumbnailStyle: thumbnailStyle, + tagStyle: tagStyle, + }; + return (jsxRuntimeExports.jsxs("div", __assign({ className: "ReactGridGallery_tile", "data-testid": "grid-gallery-item", onMouseEnter: function () { return setHover(true); }, onMouseLeave: function () { return setHover(false); }, style: galleryItem({ margin: margin }) }, { children: [jsxRuntimeExports.jsx("div", __assign({ className: "ReactGridGallery_tile-icon-bar", style: tileIconBar }, { children: jsxRuntimeExports.jsx(CheckButton, { isSelected: item.isSelected, isVisible: item.isSelected || (isSelectable && hover), onClick: handleCheckButtonClick }) })), !!item.tags && (jsxRuntimeExports.jsx("div", __assign({ className: "ReactGridGallery_tile-bottom-bar", style: bottomBar }, { children: item.tags.map(function (tag, index) { return (jsxRuntimeExports.jsx("div", __assign({ style: tagItemBlock }, { children: jsxRuntimeExports.jsx("span", __assign({ style: getStyle(tagStyle, tagItem, styleContext) }, { children: tag.value })) }), tag.key || index)); }) }))), !!item.customOverlay && (jsxRuntimeExports.jsx("div", __assign({ className: "ReactGridGallery_custom-overlay", style: customOverlay({ hover: hover }) }, { children: item.customOverlay }))), jsxRuntimeExports.jsx("div", { className: "ReactGridGallery_tile-overlay", style: tileOverlay({ + showOverlay: hover && !item.isSelected && isSelectable, + }) }), jsxRuntimeExports.jsx("div", __assign({ className: "ReactGridGallery_tile-viewport", "data-testid": "grid-gallery-item_viewport", style: getStyle(tileViewportStyle, tileViewport, styleContext), onClick: handleViewportClick }, { children: ThumbnailImageComponent ? (jsxRuntimeExports.jsx(ThumbnailImageComponent, __assign({}, thumbnailImageProps, { imageProps: thumbnailProps }))) : (jsxRuntimeExports.jsx("img", __assign({}, thumbnailProps))) })), item.thumbnailCaption && (jsxRuntimeExports.jsx("div", __assign({ className: "ReactGridGallery_tile-description", style: tileDescription }, { children: item.thumbnailCaption })))] }))); + }; + + function useContainerWidth(defaultContainerWidth) { + var ref = require$$0.useRef(null); + var observerRef = require$$0.useRef(); + var _a = require$$0.useState(defaultContainerWidth), containerWidth = _a[0], setContainerWidth = _a[1]; + var containerRef = require$$0.useCallback(function (node) { + var _a; + (_a = observerRef.current) === null || _a === void 0 ? void 0 : _a.disconnect(); + observerRef.current = undefined; + ref.current = node; + var updateWidth = function () { + if (!ref.current) { + return; + } + var width = ref.current.clientWidth; + try { + width = ref.current.getBoundingClientRect().width; + } + catch (err) { } + setContainerWidth(Math.floor(width)); + }; + updateWidth(); + if (node && typeof ResizeObserver !== "undefined") { + observerRef.current = new ResizeObserver(updateWidth); + observerRef.current.observe(node); + } + }, []); + return { containerRef: containerRef, containerWidth: containerWidth }; + } + + var calculateCutOff = function (items, totalRowWidth, protrudingWidth) { + var cutOff = []; + var cutSum = 0; + for (var i in items) { + var item = items[i]; + var fractionOfWidth = item.scaledWidth / totalRowWidth; + cutOff[i] = Math.floor(fractionOfWidth * protrudingWidth); + cutSum += cutOff[i]; + } + var stillToCutOff = protrudingWidth - cutSum; + while (stillToCutOff > 0) { + for (var i in cutOff) { + cutOff[i]++; + stillToCutOff--; + if (stillToCutOff < 0) + break; + } + } + return cutOff; + }; + var getRow = function (images, _a) { + var containerWidth = _a.containerWidth, rowHeight = _a.rowHeight, margin = _a.margin; + var row = []; + var imgMargin = 2 * margin; + var items = __spreadArray([], images, true); + var totalRowWidth = 0; + while (items.length > 0 && totalRowWidth < containerWidth) { + var item = items.shift(); + var scaledWidth = Math.floor(rowHeight * (item.width / item.height)); + var extendedItem = __assign(__assign({}, item), { scaledHeight: rowHeight, scaledWidth: scaledWidth, viewportWidth: scaledWidth, marginLeft: 0 }); + row.push(extendedItem); + totalRowWidth += extendedItem.scaledWidth + imgMargin; + } + var protrudingWidth = totalRowWidth - containerWidth; + if (row.length > 0 && protrudingWidth > 0) { + var cutoff = calculateCutOff(row, totalRowWidth, protrudingWidth); + for (var i in row) { + var pixelsToRemove = cutoff[i]; + var item = row[i]; + item.marginLeft = -Math.abs(Math.floor(pixelsToRemove / 2)); + item.viewportWidth = item.scaledWidth - pixelsToRemove; + } + } + return [row, items]; + }; + var getRows = function (images, options, rows) { + if (rows === void 0) { rows = []; } + var _a = getRow(images, options), row = _a[0], imagesLeft = _a[1]; + var nextRows = __spreadArray(__spreadArray([], rows, true), [row], false); + if (options.maxRows && nextRows.length >= options.maxRows) { + return nextRows; + } + if (imagesLeft.length) { + return getRows(imagesLeft, options, nextRows); + } + return nextRows; + }; + var buildLayout = function (images, _a) { + var containerWidth = _a.containerWidth, maxRows = _a.maxRows, rowHeight = _a.rowHeight, margin = _a.margin; + rowHeight = typeof rowHeight === "undefined" ? 180 : rowHeight; + margin = typeof margin === "undefined" ? 2 : margin; + if (!images) + return []; + if (!containerWidth) + return []; + var options = { containerWidth: containerWidth, maxRows: maxRows, rowHeight: rowHeight, margin: margin }; + return getRows(images, options); + }; + var buildLayoutFlat = function (images, options) { + var rows = buildLayout(images, options); + return [].concat.apply([], rows); + }; + + var Gallery = function (_a) { + var images = _a.images, _b = _a.id, id = _b === void 0 ? "ReactGridGallery" : _b, _c = _a.enableImageSelection, enableImageSelection = _c === void 0 ? true : _c, _d = _a.onSelect, onSelect = _d === void 0 ? function () { } : _d, _e = _a.rowHeight, rowHeight = _e === void 0 ? 180 : _e, maxRows = _a.maxRows, _f = _a.margin, margin = _f === void 0 ? 2 : _f, _g = _a.defaultContainerWidth, defaultContainerWidth = _g === void 0 ? 0 : _g, _h = _a.onClick, onClick = _h === void 0 ? function () { } : _h, tileViewportStyle = _a.tileViewportStyle, thumbnailStyle = _a.thumbnailStyle, tagStyle = _a.tagStyle, thumbnailImageComponent = _a.thumbnailImageComponent; + var _j = useContainerWidth(defaultContainerWidth), containerRef = _j.containerRef, containerWidth = _j.containerWidth; + var thumbnails = buildLayoutFlat(images, { + containerWidth: containerWidth, + maxRows: maxRows, + rowHeight: rowHeight, + margin: margin, + }); + var handleSelect = function (index, event) { + event.preventDefault(); + onSelect(index, images[index], event); + }; + var handleClick = function (index, event) { + onClick(index, images[index], event); + }; + return (jsxRuntimeExports.jsx("div", __assign({ id: id, className: "ReactGridGallery", ref: containerRef }, { children: jsxRuntimeExports.jsx("div", __assign({ style: gallery }, { children: thumbnails.map(function (item, index) { return (jsxRuntimeExports.jsx(Image, { item: item, index: index, margin: margin, height: rowHeight, isSelectable: enableImageSelection, onClick: handleClick, onSelect: handleSelect, tagStyle: tagStyle, tileViewportStyle: tileViewportStyle, thumbnailStyle: thumbnailStyle, thumbnailImageComponent: thumbnailImageComponent }, item.key || index)); }) })) }))); + }; + Gallery.displayName = "Gallery"; + + exports.CheckButton = CheckButton; + exports.Gallery = Gallery; + exports.buildLayout = buildLayout; + exports.buildLayoutFlat = buildLayoutFlat; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); +//# sourceMappingURL=react-grid-gallery.umd.js.map diff --git a/src/components/react-grid-gallery/dist/react-grid-gallery.umd.js.map b/src/components/react-grid-gallery/dist/react-grid-gallery.umd.js.map new file mode 100644 index 00000000..6da36a9e --- /dev/null +++ b/src/components/react-grid-gallery/dist/react-grid-gallery.umd.js.map @@ -0,0 +1 @@ +{"version":3,"file":"react-grid-gallery.umd.js","sources":["../node_modules/react/cjs/react-jsx-runtime.production.min.js","../node_modules/react/jsx-runtime.js","../src/styles.ts","../src/CheckButton.tsx","../src/Image.tsx","../src/useContainerWidth.ts","../src/buildLayout.ts","../src/Gallery.tsx"],"sourcesContent":["/**\n * @license React\n * react-jsx-runtime.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';var f=require(\"react\"),k=Symbol.for(\"react.element\"),l=Symbol.for(\"react.fragment\"),m=Object.prototype.hasOwnProperty,n=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,p={key:!0,ref:!0,__self:!0,__source:!0};\nfunction q(c,a,g){var b,d={},e=null,h=null;void 0!==g&&(e=\"\"+g);void 0!==a.key&&(e=\"\"+a.key);void 0!==a.ref&&(h=a.ref);for(b in a)m.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return{$$typeof:k,type:c,key:e,ref:h,props:d,_owner:n.current}}exports.Fragment=l;exports.jsx=q;exports.jsxs=q;\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.min.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","import { CSSProperties } from \"react\";\nimport {\n ImageExtended,\n StyleFunction,\n StyleFunctionContext,\n StyleProp,\n} from \"./types\";\n\nexport const getStyle = (\n styleProp: StyleProp | undefined,\n fallback: StyleFunction,\n context: StyleFunctionContext\n): CSSProperties => {\n if (typeof styleProp === \"function\") {\n return styleProp(context);\n }\n if (typeof styleProp === \"object\") {\n return styleProp;\n }\n return fallback(context);\n};\n\nconst rotationTransformMap: Record<number, string> = {\n 3: \"rotate(180deg)\",\n 2: \"rotateY(180deg)\",\n 4: \"rotate(180deg) rotateY(180deg)\",\n 5: \"rotate(270deg) rotateY(180deg)\",\n 6: \"rotate(90deg)\",\n 7: \"rotate(90deg) rotateY(180deg)\",\n 8: \"rotate(270deg)\",\n};\n\nconst SELECTION_MARGIN = 16;\n\nexport const gallery: CSSProperties = {\n display: \"flex\",\n flexWrap: \"wrap\",\n};\n\nexport const thumbnail = ({ item }: { item: ImageExtended }): CSSProperties => {\n const rotationTransformValue = rotationTransformMap[item.orientation];\n\n const style = {\n cursor: \"pointer\",\n maxWidth: \"none\",\n width: item.scaledWidth,\n height: item.scaledHeight,\n marginLeft: item.marginLeft,\n marginTop: 0,\n transform: rotationTransformValue,\n };\n\n if (item.isSelected) {\n const ratio = item.scaledWidth / item.scaledHeight;\n const viewportHeight = item.scaledHeight - SELECTION_MARGIN * 2;\n const viewportWidth = item.viewportWidth - SELECTION_MARGIN * 2;\n\n let height, width;\n if (item.scaledWidth > item.scaledHeight) {\n width = item.scaledWidth - SELECTION_MARGIN * 2;\n height = Math.floor(width / ratio);\n } else {\n height = item.scaledHeight - SELECTION_MARGIN * 2;\n width = Math.floor(height * ratio);\n }\n\n const marginTop = Math.abs(Math.floor((viewportHeight - height) / 2));\n const marginLeft = Math.abs(Math.floor((viewportWidth - width) / 2));\n\n style.width = width;\n style.height = height;\n style.marginLeft = marginLeft === 0 ? 0 : -marginLeft;\n style.marginTop = marginTop === 0 ? 0 : -marginTop;\n }\n\n return style;\n};\n\nexport const tileViewport = ({\n item,\n}: {\n item: ImageExtended;\n}): CSSProperties => {\n const styles: CSSProperties = {\n width: item.viewportWidth,\n height: item.scaledHeight,\n overflow: \"hidden\",\n };\n if (item.nano) {\n styles.background = `url(${item.nano})`;\n styles.backgroundSize = \"cover\";\n styles.backgroundPosition = \"center center\";\n }\n if (item.isSelected) {\n styles.width = item.viewportWidth - SELECTION_MARGIN * 2;\n styles.height = item.scaledHeight - SELECTION_MARGIN * 2;\n styles.margin = SELECTION_MARGIN;\n }\n return styles;\n};\n\nexport const customOverlay = ({\n hover,\n}: {\n hover: boolean;\n}): CSSProperties => ({\n pointerEvents: \"none\",\n opacity: hover ? 1 : 0,\n position: \"absolute\",\n height: \"100%\",\n width: \"100%\",\n});\n\nexport const galleryItem = ({ margin }: { margin: number }): CSSProperties => ({\n margin,\n WebkitUserSelect: \"none\",\n position: \"relative\",\n background: \"#eee\",\n padding: \"0px\",\n});\n\nexport const tileOverlay = ({\n showOverlay,\n}: {\n showOverlay: boolean;\n}): CSSProperties => ({\n pointerEvents: \"none\",\n opacity: 1,\n position: \"absolute\",\n height: \"100%\",\n width: \"100%\",\n background: showOverlay\n ? \"linear-gradient(to bottom,rgba(0,0,0,0.26),transparent 56px,transparent)\"\n : \"none\",\n});\n\nexport const tileIconBar: CSSProperties = {\n pointerEvents: \"none\",\n opacity: 1,\n position: \"absolute\",\n height: \"36px\",\n width: \"100%\",\n};\n\nexport const tileDescription: CSSProperties = {\n background: \"white\",\n width: \"100%\",\n margin: 0,\n userSelect: \"text\",\n WebkitUserSelect: \"text\",\n MozUserSelect: \"text\",\n overflow: \"hidden\",\n};\n\nexport const bottomBar: CSSProperties = {\n padding: \"2px\",\n pointerEvents: \"none\",\n position: \"absolute\",\n minHeight: \"0px\",\n maxHeight: \"160px\",\n width: \"100%\",\n bottom: \"0px\",\n overflow: \"hidden\",\n};\n\nexport const tagItemBlock: CSSProperties = {\n display: \"inline-block\",\n cursor: \"pointer\",\n pointerEvents: \"visible\",\n margin: \"2px\",\n};\n\nexport const tagItem = (): CSSProperties => ({\n display: \"inline\",\n padding: \".2em .6em .3em\",\n fontSize: \"75%\",\n fontWeight: \"600\",\n lineHeight: \"1\",\n color: \"yellow\",\n background: \"rgba(0,0,0,0.65)\",\n textAlign: \"center\",\n whiteSpace: \"nowrap\",\n verticalAlign: \"baseline\",\n borderRadius: \".25em\",\n});\n\nexport const checkButton = ({\n isVisible,\n}: {\n isVisible: boolean;\n}): CSSProperties => ({\n visibility: isVisible ? \"visible\" : \"hidden\",\n background: \"none\",\n float: \"left\",\n width: 36,\n height: 36,\n border: \"none\",\n padding: 6,\n cursor: \"pointer\",\n pointerEvents: \"visible\",\n});\n","import { useState } from \"react\";\nimport * as styles from \"./styles\";\nimport { CheckButtonProps } from \"./types\";\n\nexport const CheckButton = ({\n isSelected = false,\n isVisible = true,\n onClick,\n color = \"#FFFFFFB2\",\n selectedColor = \"#4285F4FF\",\n hoverColor = \"#FFFFFFFF\",\n}: CheckButtonProps): JSX.Element => {\n const [hover, setHover] = useState(false);\n\n const circleStyle = { display: isSelected ? \"block\" : \"none\" };\n const fillColor = isSelected ? selectedColor : hover ? hoverColor : color;\n\n const handleMouseOver = () => setHover(true);\n const handleMouseOut = () => setHover(false);\n\n return (\n <div\n data-testid=\"grid-gallery-item_check-button\"\n title=\"Select\"\n style={styles.checkButton({ isVisible })}\n onClick={onClick}\n onMouseOver={handleMouseOver}\n onMouseOut={handleMouseOut}\n >\n <svg\n fill={fillColor}\n height=\"24\"\n viewBox=\"0 0 24 24\"\n width=\"24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <radialGradient\n id=\"shadow\"\n cx=\"38\"\n cy=\"95.488\"\n r=\"10.488\"\n gradientTransform=\"matrix(1 0 0 -1 -26 109)\"\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop offset=\".832\" stopColor=\"#010101\"></stop>\n <stop offset=\"1\" stopColor=\"#010101\" stopOpacity=\"0\"></stop>\n </radialGradient>\n\n <circle\n style={circleStyle}\n opacity=\".26\"\n fill=\"url(#shadow)\"\n cx=\"12\"\n cy=\"13.512\"\n r=\"10.488\"\n />\n <circle style={circleStyle} fill=\"#FFF\" cx=\"12\" cy=\"12.2\" r=\"8.292\" />\n <path d=\"M0 0h24v24H0z\" fill=\"none\" />\n <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\" />\n </svg>\n </div>\n );\n};\n","import { useState, MouseEvent } from \"react\";\nimport { CheckButton } from \"./CheckButton\";\nimport { ImageExtended, ImageProps } from \"./types\";\nimport * as styles from \"./styles\";\nimport { getStyle } from \"./styles\";\n\nexport const Image = <T extends ImageExtended>({\n item,\n thumbnailImageComponent: ThumbnailImageComponent,\n isSelectable = true,\n thumbnailStyle,\n tagStyle,\n tileViewportStyle,\n margin,\n index,\n onSelect,\n onClick,\n}: ImageProps<T>): JSX.Element => {\n const styleContext = { item };\n\n const [hover, setHover] = useState(false);\n\n const thumbnailProps = {\n key: index,\n \"data-testid\": \"grid-gallery-item_thumbnail\",\n src: item.src,\n alt: item.alt ? item.alt : \"\",\n title: typeof item.caption === \"string\" ? item.caption : null,\n style: getStyle(thumbnailStyle, styles.thumbnail, styleContext),\n };\n\n const handleCheckButtonClick = (event: MouseEvent<HTMLElement>) => {\n if (!isSelectable) {\n return;\n }\n onSelect(index, event);\n };\n\n const handleViewportClick = (event: MouseEvent<HTMLElement>) => {\n onClick(index, event);\n };\n\n const thumbnailImageProps = {\n item,\n index,\n margin,\n onSelect,\n onClick,\n isSelectable,\n tileViewportStyle,\n thumbnailStyle,\n tagStyle,\n };\n\n return (\n <div\n className=\"ReactGridGallery_tile\"\n data-testid=\"grid-gallery-item\"\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={styles.galleryItem({ margin })}\n >\n <div\n className=\"ReactGridGallery_tile-icon-bar\"\n style={styles.tileIconBar}\n >\n <CheckButton\n isSelected={item.isSelected}\n isVisible={item.isSelected || (isSelectable && hover)}\n onClick={handleCheckButtonClick}\n />\n </div>\n\n {!!item.tags && (\n <div\n className=\"ReactGridGallery_tile-bottom-bar\"\n style={styles.bottomBar}\n >\n {item.tags.map((tag, index) => (\n <div\n key={tag.key || index}\n title={tag.title}\n style={styles.tagItemBlock}\n >\n <span style={getStyle(tagStyle, styles.tagItem, styleContext)}>\n {tag.value}\n </span>\n </div>\n ))}\n </div>\n )}\n\n {!!item.customOverlay && (\n <div\n className=\"ReactGridGallery_custom-overlay\"\n style={styles.customOverlay({ hover })}\n >\n {item.customOverlay}\n </div>\n )}\n\n <div\n className=\"ReactGridGallery_tile-overlay\"\n style={styles.tileOverlay({\n showOverlay: hover && !item.isSelected && isSelectable,\n })}\n />\n\n <div\n className=\"ReactGridGallery_tile-viewport\"\n data-testid=\"grid-gallery-item_viewport\"\n style={getStyle(tileViewportStyle, styles.tileViewport, styleContext)}\n onClick={handleViewportClick}\n >\n {ThumbnailImageComponent ? (\n <ThumbnailImageComponent\n {...thumbnailImageProps}\n imageProps={thumbnailProps}\n />\n ) : (\n <img {...thumbnailProps} />\n )}\n </div>\n {item.thumbnailCaption && (\n <div\n className=\"ReactGridGallery_tile-description\"\n style={styles.tileDescription}\n >\n {item.thumbnailCaption}\n </div>\n )}\n </div>\n );\n};\n","import { useRef, useCallback, useState } from \"react\";\n\nexport function useContainerWidth(defaultContainerWidth: number) {\n const ref = useRef<HTMLElement | null>(null);\n const observerRef = useRef<ResizeObserver>();\n\n const [containerWidth, setContainerWidth] = useState(defaultContainerWidth);\n\n const containerRef = useCallback((node: HTMLElement | null) => {\n observerRef.current?.disconnect();\n observerRef.current = undefined;\n\n ref.current = node;\n\n const updateWidth = () => {\n if (!ref.current) {\n return;\n }\n let width = ref.current.clientWidth;\n try {\n width = ref.current.getBoundingClientRect().width;\n } catch (err) {}\n setContainerWidth(Math.floor(width));\n };\n\n updateWidth();\n\n if (node && typeof ResizeObserver !== \"undefined\") {\n observerRef.current = new ResizeObserver(updateWidth);\n observerRef.current.observe(node);\n }\n }, []);\n\n return { containerRef, containerWidth };\n}\n","import {\n ImageExtended,\n Image,\n BuildLayoutOptions,\n ImageExtendedRow,\n} from \"./types\";\n\nconst calculateCutOff = <T extends ImageExtended = ImageExtended>(\n items: T[],\n totalRowWidth: number,\n protrudingWidth: number\n) => {\n const cutOff: number[] = [];\n let cutSum = 0;\n for (let i in items) {\n const item = items[i];\n const fractionOfWidth = item.scaledWidth / totalRowWidth;\n cutOff[i] = Math.floor(fractionOfWidth * protrudingWidth);\n cutSum += cutOff[i];\n }\n\n let stillToCutOff = protrudingWidth - cutSum;\n while (stillToCutOff > 0) {\n for (let i in cutOff) {\n cutOff[i]++;\n stillToCutOff--;\n if (stillToCutOff < 0) break;\n }\n }\n return cutOff;\n};\n\nconst getRow = <T extends Image = Image>(\n images: T[],\n { containerWidth, rowHeight, margin }: BuildLayoutOptions\n): [ImageExtendedRow<T>, T[]] => {\n const row: ImageExtendedRow<T> = [];\n const imgMargin = 2 * margin;\n const items = [...images];\n\n let totalRowWidth = 0;\n while (items.length > 0 && totalRowWidth < containerWidth) {\n const item = items.shift();\n const scaledWidth = Math.floor(rowHeight * (item.width / item.height));\n const extendedItem: ImageExtended<T> = {\n ...item,\n scaledHeight: rowHeight,\n scaledWidth,\n viewportWidth: scaledWidth,\n marginLeft: 0,\n };\n row.push(extendedItem);\n totalRowWidth += extendedItem.scaledWidth + imgMargin;\n }\n\n const protrudingWidth = totalRowWidth - containerWidth;\n if (row.length > 0 && protrudingWidth > 0) {\n const cutoff = calculateCutOff(row, totalRowWidth, protrudingWidth);\n for (const i in row) {\n const pixelsToRemove = cutoff[i];\n const item = row[i];\n item.marginLeft = -Math.abs(Math.floor(pixelsToRemove / 2));\n item.viewportWidth = item.scaledWidth - pixelsToRemove;\n }\n }\n\n return [row, items];\n};\n\nconst getRows = <T extends Image = Image>(\n images: T[],\n options: BuildLayoutOptions,\n rows: ImageExtendedRow<T>[] = []\n): ImageExtendedRow<T>[] => {\n const [row, imagesLeft] = getRow(images, options);\n const nextRows = [...rows, row];\n\n if (options.maxRows && nextRows.length >= options.maxRows) {\n return nextRows;\n }\n if (imagesLeft.length) {\n return getRows(imagesLeft, options, nextRows);\n }\n return nextRows;\n};\n\nexport const buildLayout = <T extends Image = Image>(\n images: T[],\n { containerWidth, maxRows, rowHeight, margin }: BuildLayoutOptions\n): ImageExtendedRow<T>[] => {\n rowHeight = typeof rowHeight === \"undefined\" ? 180 : rowHeight;\n margin = typeof margin === \"undefined\" ? 2 : margin;\n\n if (!images) return [];\n if (!containerWidth) return [];\n\n const options = { containerWidth, maxRows, rowHeight, margin };\n return getRows(images, options);\n};\n\nexport const buildLayoutFlat = <T extends Image = Image>(\n images: T[],\n options: BuildLayoutOptions\n): ImageExtendedRow<T> => {\n const rows = buildLayout(images, options);\n return [].concat.apply([], rows);\n};\n","import { MouseEvent } from \"react\";\nimport { Image } from \"./Image\";\nimport { useContainerWidth } from \"./useContainerWidth\";\nimport { buildLayoutFlat } from \"./buildLayout\";\nimport { Image as ImageInterface, GalleryProps } from \"./types\";\nimport * as styles from \"./styles\";\n\nexport const Gallery = <T extends ImageInterface>({\n images,\n id = \"ReactGridGallery\",\n enableImageSelection = true,\n onSelect = () => {},\n rowHeight = 180,\n maxRows,\n margin = 2,\n defaultContainerWidth = 0,\n onClick = () => {},\n tileViewportStyle,\n thumbnailStyle,\n tagStyle,\n thumbnailImageComponent,\n}: GalleryProps<T>): JSX.Element => {\n const { containerRef, containerWidth } = useContainerWidth(\n defaultContainerWidth\n );\n\n const thumbnails = buildLayoutFlat<T>(images, {\n containerWidth,\n maxRows,\n rowHeight,\n margin,\n });\n\n const handleSelect = (index: number, event: MouseEvent<HTMLElement>) => {\n event.preventDefault();\n onSelect(index, images[index], event);\n };\n\n const handleClick = (index: number, event: MouseEvent<HTMLElement>) => {\n onClick(index, images[index], event);\n };\n\n return (\n <div id={id} className=\"ReactGridGallery\" ref={containerRef}>\n <div style={styles.gallery}>\n {thumbnails.map((item, index) => (\n <Image\n key={item.key || index}\n item={item}\n index={index}\n margin={margin}\n height={rowHeight}\n isSelectable={enableImageSelection}\n onClick={handleClick}\n onSelect={handleSelect}\n tagStyle={tagStyle}\n tileViewportStyle={tileViewportStyle}\n thumbnailStyle={thumbnailStyle}\n thumbnailImageComponent={thumbnailImageComponent}\n />\n ))}\n </div>\n </div>\n );\n};\n\nGallery.displayName = \"Gallery\";\n"],"names":["require$$0","jsxRuntimeModule","useState","_jsx","styles.checkButton","_jsxs","styles.thumbnail","styles.galleryItem","styles.tileIconBar","styles.bottomBar","styles.tagItemBlock","styles.tagItem","styles.customOverlay","styles.tileOverlay","styles.tileViewport","styles.tileDescription","useRef","useCallback","styles.gallery"],"mappings":"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"} \ No newline at end of file diff --git a/src/components/react-grid-gallery/package.json b/src/components/react-grid-gallery/package.json new file mode 100644 index 00000000..87dbf721 --- /dev/null +++ b/src/components/react-grid-gallery/package.json @@ -0,0 +1,90 @@ +{ + "name": "react-grid-gallery", + "version": "1.0.1", + "description": "Justified gallery component for React.", + "types": "dist/react-grid-gallery.d.ts", + "main": "dist/react-grid-gallery.cjs.js", + "module": "dist/react-grid-gallery.esm.js", + "browser": "dist/react-grid-gallery.umd.js", + "files": [ + "dist", + "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": { + "prepublishOnly": "npm run build", + "clean": "rimraf dist && rimraf node_modules/.cache", + "rollup:build": "rollup -c", + "watch": "rollup -c -w", + "build": "npm run clean && npm run rollup:build", + "test": "jest", + "test:unit": "jest --testPathIgnorePatterns=\\.e2e\\.test\\.js", + "test:e2e": "jest --testPathPattern=\\.e2e\\.test\\.js" + }, + "peerDependencies": { + "react": ">=16.14.0" + }, + "devDependencies": { + "@babel/core": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-react": "^7.22.15", + "@babel/preset-typescript": "^7.23.2", + "@rollup/plugin-babel": "^6.0.4", + "@rollup/plugin-commonjs": "^25.0.5", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-replace": "^5.0.3", + "@testing-library/jest-dom": "^6.1.4", + "@testing-library/react": "^14.0.0", + "@types/jest": "^29.5.5", + "@types/jest-environment-puppeteer": "^5.0.4", + "@types/jest-image-snapshot": "^6.2.1", + "@types/react": "^18.2.28", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "jest-image-snapshot": "^6.2.0", + "jest-puppeteer": "^9.0.1", + "puppeteer": "^21.3.8", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "rimraf": "^5.0.5", + "rollup": "^2.79.1", + "rollup-plugin-dts": "^4.2.2", + "rollup-plugin-peer-deps-external": "^2.2.4", + "rollup-plugin-sourcemaps": "^0.6.3", + "rollup-plugin-typescript2": "^0.36.0", + "typescript": "^4.8.2" + }, + "repository": { + "type": "git", + "url": "https://github.com/benhowell/react-grid-gallery.git" + }, + "keywords": [ + "react", + "react-component", + "image", + "images", + "photo", + "photos", + "gallery", + "select", + "selectable", + "justified", + "tags", + "tagging", + "EXIF", + "image gallery", + "photo gallery" + ], + "author": "Ben Howell", + "license": "MIT", + "bugs": { + "url": "https://github.com/benhowell/react-grid-gallery/issues" + }, + "homepage": "https://benhowell.github.io/react-grid-gallery/" +} diff --git a/src/components/react-grid-gallery/src/Gallery.tsx b/src/components/react-grid-gallery/src/Gallery.tsx new file mode 100755 index 00000000..b23b703e --- /dev/null +++ b/src/components/react-grid-gallery/src/Gallery.tsx @@ -0,0 +1,67 @@ +import { MouseEvent } from "react"; +import { Image } from "./Image"; +import { useContainerWidth } from "./useContainerWidth"; +import { buildLayoutFlat } from "./buildLayout"; +import { Image as ImageInterface, GalleryProps } from "./types"; +import * as styles from "./styles"; + +export const Gallery = <T extends ImageInterface>({ + images, + id = "ReactGridGallery", + enableImageSelection = true, + onSelect = () => {}, + rowHeight = 180, + maxRows, + margin = 2, + defaultContainerWidth = 0, + onClick = () => {}, + tileViewportStyle, + thumbnailStyle, + tagStyle, + thumbnailImageComponent, +}: GalleryProps<T>): JSX.Element => { + const { containerRef, containerWidth } = useContainerWidth( + defaultContainerWidth + ); + + const thumbnails = buildLayoutFlat<T>(images, { + containerWidth, + maxRows, + rowHeight, + margin, + }); + + const handleSelect = (index: number, event: MouseEvent<HTMLElement>) => { + event.preventDefault(); + onSelect(index, images[index], event); + }; + + const handleClick = (index: number, event: MouseEvent<HTMLElement>) => { + onClick(index, images[index], event); + }; + + return ( + <div id={id} className="ReactGridGallery" ref={containerRef}> + <div style={styles.gallery}> + {thumbnails.map((item, index) => ( + <Image + key={item.key || index} + item={item} + index={index} + margin={margin} + height={rowHeight} + isSelectable={enableImageSelection} + onClick={handleClick} + onSelect={handleSelect} + tagStyle={tagStyle} + tileViewportStyle={tileViewportStyle} + thumbnailStyle={thumbnailStyle} + thumbnailImageComponent={thumbnailImageComponent} + /> + ))} + </div> + </div> + ); +}; + +Gallery.displayName = "Gallery"; diff --git a/src/components/react-grid-gallery/src/Image.tsx b/src/components/react-grid-gallery/src/Image.tsx new file mode 100755 index 00000000..e768b795 --- /dev/null +++ b/src/components/react-grid-gallery/src/Image.tsx @@ -0,0 +1,119 @@ +import { useState, MouseEvent } from "react"; +import { ImageExtended, ImageProps } from "./types"; +import * as styles from "./styles"; + +export const Image = <T extends ImageExtended>({ + item, + thumbnailImageComponent: ThumbnailImageComponent, + isSelectable = true, + thumbnailStyle, + tagStyle, + tileViewportStyle, + margin, + index, + onSelect, + onClick, +}: ImageProps<T>): JSX.Element => { + + const [hover, setHover] = useState(false); + + const thumbnailProps = { + key: index, + "data-testid": "grid-gallery-item_thumbnail", + src: item.src, + alt: item.alt ? item.alt : "", + }; + + + + const handleViewportClick = (event: MouseEvent<HTMLElement>) => { + onClick(index, event); + }; + + const thumbnailImageProps = { + item, + index, + margin, + onSelect, + onClick, + isSelectable, + tileViewportStyle, + thumbnailStyle, + tagStyle, + }; + + return ( + <div + className="ReactGridGallery_tile" + data-testid="grid-gallery-item" + onMouseEnter={() => setHover(true)} + onMouseLeave={() => setHover(false)} + style={styles.galleryItem({ margin })} + > + <div + className="ReactGridGallery_tile-icon-bar" + style={styles.tileIconBar} + > + + </div> + + {!!item.tags && ( + <div + className="ReactGridGallery_tile-bottom-bar" + style={styles.bottomBar} + > + {item.tags.map((tag, index) => ( + <div + key={tag.key || index} + + style={styles.tagItemBlock} + > + <span> + {tag.value} + </span> + </div> + ))} + </div> + )} + + {!!item.customOverlay && ( + <div + className="ReactGridGallery_custom-overlay" + style={styles.customOverlay({ hover })} + > + {item.customOverlay} + </div> + )} + + <div + className="ReactGridGallery_tile-overlay" + style={styles.tileOverlay({ + showOverlay: hover && !item.isSelected && isSelectable, + })} + /> + + <div + className="ReactGridGallery_tile-viewport" + data-testid="grid-gallery-item_viewport" + onClick={handleViewportClick} + > + {ThumbnailImageComponent ? ( + <ThumbnailImageComponent + {...thumbnailImageProps} + imageProps={thumbnailProps} + /> + ) : ( + <img {...thumbnailProps} /> + )} + </div> + {item.thumbnailCaption && ( + <div + className="ReactGridGallery_tile-description" + style={styles.tileDescription} + > + {item.thumbnailCaption} + </div> + )} + </div> + ); +}; diff --git a/src/components/react-grid-gallery/src/buildLayout.ts b/src/components/react-grid-gallery/src/buildLayout.ts new file mode 100644 index 00000000..532983bd --- /dev/null +++ b/src/components/react-grid-gallery/src/buildLayout.ts @@ -0,0 +1,110 @@ +import { + ImageExtended, + Image, + BuildLayoutOptions, + ImageExtendedRow, +} from "./types"; + +const calculateCutOff = <T extends ImageExtended>( + items: T[], + totalRowWidth: number, + protrudingWidth: number +) => { + const cutOff: number[] = []; + 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]; + } + + let stillToCutOff = protrudingWidth - cutSum; + while (stillToCutOff > 0) { + for (let i in cutOff) { + cutOff[i]++; + stillToCutOff--; + if (stillToCutOff < 0) break; + } + } + return cutOff; +}; + +const getRow = <T extends Image = Image>( + images: T[], + { containerWidth, rowHeight, margin }: BuildLayoutOptions +): [ImageExtendedRow<Image>, T[]] => { + const row: ImageExtendedRow<Image> = []; + 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: ImageExtended<Image> = { + src: item!.src, + width: item!.width, + height: item!.height, + 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; + } + } + + return [row, items]; +}; + +const getRows = <T extends Image = Image>( + images: Image[], + options: BuildLayoutOptions, + rows: ImageExtendedRow<Image>[] = [] +): ImageExtendedRow<Image>[] => { + const [row, imagesLeft] = getRow(images, options); + const nextRows = [...rows, row]; + + if (options.maxRows && nextRows.length >= options.maxRows) { + return nextRows; + } + if (imagesLeft.length) { + return getRows(imagesLeft, options, nextRows); + } + return nextRows; +}; + +export const buildLayout = <T extends Image = Image>( + images: Image[], + { containerWidth, maxRows, rowHeight, margin }: BuildLayoutOptions +): ImageExtendedRow<Image>[] => { + 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); +}; + +export const buildLayoutFlat = <T extends Image = Image>( + images: T[], + options: BuildLayoutOptions +): ImageExtendedRow<Image>[] => { + const rows = buildLayout(images, options); + return rows; + +} diff --git a/src/components/react-grid-gallery/src/index.ts b/src/components/react-grid-gallery/src/index.ts new file mode 100644 index 00000000..798c683f --- /dev/null +++ b/src/components/react-grid-gallery/src/index.ts @@ -0,0 +1,3 @@ +export * from "./types"; +export { Gallery } from "./Gallery"; +export { buildLayout, buildLayoutFlat } from "./buildLayout"; diff --git a/src/components/react-grid-gallery/src/styles.ts b/src/components/react-grid-gallery/src/styles.ts new file mode 100644 index 00000000..fe09b602 --- /dev/null +++ b/src/components/react-grid-gallery/src/styles.ts @@ -0,0 +1,201 @@ +import { CSSProperties } from "react"; +import { + ImageExtended, + StyleFunction, + StyleFunctionContext, + StyleProp, +} from "./types"; + +export const getStyle = ( + styleProp: StyleProp, + fallback: StyleFunction, + context: StyleFunctionContext +): CSSProperties => { + if (typeof styleProp === "function") { + return styleProp(context); + } + if (typeof styleProp === "object") { + return styleProp; + } + return fallback! (context); +}; + +const rotationTransformMap: Record<number, string> = { + 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; + +export const gallery: CSSProperties = { + display: "flex", + flexWrap: "wrap", +}; + +export const thumbnail = ({ item }: { item: ImageExtended }): CSSProperties => { + 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 style; +}; + +export const tileViewport = ({ + item, +}: { + item: ImageExtended; +}): CSSProperties => { + const styles: CSSProperties = { + width: item.viewportWidth, + height: item.scaledHeight, + overflow: "hidden", + }; + if (item.nano) { + styles.background = `url(${item.nano})`; + styles.backgroundSize = "cover"; + styles.backgroundPosition = "center center"; + } + if (item.isSelected) { + styles.width = item.viewportWidth - SELECTION_MARGIN * 2; + styles.height = item.scaledHeight - SELECTION_MARGIN * 2; + styles.margin = SELECTION_MARGIN; + } + return styles; +}; + +export const customOverlay = ({ + hover, +}: { + hover: boolean; +}): CSSProperties => ({ + pointerEvents: "none", + opacity: hover ? 1 : 0, + position: "absolute", + height: "100%", + width: "100%", +}); + +export const galleryItem = ({ margin }: { margin: number }): CSSProperties => ({ + margin, + WebkitUserSelect: "none", + position: "relative", + background: "#eee", + padding: "0px", +}); + +export const tileOverlay = ({ + showOverlay, +}: { + showOverlay: boolean; +}): CSSProperties => ({ + 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", +}); + +export const tileIconBar: CSSProperties = { + pointerEvents: "none", + opacity: 1, + position: "absolute", + height: "36px", + width: "100%", +}; + +export const tileDescription: CSSProperties = { + background: "white", + width: "100%", + margin: 0, + userSelect: "text", + WebkitUserSelect: "text", + MozUserSelect: "text", + overflow: "hidden", +}; + +export const bottomBar: CSSProperties = { + padding: "2px", + pointerEvents: "none", + position: "absolute", + minHeight: "0px", + maxHeight: "160px", + width: "100%", + bottom: "0px", + overflow: "hidden", +}; + +export const tagItemBlock: CSSProperties = { + display: "inline-block", + cursor: "pointer", + pointerEvents: "visible", + margin: "2px", +}; + +export const tagItem = (): CSSProperties => ({ + 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", +}); + +export const checkButton = ({ + isVisible, +}: { + isVisible: boolean; +}): CSSProperties => ({ + visibility: isVisible ? "visible" : "hidden", + background: "none", + float: "left", + width: 36, + height: 36, + border: "none", + padding: 6, + cursor: "pointer", + pointerEvents: "visible", +}); diff --git a/src/components/react-grid-gallery/src/types.ts b/src/components/react-grid-gallery/src/types.ts new file mode 100644 index 00000000..06a2f2f2 --- /dev/null +++ b/src/components/react-grid-gallery/src/types.ts @@ -0,0 +1,107 @@ +import { MouseEvent, CSSProperties, ReactNode, ComponentType } from "react"; + +type Key = string | number; + +export interface ImageTag { + value: ReactNode; + key?: Key; +} + +export interface Image { + key?: Key; + src: string; + width: number; + height: number; + nano?: string; + alt?: string; + tags?: ImageTag[]; + isSelected?: boolean; + caption?: ReactNode; + customOverlay?: ReactNode; + thumbnailCaption?: ReactNode; + orientation?: number; +} + +export type ImageExtended<T extends Image = Image> = T & { + scaledWidth: number; + scaledHeight: number; + viewportWidth: number; + marginLeft: number; +}; + +export interface BuildLayoutOptions { + containerWidth: number; + maxRows?: number; + rowHeight?: number; + margin?: number; +} + +export type ImageExtendedRow<T extends Image = Image> = ImageExtended<T>[]; + +export type EventHandler<T extends Image = Image> = ( + index: number, + item: T, + event: MouseEvent<HTMLElement> +) => void; + +export type StyleFunctionContext<T extends Image = Image> = { + item: T; +}; + +export type StyleFunction<T extends Image = Image> = ( + context: StyleFunctionContext +) => CSSProperties; + +export type StyleProp<T extends Image = Image> = + | CSSProperties + | StyleFunction<T>; + +export interface ImageProps<T extends ImageExtended = ImageExtended> { + item: Image; + index: number; + margin: number; + isSelectable: boolean; + onClick: (index: number, event: MouseEvent<HTMLElement>) => void; + onSelect: (index: number, event: MouseEvent<HTMLElement>) => void; + tileViewportStyle: StyleProp<T>; + thumbnailStyle: StyleProp<T>; + tagStyle: StyleProp<T>; + height?: number; + thumbnailImageComponent?: ComponentType<ThumbnailImageProps>; +} + +export interface ThumbnailImageComponentImageProps { + key: string | number; + src: string; + alt: string; +} + +export type ThumbnailImageProps<T extends ImageExtended = ImageExtended> = + ImageProps<T> & { + imageProps: ThumbnailImageComponentImageProps; + }; + +export interface GalleryProps<T extends Image = Image> { + images: T[]; + id?: string; + enableImageSelection?: boolean; + onSelect?: EventHandler<T>; + rowHeight?: number; + maxRows?: number; + margin?: number; + defaultContainerWidth?: number; + onClick?: EventHandler<T>; + tileViewportStyle?: StyleProp<T>; + thumbnailStyle?: StyleProp<T>; + tagStyle?: StyleProp<T>; + thumbnailImageComponent?: ComponentType<ThumbnailImageProps>; +} + +export interface CheckButtonProps { + isSelected: boolean; + isVisible: boolean; + onClick: (event: MouseEvent<HTMLElement>) => void; + color?: string; + selectedColor?: string; + hoverColor?: string; +} diff --git a/src/components/react-grid-gallery/src/useContainerWidth.ts b/src/components/react-grid-gallery/src/useContainerWidth.ts new file mode 100644 index 00000000..7a53f17a --- /dev/null +++ b/src/components/react-grid-gallery/src/useContainerWidth.ts @@ -0,0 +1,35 @@ +import { useRef, useCallback, useState } from "react"; + +export function useContainerWidth(defaultContainerWidth: number) { + const ref = useRef<HTMLElement | null>(null); + const observerRef = useRef<ResizeObserver>(); + + const [containerWidth, setContainerWidth] = useState(defaultContainerWidth); + + const containerRef = useCallback((node: HTMLElement | null) => { + observerRef.current?.disconnect(); + observerRef.current = undefined; + + ref.current = node; + + const updateWidth = () => { + if (!ref.current) { + return; + } + let width = ref.current.clientWidth; + try { + width = ref.current.getBoundingClientRect().width; + } catch (err) {} + setContainerWidth(Math.floor(width)); + }; + + updateWidth(); + + if (node && typeof ResizeObserver !== "undefined") { + observerRef.current = new ResizeObserver(updateWidth); + observerRef.current.observe(node); + } + }, []); + + return { containerRef, containerWidth }; +} -- GitLab