From 2ea7936bcd576e9b83dc303de94158efbd03a17c Mon Sep 17 00:00:00 2001 From: Drew Pledger Date: Thu, 18 Jul 2024 15:30:27 -0500 Subject: [PATCH] refactor: gallery refactor --- .../[slug]/_components/gallery/index.tsx | 47 +-- core/components/ui/gallery/gallery.tsx | 359 +++++------------- 2 files changed, 89 insertions(+), 317 deletions(-) diff --git a/core/app/[locale]/(default)/product/[slug]/_components/gallery/index.tsx b/core/app/[locale]/(default)/product/[slug]/_components/gallery/index.tsx index 8d65ef77b4..684aa4c7ca 100644 --- a/core/app/[locale]/(default)/product/[slug]/_components/gallery/index.tsx +++ b/core/app/[locale]/(default)/product/[slug]/_components/gallery/index.tsx @@ -4,15 +4,7 @@ import { removeEdgesAndNodes } from '@bigcommerce/catalyst-client'; import { FragmentOf } from '~/client/graphql'; import { BcImage } from '~/components/bc-image'; -import { - Gallery as ComponentsGallery, - GalleryContent, - GalleryControls, - GalleryImage, - GalleryThumbnail, - GalleryThumbnailItem, - GalleryThumbnailList, -} from '~/components/ui/gallery'; +import { Gallery as ComponentsGallery } from '~/components/ui/gallery'; import { GalleryFragment } from './fragment'; @@ -46,42 +38,7 @@ export const Gallery = ({ product, noImageText }: Props) => { return (
- - - - {({ selectedImage }) => - selectedImage ? ( - - ) : ( -
-
- {noImageText ?? 'Coming soon'} -
-
- ) - } -
- -
- - {images.map((image, index) => { - return ( - - - - - - ); - })} - -
+
); diff --git a/core/components/ui/gallery/gallery.tsx b/core/components/ui/gallery/gallery.tsx index dedbfee1f7..b462b6f4a3 100644 --- a/core/components/ui/gallery/gallery.tsx +++ b/core/components/ui/gallery/gallery.tsx @@ -1,14 +1,13 @@ -import { Slot } from '@radix-ui/react-slot'; import { ChevronLeft, ChevronRight } from 'lucide-react'; import { + ComponentPropsWithoutRef, ComponentPropsWithRef, - createContext, ElementRef, forwardRef, - useContext, useEffect, useState, } from 'react'; +import { BcImage } from '~/components/bc-image'; import { cn } from '~/lib/utils'; @@ -17,282 +16,98 @@ interface Image { altText: string; } -const GalleryContext = createContext<{ +interface Props extends ComponentPropsWithoutRef<'div'> { images: Image[] | []; - selectedImageIndex: number; - setSelectedImageIndex: React.Dispatch>; -}>({ - images: [], - selectedImageIndex: 0, - setSelectedImageIndex: () => null, -}); - -const ThumbnailContext = createContext<{ - index: number; -}>({ - index: 0, -}); - -const GalleryPreviousIndicator = forwardRef, ComponentPropsWithRef<'button'>>( - ({ children, className, onClick, ...props }, ref) => { - const { images, selectedImageIndex, setSelectedImageIndex } = useContext(GalleryContext); - const previousIndex = selectedImageIndex === 0 ? images.length - 1 : selectedImageIndex - 1; - - return ( - - ); - }, -); - -GalleryPreviousIndicator.displayName = 'GalleryPreviousIndicator'; - -const GalleryNextIndicator = forwardRef, ComponentPropsWithRef<'button'>>( - ({ children, className, onClick, ...props }, ref) => { - const { images, selectedImageIndex, setSelectedImageIndex } = useContext(GalleryContext); - const nextIndex = selectedImageIndex + 1 < images.length ? selectedImageIndex + 1 : 0; - - return ( - - ); - }, -); - -GalleryNextIndicator.displayName = 'GalleryNextIndicator'; - -const GalleryControls = forwardRef, ComponentPropsWithRef<'div'>>( - ({ children, className, ...props }, ref) => { - const { images } = useContext(GalleryContext); - - if (images.length <= 1) { - return null; - } + defaultImageIndex?: number; +} - return ( -
{ + const [selectedImageIndex, setSelectedImageIndex] = useState(defaultImageIndex); + + const selectedImage = images.length > 0 ? images[selectedImageIndex] : undefined; + + return ( +
+
+ {selectedImage ? ( + + ) : ( +
+
Coming soon
+
)} - ref={ref} - {...props} - > - {children || ( - <> - - - + {images.length > 1 && ( +
+ + +
)} -
- ); - }, -); - -GalleryControls.displayName = 'GalleryControls'; - -interface GalleryImageProps extends Omit, 'children'> { - children?: (({ selectedImage }: { selectedImage?: Image }) => React.ReactNode) | React.ReactNode; -} - -const GalleryImage = forwardRef, GalleryImageProps>( - ({ className, children, ...props }, ref) => { - const { images, selectedImageIndex } = useContext(GalleryContext); - const selectedImage = images.length > 0 ? images[selectedImageIndex] : undefined; - - if (typeof children === 'function') { - return children({ selectedImage }); - } - - if (selectedImage) { - return ( - // eslint-disable-next-line @next/next/no-img-element - {selectedImage.altText} - ); - } - }, -); - -GalleryImage.displayName = 'GalleryImage'; - -const GalleryContent = forwardRef, ComponentPropsWithRef<'figure'>>( - ({ className, children, ...props }, ref) => { - return ( -
- {children}
- ); - }, -); - -GalleryContent.displayName = 'GalleryContent'; - -const GalleryThumbnailList = forwardRef, ComponentPropsWithRef<'nav'>>( - ({ children, className, ...props }, ref) => { - return ( - ); - }, -); - -GalleryThumbnailList.displayName = 'GalleryThumbnailList'; - -interface GalleryThumbnailItemProps extends ComponentPropsWithRef<'button'> { - imageIndex: number; -} - -const GalleryThumbnailItem = forwardRef, GalleryThumbnailItemProps>( - ({ className, children, imageIndex, onClick, ...props }, ref) => { - const { selectedImageIndex, setSelectedImageIndex } = useContext(GalleryContext); - const isActive = selectedImageIndex === imageIndex; - - return ( - - ); - }, -); - -GalleryThumbnailItem.displayName = 'GalleryThumbnailItem'; - -interface GalleryThumbnailProps extends ComponentPropsWithRef<'img'> { - asChild?: boolean; -} - -const GalleryThumbnail = forwardRef, GalleryThumbnailProps>( - ({ asChild, className, ...props }, ref) => { - const { selectedImageIndex } = useContext(GalleryContext); - const { index } = useContext(ThumbnailContext); - - const isActive = selectedImageIndex === index; - - const Comp = asChild ? Slot : 'img'; - - return ( - - ); - }, -); - -GalleryThumbnail.displayName = 'GalleryThumbnail'; - -interface GalleryProps extends ComponentPropsWithRef<'div'> { - images: Image[] | []; - defaultImageIndex?: number; -} - -const Gallery = forwardRef, GalleryProps>( - ({ className, children, images, defaultImageIndex = 0, ...props }, ref) => { - const [selectedImageIndex, setSelectedImageIndex] = useState(defaultImageIndex); - - useEffect(() => { - setSelectedImageIndex(defaultImageIndex); - }, [defaultImageIndex]); - - return ( - -
- {children} -
-
- ); - }, -); - -Gallery.displayName = 'Gallery'; - -export { - Gallery, - GalleryThumbnail, - GalleryThumbnailItem, - GalleryThumbnailList, - GalleryContent, - GalleryImage, - GalleryControls, - GalleryNextIndicator, - GalleryPreviousIndicator, +
+ ); }; + +export { Gallery };