| class CustomGalleryGrid extends HTMLElement { |
| static get observedAttributes() { |
| return ['items']; |
| } |
|
|
| constructor() { |
| super(); |
| this.items = []; |
| } |
|
|
| connectedCallback() { |
| this.attachShadow({ mode: 'open' }); |
| this.render(); |
| } |
|
|
| setItems(items) { |
| this.items = items; |
| this.render(); |
| } |
|
|
| render() { |
| this.shadowRoot.innerHTML = ` |
| <style> |
| :host { |
| display: block; |
| } |
| |
| .gallery-grid { |
| display: grid; |
| grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); |
| gap: 1.5rem; |
| } |
| |
| @media (max-width: 768px) { |
| .gallery-grid { |
| grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); |
| } |
| } |
| |
| .gallery-item { |
| position: relative; |
| aspect-ratio: 16/10; |
| border-radius: 16px; |
| overflow: hidden; |
| cursor: pointer; |
| transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); |
| background: rgba(30, 41, 59, 0.5); |
| } |
| |
| .gallery-item:hover { |
| transform: translateY(-8px) scale(1.02); |
| box-shadow: 0 30px 60px rgba(14, 165, 233, 0.2); |
| } |
| |
| .gallery-item img, |
| .gallery-item video { |
| width: 100%; |
| height: 100%; |
| object-fit: cover; |
| transition: transform 0.6s ease; |
| } |
| |
| .gallery-item:hover img, |
| .gallery-item:hover video { |
| transform: scale(1.1); |
| } |
| |
| .item-overlay { |
| position: absolute; |
| inset: 0; |
| background: linear-gradient(to top, rgba(15, 23, 42, 0.95) 0%, rgba(15, 23, 42, 0.3) 50%, transparent 100%); |
| opacity: 0; |
| transition: opacity 0.3s ease; |
| display: flex; |
| flex-direction: column; |
| justify-content: flex-end; |
| padding: 1.5rem; |
| } |
| |
| .gallery-item:hover .item-overlay { |
| opacity: 1; |
| } |
| |
| .resolution-badge { |
| position: absolute; |
| top: 1rem; |
| right: 1rem; |
| padding: 0.375rem 0.75rem; |
| background: linear-gradient(135deg, #0ea5e9, #d946ef); |
| border-radius: 8px; |
| font-size: 0.75rem; |
| font-weight: 700; |
| color: white; |
| text-transform: uppercase; |
| } |
| |
| .item-prompt { |
| font-size: 0.875rem; |
| color: #e2e8f0; |
| line-height: 1.5; |
| display: -webkit-box; |
| -webkit-line-clamp: 2; |
| -webkit-box-orient: vertical; |
| overflow: hidden; |
| margin-bottom: 0.75rem; |
| } |
| |
| .item-meta { |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| font-size: 0.75rem; |
| color: #94a3b8; |
| } |
| |
| .item-actions { |
| display: flex; |
| gap: 0.5rem; |
| } |
| |
| .action-btn { |
| width: 36px; |
| height: 36px; |
| border-radius: 10px; |
| background: rgba(255, 255, 255, 0.1); |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| color: white; |
| cursor: pointer; |
| transition: all 0.2s ease; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| } |
| |
| .action-btn:hover { |
| background: #0ea5e9; |
| border-color: #0ea5e9; |
| } |
| |
| .empty-state { |
| text-align: center; |
| padding: 4rem; |
| color: #64748b; |
| } |
| |
| .loading-skeleton { |
| aspect-ratio: 16/10; |
| border-radius: 16px; |
| background: linear-gradient(90deg, rgba(30, 41, 59, 0.5) 25%, rgba(30, 41, 59, 0.8) 50%, rgba(30, 41, 59, 0.5) 75%); |
| background-size: 200% 100%; |
| animation: shimmer 1.5s infinite; |
| } |
| |
| @keyframes shimmer { |
| 0% { background-position: 200% 0; } |
| 100% { background-position: -200% 0; } |
| } |
| </style> |
| |
| <div class="gallery-grid"> |
| ${this.items.length === 0 ? ` |
| <div class="loading-skeleton"></div> |
| <div class="loading-skeleton"></div> |
| <div class="loading-skeleton"></div> |
| <div class="loading-skeleton"></div> |
| ` : this.items.map(item => ` |
| <div class="gallery-item" data-id="${item.id}"> |
| ${item.result.qualityLabel ? ` |
| <span class="resolution-badge ${item.isFallback ? 'bg-amber-500/20 text-amber-400' : ''}"> |
| ${item.result.qualityLabel} |
| ${item.isFallback ? ' (Demo)' : ''} |
| </span> |
| ` : ''} |
| <img src="${item.result.url}" alt="${item.prompt}" loading="lazy"> |
| <div class="item-overlay"> |
| <p class="item-prompt">${item.prompt}</p> |
| <div class="item-meta"> |
| <span>${item.mode.toUpperCase()} • ${item.result.resolution || 'Standard'}</span> |
| <div class="item-actions"> |
| <button class="action-btn" title="Download"> |
| <i data-feather="download" style="width: 16px; height: 16px;"></i> |
| </button> |
| <button class="action-btn" title="Expand"> |
| <i data-feather="maximize-2" style="width: 16px; height: 16px;"></i> |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
| `).join('')} |
| </div> |
| `; |
| |
| if (window.feather) { |
| setTimeout(() => feather.replace(), 0); |
| } |
| } |
| } |
|
|
| customElements.define('custom-gallery-grid', CustomGalleryGrid); |