Skip to content

Instance events

Everything an instance dispatches is a real DOM event, so a plain addEventListener hears all of it.

Component events

$emit(name, payload?) dispatches on $el:

PropertyValue
bubblestrue
cancelabletrue
detailthe payload object, or null

Names are typed lower-kebab string literals declared through the props type's $emits key. There is no namespace: a component event is open, not js-toolkit:open.

js
el.addEventListener('goto', (event) => {
  console.log(event.detail.index);
});

Lifecycle announcements

Every instance announces its own mount and unmount, carrying itself in the payload:

ts
interface LifecycleEventDetail {
  instance: Base;
}
EventConstantDispatched from
js-toolkit:component:mountedEVENTS.component.mountedthe element — bubbles
js-toolkit:component:unmountedEVENTS.component.unmounteddocument
ts
import { 
EVENTS
, type LifecycleEventDetail } from '@studiometa/js-toolkit';
document
.
addEventListener
(
EVENTS
.
component
.
mounted
, (
rawEvent
) => {
const
event
=
rawEvent
as
CustomEvent
<LifecycleEventDetail>;
console
.
log
(`${
event
.
detail
.
instance
.
$id
} mounted`);
});

The unmount event dispatches from document because the element can already be detached. That is also what lets one lazy, realm-shared listener serve every $watchChildren() watcher while the document holds nothing but weak references to them — a listener per watcher would make every watching component immortal.

An instance that is scheduled but not mounted announces nothing.

Diagnostics

js-toolkit:diagnosticEVENTS.diagnostic — starts on the relevant connected element, or on document when there is none, with { bubbles: true, composed: true, cancelable: true }.

preventDefault() suppresses the default console output only. See Diagnostics.

Negotiated events

js-toolkit:dom:updateEVENTS.dom.update — is dispatched by domUpdate(), and emitExtendable() dispatches the name its caller gives.

Both are bubbling and non-cancelable: the step is announced, not proposed. Their detail carries a wrap() or a waitUntil() valid only while the event dispatches.

They have no Base path and are absent from $emits, so the negotiation code and the optional view-transition import stay out of the Base graph. Plain DOM code uses the same functions with no instance.

Private transports

The context request is a bubbling, module-private event and is deliberately not part of public EVENTS. Framework internals that need a transport use module-local namespaced constants; only what a consumer can usefully listen to is exported.

The convention, in full

  • Public framework events use the deeply frozen EVENTS object and the js-toolkit: namespace.
  • Private framework transports use module-local constants and do not join EVENTS.
  • Component events use typed lower-kebab string literals from $emits.
  • A payload is one object in CustomEvent.detail, or the platform value null.
  • Diagnostic events are cancelable, so monitoring can suppress the default output only.

MIT Licensed