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 = `
`;
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);