Use familiar JSX syntax with DOM++ by providing a tiny custom factory function. This example runs entirely in the browser using Babel Standalone (no build step).
/** @jsx d */ pragma tells Babel to transform
<div> into d("div", props, ...children).
d factory creates real DOM nodes and forwards
special props (style, className, on)
to the corresponding DOM++ setters.
This is the exact source that gets transformed by Babel and executed. The pragma, factory, and all four demo patterns are shown below.
/** @jsx d */
const app =
document.getElementById("app");
// JSX factory: d(tag, props, ...children)
function d(tag, props, ...children) {
const node = document.createElement(tag);
if (props) {
const { style, className, class: classAttr, on, ...attrs } = props;
if (className || classAttr) {
node.setAttributes({ class: className || classAttr });
}
if (style) {
node.setStyles(style);
}
if (on) {
node.setEvents(on);
}
if (Object.keys(attrs).length) {
node.setAttributes(attrs);
}
}
if (children.length) {
node.setChildren(...children.flat());
}
return node;
}
function card(title, description, content) {
return (
<section className="card">
<h2>{title}</h2>
<small>{description}</small>
{content}
</section>
);
}
function demoBasicUsage() {
return card(
"Basic Usage",
"DOM++ extends real DOM nodes with chainable helpers.",
(
<div>
<h3>Hello DOM++</h3>
<p>This is a DOM++ element created via JSX.</p>
</div>
)
);
}
function demoStatefulPanel() {
const panel = <section className="panel" />;
panel
.setState({ total: 0 })
.setChildren(({ state, setState }) => [
<h3>{`Total: ${state.total}`}</h3>,
<button on={{ click: () => setState(({ state }) => { state.total += 10000; }) }}>
Donate 10k
</button>
]);
return card(
"Stateful Panel",
"State lives on the element; setChildren re-runs when state changes.",
panel
);
}
function demoCrossElement() {
const summary = <div />;
summary
.setState({ total: 0 })
.setChildren(({ state }) => [
<strong>{`Total: ${state.total}`}</strong>
]);
return card(
"Cross-Element Updates",
"Buttons update another element's state via its setState method.",
(
<div>
{summary}
<div className="actions">
<button on={{ click: () => {
summary.setState(({ state }) => { state.total += 10000; });
} }}>Donate 10k</button>
<button className="secondary" on={{ click: () => {
summary.setState(({ state }) => { state.total += 25000; });
} }}>Donate 25k</button>
</div>
</div>
)
);
}
function demoFineGrained() {
const [count, setCount] =
document.createSignal(0);
const display =
<strong className="signal-count" />;
display
.setFineGrained()
.setText(() => `Signal: ${count()}`);
return card(
"Fine-Grained Signals",
"JSX node + setFineGrained + signal-driven setText (no setState).",
(
<div>
{display}
<div className="actions">
<button on={{ click: () => setCount( count() + 1 ) }}>+1</button>
<button className="secondary" on={{ click: () => setCount(0) }}>Reset</button>
</div>
</div>
)
);
}
app.setChildren(
demoBasicUsage(),
demoStatefulPanel(),
demoCrossElement(),
demoFineGrained()
);