Components
component() defines a real custom element and returns a typed factory for composition.
Props are signals
Declare props as a TypeScript interface. Inside setup, every prop is a Signal — read .value or use it in a template. The setup function must be synchronous.
import { component, computed, html } from '@nisli/core';
interface GreetingProps {
name: string;
}
export const Greeting = component<GreetingProps>('x-greeting', (props) => {
const upper = computed(() => props.name.value.toUpperCase());
return html`<p>Hello, ${upper}</p>`;
});
Factory composition
Calling Greeting({ name: 'nisli' }) returns a template you compose into other components. Pass a plain value for static props, or a signal to stay reactive.
Lifecycle
onMount() runs after the element connects; onCleanup() runs on teardown. Effects created in setup are disposed automatically.
import { component, onMount, onCleanup, signal, html } from '@nisli/core';
component('x-clock', () => {
const now = signal(new Date().toLocaleTimeString());
onMount(() => {
const id = setInterval(() => {
now.value = new Date().toLocaleTimeString();
}, 1000);
onCleanup(() => clearInterval(id));
});
return html`<time>${now}</time>`;
});