1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-12-17 04:01:51 +00:00
tobspr_shapez.io/src/js/jsx-runtime.ts
Даниїл Григор'єв 78b9ab49f1
Allow Node in JSX runtime
The typings are not consistent, but they seem to work. I'll leave the
rest as-is and just hope that someone fixes them later.
2024-07-20 13:35:11 +03:00

42 lines
1.5 KiB
TypeScript

function isDisplayed(node: JSX.JSXNode): node is Exclude<JSX.JSXNode, boolean | null | undefined> {
return typeof node !== "boolean" && node != null;
}
/**
* JSX factory.
*/
function jsx<T extends keyof JSX.IntrinsicElements>(tag: T, props: JSX.IntrinsicElements[T]): HTMLElement;
function jsx<U extends JSX.Props>(tag: JSX.Component<U>, props: U): Element;
function jsx<U extends JSX.Props>(
tag: keyof JSX.IntrinsicElements | JSX.Component<U>,
props: U
): JSX.Element {
if (typeof tag === "function") return tag(props);
const { children, ...attrs } = props as JSX.IntrinsicElements[keyof JSX.IntrinsicElements];
const element = document.createElement(tag);
Object.entries(attrs).forEach(([key, value]) => {
switch (typeof value) {
case "boolean":
if (!value) return;
return element.setAttribute(key, "");
case "number":
case "string":
return element.setAttribute(key, `${value}`);
}
throw new TypeError("JSX element attribute assigned invalid type");
});
element.append(...([children].flat(Infinity) as JSX.JSXNode[]).filter(isDisplayed));
return element;
}
// functional component, called indirectly as `jsx(Fragment, props)`
/**
* Groups elements without introducing a parent element.
*/
const Fragment = (props: JSX.Props) => props.children as JSX.Element;
// jsxs is used when there are multiple children
export { Fragment, jsx, jsx as jsxs };