File size: 2,240 Bytes
baa8e90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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();
			},
		});
	}

	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) {
		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";
		await loadImage(img);
		this.spinner.style.display = "none";
		this.link.href = img;
		this.img.src = img;
		this.img.style.opacity = 1;
	}
}

export const lightbox = new Lightbox();