libreria-renderizado-npm
Version:
Una librería básica para gestionar el estado y JSX
93 lines (74 loc) • 2.82 kB
text/typescript
type Listener = () => void;
export function createState<T>(initialValue: T) {
let value = initialValue;
const listeners = new Set<Listener>();
function setState(newValue: T): void {
if (newValue !== value) {
value = newValue;
listeners.forEach(listener => listener());
}
}
function getState(): T {
return value;
}
function subscribe(listener: Listener): () => void {
if (typeof listener !== 'function') {
throw new Error('El listener debe ser una función');
}
listeners.add(listener);
// Devuelve una función que permitirá desuscribirse
return () => listeners.delete(listener);
}
return [getState, setState, subscribe] as const;
}
// Función para crear un elemento con JSX
export function jsx(type: string, props: { [key: string]: any }, ...children: any[]): HTMLElement {
if (typeof type !== 'string') {
throw new Error('El tipo del elemento debe ser una cadena');
}
const el = document.createElement(type);
if (props) {
Object.keys(props).forEach((key) => {
if (key.startsWith('on')) {
const event = key.substring(2).toLowerCase();
if (typeof props[key] === 'function') {
el.addEventListener(event, props[key]);
} else {
console.warn(`El manejador del evento ${event} no es una función.`);
}
} else if (key === 'className') {
el.classList.add(props[key]);
} else {
el.setAttribute(key, props[key]);
}
});
}
children.forEach((child) => {
if (typeof child === 'string') {
el.appendChild(document.createTextNode(child));
} else if (child instanceof HTMLElement) {
el.appendChild(child);
}
});
return el;
}
// Función para renderizar un componente en un contenedor
// Función para renderizar un componente en un contenedor
// Función para renderizar un componente en un contenedor
export function render(component: () => { element: HTMLElement, subscribe: (listener: () => void) => () => void }, container: HTMLElement): () => void {
if (!container || !(container instanceof HTMLElement)) {
throw new Error('El contenedor debe ser un elemento DOM válido');
}
function update(): void {
const { element } = component(); // Obtener el componente renderizado
container.innerHTML = ''; // Limpiar el contenedor
container.appendChild(element); // Añadir el componente al contenedor
}
update(); // Primer renderizado
// La función subscribe devuelve una función para desuscribirse
const unsubscribe = component().subscribe(update); // Suscribirse al estado
return () => {
update();
unsubscribe(); // Desuscribirse cuando sea necesario
};
}