From 656b606c3ed21c64823cd5a91dfc9ca01fa7b1fb Mon Sep 17 00:00:00 2001 From: Volpeon Date: Wed, 22 Jul 2026 22:32:09 +0200 Subject: Package cleanup --- src/scripts/lib/lightbox.ts | 450 -------------------------------------------- 1 file changed, 450 deletions(-) delete mode 100644 src/scripts/lib/lightbox.ts (limited to 'src/scripts/lib/lightbox.ts') diff --git a/src/scripts/lib/lightbox.ts b/src/scripts/lib/lightbox.ts deleted file mode 100644 index ac5b581..0000000 --- a/src/scripts/lib/lightbox.ts +++ /dev/null @@ -1,450 +0,0 @@ -import Alpine from "alpinejs"; - -export interface LightboxItem { - thumbnail?: string; - src: string; - srcset?: string; - alt: string; -} - -function touchParams(e: TouchEvent) { - const [t0, t1] = e.touches; - - if (e.touches.length > 2 || !t0) { - return; - } - - let x = t0.clientX; - let y = t0.clientY; - let dist = 0; - - if (t1) { - dist = Math.hypot(x - t1.clientX, y - t1.clientY); - x = (x + t1.clientX) / 2; - y = (y + t1.clientY) / 2; - } - - return { x, y, dist }; -} - -export function mountLightbox() { - const minZoom = 0.9; - - Alpine.data("lightbox", () => ({ - _zoom: minZoom, - _offsetX: 0, - _offsetY: 0, - - loading: false, - inertia: false, - items: [], - current: 0, - dragging: false, - touchStart: { - x: 0, - y: 0, - distance: 0, - transformOrigin: { x: 0, y: 0 }, - zoom: 1, - offsetX: 0, - offsetY: 0, - timestamp: 0, - }, - velocity: { - measure: false, - prevOffsetX: 0, - prevOffsetY: 0, - timestamp: 0, - x: 0, - y: 0, - }, - - get zoom() { - return this._zoom; - }, - set zoom(value) { - this._zoom = Math.min(this.maxZoom, Math.max(minZoom, value)); - /* oxlint-disable-next-line eslint/no-self-assign */ // deno-lint-ignore no-self-assign - this.offsetX = this.offsetX; - /* oxlint-disable-next-line eslint/no-self-assign */ // deno-lint-ignore no-self-assign - this.offsetY = this.offsetY; - }, - - get offsetX() { - return this._offsetX; - }, - set offsetX(value) { - const limit = this.offsetLimit; - this._offsetX = Math.min(limit.x, Math.max(-limit.x, value)); - }, - - get offsetY() { - return this._offsetY; - }, - set offsetY(value) { - const limit = this.offsetLimit; - this._offsetY = Math.min(limit.y, Math.max(-limit.y, value)); - }, - - get offsetLimit(): { x: number; y: number } { - if (!this.$refs.img) { - return { x: 0, y: 0 }; - } - - const th = this.$refs.thumbnails?.clientHeight ?? 0; - const cw = this.$root.clientWidth; - const ch = this.$root.clientHeight - th; - const x = 0.5 * Math.max(0, this.$refs.img.clientWidth * this.zoom - cw); - const y = 0.5 * Math.max(0, this.$refs.img.clientHeight * this.zoom - ch); - - return { x, y }; - }, - - get open(): boolean { - return !!this.$root.hasAttribute("open"); - }, - - get currentItem(): LightboxItem { - return this.items[this.current] ?? { src: "", alt: "" }; - }, - - get transformOrigin(): { x: number; y: number } { - const img = this.$refs.img; - - if (!img) { - return { x: this.offsetX, y: this.offsetY }; - } - - return { - x: img.offsetLeft + img.clientWidth / 2 + this.offsetX, - y: img.offsetTop + img.clientHeight / 2 + this.offsetY, - }; - }, - - get naturalZoom() { - const img = this.$refs.img; - return img ? img.naturalWidth / img.clientWidth : 1; - }, - - get maxZoom() { - return Math.max(this.naturalZoom, 5); - }, - - get zoomedFull() { - return Math.abs(this.zoom - this.naturalZoom) < 0.1; - }, - - init() { - const triggerEls = document.querySelectorAll("a[data-lightbox]"); - const galleries = new Map(); - - for (const triggerEl of triggerEls) { - const triggerImgEl = triggerEl.querySelector("img"); - - const key = triggerEl.dataset.lightbox ?? ""; - const gallery = galleries.get(key); - const item: LightboxItem = { - thumbnail: triggerImgEl?.src, - src: triggerEl.href, - srcset: triggerEl.dataset.lightboxSrcset, - alt: "", - }; - - if (gallery) { - gallery.push(item); - } else { - galleries.set(key, [item]); - } - - triggerEl.style.cursor = "zoom-in"; - triggerEl.addEventListener("click", (e) => { - e.preventDefault(); - this.show(galleries.get(key) ?? [], item.src); - }); - } - - this.$watch("currentItem.src", () => { - this.loading = true; - this.reset(); - }); - }, - - show(items: LightboxItem[], src?: string) { - const current = items.findIndex((item) => item.src === src); - this.items = items; - this.current = current === -1 ? 0 : current; - this.reset(); - - (this.$root).showModal(); - }, - - close() { - (this.$root).close(); - }, - - reset() { - this.stopVelocity(); - this.stopInertia(); - this.dragging = false; - this._zoom = minZoom; - this._offsetX = 0; - this._offsetY = 0; - }, - - prev() { - this.current = this.current > 0 ? this.current - 1 : this.items.length - 1; - }, - - next() { - this.current = this.current < this.items.length - 1 ? this.current + 1 : 0; - }, - - toggleZoom(x?: number, y?: number) { - const zoom = this.zoomedFull ? minZoom : this.naturalZoom; - const deltaZoom = zoom / this.zoom - 1; - - this.zoom = zoom; - - if (x !== undefined && y !== undefined) { - const transformOrigin = this.transformOrigin; - const offsetX = transformOrigin.x - x; - const offsetY = transformOrigin.y - y; - - this.offsetX += offsetX * deltaZoom; - this.offsetY += offsetY * deltaZoom; - } - }, - - measureVelocity(loop?: boolean) { - if (!loop) { - this.inertia = false; - - if (this.velocity.measure) { - return; - } else { - this.velocity.prevOffsetX = this.offsetX; - this.velocity.prevOffsetY = this.offsetY; - this.velocity.x = 0; - this.velocity.y = 0; - this.velocity.measure = true; - } - } - if (!this.velocity.measure) { - return; - } - - const deltaX = this.offsetX - this.velocity.prevOffsetX; - const deltaY = this.offsetY - this.velocity.prevOffsetY; - let window = 1; - - if ( - Math.sqrt(deltaX ** 2 + deltaY ** 2) < - Math.sqrt(this.velocity.x ** 2 + this.velocity.y ** 2) - ) { - window = 6; - } - - this.velocity.x -= this.velocity.x / window; - this.velocity.x += deltaX / window; - this.velocity.y -= this.velocity.y / window; - this.velocity.y += deltaY / window; - - this.velocity.prevOffsetX = this.offsetX; - this.velocity.prevOffsetY = this.offsetY; - - requestAnimationFrame(this.measureVelocity.bind(this, true)); - }, - - stopVelocity() { - this.velocity.measure = false; - }, - - runInertia(loop?: boolean, timestamp: DOMHighResTimeStamp = performance.now()) { - const len = Math.sqrt(this.velocity.x ** 2 + this.velocity.y ** 2); - - if (!loop) { - this.stopVelocity(); - - if (this.inertia) { - return; - } else if (len > 5) { - this.inertia = true; - this.velocity.timestamp = timestamp; - } - } - - if (!this.inertia) { - this.stopInertia(); - return; - } - - if (loop) { - const norm = { x: this.velocity.x / len, y: this.velocity.y / len }; - const elapsed = timestamp - this.velocity.timestamp; - const friction = 30 * (elapsed / 1000); - const decel = { x: norm.x * friction, y: norm.y * friction }; - const decelLen = Math.sqrt(decel.x ** 2 + decel.y ** 2); - - if (len < decelLen) { - this.stopInertia(); - return; - } - - this.offsetX += this.velocity.x; - this.offsetY += this.velocity.y; - this.velocity.x -= decel.x; - this.velocity.y -= decel.y; - this.velocity.timestamp = timestamp; - } - - requestAnimationFrame(this.runInertia.bind(this, true)); - }, - - stopInertia() { - this.inertia = false; - }, - - handleClose() { - this.stopVelocity(); - this.stopInertia(); - }, - - handleScroll(e: WheelEvent) { - this.stopInertia(); - - const direction = e.deltaY > 0 ? -1 : 1; - - const transformOrigin = this.transformOrigin; - const offsetX = transformOrigin.x - e.clientX; - const offsetY = transformOrigin.y - e.clientY; - - const zoom = Math.min(this.maxZoom, Math.max(minZoom, this.zoom * (1 + direction * 0.1))); - const deltaZoom = zoom / this.zoom - 1; - - this.zoom = zoom; - this.offsetX += offsetX * deltaZoom; - this.offsetY += offsetY * deltaZoom; - }, - - handleMouseDown(e: MouseEvent) { - this.measureVelocity(); - - if (e.buttons === 1) { - this.dragging = true; - } - }, - - handleMouseMove(e: MouseEvent) { - if (!this.dragging) { - return; - } - - this.offsetX += e.movementX; - this.offsetY += e.movementY; - }, - - handleMouseUp() { - this.dragging = false; - this.runInertia(); - }, - - handleDoubleClick(e: MouseEvent) { - this.toggleZoom(e.clientX, e.clientY); - }, - - handleTouchStart(e: TouchEvent) { - const params = touchParams(e); - - if (!params || (e.touches.length === 1 && e.target !== this.$refs.img)) { - return; - } - - e.preventDefault(); - - const now = Date.now(); - - if (e.touches.length === 1) { - if ( - now - this.touchStart.timestamp < 200 && - Math.sqrt((params.x - this.touchStart.x) ** 2 + (params.y - this.touchStart.y) ** 2) < 20 - ) { - this.toggleZoom(params.x, params.y); - } - } - - this.touchStart.x = params.x; - this.touchStart.y = params.y; - this.touchStart.distance = params.dist; - this.touchStart.transformOrigin = this.transformOrigin; - this.touchStart.zoom = this.zoom; - this.touchStart.offsetX = this.offsetX; - this.touchStart.offsetY = this.offsetY; - this.touchStart.timestamp = now; - - this.dragging = false; - - if (e.touches.length === 1) { - this.measureVelocity(); - } else { - this.stopVelocity(); - } - }, - - handleTouchMove(e: TouchEvent) { - const params = touchParams(e); - - if (!params || (e.touches.length === 1 && e.target !== this.$refs.img)) { - return; - } - - e.preventDefault(); - - const deltaX = params.x - this.touchStart.x; - const deltaY = params.y - this.touchStart.y; - const deltaDist = this.touchStart.distance ? params.dist / this.touchStart.distance : 1; - - const offsetX = this.touchStart.transformOrigin.x - this.touchStart.x; - const offsetY = this.touchStart.transformOrigin.y - this.touchStart.y; - - const zoom = Math.min(this.maxZoom, Math.max(minZoom, this.touchStart.zoom * deltaDist)); - const deltaZoom = zoom / this.touchStart.zoom - 1; - - this.zoom = zoom; - this.offsetX = this.touchStart.offsetX + deltaX + offsetX * deltaZoom; - this.offsetY = this.touchStart.offsetY + deltaY + offsetY * deltaZoom; - }, - - handleTouchEnd(e: TouchEvent) { - this.handleTouchStart(e); - - if (!e.touches.length) { - this.runInertia(); - } - }, - - handleKeyDown(e: KeyboardEvent) { - if (!this.open || e.defaultPrevented) { - return; - } - - this.stopInertia(); - - switch (e.key) { - case "Left": - case "ArrowLeft": - this.prev(); - break; - - case "Right": - case "ArrowRight": - this.next(); - break; - - default: - return; - } - - e.preventDefault(); - }, - })); -} -- cgit v1.3.1