From 1409769652a6331544f98a85dba3566528004fc4 Mon Sep 17 00:00:00 2001 From: AntoineBorda Date: Sat, 26 Oct 2024 22:40:19 +0200 Subject: [PATCH] [FEATURE] Add a zoom feature for images in the carousel --- assets/components/ui/carousel.tsx | 68 +++++++---- assets/components/ui/dialog.tsx | 126 ++++++++++++++++++++ assets/react/controllers/SatisfactoryBp.tsx | 1 - 3 files changed, 171 insertions(+), 24 deletions(-) create mode 100644 assets/components/ui/dialog.tsx diff --git a/assets/components/ui/carousel.tsx b/assets/components/ui/carousel.tsx index 4d3706e..2ec2f29 100644 --- a/assets/components/ui/carousel.tsx +++ b/assets/components/ui/carousel.tsx @@ -1,8 +1,9 @@ 'use client' import * as React from 'react' -import { ChevronLeft, ChevronRight } from 'lucide-react' +import { ChevronLeft, ChevronRight, X } from 'lucide-react' import { Button } from "@/components/ui/button" +import { Dialog, DialogContent, DialogClose } from "@/components/ui/dialog" import { ReactNode, useEffect, useState } from 'react' interface CarouselItem { @@ -11,75 +12,96 @@ interface CarouselItem { } interface CarouselProps { - items: CarouselItem[] - autoSlideInterval?: number // Optionnel : intervalle pour le diaporama automatique + items?: CarouselItem[] + autoSlideInterval?: number } -const Carousel: React.FC = ({ items, autoSlideInterval = 3000 }) => { +export default function Carousel({ items = [], autoSlideInterval = 3000 }: CarouselProps) { const [currentIndex, setCurrentIndex] = useState(0) + const [isEnlarged, setIsEnlarged] = useState(false) + const [enlargedIndex, setEnlargedIndex] = useState(0) const nextSlide = () => { - setCurrentIndex((prevIndex) => (prevIndex + 1) % items.length) + if (items.length > 0) { + setCurrentIndex((prevIndex) => (prevIndex + 1) % items.length) + } } const prevSlide = () => { - setCurrentIndex((prevIndex) => (prevIndex - 1 + items.length) % items.length) + if (items.length > 0) { + setCurrentIndex((prevIndex) => (prevIndex - 1 + items.length) % items.length) + } + } + + const handleImageClick = (index: number) => { + setEnlargedIndex(index) + setIsEnlarged(true) } useEffect(() => { - if (autoSlideInterval > 0) { + if (autoSlideInterval > 0 && !isEnlarged && items.length > 0) { const timer = setInterval(() => { nextSlide() }, autoSlideInterval) return () => clearInterval(timer) } - }, [currentIndex, autoSlideInterval]) + }, [currentIndex, autoSlideInterval, isEnlarged, items.length]) + + if (!items || items.length === 0) { + return
No items to display
+ } return (
-
+
- {items.map((item) => ( + {items.map((item, index) => (
-
- {/* Conteneur carré */} -
- {React.isValidElement(item.content) && React.cloneElement(item.content as React.ReactElement, { - className: "w-full h-full object-cover rounded", - })} - {/* Si content n'est pas une image, ajustez selon vos besoins */} -
+
handleImageClick(index)}> + {React.isValidElement(item.content) && React.cloneElement(item.content as React.ReactElement, { + className: "w-full h-full object-cover rounded-lg", + })}
))}
- {/* Bouton Précédent */} - {/* Bouton Suivant */} + + + +
+ {items[enlargedIndex] && React.isValidElement(items[enlargedIndex].content) && + React.cloneElement(items[enlargedIndex].content as React.ReactElement, { + className: "w-full h-full object-contain", + }) + } +
+
+
) } -export { Carousel } +export { Carousel } \ No newline at end of file diff --git a/assets/components/ui/dialog.tsx b/assets/components/ui/dialog.tsx new file mode 100644 index 0000000..b551957 --- /dev/null +++ b/assets/components/ui/dialog.tsx @@ -0,0 +1,126 @@ +'use client' + +import * as DialogPrimitive from '@radix-ui/react-dialog' +import { X } from 'lucide-react' + +import * as React from 'react' + +import { cn } from '@/lib/utils' +import { Button } from './button' + +const Dialog = DialogPrimitive.Root + +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal = DialogPrimitive.Portal + +const DialogClose = DialogPrimitive.Close + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +DialogContent.displayName = DialogPrimitive.Content.displayName + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogHeader.displayName = 'DialogHeader' + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogFooter.displayName = 'DialogFooter' + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogClose, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} \ No newline at end of file diff --git a/assets/react/controllers/SatisfactoryBp.tsx b/assets/react/controllers/SatisfactoryBp.tsx index af1cdf5..a766712 100644 --- a/assets/react/controllers/SatisfactoryBp.tsx +++ b/assets/react/controllers/SatisfactoryBp.tsx @@ -17,7 +17,6 @@ import { TooltipProvider, TooltipTrigger, } from '@/components/ui/tooltip' -import { Separator } from "@/components/ui/separator" import { CalendarClock, Download, Hammer, Heart, RefreshCcw, User } from "lucide-react"; interface Block {