Elements can be sheared, as in InDesign, with a new Shear field beside Rotate. Slider drags are one
undo step again. And an embedding page can now hand the editor its templates, images, clips and
save functions directly, through host.
ui.hide('parameterbar.shear').host (TYP-697)This shipped on 2026-10-14, when it was merged; it is recorded here with the release it belongs to.
new Typograph.Editor({ host: { ... } }) now accepts host providers directly — the way to
supply templates, images, the manifest and clips without the deprecated set_*_callback
setters. A provider may return its value directly or as a promise.new Typograph.Viewer({ host, legacy_php_fallback }) takes the same two options.Editor constructed after the legacy auto-boot already ran applies host and
legacy_php_fallback to the existing document instead of setting up again.typograph.setup() yourself with the editor or viewer on the page: both call it
themselves, and a second call replaces the document with an empty one (the page "flips") and
drops every provider and callback set on the first. Pass host to the constructor instead.set_templates_callback, set_images_callback, and set_clips_callback setters keep
working, and each logs one deprecation warning naming the host field that replaces it.php/get_manifest.php, php/get_clips.php) stay, as
relative requests the host's page serves; version 2 removes them.host.save_document and host.save_clip are now consulted the same way, ahead of the matching
legacy callback and PHP endpoint. host.upload_image, host.remove_file and host.delete_files
are also consulted in the source, but nothing in the shipped editor UI calls their consumers yet,
so supplying them has no observable effect today.host.save_template is now consulted ahead of the legacy save_template_callback: File ▸ Save
as template proceeds when either source is configured, where previously only the legacy callback
opened the path.XMLHttpRequest calls in the asset manager and clip manager have been
replaced with fetch — neither file ships in the current bundle, so there is nothing to observe
from outside.legacy_php_fallback (default true): set it to false, or call
doc.host.set_legacy_php_fallback(false), and the editor makes no php/*.php request at all.
UI that no provider backs is then hidden: the Images, Clips and Templates tabs, and File ▸
Save / Save as template / Save as clip. With the default, nothing changes. The first PHP
fallback per endpoint now logs a [TYP-697] deprecation warning.php/ directory. None of these were reachable from the bundle.localhost:8888. It needs a document url, and
the menu item is hidden when no templates provider backs it (with legacy_php_fallback on it
stays visible, as before). Calling OpenDocumentUrl() without a url now warns instead of
loading the developer's demo file.src/test_editor_ui.ts) is no longer imported by the editor bundle.
It shipped ten localhost:8888 URLs to every host; build it separately with
npm run build:test and load it next to the bundle, as CLAUDE.md describes.set_*_callback setters, the PHP fallbacks and
legacy_php_fallback, and will be published under editor/v2/. latest stays on 1.x until
embedders have moved.docs/Embedding.md for the full host provider contract.The providers do not take the callbacks' shapes: a list provider returns an array, not a JSON
string, and a save provider takes (name, data), not { name, data }. Adapt the existing
functions rather than passing them unchanged:
new Typograph.Editor({
container: '#app',
host: {
templates: () => JSON.parse(getTemplates()),
clips: () => JSON.parse(getClips()),
save_document: (name, data) => saveTemplate({ name, data }),
save_template: (name, data) => saveTemplate({ name, data }),
save_clip: (name, data, thumbnail) => saveClip({ name, data, thumbnail }),
},
legacy_php_fallback: false,
});
Until you move, keep the setters and do not add a typograph.setup() call: the deprecation warning
is only a warning.
Page thumbnails draw turned and sheared text frames correctly. In a page thumbnail — the page
bar's, or one a host makes with PagePreview — a text frame with more text than fits passed its
rotation or shear on to every element drawn after it, so those came out turned, sheared or moved.
The page itself was always right; only the thumbnail was wrong. A stored thumbnail keeps its old
picture until it is drawn again.
Dragging a slider is one undo step. Dragging the slider of the toolbar's Opacity, a shadow's opacity or the new Shear field recorded one undo step for every movement of the mouse, so undoing a drag took many steps. A drag is now undone in one.
feat/TYP-370-shear-field): the field is an Inputfiel_slider_control
(parameterbarrotate.ts, component shear) writing PageElement.set_skew_angle(); the multi bar's
rotate proxy gained set_skew_angle, and element_rotate_panel() takes the value to show, so the
multi bar passes common_value(elements, el => el.get_skew_angle()) and a mixed selection shows
empty with the — placeholder. Inputfiel_slider_control mapped its
slider across 0…max and divided by a fixed 100; it now maps across [min, max], identical for
every existing (0…100) caller. The field writes the element's own value past the field's range
instead of the clamped one.Slidercontrol's thumb sits inside its bar, so a press on the thumb also reached
the bar's mousedown, whose start-value-end call closed the drag before it began. The thumb's
handler now stops propagation. Slidercontrol_color has no undo bracket and is unchanged.PageElement.skewAngle (#59, ±90 exclusive, absent when
unsheared), canvas #183 (skew_angle, one transform matrix for drawing, hit-testing, handles,
bounds and wrap; browser suite run_skew_tests()), document-generator #61 (SkewX between the
rotation and the flip), indesign-converter #67 (decomposes the item's effective matrix; also fixes
mirrored items, which converted as 180° plus a flip, and groups, whose transform was applied
twice), with the lock bumps in the services. canvas-service moves its canvas pin to 3c50e40 in
chore/TYP-370-pin-canvas; until then its layout step drops a converted item's shear.richtext.ts restored the
save() at the top of its draw() only when handles were shown. PagePreview draws without
handles, so the frame's own restore() popped the wrong save and its transform stayed on the
context. Older than the shear, which only made it visible. Browser suite run_skew_tests().96e92ea — TYP-370 (PR #183) and the thumbnail fix (PR #185), on top of 7f0e139.
The other canvas merges in between are CI only (TYP-850, TYP-892), the TYP-849 build fix, and
canvas's TYP-697 host contract: #164 and its revert #179 cancel out, and #180 only points the
deprecation warning at the Editor / Viewer constructors.