typograph-editor-documentation
    Preparing search index...

    Typograph — Element Events

    This document describes the custom DOM events fired by the Typograph canvas engine in response to page-element actions (selecting an element, editing its text, etc.). It is intended for developers who embed the Typograph editor and need to react to element-level activity — for example to drive a custom properties panel, sync selection with an external UI, or track unsaved changes.

    For page-structure events (add / delete / duplicate / reorder pages) see PageEvents.md. For "the document's content changed", which is what an auto-save or a dirty-state indicator wants, see DocumentEvents.md.

    Source of truth: the event names live in the canvas package at src/typograph_events.ts. This document reflects what the engine actually dispatches today — a number of element event names are declared but not yet fired (see Reserved / not-yet-fired).


    All events are dispatched on document. Element events fired through sendCustomEvent are CustomEvent objects whose payload is on event.detail; events fired through sendEvent are plain Event objects with no payload.

    document.addEventListener('typograph_pageelement_selected', (event) => {
    const { uuid } = event.detail;
    console.log(`Element ${uuid} was selected`);
    });

    Nothing is throttled by default. Throttling is opt-in per event type, and no type opts in (TYP-592). Assume one event per user action.

    This previously said that every CustomEvent passed through a shared 5-per-second throttle. That was true and it was the bug: the throttle only ever dropped discrete events, so two elements selected within 200ms produced one typograph_pageelement_selected and left the listener pointing at the wrong element, and a dropped typograph_textInput — which carries the inserted text, not the whole string — lost characters outright.

    set_custom_event_throttle(max) still sets the rate, for whichever types are opted in.

    document.addEventListener('typograph_editor_ready', () => {
    typograph.set_custom_event_throttle(10); // max 10 per type per second
    });

    Plain Event-based events (typograph_edit_done) are not throttled. typograph_pageelement_hover is also not throttled — it is rate-limited by its own change-detection instead (see its entry below).


    Fired when an element becomes selected — specifically on the transition from not selected to selected (PageElement.set_selected(true)). Re-selecting an already-selected element does not re-fire.

    Property Type Description
    message string Always 'selected'
    uuid string UUID of the element that was selected
    document.addEventListener('typograph_pageelement_selected', (e) => {
    const { uuid } = e.detail;
    });

    There is currently no matching deselect event (see below), and the throttle can drop a selection if several happen within the same 200 ms window. If you need reliable current-selection state, read it from the document/page API on receipt rather than treating the event as an exact 1:1 signal.


    Fired when the element under the cursor changes — the mouse enters a different element, or leaves all elements. Use it to drive a hover highlight or a context-sensitive UI.

    It fires once per boundary crossing: it does not fire repeatedly while the mouse keeps moving inside the same element. When the cursor leaves all elements, it fires once with uuid: null.

    Property Type Description
    uuid string | null UUID of the element now under the cursor, or null when the cursor is over no element
    document.addEventListener('typograph_pageelement_hover', (e) => {
    const { uuid } = e.detail;
    if (uuid) highlightElement(uuid);
    else clearHighlight();
    });

    Unlike the other custom events, typograph_pageelement_hover is not throttled — the change-detection already limits it to one event per element-boundary crossing, and each event is meaningful (throttling could drop the final transition and leave your highlight stale).


    Fired while the user types into a rich-text element (PageElementRichText).

    Property Type Description
    text string The text that was input
    uuid string UUID of the rich-text element being edited
    document.addEventListener('typograph_textInput', (e) => {
    const { text, uuid } = e.detail;
    });

    Throttled to 5/sec by default, so this is not a per-keystroke event and should not be used to reconstruct the typed string. Treat it as a "text in this element changed" hint and re-read the element's content when you need it.


    Fired when a rich-text element loses focus (the editor's setFocus(false)), i.e. the user finished editing text and clicked away.

    This is a plain Event — there is no detail payload, so it does not tell you which element was being edited. Read the current selection/active element from the document API if you need that.

    document.addEventListener('typograph_edit_done', () => {
    // user stopped editing text somewhere — re-read state / mark dirty
    });

    The following element event names are declared in typograph_events.ts but are not dispatched anywhere in the current canvas or editor-ui code. Do not rely on them yet — a listener will simply never be called until the engine is updated to fire them.

    Constant String value Intended meaning
    typograph_pageelement_created typograph_pageelement_created An element was created
    typograph_pageelement_deleted typograph_pageelement_deleted An element was deleted

    Both are still undispatched because the engine does not yet distinguish a user creating an element from one appearing for another reason — opening a document creates every element, undo recreates them, duplicating a spread creates a dozen. Firing on all of that is noise a listener cannot use, so the distinction has to come first.

    Two corrections to earlier versions of this list, so nothing is inferred from a stale copy:

    • typograph_pageelement_deselected does fire, and has since TYP-592. It is documented in the table above.
    • typograph_text_edit_start / _change / _stop no longer exist. They were declared but never dispatched and were deleted in TYP-592. typograph_edit_done covers "text editing finished" and typograph_textInput covers "the text changed".

    There is still no per-element "changed" event: geometry changes (move, resize, rotate) and style changes (fill, stroke, colour, opacity, shadow, …) do not report which element changed. If you only need to know that the document changed at all — for an auto-save or a modified indicator — use typograph_document_changed (DocumentEvents.md), which covers those edits. Polling element state is no longer the recommended approach for that case.


    Event Fired? Trigger detail
    typograph_pageelement_selected Element becomes selected (unselected → selected) { message: 'selected', uuid }
    typograph_pageelement_deselected Element becomes deselected (selected → unselected) { message: 'deselected', uuid }
    typograph_pageelement_hover ✅ (unthrottled) Hovered element changes (enter/leave) { uuid: string | null }
    typograph_textInput Typing into a rich-text element { text, uuid }
    typograph_edit_done ✅ (plain Event) Rich-text element loses focus (none)
    typograph_document_changed Document content changed — see DocumentEvents.md { reason }
    typograph_pageelement_created ❌ reserved Element created
    typograph_pageelement_deleted ❌ reserved Element deleted