Type-safe document.createElement wrapper with JSX support and optional reactive lib integrations for building DOM elements.
- Type-safe element creation with TypeScript (Usage)
- Support for HTML, SVG, and MathML elements
- Simple attribute and event handling (Attributes)
- JSX Support
- Optional reactive programming with alien-signals, alien-deepsignals, faisceau, @preact/signals-core, and @vue/reactivity (Reactive Support)
pnpm add @lilian1315/create-elementimport { h } from '@lilian1315/create-element'
// Create a simple element
const div = h('div', { class: 'container' }, 'Hello World!')
// With event handlers
const button = h('button', {
onclick: () => console.log('Clicked!')
}, 'Click me')
// Nested elements
const app = h('div', null, [
h('h1', null, 'My App'),
button
])tag: HTML tag name (e.g.,'div','button')attributes: Optional object with element attributeschildren: Child elements or text
// Classes
h('div', { class: 'btn primary' })
h('div', { class: ['btn', 'primary'] })
h('div', { class: { btn: true, primary: true, active: false } })
// Styles
h('div', { style: 'color: red' })
h('div', { style: { color: 'red', fontSize: '16px' } })
// Events
h('button', { onclick: () => console.log('clicked') })
// Data attributes
h('div', {
data: {
testId: 'my-component',
active: true, // data-active=""
hidden: false, // removed
count: null, // removed
empty: undefined // removed
}
})
// InnerHTML (cannot be used with children attribute or property)
h('div', { innerHTML: '<span>content</span>' })// SVG elements
const svg = h('svg', { width: '100', height: '100' })
const circle = h('svg:circle', { cx: '50', cy: '50', r: '20' })
// MathML elements
const math = h('math')
const variable = h('math:mi', null, 'x')Use JSX syntax with TypeScript configuration:
// Regular JSX
function App() {
return (
<div class="container">
<h1>My App</h1>
<button onclick={() => console.log('clicked')}>
Click me
</button>
</div>
)
}For reactive JSX, set jsxImportSource to the adapter you use (e.g. @lilian1315/create-element/alien-signals, @lilian1315/create-element/alien-deepsignals, @lilian1315/create-element/faisceau, @lilian1315/create-element/preact-signals, @lilian1315/create-element/vue-reactivity).
@lilian1315/create-element ships multiple reactive adapters. Import h from the adapter that matches your signal library and install the corresponding dependency. Attributes, styles, datasets, and children will stay in sync automatically.
import { h } from '@lilian1315/create-element/alien-signals'
import { computed, signal } from 'alien-signals'
const count = signal(0)
const label = computed(() => `Count: ${count()}`)
const counter = h('section', { class: 'counter' }, [
h('p', null, label),
h('button', { onclick: () => count(count() + 1) }, 'Increment'),
])Requires: pnpm add alien-signals
import { h } from '@lilian1315/create-element/alien-deepsignals'
import { computed, signal } from 'alien-deepsignals'
const count = signal(0)
const label = computed(() => `Count: ${count.get()}`)
const counter = h('section', null, [
h('p', null, label),
h('button', { onclick: () => count.set(count.get() + 1) }, 'Increment'),
])Requires: pnpm add alien-deepsignals
import { h } from '@lilian1315/create-element/faisceau'
import { computed, signal } from 'faisceau'
const count = signal(0)
const label = computed(() => `Count: ${count.get()}`)
const counter = h('section', null, [
h('p', null, label),
h('button', { onclick: () => count.set(count.get() + 1) }, 'Increment'),
])Requires: pnpm add faisceau
import { h } from '@lilian1315/create-element/preact-signals'
import { computed, signal } from '@preact/signals-core'
const count = signal(0)
const label = computed(() => `Count: ${count.value}`)
const counter = h('section', null, [
h('p', null, label),
h('button', { onclick: () => (count.value = count.value + 1) }, 'Increment'),
])Requires: pnpm add @preact/signals-core
import { h } from '@lilian1315/create-element/vue-reactivity'
import { computed, ref } from '@vue/reactivity'
const count = ref(0)
const label = computed(() => `Count: ${count.value}`)
const counter = h('section', null, [
h('p', null, label),
h('button', { onclick: () => count.value++ }, 'Increment'),
])Requires: pnpm add @vue/reactivity
MIT