This document describes the custom DOM events fired by the Typograph canvas engine when the user performs page-level actions. It is intended for developers who embed the Typograph editor and need to react to changes in the page structure (e.g. to sync a thumbnail strip, update a save state, or push changes to a backend).
Two events here are not structural changes: typograph_page_shown
reports which spread is shown, and typograph_page_hover which page the
pointer is over. It is documented alongside the others because it
speaks about pages, and in full — with the two accessors that answer which page is selected and
which page is the work on — in PageSelection.md.
All page events are dispatched on document as standard CustomEvent objects.
The event payload is available on event.detail.
document.addEventListener('typograph_page_added', (event) => {
const { page_index, page_name } = event.detail;
console.log(`Page "${page_name}" added at index ${page_index}`);
});
The page action events pass through the same throttle as all other Typograph custom events. The default limit is 5 events per event-type per second. Because page actions are user-initiated and infrequent this limit is never reached in practice.
typograph_page_shown and typograph_page_hover are the exceptions: they are not
throttled, for the reasons given in their own sections below.
If your application needs a higher or lower rate you can adjust it after the editor is ready:
document.addEventListener('typograph_editor_ready', () => {
typograph.set_custom_event_throttle(10); // max 10 per type per second
});
typograph_page_addedFired after a new blank page has been appended to the document.
| Property | Type | Description |
|---|---|---|
page_index |
number |
Zero-based index of the newly added page |
page_name |
string |
Name given to the new page |
document.addEventListener('typograph_page_added', (e) => {
const { page_index, page_name, container_index, record_index } = e.detail;
});
typograph_page_duplicatedFired after a page has been duplicated. The new page is always appended at the end of the document.
| Property | Type | Description |
|---|---|---|
source_index |
number |
Zero-based index of the page that was copied |
page_index |
number |
Zero-based index of the resulting duplicate |
page_name |
string |
Name of the duplicate page |
document.addEventListener('typograph_page_duplicated', (e) => {
const { source_index, page_index, page_name } = e.detail;
});
typograph_page_deletedFired after a page has been removed from the document.
Note —
page_indexis the index the page held before it was deleted. After deletion, all pages at higher indexes shift down by one.
| Property | Type | Description |
|---|---|---|
page_index |
number |
Zero-based index of the spread the page was in (pre-deletion) |
page_name |
string |
Name of the deleted page |
container_index |
number |
The same spread index, named the way get_selected_page() names it |
record_index |
number | null |
Which page of that spread was deleted; null when the whole spread was |
Deleting one page out of a two-page spread fires this event too, with that page's
record_index; the spread itself stays, holding the other page. Before 20261007 only deleting a
whole spread fired it.
document.addEventListener('typograph_page_deleted', (e) => {
const { page_index, page_name } = e.detail;
});
typograph_page_rearrangedFired after the user drags a page thumbnail to a new position in the page bar.
| Property | Type | Description |
|---|---|---|
from_index |
number |
Zero-based index of the page before the move |
to_index |
number |
Zero-based index of the page after the move |
document.addEventListener('typograph_page_rearranged', (e) => {
const { from_index, to_index } = e.detail;
});
typograph_page_scaledFired after a page and all its elements have been scaled. Both dimensions are scaled independently, so non-uniform scaling is possible.
| Property | Type | Description |
|---|---|---|
page_index |
number |
Zero-based index of the scaled page |
scale_x |
number |
Horizontal scale factor (e.g. 2.0 = doubled in width) |
scale_y |
number |
Vertical scale factor |
document.addEventListener('typograph_page_scaled', (e) => {
const { page_index, scale_x, scale_y } = e.detail;
});
typograph_spread_splitFired after a spread page has been split into two independent single pages. The spread is replaced by the two pages at the same position in the document; subsequent pages shift up by one index.
| Property | Type | Description |
|---|---|---|
spread_index |
number |
Zero-based index the spread occupied before the split |
page_name |
string |
Name of the spread page that was split |
document.addEventListener('typograph_spread_split', (e) => {
const { spread_index, page_name } = e.detail;
});
typograph_pages_mergedFired after two adjacent single pages have been merged into a horizontal spread. The right page is removed from the document; the left page becomes the spread and retains its index. Pages that were after the right page shift down by one.
| Property | Type | Description |
|---|---|---|
left_index |
number |
Zero-based index of the left (surviving) page before the merge |
right_index |
number |
Zero-based index of the right page before it was merged in |
document.addEventListener('typograph_pages_merged', (e) => {
const { left_index, right_index } = e.detail;
});
typograph_page_shownFired when a different spread is shown on the canvas — whatever showed it: a click in the page
bar, set_active_page(), opening a document, or a delete, reorder or undo that moves the view.
| Property | Type | Description |
|---|---|---|
container_index |
number |
Zero-based index of the spread now shown |
record_indexes |
number[] |
Its pages — [0] for a single page, [0, 1] for a facing pair |
page_names |
string[] |
The name of each of those pages, in the same order ('' for an unnamed page) |
document.addEventListener('typograph_page_shown', (e) => {
const { container_index, record_indexes, page_names } = e.detail;
myPageList.markCurrent(container_index);
myTitle.textContent = page_names.filter(Boolean).join(' / ');
});
It fires once per change and never for a redraw that keeps the same spread — zooming, scrolling, editing or an undo on the spread already shown report nothing. Opening a document always reports the spread it opens on, even when it is the same document again, so a host can set its own state from this one event. While a cover's spine is edited upright (below) nothing is reported: it is still the same page to the host.
Like typograph_page_hover it is not throttled: each event is a real change, and dropping one
would leave your UI showing the wrong page.
The pair
container_index+record_indexesaddresses pages the waytypograph.get_selected_page(),logical_pages()andmove_logical_page()do — seePageSelection.md. To ask at any moment rather than listen,typograph.get_focused_page()answers which spread is shown.
typograph_page_hoverFired when the page under the pointer changes, on the rendered spread in the canvas — not on the page bar.
| Property | Type | Description |
|---|---|---|
container_index |
number | null |
Zero-based index of the spread under the pointer; null when the pointer is over no page |
record_index |
number | null |
Which page within that spread — 0 or 1 for a facing pair; null when over no page |
document.addEventListener('typograph_page_hover', (e) => {
const { container_index, record_index } = e.detail;
if (record_index === null) clearPageHighlight();
else highlightPage(container_index, record_index);
});
Both fields are null together, and that is a real state rather than a failure: the pointer can
be over the canvas without being over paper — the grey around the spread, or the gutter between
two pages.
It fires once per boundary crossing, not continuously while the pointer stays on one page. Like
typograph_pageelement_hover — and unlike every
other event in this document — it is not throttled: the change detection already limits it to
one event per crossing, and each one is a meaningful transition.
Off by default in a view-only embed. Hover dispatch follows
set_hover_events()and is deliberately independent ofinteractive/set_interactive(), so a viewer host can drive a layout picker or a page highlight without making the document editable:typograph.set_hover_events(true).
⚠️ Element hover and page hover are independent. A page can have no element on it, and an element can overhang the paper onto the grey — do not infer one from the other.
⚠️ The pair addresses a page the way
logical_pages(),move_logical_page()anddelete_logical_page()do. The other page events in this document carry a flatpage_indexinstead; the two are not interchangeable. SeePageSelection.mdfor converting between them.
typograph_spine_edit_started / typograph_spine_edit_endedA cover's spine was opened for editing upright, and later closed (TYP-783). Page → Edit spine, or a double-click on an empty part of the spine, opens it; OK / Cancel above the spine, the same two buttons in the Spine panel, or Escape closes it.
| Event | Property | Type | Description |
|---|---|---|---|
…_started |
container_index |
number |
The cover's index in the document's spreads |
spine_direction |
'top_to_bottom' | 'bottom_to_top' |
Which way the spine reads, and so which way it was turned | |
…_ended |
container_index |
number |
As above |
outcome |
'ok' | 'cancel' |
OK wrote the spine into the cover as one undo step; Cancel left the cover as it was |
document.addEventListener('typograph_spine_edit_started', () => myToolbar.lockSaving(true));
document.addEventListener('typograph_spine_edit_ended', () => myToolbar.lockSaving(false));
⚠️ Lock your own save and page UI between the two. While the spine is open, the spread at the
cover's position is a temporary one — the spine turned on its side — and the cover is held aside.
Saving is safe (get_document_data_as_string() writes the held cover in its place), but it saves
the cover without the edits made in the session so far, and anything that walks the spreads
sees the temporary one. The editor greys its File and Page menus, refuses ⌘S / ⌘O, and locks the
page bar; a host's own menu items are greyed too. typograph.get_typograph_document().is_spine_editing()
answers at any moment.
typograph_keep_pages_togetherA spread's Keep pages together was turned on or off (TYP-976): from the Page panel's switch, or by
the host calling typograph.set_keep_pages_together(container_index, keep).
| Property | Type | Description |
|---|---|---|
container_index |
number |
The spread's index in the document's spreads |
keep_together |
boolean |
true: its pages stay one block through every reorder, delete and facing toggle |
document.addEventListener('typograph_keep_pages_together', (e) => {
const { container_index, keep_together } = e.detail;
myLayoutPanel.setLocked(container_index, keep_together);
});
typograph.set_keep_pages_together(2, true); // true when applied, false when refused
typograph.get_keep_pages_together(2); // true / false, or null for a spread that does not exist
The change is one undo step, so it also fires typograph_document_changed and is_changed() turns
true. Turning it off lets the pages pair the way the rest of the document does at once: with facing
pages off, a kept-together spread becomes single pages, in the same undo step.
⚠️ Not sent when nothing changes:
set_keep_pages_together() answers false for a spread that does not exist, for the cover (always
one block), and while a spine is being edited;true and sends nothing when the spread already has that setting.An undo or redo of the toggle is a structure step like any other, so it fires
typograph_document_changed, not this event. Read the state again with get_keep_pages_together()
when that fires.
| Event | Trigger | Key detail properties |
|---|---|---|
typograph_page_added |
New blank page appended | page_index, page_name |
typograph_page_duplicated |
Active page duplicated | source_index, page_index, page_name |
typograph_page_deleted |
Page removed | page_index, page_name, container_index, record_index |
typograph_page_rearranged |
Page dragged to new position | from_index, to_index |
typograph_page_scaled |
Page and elements scaled | page_index, scale_x, scale_y |
typograph_spread_split |
Spread split into two pages | spread_index, page_name |
typograph_pages_merged |
Two pages merged into a spread | left_index, right_index |
typograph_page_shown |
A different spread is shown (page bar, navigation, document opened, …) | container_index, record_indexes, page_names |
typograph_page_hover |
Pointer moves onto a different page (or off the paper) | container_index, record_index |
typograph_spine_edit_started |
A cover's spine opened for editing | container_index, spine_direction |
typograph_spine_edit_ended |
The spine session closed | container_index, outcome |
typograph_keep_pages_together |
A spread's Keep pages together turned on or off | container_index, keep_together |