@redot-src/glare 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1339 @@
1
+ const d = {
2
+ close: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>',
3
+ next: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 18 6-6-6-6"/></svg>',
4
+ prev: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 18-6-6 6-6"/></svg>',
5
+ zoomIn: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/><path d="M11 8v6"/><path d="M8 11h6"/></svg>',
6
+ zoomOut: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/><path d="M8 11h6"/></svg>',
7
+ download: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/></svg>',
8
+ share: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" x2="15.42" y1="13.51" y2="17.49"/><line x1="15.41" x2="8.59" y1="6.51" y2="10.49"/></svg>',
9
+ thumbs: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M3 9h18"/><path d="M9 21V9"/></svg>',
10
+ play: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polygon points="6 3 20 12 6 21 6 3"/></svg>',
11
+ pause: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="4" height="16" x="6" y="4"/><rect width="4" height="16" x="14" y="4"/></svg>',
12
+ fullscreen: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 3H5a2 2 0 0 0-2 2v3"/><path d="M21 8V5a2 2 0 0 0-2-2h-3"/><path d="M3 16v3a2 2 0 0 0 2 2h3"/><path d="M16 21h3a2 2 0 0 0 2-2v-3"/></svg>',
13
+ fullscreenExit: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 3v3a2 2 0 0 1-2 2H3"/><path d="M21 8h-3a2 2 0 0 1-2-2V3"/><path d="M3 16h3a2 2 0 0 1 2 2v3"/><path d="M16 21v-3a2 2 0 0 1 2-2h3"/></svg>'
14
+ }, N = {
15
+ CLOSE: "Close",
16
+ NEXT: "Next",
17
+ PREV: "Previous",
18
+ ERROR: "The requested content cannot be loaded.<br/>Please try again later.",
19
+ PLAY_START: "Start slideshow",
20
+ PLAY_STOP: "Pause slideshow",
21
+ FULL_SCREEN: "Full screen",
22
+ THUMBS: "Thumbnails",
23
+ DOWNLOAD: "Download",
24
+ SHARE: "Share",
25
+ ZOOM: "Zoom"
26
+ }, _ = {
27
+ youtube: {
28
+ matcher: /(?:youtube\.com|youtu\.be|youtube-nocookie\.com)\/(?:watch\?(?:.*&)?v=|v\/|u\/\w\/|embed\/|shorts\/)?([\w-]{11})/i,
29
+ type: "iframe",
30
+ url: (r, t) => `https://www.youtube-nocookie.com/embed/${r[1]}`,
31
+ thumb: (r) => `https://img.youtube.com/vi/${r[1]}/hqdefault.jpg`,
32
+ params: {
33
+ autoplay: 1,
34
+ rel: 0,
35
+ modestbranding: 1,
36
+ playsinline: 1
37
+ }
38
+ },
39
+ vimeo: {
40
+ matcher: /(?:vimeo\.com)\/(?:video\/)?(\d+)/i,
41
+ type: "iframe",
42
+ url: (r) => `https://player.vimeo.com/video/${r[1]}`,
43
+ params: {
44
+ autoplay: 1,
45
+ title: 0,
46
+ byline: 0,
47
+ portrait: 0
48
+ }
49
+ },
50
+ gmap: {
51
+ matcher: /(?:maps\.)?google\.([a-z]{2,3}(?:\.[a-z]{2})?)\/(?:maps\/(?:place\/[^/]+\/)?@([^/]+)|maps\?q=([^&]+)|maps\/search\/([^/?]+))/i,
52
+ type: "iframe",
53
+ url: (r) => {
54
+ const t = r[1];
55
+ if (r[2]) {
56
+ const s = r[2].split(","), i = s[0], n = s[1], o = s[2] ? Math.floor(parseFloat(s[2])) : 14;
57
+ return `https://maps.google.${t}/maps?ll=${i},${n}&z=${o}&output=embed`;
58
+ }
59
+ const e = decodeURIComponent(r[3] || r[4] || "");
60
+ return `https://maps.google.${t}/maps?q=${encodeURIComponent(e)}&output=embed`;
61
+ }
62
+ }
63
+ }, T = {
64
+ closeExisting: !1,
65
+ loop: !1,
66
+ gutter: 50,
67
+ keyboard: !0,
68
+ preventCaptionOverlap: !0,
69
+ arrows: !0,
70
+ infobar: !0,
71
+ smallBtn: "auto",
72
+ toolbar: "auto",
73
+ buttons: ["zoom", "slideshow", "thumbs", "share", "download", "fullscreen", "close"],
74
+ idleTime: 3,
75
+ protect: !1,
76
+ modal: !1,
77
+ image: {
78
+ preload: !1
79
+ },
80
+ ajax: {
81
+ settings: {
82
+ headers: {
83
+ "X-Requested-With": "XMLHttpRequest"
84
+ }
85
+ }
86
+ },
87
+ iframe: {
88
+ preload: !0,
89
+ css: {},
90
+ attr: {
91
+ allowfullscreen: "true",
92
+ allow: "autoplay; fullscreen; picture-in-picture"
93
+ },
94
+ tpl: '<iframe class="glare-iframe" allowfullscreen allow="autoplay; fullscreen; picture-in-picture" src=""></iframe>'
95
+ },
96
+ video: {
97
+ tpl: '<video class="glare-video" controls playsinline controlsList="nodownload" poster="{{poster}}"><source src="{{src}}" type="{{format}}"/>Your browser does not support HTML5 video.</video>',
98
+ format: "",
99
+ autoStart: !0
100
+ },
101
+ defaultType: "image",
102
+ animationEffect: "zoom",
103
+ animationDuration: 366,
104
+ zoomOpacity: "auto",
105
+ transitionEffect: "fade",
106
+ transitionDuration: 366,
107
+ slideClass: "",
108
+ baseClass: "",
109
+ parentEl: "body",
110
+ hideScrollbar: !0,
111
+ autoFocus: !0,
112
+ backFocus: !0,
113
+ trapFocus: !0,
114
+ fullScreen: {
115
+ autoStart: !1
116
+ },
117
+ touch: {
118
+ vertical: !0,
119
+ momentum: !0
120
+ },
121
+ hash: !0,
122
+ media: _,
123
+ slideShow: {
124
+ autoStart: !1,
125
+ speed: 3e3
126
+ },
127
+ thumbs: {
128
+ autoStart: !1,
129
+ hideOnClose: !0,
130
+ parentEl: ".glare-container",
131
+ axis: "y"
132
+ },
133
+ share: !0,
134
+ wheel: "auto",
135
+ clickContent: function(r) {
136
+ return r.type === "image" ? "zoom" : !1;
137
+ },
138
+ clickSlide: "close",
139
+ clickOutside: "close",
140
+ dblclickContent: !1,
141
+ dblclickSlide: !1,
142
+ dblclickOutside: !1,
143
+ mobile: {
144
+ preventCaptionOverlap: !1,
145
+ idleTime: !1,
146
+ clickContent: function(r) {
147
+ return r.type === "image" ? "toggleControls" : !1;
148
+ },
149
+ clickSlide: function(r) {
150
+ return r.type === "image" ? "toggleControls" : "close";
151
+ },
152
+ dblclickContent: function(r) {
153
+ return r.type === "image" ? "zoom" : !1;
154
+ },
155
+ dblclickSlide: function(r) {
156
+ return r.type === "image" ? "zoom" : !1;
157
+ }
158
+ },
159
+ lang: "en",
160
+ i18n: {
161
+ en: N
162
+ },
163
+ spinnerTpl: '<div class="glare-spinner" role="status" aria-label="Loading"></div>',
164
+ errorTpl: '<div class="glare-error"><p>{{ERROR}}</p></div>',
165
+ baseTpl: `
166
+ <div class="glare-container" role="dialog" aria-modal="true" tabindex="-1">
167
+ <div class="glare-bg"></div>
168
+ <div class="glare-inner">
169
+ <div class="glare-infobar"><span class="glare-infobar-index"></span></div>
170
+ <div class="glare-toolbar"></div>
171
+ <div class="glare-navigation">
172
+ <button type="button" class="glare-button glare-button--prev" data-glare-prev title="{{PREV}}" aria-label="{{PREV}}">${d.prev}</button>
173
+ <button type="button" class="glare-button glare-button--next" data-glare-next title="{{NEXT}}" aria-label="{{NEXT}}">${d.next}</button>
174
+ </div>
175
+ <div class="glare-stage"></div>
176
+ <div class="glare-caption"></div>
177
+ </div>
178
+ </div>
179
+ `,
180
+ btnTpl: {
181
+ download: `<a class="glare-button glare-button--download" data-glare-download download title="{{DOWNLOAD}}" aria-label="{{DOWNLOAD}}" href="javascript:;">${d.download}</a>`,
182
+ zoom: `<button type="button" class="glare-button glare-button--zoom" data-glare-zoom title="{{ZOOM}}" aria-label="{{ZOOM}}">${d.zoomIn}</button>`,
183
+ close: `<button type="button" class="glare-button glare-button--close" data-glare-close title="{{CLOSE}}" aria-label="{{CLOSE}}">${d.close}</button>`,
184
+ share: `<button type="button" class="glare-button glare-button--share" data-glare-share title="{{SHARE}}" aria-label="{{SHARE}}">${d.share}</button>`,
185
+ thumbs: `<button type="button" class="glare-button glare-button--thumbs" data-glare-thumbs title="{{THUMBS}}" aria-label="{{THUMBS}}">${d.thumbs}</button>`,
186
+ slideshow: `<button type="button" class="glare-button glare-button--slideshow" data-glare-slideshow title="{{PLAY_START}}" aria-label="{{PLAY_START}}">${d.play}</button>`,
187
+ fullscreen: `<button type="button" class="glare-button glare-button--fullscreen" data-glare-fullscreen title="{{FULL_SCREEN}}" aria-label="{{FULL_SCREEN}}">${d.fullscreen}</button>`,
188
+ smallBtn: `<button type="button" class="glare-button glare-close-small" data-glare-close title="{{CLOSE}}" aria-label="{{CLOSE}}">${d.close}</button>`
189
+ }
190
+ };
191
+ function D(r) {
192
+ return typeof r == "object" && r !== null && !Array.isArray(r);
193
+ }
194
+ function L(r, ...t) {
195
+ const e = { ...r };
196
+ for (const s of t)
197
+ if (!(!s || typeof s != "object"))
198
+ for (const [i, n] of Object.entries(s)) {
199
+ if (n === void 0) continue;
200
+ const o = e[i];
201
+ D(o) && D(n) && !Array.isArray(n) ? e[i] = L(
202
+ o,
203
+ n
204
+ ) : e[i] = n;
205
+ }
206
+ return e;
207
+ }
208
+ function p(r, t = document) {
209
+ return t.querySelector(r);
210
+ }
211
+ function S(r, t = document) {
212
+ return Array.from(t.querySelectorAll(r));
213
+ }
214
+ function b(r, t, e) {
215
+ const s = document.createElement(r);
216
+ return t && (s.className = t), e !== void 0 && (s.innerHTML = e), s;
217
+ }
218
+ function c(r, t, e, s) {
219
+ return r.addEventListener(t, e, s), () => r.removeEventListener(t, e, s);
220
+ }
221
+ function m(r, t) {
222
+ for (const [e, s] of Object.entries(t))
223
+ s == null ? r.style.removeProperty(U(e)) : r.style[e] = String(s);
224
+ }
225
+ function U(r) {
226
+ return r.replace(/[A-Z]/g, (t) => `-${t.toLowerCase()}`);
227
+ }
228
+ function x(r, t, e) {
229
+ return Math.min(e, Math.max(t, r));
230
+ }
231
+ function W() {
232
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
233
+ navigator.userAgent
234
+ ) || navigator.maxTouchPoints > 1 && window.matchMedia("(pointer: coarse)").matches;
235
+ }
236
+ function X() {
237
+ return window.innerWidth - document.documentElement.clientWidth;
238
+ }
239
+ function R(r) {
240
+ const t = document.documentElement;
241
+ if (r) {
242
+ const e = X();
243
+ t.classList.add("glare-lock"), e > 0 && (t.style.marginRight = `${e}px`);
244
+ } else document.querySelector(".glare-container") || (t.classList.remove("glare-lock"), t.style.marginRight = "");
245
+ }
246
+ function $(r, t) {
247
+ return r.replace(/\{\{(\w+)\}\}/g, (e, s) => t[s] ?? "");
248
+ }
249
+ function E(r) {
250
+ return r.getBoundingClientRect();
251
+ }
252
+ function q(r) {
253
+ return window.requestAnimationFrame(r);
254
+ }
255
+ function A(r) {
256
+ q(() => q(r));
257
+ }
258
+ function M() {
259
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
260
+ }
261
+ function Y(r) {
262
+ return Object.entries(r).map(([t, e]) => `${encodeURIComponent(t)}=${encodeURIComponent(String(e))}`).join("&");
263
+ }
264
+ function j(r, t) {
265
+ const e = r.x - t.x, s = r.y - t.y;
266
+ return Math.hypot(e, s);
267
+ }
268
+ function V(r, t) {
269
+ return { x: (r.x + t.x) / 2, y: (r.y + t.y) / 2 };
270
+ }
271
+ function I(r) {
272
+ return "touches" in r ? Array.from(r.touches).map((t) => ({ x: t.clientX, y: t.clientY })) : [{ x: r.clientX, y: r.clientY }];
273
+ }
274
+ class G {
275
+ constructor(t) {
276
+ this.state = {
277
+ isPanning: !1,
278
+ isSwiping: !1,
279
+ isZooming: !1,
280
+ startPoints: [],
281
+ lastPoints: [],
282
+ startDistance: 0,
283
+ startScale: 1,
284
+ startTranslate: { x: 0, y: 0 },
285
+ currentTranslate: { x: 0, y: 0 },
286
+ scale: 1,
287
+ startTime: 0,
288
+ moved: !1
289
+ }, this.cleanups = [], this.pointerId = null, this.instance = t;
290
+ }
291
+ attach(t) {
292
+ this.detach(), this.cleanups.push(
293
+ c(t, "pointerdown", (e) => this.onPointerDown(e), { passive: !1 }),
294
+ c(window, "pointermove", (e) => this.onPointerMove(e), { passive: !1 }),
295
+ c(window, "pointerup", (e) => this.onPointerUp(e)),
296
+ c(window, "pointercancel", (e) => this.onPointerUp(e)),
297
+ c(t, "touchstart", (e) => this.onTouchStart(e), { passive: !1 }),
298
+ c(t, "touchmove", (e) => this.onTouchMove(e), { passive: !1 }),
299
+ c(t, "touchend", (e) => this.onTouchEnd(e)),
300
+ c(t, "touchcancel", (e) => this.onTouchEnd(e))
301
+ );
302
+ }
303
+ detach() {
304
+ this.cleanups.forEach((t) => t()), this.cleanups = [];
305
+ }
306
+ touchEnabled() {
307
+ return this.instance.opts.touch !== !1;
308
+ }
309
+ onPointerDown(t) {
310
+ if (!this.touchEnabled() || t.pointerType === "touch" || t.button !== 0 || t.target.closest("a, button, input, textarea, select, .glare-thumbs")) return;
311
+ this.pointerId = t.pointerId;
312
+ const s = [{ x: t.clientX, y: t.clientY }];
313
+ this.begin(s);
314
+ }
315
+ onPointerMove(t) {
316
+ this.pointerId === t.pointerId && this.move([{ x: t.clientX, y: t.clientY }], t);
317
+ }
318
+ onPointerUp(t) {
319
+ this.pointerId === t.pointerId && (this.pointerId = null, this.end([{ x: t.clientX, y: t.clientY }]));
320
+ }
321
+ onTouchStart(t) {
322
+ !this.touchEnabled() || t.target.closest("a, button, input, textarea, select, .glare-thumbs") || this.begin(I(t));
323
+ }
324
+ onTouchMove(t) {
325
+ this.move(I(t), t);
326
+ }
327
+ onTouchEnd(t) {
328
+ this.end(I(t));
329
+ }
330
+ begin(t) {
331
+ const e = this.instance.getZoomState();
332
+ this.state = {
333
+ isPanning: !1,
334
+ isSwiping: !1,
335
+ isZooming: t.length >= 2,
336
+ startPoints: t,
337
+ lastPoints: t,
338
+ startDistance: t.length >= 2 ? j(t[0], t[1]) : 0,
339
+ startScale: e.scale,
340
+ startTranslate: { x: e.x, y: e.y },
341
+ currentTranslate: { x: e.x, y: e.y },
342
+ scale: e.scale,
343
+ startTime: performance.now(),
344
+ moved: !1
345
+ };
346
+ }
347
+ move(t, e) {
348
+ if (!this.state.startPoints.length) return;
349
+ const s = this.instance.current;
350
+ if (!s) return;
351
+ if (t.length >= 2 && this.state.startPoints.length >= 2) {
352
+ e.preventDefault(), this.state.isZooming = !0, this.state.moved = !0;
353
+ const h = j(t[0], t[1]), f = x(
354
+ h / (this.state.startDistance || h) * this.state.startScale,
355
+ 1,
356
+ 5
357
+ ), w = V(t[0], t[1]);
358
+ this.state.scale = f, this.instance.applyZoom(f, w.x, w.y, !1), this.state.lastPoints = t;
359
+ return;
360
+ }
361
+ if (!t.length || !this.state.startPoints.length) return;
362
+ const i = t[0].x - this.state.startPoints[0].x, n = t[0].y - this.state.startPoints[0].y, o = Math.abs(i), a = Math.abs(n);
363
+ if (!this.state.moved && o < 6 && a < 6) return;
364
+ this.state.moved = !0;
365
+ const l = this.instance.getZoomState();
366
+ if (l.scale > 1.01 && s.type === "image" || this.state.isPanning) {
367
+ e.preventDefault(), this.state.isPanning = !0;
368
+ const h = this.state.startTranslate.x + i, f = this.state.startTranslate.y + n;
369
+ this.state.currentTranslate = { x: h, y: f }, this.instance.applyZoom(l.scale, h, f, !1);
370
+ } else {
371
+ const h = this.instance.opts.touch;
372
+ if (!(h && typeof h == "object" ? h.vertical !== !1 : !0) && a > o) return;
373
+ e.preventDefault(), this.state.isSwiping = !0, this.instance.onSwipe(i, n, !1);
374
+ }
375
+ this.state.lastPoints = t;
376
+ }
377
+ end(t) {
378
+ if (!this.state.startPoints.length) return;
379
+ const e = Math.max(performance.now() - this.state.startTime, 1), s = t[0] || this.state.lastPoints[0] || this.state.startPoints[0], i = this.state.startPoints[0], n = s.x - i.x, o = s.y - i.y, a = { x: n / e, y: o / e };
380
+ if (this.state.isSwiping)
381
+ this.instance.onSwipe(n, o, !0, a);
382
+ else if (this.state.isPanning) {
383
+ const l = this.instance.opts.touch;
384
+ if (l && typeof l == "object" ? l.momentum !== !1 : !0) {
385
+ const h = this.instance.getZoomState();
386
+ this.instance.applyZoom(
387
+ h.scale,
388
+ this.state.currentTranslate.x + a.x * 120,
389
+ this.state.currentTranslate.y + a.y * 120,
390
+ !0
391
+ );
392
+ }
393
+ }
394
+ this.state.startPoints = [], this.state.isPanning = !1, this.state.isSwiping = !1, this.state.isZooming = !1;
395
+ }
396
+ wasMoved() {
397
+ return this.state.moved;
398
+ }
399
+ resetMoved() {
400
+ this.state.moved = !1;
401
+ }
402
+ }
403
+ class K {
404
+ constructor(t) {
405
+ this.cleanups = [], this.instance = t;
406
+ }
407
+ init() {
408
+ this.cleanups.push(
409
+ c(document, "fullscreenchange", () => this.sync()),
410
+ c(document, "webkitfullscreenchange", () => this.sync())
411
+ );
412
+ }
413
+ isFullscreen() {
414
+ const t = document;
415
+ return !!(document.fullscreenElement || t.webkitFullscreenElement || t.mozFullScreenElement || t.msFullscreenElement);
416
+ }
417
+ request() {
418
+ const t = this.instance.$refs.container || document.documentElement;
419
+ (t.requestFullscreen || t.webkitRequestFullscreen || t.mozRequestFullScreen || t.msRequestFullscreen)?.call(t);
420
+ }
421
+ exit() {
422
+ const t = document, e = document.exitFullscreen || t.webkitExitFullscreen || t.mozCancelFullScreen || t.msExitFullscreen;
423
+ this.isFullscreen() && e?.call(document);
424
+ }
425
+ toggle() {
426
+ this.isFullscreen() ? this.exit() : this.request();
427
+ }
428
+ sync() {
429
+ const t = this.isFullscreen();
430
+ this.instance.$refs.container?.classList.toggle("glare-is-fullscreen", t);
431
+ const e = this.instance.$refs.container?.querySelector(
432
+ "[data-glare-fullscreen]"
433
+ );
434
+ e && (e.innerHTML = t ? d.fullscreenExit : d.fullscreen, e.classList.toggle("is-active", t));
435
+ }
436
+ destroy() {
437
+ this.isFullscreen() && this.exit(), this.cleanups.forEach((t) => t()), this.cleanups = [];
438
+ }
439
+ }
440
+ function P() {
441
+ const r = window.location.hash.replace(/^#/, "");
442
+ if (!r) return null;
443
+ const t = r.match(/^(?:glare-)?(.+?)(?:-|\/)(\d+)$/);
444
+ return t ? { gallery: t[1], index: Math.max(0, parseInt(t[2], 10) - 1) } : null;
445
+ }
446
+ function Q(r, t) {
447
+ return `${r}-${t + 1}`;
448
+ }
449
+ const F = class F {
450
+ constructor(t, e) {
451
+ this.cleanups = [], this.skipping = !1, this.instance = t, this.gallery = e || "gallery";
452
+ }
453
+ init() {
454
+ this.cleanups.push(
455
+ c(window, "hashchange", () => {
456
+ if (this.skipping) return;
457
+ const t = P();
458
+ if (!t || t.gallery !== this.gallery) {
459
+ this.instance.isActive && this.instance.close();
460
+ return;
461
+ }
462
+ t.index !== this.instance.currIndex && this.instance.jumpTo(t.index);
463
+ })
464
+ ), this.update();
465
+ }
466
+ update(t = this.instance.currIndex) {
467
+ if (!this.gallery) return;
468
+ const e = Q(this.gallery, t);
469
+ if (window.location.hash.replace(/^#/, "") === e) return;
470
+ this.skipping = !0;
471
+ const s = `${window.location.pathname}${window.location.search}#${e}`;
472
+ window.history.replaceState(null, "", s), queueMicrotask(() => {
473
+ this.skipping = !1;
474
+ });
475
+ }
476
+ clear() {
477
+ const t = P();
478
+ if (t && t.gallery === this.gallery) {
479
+ this.skipping = !0;
480
+ const e = `${window.location.pathname}${window.location.search}`;
481
+ window.history.replaceState(null, "", e), queueMicrotask(() => {
482
+ this.skipping = !1;
483
+ });
484
+ }
485
+ }
486
+ destroy() {
487
+ this.clear(), this.cleanups.forEach((t) => t()), this.cleanups = [];
488
+ }
489
+ };
490
+ F.parse = P;
491
+ let O = F;
492
+ const H = /\.(avif|bmp|gif|jpe?g|png|svg|webp|ico)(\?.*)?$/i, Z = /\.(mp4|webm|ogg|ogv|mov|m4v)(\?.*)?$/i, J = /\.pdf(\?.*)?$/i;
493
+ function tt(r, t) {
494
+ return t || (r ? r.startsWith("#") || r.startsWith(".") ? "inline" : H.test(r) ? "image" : Z.test(r) ? "video" : J.test(r) || /^https?:\/\//i.test(r) || r.startsWith("//") || r.startsWith("/") ? "iframe" : "html" : "html");
495
+ }
496
+ function et(r, t) {
497
+ if (!t) return null;
498
+ for (const e of Object.values(t)) {
499
+ const s = r.match(e.matcher);
500
+ if (!s) continue;
501
+ let i = r;
502
+ if (typeof e.url == "function" ? i = e.url(s, r) : typeof e.url == "string" && (i = e.url.replace(/\$(\d+)/g, (o, a) => s[Number(a)] || "")), e.params) {
503
+ const o = i.includes("?") ? "&" : "?";
504
+ i += o + Y(e.params);
505
+ }
506
+ let n;
507
+ return typeof e.thumb == "function" ? n = e.thumb(s, r) : typeof e.thumb == "string" && (n = e.thumb.replace(/\$(\d+)/g, (o, a) => s[Number(a)] || "")), {
508
+ src: i,
509
+ type: e.type || "iframe",
510
+ thumb: n
511
+ };
512
+ }
513
+ return null;
514
+ }
515
+ function B(r, t, e) {
516
+ const s = typeof r == "string" ? { src: r } : { ...r };
517
+ let i = s.src || "", n = s.type, o = s.thumb;
518
+ s.html && !i && (n = "html", i = "");
519
+ const a = i ? et(i, e.media) : null;
520
+ a && (i = a.src || i, n = a.type || n, o = o || a.thumb), n || (s.content || s.html ? n = "html" : n = tt(i, e.defaultType)), n === "iframe" && H.test(i) && (n = "image"), n === "iframe" && Z.test(i) && (n = "video");
521
+ const l = {
522
+ ...s,
523
+ index: t,
524
+ src: i,
525
+ type: n,
526
+ thumb: o,
527
+ caption: s.caption ?? s.title ?? "",
528
+ isLoaded: !1,
529
+ isComplete: !1,
530
+ hasError: !1,
531
+ canZoomIn: !1,
532
+ canZoomOut: !1
533
+ };
534
+ return s.opts && (l.opts = L({}, e, s.opts)), l;
535
+ }
536
+ function st(r, t) {
537
+ return r.map((e, s) => {
538
+ const i = e.getAttribute("data-src") || e.getAttribute("data-glare-src") || e.getAttribute("href") || "", n = e.getAttribute("data-type") || e.getAttribute("data-glare-type") || void 0, o = e.getAttribute("data-caption") || e.getAttribute("data-glare-caption") || e.getAttribute("title") || "", a = e.getAttribute("data-thumb") || e.getAttribute("data-glare-thumb") || e.querySelector("img")?.getAttribute("src") || void 0, l = e.getAttribute("data-width") || void 0, u = e.getAttribute("data-height") || void 0, h = e.getAttribute("data-poster") || void 0, f = e.getAttribute("data-download-src") || e.getAttribute("data-glare-download") || void 0;
539
+ let w;
540
+ const C = e.getAttribute("data-html") || e.getAttribute("data-glare-html");
541
+ return C && (w = C), B(
542
+ {
543
+ src: i,
544
+ type: n,
545
+ caption: o,
546
+ thumb: a,
547
+ width: l,
548
+ height: u,
549
+ poster: h,
550
+ downloadSrc: f,
551
+ html: w,
552
+ alt: e.querySelector("img")?.getAttribute("alt") || o || "",
553
+ $trigger: e
554
+ },
555
+ s,
556
+ t
557
+ );
558
+ });
559
+ }
560
+ const it = `
561
+ <div class="glare-share">
562
+ <h4 class="glare-share-title">{{SHARE}}</h4>
563
+ <p><a class="glare-share-link" href="{{url_facebook}}" target="_blank" rel="noopener">Facebook</a></p>
564
+ <p><a class="glare-share-link" href="{{url_twitter}}" target="_blank" rel="noopener">X / Twitter</a></p>
565
+ <p><a class="glare-share-link" href="{{url_pinterest}}" target="_blank" rel="noopener">Pinterest</a></p>
566
+ <p><input class="glare-share-input" type="text" value="{{url_direct}}" readonly /></p>
567
+ </div>
568
+ `;
569
+ class nt {
570
+ constructor(t, e) {
571
+ this.$overlay = null, this.cleanups = [], this.instance = t, this.opts = e === !0 ? {} : e;
572
+ }
573
+ open() {
574
+ const t = this.instance.current;
575
+ if (!t || !this.instance.$refs.container) return;
576
+ this.close();
577
+ const e = this.resolveUrl(t), s = encodeURIComponent(e), i = encodeURIComponent(t.thumb || t.src || e), n = encodeURIComponent(t.caption || ""), o = this.instance.opts.lang || "en", a = {
578
+ ...this.instance.opts.i18n?.en || {},
579
+ ...this.instance.opts.i18n?.[o] || {},
580
+ url_direct: e,
581
+ url_facebook: `https://www.facebook.com/sharer/sharer.php?u=${s}`,
582
+ url_twitter: `https://twitter.com/intent/tweet?url=${s}&text=${n}`,
583
+ url_pinterest: `https://pinterest.com/pin/create/button/?url=${s}&media=${i}&description=${n}`
584
+ }, l = $(this.opts.tpl || it, a);
585
+ this.$overlay = b("div", "glare-share-overlay", l), this.instance.$refs.container.appendChild(this.$overlay), this.$overlay.querySelector(".glare-share-input")?.select(), this.cleanups.push(
586
+ c(this.$overlay, "click", (h) => {
587
+ h.target === this.$overlay && this.close();
588
+ })
589
+ );
590
+ }
591
+ close() {
592
+ this.cleanups.forEach((t) => t()), this.cleanups = [], this.$overlay?.remove(), this.$overlay = null;
593
+ }
594
+ resolveUrl(t) {
595
+ return typeof this.opts.url == "function" ? this.opts.url(t) : typeof this.opts.url == "string" ? this.opts.url : t.src && /^https?:\/\//i.test(t.src) ? t.src : window.location.href;
596
+ }
597
+ destroy() {
598
+ this.close();
599
+ }
600
+ }
601
+ class rt {
602
+ constructor(t, e) {
603
+ this.timer = null, this.active = !1, this.instance = t, this.opts = e;
604
+ }
605
+ init() {
606
+ this.opts.autoStart && this.start();
607
+ }
608
+ isActive() {
609
+ return this.active;
610
+ }
611
+ start() {
612
+ this.instance.group.length < 2 || (this.active = !0, this.instance.$refs.container?.classList.add("glare-is-slideshow"), this.updateButton(), this.queue());
613
+ }
614
+ stop() {
615
+ this.active = !1, this.clear(), this.instance.$refs.container?.classList.remove("glare-is-slideshow"), this.updateButton();
616
+ }
617
+ toggle() {
618
+ this.active ? this.stop() : this.start();
619
+ }
620
+ queue() {
621
+ this.clear(), this.active && (this.timer = setTimeout(() => {
622
+ this.active && (this.instance.next(), this.queue());
623
+ }, this.opts.speed || 3e3));
624
+ }
625
+ clear() {
626
+ this.timer && (clearTimeout(this.timer), this.timer = null);
627
+ }
628
+ updateButton() {
629
+ const t = this.instance.$refs.container?.querySelector(
630
+ "[data-glare-slideshow]"
631
+ );
632
+ if (!t) return;
633
+ const e = this.active ? this.getLabel("PLAY_STOP") : this.getLabel("PLAY_START");
634
+ t.setAttribute("title", e), t.setAttribute("aria-label", e), t.innerHTML = this.active ? d.pause : d.play, t.classList.toggle("is-active", this.active);
635
+ }
636
+ getLabel(t) {
637
+ const e = this.instance.opts.lang || "en";
638
+ return {
639
+ ...this.instance.opts.i18n?.en || {},
640
+ ...this.instance.opts.i18n?.[e] || {}
641
+ }[t] || t;
642
+ }
643
+ destroy() {
644
+ this.stop();
645
+ }
646
+ }
647
+ class ot {
648
+ constructor(t, e) {
649
+ this.isActive = !1, this.$container = null, this.$list = null, this.cleanups = [], this.instance = t, this.opts = e;
650
+ }
651
+ init() {
652
+ if (this.instance.group.length < 2) return;
653
+ const t = typeof this.opts.parentEl == "string" ? p(this.opts.parentEl) || this.instance.$refs.container : this.opts.parentEl || this.instance.$refs.container;
654
+ if (t) {
655
+ this.$container = b("div", `glare-thumbs glare-thumbs--${this.opts.axis || "y"}`), this.$list = b("div", "glare-thumbs-list"), this.$container.appendChild(this.$list);
656
+ for (const e of this.instance.group) {
657
+ const s = b("button", "glare-thumbs-item");
658
+ if (s.type = "button", s.setAttribute("aria-label", `Go to slide ${e.index + 1}`), s.dataset.index = String(e.index), e.thumb || e.type === "image" && e.src) {
659
+ const i = b("img");
660
+ i.src = e.thumb || e.src, i.alt = e.alt || e.caption || "", i.loading = "lazy", s.appendChild(i);
661
+ } else
662
+ s.textContent = String(e.index + 1);
663
+ this.$list.appendChild(s), this.cleanups.push(
664
+ c(s, "click", () => {
665
+ this.instance.jumpTo(e.index);
666
+ })
667
+ );
668
+ }
669
+ t.appendChild(this.$container), this.opts.autoStart && this.show(), this.focus(this.instance.currIndex);
670
+ }
671
+ }
672
+ show() {
673
+ this.$container && (this.isActive = !0, this.$container.classList.add("glare-thumbs--active"), this.instance.$refs.container?.classList.add("glare-show-thumbs"));
674
+ }
675
+ hide() {
676
+ this.$container && (this.isActive = !1, this.$container.classList.remove("glare-thumbs--active"), this.instance.$refs.container?.classList.remove("glare-show-thumbs"));
677
+ }
678
+ toggle() {
679
+ this.isActive ? this.hide() : this.show();
680
+ }
681
+ focus(t = this.instance.currIndex) {
682
+ if (!this.$list) return;
683
+ S(".glare-thumbs-item", this.$list).forEach((s) => {
684
+ s.classList.toggle("is-active", Number(s.dataset.index) === t);
685
+ }), this.$list.querySelector(".is-active")?.scrollIntoView({ block: "nearest", inline: "nearest", behavior: "smooth" });
686
+ }
687
+ destroy() {
688
+ this.opts.hideOnClose !== !1 && this.hide(), this.cleanups.forEach((t) => t()), this.cleanups = [], this.$container?.remove(), this.$container = null, this.$list = null;
689
+ }
690
+ }
691
+ class at {
692
+ constructor(t, e) {
693
+ this.cleanups = [], this.locked = !1, this.instance = t, this.mode = e;
694
+ }
695
+ init(t) {
696
+ this.mode !== !1 && this.cleanups.push(
697
+ c(
698
+ t,
699
+ "wheel",
700
+ (e) => {
701
+ const s = e;
702
+ if (this.locked) return;
703
+ const i = this.instance.current;
704
+ i && (this.mode === "auto" && i.type !== "image" || i.type === "image" && this.instance.$refs.container?.classList.contains("glare-can-zoom-out") || (s.preventDefault(), this.locked = !0, s.deltaY > 0 ? this.instance.next() : this.instance.prev(), setTimeout(() => {
705
+ this.locked = !1;
706
+ }, 350)));
707
+ },
708
+ { passive: !1 }
709
+ )
710
+ );
711
+ }
712
+ destroy() {
713
+ this.cleanups.forEach((t) => t()), this.cleanups = [];
714
+ }
715
+ }
716
+ let lt = 0;
717
+ const g = [];
718
+ function ct(r) {
719
+ return r ? typeof r == "string" ? p(r) || document.body : r : document.body;
720
+ }
721
+ const v = class v {
722
+ constructor(t, e = {}, s = 0, i = "") {
723
+ this.group = [], this.current = null, this.currIndex = 0, this.prevIndex = 0, this.isActive = !1, this.isClosing = !1, this.isAnimating = !1, this.isIdle = !1, this.$refs = {
724
+ container: null,
725
+ stage: null,
726
+ bg: null,
727
+ inner: null,
728
+ caption: null,
729
+ toolbar: null,
730
+ infobar: null,
731
+ navigation: null
732
+ }, this.galleryName = "", this.cleanups = [], this.idleTimer = null, this.gestures = null, this.hash = null, this.wheel = null, this.share = null, this.zoom = { scale: 1, x: 0, y: 0, min: 1, max: 5 }, this.previouslyFocused = null, this.openedFrom = null, this.id = ++lt, this.galleryName = i;
733
+ const n = L(
734
+ {},
735
+ T,
736
+ e
737
+ );
738
+ W() && n.mobile ? this.opts = L(
739
+ {},
740
+ n,
741
+ n.mobile
742
+ ) : this.opts = n, t.length && t[0] instanceof HTMLElement ? this.group = st(t, this.opts) : this.group = t.map(
743
+ (o, a) => B(o, a, this.opts)
744
+ ), this.currIndex = x(s, 0, Math.max(0, this.group.length - 1));
745
+ }
746
+ open(t = this.currIndex) {
747
+ if (this.isActive) {
748
+ this.jumpTo(t);
749
+ return;
750
+ }
751
+ this.opts.closeExisting && v.close(!0), this.currIndex = x(t, 0, Math.max(0, this.group.length - 1)), this.current = this.group[this.currIndex] || null, this.openedFrom = this.current?.$trigger || null, this.previouslyFocused = document.activeElement, this.trigger("onInit"), this.build(), this.isActive = !0, g.push(this), this.opts.hideScrollbar && R(!0), this.trigger("onActivate"), this.trigger("beforeShow", this.current || void 0), A(() => {
752
+ this.$refs.container?.classList.add("glare-is-open", "glare-is-animated"), this.loadSlide(this.currIndex, !0), this.bindEvents(), this.initModules(), this.opts.autoFocus && this.focus(), this.resetIdle();
753
+ });
754
+ }
755
+ close(t, e) {
756
+ if (!this.isActive || this.isClosing || this.trigger("beforeClose", this.current || void 0) === !1) return;
757
+ this.isClosing = !0, this.SlideShow?.stop(), this.clearIdle();
758
+ const s = this.$refs.container, i = e ?? (M() ? 0 : this.opts.animationDuration || 0);
759
+ s?.classList.add("glare-is-closing"), s?.classList.remove("glare-is-open");
760
+ const n = () => {
761
+ this.teardown();
762
+ };
763
+ if (i > 0 && s) {
764
+ const o = (a) => {
765
+ a.target === s && (s.removeEventListener("transitionend", o), n());
766
+ };
767
+ s.addEventListener("transitionend", o), setTimeout(n, i + 50);
768
+ } else
769
+ n();
770
+ }
771
+ next(t) {
772
+ this.jumpTo(this.currIndex + 1, t);
773
+ }
774
+ previous(t) {
775
+ this.jumpTo(this.currIndex - 1, t);
776
+ }
777
+ prev(t) {
778
+ this.previous(t);
779
+ }
780
+ jumpTo(t, e) {
781
+ if (!this.isActive || this.isClosing) return;
782
+ const s = this.group.length;
783
+ if (!s) return;
784
+ let i = t;
785
+ if (this.opts.loop)
786
+ i = (t % s + s) % s;
787
+ else if (i = x(t, 0, s - 1), i === this.currIndex && t !== this.currIndex) return;
788
+ i !== this.currIndex && (this.prevIndex = this.currIndex, this.currIndex = i, this.current = this.group[i], this.resetZoom(), this.loadSlide(i, !1, e), this.updateChrome(), this.Thumbs?.focus(i), this.hash?.update(i), this.trigger("onUpdate", this.current));
789
+ }
790
+ scaleToFit(t = 300) {
791
+ this.animateZoom(1, 0, 0, t), this.$refs.container?.classList.remove("glare-can-zoom-out"), this.$refs.container?.classList.add("glare-can-zoom-in"), this.updateZoomButton();
792
+ }
793
+ scaleToActual(t, e, s = 300) {
794
+ const i = this.getImageWrap();
795
+ if (!i) return;
796
+ const n = E(i), o = t ?? n.left + n.width / 2, a = e ?? n.top + n.height / 2, l = Math.min(this.zoom.max, 2.5), u = (n.left + n.width / 2 - o) * (l - 1), h = (n.top + n.height / 2 - a) * (l - 1);
797
+ this.animateZoom(l, u, h, s), this.$refs.container?.classList.add("glare-can-zoom-out"), this.$refs.container?.classList.remove("glare-can-zoom-in"), this.updateZoomButton();
798
+ }
799
+ update() {
800
+ this.updateChrome(), this.positionContent();
801
+ }
802
+ focus() {
803
+ this.$refs.container?.focus({ preventScroll: !0 });
804
+ }
805
+ toggleControls(t) {
806
+ const e = this.$refs.container;
807
+ if (!e) return;
808
+ const s = t === void 0 ? !e.classList.contains("glare-is-idle") : t;
809
+ e.classList.toggle("glare-is-idle", s), this.isIdle = s;
810
+ }
811
+ getContentEl() {
812
+ return this.current?.$content || null;
813
+ }
814
+ getImageWrap() {
815
+ return this.current?.$slide?.querySelector(".glare-content");
816
+ }
817
+ getZoomState() {
818
+ return { ...this.zoom };
819
+ }
820
+ applyZoom(t, e, s, i = !1) {
821
+ this.animateZoom(t, e, s, i ? 250 : 0);
822
+ const n = t > 1.01;
823
+ this.$refs.container?.classList.toggle("glare-can-zoom-out", n), this.$refs.container?.classList.toggle("glare-can-zoom-in", !n), this.updateZoomButton();
824
+ }
825
+ onSwipe(t, e, s, i) {
826
+ const n = this.$refs.stage;
827
+ if (!n) return;
828
+ if (!s) {
829
+ if (m(n, {
830
+ transform: `translate3d(${t}px, ${e}px, 0)`,
831
+ transitionDuration: "0ms"
832
+ }), this.$refs.bg) {
833
+ const h = x(1 - Math.abs(e) / 400, 0.35, 1);
834
+ m(this.$refs.bg, { opacity: String(h) });
835
+ }
836
+ return;
837
+ }
838
+ const o = Math.abs(t), a = Math.abs(e), l = i?.x || 0, u = i?.y || 0;
839
+ if (m(n, { transitionDuration: "" }), this.$refs.bg && m(this.$refs.bg, { opacity: "" }), (a > 100 || Math.abs(u) > 0.5) && a > o) {
840
+ this.close();
841
+ return;
842
+ }
843
+ (o > 80 || Math.abs(l) > 0.4) && (t < 0 ? this.next() : this.prev()), m(n, { transform: "" });
844
+ }
845
+ /* -------------------- private -------------------- */
846
+ build() {
847
+ const t = this.dict(), e = $(this.opts.baseTpl || "", t), i = b("div", "", e).firstElementChild;
848
+ i.dataset.glareId = String(this.id), this.opts.baseClass && i.classList.add(this.opts.baseClass), this.opts.modal && i.classList.add("glare-is-modal"), this.$refs.container = i, this.$refs.bg = p(".glare-bg", i), this.$refs.inner = p(".glare-inner", i), this.$refs.stage = p(".glare-stage", i), this.$refs.caption = p(".glare-caption", i), this.$refs.toolbar = p(".glare-toolbar", i), this.$refs.infobar = p(".glare-infobar", i), this.$refs.navigation = p(".glare-navigation", i), this.buildToolbar(), this.updateChrome(), (!this.opts.arrows || this.group.length < 2) && this.$refs.navigation?.classList.add("glare-hidden"), (!this.opts.infobar || this.group.length < 2) && this.$refs.infobar?.classList.add("glare-hidden"), ct(this.opts.parentEl).appendChild(i);
849
+ }
850
+ buildToolbar() {
851
+ const t = this.$refs.toolbar;
852
+ if (!t) return;
853
+ if (!(this.opts.toolbar === !0 || this.opts.toolbar === "auto")) {
854
+ t.classList.add("glare-hidden");
855
+ return;
856
+ }
857
+ const s = this.dict(), i = this.opts.buttons || [];
858
+ t.innerHTML = "";
859
+ for (const n of i) {
860
+ if (n === "thumbs" && this.group.length < 2 || n === "slideshow" && this.group.length < 2) continue;
861
+ const o = this.opts.btnTpl?.[n];
862
+ o && t.insertAdjacentHTML("beforeend", $(o, s));
863
+ }
864
+ }
865
+ initModules() {
866
+ const t = this.opts.thumbs;
867
+ if (t) {
868
+ const s = t === !0 ? { ...T.thumbs } : t;
869
+ this.Thumbs = new ot(this, s), this.Thumbs.init();
870
+ }
871
+ const e = this.opts.slideShow;
872
+ if (e) {
873
+ const s = e === !0 ? { ...T.slideShow } : e;
874
+ this.SlideShow = new rt(this, s), this.SlideShow.init();
875
+ }
876
+ if (this.opts.fullScreen !== !1) {
877
+ this.FullScreen = new K(this), this.FullScreen.init();
878
+ const s = this.opts.fullScreen;
879
+ s && typeof s == "object" && s.autoStart && this.FullScreen.request();
880
+ }
881
+ this.opts.share && (this.share = new nt(this, this.opts.share)), this.opts.hash && this.galleryName && (this.hash = new O(this, this.galleryName), this.hash.init()), this.opts.wheel !== !1 && this.$refs.stage && (this.wheel = new at(this, this.opts.wheel || "auto"), this.wheel.init(this.$refs.stage)), this.opts.touch !== !1 && this.$refs.stage && (this.gestures = new G(this), this.gestures.attach(this.$refs.stage));
882
+ }
883
+ bindEvents() {
884
+ const t = this.$refs.container;
885
+ t && (this.cleanups.push(
886
+ c(t, "click", (e) => this.onClick(e)),
887
+ c(t, "dblclick", (e) => this.onDblClick(e)),
888
+ c(document, "keydown", (e) => this.onKeydown(e)),
889
+ c(window, "resize", () => this.positionContent()),
890
+ c(window, "orientationchange", () => this.positionContent()),
891
+ c(document, "mousemove", () => this.resetIdle()),
892
+ c(document, "touchstart", () => this.resetIdle(), { passive: !0 })
893
+ ), this.opts.trapFocus && this.cleanups.push(
894
+ c(t, "keydown", (e) => {
895
+ const s = e;
896
+ if (s.key !== "Tab") return;
897
+ const i = S('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])', t).filter((a) => !a.hasAttribute("disabled") && a.offsetParent !== null);
898
+ if (!i.length) return;
899
+ const n = i[0], o = i[i.length - 1];
900
+ s.shiftKey && document.activeElement === n ? (s.preventDefault(), o.focus()) : !s.shiftKey && document.activeElement === o && (s.preventDefault(), n.focus());
901
+ })
902
+ ), this.opts.protect && this.cleanups.push(
903
+ c(t, "contextmenu", (e) => {
904
+ e.preventDefault();
905
+ }),
906
+ c(t, "dragstart", (e) => {
907
+ e.target.tagName === "IMG" && e.preventDefault();
908
+ })
909
+ ));
910
+ }
911
+ onClick(t) {
912
+ if (this.gestures?.wasMoved()) {
913
+ this.gestures.resetMoved();
914
+ return;
915
+ }
916
+ const e = t.target;
917
+ if (e.closest("[data-glare-close]")) {
918
+ this.close(t);
919
+ return;
920
+ }
921
+ if (e.closest("[data-glare-next]")) {
922
+ this.next();
923
+ return;
924
+ }
925
+ if (e.closest("[data-glare-prev]")) {
926
+ this.prev();
927
+ return;
928
+ }
929
+ if (e.closest("[data-glare-zoom]")) {
930
+ this.toggleZoom(t);
931
+ return;
932
+ }
933
+ if (e.closest("[data-glare-slideshow]")) {
934
+ this.SlideShow?.toggle();
935
+ return;
936
+ }
937
+ if (e.closest("[data-glare-thumbs]")) {
938
+ this.Thumbs?.toggle();
939
+ return;
940
+ }
941
+ if (e.closest("[data-glare-fullscreen]")) {
942
+ this.FullScreen?.toggle();
943
+ return;
944
+ }
945
+ if (e.closest("[data-glare-share]")) {
946
+ this.share?.open();
947
+ return;
948
+ }
949
+ if (!e.closest("[data-glare-download]")) {
950
+ if (e.closest(".glare-content") || e.closest(".glare-space")) {
951
+ this.handleClickAction(this.opts.clickContent, t);
952
+ return;
953
+ }
954
+ if (e.closest(".glare-slide")) {
955
+ this.handleClickAction(this.opts.clickSlide, t);
956
+ return;
957
+ }
958
+ (e.classList.contains("glare-bg") || e.classList.contains("glare-stage")) && this.handleClickAction(this.opts.clickOutside, t);
959
+ }
960
+ }
961
+ onDblClick(t) {
962
+ const e = t.target;
963
+ e.closest(".glare-content") || e.closest(".glare-space") ? this.handleClickAction(this.opts.dblclickContent, t) : e.closest(".glare-slide") ? this.handleClickAction(this.opts.dblclickSlide, t) : this.handleClickAction(this.opts.dblclickOutside, t);
964
+ }
965
+ handleClickAction(t, e) {
966
+ if (!t || !this.current) return;
967
+ let s = t;
968
+ switch (typeof t == "function" && (s = t(this.current, e)), s) {
969
+ case "close":
970
+ this.close(e);
971
+ break;
972
+ case "next":
973
+ this.next();
974
+ break;
975
+ case "nextOrClose":
976
+ this.currIndex === this.group.length - 1 && !this.opts.loop ? this.close(e) : this.next();
977
+ break;
978
+ case "toggleControls":
979
+ this.toggleControls();
980
+ break;
981
+ case "zoom":
982
+ this.toggleZoom(e);
983
+ break;
984
+ }
985
+ }
986
+ onKeydown(t) {
987
+ if (!this.isActive || !this.opts.keyboard || this.opts.modal || g[g.length - 1] !== this) return;
988
+ const e = t.target?.tagName;
989
+ if (!(e === "INPUT" || e === "TEXTAREA" || e === "SELECT"))
990
+ switch (t.key) {
991
+ case "Escape":
992
+ t.preventDefault(), this.close(t);
993
+ break;
994
+ case "ArrowRight":
995
+ case "ArrowDown":
996
+ t.preventDefault(), this.next();
997
+ break;
998
+ case "ArrowLeft":
999
+ case "ArrowUp":
1000
+ t.preventDefault(), this.prev();
1001
+ break;
1002
+ case " ":
1003
+ case "Spacebar":
1004
+ t.preventDefault(), this.SlideShow?.toggle();
1005
+ break;
1006
+ case "f":
1007
+ case "F":
1008
+ this.FullScreen?.toggle();
1009
+ break;
1010
+ }
1011
+ }
1012
+ loadSlide(t, e, s) {
1013
+ const i = this.$refs.stage;
1014
+ if (!i) return;
1015
+ const n = this.group[t];
1016
+ if (!n) return;
1017
+ S(".glare-slide", i).forEach((a) => {
1018
+ Number(a.dataset.index) !== t && (a.classList.add("glare-slide--out"), setTimeout(() => a.remove(), this.opts.transitionDuration || 366));
1019
+ });
1020
+ let o = i.querySelector(`.glare-slide[data-index="${t}"]`);
1021
+ if (o || (o = b("div", `glare-slide${this.opts.slideClass ? ` ${this.opts.slideClass}` : ""}`), o.dataset.index = String(t), o.innerHTML = `
1022
+ <div class="glare-space">
1023
+ <div class="glare-content"></div>
1024
+ </div>
1025
+ `, i.appendChild(o)), n.$slide = o, n.$content = p(".glare-content", o), n.pos = t, o.classList.add("glare-slide--current"), o.classList.remove("glare-slide--out"), this.shouldSmallBtn(n)) {
1026
+ const a = this.dict();
1027
+ o.querySelector(".glare-close-small") || o.insertAdjacentHTML(
1028
+ "beforeend",
1029
+ $(this.opts.btnTpl?.smallBtn || "", a)
1030
+ );
1031
+ }
1032
+ this.showSpinner(o), this.trigger("beforeLoad", n), this.resolveContent(n).then(() => {
1033
+ !this.isActive || this.currIndex !== t || (this.hideSpinner(o), this.trigger("afterLoad", n), this.positionContent(), this.updateChrome(), this.updateDownload(n), e ? this.playOpenAnimation(n) : this.playTransition(), this.trigger("afterShow", n), this.trigger("onReveal", n));
1034
+ }).catch(() => {
1035
+ !this.isActive || this.currIndex !== t || (this.hideSpinner(o), this.showError(n));
1036
+ }), this.opts.image?.preload && [t - 1, t + 1].forEach((a) => {
1037
+ const l = this.group[a];
1038
+ if (l?.type === "image" && l.src) {
1039
+ const u = new Image();
1040
+ u.src = l.src;
1041
+ }
1042
+ });
1043
+ }
1044
+ shouldSmallBtn(t) {
1045
+ return this.opts.smallBtn === !0 ? !0 : this.opts.smallBtn === !1 ? !1 : t.type !== "image";
1046
+ }
1047
+ async resolveContent(t) {
1048
+ const e = t.$content;
1049
+ if (!e) throw new Error("Missing content node");
1050
+ switch (e.innerHTML = "", e.className = `glare-content glare-content--${t.type}`, t.type) {
1051
+ case "image":
1052
+ await this.loadImage(t, e);
1053
+ break;
1054
+ case "video":
1055
+ this.loadVideo(t, e);
1056
+ break;
1057
+ case "iframe":
1058
+ await this.loadIframe(t, e);
1059
+ break;
1060
+ case "inline":
1061
+ this.loadInline(t, e);
1062
+ break;
1063
+ case "ajax":
1064
+ await this.loadAjax(t, e);
1065
+ break;
1066
+ default:
1067
+ this.loadHtml(t, e);
1068
+ break;
1069
+ }
1070
+ t.isLoaded = !0, t.isComplete = !0;
1071
+ }
1072
+ loadImage(t, e) {
1073
+ return new Promise((s, i) => {
1074
+ const n = b("img", "glare-image");
1075
+ n.alt = t.alt || t.caption || "", n.decoding = "async", n.draggable = !1, this.opts.protect && (n.style.pointerEvents = "none"), n.onload = () => {
1076
+ t.$image = n, t.contentWidth = n.naturalWidth, t.contentHeight = n.naturalHeight, t.canZoomIn = !0, e.appendChild(n), this.$refs.container?.classList.add("glare-can-zoom-in"), s();
1077
+ }, n.onerror = () => {
1078
+ t.hasError = !0, i(new Error("image error"));
1079
+ }, n.src = t.src;
1080
+ });
1081
+ }
1082
+ loadVideo(t, e) {
1083
+ const s = t.format || this.opts.video?.format || (t.src.match(/\.(\w+)(?:\?|$)/)?.[1] ? `video/${t.src.match(/\.(\w+)(?:\?|$)/)?.[1]?.replace("ogv", "ogg")}` : "video/mp4"), i = $(this.opts.video?.tpl || "", {
1084
+ src: t.src,
1085
+ format: s,
1086
+ poster: t.poster || ""
1087
+ });
1088
+ e.innerHTML = i;
1089
+ const n = e.querySelector("video");
1090
+ t.$content = e, n && (t.autoStart ?? this.opts.video?.autoStart) && n.play().catch(() => {
1091
+ });
1092
+ }
1093
+ loadIframe(t, e) {
1094
+ return new Promise((s) => {
1095
+ const i = b("div", "glare-iframe-wrap");
1096
+ i.innerHTML = this.opts.iframe?.tpl || '<iframe class="glare-iframe"></iframe>';
1097
+ const n = i.querySelector("iframe"), o = this.opts.iframe?.attr || {};
1098
+ for (const [a, l] of Object.entries(o)) n.setAttribute(a, l);
1099
+ if (this.opts.iframe?.css && m(n, this.opts.iframe.css), t.width && m(i, { width: typeof t.width == "number" ? `${t.width}px` : String(t.width) }), t.height && m(i, { height: typeof t.height == "number" ? `${t.height}px` : String(t.height) }), e.appendChild(i), this.opts.iframe?.preload === !1) {
1100
+ n.src = t.src, s();
1101
+ return;
1102
+ }
1103
+ n.onload = () => s(), n.src = t.src, setTimeout(() => s(), 1200);
1104
+ });
1105
+ }
1106
+ loadInline(t, e) {
1107
+ const s = t.src ? p(t.src) : null;
1108
+ if (!s)
1109
+ throw t.hasError = !0, new Error("inline target missing");
1110
+ const i = s.cloneNode(!0);
1111
+ i.id = "", i.classList.remove("glare-hidden"), i.hidden = !1, i.style.display = "", e.appendChild(i);
1112
+ }
1113
+ async loadAjax(t, e) {
1114
+ const s = this.opts.ajax?.settings || {}, i = await fetch(t.src, s);
1115
+ if (!i.ok) throw new Error("ajax failed");
1116
+ const n = await i.text();
1117
+ e.innerHTML = n;
1118
+ }
1119
+ loadHtml(t, e) {
1120
+ t.content instanceof HTMLElement ? e.appendChild(t.content) : e.innerHTML = t.html || t.content || t.src || "";
1121
+ }
1122
+ showSpinner(t) {
1123
+ t.querySelector(".glare-spinner") || t.insertAdjacentHTML("beforeend", this.opts.spinnerTpl || "");
1124
+ }
1125
+ hideSpinner(t) {
1126
+ t.querySelector(".glare-spinner")?.remove();
1127
+ }
1128
+ showError(t) {
1129
+ t.hasError = !0;
1130
+ const e = t.$content;
1131
+ e && (e.className = "glare-content glare-content--error", e.innerHTML = $(this.opts.errorTpl || "", this.dict()));
1132
+ }
1133
+ playOpenAnimation(t) {
1134
+ const e = this.$refs.container;
1135
+ if (!e) return;
1136
+ const s = M() ? !1 : this.opts.animationEffect;
1137
+ if (e.dataset.animation = s ? String(s) : "none", e.style.setProperty("--glare-duration", `${this.opts.animationDuration || 0}ms`), s === "zoom" && t.$trigger && t.type === "image" && t.$image) {
1138
+ const i = E(t.$trigger), n = E(t.$image), o = i.width / Math.max(n.width, 1), a = i.height / Math.max(n.height, 1), l = i.left + i.width / 2 - (n.left + n.width / 2), u = i.top + i.height / 2 - (n.top + n.height / 2);
1139
+ m(t.$image, {
1140
+ transform: `translate3d(${l}px, ${u}px, 0) scale(${Math.max(o, a)})`,
1141
+ opacity: this.opts.zoomOpacity === !1 ? "1" : "0.2",
1142
+ transitionDuration: "0ms"
1143
+ }), A(() => {
1144
+ t.$image && m(t.$image, {
1145
+ transform: "",
1146
+ opacity: "",
1147
+ transitionDuration: `${this.opts.animationDuration || 366}ms`
1148
+ });
1149
+ });
1150
+ }
1151
+ A(() => e.classList.add("glare-is-ready"));
1152
+ }
1153
+ playTransition() {
1154
+ const t = this.$refs.container;
1155
+ if (!t) return;
1156
+ const e = M() ? !1 : this.opts.transitionEffect;
1157
+ t.dataset.transition = e ? String(e) : "none", t.style.setProperty(
1158
+ "--glare-transition-duration",
1159
+ `${this.opts.transitionDuration || 0}ms`
1160
+ );
1161
+ }
1162
+ positionContent() {
1163
+ const t = this.current;
1164
+ if (!t?.$image || !t.contentWidth || !t.contentHeight) return;
1165
+ const e = t.$slide;
1166
+ if (!e) return;
1167
+ const s = p(".glare-space", e);
1168
+ if (!s) return;
1169
+ const i = E(s), n = Math.min(i.width / t.contentWidth, i.height / t.contentHeight, 1);
1170
+ t.canZoomIn = n < 0.98 || t.contentWidth > i.width || t.contentHeight > i.height, this.$refs.container?.classList.toggle("glare-can-zoom-in", !!t.canZoomIn && this.zoom.scale <= 1.01);
1171
+ }
1172
+ updateChrome() {
1173
+ const t = this.current;
1174
+ if (!t) return;
1175
+ if (this.$refs.infobar) {
1176
+ const i = p(".glare-infobar-index", this.$refs.infobar);
1177
+ i && (i.textContent = `${this.currIndex + 1} / ${this.group.length}`);
1178
+ }
1179
+ if (this.$refs.caption) {
1180
+ let i = t.caption || "";
1181
+ typeof this.opts.caption == "function" ? i = this.opts.caption(this, t) : typeof this.opts.caption == "string" && (i = this.opts.caption), this.$refs.caption.innerHTML = i, this.$refs.caption.classList.toggle("glare-hidden", !i), this.$refs.container?.classList.toggle("glare-show-caption", !!i);
1182
+ }
1183
+ const e = this.currIndex === 0 && !this.opts.loop, s = this.currIndex === this.group.length - 1 && !this.opts.loop;
1184
+ this.$refs.container?.querySelector("[data-glare-prev]")?.classList.toggle("glare-disabled", e), this.$refs.container?.querySelector("[data-glare-next]")?.classList.toggle("glare-disabled", s), this.$refs.container?.setAttribute("aria-label", ut(t, this.currIndex, this.group.length));
1185
+ }
1186
+ updateDownload(t) {
1187
+ const e = this.$refs.container?.querySelector("[data-glare-download]");
1188
+ if (!e) return;
1189
+ const s = t.downloadSrc || (t.type === "image" ? t.src : "");
1190
+ s ? (e.href = s, e.classList.remove("glare-hidden")) : e.classList.add("glare-hidden");
1191
+ }
1192
+ toggleZoom(t) {
1193
+ if (!(!this.current || this.current.type !== "image"))
1194
+ if (this.zoom.scale > 1.01)
1195
+ this.scaleToFit();
1196
+ else {
1197
+ const e = t ? { x: t.clientX, y: t.clientY } : void 0;
1198
+ this.scaleToActual(e?.x, e?.y);
1199
+ }
1200
+ }
1201
+ animateZoom(t, e, s, i = 0) {
1202
+ const n = this.getImageWrap(), o = this.current?.$image;
1203
+ !n || !o || (this.zoom.scale = x(t, this.zoom.min, this.zoom.max), this.zoom.x = e, this.zoom.y = s, m(o, {
1204
+ transform: `translate3d(${e}px, ${s}px, 0) scale(${this.zoom.scale})`,
1205
+ transitionDuration: `${i}ms`
1206
+ }));
1207
+ }
1208
+ resetZoom() {
1209
+ this.zoom = { scale: 1, x: 0, y: 0, min: 1, max: 5 }, this.$refs.container?.classList.remove("glare-can-zoom-out");
1210
+ }
1211
+ updateZoomButton() {
1212
+ const t = this.$refs.container?.querySelector("[data-glare-zoom]");
1213
+ t && (t.innerHTML = this.zoom.scale > 1.01 ? d.zoomOut : d.zoomIn, t.classList.toggle("is-active", this.zoom.scale > 1.01));
1214
+ }
1215
+ resetIdle() {
1216
+ this.clearIdle(), this.isIdle && this.toggleControls(!1);
1217
+ const t = this.opts.idleTime;
1218
+ !t || this.opts.modal || (this.idleTimer = setTimeout(() => {
1219
+ this.toggleControls(!0);
1220
+ }, t * 1e3));
1221
+ }
1222
+ clearIdle() {
1223
+ this.idleTimer && (clearTimeout(this.idleTimer), this.idleTimer = null);
1224
+ }
1225
+ dict() {
1226
+ const t = this.opts.lang || "en";
1227
+ return {
1228
+ ...ht,
1229
+ ...this.opts.i18n?.en || {},
1230
+ ...this.opts.i18n?.[t] || {}
1231
+ };
1232
+ }
1233
+ trigger(t, e, ...s) {
1234
+ const i = this.opts[t];
1235
+ if (typeof i == "function")
1236
+ return i(this, e, ...s);
1237
+ }
1238
+ teardown() {
1239
+ this.gestures?.detach(), this.wheel?.destroy(), this.hash?.destroy(), this.share?.destroy(), this.Thumbs?.destroy(), this.SlideShow?.destroy(), this.FullScreen?.destroy(), this.cleanups.forEach((e) => e()), this.cleanups = [], this.$refs.container?.remove(), this.$refs = {
1240
+ container: null,
1241
+ stage: null,
1242
+ bg: null,
1243
+ inner: null,
1244
+ caption: null,
1245
+ toolbar: null,
1246
+ infobar: null,
1247
+ navigation: null
1248
+ };
1249
+ const t = g.indexOf(this);
1250
+ t >= 0 && g.splice(t, 1), this.opts.hideScrollbar && R(!1), this.opts.backFocus && (this.openedFrom || this.previouslyFocused)?.focus?.({ preventScroll: !0 }), this.isActive = !1, this.isClosing = !1, this.trigger("afterClose", this.current || void 0), this.trigger("onDeactivate"), this.trigger("onDestroy");
1251
+ }
1252
+ static getInstance(t) {
1253
+ return t != null ? g.find((e) => e.id === t) || null : g[g.length - 1] || null;
1254
+ }
1255
+ static getInstances() {
1256
+ return [...g];
1257
+ }
1258
+ static open(t, e = {}, s = 0) {
1259
+ const i = new v(t, e, s);
1260
+ return i.open(s), i;
1261
+ }
1262
+ static close(t = !1) {
1263
+ if (t) {
1264
+ [...g].reverse().forEach((e) => e.close());
1265
+ return;
1266
+ }
1267
+ g[g.length - 1]?.close();
1268
+ }
1269
+ static destroy() {
1270
+ v.close(!0), k.forEach((t) => t.destroy()), k.length = 0;
1271
+ }
1272
+ static bind(t, e = {}) {
1273
+ const s = typeof t == "string" ? S(t) : t instanceof HTMLElement ? [t] : Array.from(t), i = (a) => {
1274
+ const l = a.target;
1275
+ if (!l) return;
1276
+ const u = s.find((y) => y === l || y.contains(l));
1277
+ if (!u) return;
1278
+ a.preventDefault();
1279
+ const h = u.getAttribute("data-glare") || u.getAttribute("data-glare") || "", f = h ? s.filter(
1280
+ (y) => (y.getAttribute("data-glare") || y.getAttribute("data-glare") || "") === h
1281
+ ) : [u], w = Math.max(0, f.indexOf(u));
1282
+ new v(f, e, w, h || "gallery").open(w);
1283
+ }, n = s.map((a) => c(a, "click", i)), o = {
1284
+ selector: typeof t == "string" ? t : "",
1285
+ options: e,
1286
+ elements: s,
1287
+ destroy: () => {
1288
+ n.forEach((l) => l());
1289
+ const a = k.indexOf(o);
1290
+ a >= 0 && k.splice(a, 1);
1291
+ }
1292
+ };
1293
+ return k.push(o), o;
1294
+ }
1295
+ static fromSelector(t, e = {}) {
1296
+ const s = S(t);
1297
+ if (!s.length) return null;
1298
+ const i = new v(s, e, 0, "gallery");
1299
+ return i.open(0), i;
1300
+ }
1301
+ };
1302
+ v.defaults = T;
1303
+ let z = v;
1304
+ const k = [], ht = {
1305
+ CLOSE: "Close",
1306
+ NEXT: "Next",
1307
+ PREV: "Previous",
1308
+ ERROR: "The requested content cannot be loaded.<br/>Please try again later.",
1309
+ PLAY_START: "Start slideshow",
1310
+ PLAY_STOP: "Pause slideshow",
1311
+ FULL_SCREEN: "Full screen",
1312
+ THUMBS: "Thumbnails",
1313
+ DOWNLOAD: "Download",
1314
+ SHARE: "Share",
1315
+ ZOOM: "Zoom"
1316
+ };
1317
+ function ut(r, t, e) {
1318
+ const s = r.caption || r.alt || "Media lightbox";
1319
+ return e > 1 ? `${s} (${t + 1} of ${e})` : s;
1320
+ }
1321
+ function dt() {
1322
+ if (typeof document > "u") return;
1323
+ const r = () => {
1324
+ S("[data-glare], [data-glare]").length && z.bind("[data-glare], [data-glare]");
1325
+ };
1326
+ document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", r, { once: !0 }) : r();
1327
+ }
1328
+ export {
1329
+ z as Glare,
1330
+ dt as autoBind,
1331
+ z as default,
1332
+ _ as defaultMedia,
1333
+ T as defaults,
1334
+ tt as detectType,
1335
+ N as i18nEn,
1336
+ st as itemsFromElements,
1337
+ B as normalizeItem
1338
+ };
1339
+ //# sourceMappingURL=glare.esm.js.map