/**
* Image Manager Web Component
* Centralized management of all image prompts and configurations
* Provides a single source of truth for all image URLs in the application
*/
class ImageManager extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.config = null;
this.imageCache = new Map();
}
connectedCallback() {
this.loadConfig();
this.render();
}
loadConfig() {
// Try to load from JSON config element
const configElement = document.getElementById('imagePromptsConfig');
if (configElement) {
try {
this.config = JSON.parse(configElement.textContent);
} catch (e) {
console.error('Failed to parse image prompts config:', e);
this.config = this.getDefaultConfig();
}
} else {
this.config = this.getDefaultConfig();
}
// Store in global window object for easy access
window.imagePrompts = this.config;
}
getDefaultConfig() {
return {
hero: "https://static.photos/medical/800x600/1",
productImages: [
"https://static.photos/medical/400x300/101",
"https://static.photos/medical/400x300/102",
"https://static.photos/medical/400x300/103",
"https://static.photos/medical/400x300/104"
],
about: "https://static.photos/workspace/800x600/201",
testimonials: [
"https://static.photos/people/48x48/301",
"https://static.photos/people/48x48/302",
"https://static.photos/people/48x48/303"
],
categories: {
medical: "medical",
workspace: "workspace",
people: "people",
abstract: "abstract"
},
placeholder: "https://static.photos/abstract/100x100",
fallback: "https://static.photos/abstract/400x300"
};
}
render() {
this.shadowRoot.innerHTML = `
Hero Image
${this.config?.hero ? this.config.hero.substring(0, 30) + '...' : ''}
Product Images (${this.config?.productImages?.length || 0})
${this.config?.productImages?.map((url, index) => `
Product ${index + 1}: ${url.substring(0, 25)}...
`).join('') || '
No product images configured
'}
Testimonial Images (${this.config?.testimonials?.length || 0})
${this.config?.testimonials?.map((url, index) => `
Testimonial ${index + 1}: ${url.substring(0, 25)}...
`).join('') || '
No testimonial images configured
'}
Configuration
Categories: ${this.config?.categories ? Object.keys(this.config.categories).join(', ') : ''}
`;
this.addEventListeners();
}
addEventListeners() {
const toggleBtn = this.shadowRoot.querySelector('.image-manager-toggle');
const closeBtn = this.shadowRoot.querySelector('.image-manager-close');
const panel = this.shadowRoot.querySelector('.image-manager-panel');
const copyButtons = this.shadowRoot.querySelectorAll('.image-manager-copy');
if (toggleBtn && panel) {
toggleBtn.addEventListener('click', () => {
panel.classList.toggle('active');
});
}
if (closeBtn && panel) {
closeBtn.addEventListener('click', () => {
panel.classList.remove('active');
});
}
if (copyButtons) {
copyButtons.forEach(btn => {
btn.addEventListener('click', (e) => {
const url = e.currentTarget.getAttribute('data-url');
this.copyToClipboard(url);
// Show feedback
const originalText = e.currentTarget.textContent;
e.currentTarget.textContent = 'Copied!';
e.currentTarget.style.background = '#28a745';
setTimeout(() => {
e.currentTarget.textContent = originalText;
e.currentTarget.style.background = '#5d9245';
}, 1500);
});
});
}
}
copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
console.log('Image URL copied to clipboard:', text);
}).catch(err => {
console.error('Failed to copy:', err);
// Fallback method
const textArea = document.createElement('textarea');
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
});
}
// Public API methods
getImage(category, index = 0) {
if (!this.config) return this.config?.fallback || '';
switch(category) {
case 'hero':
return this.config.hero;
case 'product':
return this.config.productImages[index] || this.config.fallback;
case 'testimonial':
return this.config.testimonials[index] || this.config.fallback;
case 'about':
return this.config.about;
case 'placeholder':
return this.config.placeholder;
default:
return this.config.fallback;
}
}
updateImage(category, value, index = 0) {
if (!this.config) return false;
switch(category) {
case 'hero':
this.config.hero = value;
break;
case 'product':
if (this.config.productImages && index < this.config.productImages.length) {
this.config.productImages[index] = value;
}
break;
case 'testimonial':
if (this.config.testimonials && index < this.config.testimonials.length) {
this.config.testimonials[index] = value;
}
break;
case 'about':
this.config.about = value;
break;
default:
return false;
}
// Update the JSON config element
const configElement = document.getElementById('imagePromptsConfig');
if (configElement) {
configElement.textContent = JSON.stringify(this.config, null, 2);
}
return true;
}
static get observedAttributes() {
return ['config'];
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'config' && oldValue !== newValue) {
this.loadConfig();
this.render();
}
}
}
customElements.define('image-manager', ImageManager);