feat(SW-842): Added lightbox to roomcard

This commit is contained in:
Erik Tiekstra
2024-11-12 10:39:42 +01:00
parent d732138696
commit 962760ae1b
11 changed files with 150 additions and 142 deletions

View File

@@ -1,6 +1,6 @@
"use client"
import { AnimatePresence, motion } from "framer-motion"
import React, { useState } from "react"
import { useEffect, useState } from "react"
import { Dialog, Modal, ModalOverlay } from "react-aria-components"
import FullView from "./FullView"
@@ -12,24 +12,19 @@ import type { LightboxProps } from "@/types/components/lightbox/lightbox"
export default function Lightbox({
images,
children,
dialogTitle,
onClose,
isOpen,
}: LightboxProps) {
const [isOpen, setIsOpen] = useState(false)
const [selectedImageIndex, setSelectedImageIndex] = useState(0)
const [isFullView, setIsFullView] = useState(false)
function handleOpenChange(open: boolean) {
if (!open) {
setTimeout(() => {
setIsOpen(false)
setSelectedImageIndex(0)
setIsFullView(false)
}, 300) // 300ms delay
} else {
setIsOpen(true)
useEffect(() => {
if (isOpen) {
setSelectedImageIndex(0)
setIsFullView(false)
}
}
}, [isOpen])
function handleNext() {
setSelectedImageIndex((prevIndex) => (prevIndex + 1) % images.length)
@@ -41,75 +36,53 @@ export default function Lightbox({
)
}
const triggerElement = React.Children.map(
children,
function mapChild(child): React.ReactNode {
if (React.isValidElement(child)) {
if (child.props.id === "lightboxTrigger") {
return React.cloneElement(child, {
onClick: () => setIsOpen(true),
} as React.HTMLAttributes<HTMLElement>)
} else if (child.props.children) {
return React.cloneElement(child, {
children: React.Children.map(child.props.children, mapChild),
} as React.HTMLAttributes<HTMLElement>)
}
}
return child
}
)
return (
<>
{triggerElement}
<ModalOverlay
isOpen={isOpen}
onOpenChange={handleOpenChange}
className={styles.overlay}
isDismissable
>
<Modal>
<AnimatePresence>
<ModalOverlay
isOpen={isOpen}
onOpenChange={onClose}
className={styles.overlay}
isDismissable
>
<Modal>
<AnimatePresence>
<Dialog aria-label={dialogTitle}>
{isOpen && (
<Dialog>
<motion.div
className={`${styles.content} ${
isFullView ? styles.fullViewContent : styles.galleryContent
}`}
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1, x: "-50%", y: "-50%" }}
exit={{ opacity: 0, scale: 0.95 }}
transition={{ duration: 0.2 }}
>
{isFullView ? (
<FullView
image={images[selectedImageIndex]}
onClose={() => setIsFullView(false)}
onNext={handleNext}
onPrev={handlePrev}
currentIndex={selectedImageIndex}
totalImages={images.length}
/>
) : (
<Gallery
images={images}
dialogTitle={dialogTitle}
onClose={() => setIsOpen(false)}
onSelectImage={(image) => {
setSelectedImageIndex(
images.findIndex((img) => img === image)
)
}}
onImageClick={() => setIsFullView(true)}
selectedImage={images[selectedImageIndex]}
/>
)}
</motion.div>
</Dialog>
<motion.div
className={`${styles.content} ${
isFullView ? styles.fullViewContent : styles.galleryContent
}`}
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1, x: "-50%", y: "-50%" }}
exit={{ opacity: 0, scale: 0.95 }}
transition={{ duration: 0.2 }}
>
{isFullView ? (
<FullView
image={images[selectedImageIndex]}
onClose={() => setIsFullView(false)}
onNext={handleNext}
onPrev={handlePrev}
currentIndex={selectedImageIndex}
totalImages={images.length}
/>
) : (
<Gallery
images={images}
onClose={onClose}
onSelectImage={(image) => {
setSelectedImageIndex(
images.findIndex((img) => img === image)
)
}}
onImageClick={() => setIsFullView(true)}
selectedImage={images[selectedImageIndex]}
/>
)}
</motion.div>
)}
</AnimatePresence>
</Modal>
</ModalOverlay>
</>
</Dialog>
</AnimatePresence>
</Modal>
</ModalOverlay>
)
}