Spaces:
Build error
Build error
| import { $el } from "../../../../scripts/ui.js"; | |
| import { addStylesheet, getUrl, loadImage } from "./utils.js"; | |
| import { createSpinner } from "./spinner.js"; | |
| addStylesheet(getUrl("lightbox.css", import.meta.url)); | |
| const $$el = (tag, name, ...args) => { | |
| if (name) name = "-" + name; | |
| return $el(tag + ".pysssss-lightbox" + name, ...args); | |
| }; | |
| const ani = async (a, t, b) => { | |
| a(); | |
| await new Promise((r) => setTimeout(r, t)); | |
| b(); | |
| }; | |
| export class Lightbox { | |
| constructor() { | |
| this.el = $$el("div", "", { | |
| parent: document.body, | |
| onclick: (e) => { | |
| e.stopImmediatePropagation(); | |
| this.close(); | |
| }, | |
| style: { | |
| display: "none", | |
| opacity: 0, | |
| }, | |
| }); | |
| this.closeBtn = $$el("div", "close", { | |
| parent: this.el, | |
| }); | |
| this.prev = $$el("div", "prev", { | |
| parent: this.el, | |
| onclick: (e) => { | |
| this.update(-1); | |
| e.stopImmediatePropagation(); | |
| }, | |
| }); | |
| this.main = $$el("div", "main", { | |
| parent: this.el, | |
| }); | |
| this.next = $$el("div", "next", { | |
| parent: this.el, | |
| onclick: (e) => { | |
| this.update(1); | |
| e.stopImmediatePropagation(); | |
| }, | |
| }); | |
| this.link = $$el("a", "link", { | |
| parent: this.main, | |
| target: "_blank", | |
| }); | |
| this.spinner = createSpinner(); | |
| this.link.appendChild(this.spinner); | |
| this.img = $$el("img", "img", { | |
| style: { | |
| opacity: 0, | |
| }, | |
| parent: this.link, | |
| onclick: (e) => { | |
| e.stopImmediatePropagation(); | |
| }, | |
| onwheel: (e) => { | |
| if (!(e instanceof WheelEvent) || e.ctrlKey) { | |
| return; | |
| } | |
| const direction = Math.sign(e.deltaY); | |
| this.update(direction); | |
| }, | |
| }); | |
| } | |
| close() { | |
| ani( | |
| () => (this.el.style.opacity = 0), | |
| 200, | |
| () => (this.el.style.display = "none") | |
| ); | |
| } | |
| async show(images, index) { | |
| this.images = images; | |
| this.index = index || 0; | |
| await this.update(0); | |
| } | |
| async update(shift) { | |
| if (shift < 0 && this.index <= 0) { | |
| return; | |
| } | |
| if (shift > 0 && this.index >= this.images.length - 1) { | |
| return; | |
| } | |
| this.index += shift; | |
| this.prev.style.visibility = this.index ? "unset" : "hidden"; | |
| this.next.style.visibility = this.index === this.images.length - 1 ? "hidden" : "unset"; | |
| const img = this.images[this.index]; | |
| this.el.style.display = "flex"; | |
| this.el.clientWidth; // Force a reflow | |
| this.el.style.opacity = 1; | |
| this.img.style.opacity = 0; | |
| this.spinner.style.display = "inline-block"; | |
| try { | |
| await loadImage(img); | |
| } catch (err) { | |
| console.error('failed to load image', img, err); | |
| } | |
| this.spinner.style.display = "none"; | |
| this.link.href = img; | |
| this.img.src = img; | |
| this.img.style.opacity = 1; | |
| } | |
| async updateWithNewImage(img, feedDirection) { | |
| // No-op if lightbox is not open | |
| if (this.el.style.display === "none" || this.el.style.opacity === "0") return; | |
| // Ensure currently shown image does not change | |
| const [method, shift] = feedDirection === "newest first" ? ["unshift", 1] : ["push", 0]; | |
| this.images[method](img); | |
| await this.update(shift); | |
| } | |
| } | |
| export const lightbox = new Lightbox(); | |
| addEventListener('keydown', (event) => { | |
| if (lightbox.el.style.display === 'none') { | |
| return; | |
| } | |
| const { key } = event; | |
| switch (key) { | |
| case 'ArrowLeft': | |
| case 'a': | |
| lightbox.update(-1); | |
| break; | |
| case 'ArrowRight': | |
| case 'd': | |
| lightbox.update(1); | |
| break; | |
| case 'Escape': | |
| lightbox.close(); | |
| break; | |
| } | |
| }); |