This document describes the event that reports the document's content changed. It is intended for developers who embed the Typograph editor or viewer and need to react to edits — to drive an auto-save, enable a "save" button, mark a tab dirty, or re-render something derived from the document.
For element-level activity (selection, text input) see ElementEvents.md.
For page structure (add / delete / duplicate / reorder) see PageEvents.md.
Source of truth: the event names live in the canvas package at
src/typograph_events.ts.
Dispatched on document as a CustomEvent; the payload is on event.detail.
document.addEventListener('typograph_document_changed', (event) => {
const { reason } = event.detail; // 'edit' | 'undo' | 'redo'
schedule_autosave();
});
Both the editor and the viewer fire it — it is dispatched from the canvas engine, which both products share, so one listener works against either.
typograph_document_changed| detail | { reason: 'edit' | 'undo' | 'redo' } |
| fires on | a user edit, an undo, a redo |
| throttled | no |
reason distinguishes a fresh edit from a history navigation. Most consumers can ignore it: undo
and redo change the content just as an edit does, which is why they are reported at all.
| why | |
|---|---|
| opening a document | Opening is not a change — the signal means "this differs from what was loaded". Listen for typograph_document_opened instead. |
| redraw, zoom, scroll, resize | Presentation, not content. |
| selection and deselection | Not a content change; see typograph_pageelement_selected / _deselected. |
The event is dispatched from the engine's undo manager, so it reports what the undo stack records. That is very close to "the document changed" but not identical.
Fires for: drawing, moving, resizing and deleting elements; text edits; image content edits; page property changes such as size and colour; and adding, duplicating or deleting a page.
One known gap: changes made through host API calls that do not go through the undo system —
set_userdata() is the clearest example — do not fire. If your integration mutates the document
that way, treat your own call as the change signal; you already know when you made it.
Debounce if you act on this event. A single user gesture can produce more than one, and an auto-save should coalesce regardless.
is_changed()The event tells you something happened. To ask whether the document currently differs from the last saved or loaded state, use the document itself:
const doc = editor.get_document(); // or viewer.get_document()
if (doc.is_changed())
enable_save_button();
await save(doc);
doc.mark_saved(); // is_changed() reads false until the next edit
is_changed() |
|
|---|---|
| document just opened | false |
| after an edit | true |
| after undoing back to the opened state | false |
after mark_saved() |
false |
| after undoing back to the save point | false |
The two highlighted rows are the reason to prefer this over counting events: undoing your way back to a saved state really is unchanged, and a tally of edits can never say so.
Use the event to drive an auto-save; use is_changed() for a Save button, a "modified"
marker, or a "discard changes?" prompt. mark_saved() is yours to call after a successful save —
opening a document needs no call, it resets on its own.
is_changed() covers the same edits the event does, and shares the same gap: a host API call that
bypasses undo is invisible to both.