UNPKG

frontend-hamroun

Version:

A lightweight frontend JavaScript framework with React-like syntax

85 lines (84 loc) 2.82 kB
import { createElement } from './jsx-runtime.js'; export class Component { constructor(props = {}) { this.state = {}; this.element = null; this._mounted = false; this.props = props; } componentDidMount() { // Hook for after component is mounted } async setState(newState) { const prevState = { ...this.state }; this.state = { ...prevState, ...newState }; console.log(`${this.constructor.name} state updated:`, { prev: prevState, next: this.state }); await Promise.resolve(); // Ensure state is updated before re-render if (this._mounted) { await this.update(); } else { await this.update(); } } _replayEvents(oldElement, newElement) { const oldEvents = oldElement.__events || {}; Object.entries(oldEvents).forEach(([event, handler]) => { newElement.addEventListener(event, handler); }); newElement.__events = oldEvents; } _deepCloneWithEvents(node) { const clone = node.cloneNode(false); // Copy events from original element const events = node.__events || {}; clone.__events = events; Object.entries(events).forEach(([event, handler]) => { clone.addEventListener(event, handler); }); // Clone children Array.from(node.childNodes).forEach(child => { if (child instanceof HTMLElement) { clone.appendChild(this._deepCloneWithEvents(child)); } else { clone.appendChild(child.cloneNode(true)); } }); return clone; } async update() { const vdom = this.render(); if (!vdom) return document.createTextNode(''); const rendered = await createElement(vdom); if (rendered instanceof HTMLElement) { return this._updateElement(rendered); } const wrapper = document.createElement('div'); wrapper.appendChild(rendered); return this._updateElement(wrapper); } async _updateElement(rendered) { const newElement = this._deepCloneWithEvents(rendered); newElement.__instance = this; if (!this.element) { this.element = newElement; if (!this._mounted) { this._mounted = true; queueMicrotask(() => this.componentDidMount()); } } else if (this.element.parentNode) { this.element.parentNode.replaceChild(newElement, this.element); this.element = newElement; } return this.element; } render() { throw new Error('Component must implement render() method'); } }