class FileTree extends HTMLElement { constructor() { super(); this.fileStructure = {}; this.selectedFiles = []; } connectedCallback() { this.render(); } static get observedAttributes() { return ['file-structure']; } attributeChangedCallback(name, oldValue, newValue) { if (name === 'file-structure') { this.fileStructure = JSON.parse(newValue); this.render(); } } set fileStructure(value) { this._fileStructure = value; this.render(); } get fileStructure() { return this._fileStructure; } render() { this.innerHTML = ''; const container = document.createElement('div'); container.className = 'file-tree'; this.appendChild(container); if (this.fileStructure) { this.renderDirectory(this.fileStructure, container, ''); } } renderDirectory(structure, container, path) { Object.keys(structure).sort().forEach(key => { const item = structure[key]; const fullPath = path ? `${path}/${item.name}` : item.name; const itemElement = document.createElement('div'); itemElement.className = 'file-tree-item'; itemElement.dataset.path = fullPath; if (item.type === 'directory') { itemElement.classList.add('folder'); itemElement.innerHTML = `
${item.name} `; container.appendChild(itemElement); const childrenContainer = document.createElement('div'); childrenContainer.className = 'file-tree-children'; container.appendChild(childrenContainer); this.renderDirectory(item.children, childrenContainer, fullPath); } else { itemElement.classList.add('file'); itemElement.innerHTML = `
${item.name} `; container.appendChild(itemElement); // Add to selected files list this.selectedFiles.push({ path: fullPath, selected: item.selected }); } // Add event listener for checkbox const checkbox = itemElement.querySelector('input[type="checkbox"]'); checkbox.addEventListener('change', (e) => { this.updateSelection(fullPath, e.target.checked, item.type === 'directory'); this.dispatchSelectionEvent(); }); }); feather.replace(); } updateSelection(path, selected, isDirectory) { // Update the selected files list this.selectedFiles = this.selectedFiles.map(file => { if (file.path.startsWith(path)) { return { ...file, selected }; } return file; }); } dispatchSelectionEvent() { const event = new CustomEvent('selection-change', { detail: this.selectedFiles }); this.dispatchEvent(event); } } customElements.define('file-tree', FileTree);