@warmjs/core
v1.0.0
Published
Zero-dependency JSX runtime for WarmJS — converts JSX to real DOM nodes, no virtual DOM.
Maintainers
Readme
@warmjs/core
Zero-dependency JSX runtime for WarmJS. It converts JSX directly into real DOM nodes — no virtual DOM, no diffing, no framework reactivity.
This package is restored from the original Pixorig custom UI shell (src/ui/jsx.ts). It is intentionally tiny (~90 lines) so it can be audited, vendored, and kept politically neutral.
Inspired by the SolidJS philosophy (JSX → direct DOM), but without a compiler or signals. Reactivity, if needed, lives in a separate layer.
Install
npm install @warmjs/coreRequires a DOM environment (browser). No runtime dependencies.
TypeScript setup
{
"compilerOptions": {
"jsx": "react",
"jsxFactory": "h",
"jsxFragmentFactory": "Fragment"
}
}/** @jsx h */
/** @jsxFrag Fragment */
import { h, Fragment } from "@warmjs/core";Usage
/** @jsx h */
import { h } from "@warmjs/core";
function PanelHeader({ title, onBack }: { title: string; onBack: () => void }) {
return (
<div class="panel-header">
<button onClick={onBack}>Back</button>
<span>{title}</span>
</div>
);
}
const node = <PanelHeader title="Opacity" onBack={() => history.back()} />;
document.getElementById("sub-sidebar")!.appendChild(node);Fragments:
/** @jsx h */
/** @jsxFrag Fragment */
import { h, Fragment } from "@warmjs/core";
const list = (
<>
<span>Monochrome</span>
<span>Gradient</span>
</>
);API
h(tag, props, ...children): Node
tag: string | ComponentFunction | typeof Fragment- HTML tag (
div,button,input, …) →document.createElement - SVG tag (
svg,path,circle,rect, …) →document.createElementNS - Function component → called as
tag({ ...props, children }) Fragment→DocumentFragment
- HTML tag (
- Props:
onXxx={fn}→addEventListener(xxx.toLowerCase(), fn)class/className→ class assignment (SVG viasetAttribute)style={object}→Object.assign(el.style, value)style="..."→setAttribute("style", ...)boolean true→ present attribute,false/null/undefined→ skippedinnerHTML={string}→ direct assignment- everything else →
setAttribute(key, String(value)) childrenprop is ignored (children come from arguments)
Fragment({ children }): DocumentFragment
Groups children without a wrapper element.
ComponentFunction<P>
type ComponentFunction<P> = (props: P, ...children: Node[]) => Node;Note:
h()currently invokes components astag({ ...props, children }). Keep components to the single-propsform for forward compatibility.
What it is NOT
- No hooks (
useState,useEffect). - No signals / fine-grained reactivity (unlike SolidJS).
- No re-render. Updates are imperative: re-call
h()or patch the DOM manually. - No keyed list diffing, no scheduler, no SSR.
If you need auto-updates, add a minimal signal layer on top (planned as @warmjs/signals) instead of bloating this runtime.
Limitations (known)
SVG_TAGScovers common tags only. Extend it if you usetext,tspan,ellipse,linearGradient,stop, etc.- No
ref/keyhandling. - No numeric
style→pxconversion. JSX.Elementis typed asHTMLElementfor simplicity.
License
MIT — free for commercial and personal use. WarmJS stays neutral and dependency-free by design.
