/** Callback for the custom `enterViewport` event (IntersectionObserver). */ export type EnterViewportHandler = (entry: IntersectionObserverEntry) => void; /** Callback for the custom `exitViewport` event (IntersectionObserver). */ export type ExitViewportHandler = (entry: IntersectionObserverEntry) => void; /** Callback for the custom `clickOutside` event (mousedown outside element). */ export type ClickOutsideHandler = (event: MouseEvent) => void; export interface MatesCustomEventMap { /** Fires when the element enters the viewport (via IntersectionObserver). */ enterViewport: EnterViewportHandler; /** Fires when the element exits the viewport (via IntersectionObserver). */ exitViewport: ExitViewportHandler; /** Fires when the user clicks outside of this element. */ clickOutside: ClickOutsideHandler; } /** * Full event handler map merging standard HTMLElement events with mates-specific * custom events. Each key is an event name and each value is the handler * function. All entries are optional. */ export type OnEventMap = { [K in keyof HTMLElementEventMap]?: (event: HTMLElementEventMap[K]) => void; } & { [K in keyof MatesCustomEventMap]?: MatesCustomEventMap[K]; }; /** * Declarative event-binding directive for lit-html templates. * * Accepts a map of DOM event names (type-safe) plus mates-specific custom * events: `enterViewport`, `exitViewport`, and `clickOutside`. * * Listeners and observers are created once and reused across re-renders. * If a handler's identity changes, only the handler reference is swapped — * the underlying listener / observer stays intact (no teardown/recreate). * Handlers that are removed from the map between renders are cleaned up. * * When the host element is disconnected from the DOM, all listeners and * observers are automatically torn down. They are re-created on the next * render after reconnection. * * For element-level resize observation, use the `onResize` lifecycle hook * instead. * * @example * ```ts * import { html } from "mates"; * import { on } from "mates"; * * html` *