Craftit
⚡ Quick Reference
Package: @vielzeug/craftit · Category: Ui Primitives
Key exports: define, html, css, signal, computed, effect, props, propsOf, on, ref, host, provide, inject
When to use: Framework-agnostic UI components powered by reactive signals. Ideal when you need custom elements without a full UI framework.
Craftit is a custom-element authoring library built on @vielzeug/stateit.
Installation
pnpm add @vielzeug/craftitnpm install @vielzeug/craftityarn add @vielzeug/craftitQuick Start
import { computed, css, define, html, prop, signal } from '@vielzeug/craftit';
define('my-counter', {
props: {
label: prop.string('Count'),
step: prop.number(1),
},
setup(props, { host }) {
const count = signal(0);
const doubled = computed(() => count.value * 2);
host.class({ 'is-positive': () => count.value > 0 });
return () => html`
<button @click=${() => (count.value += props.step.value)}>${props.label}: ${count}</button>
<p>Doubled: ${doubled}</p>
`;
},
styles: [
css`
:host {
display: inline-grid;
gap: 0.5rem;
}
`,
],
});Why Craftit?
Craftit keeps custom elements functional and signal-driven while still giving you direct control over templates, lifecycle hooks, host bindings, and form-associated behavior.
| Feature | Craftit | Lit | Stencil |
|---|---|---|---|
| Bundle size | 7.9 KB | ~12 kB | ~60 kB+ toolchain |
| Signal-first runtime | ✅ | ❌ (separate signals package) | ❌ |
| Functional component setup | ✅ | Partial | ❌ |
| Typed prop helpers | ✅ | Partial | ✅ |
| Host binding helpers | ✅ | Partial | Partial |
| Form-associated helpers | ✅ | Manual | Partial |
| Headless controls package | ✅ | ❌ | ❌ |
| Zero dependencies | ✅ | ✅ | ❌ |
Use Craftit when you want typed, signal-driven custom elements with minimal runtime overhead and no framework lock-in.
Consider Lit or Stencil when you need their ecosystem-specific tooling, decorators, or compiler-first workflows.
Features
- Signal-first runtime with
signal,computed,watch,batch, and related stateit APIs - Functional component authoring via
define(tag, { props, setup, styles, formAssociated }) - Props via
prop.*helpers or rawPropDefobjects; shared bundles can type againstPropsDef<...> - Setup returns a template function:
return () => html\...`` - Lifecycle hooks:
onMounted(),onCleanup(),onElement(),effect() - Directives:
each,classMap,styleMap,guard,when,live,until,raw - Host bindings:
host.attr,host.class,host.style,host.prop,host.on,host.bind - Form-associated helpers with
defineField() - Headless controls (
@vielzeug/craftit/controls) - Observers (
@vielzeug/craftit/observers) - Testing utilities (
@vielzeug/craftit/testing)
Package Entry Points
| Import | Purpose |
|---|---|
@vielzeug/craftit | Core component API, directives, utilities, and stateit re-exports |
@vielzeug/craftit/controls | Headless controls for fields, navigation, overlays, press, sliders, and spinners |
@vielzeug/craftit/observers | resizeObserver, intersectionObserver, mediaObserver |
@vielzeug/craftit/testing | mount, fire, user, waitFor, cleanup, and helpers |
Compatibility
| Environment | Support |
|---|---|
| Browser | ✅ |
| Node.js | ✅ |
| SSR | ✅ |
| Deno | ✅ |