Events
Litsx events use the platform model end to end: listen with on:event, keep external callbacks fresh with useEvent(...), and publish typed CustomEvents with useEmit(...).
Listening in JSX
<button on:click={save}>Save</button>
<input on:input={(event) => setQuery(event.currentTarget.value)} />
<user-picker on:user-selected={(event) => select(event.detail.id)} />The colon marks the explicit event channel and preserves the event name. Native onClick is not an event alias; it remains an ordinary prop. The React compatibility pipeline translates React event conventions separately.
Typed component events
Pass an event map to useEmit so emission and consumers share one contract:
type PickerEvents = {
"user-selected": { id: string };
close: undefined;
};
export function UserPicker() {
const emit = useEmit<PickerEvents>();
return (
<button on:click={() => emit("user-selected", { id: "ada" })}>
Select Ada
</button>
);
}
const picker = (
<UserPicker on:user-selected={(event) => event.detail.id} />
);Literal event names let the compiler publish a complete event contract on the component. Use lowercase kebab-case for public declarative events. Names outside the JSX channel, such as menu:open, remain available through addEventListener().
useEmit(...) defaults to { bubbles: true, composed: true, cancelable: false }; pass options when a component needs a different public event contract.
External listeners
useEvent(...) returns a stable callback that always sees current props and state. Pair it with useOnConnect(...) for listeners or resources registered against window, document, observers, or timers.
const onResize = useEvent(() => measure(layout));
useOnConnect(() => {
window.addEventListener("resize", onResize);
return () => window.removeEventListener("resize", onResize);
}, []);