LiveEventEmitter
The single place every emit point in this package's component/render/ HTTP lifecycle goes through — one small set of static helpers instead of duplicating the "construct a slot, dispatch, read it back" dance at each of the call sites (`AutocompleteComponent`, `AbstractDashboardComponent` + `DataTableComponent`, `AbstractFieldComponent`, the four HTML/TUI renderers, `LiveEndpoint`). Every method here is nullable-safe: `$dispatcher === null` means every `with*()` helper below runs its `$compute` closure directly and no event is ever constructed or dispatched — byte-identical to this package's pre-event behavior. This is the load-bearing property the whole retrofit rests on (see `docs/superpowers/specs/2026-07-08-event-driven-familia-design.md` §milpa/live: "el dispatcher entra como dep opcional; sin él los * componentes corren igual").
LiveEventEmitter::withMounting()
public static function withMounting(?Milpa\Interfaces\Event\MilpaEventDispatcherInterface $dispatcher, string $componentName, array $props, Milpa\Live\ValueObjects\ComponentContext $context, Closure $compute): Milpa\Live\ValueObjects\StateSnapshotWraps a `mount()` call with `component.mounting` (PRE, no slot) / `component.mounted` (POST, no slot). Mount has no interception seam in this catalog — see {@see ComponentMountingEvent}.
Parameters
| Name | Type | Description |
|---|---|---|
| $dispatcher | ?Milpa\Interfaces\Event\MilpaEventDispatcherInterface | |
| $componentName | string | |
| $props | array<string, mixed> | |
| $context | Milpa\Live\ValueObjects\ComponentContext | |
| $compute | \Closure(): StateSnapshot |
LiveEventEmitter::withHandling()
public static function withHandling(?Milpa\Interfaces\Event\MilpaEventDispatcherInterface $dispatcher, Milpa\Live\ValueObjects\InteractionRequest $request, Closure $compute): Milpa\Live\ValueObjects\InteractionResultWraps a `handle()` call with `component.handling` (PRE, slot) / `component.handled` (POST, no slot). A `component.handling` listener may: - short-circuit (`InterceptionSlot::shortCircuit($interactionResult)`) to answer on the component's behalf — `$compute` never runs; - veto (`InterceptionSlot::stop()`) — `$compute` never runs; the veto is reported back to the caller via `InteractionResult::$errors` rather than silently doing nothing, per {@see \Milpa\Live\Contracts\Component\ComponentDefinitionInterface::handle()}'s own "SHOULD report via errors, not throw" contract; - do neither — `$compute` runs exactly as it would with no dispatcher wired.
Parameters
| Name | Type | Description |
|---|---|---|
| $dispatcher | ?Milpa\Interfaces\Event\MilpaEventDispatcherInterface | |
| $request | Milpa\Live\ValueObjects\InteractionRequest | |
| $compute | \Closure(): InteractionResult |
Throws
\LogicException If a listener short-circuits with a value that is not an
{@see InteractionResult} — the documented contract for this slot.
LiveEventEmitter::withRendering()
public static function withRendering(?Milpa\Interfaces\Event\MilpaEventDispatcherInterface $dispatcher, string $componentName, Milpa\Live\ValueObjects\RenderRequest $request, Closure $compute): Milpa\Live\ValueObjects\RenderResultWraps a `render()` call with `component.rendering` (PRE, slot) / `component.rendered` (POST, no slot). See {@see withHandling()} for the short-circuit/veto/passthrough shape — identical here, just for {@see RenderResult} instead of {@see InteractionResult}. A pure veto (`stop()` with no result) yields an empty {@see RenderResult} for this target rather than running the renderer.
Parameters
| Name | Type | Description |
|---|---|---|
| $dispatcher | ?Milpa\Interfaces\Event\MilpaEventDispatcherInterface | |
| $componentName | string | |
| $request | Milpa\Live\ValueObjects\RenderRequest | |
| $compute | \Closure(): RenderResult |
Throws
\LogicException If a listener short-circuits with a value that is not a
{@see RenderResult} — the documented contract for this slot.
LiveEventEmitter::liveRequest()
public static function liveRequest(?Milpa\Interfaces\Event\MilpaEventDispatcherInterface $dispatcher, Milpa\Live\ValueObjects\InteractionRequest $interaction, ?Milpa\Live\ValueObjects\SecurityPrincipal $principal): Milpa\Events\InterceptionSlotDispatches `live.request` (PRE, slot) — see {@see LiveRequestEvent} for the security-anchor placement contract. Returns the slot for {@see \Milpa\Live\Http\LiveEndpoint::handle()} to read back; unlike the other `with*()` helpers here, `LiveEndpoint` needs to branch on the outcome itself (a short-circuit skips `handle()` but still re-renders with the intercepted state; a veto skips both and returns an error response directly), so this one hands back the raw slot instead of taking a `$compute` closure.
Parameters
| Name | Type | Description |
|---|---|---|
| $dispatcher | ?Milpa\Interfaces\Event\MilpaEventDispatcherInterface | |
| $interaction | Milpa\Live\ValueObjects\InteractionRequest | |
| $principal | ?Milpa\Live\ValueObjects\SecurityPrincipal |
LiveEventEmitter::liveResponded()
public static function liveResponded(?Milpa\Interfaces\Event\MilpaEventDispatcherInterface $dispatcher, Milpa\Live\ValueObjects\InteractionRequest $interaction, Milpa\Live\Http\LiveHttpResponse $response, bool $intercepted): voidDispatches `live.responded` (POST, no slot) — see {@see LiveRespondedEvent}.
Parameters
| Name | Type | Description |
|---|---|---|
| $dispatcher | ?Milpa\Interfaces\Event\MilpaEventDispatcherInterface | |
| $interaction | Milpa\Live\ValueObjects\InteractionRequest | |
| $response | Milpa\Live\Http\LiveHttpResponse | |
| $intercepted | bool |