Import
import { EventSource } from "@typed/template/EventSource";Signatures
export interface EventSource {
readonly addEventListener: <Ev extends Event>(element: EventTarget, event: EventName, handler: Handler<Ev>) => Disposable;
readonly setup: (rendered: Rendered, scope: Scope.Scope) => Effect.Effect<void>;
}Why
EventSource delegates browser events across the concrete nodes represented
by a rendered value. A matching callback receives a non-pooled Proxy that
forwards properties, binds methods to the native event, and overrides
currentTarget with the registered delegated target. Handlers may be
registered before or after a mount.
Ownership and lifetime
setup binds one rendered range to an explicit Effect Scope. That Scope
removes native listeners and interrupts every handler fiber it started.
Disposing the value returned by addEventListener removes only that entry.
No document-global registry or parallel propagation model is created, but the
callback event is not object-identical to the browser event because of that
currentTarget Proxy.
Property: addEventListener
Registers a delegated native event handler for one concrete target.
Property: addEventListener: Why
Registration can happen before a rendered range is attached, keeping template compilation separate from mounting.
Property: addEventListener: Ownership and lifetime
The returned Disposable removes this entry from every active mount; each mount Scope independently owns its native attachments.
Property: setup
Sets up event listeners for a rendered template within a scope.
Property: setup: Why
Delegation attaches to the concrete elements represented by DOM output. The
proxy preserves the browser event’s target, properties, and bound methods
while reporting the registered element as currentTarget.
Property: setup: Ownership and lifetime
The supplied Scope removes listeners and interrupts handler fibers.
Examples
import { Effect, Scope } from "effect"
import { makeEventSource } from "@typed/template/EventSource"
import * as EventHandler from "@typed/template/EventHandler"
const program = Effect.scoped(Effect.gen(function* () {
const eventSource = makeEventSource()
const button = document.createElement("button")
// Add event listener
const handler = EventHandler.make((event: MouseEvent) => {
console.log("Button clicked")
})
const disposable = eventSource.addEventListener(button, "click", handler)
// Setup listeners for rendered content
yield* eventSource.setup(button, yield* Scope.Scope)
// Cleanup
disposable[Symbol.dispose]()
}))Other public imports
These import paths expose the same declaration. Each page retains its own public name and signature.