import { HtmlElement } from "./HtmlElement";
import { VDOM } from "../ui/Widget";
import { createComponentFactory, isComponentFactory } from "../util/Component";
import { createFunctionalComponent } from "../ui/createFunctionalComponent";
import { isString } from "../util/isString";
import { isNumber } from "../util/isNumber";
import { isFunction } from "../util/isFunction";
import { isUndefined } from "../util/isUndefined";
import { isArray } from "../util/isArray";
import { flattenProps } from "../ui/flattenProps";
let htmlFactoryCache: Record = {};
function getHtmlElementFactory(tagName: string): any {
let factory = htmlFactoryCache[tagName];
if (factory) return factory;
return (htmlFactoryCache[tagName] = createComponentFactory(
() => {},
(config: any) => HtmlElement.create(HtmlElement, { tag: tagName }, flattenProps(config)),
{ tag: tagName },
));
}
export function cx(typeName: any, props?: any, ...children: any[]): any {
if (isArray(typeName)) return typeName;
if (isFunction(typeName) && isUndefined(props))
return createFunctionalComponent((config: any) => typeName(flattenProps(config)));
if (typeName.type || typeName.$type) return typeName;
if (children && children.length == 0) children = [];
if (children && children.length == 1) children = children[0];
if (typeName == "cx") return children;
if (typeName == "react") return react(children);
if (isString(typeName) && typeName[0] == typeName[0].toLowerCase()) typeName = getHtmlElementFactory(typeName);
return {
$type: typeName,
$props: props,
jsxAttributes: props && Object.keys(props),
children,
};
}
export function react(config: any): any {
if (!config || isString(config) || isNumber(config) || VDOM.isValidElement(config)) return config;
if (isArray(config)) return config.map(react);
let type = config.$type;
if (isComponentFactory(type) && type.$meta && type.$meta.tag) type = type.$meta.tag;
if (isArray(config.children)) return VDOM.createElement(type, config.$props, ...config.children.map(react));
return VDOM.createElement(type, config.$props, react(config.children));
}