From 4e4620fa27a54a72f8e8d62f67795af985467fa7 Mon Sep 17 00:00:00 2001 From: Tim Ellenberger Date: Wed, 11 Oct 2023 16:48:40 -0600 Subject: [PATCH] allow nextjs image, video etc WIP --- example/components/GalleryLightbox/index.jsx | 191 +++++++++++++----- example/next.config.js | 12 ++ example/pages/index.tsx | 147 ++++---------- .../ImageStage/components/Image/index.tsx | 24 ++- .../components/ImagePager/index.tsx | 3 +- .../SSRImagePager/SSRImagePager.tsx | 20 +- src/components/ImageStage/index.tsx | 3 +- src/index.tsx | 2 +- 8 files changed, 217 insertions(+), 185 deletions(-) diff --git a/example/components/GalleryLightbox/index.jsx b/example/components/GalleryLightbox/index.jsx index 724e97c..669068e 100644 --- a/example/components/GalleryLightbox/index.jsx +++ b/example/components/GalleryLightbox/index.jsx @@ -1,4 +1,4 @@ -import { FiHeart, FiPrinter, FiShare } from 'react-icons/fi'; +// import { FiHeart, FiPrinter, FiShare } from 'react-icons/fi'; import React from 'react'; import PropTypes from 'prop-types'; import styled from 'styled-components'; @@ -9,6 +9,114 @@ import GridImage from './components/GridImage'; import LightboxHeader from './components/LightboxHeader'; import LightboxArrowButton from './components/LightboxArrowButton'; +const mosaicImages = [ + { + alt: 'Windows 10 Dark Mode Setting', + caption: 'Windows 10 Dark Mode Setting', + height: 2035, + src: 'https://timellenberger.com/static/blog-content/dark-mode/win10-dark-mode.jpg', + width: 2848, + }, + { + alt: 'macOS Mojave Dark Mode Setting', + caption: 'macOS Mojave Dark Mode Setting', + height: 1218, + src: 'https://timellenberger.com/static/blog-content/dark-mode/macos-dark-mode.png', + width: 1200, + }, + { + alt: 'Android 9.0 Dark Mode Setting', + caption: 'Android 9.0 Dark Mode Setting', + height: 600, + src: 'https://timellenberger.com/static/blog-content/dark-mode/android-9-dark-mode.jpg', + width: 1280, + }, + { + alt: 'Windows 10 Dark Mode Setting#', + caption: 'Windows 10 Dark Mode Setting#', + height: 2035, + src: 'https://timellenberger.com/static/blog-content/dark-mode/win10-dark-mode.jpg', + width: 2848, + }, + { + alt: 'Windows 10 Dark Mode Setting', + caption: 'Windows 10 Dark Mode Setting', + height: 2035, + src: 'https://timellenberger.com/static/blog-content/dark-mode/win10-dark-mode.jpg', + width: 2848, + }, + { + alt: 'macOS Mojave Dark Mode Setting', + caption: 'macOS Mojave Dark Mode Setting', + height: 1218, + src: 'https://timellenberger.com/static/blog-content/dark-mode/macos-dark-mode.png', + width: 1200, + }, + { + alt: 'Android 9.0 Dark Mode Setting', + caption: 'Android 9.0 Dark Mode Setting', + height: 600, + src: 'https://timellenberger.com/static/blog-content/dark-mode/android-9-dark-mode.jpg', + width: 1280, + }, + { + alt: 'Windows 10 Dark Mode Setting#', + caption: 'Windows 10 Dark Mode Setting#', + height: 2035, + src: 'https://timellenberger.com/static/blog-content/dark-mode/win10-dark-mode.jpg', + width: 2848, + }, + { + alt: 'Android 9.0 Dark Mode Setting', + caption: 'Android 9.0 Dark Mode Setting', + height: 600, + src: 'https://timellenberger.com/static/blog-content/dark-mode/android-9-dark-mode.jpg', + width: 1280, + }, + { + alt: 'Windows 10 Dark Mode Setting#', + caption: 'Windows 10 Dark Mode Setting#', + height: 2035, + src: 'https://timellenberger.com/static/blog-content/dark-mode/win10-dark-mode.jpg', + width: 2848, + }, + { + alt: 'macOS Mojave Dark Mode Setting', + caption: 'macOS Mojave Dark Mode Setting', + height: 1218, + src: 'https://timellenberger.com/static/blog-content/dark-mode/macos-dark-mode.png', + width: 1200, + }, + { + alt: 'Android 9.0 Dark Mode Setting', + caption: 'Android 9.0 Dark Mode Setting', + height: 600, + src: 'https://timellenberger.com/static/blog-content/dark-mode/android-9-dark-mode.jpg', + width: 1280, + }, + { + alt: 'Windows 10 Dark Mode Setting#', + caption: 'Windows 10 Dark Mode Setting#', + height: 2035, + src: 'https://timellenberger.com/static/blog-content/dark-mode/win10-dark-mode.jpg', + width: 2848, + }, + { + alt: 'Android 9.0 Dark Mode Setting', + caption: 'Android 9.0 Dark Mode Setting', + height: 600, + src: 'https://timellenberger.com/static/blog-content/dark-mode/android-9-dark-mode.jpg', + width: 1280, + }, + { + alt: 'Windows 10 Dark Mode Setting#', + caption: 'Windows 10 Dark Mode Setting#', + height: 2035, + src: 'https://timellenberger.com/static/blog-content/dark-mode/win10-dark-mode.jpg', + width: 2848, + }, +]; + class BlogImageGallery extends React.Component { static propTypes = { galleryTitle: PropTypes.string.isRequired, @@ -96,15 +204,6 @@ class BlogImageGallery extends React.Component { const { clientSide, currentImageIndex, lightboxIsOpen } = this.state; const { galleryTitle, imageMasonryDirection, images } = this.props; - // remove the height and width props for the lightbox images array - const listboxImages = [...images].map((image) => { - const newImage = { ...image }; - delete newImage.height; - delete newImage.width; - - return newImage; - }); - return ( {clientSide && ( @@ -113,14 +212,14 @@ class BlogImageGallery extends React.Component { direction={imageMasonryDirection} margin={6} onClick={this.openLightbox} - photos={images} + photos={mosaicImages} renderImage={GridImage} /> )} )} - renderImageOverlay={() => ( - -

Create your own UI

- - - -
- )} + // renderImageOverlay={() => ( + // + //

Create your own UI

+ // + // + // + //
+ // )} renderNextButton={({ canNext }) => ( theme.pageContentSelectionColor} 1px solid; - background: rgba(39, 39, 39, 0.5); - p { - color: ${({ theme }) => theme.pageContentSelectionColor}; - text-align: center; - font-weight: bold; - font-size: 1.2em; - margin: 0.5em 0; - } - svg { - border: white 1px solid; - fill: ${({ theme }) => theme.pageContentSelectionColor}; - margin: 10px; - padding: 5px; - :hover { - border: ${({ theme }) => theme.pageContentSelectionColor} 1px solid; - fill: ${({ theme }) => - new Color(theme.pageContentSelectionColor).darken(0.57).hex()}; - cursor: pointer; - } - } -`; +// const ImageOverlay = styled.div` +// position: absolute; +// top: 0%; +// right: 0%; +// border: ${({ theme }) => theme.pageContentSelectionColor} 1px solid; +// background: rgba(39, 39, 39, 0.5); +// p { +// color: ${({ theme }) => theme.pageContentSelectionColor}; +// text-align: center; +// font-weight: bold; +// font-size: 1.2em; +// margin: 0.5em 0; +// } +// svg { +// border: white 1px solid; +// fill: ${({ theme }) => theme.pageContentSelectionColor}; +// margin: 10px; +// padding: 5px; +// :hover { +// border: ${({ theme }) => theme.pageContentSelectionColor} 1px solid; +// fill: ${({ theme }) => +// new Color(theme.pageContentSelectionColor).darken(0.57).hex()}; +// cursor: pointer; +// } +// } +// `; diff --git a/example/next.config.js b/example/next.config.js index 5888443..cf4c6a2 100644 --- a/example/next.config.js +++ b/example/next.config.js @@ -3,6 +3,18 @@ const nextConfig = { compiler: { styledComponents: true, }, + images: { + remotePatterns: [ + { + hostname: 'timellenberger.com', + protocol: 'https', + }, + { + hostname: 'https://picsum.photos', + protocol: 'https', + }, + ], + }, transpilePackages: ['styled-components', 'react-spring-lightbox'], }; diff --git a/example/pages/index.tsx b/example/pages/index.tsx index 63db794..a909279 100644 --- a/example/pages/index.tsx +++ b/example/pages/index.tsx @@ -2,113 +2,38 @@ import * as React from 'react'; import styled from 'styled-components'; import GalleryLightbox from '../components/GalleryLightbox'; import InlineLightbox from '../components/InlineLightbox'; +import Image from 'next/image'; -const images = [ - { - alt: 'Windows 10 Dark Mode Setting', - caption: 'Windows 10 Dark Mode Setting', - height: 2035, - src: 'https://timellenberger.com/static/blog-content/dark-mode/win10-dark-mode.jpg', - width: 2848, - }, - { - alt: 'macOS Mojave Dark Mode Setting', - caption: 'macOS Mojave Dark Mode Setting', - height: 1218, - src: 'https://timellenberger.com/static/blog-content/dark-mode/macos-dark-mode.png', - width: 1200, - }, - { - alt: 'Android 9.0 Dark Mode Setting', - caption: 'Android 9.0 Dark Mode Setting', - height: 600, - src: 'https://timellenberger.com/static/blog-content/dark-mode/android-9-dark-mode.jpg', - width: 1280, - }, - { - alt: 'Windows 10 Dark Mode Setting#', - caption: 'Windows 10 Dark Mode Setting#', - height: 2035, - src: 'https://timellenberger.com/static/blog-content/dark-mode/win10-dark-mode.jpg', - width: 2848, - }, - { - alt: 'Windows 10 Dark Mode Setting', - caption: 'Windows 10 Dark Mode Setting', - height: 2035, - src: 'https://timellenberger.com/static/blog-content/dark-mode/win10-dark-mode.jpg', - width: 2848, - }, - { - alt: 'macOS Mojave Dark Mode Setting', - caption: 'macOS Mojave Dark Mode Setting', - height: 1218, - src: 'https://timellenberger.com/static/blog-content/dark-mode/macos-dark-mode.png', - width: 1200, - }, - { - alt: 'Android 9.0 Dark Mode Setting', - caption: 'Android 9.0 Dark Mode Setting', - height: 600, - src: 'https://timellenberger.com/static/blog-content/dark-mode/android-9-dark-mode.jpg', - width: 1280, - }, - { - alt: 'Windows 10 Dark Mode Setting#', - caption: 'Windows 10 Dark Mode Setting#', - height: 2035, - src: 'https://timellenberger.com/static/blog-content/dark-mode/win10-dark-mode.jpg', - width: 2848, - }, - { - alt: 'Android 9.0 Dark Mode Setting', - caption: 'Android 9.0 Dark Mode Setting', - height: 600, - src: 'https://timellenberger.com/static/blog-content/dark-mode/android-9-dark-mode.jpg', - width: 1280, - }, - { - alt: 'Windows 10 Dark Mode Setting#', - caption: 'Windows 10 Dark Mode Setting#', - height: 2035, - src: 'https://timellenberger.com/static/blog-content/dark-mode/win10-dark-mode.jpg', - width: 2848, - }, - { - alt: 'macOS Mojave Dark Mode Setting', - caption: 'macOS Mojave Dark Mode Setting', - height: 1218, - src: 'https://timellenberger.com/static/blog-content/dark-mode/macos-dark-mode.png', - width: 1200, - }, - { - alt: 'Android 9.0 Dark Mode Setting', - caption: 'Android 9.0 Dark Mode Setting', - height: 600, - src: 'https://timellenberger.com/static/blog-content/dark-mode/android-9-dark-mode.jpg', - width: 1280, - }, - { - alt: 'Windows 10 Dark Mode Setting#', - caption: 'Windows 10 Dark Mode Setting#', - height: 2035, - src: 'https://timellenberger.com/static/blog-content/dark-mode/win10-dark-mode.jpg', - width: 2848, - }, - { - alt: 'Android 9.0 Dark Mode Setting', - caption: 'Android 9.0 Dark Mode Setting', - height: 600, - src: 'https://timellenberger.com/static/blog-content/dark-mode/android-9-dark-mode.jpg', - width: 1280, - }, - { - alt: 'Windows 10 Dark Mode Setting#', - caption: 'Windows 10 Dark Mode Setting#', - height: 2035, - src: 'https://timellenberger.com/static/blog-content/dark-mode/win10-dark-mode.jpg', - width: 2848, - }, +const images: React.ReactNode[] = [ +
+ +
, +
+

hello!

+
, + dark mode, + , + , ]; const getRandomImages = (numImages: number) => { @@ -121,17 +46,13 @@ const getRandomImages = (numImages: number) => { }; const altCaption = 'picsum photo'; - const randomizedArray = imageArray.map((imageObj) => { + const randomizedArray = imageArray.map(() => { const imageURL = `https://picsum.photos/id/${getRandomInt( 1, 200, )}/1920/1280`; - return { - ...imageObj, - alt: altCaption, - caption: altCaption, - src: imageURL, - }; + + return {altCaption}; }); return randomizedArray; diff --git a/src/components/ImageStage/components/Image/index.tsx b/src/components/ImageStage/components/Image/index.tsx index b1707b2..612fd1b 100644 --- a/src/components/ImageStage/components/Image/index.tsx +++ b/src/components/ImageStage/components/Image/index.tsx @@ -7,7 +7,6 @@ import { import { useGesture } from 'react-use-gesture'; import React, { useEffect, useRef, useState } from 'react'; import styled, { AnyStyledComponent } from 'styled-components'; -import type { ImagesListItem } from '../../../../types/ImagesList'; const defaultImageTransform = { pinching: false, @@ -18,7 +17,7 @@ const defaultImageTransform = { type IImageProps = { /** Any valid props to pass to the lightbox img element ie src, alt, caption etc*/ - imgProps: ImagesListItem; + imgProps: React.ReactNode; /** Affects Width calculation method, depending on whether the Lightbox is Inline or not */ inline: boolean; /** True if this image is currently shown in pager, otherwise false */ @@ -37,7 +36,7 @@ type IImageProps = { * Animates pinch-zoom + panning on image using spring physics */ const Image = ({ - imgProps: { style: imgStyleProp, ...restImgProps }, + imgProps, inline, isCurrentImage, pagerHeight, @@ -285,7 +284,7 @@ const Image = ({ }); return ( - images prop - {...(restImgProps as React.ComponentProps)} - /> + > + {imgProps} + ); }; @@ -318,7 +316,7 @@ Image.displayName = 'Image'; export default Image; -const AnimatedImage = styled(animated.img as AnyStyledComponent)` +const AnimatedPage = styled(animated.div as AnyStyledComponent)` width: auto; height: auto; max-width: 100%; @@ -327,4 +325,12 @@ const AnimatedImage = styled(animated.img as AnyStyledComponent)` ::selection { background: none; } + + overflow: hidden; + + > * { + width: 100%; + height: 100%; + object-fit: contain; + } `; diff --git a/src/components/ImageStage/components/ImagePager/index.tsx b/src/components/ImageStage/components/ImagePager/index.tsx index 4797db9..87ec0ee 100644 --- a/src/components/ImageStage/components/ImagePager/index.tsx +++ b/src/components/ImageStage/components/ImagePager/index.tsx @@ -3,7 +3,6 @@ import { useGesture } from 'react-use-gesture'; import Image from '../Image'; import React, { useEffect, useRef, useState } from 'react'; import styled, { AnyStyledComponent } from 'styled-components'; -import type { ImagesList } from '../../../../types/ImagesList'; type IImagePager = { /** Index of image in images array that is currently shown */ @@ -13,7 +12,7 @@ type IImagePager = { /** image stage width */ imageStageWidth: number; /** Array of image objects to be shown in Lightbox */ - images: ImagesList; + images: React.ReactNode[]; /** Affects Width calculation method, depending on whether the Lightbox is Inline or not */ inline: boolean; /** Function that closes the Lightbox */ diff --git a/src/components/ImageStage/components/SSRImagePager/SSRImagePager.tsx b/src/components/ImageStage/components/SSRImagePager/SSRImagePager.tsx index 281e630..64ecd65 100644 --- a/src/components/ImageStage/components/SSRImagePager/SSRImagePager.tsx +++ b/src/components/ImageStage/components/SSRImagePager/SSRImagePager.tsx @@ -1,23 +1,19 @@ -import type { ImagesList } from '../../../../types/ImagesList'; import styled, { css } from 'styled-components'; import * as React from 'react'; type ISSRImagePagerProps = { currentIndex: number; - images: ImagesList; + images: React.ReactNode[]; }; const SSRImagePager = ({ currentIndex, images }: ISSRImagePagerProps) => { return ( - {images.map(({ alt, src }, i) => { + {images.map((el, i) => { return ( - {alt} + + {el} + ); })} @@ -31,9 +27,9 @@ const ImagePagerContainer = styled.div` height: inherit; `; -const Image = styled.img<{ $isCurrentImage: boolean }>` - ${({ $isCurrentImage }) => - !$isCurrentImage && +const PageContainer = styled.div<{ $isCurrentPage: boolean }>` + ${({ $isCurrentPage }) => + !$isCurrentPage && css` visibility: hidden; display: none; diff --git a/src/components/ImageStage/index.tsx b/src/components/ImageStage/index.tsx index 676dbbf..f623426 100644 --- a/src/components/ImageStage/index.tsx +++ b/src/components/ImageStage/index.tsx @@ -2,7 +2,6 @@ import ImagePager from './components/ImagePager'; import React from 'react'; import styled from 'styled-components'; import useRefSize from './utils/useRefSize'; -import type { ImagesList } from '../../types/ImagesList'; import SSRImagePager from './components/SSRImagePager/SSRImagePager'; type IImageStageProps = { @@ -11,7 +10,7 @@ type IImageStageProps = { /** Index of image in images array that is currently shown */ currentIndex: number; /** Array of image objects to be shown in Lightbox */ - images: ImagesList; + images: React.ReactNode[]; /** Affects Width calculation method, depending on whether the Lightbox is Inline or not */ inline: boolean; /** Function that closes the Lightbox */ diff --git a/src/index.tsx b/src/index.tsx index 2d58ee1..9715773 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -10,7 +10,7 @@ type ILightboxProps = { /** Index of image in images array that is currently shown */ currentIndex: number; /** Array of images to be shown in Lightbox, each image object may contain any valid 'img' attribute with the exceptions of 'draggable', 'onClick', 'onDragStart' and 'ref' */ - images: ImagesList; + images: React.ReactNode[]; /** Determines whether the Lightbox returns just an Inline carousel (ImageStage) */ inline?: boolean; /** Flag that dictates if the lightbox is open or closed */