This repository has no description
7.1 kB
240 lines
1'use client';
2
3import { AppBskyEmbedImages } from '@atproto/api';
4import { Lightbox } from '@mantine-bites/lightbox';
5import { AspectRatio, SimpleGrid, Image, Spoiler, Button } from '@mantine/core';
6import { useState } from 'react';
7import styles from './ImageEmbed.module.css';
8import { useUserSettings } from '@/features/settings/lib/queries/useUserSettings';
9
10interface Props {
11 images: AppBskyEmbedImages.ViewImage[];
12}
13
14export default function ImageEmbed(props: Props) {
15 const { settings } = useUserSettings();
16 const [lightboxOpened, setLightboxOpened] = useState(false);
17
18 const lightboxImages = props.images.map((img) => ({
19 src: img.fullsize,
20 alt: img.alt,
21 }));
22
23 const openLightbox = (e: React.MouseEvent, index: number) => {
24 e.stopPropagation();
25 setLightboxOpened(true);
26 };
27
28 const lightbox = (
29 <div onClick={(e) => e.stopPropagation()}>
30 <Lightbox.Root
31 opened={lightboxOpened}
32 onClose={() => setLightboxOpened(false)}
33 >
34 <Lightbox.Toolbar>
35 <Lightbox.CloseButton />
36 </Lightbox.Toolbar>
37 <Lightbox.Controls />
38 <Lightbox.Counter />
39 <Lightbox.Slides>
40 {lightboxImages.map((img) => (
41 <Lightbox.Slide key={img.src}>
42 <Image src={img.src} alt={img.alt} />
43 </Lightbox.Slide>
44 ))}
45 </Lightbox.Slides>
46 </Lightbox.Root>
47 </div>
48 );
49
50 if (settings.cardView === 'grid') {
51 if (props.images.length === 3) {
52 return (
53 <>
54 <SimpleGrid cols={2} spacing="xs">
55 <AspectRatio
56 ratio={
57 props.images[0]?.aspectRatio
58 ? props.images[0].aspectRatio.width /
59 props.images[0].aspectRatio.height
60 : 1 / 1
61 }
62 >
63 <Image
64 src={props.images[0].thumb}
65 alt={props.images[0].alt}
66 radius="sm"
67 h={'100%'}
68 w={'100%'}
69 mah={160}
70 style={{ cursor: 'pointer' }}
71 onClick={(e) => openLightbox(e, 0)}
72 />
73 </AspectRatio>
74 <SimpleGrid cols={1} spacing="xs">
75 {props.images.slice(1).map((img, i) => {
76 const ratio = img?.aspectRatio
77 ? img.aspectRatio.width / img.aspectRatio.height
78 : 1 / 1;
79
80 return (
81 <AspectRatio ratio={ratio} key={i + 1}>
82 <Image
83 src={img.thumb}
84 alt={img.alt}
85 radius="sm"
86 h={'100%'}
87 w={'100%'}
88 mah={75}
89 style={{ cursor: 'pointer' }}
90 onClick={(e) => openLightbox(e, i + 1)}
91 />
92 </AspectRatio>
93 );
94 })}
95 </SimpleGrid>
96 </SimpleGrid>
97 {lightbox}
98 </>
99 );
100 }
101
102 return (
103 <>
104 <SimpleGrid cols={props.images.length > 1 ? 2 : 1} spacing="xs">
105 {props.images.map((img, i) => {
106 const ratio =
107 props.images.length === 1
108 ? img?.aspectRatio
109 ? img.aspectRatio.width / img.aspectRatio.height
110 : 16 / 9
111 : img?.aspectRatio
112 ? img.aspectRatio.width / img.aspectRatio.height
113 : 1 / 1;
114
115 return (
116 <AspectRatio ratio={ratio} key={i}>
117 <Image
118 src={img.thumb}
119 alt={img.alt}
120 radius="sm"
121 h={'100%'}
122 w={'100%'}
123 mah={props.images.length === 1 ? 200 : 150}
124 style={{ cursor: 'pointer' }}
125 onClick={(e) => openLightbox(e, i)}
126 />
127 </AspectRatio>
128 );
129 })}
130 </SimpleGrid>
131 {lightbox}
132 </>
133 );
134 }
135
136 return (
137 <>
138 <Spoiler
139 classNames={styles}
140 showLabel={
141 <Button
142 component="span"
143 size="xs"
144 variant="light"
145 color="gray"
146 radius={'sm'}
147 fullWidth
148 >
149 Expand image
150 </Button>
151 }
152 hideLabel={
153 <Button
154 component="span"
155 size="xs"
156 variant="light"
157 color="gray"
158 radius={'sm'}
159 fullWidth
160 >
161 Collape image
162 </Button>
163 }
164 maxHeight={280}
165 >
166 {props.images.length === 3 ? (
167 <SimpleGrid cols={2} spacing="xs">
168 <AspectRatio
169 ratio={
170 props.images[0]?.aspectRatio
171 ? props.images[0].aspectRatio.width /
172 props.images[0].aspectRatio.height
173 : 1 / 1
174 }
175 >
176 <Image
177 src={props.images[0].thumb}
178 alt={props.images[0].alt}
179 radius="sm"
180 h={'100%'}
181 w={'100%'}
182 style={{ cursor: 'pointer' }}
183 onClick={(e) => openLightbox(e, 0)}
184 />
185 </AspectRatio>
186 <SimpleGrid cols={1} spacing="xs">
187 {props.images.slice(1).map((img, i) => {
188 const ratio = img?.aspectRatio
189 ? img.aspectRatio.width / img.aspectRatio.height
190 : 1 / 1;
191
192 return (
193 <AspectRatio ratio={ratio} key={i + 1}>
194 <Image
195 src={img.thumb}
196 alt={img.alt}
197 radius="sm"
198 h={'100%'}
199 w={'100%'}
200 style={{ cursor: 'pointer' }}
201 onClick={(e) => openLightbox(e, i + 1)}
202 />
203 </AspectRatio>
204 );
205 })}
206 </SimpleGrid>
207 </SimpleGrid>
208 ) : (
209 <SimpleGrid cols={props.images.length > 1 ? 2 : 1} spacing="xs">
210 {props.images.map((img, i) => {
211 const ratio =
212 props.images.length === 1
213 ? img?.aspectRatio
214 ? img.aspectRatio.width / img.aspectRatio.height
215 : 16 / 9
216 : img?.aspectRatio
217 ? img.aspectRatio.width / img.aspectRatio.height
218 : 1 / 1;
219
220 return (
221 <AspectRatio ratio={ratio} key={i}>
222 <Image
223 src={img.thumb}
224 alt={img.alt}
225 radius="sm"
226 h={'100%'}
227 w={'100%'}
228 style={{ cursor: 'pointer' }}
229 onClick={(e) => openLightbox(e, i)}
230 />
231 </AspectRatio>
232 );
233 })}
234 </SimpleGrid>
235 )}
236 </Spoiler>
237 {lightbox}
238 </>
239 );
240}