jsx-dom-runtime
A tiny in 500 bytes library to JSX syntax templates for DOM.
Install
npm i jsx-dom-runtime
yarn add jsx-dom-runtime
How to use
Add preset to your .babelrc
file.
.babelrc
{
"presets": [
"jsx-dom-runtime/babel-preset"
]
}
Example
import { useRef } from 'jsx-dom-runtime';
const App = () => {
const ref = useRef();
const addItem = () => {
ref.current.prepend(<li>New Item</li>);
};
return (
<>
<button type="button" onclick={addItem}>
Add Item
</button>
<ul ref={ref} />
</>
);
};
document.head.append(
<link rel="stylesheet" href="/style.css" />
);
document.body.append(<App />);
Demo
Syntax
Creating Refs
Adding a reference to a DOM Element
import { useRef } from 'jsx-dom-runtime';
let i = 0;
const ref = useRef();
const click = () => {
ref.current.textContent = ++i;
};
document.body.append(
<>
<p ref={ref}>0</p>
<button type="button" onclick={click}>
+ 1
</button>
</>
);
Callback Refs
const focus = (node) => {
node.addEventListener('focusin', () => {
node.style.backgroundColor = 'pink';
});
node.addEventListener('focusout', () => {
node.style.backgroundColor = '';
});
};
document.body.append(
<input type="text" ref={focus} />
);
Text
import { useText } from 'jsx-dom-runtime';
const [text, setText] = useText('The initial text');
document.body.append(
<>
<p>{text}</p>
<button type="button" onclick={() => setText('Clicked!')}>
Click me
</button>
</>
);
Template
Get template from string.
import { Template } from 'jsx-dom-runtime';
document.body.append(
<Template>
{`<svg width="24" height="24" aria-hidden="true">
<path d="M12 12V6h-1v6H5v1h6v6h1v-6h6v-1z"/>
</svg>`}
</Template>
);
Extend
Add custom attributes in JSX.Element
.
import { Extend } from 'jsx-dom-runtime';
Extend({
'x-class': (node, value) => {
node.setAttribute('class', value.filter(Boolean).join(' '));
},
'x-dataset': (node, value) => {
for (let key in value) {
node.dataset[key] = value[key];
}
},
'x-autofocus': (node, value) => {
setTimeout(() => node.focus(), value);
},
});
document.body.append(
<input
x-class={['one', 'two']}
x-dataset={{ testid: 'test', hook: 'text' }}
x-autofocus={1000}
/>
);
TypeScript types definition for custom attributes and properties
global.d.ts
declare global {
namespace JSX {
interface Attributes {
'x-class'?: string[];
'x-dataset'?: Record<string, string>;
'x-autofocus'?: number;
}
}
}
export {};
Result
<input class="one two" data-testid="test" data-hook="text">
properties
Add support of the DOM Element object properties. By default supported innerHTML
and value
.
import { properties } from 'jsx-dom-runtime';
properties.add('textContent');
properties.add('volume');
properties.add('muted');
document.body.append(
<>
<span textContent="Hello, world!" />
<audio
src="https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"
controls
volume={0.9}
muted
/>
</>
);
TypeScript types definition for custom attributes and properties
global.d.ts
declare global {
namespace JSX {
interface Attributes {
textContent?: string;
muted?: boolean;
volume?: number;
}
}
}
export {};
TypeScript Support
TypeScript is able used only for type checking. The library doesn't support compilation with TypeScript. Use @babel/preset-typescript
.babelrc
{
"presets": [
"@babel/typescript",
"jsx-dom-runtime/babel-preset"
]
}
To provide type checking add tsconfig.json
file to your project:
tsconfig.json
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "jsx-dom-runtime",
"moduleResolution": "node",
"noEmit": true,
"lib": [
"DOM"
]
}
}
Example:
src/index.tsx
import type { FC } from 'jsx-dom-runtime';
interface Props {
text: string;
}
const App: FC<Props> = ({ text }) => {
return (
<div class="card">
<div class="text">{text}</div>
</div>
);
};
document.body.append(<App text="Hello!" />);
Read more: TypeScript JSX
License
MIT