PresentationEditor
PresentationEditor uses a typed scene graph for slides and mounts TipTap only
while a text box is being edited. Chinese and other IME pre-edit text stays
local during composition; onChange receives only the committed value, and
editor shortcuts yield to composition keyboard events.
Properties
Content contract
Use fileActions, onAgentRequest, and onStartSlideshow for stable host
integration. The internal scene-command runtime is not a public extension API.
Entrance animations
WorkSlide.animations is the canonical ordered entrance sequence for one
slide. Each record targets one slide-owned element by stable ID. One object may
have at most one editable animation, and one slide accepts at most 256 records.
Select an object and open the Animation ribbon tab to set or remove its
effect, choose the trigger, edit duration and delay, choose a fly-in direction,
move the item earlier or later, or preview the current slide. Duration is
normalized to 100–60,000 milliseconds and delay to 0–60,000 milliseconds. Each
edit produces one controlled onChange value and one Undo record. Deleting an
object removes its animation; copying objects or slides creates fresh object
and animation IDs while preserving the target mapping. Collaboration accepts
only bounded sequences with unique animation IDs, available object targets,
one effect per object, and normalized timing.
Cue and playback semantics
If a slide begins with with-previous or after-previous, its first cue starts
automatically when the slide opens. Audience and presenter modes render the
same pending, playing, and finished object state, so switching views does not
skip an object. In a prefers-reduced-motion: reduce environment, a playing
item becomes visible without decorative movement while the cue order remains
unchanged.
Native PPTX boundary
The supported subset exports as native PresentationML timing trees. Import
maps the timing target's cNvPr shape ID back to the stable browser element ID,
and a second export and reopen retain effect, order, trigger, duration, delay,
and fly-in direction. Text inside an animated shape remains one PPTX object,
and grouped animated objects keep valid timing targets.
Import is deliberately bounded. Emphasis and exit effects, motion paths, unsupported entrance presets, duplicate effects on one object, missing or ambiguous targets, malformed timing, and namespace-spoofed timing trees do not become editable records. Compatibility diagnostics report each skipped or normalized item. Export writes the supported editable sequence; it does not claim lossless preservation of an unsupported source timing tree. Audio, video, rehearsal, recording, trigger-on-object behavior, and the broader animation catalog remain future work.
Open Latest capabilities → 入场动画 in the Playground to inspect all four effects and all three trigger modes, edit the sequence from the Animation tab, and verify it in the built-in slideshow. Focused model, command, component, collaboration, clipboard, slideshow, and native PPTX reopen tests keep this public contract synchronized with the implementation.
Large decks
Decks above 60 slides window thumbnail buttons in both normal and sorter
views. A separate intersection window mounts full slide scenes only for the
selected slide and the viewport overscan. Home, End, arrows, deletion, and
external selection use absolute slide positions, so every slide remains
keyboard reachable even when its thumbnail is not mounted.
The deterministic 1,000-slide fixture mounts 18 buttons and 13 complete
thumbnail scenes at a 1440 × 1000 viewport. Master and layout metadata is
prepared once per controlled value, while each thumbnail resolves only its own
slide. content-visibility: auto is intentionally not enabled on the rail: an
interleaved five-process benchmark showed no retained-memory benefit and made
median object commits 31% slower. Reproduce the product and diagnostic modes
with bun run test:e2e:large-presentation and
bun run performance:presentation.
Real-time collaboration
Pass an initialized presentation collaboration session to make its Yjs scene
graph canonical. Slide, master, and layout order live separately from ID-keyed
records; each container owns ordered, ID-keyed scene elements. Append-only
creation claims reject conflicting same-ID records, and deletion writes a
durable tombstone that reserves the ID. Local undo tracks only the mounted
binding's origin, while presence publishes slide/object selection and renders
remote object frames.
Rust, CLI, MCP, and A3S Code use the closed
presentation-create-element, presentation-update-element,
presentation-move-element, and presentation-delete-element mutations.
Creation may place a complete element after one active stable ID. Update
compares complete expected/current/next elements and writes only changed
top-level fields, so unrelated concurrent geometry, text, or style edits merge
while a stale same-field edit fails without a durable update. Move compares the
stable observed and requested predecessor IDs instead of array indexes;
null means the first element-order position. It is idempotent at the requested
destination and otherwise fails atomically on a stale source position or an
unavailable anchor. Only the moved element's order entry changes. Delete
requires the exact complete current element and tombstones it. Element id and
type are immutable across all four operations. See
Real-time collaboration for session setup and mutation
examples.
Built-in slideshow
The slideshow keeps one shared navigation strip in audience and presenter modes. Arrow keys and Page Up/Page Down move between slides, Space advances, Home and End jump to the deck boundaries, and Escape exits playback. These commands remain active when a slideshow control has focus, while text inputs and editable content retain their normal keyboard behavior.
Presenter mode shows the current slide, next-slide cue, speaker notes, and a pauseable timer. The timer belongs to the playback session, so switching between audience and presenter modes does not reset elapsed time. At phone widths, the current slide stays full-width, the next-slide preview compacts to its title cue, notes remain scrollable, and the same navigation strip remains available.
