{"version":3,"file":"index.cjs","names":["useTheme","IconButton","X","ChevronLeft","ChevronRight","Button"],"sources":["../../../src/components/ImageGallery/GalleryModal.tsx","../../../src/components/ImageGallery/ImageGallery.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport { ChevronLeft, ChevronRight, X } from \"lucide-react\";\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { IconButton } from \"../IconButton\";\nimport { useTheme } from \"../ThemeProvider\";\nimport { ImageItem } from \"./ImageGallery\";\n\nexport interface GalleryModalProps {\n  images: ImageItem[];\n  selectedImageIndex: number;\n  setSelectedImageIndex: (index: number) => void;\n  onClose: () => void;\n}\n\nexport const GalleryModal: React.FC<GalleryModalProps> = ({\n  images,\n  selectedImageIndex,\n  setSelectedImageIndex,\n  onClose,\n}) => {\n  const [scrollButtons, setScrollButtons] = useState({ showLeft: false, showRight: false });\n  const carouselRef = useRef<HTMLDivElement>(null);\n  const modalContentRef = useRef<HTMLDivElement>(null);\n  const { portalThemeClassName } = useTheme();\n\n  // Check if scrolling is needed\n  const checkScroll = useCallback(() => {\n    if (!carouselRef.current) return;\n\n    const container = carouselRef.current;\n    setScrollButtons({\n      showLeft: container.scrollLeft > 0,\n      showRight: container.scrollLeft + container.offsetWidth < container.scrollWidth,\n    });\n  }, []);\n\n  useEffect(() => {\n    if (!carouselRef.current) {\n      return;\n    }\n\n    const container = carouselRef.current;\n    // Initial check\n    checkScroll();\n\n    const resizeObserver = new ResizeObserver(checkScroll);\n    resizeObserver.observe(container);\n\n    container.addEventListener(\"scroll\", checkScroll);\n\n    return () => {\n      container.removeEventListener(\"scroll\", checkScroll);\n      resizeObserver.disconnect();\n    };\n  }, [checkScroll]);\n\n  // Handle modal lifecycle events (scroll lock, close on escape, close on outside click)\n  useEffect(() => {\n    // Disable body scroll\n    document.body.style.overflow = \"hidden\";\n\n    const handleKeyDown = (e: KeyboardEvent) => {\n      if (e.key === \"Escape\") {\n        onClose();\n      }\n    };\n\n    const handleOutsideClick = (e: MouseEvent) => {\n      if (modalContentRef.current && !modalContentRef.current.contains(e.target as Node)) {\n        onClose();\n      }\n    };\n\n    document.addEventListener(\"keydown\", handleKeyDown);\n    document.addEventListener(\"mousedown\", handleOutsideClick);\n\n    // Cleanup\n    return () => {\n      document.body.style.overflow = \"auto\";\n      document.removeEventListener(\"keydown\", handleKeyDown);\n      document.removeEventListener(\"mousedown\", handleOutsideClick);\n    };\n  }, [onClose]);\n\n  const scroll = (direction: \"left\" | \"right\") => {\n    if (carouselRef.current) {\n      const container = carouselRef.current;\n      const containerRect = container.getBoundingClientRect();\n      const scrollAmount = containerRect.width * 0.28;\n\n      if (direction === \"left\") {\n        container.scrollBy({\n          left: -scrollAmount,\n          behavior: \"smooth\",\n        });\n      } else {\n        container.scrollBy({\n          left: scrollAmount,\n          behavior: \"smooth\",\n        });\n      }\n    }\n  };\n\n  // Memoize thumbnail click handler\n  const handleThumbnailClick = useCallback(\n    (index: number) => () => setSelectedImageIndex(index),\n    [setSelectedImageIndex],\n  );\n\n  return createPortal(\n    <div className={clsx(\"openui-gallery__modal\", portalThemeClassName)}>\n      <div\n        className=\"openui-gallery__modal-content\"\n        ref={modalContentRef}\n        role=\"dialog\"\n        aria-modal=\"true\"\n        aria-labelledby=\"openui-gallery-modal-heading\"\n      >\n        <div className=\"openui-gallery__modal-header\">\n          <span id=\"openui-gallery-modal-heading\" className=\"openui-gallery__modal-heading\">\n            All Photos\n          </span>\n          <IconButton\n            size=\"small\"\n            variant=\"secondary\"\n            icon={<X />}\n            onClick={onClose}\n            aria-label=\"Close gallery\"\n          />\n        </div>\n        <div className=\"openui-gallery__modal-main\">\n          <img\n            src={images[selectedImageIndex]?.src}\n            alt={images[selectedImageIndex]?.alt || `Gallery image ${selectedImageIndex + 1}`}\n          />\n        </div>\n        <div className=\"openui-gallery__modal-carousel-container\">\n          {scrollButtons.showLeft && (\n            <div\n              className={clsx(\n                \"openui-gallery__modal-carousel-button-container\",\n                \"openui-gallery__modal-carousel-button-container-left\",\n              )}\n            >\n              <IconButton\n                className={clsx(\n                  \"openui-gallery__carousel-button\",\n                  \"openui-gallery__carousel-button--left\",\n                )}\n                onClick={() => scroll(\"left\")}\n                aria-label=\"Scroll images left\"\n                icon={<ChevronLeft />}\n                variant=\"secondary\"\n                size=\"extra-small\"\n              />\n            </div>\n          )}\n\n          <div className=\"openui-gallery__modal-carousel\" ref={carouselRef}>\n            {images.map((image, index) => (\n              <div\n                key={index}\n                className={clsx(\n                  \"openui-gallery__modal-thumbnail\",\n                  index === selectedImageIndex && \"openui-gallery__modal-thumbnail--active\",\n                )}\n                role=\"button\"\n                tabIndex={0}\n                aria-label={image.alt || `Gallery image ${index + 1}`}\n                aria-pressed={index === selectedImageIndex}\n                onClick={handleThumbnailClick(index)}\n                onKeyDown={(e) => {\n                  if (e.key === \"Enter\" || e.key === \" \") {\n                    e.preventDefault();\n                    handleThumbnailClick(index)();\n                  }\n                }}\n              >\n                <img src={image.src} alt=\"\" aria-hidden=\"true\" />\n              </div>\n            ))}\n          </div>\n\n          {scrollButtons.showRight && (\n            <div\n              className={clsx(\n                \"openui-gallery__modal-carousel-button-container\",\n                \"openui-gallery__modal-carousel-button-container-right\",\n              )}\n            >\n              <IconButton\n                className={clsx(\n                  \"openui-gallery__carousel-button\",\n                  \"openui-gallery__carousel-button--right\",\n                )}\n                onClick={() => scroll(\"right\")}\n                aria-label=\"Scroll images right\"\n                icon={<ChevronRight />}\n                variant=\"secondary\"\n                size=\"extra-small\"\n              />\n            </div>\n          )}\n        </div>\n      </div>\n    </div>,\n    document.body,\n  );\n};\n","import clsx from \"clsx\";\nimport React, { useCallback, useMemo, useState } from \"react\";\nimport { Button } from \"../Button\";\nimport { GalleryModal } from \"./GalleryModal\";\n\nexport interface ImageItem {\n  src: string;\n  alt?: string;\n  details?: string;\n}\n\nexport interface OpenUIGalleryProps {\n  images: ImageItem[];\n}\n\nconst MAX_GRID_IMAGES = 5;\nconst getLayoutClassName = (imageCount: number): string => {\n  switch (imageCount) {\n    case 1:\n      return \"openui-gallery--single\";\n    case 2:\n      return \"openui-gallery--double\";\n    case 3:\n      return \"openui-gallery--triple\";\n    case 4:\n      return \"openui-gallery--quad\";\n    default:\n      return \"openui-gallery--default\";\n  }\n};\n\nexport const ImageGallery: React.FC<OpenUIGalleryProps> = ({ images }) => {\n  const [showAll, setShowAll] = useState(false);\n  const [selectedImageIndex, setSelectedImageIndex] = useState(0);\n\n  // Memoize layout class to prevent recalculation\n  const layoutClass = useMemo(() => getLayoutClassName(images.length), [images.length]);\n\n  // Memoize whether to show button\n  const shouldShowButton = useMemo(() => images.length > MAX_GRID_IMAGES, [images.length]);\n\n  // Memoize visible images\n  const visibleImages = useMemo(() => images.slice(0, MAX_GRID_IMAGES), [images]);\n\n  // Memoize callbacks\n  const toggleShowAll = useCallback(() => {\n    setShowAll((prev) => !prev);\n  }, []);\n\n  const handleImageClick = useCallback((index: number) => {\n    setSelectedImageIndex(index);\n    setShowAll(true);\n  }, []);\n\n  const setSelectedImageIndexMemoized = useCallback((index: number) => {\n    setSelectedImageIndex(index);\n  }, []);\n\n  return (\n    <div className={clsx(\"openui-gallery\", layoutClass)}>\n      <div className=\"openui-gallery__grid\">\n        {visibleImages.map((image, index) => (\n          <div\n            key={index}\n            className={clsx(\"openui-gallery__image\", index === 0 && \"openui-gallery__image--main\")}\n            onClick={() => handleImageClick(index)}\n          >\n            <img src={image.src} alt={image.alt || `Gallery image ${index + 1}`} />\n          </div>\n        ))}\n        {shouldShowButton && (\n          <div className=\"openui-gallery__show-all-button\">\n            <Button variant=\"primary\" size=\"small\" onClick={toggleShowAll}>\n              Show All\n            </Button>\n          </div>\n        )}\n      </div>\n\n      {showAll && (\n        <GalleryModal\n          images={images}\n          selectedImageIndex={selectedImageIndex}\n          setSelectedImageIndex={setSelectedImageIndexMemoized}\n          onClose={toggleShowAll}\n        />\n      )}\n    </div>\n  );\n};\n"],"mappings":"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"}