`;
// Tab Logic
const tabs = this.shadowRoot.querySelectorAll('.tab-btn');
const panels = this.shadowRoot.querySelectorAll('.panel-content');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
tabs.forEach(t => t.classList.remove('active'));
panels.forEach(p => p.classList.remove('active'));
tab.classList.add('active');
this.shadowRoot.getElementById(`panel-${tab.dataset.tab}`).classList.add('active');
// Resize Monaco if code tab is active
if(tab.dataset.tab === "1" && window.monacoEditor) {
window.monacoEditor.layout();
}
});
});
// File Upload Logic (Mock)
const dropZone = this.shadowRoot.getElementById('drop-zone');
const fileInput = this.shadowRoot.getElementById('file-input');
const fileList = this.shadowRoot.getElementById('file-list');
const handleFiles = (files) => {
Array.from(files).forEach(file => {
const item = document.createElement('div');
item.className = 'file-item';
item.innerHTML = `
${file.name}
`;
fileList.prepend(item);
feather.replace();
});
};
dropZone.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', (e) => handleFiles(e.target.files));
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
dropZone.style.borderColor = '#6366f1';
});
dropZone.addEventListener('dragleave', () => {
dropZone.style.borderColor = '#334155';
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
dropZone.style.borderColor = '#334155';
handleFiles(e.dataTransfer.files);
});
// Monaco Editor Loader
this.loadMonaco();
// Listen for Switch Tab Event (from Script.js when code is generated)
window.appEvents.addEventListener('switch-tab', (e) => {
const index = e.detail.index;
tabs[index].click();
});
// Listen for Code Update
window.appEvents.addEventListener('update-code', (e) => {
if(window.monacoEditor) {
window.monacoEditor.setValue(e.detail.code);
}
});
feather.replace();
}
loadMonaco() {
if (document.getElementById('monaco-script')) return; // Already loaded
const script = document.createElement('script');
script.id = 'monaco-script';
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.44.0/min/vs/loader.min.js';
script.onload = () => {
require.config({ paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.44.0/min/vs' } });
require(['vs/editor/editor.main'], function() {
// Delay slightly to ensure container is rendered and has dimensions
setTimeout(() => {
if(document.getElementById('monaco-container')) {
// Access shadow root container
const container = this.shadowRoot.getElementById('monaco-container');
// Actually, the require callback scope 'this' might be lost, but standard monaco usage usually targets global or ID
// We need to be careful with Shadow DOM and Monaco.
// Monaco appends to the body by default for overlays, but we want it inside our component.
// Simplest way for this demo: Target by ID inside ShadowDOM
// Because Monaco is a bit complex with ShadowDOM encapsulation (styles/events),
// we might need to use global or trick it.
// For this demo, let's attach to the specific ID if possible, or use window.monacoEditor for control.
// Note: Monaco doesn't fully support ShadowDOM out of the box easily without configuration tweaks.
// We will try to render it. If it fails, it might be due to the shadow root encapsulation blocking some global styles/events needed by Monaco's widget logic.
// To make it robust, we often put the monaco container *outside* or pass specific options.
// Let's try standard initialization on the element found in the shadowRoot of the custom element.
const host = document.querySelector('custom-tools-panel').shadowRoot.getElementById('monaco-container');
window.monacoEditor = monaco.editor.create(host, {
value: '# AI-generated code will appear here\n# Start coding your vibe...',
language: 'python',
theme: 'vs-dark',
automaticLayout: true,
minimap: { enabled: false }
});
}
}, 500);
}.bind(this));
};
document.head.appendChild(script);
}
}
customElements.define('custom-tools-panel', CustomToolsPanel);