Saravutw's picture
sx
6c93a54 verified
class CustomApiShowcase extends HTMLElement {
static get observedAttributes() {
return ['api-name', 'category', 'description', 'endpoint', 'docs-url'];
}
constructor() {
super();
this.apiName = 'API Name';
this.category = 'Category';
this.description = 'API description goes here.';
this.endpoint = 'https://api.example.com';
this.docsUrl = 'https://docs.example.com';
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
this[name] = newValue;
this.render();
}
}
connectedCallback() {
this.render();
}
getCategoryColor() {
const colors = {
'Data Mocking': 'bg-blue-100 text-blue-800',
'Fun & Images': 'bg-purple-100 text-purple-800',
'Weather Data': 'bg-green-100 text-green-800',
'Finance': 'bg-emerald-100 text-emerald-800',
'Social': 'bg-pink-100 text-pink-800',
'Development': 'bg-orange-100 text-orange-800',
'Business': 'bg-indigo-100 text-indigo-800'
};
return colors[this.category] || 'bg-gray-100 text-gray-800';
}
render() {
const categoryColor = this.getCategoryColor();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
}
.api-card {
transition: all 0.3s ease;
}
.api-card:hover {
transform: translateX(5px);
}
.endpoint-box {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
}
.copy-btn {
transition: all 0.2s ease;
}
.copy-btn:hover {
transform: scale(1.05);
}
.copy-btn:active {
transform: scale(0.95);
}
</style>
<div class="api-card bg-white rounded-xl border border-gray-200 p-6 hover:border-blue-300 hover:shadow-xl">
<div class="flex flex-col md:flex-row md:items-start md:justify-between mb-4">
<div class="mb-4 md:mb-0 md:mr-6">
<div class="flex items-center space-x-3 mb-2">
<h3 class="text-xl font-bold text-gray-900">${this.apiName}</h3>
<span class="px-3 py-1 rounded-full text-xs font-semibold ${categoryColor}">
${this.category}
</span>
</div>
<p class="text-gray-600">${this.description}</p>
</div>
<div class="flex space-x-3">
<a href="${this.docsUrl}" target="_blank" class="inline-flex items-center px-4 py-2 bg-blue-50 hover:bg-blue-100 text-blue-600 font-medium rounded-lg transition duration-300">
<i data-feather="book-open" class="w-4 h-4 mr-2"></i>
Docs
</a>
<a href="/try?api=${encodeURIComponent(this.apiName)}" class="inline-flex items-center px-4 py-2 bg-gradient-to-r from-blue-500 to-purple-500 hover:from-blue-600 hover:to-purple-600 text-white font-medium rounded-lg transition duration-300 shadow-md hover:shadow-lg">
<i data-feather="play" class="w-4 h-4 mr-2"></i>
Try It
</a>
</div>
</div>
<div class="mt-6">
<div class="flex items-center justify-between mb-2">
<span class="text-sm font-medium text-gray-500">Endpoint</span>
<button class="copy-btn flex items-center text-sm text-blue-600 hover:text-blue-800 font-medium" data-copy="${this.endpoint}">
<i data-feather="copy" class="w-4 h-4 mr-1"></i>
Copy
</button>
</div>
<div class="endpoint-box bg-gray-50 border border-gray-200 rounded-lg p-4 overflow-x-auto">
<code class="text-sm text-gray-800">${this.endpoint}</code>
</div>
</div>
<div class="mt-6 flex items-center text-sm text-gray-500">
<div class="flex items-center mr-6">
<i data-feather="zap" class="w-4 h-4 mr-2 text-green-500"></i>
<span>99.9% Uptime</span>
</div>
<div class="flex items-center mr-6">
<i data-feather="clock" class="w-4 h-4 mr-2 text-blue-500"></i>
<span>&lt;100ms Response</span>
</div>
<div class="flex items-center">
<i data-feather="shield" class="w-4 h-4 mr-2 text-purple-500"></i>
<span>HTTPS Only</span>
</div>
</div>
</div>
`;
// Add copy functionality
const copyBtn = this.shadowRoot.querySelector('.copy-btn');
if (copyBtn) {
copyBtn.addEventListener('click', async () => {
const textToCopy = copyBtn.getAttribute('data-copy');
try {
await navigator.clipboard.writeText(textToCopy);
const originalHTML = copyBtn.innerHTML;
copyBtn.innerHTML = '<i data-feather="check" class="w-4 h-4 mr-1"></i>Copied!';
feather.replace();
setTimeout(() => {
copyBtn.innerHTML = originalHTML;
feather.replace();
}, 2000);
} catch (err) {
console.error('Failed to copy:', err);
}
});
}
// Initialize icons in shadow DOM
setTimeout(() => {
feather.replace();
}, 100);
}
}
customElements.define('custom-api-showcase', CustomApiShowcase);