feat(SW-3695): use svg icons instead of font icons * feat(icons): use svg instead of font icons * feat(icons): use webpack/svgr for inlined svgs. Now support for isFilled again * Merge master * Remove old font icon Approved-by: Joakim Jäderberg
103 lines
2.4 KiB
TypeScript
103 lines
2.4 KiB
TypeScript
"use client"
|
|
|
|
import { memo, useState } from "react"
|
|
import { Button as ButtonRAC } from "react-aria-components"
|
|
import { useIntl } from "react-intl"
|
|
|
|
import Image from "../Image"
|
|
import ImageFallback from "../ImageFallback"
|
|
import Lightbox from "../Lightbox"
|
|
|
|
import styles from "./imageGallery.module.css"
|
|
import { ImageCounter } from "../ImageCounter"
|
|
import { cx } from "class-variance-authority"
|
|
|
|
export interface GalleryImage {
|
|
src: string
|
|
alt: string
|
|
caption?: string | null
|
|
}
|
|
|
|
type ImageGalleryProps = {
|
|
images?: GalleryImage[]
|
|
title: string
|
|
fill?: boolean
|
|
width?: number
|
|
height?: number
|
|
sizes?: string
|
|
hideLabel?: boolean
|
|
imageCountPosition?: "top" | "bottom"
|
|
}
|
|
|
|
function ImageGallery({
|
|
images,
|
|
title,
|
|
fill,
|
|
height = 280,
|
|
sizes,
|
|
hideLabel,
|
|
imageCountPosition = "bottom",
|
|
}: ImageGalleryProps) {
|
|
const intl = useIntl()
|
|
const [isOpen, setIsOpen] = useState(false)
|
|
const [imageError, setImageError] = useState(false)
|
|
const imageProps = fill
|
|
? {
|
|
fill,
|
|
sizes:
|
|
sizes ?? "auto, (max-width: 400px) 100vw, (min-width: 401px) 500px",
|
|
}
|
|
: { height, width: height * 1.5 }
|
|
|
|
if (!images?.length || imageError) {
|
|
return <ImageFallback />
|
|
}
|
|
|
|
const firstImage = images[0]
|
|
|
|
return (
|
|
<>
|
|
<div className={styles.wrapper}>
|
|
<Image
|
|
className={styles.image}
|
|
src={firstImage.src}
|
|
alt={firstImage.alt}
|
|
onError={() => setImageError(true)}
|
|
{...imageProps}
|
|
/>
|
|
<ImageCounter
|
|
className={cx(styles.imageCount, {
|
|
[styles.imageCountTop]: imageCountPosition === "top",
|
|
[styles.imageCountBottom]: imageCountPosition === "bottom",
|
|
})}
|
|
number={images.length}
|
|
size="Large"
|
|
leadingIcon
|
|
/>
|
|
|
|
<ButtonRAC
|
|
className={styles.triggerArea}
|
|
onPress={() => setIsOpen(true)}
|
|
aria-label={intl.formatMessage({
|
|
id: "imageGallery.openImageGallery",
|
|
defaultMessage: "Open image gallery",
|
|
})}
|
|
/>
|
|
</div>
|
|
<Lightbox
|
|
images={images}
|
|
dialogTitle={title}
|
|
onClose={() => setIsOpen(false)}
|
|
isOpen={isOpen}
|
|
hideLabel={hideLabel}
|
|
/>
|
|
</>
|
|
)
|
|
}
|
|
|
|
const ImageGalleryComponent = memo(ImageGallery)
|
|
|
|
export default ImageGalleryComponent as React.MemoExoticComponent<
|
|
(props: ImageGalleryProps) => React.ReactElement
|
|
>
|