import type { PropsBase, PropStates, StatesBase } from "../types.js"; import { State, type ValuesOfStateArray } from "./State.js"; export abstract class ComponentBase { static propsToPropStates(props: Props | PropStates) { const propsState: Record> = {}; Object.entries(props).forEach(([key, value]) => { if (value instanceof State) { propsState[key] = value; } else { propsState[key] = new State(value); } }); return propsState as PropStates; } states: PropStates = {} as PropStates; propStates: PropStates; children: ComponentBase[] = []; mounted: boolean = false; subscriberSymbols: { state: State, symbol: Symbol }[] = []; abstract node: Node; constructor(props: PropStates | Props) { this.propStates = ComponentBase.propsToPropStates(props); this.init(); } init(): void { } protected abstract createNode(): Node; abstract mount(target: Node): any; abstract destroy(): any; onMount(): void { }; onDestoy(): void { }; effect[]>(callback: (...values: ValuesOfStateArray) => void, states: T) { states.forEach((state) => { const symbol = state.subscribe(() => callback(...states.map(({ value }) => value) as ValuesOfStateArray)); this.subscriberSymbols.push({ state, symbol }); }) } derived[], U>(callback: (...values: ValuesOfStateArray) => U, states: T): State { const derivedState = new State(undefined as U); states.forEach((state) => { const symbol = state.subscribe(() => { const derivedValue = callback(...states.map(({ value }) => value) as ValuesOfStateArray); derivedState.set(derivedValue); }); this.subscriberSymbols.push({ state, symbol }); }); return derivedState; } update( key: T, value: T extends keyof Props ? Props[T] extends State ? U : Props[T] : U ) { let propState: State = this.propStates[key]; if (!propState) { propState = new State(value); this.propStates[key] = propState; } propState.set(value); } }