codecanvas-pro / components /code-snippet.js
Gravatar123A's picture
copy this website exactly
b2d9c8d verified
Raw
History Blame Contribute Delete
5.64 kB
class CustomCodeSnippet extends HTMLElement {
constructor() {
super();
this._title = this.getAttribute('title') || 'Code Snippet';
this._language = this.getAttribute('language') || 'javascript';
this._code = this.innerHTML.trim();
}
static get observedAttributes() {
return ['title', 'language', 'code'];
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
this[`_${name}`] = newValue;
this.render();
}
}
connectedCallback() {
this.render();
}
render() {
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
margin-bottom: 1.5rem;
}
.snippet-container {
border-radius: 0.75rem;
overflow: hidden;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
.dark .snippet-container {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.25);
}
.snippet-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.75rem 1rem;
background-color: #f1f5f9;
border-bottom: 1px solid #e2e8f0;
}
.dark .snippet-header {
background-color: #1e293b;
border-bottom-color: #334155;
}
.snippet-title {
font-weight: 600;
color: #334155;
font-size: 0.875rem;
}
.dark .snippet-title {
color: #e2e8f0;
}
.snippet-actions {
display: flex;
gap: 0.5rem;
}
.snippet-btn {
display: flex;
align-items: center;
justify-content: center;
width: 1.75rem;
height: 1.75rem;
border-radius: 0.375rem;
color: #64748b;
background-color: transparent;
border: none;
cursor: pointer;
transition: all 0.2s;
}
.snippet-btn:hover {
background-color: #e2e8f0;
color: #475569;
}
.dark .snippet-btn:hover {
background-color: #334155;
color: #94a3b8;
}
.snippet-btn-icon {
width: 1rem;
height: 1rem;
}
.snippet-content {
position: relative;
background-color: #f8fafc;
font-family: 'Fira Code', monospace;
font-size: 0.875rem;
line-height: 1.5;
color: #334155;
padding: 1.25rem;
overflow-x: auto;
}
.dark .snippet-content {
background-color: #0f172a;
color: #e2e8f0;
}
.language-tag {
position: absolute;
top: 0;
right: 1rem;
transform: translateY(-50%);
background-color: #3b82f6;
color: white;
font-size: 0.75rem;
font-weight: 500;
padding: 0.25rem 0.75rem;
border-radius: 9999px;
}
.code-block {
margin: 0;
white-space: pre;
tab-size: 2;
}
/* Syntax highlighting */
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #64748b;
}
.token.punctuation {
color: #94a3b8;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #2563eb;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #059669;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #f59e0b;
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #7c3aed;
}
.token.function,
.token.class-name {
color: #3b82f6;
}
.token.regex,
.token.important,
.token.variable {
color: #f97316;
}
</style>
<div class="snippet-container">
<div class="snippet-header">
<span class="snippet-title">${this._title}</span>
<div class="snippet-actions">
<button class="snippet-btn" data-copy-btn title="Copy code">
<i data-feather="copy" class="snippet-btn-icon"></i>
</button>
<button class="snippet-btn" title="Expand code">
<i data-feather="maximize" class="snippet-btn-icon"></i>
</button>
</div>
</div>
<div class="snippet-content">
<span class="language-tag">${this._language}</span>
<pre class="code-block"><code>${this._code}</code></pre>
</div>
</div>
`;
// Initialize feather icons within the shadow DOM
const featherScript = document.createElement('script');
featherScript.src = 'https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js';
this.shadowRoot.appendChild(featherScript);
featherScript.onload = () => {
if (window.feather) {
window.feather.replace({ class: 'snippet-btn-icon' });
}
};
}
}
customElements.define('custom-code-snippet', CustomCodeSnippet);