class AppWindow extends HTMLElement { connectedCallback() { this.attachShadow({ mode: 'open' }); const title = this.getAttribute('title') || 'Window'; const icon = this.getAttribute('icon') || 'square'; const width = this.getAttribute('width') || '600'; const height = this.getAttribute('height') || '400'; const x = this.getAttribute('x') || '100'; const y = this.getAttribute('y') || '100'; this.shadowRoot.innerHTML = `
${title}
`; this.windowId = this.id; this.isDragging = false; this.isResizing = false; this.initializeEventListeners(); // Re-render feather icons setTimeout(() => feather.replace(), 0); // Focus the window initially setTimeout(() => focusWindow(this.windowId), 100); } initializeEventListeners() { const header = this.shadowRoot.getElementById('window-header'); const resizeHandle = this.shadowRoot.getElementById('resize-handle'); const minimizeBtn = this.shadowRoot.querySelector('.window-control.minimize'); const maximizeBtn = this.shadowRoot.querySelector('.window-control.maximize'); const closeBtn = this.shadowRoot.querySelector('.window-control.close'); // Window dragging header.addEventListener('mousedown', (e) => { if (e.target.closest('.window-controls')) return; this.startDragging(e); }); // Window resizing resizeHandle.addEventListener('mousedown', (e) => { this.startResizing(e); }); // Window controls minimizeBtn.addEventListener('click', () => { minimizeWindow(this.windowId); }); maximizeBtn.addEventListener('click', () => { maximizeWindow(this.windowId); }); closeBtn.addEventListener('click', () => { closeWindow(this.windowId); }); // Focus on click this.addEventListener('mousedown', () => { focusWindow(this.windowId); }); // Global mouse events document.addEventListener('mousemove', (e) => this.handleMouseMove(e)); document.addEventListener('mouseup', () => this.handleMouseUp()); } startDragging(e) { this.isDragging = true; this.dragOffsetX = e.clientX - parseInt(this.style.left); this.dragOffsetY = e.clientY - parseInt(this.style.top); this.style.cursor = 'move'; } startResizing(e) { this.isResizing = true; this.resizeStartX = e.clientX; this.resizeStartY = e.clientY; this.resizeStartWidth = parseInt(this.style.width); this.resizeStartHeight = parseInt(this.style.height); e.stopPropagation(); } handleMouseMove(e) { if (this.isDragging) { const newX = Math.max(0, Math.min(e.clientX - this.dragOffsetX, window.innerWidth - parseInt(this.style.width || this.getAttribute('width')))); const newY = Math.max(0, Math.min(e.clientY - this.dragOffsetY, window.innerHeight - parseInt(this.style.height || this.getAttribute('height')) - 32)); this.style.left = `${newX}px`; this.style.top = `${newY}px`; } else if (this.isResizing) { const deltaX = e.clientX - this.resizeStartX; const deltaY = e.clientY - this.resizeStartY; const newWidth = Math.max(300, this.resizeStartWidth + deltaX); const newHeight = Math.max(200, this.resizeStartHeight + deltaY); this.style.width = `${newWidth}px`; this.style.height = `${newHeight}px`; } } handleMouseUp() { this.isDragging = false; this.isResizing = false; this.style.cursor = ''; } } customElements.define('app-window', AppWindow);