@grafana/ui
Version:
Grafana Components Library
1 lines • 11.4 kB
Source Map (JSON)
{"version":3,"file":"Carousel.mjs","sources":["../../../../src/components/Carousel/Carousel.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport { useState, useEffect } from 'react';\n\nimport { GrafanaTheme2 } from '@grafana/data';\n\nimport { useStyles2 } from '../../themes';\nimport { t } from '../../utils/i18n';\nimport { Alert } from '../Alert/Alert';\nimport { IconButton } from '../IconButton/IconButton';\n\n// Define the image item interface\nexport interface CarouselImage {\n path: string;\n name: string;\n}\n\nexport interface CarouselProps {\n images: CarouselImage[];\n}\n\nexport const Carousel: React.FC<CarouselProps> = ({ images }) => {\n const [selectedIndex, setSelectedIndex] = useState<number | null>(null);\n const [imageErrors, setImageErrors] = useState<Record<string, boolean>>({});\n const [validImages, setValidImages] = useState<CarouselImage[]>(images);\n\n const styles = useStyles2(getStyles());\n\n const handleImageError = (path: string) => {\n setImageErrors((prev) => ({\n ...prev,\n [path]: true,\n }));\n };\n\n useEffect(() => {\n const filteredImages = images.filter((image) => !imageErrors[image.path]);\n setValidImages(filteredImages);\n }, [imageErrors, images]);\n\n const openPreview = (index: number) => {\n setSelectedIndex(index);\n };\n\n const closePreview = () => {\n setSelectedIndex(null);\n };\n\n const goToNext = () => {\n if (selectedIndex !== null && validImages.length > 0) {\n setSelectedIndex((selectedIndex + 1) % validImages.length);\n }\n };\n\n const goToPrevious = () => {\n if (selectedIndex !== null && validImages.length > 0) {\n setSelectedIndex((selectedIndex - 1 + validImages.length) % validImages.length);\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (selectedIndex === null) {\n return;\n }\n\n switch (event.key) {\n case 'ArrowRight':\n goToNext();\n break;\n case 'ArrowLeft':\n goToPrevious();\n break;\n case 'Escape':\n closePreview();\n break;\n default:\n break;\n }\n };\n\n if (validImages.length === 0) {\n return (\n <Alert\n title={t('carousel.error', 'Something went wrong loading images')}\n severity=\"warning\"\n data-testid=\"alert-warning\"\n />\n );\n }\n\n return (\n <div onKeyDown={handleKeyDown} tabIndex={0}>\n <div className={cx(styles.imageGrid)}>\n {validImages.map((image, index) => (\n <div key={image.path} onClick={() => openPreview(index)} style={{ cursor: 'pointer' }}>\n <img src={image.path} alt={image.name} onError={() => handleImageError(image.path)} />\n <p>{image.name}</p>\n </div>\n ))}\n </div>\n\n {selectedIndex !== null && (\n <div className={cx(styles.fullScreenDiv)} onClick={closePreview} data-testid=\"carousel-full-screen\">\n <IconButton\n name=\"times\"\n aria-label={t('carousel.close', 'Close')}\n size=\"xl\"\n onClick={closePreview}\n className={cx(styles.closeButton)}\n />\n\n <IconButton\n size=\"xl\"\n name=\"angle-left\"\n aria-label={t('carousel.previous', 'Previous')}\n onClick={(e) => {\n e.stopPropagation();\n goToPrevious();\n }}\n className={cx(styles.navigationButton, styles.previousButton)}\n data-testid=\"previous-button\"\n />\n\n <div\n style={{ position: 'relative', maxWidth: '90%', maxHeight: '90%' }}\n onClick={(e) => e.stopPropagation()}\n data-testid=\"carousel-full-image\"\n >\n <img\n src={validImages[selectedIndex].path}\n alt={validImages[selectedIndex].name}\n onError={() => handleImageError(validImages[selectedIndex].path)}\n />\n </div>\n\n <IconButton\n size=\"xl\"\n name=\"angle-right\"\n aria-label={t('carousel.next', 'Next')}\n onClick={(e) => {\n e.stopPropagation();\n goToNext();\n }}\n className={cx(styles.navigationButton, styles.nextButton)}\n data-testid=\"next-button\"\n />\n </div>\n )}\n </div>\n );\n};\n\nconst getStyles = () => (theme: GrafanaTheme2) => ({\n imageGrid: css({\n display: 'grid',\n gridTemplateColumns: `repeat(auto-fill, minmax(200px, 1fr))`,\n gap: '16px',\n marginBottom: '20px',\n\n '& img': {\n width: '100%',\n height: '150px',\n objectFit: 'cover',\n border: theme.colors.border.strong,\n borderRadius: theme.shape.radius.default,\n boxShadow: theme.shadows.z1,\n },\n '& p': {\n margin: '4px 0',\n fontWeight: theme.typography.fontWeightMedium,\n color: theme.colors.text.primary,\n },\n }),\n fullScreenDiv: css({\n position: 'fixed',\n zIndex: theme.zIndex.modalBackdrop,\n top: 0,\n right: 0,\n bottom: 0,\n left: 0,\n backgroundColor: theme.components.overlay.background,\n alignItems: 'center',\n justifyContent: 'center',\n display: 'flex',\n\n '& img': {\n maxWidth: '100%',\n maxHeight: '80vh',\n objectFit: 'contain',\n },\n }),\n closeButton: css({\n position: 'absolute',\n top: '20px',\n right: '20px',\n backgroundColor: 'transparent',\n color: theme.colors.text.primary,\n }),\n navigationButton: css({\n position: 'absolute',\n backgroundColor: 'transparent',\n color: theme.colors.text.primary,\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }),\n nextButton: css({\n right: '20px',\n }),\n previousButton: css({\n left: '20px',\n }),\n});\n"],"names":[],"mappings":"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"}