import { createElement, VNode } from "preact"; export type StateFunc = (p: S) => VNode; export type StateViewMap = { [S in StateType as S["status"]]: StateFunc; }; export type RecursiveState = S | (() => RecursiveState); export function compose( hook: (p: PType) => RecursiveState, viewMap: StateViewMap, ): (p: PType) => VNode { function withHook(stateHook: () => RecursiveState): () => VNode { function ComposedComponent(): VNode { const state = stateHook(); if (typeof state === "function") { const subComponent = withHook(state); return createElement(subComponent, {}); } const statusName = state.status as unknown as SType["status"]; const viewComponent = viewMap[statusName] as unknown as StateFunc; return createElement(viewComponent, state); } return ComposedComponent; } return (p: PType) => { const h = withHook(() => hook(p)); return h(); }; } export function recursive( hook: (p: PType) => RecursiveState, ): (p: PType) => VNode { function withHook(stateHook: () => RecursiveState): () => VNode { function ComposedComponent(): VNode { const state = stateHook(); if (typeof state === "function") { const subComponent = withHook(state); return createElement(subComponent, {}); } return state; } return ComposedComponent; } return (p: PType) => { const h = withHook(() => hook(p)); return h(); }; } /** * * @param obj VNode * @returns */ export function saveVNodeForInspection(obj: T): T { // @ts-ignore window["showVNodeInfo"] = function showVNodeInfo() { inspect(obj); }; return obj; } function inspect(obj: any) { if (!obj) return; if (obj.__c && obj.__c.__H) { const componentName = obj.__c.constructor.name; const hookState = obj.__c.__H; const stateList = hookState.__ as Array; console.log("==============", componentName); stateList.forEach((hook) => { const { __: value, c: context, __h: factory, __H: args } = hook; if (typeof context !== "undefined") { const { __c: contextId } = context; console.log("context:", contextId, hook); } else if (typeof factory === "function") { console.log("memo:", value, "deps:", args); } else if (typeof value === "function") { const effectName = value.name; console.log("effect:", effectName, "deps:", args); } else if (typeof value.current !== "undefined") { const ref = value.current; console.log("ref:", ref instanceof Element ? ref.outerHTML : ref); } else if (value instanceof Array) { console.log("state:", value[0]); } else { console.log(hook); } }); } const children = obj.__k; if (children instanceof Array) { children.forEach((e) => inspect(e)); } else { inspect(children); } }