Skip to content

Commit 4ded8e8

Browse files
committed
try to pass Astro Image into React gallery, not working
1 parent 02dea7d commit 4ded8e8

File tree

7 files changed

+280
-13
lines changed

7 files changed

+280
-13
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
---
2+
import { Image } from 'astro:assets';
3+
4+
import ReactGallery from '@/components/react/Gallery';
5+
import { IMAGE_SIZES } from '@/constants/image';
6+
import { cn } from '@/utils/styles';
7+
8+
import type { AstroImageProps, ImageProps } from '@/types/common';
9+
import type { ImageMetadata } from 'astro';
10+
11+
export interface Props extends astroHTML.JSX.HTMLAttributes {}
12+
13+
// filenames
14+
const EXCLUDE_IMAGES = ['avatar1.jpg'];
15+
16+
const getAllImagesMetadata = (): ImageMetadata[] => {
17+
const imageModules = import.meta.glob<{ default: ImageMetadata }>(
18+
// cant be even variable
19+
'/src/assets/images/all-images/*.jpg',
20+
{ eager: true }
21+
);
22+
23+
// convert map to array
24+
const imagesMetadata = Object.keys(imageModules)
25+
// filter excluded filenames
26+
.filter((path) => !EXCLUDE_IMAGES.some((excludedFileName) => path.endsWith(excludedFileName)))
27+
// return metadata array
28+
.map((path) => imageModules[path].default);
29+
return imagesMetadata;
30+
};
31+
32+
const imagesMetadata = getAllImagesMetadata();
33+
34+
const imageMetadataToAstroImageProps = (imagesMetadata: ImageMetadata): AstroImageProps => ({
35+
src: imagesMetadata,
36+
...IMAGE_SIZES.FIXED.MDX_XXS_16_9,
37+
alt: 'Gallery image',
38+
});
39+
40+
const astroImagePropsToReactImageProps = (astroImageProps: AstroImageProps): ImageProps => {
41+
// console.log('astroImageProps', JSON.stringify(astroImageProps, null, 2));
42+
43+
const astroImageSrc = astroImageProps.src as ImageMetadata;
44+
45+
return {
46+
src: astroImageSrc.src,
47+
originalSrc: astroImageSrc.src,
48+
width: parseInt(String(astroImageProps.width)),
49+
height: parseInt(String(astroImageProps.height)),
50+
};
51+
};
52+
53+
const astroImages = imagesMetadata.map((metadata) => imageMetadataToAstroImageProps(metadata));
54+
const reactImages = astroImages.map((astroProps) => astroImagePropsToReactImageProps(astroProps));
55+
56+
console.log('images', JSON.stringify(reactImages, null, 2));
57+
58+
const { class: className } = Astro.props;
59+
---
60+
61+
<div class={cn('', className)}>
62+
<ReactGallery
63+
client:only="react"
64+
images={reactImages}
65+
thumbnailImageComponent={(<Image {...IMAGE_SIZES.FIXED.MDX_XXS_16_9} src="" alt="default" />)}
66+
/>
67+
</div>
68+
{
69+
/*
70+
71+
/@fs/home/username/Desktop/nemanjam.github.io/src/assets/images/all-images/cyco5.jpg?origWidth=4608&origHeight=2592&origFormat=jpg
72+
73+
<ul class={cn('grid gap-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3', className)}>
74+
{
75+
imagesMetadata.map((image) => (
76+
<li>
77+
<Image {...IMAGE_SIZES.FIXED.MDX_XXS_16_9} src={image} alt="my image" />
78+
</li>
79+
))
80+
}
81+
</ul>
82+
83+
interface Image {
84+
key?: Key;
85+
src: string;
86+
width: number;
87+
height: number;
88+
nano?: string;
89+
alt?: string;
90+
tags?: ImageTag[];
91+
isSelected?: boolean;
92+
caption?: ReactNode;
93+
customOverlay?: ReactNode;
94+
thumbnailCaption?: ReactNode;
95+
orientation?: number;
96+
}
97+
*/
98+
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"react": "^18.3.1",
5050
"react-dom": "^18.3.1",
5151
"react-grid-gallery": "^1.0.1",
52+
"react-image-lightbox": "^5.1.4",
5253
"reading-time": "^1.5.0",
5354
"sharp": "0.32.6",
5455
"tailwind-clip-path": "^1.0.0",

src/components/Gallery.astro

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
---
22
import { Image } from 'astro:assets';
33
4+
import ReactGallery from '@/components/react/Gallery';
45
import { IMAGE_SIZES } from '@/constants/image';
56
import { cn } from '@/utils/styles';
67
8+
import type { AstroImageProps, ImageProps } from '@/types/common';
79
import type { ImageMetadata } from 'astro';
810
911
export interface Props extends astroHTML.JSX.HTMLAttributes {}
@@ -29,15 +31,31 @@ const getAllImagesMetadata = (): ImageMetadata[] => {
2931
3032
const imagesMetadata = getAllImagesMetadata();
3133
34+
const imageMetadataToAstroImageProps = (imagesMetadata: ImageMetadata): AstroImageProps => ({
35+
src: imagesMetadata,
36+
...IMAGE_SIZES.FIXED.MDX_XXS_16_9,
37+
alt: 'Gallery image',
38+
});
39+
40+
const astroImagePropsToReactImageProps = (astroImageProps: AstroImageProps): ImageProps => {
41+
const astroImageSrc = astroImageProps.src as ImageMetadata;
42+
43+
return {
44+
src: astroImageSrc.src,
45+
originalSrc: astroImageSrc.src,
46+
width: parseInt(String(astroImageProps.width)),
47+
height: parseInt(String(astroImageProps.height)),
48+
};
49+
};
50+
51+
const astroImages = imagesMetadata.map((metadata) => imageMetadataToAstroImageProps(metadata));
52+
const reactImages = astroImages.map((astroProps) => astroImagePropsToReactImageProps(astroProps));
53+
3254
const { class: className } = Astro.props;
3355
---
3456

35-
<ul class={cn('grid gap-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3', className)}>
36-
{
37-
imagesMetadata.map((image) => (
38-
<li>
39-
<Image {...IMAGE_SIZES.FIXED.MDX_XXS_16_9} src={image} alt="my image" />
40-
</li>
41-
))
42-
}
43-
</ul>
57+
<div class={cn('', className)}>
58+
<ReactGallery client:only="react" images={reactImages}>
59+
<Image {...IMAGE_SIZES.FIXED.MDX_XXS_16_9} src="https://google.com" alt="default" />
60+
</ReactGallery>
61+
</div>

src/components/react/Gallery.tsx

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { cloneElement, useState } from 'react';
2+
3+
import { Gallery as ReactGridGallery } from 'react-grid-gallery';
4+
import Lightbox from 'react-image-lightbox';
5+
6+
import type { ImageProps } from '@/types/common';
7+
import type { ReactElement } from 'react';
8+
import type { ThumbnailImageComponentImageProps } from 'react-grid-gallery';
9+
10+
import 'react-image-lightbox/style.css';
11+
12+
import ThumbnailImage from '@/components/react/ThumbnailImage';
13+
14+
interface Props {
15+
children?: ReactElement;
16+
images: ImageProps[];
17+
}
18+
19+
const Gallery: React.FC<Props> = ({ images, children: thumbnailImageComponent }) => {
20+
const [index, setIndex] = useState(-1);
21+
22+
const currentImage = images[index];
23+
const nextIndex = (index + 1) % images.length;
24+
const nextImage = images[nextIndex] || currentImage;
25+
const prevIndex = (index + images.length - 1) % images.length;
26+
const prevImage = images[prevIndex] || currentImage;
27+
28+
const handleClick = (index: number, _item: ImageProps) => setIndex(index);
29+
const handleClose = () => setIndex(-1);
30+
const handleMovePrev = () => setIndex(prevIndex);
31+
const handleMoveNext = () => setIndex(nextIndex);
32+
33+
console.log('currentImage', currentImage);
34+
35+
return (
36+
<div>
37+
<ReactGridGallery
38+
images={images}
39+
thumbnailImageComponent={(props) => {
40+
const imageProps: ThumbnailImageComponentImageProps = props.imageProps;
41+
42+
// key, src, alt, title, style
43+
const { key: _, ...astroImageProps } = imageProps;
44+
45+
console.log('imageProps', imageProps);
46+
47+
return (
48+
<ThumbnailImage {...props}>
49+
{cloneElement(thumbnailImageComponent ?? <></>, {
50+
...astroImageProps,
51+
})}
52+
</ThumbnailImage>
53+
);
54+
}}
55+
onClick={handleClick}
56+
enableImageSelection={false}
57+
/>
58+
{!!currentImage && (
59+
<Lightbox
60+
imageTitle={currentImage.caption}
61+
mainSrc={currentImage.originalSrc}
62+
mainSrcThumbnail={currentImage.src}
63+
nextSrc={nextImage.originalSrc}
64+
nextSrcThumbnail={nextImage.src}
65+
prevSrc={prevImage.originalSrc}
66+
prevSrcThumbnail={prevImage.src}
67+
onCloseRequest={handleClose}
68+
onMovePrevRequest={handleMovePrev}
69+
onMoveNextRequest={handleMoveNext}
70+
/>
71+
)}
72+
</div>
73+
);
74+
};
75+
76+
export default Gallery;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Fragment } from 'react';
2+
3+
import type { ReactNode } from 'react';
4+
import type { ThumbnailImageProps } from 'react-grid-gallery';
5+
6+
interface Props {
7+
imageProps: ThumbnailImageProps['imageProps'];
8+
children?: ReactNode;
9+
}
10+
11+
const ThumbnailImage: React.FC<Props> = ({ imageProps, children }) => (
12+
<Fragment>
13+
{children ?? <img {...{ ...imageProps, title: imageProps.title ?? undefined }} />}
14+
</Fragment>
15+
);
16+
17+
export default ThumbnailImage;

src/types/common.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import { COLLECTIONS } from '@/constants/collections';
2-
1+
import type { COLLECTIONS } from '@/constants/collections';
32
import type { Page } from 'astro';
3+
import type { Image } from 'astro:assets';
44
import type { CollectionEntry } from 'astro:content';
5+
import type { ComponentProps } from 'astro/types';
6+
import type { Image as ReactGridGalleryImage } from 'react-grid-gallery';
57

68
export type CollectionType = (typeof COLLECTIONS)[keyof typeof COLLECTIONS];
79

@@ -20,3 +22,9 @@ export interface PaginationProps
2022
Page<AnyCollection>,
2123
'url' | 'currentPage' | 'lastPage' | 'start' | 'end' | 'total'
2224
> {}
25+
26+
export interface ImageProps extends ReactGridGalleryImage {
27+
originalSrc: string;
28+
}
29+
30+
export type AstroImageProps = ComponentProps<typeof Image>;

yarn.lock

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3041,6 +3041,11 @@ execa@^8.0.1:
30413041
signal-exit "^4.1.0"
30423042
strip-final-newline "^3.0.0"
30433043

3044+
exenv@^1.2.0:
3045+
version "1.2.2"
3046+
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
3047+
integrity sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==
3048+
30443049
expand-template@^2.0.3:
30453050
version "2.0.3"
30463051
resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
@@ -4148,7 +4153,7 @@ longest-streak@^3.0.0:
41484153
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4"
41494154
integrity sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==
41504155

4151-
loose-envify@^1.1.0:
4156+
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
41524157
version "1.4.0"
41534158
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
41544159
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@@ -5042,7 +5047,7 @@ nth-check@^2.0.0, nth-check@^2.0.1:
50425047
dependencies:
50435048
boolbase "^1.0.0"
50445049

5045-
object-assign@^4.0.1:
5050+
object-assign@^4.0.1, object-assign@^4.1.1:
50465051
version "4.1.1"
50475052
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
50485053
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
@@ -5500,6 +5505,15 @@ prompts@^2.4.2:
55005505
kleur "^3.0.3"
55015506
sisteransi "^1.0.5"
55025507

5508+
prop-types@^15.7.2:
5509+
version "15.8.1"
5510+
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
5511+
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
5512+
dependencies:
5513+
loose-envify "^1.4.0"
5514+
object-assign "^4.1.1"
5515+
react-is "^16.13.1"
5516+
55035517
property-information@^6.0.0:
55045518
version "6.5.0"
55055519
resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec"
@@ -5561,6 +5575,34 @@ react-grid-gallery@^1.0.1:
55615575
resolved "https://registry.yarnpkg.com/react-grid-gallery/-/react-grid-gallery-1.0.1.tgz#51e9e920cb83df6c61fbd1f2c7eed7db3b6e5a1b"
55625576
integrity sha512-+fVd6fH9tm0W+UMgzRHET/gmzSs2/l2sGOuELLaHXMto6UhuZdscj9ILHOYe7hn0GBRUJiczMllsEs7OJz9uPA==
55635577

5578+
react-image-lightbox@^5.1.4:
5579+
version "5.1.4"
5580+
resolved "https://registry.yarnpkg.com/react-image-lightbox/-/react-image-lightbox-5.1.4.tgz#5b847dcb79e9efdf9d7cd5621a92e0f156d2cf30"
5581+
integrity sha512-kTiAODz091bgT7SlWNHab0LSMZAPJtlNWDGKv7pLlLY1krmf7FuG1zxE0wyPpeA8gPdwfr3cu6sPwZRqWsc3Eg==
5582+
dependencies:
5583+
prop-types "^15.7.2"
5584+
react-modal "^3.11.1"
5585+
5586+
react-is@^16.13.1:
5587+
version "16.13.1"
5588+
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
5589+
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
5590+
5591+
react-lifecycles-compat@^3.0.0:
5592+
version "3.0.4"
5593+
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
5594+
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
5595+
5596+
react-modal@^3.11.1:
5597+
version "3.16.1"
5598+
resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.16.1.tgz#34018528fc206561b1a5467fc3beeaddafb39b2b"
5599+
integrity sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==
5600+
dependencies:
5601+
exenv "^1.2.0"
5602+
prop-types "^15.7.2"
5603+
react-lifecycles-compat "^3.0.0"
5604+
warning "^4.0.3"
5605+
55645606
react-refresh@^0.14.2:
55655607
version "0.14.2"
55665608
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9"
@@ -6937,6 +6979,13 @@ walk-up-path@^3.0.1:
69376979
resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-3.0.1.tgz#c8d78d5375b4966c717eb17ada73dbd41490e886"
69386980
integrity sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==
69396981

6982+
warning@^4.0.3:
6983+
version "4.0.3"
6984+
resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
6985+
integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
6986+
dependencies:
6987+
loose-envify "^1.0.0"
6988+
69406989
web-namespaces@^2.0.0:
69416990
version "2.0.1"
69426991
resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-2.0.1.tgz#1010ff7c650eccb2592cebeeaf9a1b253fd40692"

0 commit comments

Comments
 (0)