| class FileUploader extends HTMLElement { |
| connectedCallback() { |
| this.attachShadow({ mode: 'open' }); |
| this.shadowRoot.innerHTML = ` |
| <style> |
| .upload-container { |
| margin: 1rem 0; |
| border: 2px dashed #ccc; |
| border-radius: 0.5rem; |
| padding: 1.5rem; |
| text-align: center; |
| transition: all 0.3s; |
| } |
| .upload-container:hover { |
| border-color: #667eea; |
| background: #f7fafc; |
| } |
| .file-input { |
| display: none; |
| } |
| .upload-btn { |
| background: #667eea; |
| color: white; |
| padding: 0.5rem 1rem; |
| border-radius: 0.25rem; |
| cursor: pointer; |
| display: inline-block; |
| margin-bottom: 1rem; |
| } |
| .file-list { |
| text-align: left; |
| margin-top: 1rem; |
| } |
| .file-item { |
| display: flex; |
| align-items: center; |
| padding: 0.5rem; |
| border-bottom: 1px solid #eee; |
| } |
| .file-name { |
| flex-grow: 1; |
| margin-left: 0.5rem; |
| } |
| .remove-btn { |
| color: #f56565; |
| cursor: pointer; |
| margin-left: 0.5rem; |
| } |
| </style> |
| <div class="upload-container"> |
| <input type="file" class="file-input" multiple accept=".js,.ts,.sql,.json,.txt,.md,.html,.css"> |
| <button class="upload-btn">Choose Files</button> |
| <div class="file-list"></div> |
| <p>Supported files: JavaScript, TypeScript, SQL, JSON, etc.</p> |
| </div> |
| `; |
|
|
| const input = this.shadowRoot.querySelector('.file-input'); |
| const button = this.shadowRoot.querySelector('.upload-btn'); |
| const fileList = this.shadowRoot.querySelector('.file-list'); |
| const files = []; |
|
|
| button.addEventListener('click', () => input.click()); |
| |
| input.addEventListener('change', (e) => { |
| files.length = 0; |
| fileList.innerHTML = ''; |
| |
| Array.from(e.target.files).forEach(file => { |
| files.push(file); |
| |
| const fileItem = document.createElement('div'); |
| fileItem.className = 'file-item'; |
| fileItem.innerHTML = ` |
| <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"> |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /> |
| </svg> |
| <span class="file-name">${file.name} (${(file.size / 1024).toFixed(2)} KB)</span> |
| <span class="remove-btn">×</span> |
| `; |
| |
| fileItem.querySelector('.remove-btn').addEventListener('click', () => { |
| const index = files.indexOf(file); |
| if (index > -1) { |
| files.splice(index, 1); |
| } |
| fileItem.remove(); |
| }); |
| |
| fileList.appendChild(fileItem); |
| }); |
| }); |
|
|
| |
| this.getFiles = () => files; |
| } |
| } |
|
|
| customElements.define('file-uploader', FileUploader); |