import React__default, { createContext, useContext, useState, useRef, useEffect } from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import ReactDOM__default from 'react-dom';
import { useFocusTrap, useDebounce, useIsMounted, useRefocusOnActivator, useOnKeyDown, useBreakpoints } from '@jobber/hooks';
import classnames from 'classnames';
import { n as noop } from './noop-es.js';
import { B as ButtonDismiss } from './ButtonDismiss-es.js';
import { T as Text } from './Text-es.js';
import { B as Button } from './Button-es.js';
import { H as Heading } from './Heading-es.js';
import { A as AtlantisThemeContextProvider } from './AtlantisThemeContext-es.js';

var styles = {"backgroundImage":"i9Tw1T65W-k-","next":"Q8amcRaTGf0-","prev":"W9FVb24yJrk-","buttonHidden":"nsN0TPWsBXI-","buttonVisible":"dkLYp7AD2jE-","lightboxWrapper":"_5p2iAj4JfoE-","toolbar":"rMK4cKdOxFw-","closeButton":"_0m6vb11DgiA-","slideNumber":"kCc68gGuTgg-","image":"yYFVVScosfQ-","imageArea":"UskuwLHR6fg-","captionWrapper":"OGjhge-r-U4-","title":"tZU2g-NYdIs-","blurOverlay":"GKIdLTmvcvQ-","thumbnailBar":"_3TfQLQEE3GQ-","thumbnailImage":"eBMzUOlcfQ4-","thumbnail":"eapm2zruLn8-","selected":"PeLn2u-QB0k-","spinning":"_8tDoqjgfLcw-"};

// A little bit more than the transition's duration
// We're doing this to prevent a bug from framer-motion
// https://github.com/framer/motion/issues/1769
const BUTTON_DEBOUNCE_DELAY = 250;
const MOVEMENT_DEBOUNCE_DELAY = 1000;
const swipeConfidenceThreshold = 10000;
const swipePower = (offset, velocity) => {
    return Math.abs(offset) * velocity;
};
const slideVariants = {
    enter: (directionRef) => ({
        x: directionRef.current > 0 ? "150%" : "-150%",
    }),
    center: {
        x: 0,
    },
    exit: (directionRef) => ({
        x: directionRef.current < 0 ? "150%" : "-150%",
    }),
};
const imageTransition = {
    x: { duration: 0.65, ease: [0.42, 0, 0, 1.03] },
};

/* eslint-disable max-statements */
const LightBoxContext = createContext({
    open: false,
    images: [],
    currentImageIndex: 0,
    mouseIsStationary: true,
    boxSizing: "content-box",
    directionRef: { current: 0 },
    selectedThumbnailRef: { current: null },
    lightboxRef: { current: null },
    mounted: { current: false },
    handleMouseMove: noop,
    handleRequestClose: noop,
    handleOnDragEnd: noop,
    handleThumbnailClick: noop,
    debouncedHandleNext: noop,
    debouncedHandlePrevious: noop,
});
function LightBoxProvider({ open = true, images, imageIndex = 0, onRequestClose = noop, onImageChange = noop, boxSizing = "content-box", children, }) {
    const [currentImageIndex, setCurrentImageIndex] = useState(imageIndex);
    const directionRef = useRef(0);
    const [mouseIsStationary, setMouseIsStationary] = useState(true);
    const lightboxRef = useFocusTrap(open);
    const selectedThumbnailRef = useRef(null);
    const debouncedHandleNext = useDebounce(handleMoveNext, BUTTON_DEBOUNCE_DELAY);
    const debouncedHandlePrevious = useDebounce(handleMovePrevious, BUTTON_DEBOUNCE_DELAY);
    const mounted = useIsMounted();
    const prevOpen = useRef(open);
    useRefocusOnActivator(open);
    const handleMouseMovement = useDebounce(() => {
        setMouseIsStationary(true);
    }, MOVEMENT_DEBOUNCE_DELAY);
    useOnKeyDown(handleRequestClose, "Escape");
    useOnKeyDown(debouncedHandlePrevious, {
        key: "ArrowLeft",
    });
    useOnKeyDown(debouncedHandleNext, {
        key: "ArrowRight",
    });
    useEffect(() => {
        setCurrentImageIndex(imageIndex);
        onImageChange(imageIndex);
    }, [imageIndex, open]);
    if (prevOpen.current !== open) {
        prevOpen.current = open;
        togglePrintStyles(open);
    }
    useEffect(() => {
        var _a;
        (_a = selectedThumbnailRef === null || selectedThumbnailRef === void 0 ? void 0 : selectedThumbnailRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({
            behavior: "smooth",
            block: "nearest",
            inline: "center",
        });
    }, [currentImageIndex]);
    function handleMouseMove() {
        if (mouseIsStationary) {
            setMouseIsStationary(false);
        }
        handleMouseMovement();
    }
    function handleMovePrevious() {
        directionRef.current = -1;
        const newIndex = (currentImageIndex + images.length - 1) % images.length;
        setCurrentImageIndex(newIndex);
        onImageChange(newIndex);
    }
    function handleMoveNext() {
        directionRef.current = 1;
        const newIndex = (currentImageIndex + 1) % images.length;
        setCurrentImageIndex(newIndex);
        onImageChange(newIndex);
    }
    function handleRequestClose() {
        onRequestClose({ lastPosition: currentImageIndex });
    }
    function handleOnDragEnd(_event, { offset, velocity }) {
        const swipe = swipePower(offset.x, velocity.x);
        if (swipe < -swipeConfidenceThreshold) {
            handleMoveNext();
        }
        else if (swipe > swipeConfidenceThreshold) {
            handleMovePrevious();
        }
    }
    function handleThumbnailClick(index) {
        if (index < currentImageIndex) {
            directionRef.current = -1;
        }
        else {
            directionRef.current = 1;
        }
        setCurrentImageIndex(index);
        onImageChange(index);
    }
    return (React__default.createElement(LightBoxContext.Provider, { value: {
            open,
            images,
            currentImageIndex,
            mouseIsStationary,
            boxSizing,
            directionRef,
            selectedThumbnailRef,
            lightboxRef,
            mounted,
            handleMouseMove,
            handleRequestClose,
            handleOnDragEnd,
            handleThumbnailClick,
            debouncedHandleNext,
            debouncedHandlePrevious,
        } }, children));
}
function useLightBoxContext() {
    return useContext(LightBoxContext);
}
function togglePrintStyles(open) {
    try {
        if (open) {
            document.documentElement.classList.add("atlantisLightBoxActive");
        }
        else {
            document.documentElement.classList.remove("atlantisLightBoxActive");
        }
    }
    catch (error) {
        console.error(error);
    }
}

function LightBoxContent() {
    const { open, lightboxRef, handleMouseMove } = useLightBoxContext();
    const mounted = useIsMounted();
    const template = (React__default.createElement(React__default.Fragment, null, open && (React__default.createElement("div", { className: styles.lightboxWrapper, tabIndex: 0, "aria-label": "Lightbox", key: "Lightbox", ref: lightboxRef, onMouseMove: handleMouseMove },
        React__default.createElement(LightBoxBackground, null),
        React__default.createElement(LightBoxOverlay, null),
        React__default.createElement(LightBoxToolbar, null),
        React__default.createElement(LightBoxSlides, null),
        React__default.createElement(LightBoxNavigation, null),
        React__default.createElement(LightBoxCaption, null),
        React__default.createElement(LightBoxThumbnails, null)))));
    return mounted.current
        ? ReactDOM__default.createPortal(template, document.body)
        : template;
}
function PreviousButton({ onClick, hideButton, className }) {
    const { mediumAndUp } = useBreakpoints();
    return (React__default.createElement("div", { className: `${className} ${hideButton ? styles.buttonHidden : styles.buttonVisible}` },
        React__default.createElement(Button, { size: mediumAndUp ? "large" : "small", variation: "subtle", type: "secondary", icon: "arrowLeft", ariaLabel: "Previous image", onClick: onClick })));
}
function NextButton({ onClick, hideButton, className }) {
    const { mediumAndUp } = useBreakpoints();
    return (React__default.createElement("div", { className: `${className} ${hideButton ? styles.buttonHidden : styles.buttonVisible}` },
        React__default.createElement(Button, { size: mediumAndUp ? "large" : "small", variation: "subtle", type: "secondary", icon: "arrowRight", ariaLabel: "Next image", onClick: onClick })));
}
/**
 * Blurred, desaturated copy of the current image rendered as a full-bleed
 * background behind the lightbox. Pass `className` to apply additional styles.
 */
function LightBoxBackground({ className }) {
    const { images, currentImageIndex } = useLightBoxContext();
    return (React__default.createElement("div", { className: classnames(styles.backgroundImage, className), style: {
            backgroundImage: `url("${images[currentImageIndex].url}")`,
        } }));
}
/**
 * Semi-transparent blur backdrop. Clicking it calls `onRequestClose`.
 * Pass `className` to apply additional styles.
 */
function LightBoxOverlay({ className }) {
    const { handleRequestClose } = useLightBoxContext();
    return (React__default.createElement("div", { className: classnames(styles.blurOverlay, className), onClick: handleRequestClose }));
}
/**
 * Top bar showing the current image counter (`1/3`) and a close button.
 * Styled for dark backgrounds.
 */
function LightBoxToolbar() {
    const { images, currentImageIndex, handleRequestClose } = useLightBoxContext();
    return (React__default.createElement(AtlantisThemeContextProvider, { dangerouslyOverrideTheme: "dark" },
        React__default.createElement("div", { className: styles.toolbar },
            React__default.createElement("div", { className: styles.slideNumber },
                React__default.createElement(Text, null, `${currentImageIndex + 1}/${images.length}`)),
            React__default.createElement("div", { className: styles.closeButton },
                React__default.createElement(ButtonDismiss, { ariaLabel: "Close", onClick: handleRequestClose })))));
}
/**
 * The animated hero image with swipe-to-navigate and slide animation.
 *
 * Pass `className` to add styles to the image wrapper. Supports
 * swipe-to-navigate (drag). Keyboard arrow navigation is handled by
 * `LightBox.Provider`.
 *
 * @example
 * ```tsx
 * <LightBox.Slides className={styles.imageArea} />
 * <LightBox.Navigation
 *   prevButtonClassName={styles.prev}
 *   nextButtonClassName={styles.next}
 * />
 * ```
 */
function LightBoxSlides({ className }) {
    const { images, currentImageIndex, directionRef, handleOnDragEnd } = useLightBoxContext();
    return (React__default.createElement("div", { className: classnames(styles.imageArea, className) },
        React__default.createElement(AnimatePresence, { initial: false },
            React__default.createElement(motion.img, { key: currentImageIndex, variants: slideVariants, src: images[currentImageIndex].url, custom: directionRef, className: styles.image, initial: "enter", alt: images[currentImageIndex].alt ||
                    images[currentImageIndex].title ||
                    "", animate: "center", exit: "exit", transition: imageTransition, drag: "x", dragConstraints: { left: 0, right: 0 }, dragElastic: 1, onDragEnd: handleOnDragEnd }))));
}
/**
 * Previous and next navigation buttons. Returns `null` when the image set
 * has only one image.
 *
 * Use `prevButtonClassName` and `nextButtonClassName` to override the styles
 * on each button's wrapper for custom layouts.
 *
 * @example
 * ```tsx
 * <LightBox.Navigation
 *   prevButtonClassName={styles.prev}
 *   nextButtonClassName={styles.next}
 * />
 * ```
 */
function LightBoxNavigation({ prevButtonClassName, nextButtonClassName, }) {
    const { images, mouseIsStationary, debouncedHandleNext, debouncedHandlePrevious, } = useLightBoxContext();
    if (images.length <= 1)
        return null;
    return (React__default.createElement(React__default.Fragment, null,
        React__default.createElement(PreviousButton, { onClick: debouncedHandlePrevious, hideButton: mouseIsStationary, className: classnames(styles.prev, prevButtonClassName) }),
        React__default.createElement(NextButton, { onClick: debouncedHandleNext, hideButton: mouseIsStationary, className: classnames(styles.next, nextButtonClassName) })));
}
/**
 * Title and caption text for the current image. Only renders when the current
 * image has a `title` or `caption`. Styled for dark backgrounds.
 */
function LightBoxCaption() {
    const { images, currentImageIndex } = useLightBoxContext();
    const { title, caption } = images[currentImageIndex];
    if (!title && !caption)
        return null;
    return (React__default.createElement("div", { className: styles.captionWrapper },
        React__default.createElement(AtlantisThemeContextProvider, { dangerouslyOverrideTheme: "dark" },
            title && (React__default.createElement("div", { className: styles.title },
                React__default.createElement(Heading, { level: 4 }, title))),
            caption && React__default.createElement(Text, { size: "large" }, caption))));
}
/**
 * Scrollable thumbnail strip. Only renders when there are two or more images.
 */
function LightBoxThumbnails() {
    const { images, currentImageIndex, boxSizing, selectedThumbnailRef, handleThumbnailClick, } = useLightBoxContext();
    if (images.length <= 1)
        return null;
    return (React__default.createElement("div", { className: styles.thumbnailBar, style: { "--lightbox--box-sizing": boxSizing }, "data-testid": "ATL-Thumbnail-Bar" }, images.map((image, index) => (React__default.createElement("div", { key: index, className: classnames(styles.thumbnail, {
            [styles.selected]: index === currentImageIndex,
        }), onClick: () => handleThumbnailClick(index), ref: index === currentImageIndex ? selectedThumbnailRef : null },
        React__default.createElement("img", { key: index, src: image.url, alt: image.alt || image.title || "", className: styles.thumbnailImage }))))));
}
/**
 * LightBox displays images in a fullscreen overlay.
 *
 * **Self-contained (legacy) usage:**
 * ```tsx
 * <LightBox
 *   open={isOpen}
 *   images={images}
 *   imageIndex={imageIndex}
 *   onRequestClose={({ lastPosition }) => { setIsOpen(false); }}
 * />
 * ```
 *
 * **Full composable (fullscreen) usage:**
 * ```tsx
 * <LightBox.Provider open={isOpen} images={images} onRequestClose={onClose}>
 *   <LightBox.Content />
 * </LightBox.Provider>
 * ```
 *
 * **Inline gallery usage (no overlay, no close):**
 * ```tsx
 * <LightBox.Provider
 *   open={true}
 *   images={images}
 *   imageIndex={activeIndex}
 *   onImageChange={onImageChange}
 * >
 *   <div className={styles.lightboxWrapper} onMouseMove={handleMouseMove}>
 *     <LightBox.Background className={styles.backgroundImage} />
 *     <LightBox.Overlay className={styles.blurOverlay} />
 *     <LightBox.Slides className={styles.imageArea} />
 *     <LightBox.Navigation
 *       prevButtonClassName={styles.prev}
 *       nextButtonClassName={styles.next}
 *     />
 *   </div>
 * </LightBox.Provider>
 * ```
 */
function LightBox(props) {
    return (React__default.createElement(LightBoxProvider, Object.assign({}, props),
        React__default.createElement(LightBoxContent, null)));
}
LightBox.Provider = LightBoxProvider;
LightBox.Content = LightBoxContent;
LightBox.Background = LightBoxBackground;
LightBox.Overlay = LightBoxOverlay;
LightBox.Toolbar = LightBoxToolbar;
LightBox.Slides = LightBoxSlides;
LightBox.Navigation = LightBoxNavigation;
LightBox.Caption = LightBoxCaption;
LightBox.Thumbnails = LightBoxThumbnails;

export { LightBox as L, useLightBoxContext as u };
