Component Context
defineComponent((ctx) => …) receives exactly one argument: the component
context. It bundles DOM access, reactivity, events and cleanup for this
instance.
import { defineComponent } from "@fullhaus/rivet";
export default defineComponent((ctx) => { const { root, part, signal, effect, on } = ctx; // … return { /* public API */ };});Overview
Section titled “Overview”| Property | Description |
|---|---|
root | The component root element (HTMLElement) |
part(name) | Finds one [data-rivet-part="name"] in root |
parts(name) | Finds all matching parts (array) |
template(name) | Factory that clones a <template> part |
signal(initial) | Creates a reactive signal |
computed(fn) | Creates a derived signal |
effect(fn) | Runs fn immediately & on signal changes |
untrack(fn) | Reads signals without subscribing the effect |
on(target, event, handler, options?) | Event listener with auto cleanup |
cleanup(fn) | Registers a cleanup function |
emit(name, detail?) | Emits a local app event |
listen(name, handler) | Listens to a local app event (auto cleanup) |
global.emit(name, detail?) | Emits a global event (cross-app) |
global.listen(name, handler) | Listens to a global event (auto cleanup) |
root: HTMLElement
Section titled “root: HTMLElement”The element carrying the data-rivet attribute.
part<T>(name): T
Section titled “part<T>(name): T”Returns the first [data-rivet-part="name"] inside root. Throws an error with
component context if none exists.
const button = part<HTMLButtonElement>("button");parts<T>(name): T[]
Section titled “parts<T>(name): T[]”Returns all matching parts as an array (possibly empty).
for (const item of parts("item")) { /* … */ }template(name): () => DocumentFragment
Section titled “template(name): () => DocumentFragment”Looks for template[data-rivet-part="name"] and returns a factory that yields a
fresh clone on each call. See Templates.
Reactivity
Section titled “Reactivity”signal<T>(initial): SignalGetter<T>
Section titled “signal<T>(initial): SignalGetter<T>”Creates a signal. See Reactivity for the full signature
(set, update, peek).
computed<T>(fn): SignalGetter<T>
Section titled “computed<T>(fn): SignalGetter<T>”Derived signal. Cleaned up on unmount.
effect(fn): void
Section titled “effect(fn): void”Runs fn immediately and again on changes of signals read inside. A function
returned by the effect serves as cleanup. In the context, the effect registers
itself for unmount cleanup automatically (returns void).
untrack<T>(fn): T
Section titled “untrack<T>(fn): T”Reads signals without subscribing the surrounding effect.
Events & cleanup
Section titled “Events & cleanup”on(target, event, handler, options?): void
Section titled “on(target, event, handler, options?): void”Adds an event listener that is removed automatically on unmount. options is
the native AddEventListenerOptions.
on(window, "scroll", onScroll, { passive: true });cleanup(fn): void
Section titled “cleanup(fn): void”Registers any cleanup function that runs on unmount.
const obs = new ResizeObserver(/* … */);cleanup(() => obs.disconnect());emit(name, detail?) / listen(name, handler)
Section titled “emit(name, detail?) / listen(name, handler)”Local app bus. listen is unsubscribed automatically on unmount. See
Events.
global.emit / global.listen
Section titled “global.emit / global.listen”Cross-app bus (singleton). global.listen is also unsubscribed automatically.
Complete example
Section titled “Complete example”export default defineComponent( ({ root, part, parts, signal, computed, effect, on, cleanup, listen }) => { const items = parts("item"); const active = signal(0); const label = computed(() => `${active() + 1} / ${items.length}`);
on(part("next"), "click", () => active.update((i) => (i + 1) % items.length) );
effect(() => { items.forEach((el, i) => el.classList.toggle("is-active", i === active())); part("label").textContent = label(); });
listen("reset", () => active.set(0));
const obs = new IntersectionObserver(() => {}); obs.observe(root); cleanup(() => obs.disconnect());
return { goTo: (i: number) => active.set(i) }; });