This commit is contained in:
Benjamin Palko 2025-04-10 13:14:59 -04:00
parent ac35d7e35b
commit 7639585a91
13 changed files with 593 additions and 56 deletions

View file

@ -0,0 +1 @@
export * from "./jsx-runtime";

20
lib/jsx/jsx-runtime.ts Normal file
View file

@ -0,0 +1,20 @@
import { renderJSX } from "./render";
import type { JSXChildren, RenderedNode } from "./types";
namespace JSX {
export type Attributes = Record<string, unknown> & JSXChildren;
// Allow any html tag
export type IntrinsicElements = Record<string, Attributes>;
// Declare the shape of JSX rendering result
// This is required so the return types of components can be inferred
export type Element = RenderedNode;
}
// Expose the main namespace
export type { JSX };
// Expose factories
export const jsx = renderJSX;
export const jsxs = renderJSX;
export const jsxDEV = renderJSX;

16
lib/jsx/render.ts Normal file
View file

@ -0,0 +1,16 @@
import type { JSX } from "./jsx-runtime";
import type { FunctionComponent } from "./types";
export function renderJSX<T extends keyof JSX.IntrinsicElements>(
tag: string | FunctionComponent | undefined,
props: JSX.IntrinsicElements[T],
) {
if (typeof tag === "function") {
return tag(props);
}
if (typeof tag === "undefined") {
return {};
}
const { children, ...rest } = props;
return { [tag]: { ...rest } };
}

19
lib/jsx/types.ts Normal file
View file

@ -0,0 +1,19 @@
export type RenderedNode = object;
export type JSXNode =
| RenderedNode
| (() => JSXNode)
| boolean
| number
| bigint
| string
| null
| undefined;
export interface JSXChildren {
children?: JSXNode | JSXNode[] | undefined;
}
export type FunctionComponent = (
props?: Record<string, unknown>,
) => RenderedNode;