# EventSource

An interface for managing event listeners on DOM nodes.

It abstracts the process of adding and removing event listeners, ensuring that they are
properly cleaned up when the scope is closed or the element is removed.

## Signatures

```ts
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

```ts
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]()
}))
```
