/** * @fileoverview Image Preview Component for Rantii * @author retoor * @description Displays images with lightbox functionality * @keywords image, preview, lightbox, gallery, media */ import { BaseComponent } from './base-component.js'; import { buildDevrantImageUrl, isGifUrl } from '../utils/url.js'; class ImagePreview extends BaseComponent { static get observedAttributes() { return ['src', 'width', 'height', 'alt']; } init() { this.render(); this.bindEvents(); } render() { const src = this.getAttr('src'); const width = this.getAttr('width'); const height = this.getAttr('height'); const alt = this.getAttr('alt') || 'Image'; if (!src) { this.setHtml(''); return; } const imageUrl = buildDevrantImageUrl(src); const isGif = isGifUrl(imageUrl); const aspectRatio = width && height ? width / height : null; this.addClass('image-preview'); this.setHtml(`
${alt} ${isGif ? 'GIF' : ''}
`); } bindEvents() { this.on(this, 'click', this.handleClick); } handleClick(e) { const expandBtn = e.target.closest('.expand-btn'); const img = e.target.closest('.preview-image'); if (expandBtn || img) { e.preventDefault(); this.openLightbox(); } } openLightbox() { const src = this.getAttr('src'); if (!src) return; const imageUrl = buildDevrantImageUrl(src); const lightbox = document.createElement('image-lightbox'); lightbox.setAttribute('src', imageUrl); document.body.appendChild(lightbox); } onAttributeChanged(name, oldValue, newValue) { this.render(); } } customElements.define('image-preview', ImagePreview); class ImageLightbox extends BaseComponent { static get observedAttributes() { return ['src']; } init() { this.keydownHandler = (e) => this.handleKeydown(e); this.render(); this.bindEvents(); } render() { const src = this.getAttr('src'); this.addClass('lightbox'); this.setHtml(` `); requestAnimationFrame(() => this.addClass('lightbox-visible')); } bindEvents() { this.on(this, 'click', this.handleClick); document.addEventListener('keydown', this.keydownHandler); } handleClick(e) { if (e.target.classList.contains('lightbox-backdrop') || e.target.closest('.lightbox-close')) { this.close(); } } handleKeydown(e) { if (e.key === 'Escape') { this.close(); } } close() { document.removeEventListener('keydown', this.keydownHandler); this.removeClass('lightbox-visible'); setTimeout(() => this.remove(), 300); } } customElements.define('image-lightbox', ImageLightbox); export { ImagePreview, ImageLightbox };