Events & commands
Commands are the actions exposed to your renderer; events are optional typed CustomEvents you can bubble to host apps.
Declaring events
Section titled “Declaring events”events: (event) => ({ incremented: event<{ amount: number }>(),})With events defined, commands receives an emit helper:
commands: ({ actor, emit }) => ({ add: (amount: number) => { actor.send({ type: 'ADD', amount }); emit('incremented', { amount }); },}),Events bubble and are composed by default, so frameworks can listen with addEventListener.
Listening
Section titled “Listening”- Plain DOM:
element.addEventListener('incremented', (event) => console.log(event.detail.amount)); - Ignite JSX:
<my-counter onIncremented={(event) => handleIncrement(event.detail)}></my-counter>.
Command inputs
Section titled “Command inputs”commands also receive host (the custom element instance) and your adapter’s control surface (actor, store, or observable). Keep commands small and deterministic—delegate async side effects to your state library.
Host helpers
Section titled “Host helpers”Use host for DOM affordances:
commands: ({ host, emit }) => ({ focusSelf: () => host.focus(), emitSize: () => { const { width, height } = host.getBoundingClientRect(); emit('measured', { width, height }); },});You can read dataset, measure the element, or dispatch additional DOM events from host as needed. Reflect state (attrs/aria/class) primarily via your renderer to keep outputs declarative.
Type flow
Section titled “Type flow”- When
eventsis present, event names and payloads are inferred intoemit. statesandcommandsoutputs are merged into the props your renderer receives, giving you typed render args without extra wiring.
Putting it together (XState)
Section titled “Putting it together (XState)”import { igniteCore } from 'ignite-element/xstate';import machine from './counter-machine';
const component = igniteCore({ source: machine, events: (event) => ({ incremented: event<{ count: number }>(), }), states: (snapshot) => ({ count: snapshot.context.count, canDecrement: snapshot.context.count > 0, }), commands: ({ actor, emit }) => ({ increment: () => { actor.send({ type: 'INCREMENT' }); emit('incremented', { count: actor.getSnapshot().context.count }); }, decrement: () => actor.send({ type: 'DECREMENT' }), }),});
component('my-counter', ({ count, canDecrement, increment, decrement }) => ( <div class="counter"> <button onClick={decrement} disabled={!canDecrement}>-</button> <span>{count}</span> <button onClick={increment}>+</button> </div>));