{"version":3,"sources":["jsdelivr-header.js","/npm/yet-another-medium-zoom@0.4.2/src/types.ts","/npm/yet-another-medium-zoom@0.4.2/src/dom.ts","/npm/yet-another-medium-zoom@0.4.2/src/flip.ts","/npm/yet-another-medium-zoom@0.4.2/node_modules/style-inject/dist/style-inject.es.js","/npm/yet-another-medium-zoom@0.4.2/src/core.ts","/npm/yet-another-medium-zoom@0.4.2/src/swipe/detector.ts","/npm/yet-another-medium-zoom@0.4.2/src/index.ts","/npm/yet-another-medium-zoom@0.4.2/src/swipe/swipe.ts","/npm/yet-another-medium-zoom@0.4.2/src/album/album.ts","/npm/yet-another-medium-zoom@0.4.2/src/caption/caption.ts"],"names":[],"mappings":"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","file":"/npm/yet-another-medium-zoom@0.4.2/dist/yet-another-medium-zoom.umd.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.37.0.\n * Original file: /npm/yet-another-medium-zoom@0.4.2/dist/yet-another-medium-zoom.umd.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","import { MediumLightboxCore } from \"./core\";\r\n\r\nexport interface GlobalOptions {\r\n    scrollAllowance: number;\r\n    duration: number;\r\n    container?: HTMLElement;\r\n    lightboxGenerator?: (\r\n        $img: HTMLElement,\r\n        opts: ImageOptions,\r\n        $original: HTMLElement\r\n    ) => HTMLElement;\r\n}\r\n\r\nexport interface ImageOptions extends Partial<GlobalOptions> {\r\n    highres?: string;\r\n    class?: string;\r\n}\r\n\r\nexport interface YamzElement extends HTMLElement {\r\n    yamzOpts?: ImageOptions;\r\n}\r\n\r\nexport enum Classes {\r\n    WRAPPER = \"yamz__wrapper\",\r\n    WRAPPER_CLOSING = \"yamz__wrapper--closing\",\r\n    IMG_WRAPPER = \"yamz__img-wrapper\",\r\n    IMG = \"yamz__img\",\r\n    HIGHRES = \"yamz__highres\",\r\n    HAS_HIGHRES = \"yamz__wrapper--has-highres\",\r\n    HIGHRES_LOADED = \"yamz__wrapper--highres-loaded\",\r\n    CAPTION = \"yamz__caption\",\r\n    HAS_CAPTION = \"yamz__wrapper--has-caption\",\r\n    ORIGINAL = \"yamz__original\",\r\n    ORIGINAL_OPEN = \"yamz__original--open\",\r\n    LOADER = \"yamz__loader\",\r\n    ALBUM_PREV = \"yamz__album__prev\",\r\n    ALBUM_NEXT = \"yamz__album__next\",\r\n}\r\n\r\nexport enum STATES {\r\n    Closed,\r\n    Opening,\r\n    Open,\r\n    Closing,\r\n}\r\n\r\n// utility types\r\n// https://github.com/piotrwitek/utility-types/blob/ba66c895c7e52263268d179c142088f3e245a033/src/mapped-types.ts#L283-L296\r\nexport type Subtract<T extends object, U extends object> = Pick<T, Exclude<keyof T, keyof U>>;\r\ntype Overwrite<T extends object, U extends object> = Subtract<T, U> & U;\r\n/**\r\n * Applies a given Plugin, with its own GlobalOptions and ImageOptions, to an instance of YAMZ\r\n */\r\nexport type YamzPlugin<\r\n    Yamz extends MediumLightboxCore,\r\n    Plugin extends object,\r\n    NewGlobalOpts extends object,\r\n    NewImageOpts extends object\r\n> = Overwrite<\r\n    Yamz,\r\n    Overwrite<\r\n        {\r\n            defaultLightboxGenerator: (\r\n                $copiedImg: HTMLElement,\r\n                opts: Parameters<Yamz[\"defaultLightboxGenerator\"]>[1] & NewImageOpts,\r\n                $original: HTMLElement\r\n            ) => HTMLElement;\r\n            setOptions: (\r\n                options: Parameters<Yamz[\"setOptions\"]>[0] & Partial<NewGlobalOpts>\r\n            ) => ReturnType<Yamz[\"setOptions\"]>;\r\n            optsFromElm: ($elm: HTMLElement) => ReturnType<Yamz[\"optsFromElm\"]> & NewImageOpts;\r\n            open: (\r\n                $img: Parameters<Yamz[\"open\"]>[0],\r\n                opts?: Parameters<Yamz[\"open\"]>[1] & NewImageOpts\r\n            ) => ReturnType<Yamz[\"open\"]>;\r\n            replace: (\r\n                $img: Parameters<Yamz[\"replace\"]>[0],\r\n                opts?: Parameters<Yamz[\"replace\"]>[1] & NewImageOpts\r\n            ) => ReturnType<Yamz[\"replace\"]>;\r\n            bind: (\r\n                $imgs: Parameters<Yamz[\"bind\"]>[0],\r\n                opts?: Parameters<Yamz[\"bind\"]>[1] & NewImageOpts\r\n            ) => ReturnType<Yamz[\"bind\"]>;\r\n            options: Yamz[\"options\"] & NewGlobalOpts;\r\n        },\r\n        Plugin\r\n    >\r\n>;\r\n","import { ImageOptions, Classes } from \"./types\";\n\n/**\n * Creates an image for use in the lightbox based on an input element.\n * Always returns an <img>, regardless of the input element.\n */\nexport function generateLightboxImg(\n    $img: HTMLPictureElement | HTMLImageElement,\n    newSrc?: string\n): HTMLImageElement {\n    const $newImg = document.createElement(\"img\");\n    const src = newSrc ? newSrc : getSrcFromImage($img);\n    $newImg.src = src;\n\n    return $newImg;\n}\n\nexport function isValidImage($elm: HTMLElement): $elm is HTMLImageElement | HTMLPictureElement {\n    const types = [HTMLPictureElement, HTMLImageElement];\n    return types.some(type => $elm instanceof type);\n}\n\nexport function getHighResFromImage(\n    $image: HTMLImageElement | HTMLPictureElement,\n    targetWidth = document.body.clientWidth\n): string {\n    let cur = { width: $image.offsetWidth, src: getSrcFromImage($image) };\n    const $targets =\n        $image instanceof HTMLImageElement\n            ? [$image]\n            : Array.from($image.querySelectorAll(\"source\"));\n    $targets.forEach(($target: HTMLImageElement | HTMLSourceElement) => {\n        // ignore sources that don't match\n        if (\n            $target instanceof HTMLSourceElement &&\n            $target.media &&\n            !matchMedia($target.media).matches\n        ) {\n            return;\n        }\n        // extract size and URL from srcset\n        if (!$target.srcset) {\n            return;\n        }\n        const srcset = $target.srcset;\n        const parsed = getHighestFromSrcSet(srcset, targetWidth);\n        if (parsed && parsed.width > cur.width) {\n            cur = parsed;\n        }\n    });\n    return cur.src;\n}\n\nexport function getHighestFromSrcSet(srcset: string, targetWidth = document.body.clientWidth) {\n    const parsed = srcset.split(\",\").map(entry => {\n        const widthMatch = /([^ ]+) +(\\d+)w$/.exec(entry.trim());\n        if (!widthMatch) {\n            return null;\n        }\n        return {\n            src: widthMatch[1],\n            width: +widthMatch[2],\n        };\n    });\n\n    return parsed.reduce((prev, entry) => {\n        if (!entry) {\n            return prev;\n        }\n        if (!prev) {\n            return entry;\n        }\n        // if we've already found a smaller image that is bigger than the screen, use that image instead\n        if (entry.width > prev.width && prev.width >= targetWidth) {\n            return prev;\n        }\n        // if the one we've found is smaller than the previously found, only use it if it's bigger than targetWidth\n        if (entry.width < prev.width && entry.width < targetWidth) {\n            return prev;\n        }\n        return entry;\n    }, null);\n}\n\nexport function getSrcFromImage($elm: HTMLImageElement | HTMLPictureElement): string {\n    if ($elm instanceof HTMLImageElement) {\n        return $elm.currentSrc || /* IE11 support */ $elm.src;\n    }\n    if ($elm instanceof HTMLPictureElement) {\n        const $img = $elm.querySelector(\"img\");\n        if ($img) {\n            return $img.currentSrc || /* IE11 support */ $img.src;\n        }\n    }\n    return \"\";\n}\n\nexport function getScrollPosition(horizontal: boolean = false): number {\n    return horizontal\n        ? window.scrollX || document.body.scrollLeft || document.documentElement.scrollLeft || 0\n        : window.scrollY || document.body.scrollTop || document.documentElement.scrollTop || 0;\n}\n\nexport function defaultLightboxGenerator(\n    $copiedImg: HTMLElement,\n    opts: ImageOptions,\n    $original: HTMLElement\n) {\n    const $wrapper = document.createElement(\"aside\");\n    $wrapper.classList.add(Classes.WRAPPER);\n    if (opts.class) {\n        $wrapper.classList.add(opts.class);\n    }\n\n    const $imgWrapper = document.createElement(\"div\");\n    $imgWrapper.classList.add(Classes.IMG_WRAPPER);\n    $imgWrapper.appendChild($copiedImg);\n    $wrapper.appendChild($imgWrapper);\n\n    // add loading UI if we're going to load a highres\n    if (opts.highres) {\n        $wrapper.classList.add(Classes.HAS_HIGHRES);\n        const $loader = document.createElement(\"div\");\n        $loader.classList.add(Classes.LOADER);\n        $imgWrapper.insertBefore($loader, $copiedImg);\n    }\n\n    return $wrapper;\n}\n","import { getScrollPosition } from \"./dom\";\n\n/** Used to make sure a single element never has two animations at a time */\nconst elmMap: Map<HTMLElement, FLIPElement> = new Map();\n\n/** https://aerotwist.com/blog/flip-your-animations/ */\nexport default class FLIPElement {\n    $elm: HTMLElement;\n    playing: boolean = false;\n    _first?: Snapshot;\n    _last?: Snapshot;\n    _elmPos?: Snapshot;\n    _target$Elm?: HTMLElement;\n    _playResolver?: (val?: unknown) => void;\n    _transitionFallback?: number;\n\n    constructor($elm: HTMLElement) {\n        this.$elm = $elm;\n\n        if (elmMap.has($elm)) {\n            const self = elmMap.get($elm);\n            if (self) {\n                return self;\n            }\n        }\n\n        elmMap.set($elm, this);\n        this._onTransitionEnd = this._onTransitionEnd.bind(this);\n        this.stop = this.stop.bind(this);\n    }\n\n    first($elm: HTMLElement = this.$elm) {\n        if (this.playing) {\n            this.stop();\n        }\n\n        this._first = getSnapshot($elm);\n        return this;\n    }\n\n    last($elm: HTMLElement = this.$elm) {\n        if (this.playing) {\n            this.stop();\n        }\n\n        this._last = getSnapshot($elm);\n        return this;\n    }\n\n    invert($elm: HTMLElement = this.$elm) {\n        if (!this._first || !this._last) {\n            throw new Error(\".first() and .last() must be called before .invert()\");\n        }\n\n        this._elmPos = getSnapshot($elm);\n        $elm.style.transitionDuration = \"0s\";\n        $elm.style.transformOrigin = \"50% 50%\";\n        $elm.style.transform = getTransform(this._elmPos, this._first);\n\n        this._target$Elm = $elm;\n        return this;\n    }\n\n    play(duration = 300) {\n        if (!this._target$Elm || !this._elmPos || !this._first || !this._last) {\n            throw new Error(\".invert() must be called before .play()\");\n        }\n        if (this.playing) {\n            this.stop();\n        }\n        this.playing = true;\n\n        const $elm = this._target$Elm;\n        +$elm.offsetHeight; // force reflow\n        $elm.style.transitionDuration = `${duration}ms`;\n        $elm.style.transform = getTransform(this._elmPos, this._last);\n\n        $elm.addEventListener(\"transitioncancel\", this._onTransitionEnd);\n        $elm.addEventListener(\"transitionend\", this._onTransitionEnd);\n        clearTimeout(this._transitionFallback);\n        this._transitionFallback = (setTimeout(this.stop, duration + 50) as unknown) as number;\n\n        return new Promise((res, rej) => {\n            this._playResolver = res;\n        });\n    }\n\n    stop() {\n        clearTimeout(this._transitionFallback);\n        if (this._target$Elm) {\n            this._target$Elm.removeEventListener(\"transitioncancel\", this._onTransitionEnd);\n            this._target$Elm.removeEventListener(\"transitionend\", this._onTransitionEnd);\n        }\n        if (this._playResolver) {\n            this._playResolver();\n            this._playResolver = undefined;\n        }\n        this.playing = false;\n        this._target$Elm = undefined;\n    }\n\n    /** Updates an animation while it's playing */\n    update($target: HTMLElement, updater?: () => void, duration?: number) {\n        const $elm = this._target$Elm;\n        if (!this.playing || !$elm || !this._first) {\n            return;\n        }\n\n        const currentPos = getTransformedSnapshot($elm);\n        if (updater) {\n            updater();\n        }\n        this._elmPos = getSnapshot($elm);\n        this._last = getSnapshot($target);\n        const prevDuration = duration ? `${duration}ms` : $elm.style.transitionDuration;\n        $elm.style.transitionDuration = `0ms`;\n        $elm.style.transform = getTransform(this._elmPos, currentPos);\n        +$elm.offsetHeight; // force reflow\n        $elm.style.transitionDuration = prevDuration;\n        $elm.style.transform = getTransform(this._elmPos, this._last);\n    }\n\n    _onTransitionEnd(e: TransitionEvent) {\n        if (e.target === this._target$Elm && e.propertyName === \"transform\") {\n            this.stop();\n        }\n    }\n}\n\ninterface Snapshot {\n    left: number;\n    top: number;\n    width: number;\n    height: number;\n}\n\nexport function getSnapshot($elm: HTMLElement): Snapshot {\n    const outp = {\n        width: $elm.offsetWidth,\n        height: $elm.offsetHeight,\n        left: $elm.offsetLeft,\n        top: $elm.offsetTop,\n    };\n\n    // make sure left/top is measured from center\n    // this allows us to combine scaling and translating\n    outp.left += outp.width / 2;\n    outp.top += outp.height / 2;\n\n    // offsetLeft/Top relates to offsetParent. Walk up the tree to get it relative to the window\n    while (\n        $elm.offsetParent instanceof HTMLElement &&\n        $elm.offsetParent &&\n        $elm.offsetParent !== document.body &&\n        $elm.offsetParent !== document.documentElement\n    ) {\n        $elm = $elm.offsetParent;\n        outp.left += $elm.offsetLeft;\n        outp.top += $elm.offsetTop;\n    }\n\n    // if the element is fixed, offsetLeft/Top will be 0 when we want it to be the scroll position\n    if (\n        $elm.offsetTop === 0 &&\n        $elm.offsetLeft === 0 &&\n        window.getComputedStyle($elm).position === \"fixed\"\n    ) {\n        const $doc = document.documentElement;\n        outp.left += getScrollPosition(true) - ($doc.clientLeft || 0);\n        outp.top += getScrollPosition() - ($doc.clientTop || 0);\n    }\n\n    return outp;\n}\n\n/** Gets the snapshot of an element, but doesn't ignore transforms (unlike getSnapshot) */\nfunction getTransformedSnapshot($elm: HTMLElement): Snapshot {\n    const boundingRect = $elm.getBoundingClientRect();\n    const $doc = document.documentElement;\n    const outp = {\n        left: Math.round(boundingRect.left) + getScrollPosition(true) - ($doc.clientLeft || 0),\n        top: Math.round(boundingRect.top) + getScrollPosition() - ($doc.clientTop || 0),\n        width: Math.round(boundingRect.width),\n        height: Math.round(boundingRect.height),\n    };\n    outp.left += outp.width / 2;\n    outp.top += outp.height / 2;\n    return outp;\n}\n\nfunction getTransform(from: Snapshot, to: Snapshot) {\n    const delta = {\n        left: to.left - from.left,\n        top: to.top - from.top,\n        width: to.width / from.width,\n        height: to.height / from.height,\n    };\n\n    const translation = `translate(${delta.left.toFixed(5)}px, ${delta.top.toFixed(5)}px)`;\n    const scaling = `scale(${delta.width.toFixed(5)}, ${delta.height.toFixed(5)})`;\n    return `${translation} ${scaling}`;\n}\n","function styleInject(css, ref) {\n  if ( ref === void 0 ) ref = {};\n  var insertAt = ref.insertAt;\n\n  if (!css || typeof document === 'undefined') { return; }\n\n  var head = document.head || document.getElementsByTagName('head')[0];\n  var style = document.createElement('style');\n  style.type = 'text/css';\n\n  if (insertAt === 'top') {\n    if (head.firstChild) {\n      head.insertBefore(style, head.firstChild);\n    } else {\n      head.appendChild(style);\n    }\n  } else {\n    head.appendChild(style);\n  }\n\n  if (style.styleSheet) {\n    style.styleSheet.cssText = css;\n  } else {\n    style.appendChild(document.createTextNode(css));\n  }\n}\n\nexport default styleInject;\n","import { ImageOptions, GlobalOptions, Classes, STATES, YamzElement } from \"./types\";\r\nimport {\r\n    defaultLightboxGenerator,\r\n    isValidImage,\r\n    getSrcFromImage,\r\n    getHighResFromImage,\r\n    generateLightboxImg,\r\n    getScrollPosition,\r\n} from \"./dom\";\r\nimport FLIPElement from \"./flip\";\r\nimport \"./style.css\";\r\n\r\nexport const DEFAULT_OPTS: GlobalOptions = {\r\n    scrollAllowance: 128,\r\n    duration: 300,\r\n    container: undefined,\r\n    lightboxGenerator: undefined,\r\n};\r\n\r\nexport class MediumLightboxCore {\r\n    options: GlobalOptions = {\r\n        ...DEFAULT_OPTS,\r\n    };\r\n    state: STATES = STATES.Closed;\r\n    active?: {\r\n        $lightbox: HTMLElement;\r\n        $img: HTMLElement;\r\n        $copiedImg: HTMLImageElement;\r\n        $highRes?: HTMLImageElement;\r\n        scrollPos: number;\r\n        origSrc?: string;\r\n        options: ImageOptions;\r\n    } = undefined;\r\n    _flip?: FLIPElement;\r\n\r\n    _raf: boolean = false;\r\n\r\n    constructor() {\r\n        this._onScroll = this._onScroll.bind(this);\r\n        this._onKeyDown = this._onKeyDown.bind(this);\r\n    }\r\n\r\n    /** Set options used by every lightbox */\r\n    setOptions(newOpts: Partial<GlobalOptions>) {\r\n        this.options = {\r\n            ...this.options,\r\n            ...newOpts,\r\n        };\r\n    }\r\n    /** Get the currently set global options */\r\n    getOptions() {\r\n        return this.options;\r\n    }\r\n\r\n    /** Open a specific image in the lightbox */\r\n    async open($img: YamzElement, opts?: ImageOptions): Promise<HTMLElement> {\r\n        if (!isValidImage($img)) {\r\n            throw new TypeError(`${$img} cannot be used as an image`);\r\n        }\r\n        if (this.active) {\r\n            await this.close();\r\n        }\r\n\r\n        const options = {\r\n            ...this.options,\r\n            ...($img.yamzOpts || {}),\r\n            ...(opts || {}),\r\n        };\r\n\r\n        // generate our lightbox\r\n        this.state = STATES.Opening;\r\n        this.active = {\r\n            ...this.generateLightbox($img, options),\r\n            options,\r\n            scrollPos: getScrollPosition(),\r\n        };\r\n\r\n        // then insert and animate it\r\n        (options.container || document.body).appendChild(this.active.$lightbox);\r\n        this.active.$lightbox.style.top = `${this.active.scrollPos}px`;\r\n        const $animElm = this.active.$copiedImg.parentElement || this.active.$copiedImg;\r\n        let $positionElm = $img.nodeName === \"PICTURE\" ? $img.querySelector(\"img\") : $img;\r\n        if (!$positionElm) {\r\n            $positionElm = $img;\r\n        }\r\n        if (options.duration > 0) {\r\n            this._flip = new FLIPElement($img);\r\n            await this._flip\r\n                .first($positionElm)\r\n                .last(this.active.$copiedImg)\r\n                .invert($animElm)\r\n                .play(options.duration);\r\n        }\r\n        this.state = STATES.Open;\r\n\r\n        this.attachListeners();\r\n\r\n        return this.active.$lightbox;\r\n    }\r\n\r\n    /** Close the currently active image. If img is given, only closes if that's the currently active img */\r\n    async close($img?: YamzElement): Promise<void> {\r\n        if (!this.active) {\r\n            return;\r\n        }\r\n        if ($img && this.active.$img !== $img) {\r\n            return;\r\n        }\r\n        if (!$img) {\r\n            $img = this.active.$img;\r\n        }\r\n\r\n        this.detachListeners();\r\n\r\n        this.state = STATES.Closing;\r\n        const active = this.active; // we store this for later in case .active is updated while we're animating the close\r\n        const options = active.options;\r\n        this.active.$lightbox.classList.add(Classes.WRAPPER_CLOSING);\r\n        const $animElm = this.active.$copiedImg.parentElement || this.active.$copiedImg;\r\n        let $positionElm =\r\n            this.active.$img.nodeName === \"PICTURE\" ? this.active.$img.querySelector(\"img\") : $img;\r\n        if (!$positionElm) {\r\n            $positionElm = this.active.$img;\r\n        }\r\n        if (options.duration) {\r\n            const flip = new FLIPElement($img);\r\n            flip.first(this.active.$copiedImg).last($positionElm);\r\n\r\n            await flip.invert($animElm).play(options.duration);\r\n        }\r\n        active.$img.classList.remove(Classes.ORIGINAL_OPEN);\r\n        const $parent = active.$lightbox.parentNode;\r\n        if ($parent) {\r\n            $parent.removeChild(active.$lightbox);\r\n        }\r\n        this.state = STATES.Closed;\r\n\r\n        if (this.active === active) {\r\n            this.active = undefined;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Replaces the currently open lightbox with that of another image, without animating a close/open\r\n     */\r\n    replace($img: YamzElement, opts?: ImageOptions) {\r\n        if (!isValidImage($img)) {\r\n            throw new TypeError(`${$img} cannot be used as an image`);\r\n        }\r\n        if (!this.active) {\r\n            return;\r\n        }\r\n\r\n        // unhide the original image\r\n        this.active.$img.classList.remove(Classes.ORIGINAL_OPEN);\r\n\r\n        // then generate the new lightbox and set it as active\r\n        const $oldLightbox = this.active.$lightbox;\r\n        const nextOpts = {\r\n            ...this.options,\r\n            ...($img.yamzOpts || {}),\r\n            ...(opts || {}),\r\n        };\r\n        const nextActive = this.generateLightbox($img, nextOpts);\r\n        this.active = {\r\n            ...this.active,\r\n            ...nextActive,\r\n            $lightbox: $oldLightbox,\r\n            options: nextOpts,\r\n        };\r\n\r\n        // then update the DOM\r\n        this.replaceLightboxDOM(nextActive.$lightbox, $oldLightbox);\r\n    }\r\n\r\n    /**\r\n     * Replaces the currently active lightbox DOM with the given one\r\n     * Mostly its own method so plugins can overwrite it\r\n     */\r\n    replaceLightboxDOM($newLightbox: HTMLElement, $oldLightbox?: HTMLElement) {\r\n        if (!$oldLightbox) {\r\n            $oldLightbox = this.active && this.active.$lightbox;\r\n        }\r\n        if (!$oldLightbox) {\r\n            return;\r\n        }\r\n\r\n        /**\r\n         * We replace the content of the lightbox instead of just replacing the element itself because the open\r\n         * animations (e.g. fade-in of background) are CSS animations, that would replay if a new lightbox was inserted\r\n         * TODO: consider whether this approach is better than having a CSS class that disables open animation\r\n         */\r\n\r\n        // replace the content of the current lightbox with that of the target lightbox\r\n        while ($oldLightbox.firstChild) {\r\n            $oldLightbox.removeChild($oldLightbox.firstChild);\r\n        }\r\n        const $children = Array.from($newLightbox.children);\r\n        for (let i = 0; i < $children.length; ++i) {\r\n            $oldLightbox.appendChild($children[i]);\r\n        }\r\n\r\n        // update the lightbox's attributes to match the new one\r\n        $oldLightbox.setAttribute(\"class\", $newLightbox.className);\r\n    }\r\n\r\n    /**\r\n     * Function for generating lightbox for a given image.\r\n     * This also handles loading the highres and stuff.\r\n     * If you're only looking for generating the DOM (e.g. if you're creating a custom lightbox generator), use .defaultLightboxGenerator\r\n     */\r\n    generateLightbox(\r\n        $img: HTMLPictureElement | HTMLImageElement,\r\n        opts: GlobalOptions & ImageOptions\r\n    ): {\r\n        $img: HTMLPictureElement | HTMLImageElement;\r\n        $copiedImg: HTMLImageElement;\r\n        $lightbox: HTMLElement;\r\n        origSrc: string;\r\n        $highRes?: HTMLImageElement;\r\n    } {\r\n        const generator = opts.lightboxGenerator || this.defaultLightboxGenerator;\r\n        const origSrc = getSrcFromImage($img);\r\n        const hasSrcSet = $img instanceof HTMLPictureElement || $img.srcset;\r\n\r\n        // if we weren't explicitly given a highres, try to extract one from the image\r\n        if (!opts.highres && hasSrcSet) {\r\n            const highRes = getHighResFromImage($img);\r\n            opts.highres = highRes;\r\n        }\r\n\r\n        // generate the DOM\r\n        const $copiedImg = generateLightboxImg($img);\r\n        $copiedImg.classList.add(Classes.IMG);\r\n        $copiedImg.classList.remove(Classes.ORIGINAL);\r\n        $img.classList.add(Classes.ORIGINAL_OPEN);\r\n        const $lightbox = generator.call(this, $copiedImg, opts, $img);\r\n\r\n        // add event listeners\r\n        $lightbox.addEventListener(\"click\", () => this.close());\r\n\r\n        // and start loading high-res if we need to\r\n        // start loading the highres version if we have one\r\n        let $highRes: HTMLImageElement | undefined;\r\n        if (opts.highres) {\r\n            $highRes = new Image();\r\n            $highRes.decoding = \"async\";\r\n            $highRes.addEventListener(\"load\", () => {\r\n                if (this.active && this.active.$img === $img) {\r\n                    this._highResLoaded($highRes as HTMLImageElement);\r\n                }\r\n            });\r\n            $highRes.addEventListener(\"error\", e => {\r\n                console.error(`High-res image failed to load`, e);\r\n                $lightbox.classList.remove(Classes.HAS_HIGHRES);\r\n                const $loader = $lightbox.querySelector(`.${Classes.LOADER}`);\r\n                if ($loader && $loader.parentNode) {\r\n                    $loader.parentNode.removeChild($loader);\r\n                }\r\n            });\r\n            $highRes.src = opts.highres;\r\n            $highRes.classList.add(Classes.HIGHRES);\r\n        }\r\n\r\n        return {\r\n            $img,\r\n            $copiedImg,\r\n            $lightbox,\r\n            origSrc,\r\n            $highRes,\r\n        };\r\n    }\r\n\r\n    /** Called when a high-res version of an image has loaded */\r\n    _highResLoaded($highRes: HTMLImageElement) {\r\n        if (!this.active) {\r\n            return;\r\n        }\r\n        const $copiedImg = this.active.$copiedImg;\r\n        const $animElm = $copiedImg.parentElement || $copiedImg;\r\n\r\n        // function that inserts the highres, resizing the img wrapper to the size of the highres\r\n        const updater = () => {\r\n            if (!this.active) {\r\n                return;\r\n            }\r\n            if ($copiedImg.parentElement) {\r\n                this.active.$highRes = $highRes;\r\n                this.active.$lightbox.classList.add(Classes.HIGHRES_LOADED);\r\n                $copiedImg.parentElement.insertBefore(\r\n                    $highRes,\r\n                    $copiedImg.parentElement.firstChild\r\n                );\r\n            }\r\n        };\r\n\r\n        if (this.state === STATES.Opening && this._flip) {\r\n            this._flip.update($animElm, updater, this.active.options.duration);\r\n        } else if (this.state === STATES.Open && this.active) {\r\n            this._flip = new FLIPElement(this.active.$img);\r\n            this._flip.first(this.active.$copiedImg);\r\n            updater();\r\n            this._flip\r\n                .last(this.active.$copiedImg)\r\n                .invert($animElm)\r\n                .play(this.active.options.duration);\r\n        } else {\r\n            updater();\r\n        }\r\n    }\r\n\r\n    /** Parses options from a DOM element */\r\n    optsFromElm($elm: HTMLElement): ImageOptions {\r\n        const outp: ImageOptions = {};\r\n\r\n        if ($elm.dataset.class) {\r\n            outp.class = $elm.dataset.class;\r\n        }\r\n        if ($elm.dataset.highres) {\r\n            outp.highres = $elm.dataset.highres;\r\n        }\r\n        if ($elm.dataset.duration && !Number.isNaN(+$elm.dataset.duration)) {\r\n            outp.duration = +$elm.dataset.duration;\r\n        }\r\n        if ($elm.dataset.scrollAllowance && !Number.isNaN(+$elm.dataset.scrollAllowance)) {\r\n            outp.scrollAllowance = +$elm.dataset.scrollAllowance;\r\n        }\r\n\r\n        return outp;\r\n    }\r\n\r\n    /** Binds an image (or multiple), such that clicking it will open it\r\n     * @param $imgs The image(s) to bind. If this is a string, it's used as a selector. */\r\n    bind($imgs: HTMLElement | HTMLElement[] | string, opts?: ImageOptions): void {\r\n        if (typeof $imgs === \"string\") {\r\n            $imgs = Array.from(document.querySelectorAll($imgs));\r\n        }\r\n        if (!($imgs instanceof Array)) {\r\n            $imgs = [$imgs];\r\n        }\r\n\r\n        $imgs.forEach($img => {\r\n            $img.addEventListener(\"click\", () => {\r\n                // we extract options from the DOM here so that developers can change the data attributes and have it reflected\r\n                const imgOpts = {\r\n                    ...this.optsFromElm($img),\r\n                    ...(opts || {}),\r\n                };\r\n                this.open($img, imgOpts);\r\n            });\r\n            $img.classList.add(Classes.ORIGINAL);\r\n\r\n            // we store the custom opts given to us so we can later recreate the lightbox just from the element\r\n            if (opts) {\r\n                ($img as YamzElement).yamzOpts = opts;\r\n            }\r\n        });\r\n    }\r\n\r\n    /** Attaches listeners we need globally */\r\n    attachListeners() {\r\n        window.addEventListener(\"scroll\", this._onScroll);\r\n        document.addEventListener(\"keydown\", this._onKeyDown);\r\n    }\r\n\r\n    /** Detaches global listeners */\r\n    detachListeners() {\r\n        window.removeEventListener(\"scroll\", this._onScroll);\r\n        document.removeEventListener(\"keydown\", this._onKeyDown);\r\n    }\r\n\r\n    /** Helper function used as scroll listener. Debounces calls to .onScroll */\r\n    _onScroll(): void {\r\n        if (this._raf) {\r\n            return;\r\n        }\r\n        this._raf = true;\r\n        setTimeout(() => {\r\n            this._raf = false;\r\n            this.onScroll();\r\n        }, 60);\r\n    }\r\n    onScroll(): void {\r\n        if (!this.active) {\r\n            return;\r\n        }\r\n        if (\r\n            this.active.options.scrollAllowance === undefined ||\r\n            this.active.options.scrollAllowance < 0\r\n        ) {\r\n            return;\r\n        }\r\n        const scrollAllowance = this.active.options.scrollAllowance;\r\n        const scrollPos = getScrollPosition();\r\n        const delta = Math.abs(this.active.scrollPos - scrollPos);\r\n\r\n        if (delta > scrollAllowance) {\r\n            this.close();\r\n        }\r\n    }\r\n\r\n    /** Helper function used to ensure that .onKeyDown is called with proper `this` value, even if overwritten by plugins */\r\n    _onKeyDown(e: KeyboardEvent) {\r\n        this.onKeyDown(e);\r\n    }\r\n    onKeyDown(e: KeyboardEvent) {\r\n        if (!this.active) {\r\n            return;\r\n        }\r\n        if (e.key === \"Escape\") {\r\n            this.close();\r\n        }\r\n    }\r\n\r\n    // re-export some stuff so it's easily available to plugins\r\n    defaultLightboxGenerator = defaultLightboxGenerator;\r\n}\r\n\r\nexport default new MediumLightboxCore();\r\n","type coordinates = {\n    x: number;\n    y: number;\n};\ntype listeners = {\n    start?: (position: coordinates, metadata?: any) => void;\n    update?: (offset: coordinates, metadata?: any) => void;\n    end?: (direction: \"left\" | \"right\", metadata?: any) => void;\n    cancel?: (metadata?: any) => void;\n};\n\nexport default class SwipeDetector {\n    listeners: listeners;\n    state?: {\n        startTouch: coordinates & { time: number };\n        lastTouch: coordinates & { time: number };\n        identifier?: number;\n        velocity: number;\n        isSwipe: boolean;\n        metadata?: any;\n    };\n    threshold: number;\n\n    constructor(listeners: listeners, threshold: number = 0) {\n        this.listeners = listeners;\n        this.threshold = threshold;\n\n        // make sure we can be attached as event listeners easily\n        this.start = this.start.bind(this);\n        this.move = this.move.bind(this);\n        this.end = this.end.bind(this);\n        this.cancel = this.cancel.bind(this);\n    }\n    setThreshold(threshold: number) {\n        this.threshold = threshold;\n    }\n\n    start(e: MouseEvent | TouchEvent, metadata?: any) {\n        if (!(e instanceof MouseEvent)) {\n            // we ignore any start touches if another finger is currently down (and cancel any active ones if a new finger is touched)\n            if (e.touches.length > 1) {\n                this.cancel();\n                return false;\n            }\n        }\n        const touch = e instanceof MouseEvent ? e : e.touches[0];\n\n        const initialTouch = {\n            x: touch.clientX,\n            y: touch.clientY,\n            time: Date.now(),\n        };\n        this.state = {\n            startTouch: { ...initialTouch },\n            lastTouch: { ...initialTouch },\n            isSwipe: false,\n            velocity: 0,\n            identifier: touch instanceof MouseEvent ? undefined : touch.identifier,\n            metadata: metadata,\n        };\n\n        this.emit(\"start\", initialTouch, metadata);\n    }\n\n    move(e: MouseEvent | TouchEvent) {\n        if (!this.state) {\n            return;\n        } // ignore if we aren't currently dragging\n        let touch: MouseEvent | Touch | undefined = e instanceof MouseEvent ? e : undefined;\n        if (!(e instanceof MouseEvent)) {\n            for (let i = 0; i < e.changedTouches.length; ++i) {\n                const t = e.changedTouches[i];\n                if (t.identifier === this.state.identifier) {\n                    touch = t;\n                    break;\n                }\n            }\n        }\n        if (!touch) {\n            return;\n        } // ignore if none of the touches are the one we're tracking\n\n        const timeDelta = Date.now() - this.state.lastTouch.time;\n        if (timeDelta < 16) {\n            return;\n        } // debounce\n        // we compare the direction relative to the starting point; if it's more down than up, we cancel the drag ('cause it's probably a scroll)\n        const xDelta = touch.clientX - this.state.startTouch.x;\n        const yDelta = touch.clientY - this.state.startTouch.y;\n        const absXDelta = Math.abs(xDelta);\n        const absYDelta = Math.abs(yDelta);\n\n        // ignore ones where the mouse hasn't moved\n        if (absXDelta === 0 && absYDelta === 0) {\n            return;\n        }\n\n        // update our state\n        this.state.lastTouch.x = touch.clientX;\n        this.state.lastTouch.y = touch.clientY;\n        this.state.lastTouch.time = Date.now();\n        this.state.velocity = timeDelta ? (touch.clientX - this.state.lastTouch.x) / timeDelta : 0;\n\n        const IGNORE_THRESHOLD = 32; // ignore test if we have moved barely anything. Possibly consider if this is better as an option?\n        if (!this.state.isSwipe) {\n            // don't start tracking as a swipe until after we've exceeding our threshold\n            if (Math.max(absXDelta, absYDelta) < IGNORE_THRESHOLD) {\n                return;\n            } else {\n                // if we've just now gone past our threshold, check if this looks more like a scroll than a swipe\n                if (absYDelta > absXDelta) {\n                    this.cancel();\n                    return;\n                }\n                this.state.isSwipe = true;\n            }\n        }\n\n        e.preventDefault(); // stop any scrolling if we are currently swiping\n        this.emit(\"update\", { x: xDelta, y: yDelta }, this.state.metadata);\n    }\n\n    end(e: MouseEvent | TouchEvent) {\n        if (!this.state) {\n            return false;\n        } // ignore if we aren't currently dragging\n        let touch: MouseEvent | Touch | undefined = e instanceof MouseEvent ? e : undefined;\n        if (!(e instanceof MouseEvent)) {\n            for (let i = 0; i < e.changedTouches.length; ++i) {\n                const t = e.changedTouches[i];\n                if (t.identifier === this.state.identifier) {\n                    touch = t;\n                    break;\n                }\n            }\n        }\n        if (!touch) {\n            return false;\n        } // ignore if none of the touches are the one we're tracking\n\n        // then calculate the projected point we want to check\n        const velocity = this.state.velocity;\n        const totalDelta = touch.clientX - this.state.startTouch.x;\n        const recentDelta = touch.clientX - this.state.lastTouch.x;\n        let finalDelta = totalDelta;\n        // we only project a point out if the flick is in the direction of the swipe, otherwise we just use the touch position\n        if ((totalDelta >= 0 && recentDelta >= 0) || (totalDelta <= 0 && recentDelta <= 0)) {\n            finalDelta += velocity * 50; // project it 50ms out\n        }\n\n        // finally check if it's a swipe\n        if (this.threshold && this.threshold > 0 && Math.abs(finalDelta) > this.threshold) {\n            this.emit(\"end\", finalDelta < 0 ? \"left\" : \"right\", this.state.metadata);\n            this.after();\n            return true;\n        }\n        this.cancel();\n        return false;\n    }\n\n    cancel() {\n        if (!this.state) {\n            return;\n        }\n        this.emit(\"cancel\", this.state.metadata);\n        this.after();\n    }\n\n    after() {\n        delete this.state;\n    }\n\n    emit(event: keyof listeners, ...args: any[]) {\n        const listener = this.listeners[event] as ((...args: any[]) => void) | undefined;\n        if (listener) {\n            listener(...args);\n        }\n    }\n}\n","import yamz from \"./core\";\nimport withCaption from \"./caption/caption\";\nimport withAlbum from \"./album/album\";\nimport withSwipe from \"./swipe/swipe\";\n\nexport default withSwipe(withAlbum(withCaption(yamz)));\n","import { MediumLightboxCore } from \"../core\";\nimport { YamzPlugin, Classes } from \"../types\";\nimport withAlbum from \"../album/album\";\nimport \"./swipe.css\";\nimport SwipeDetector from \"./detector\";\n\nexport interface Swipeable {\n    swipeDetector: SwipeDetector;\n    applySwipeTransform: (offset: { x: number; y: number }, opts: SwipeOptions) => void;\n    onSwipeStart: (point: { x: number; y: number }, opts: SwipeOptions) => void;\n    onSwipeEnd: (direction: \"left\" | \"right\", opts: SwipeOptions) => void;\n    onSwipeCancel: (opts: SwipeOptions) => void;\n    afterSwipe: () => void;\n}\n\nexport interface SwipeOptions {\n    /** Describes how far users have to drag before it's recognized as a drag */\n    swipeThreshold?: number;\n    /** Describes how far the image can move visually in response to being dragged */\n    swipeResponseLimit?: number;\n    /** If true, desktop users can drag images using their mouse */\n    swipeOnDesktop?: boolean;\n}\n\n/** Augments the YAMZ instance to support swiping through albums on mobile */\nexport default function withSwipe<YamzType extends ReturnType<typeof withAlbum>>(_yamz: YamzType) {\n    const { defaultLightboxGenerator } = _yamz;\n    const yamz = _yamz as YamzPlugin<YamzType, Swipeable, SwipeOptions, SwipeOptions>;\n    if (typeof window === \"undefined\") {\n        return yamz;\n    }\n\n    yamz.options = {\n        swipeThreshold: window.innerWidth * 0.25,\n        swipeResponseLimit: window.innerWidth * 0.05,\n        swipeOnDesktop: false,\n        ...yamz.options,\n    };\n\n    // attach listeners to lightbox if we're displaying an album\n    yamz.defaultLightboxGenerator = function($copiedImg, opts, $original) {\n        const $lightbox = defaultLightboxGenerator.call(this, $copiedImg, opts, $original);\n\n        if (!opts.album) {\n            return $lightbox;\n        }\n\n        if (opts.swipeThreshold) {\n            yamz.swipeDetector.setThreshold(opts.swipeThreshold);\n        }\n\n        // normally we don't let mouse users swipe, but developers can enable it if they want\n        if (opts.swipeOnDesktop) {\n            $lightbox.addEventListener(\"mousedown\", e => {\n                e.preventDefault();\n                yamz.swipeDetector.start(e, opts);\n            });\n            $lightbox.addEventListener(\"mousemove\", e => {\n                e.preventDefault();\n                yamz.swipeDetector.move(e);\n            });\n            let justSwiped = 0;\n            $lightbox.addEventListener(\"mouseup\", e => {\n                e.preventDefault();\n                if (yamz.swipeDetector.state) {\n                    justSwiped = yamz.swipeDetector.state.isSwipe ? Date.now() : 0;\n                }\n                if (!yamz.swipeDetector.end(e)) {\n                    this.onSwipeCancel(opts);\n                }\n            });\n            $lightbox.addEventListener(\"click\", e => {\n                // we stop propagation here so that the lightbox doesn't close if we just swiped\n                if (Date.now() - justSwiped < 16) {\n                    e.stopImmediatePropagation();\n                }\n            });\n        }\n\n        // we always attach listeners for touch\n        $lightbox.addEventListener(\"touchstart\", e => {\n            yamz.swipeDetector.start(e, opts);\n        });\n        $lightbox.addEventListener(\"touchmove\", yamz.swipeDetector.move);\n        $lightbox.addEventListener(\"touchend\", yamz.swipeDetector.end);\n        $lightbox.addEventListener(\"touchcancel\", yamz.swipeDetector.cancel);\n\n        return $lightbox;\n    };\n\n    yamz.applySwipeTransform = function(touchOffset: { x: number; y: number }, opts: SwipeOptions) {\n        if (!this.active) {\n            return;\n        }\n        let offset = Math.abs(touchOffset.x);\n        let scale = 1;\n        if (opts.swipeResponseLimit) {\n            // use a sine function to slowly scale down\n            // sine wave is 3 long, because that gives a 45 degree angle at the start, so 1px touch movement = 1px image movement\n            const limit = opts.swipeResponseLimit * 1.5; // this is where we want the image to stop moving entirely\n            const progress = Math.abs(touchOffset.x) / opts.swipeResponseLimit;\n            const clampedProgress = Math.min(progress, 1.5);\n            const offsetScale = Math.sin((clampedProgress * Math.PI) / 3);\n            offset = opts.swipeResponseLimit * offsetScale;\n\n            // update the opacity if we're nearing the end\n            if (progress > 1) {\n                scale = Math.min(Math.max(1 - (progress - 1) * 0.01, 0.8), 1);\n            }\n\n            // maintain a very slight response to dragging further\n            const linearOffset = Math.abs(touchOffset.x) - Math.min(Math.abs(touchOffset.x), limit);\n            offset += linearOffset * 0.05;\n\n            if (touchOffset.x < 0) {\n                offset = -offset;\n            }\n        }\n\n        const $target = this.active.$lightbox.querySelector(\n            `.${Classes.IMG_WRAPPER}`\n        ) as HTMLElement | null;\n        if ($target) {\n            $target.style.transform = `translateX(${offset.toFixed(5)}px) scale(${scale.toFixed(\n                5\n            )})`;\n            $target.style.opacity = `${1 - (1 - scale) * 4}`;\n        }\n    };\n\n    yamz.onSwipeStart = function(point: { x: number; y: number }, opts: SwipeOptions) {\n        if (this.active) {\n            const $target = this.active.$lightbox.querySelector(`.${Classes.IMG_WRAPPER}`);\n            if ($target) {\n                $target.classList.add(`${Classes.IMG_WRAPPER}--swiping`);\n            }\n        }\n    };\n    yamz.onSwipeEnd = function(direction: \"left\" | \"right\", opts: SwipeOptions) {\n        if (this.active) {\n            const $btn =\n                direction === \"left\"\n                    ? this.active.$lightbox.querySelector(`.${Classes.ALBUM_NEXT}`)\n                    : this.active.$lightbox.querySelector(`.${Classes.ALBUM_PREV}`);\n            if ($btn) {\n                ($btn as HTMLElement).click();\n            }\n        }\n        this.afterSwipe();\n    };\n\n    yamz.onSwipeCancel = function(opts: SwipeOptions) {\n        this.applySwipeTransform({ x: 0, y: 0 }, opts);\n        this.afterSwipe();\n    };\n\n    yamz.afterSwipe = function() {\n        if (this.active) {\n            const $target = this.active.$lightbox.querySelector(`.${Classes.IMG_WRAPPER}`);\n            if ($target) {\n                $target.classList.remove(`${Classes.IMG_WRAPPER}--swiping`);\n            }\n        }\n    };\n\n    yamz.swipeDetector = new SwipeDetector({\n        start: yamz.onSwipeStart.bind(yamz),\n        update: yamz.applySwipeTransform.bind(yamz),\n        end: yamz.onSwipeEnd.bind(yamz),\n        cancel: yamz.onSwipeCancel.bind(yamz),\n    });\n\n    return yamz;\n}\n","import { MediumLightboxCore } from \"../core\";\nimport { Classes, YamzPlugin } from \"../types\";\nimport \"./album.css\";\n\nexport interface Albumed<Yamz extends MediumLightboxCore> {\n    moveToAlbumEntry: (entry: AlbumEntry<Yamz>, direction: \"next\" | \"prev\") => void;\n}\n\nexport interface AlbumOptions<Yamz extends MediumLightboxCore> {\n    album?: AlbumEntry<Yamz>[];\n    wrapAlbum?: boolean;\n}\n\nexport interface AlbumEntry<Yamz extends MediumLightboxCore> {\n    img: HTMLElement;\n    opts?: ReturnType<Yamz[\"optsFromElm\"]> & AlbumOptions<Yamz>;\n}\n\n/** Augments the YAMZ instance to support albums */\nexport default function withAlbum<YamzType extends MediumLightboxCore>(_yamz: YamzType) {\n    const { defaultLightboxGenerator, optsFromElm, onKeyDown } = _yamz;\n    const yamz = _yamz as YamzPlugin<\n        YamzType,\n        Albumed<YamzType>,\n        AlbumOptions<YamzType>,\n        AlbumOptions<YamzType>\n    >;\n\n    yamz.options = {\n        wrapAlbum: false,\n        ...yamz.options,\n    };\n\n    function augmentLightbox(\n        yamz: Albumed<YamzType>,\n        $lightbox: HTMLElement,\n        opts: AlbumOptions<YamzType>,\n        index: number\n    ) {\n        if (!opts.album) {\n            return $lightbox;\n        }\n        const prevIndex = opts.wrapAlbum\n            ? (opts.album.length + index - 1) % opts.album.length\n            : index - 1;\n        const nextIndex = opts.wrapAlbum\n            ? (opts.album.length + index + 1) % opts.album.length\n            : index + 1;\n\n        if (prevIndex >= 0) {\n            const $prev = document.createElement(\"button\");\n            $prev.classList.add(Classes.ALBUM_PREV);\n            $prev.addEventListener(\"click\", e => {\n                if (!opts.album) {\n                    return;\n                }\n                e.stopPropagation();\n                yamz.moveToAlbumEntry(opts.album[prevIndex], \"prev\");\n            });\n            $lightbox.appendChild($prev);\n        }\n        if (nextIndex < opts.album.length) {\n            const $next = document.createElement(\"button\");\n            $next.classList.add(Classes.ALBUM_NEXT);\n            $next.addEventListener(\"click\", e => {\n                if (!opts.album) {\n                    return;\n                }\n                e.stopPropagation();\n                yamz.moveToAlbumEntry(opts.album[nextIndex], \"next\");\n            });\n            $lightbox.appendChild($next);\n        }\n    }\n\n    // insert album stuff into the lightbox if we're given one\n    yamz.defaultLightboxGenerator = function($copiedImg, opts, $original) {\n        const $lightbox = defaultLightboxGenerator($copiedImg, opts, $original);\n\n        if (opts.album) {\n            const index = opts.album.findIndex(entry => entry.img === $original);\n            augmentLightbox(this, $lightbox, opts, index);\n        }\n\n        return $lightbox;\n    };\n\n    // also allow specifying the album in HTML\n    yamz.optsFromElm = function($elm: HTMLElement) {\n        type outpType = ReturnType<YamzType[\"optsFromElm\"]> & AlbumOptions<YamzType>;\n        const outp: outpType = optsFromElm($elm) as outpType;\n        if ($elm.dataset.album) {\n            const $siblings = Array.from(\n                document.querySelectorAll(`[data-album=\"${$elm.dataset.album}\"]`)\n            ) as HTMLElement[];\n            outp.album = $siblings.map($sibling => {\n                return {\n                    img: $sibling,\n                    opts: optsFromElm($sibling),\n                };\n            }) as AlbumEntry<YamzType>[];\n            // make sure each entry knows about which album it's in\n            outp.album.forEach(entry => {\n                entry.opts = {\n                    ...(entry.opts || {}),\n                    album: outp.album,\n                } as outpType;\n            });\n        }\n        return outp;\n    };\n\n    // add new method for moving to an album entry\n    yamz.moveToAlbumEntry = function(entry: AlbumEntry<YamzType>, direction: \"next\" | \"prev\") {\n        if (!this.active) {\n            return;\n        }\n        const $target = this.active.$lightbox.querySelector(\n            `.${Classes.IMG_WRAPPER}`\n        ) as HTMLElement;\n        if (!$target) {\n            throw new ReferenceError(\"Could not find image wrapper in lightbox\");\n        }\n        const directions = {\n            out: direction === \"next\" ? \"left\" : \"right\",\n            in: direction === \"next\" ? \"right\" : \"left\",\n        };\n        let replaced = false;\n        const _onAnimEnd = () => {\n            if (replaced || !this.active) {\n                return;\n            }\n            replaced = true;\n            this.replace(entry.img, entry.opts);\n            const $newTarget = this.active.$lightbox.querySelector(\n                `.${Classes.IMG_WRAPPER}`\n            ) as HTMLElement;\n            if (!$newTarget) {\n                return;\n            }\n            $newTarget.classList.add(`${Classes.IMG_WRAPPER}--in-${directions.in}`);\n        };\n\n        setTimeout(_onAnimEnd, 1000); // fail safe if for whatever reason animation doesn't play\n        $target.addEventListener(\"animationend\", _onAnimEnd);\n        $target.addEventListener(\"animationcancel\", _onAnimEnd);\n        $target.classList.add(`${Classes.IMG_WRAPPER}--out-${directions.out}`);\n    };\n\n    // finally extend the keyboard interactivity\n    yamz.onKeyDown = function(e: KeyboardEvent) {\n        onKeyDown.call(this, e);\n        if (!this.active) {\n            return;\n        }\n        const opts = this.active.options as AlbumOptions<YamzType>;\n        if (!opts.album) {\n            return;\n        }\n\n        // move back/forward in album when pressing arrow keys\n        if (e.key === \"ArrowLeft\" || e.key === \"ArrowRight\") {\n            const $curImg = this.active.$img;\n            const index = opts.album.findIndex(entry => entry.img === $curImg);\n            const prevIndex = opts.wrapAlbum\n                ? (opts.album.length + index - 1) % opts.album.length\n                : index - 1;\n            const nextIndex = opts.wrapAlbum\n                ? (opts.album.length + index + 1) % opts.album.length\n                : index + 1;\n            const targetIndex = e.key === \"ArrowLeft\" ? prevIndex : nextIndex;\n\n            if (targetIndex >= 0 && targetIndex < opts.album.length) {\n                (this as Albumed<YamzType>).moveToAlbumEntry(\n                    opts.album[targetIndex],\n                    e.key === \"ArrowLeft\" ? \"prev\" : \"next\"\n                );\n            }\n        }\n    };\n\n    return yamz;\n}\n","import { MediumLightboxCore } from \"../core\";\nimport { Classes, YamzPlugin } from \"../types\";\nimport \"./caption.css\";\n\nexport interface Captioned {}\n\nexport interface CaptionOptions {\n    caption?: string | HTMLElement;\n}\n\n/** Augments the YAMZ instance to support captions */\nexport default function withCaption<YamzType extends MediumLightboxCore>(_yamz: YamzType) {\n    const { defaultLightboxGenerator, optsFromElm } = _yamz;\n    const yamz = _yamz as YamzPlugin<YamzType, Captioned, CaptionOptions, CaptionOptions>;\n\n    // insert caption into the lightbox if we're given one\n    yamz.defaultLightboxGenerator = function($copiedImg, opts, $original) {\n        const $lightbox = defaultLightboxGenerator.call(this, $copiedImg, opts, $original);\n\n        // add caption if given\n        if (opts.caption) {\n            const $caption = document.createElement(\"div\");\n            $caption.classList.add(Classes.CAPTION);\n            if (opts.caption instanceof HTMLElement) {\n                $caption.appendChild(opts.caption);\n            } else {\n                $caption.textContent = opts.caption;\n            }\n            $lightbox.classList.add(Classes.HAS_CAPTION);\n            $lightbox.appendChild($caption);\n        }\n\n        return $lightbox;\n    };\n\n    // also allow specifying the caption in HTML\n    yamz.optsFromElm = function($elm: HTMLElement) {\n        type outpType = ReturnType<YamzType[\"optsFromElm\"]> & CaptionOptions;\n        const outp: outpType = optsFromElm.call(this, $elm) as outpType;\n        if ($elm.dataset.caption) {\n            outp.caption = $elm.dataset.caption;\n        }\n        return outp;\n    };\n\n    return yamz;\n}\n"]}