lit-builder
v0.1.1
Published
A builder API for programmatically constructing Lit templates using object notation
Maintainers
Readme
Lit-Builder
A builder API for programmatically constructing Lit templates using object notation.
✨ Key Features:
- Type-safe template construction - Build Lit templates with full TypeScript support
- Declarative API - Define DOM structures using simple JavaScript objects
- Full Lit integration - Supports attributes, properties, events, and directives
- Flexible composition - Mix BuildElements, TemplateResults, and strings seamlessly
Installation
npm install lit-builderUsage
build
Builds a Lit TemplateResult from one or more BuildElement objects.
build(elements: BuildElement | BuildElement[]): TemplateResultBasic Example
import { build } from 'lit-builder';
import { html, LitElement } from 'lit';
class MyElement extends LitElement {
render() {
return html`
<div>
${build({
name: 'button',
attributes: { class: 'primary' },
children: ['Click me!']
})}
</div>
`;
}
}BuildElement
An object representing a DOM element with the following properties:
interface BuildElement {
name?: string; // Tag name (e.g., 'div', 'button')
attributes?: Record<string, string>; // HTML attributes
properties?: Record<string, unknown>; // DOM properties
events?: Record<string, (e: Event) => void>; // Event handlers
directives?: DirectiveResult[]; // Lit directives (e.g., ref)
children?: (BuildElement | TemplateResult | string)[]; // Child content
}Single Element
build({
name: 'div',
children: ['Hello, World!']
})Element Array
build([
{ name: 'p', children: ['First paragraph'] },
{ name: 'p', children: ['Second paragraph'] }
])Attributes
build({
name: 'a',
attributes: {
href: 'https://lit.dev',
target: '_blank'
},
children: ['Visit Lit']
})Properties
build({
name: 'input',
attributes: { type: 'text' },
properties: {
value: 'Default value'
}
})Events
build({
name: 'button',
events: {
click: () => console.log('Clicked!')
},
children: ['Click me']
})Directives
import { createRef, ref } from 'lit/directives/ref.js';
const inputRef = createRef();
build({
name: 'input',
directives: [ref(inputRef)]
})Nested Elements
build({
name: 'ul',
children: [
{
name: 'li',
children: ['Item 1']
},
{
name: 'li',
children: [
'Item 2 with ',
{ name: 'strong', children: ['bold text'] }
]
}
]
})Fragments (Elements without name)
build({
children: [
{ name: 'span', children: ['First'] },
' - ',
{ name: 'span', children: ['Second'] }
]
})Mixed Content
import { html } from 'lit';
import { classMap } from 'lit/directives/class-map.js';
build({
name: 'div',
children: [
'Plain text',
{ name: 'strong', children: ['Bold text'] },
html`<span class=${classMap({ active: true })}>With directive</span>`
]
})Dynamic Lists
const items = ['Apple', 'Banana', 'Cherry'];
build(
items.map(item => ({
name: 'li',
children: [item]
}))
)Conditional Rendering
const isLoggedIn = true;
build([
{ name: 'h1', children: ['Welcome'] },
...(isLoggedIn ? [{
name: 'button',
children: ['Logout']
}] : [{
name: 'button',
children: ['Login']
}])
])Programmatic Component Generation
function createCard(title: string, content: string) {
return build({
name: 'div',
attributes: { class: 'card' },
children: [
{ name: 'h3', children: [title] },
{ name: 'p', children: [content] }
]
});
}Rendering from JSON
// Parse JSON string and render
const jsonTemplate = '[{"name": "div", "children": ["Hello from JSON"]}]';
const elements = JSON.parse(jsonTemplate);
build(elements);Note: JSON only supports serializable values:
- ✅
name,attributes,children - ⚠️
properties(plain objects/arrays only, no functions or special objects) - ❌
events,directives
Limitations
Directive values: Directives like live() cannot be used as property/attribute values due to Lit's template literal design. Use the directives field for element-level directives like ref().
Static template optimization: Dynamic template construction doesn't benefit from Lit's static template caching.
License
MIT
