feat(components): Add lightgallery library

Add external library until I develop a custom ligthbox
closes #20
This commit is contained in:
Alexander Navarro 2023-12-17 18:33:19 -03:00
parent 5a4c64ed21
commit a6f9ce9647
8 changed files with 491 additions and 784 deletions

View file

@ -4,13 +4,15 @@ This is a static site created for personal information and content serving such
## Dependencies
One of the objective of this project is to use as few dependencies as possible, and try to do everything from scratch.
One of the objective of this project is to use as few dependencies as possible,
and try to do everything from scratch.
Here is the list of main code dependencies:
- Astro Website framework
- ReactJS for interactive components
- [Gardevoir](https://github.com/krshoss/gardevoir) for CSS reset and normalization
- [LightGallery](https://github.com/sachinchoolur/lightGallery), this is a temporary dependency until I have the time (or will) to develop a custom ligthbox.
And here is a list of color schemes used for this project:
@ -24,6 +26,6 @@ And here is a list of color schemes used for this project:
- [ ] Create a TOC for content
- [ ] Create a lightbox compoenent
- [ ] Setup a Theme switcher
- [ ] Improve overall desing of content
- [ ] Improve overall design of content
Understand content as "one entry of the blog" or portafolio, etc.

View file

@ -10,11 +10,12 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/react": "^3.0.2",
"@astrojs/ts-plugin": "^1.1.3",
"@astrojs/react": "^3.0.7",
"@astrojs/ts-plugin": "^1.3.1",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"astro": "^3.0.12",
"astro": "^4.0.6",
"lightgallery": "^2.7.2",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"sharp": "^0.32.6"

1139
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -79,3 +79,14 @@ li:not(:last-child) {
background-color: var(--prj--primary-bg);
color: var(--prj--primary-text);
}
/* Lightgallery iframe fix */
.lg-has-iframe {
position: absolute;
top: 0;
left: 0;
.lg-object {
width: 100% !important;
height: 100% !important;
}
}

View file

@ -0,0 +1,18 @@
.thumbnailList {
display: grid;
overflow-x: scroll;
gap: var(--prj-spacing-3);
padding-bottom: var(--prj-spacing-2);
grid-auto-columns: 25%;
grid-auto-flow: column;
}
.thumbnailItem {
width: 100%;
}
.thumbnailItem:hover {
cursor: pointer;
}

View file

@ -1,30 +1,77 @@
import React from 'react';
import { MediaType, type Media } from './types';
import classes from './Gallery.module.css';
import LightGallery from 'lightgallery/react';
// import styles
import 'lightgallery/css/lightgallery.css';
import 'lightgallery/css/lg-zoom.css';
import 'lightgallery/css/lg-thumbnail.css';
// import plugins if you need
import lgThumbnail from 'lightgallery/plugins/thumbnail';
import lgZoom from 'lightgallery/plugins/zoom';
import lgVideo from 'lightgallery/plugins/video';
interface Props {
items: Media[];
}
// TODO: transform this component in a lightbox
// TODO: Replace the external library for custom module
export default function Gallery({ items }: Props): JSX.Element {
const renderItem = (item: Media): JSX.Element => {
const getUrlFromGoogleDrive = (
originalUrl: string,
type: MediaType,
): string => {
// get the file id from the "share" link of google drive
const googleFileId = item.url.split('/').at(5);
let url;
const googleFileId = originalUrl.split('/').at(5);
if (googleFileId == null) {
return originalUrl;
}
switch (type) {
case MediaType.Image:
return `https://drive.google.com/uc?export=preview&id=${googleFileId}`;
case MediaType.Video:
return `https://drive.google.com/file/d/${googleFileId}/preview`;
default:
return '';
}
};
const renderItem = (item: Media, index: number): JSX.Element => {
// get the file id from the "share" link of google drive
const url = getUrlFromGoogleDrive(item.url, item.type);
let thumbnail;
if (item.thumbnail !== undefined) {
thumbnail = getUrlFromGoogleDrive(item.thumbnail, MediaType.Image);
} else {
thumbnail = url;
}
switch (item.type) {
case MediaType.Image:
url =
googleFileId !== undefined
? `https://drive.google.com/uc?export=preview&id=${googleFileId}`
: item.url;
return <img src={url} alt={item.alt} />;
case MediaType.Video:
url =
googleFileId !== undefined
? `https://drive.google.com/file/d/${googleFileId}/preview`
: item.url;
return (
<iframe src={url} width="600" height="500" allow="autoplay"></iframe>
<a key={index} href={url} className={classes.thumbnailItem}>
<img src={url} alt={item.alt} />
</a>
);
case MediaType.Video:
return (
<div
key={index}
className={classes.thumbnailItem}
data-src={url}
data-iframe={true}
id={item.url}
data-iframe-title="foo"
>
<img src={thumbnail} alt={item.alt} />
</div>
);
default:
@ -35,10 +82,14 @@ export default function Gallery({ items }: Props): JSX.Element {
};
return (
<ul className="list-unstyle">
{items.map((item, idx) => (
<li key={idx}>{renderItem(item)}</li>
))}
</ul>
<div>
<LightGallery
speed={500}
plugins={[lgThumbnail, lgZoom, lgVideo]}
elementClassNames={classes.thumbnailList}
>
{items.map(renderItem)}
</LightGallery>
</div>
);
}

View file

@ -8,4 +8,5 @@ export interface Media {
url: string;
alt: string;
mime?: string;
thumbnail?: string;
}

View file

@ -23,7 +23,7 @@ const { Content, headings } = await entry.render();
<Layout title={entry.data.title}>
<h1>{entry.data.title}</h1>
<Gallery items={entry.data.media} />
<Gallery client:load items={entry.data.media} />
<Toc headings={headings} />