|
|
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><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> |
|
|
`; |
|
|
|
|
|
|
|
|
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); |
|
|
} |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
feather.replace(); |
|
|
}, 100); |
|
|
} |
|
|
} |
|
|
|
|
|
customElements.define('custom-api-showcase', CustomApiShowcase); |