Skip to content

Presentation Shapes

A stable, plugin-owned shape lifecycle on Present-mode sheets. Accessed via snaptrude.presentation.shapes.

Where presentation.annotate is fire-and-forget (every call creates a new shape), this namespace keys each shape by a caller-chosen string — so rerunning an analysis updates its sheet output in place instead of duplicating it. Shape ids are derived deterministically from the plugin id + key, so upserts converge across collaborators, and every shape is stamped with the owning plugin's id: each plugin sees and mutates only its own shapes.

Mutations are gated on the plugin write floor and require Present (documentation) mode to be open; each mutation is a single undo step. list is a never-throw read.

Types

PluginPresentationShapeSpec

The desired shape for upsert — a discriminated union over the four annotate kinds, with the same option shapes as the matching presentation.annotate call. Positions/bounds are relative to the sheet's top-left, in canvas units.

typePayloadMirrors
"text"text, position?, size?, color?annotate.text
"note"text, position?, color?, size?annotate.note
"arrow"start, end, color?, size?annotate.arrow
"geo"kind, bounds, color?, fill?annotate.shape

Option types (PluginAnnotateTextSize, PluginAnnotateTextColor, PluginAnnotateGeoKind, PluginAnnotateFill) are the annotate types — see Presentation Annotate.

PluginPresentationShapeType

The shape kind of a plugin-owned shape (the type discriminant above).

"text" | "note" | "arrow" | "geo"

PluginPresentationShapesUpsertResult

PropertyTypeDescription
shapeIdstringStable id of the canvas shape for the key
createdbooleantrue if the shape was created, false if updated

PluginPresentationShapesListResult

PropertyTypeDescription
shapes{ key: string; shapeId: string; type: PluginPresentationShapeType }[]One entry per live plugin-owned shape

Functions

upsert(key, shape, options?)

Create or update the shape for a key. On first call for a key the shape is created on the target sheet and nested under the sheet frame; on later calls the existing shape is updated in place — same shape id, same sheet, one undo step. Changing the spec's type for an existing key replaces the shape (same shape id).

  • Parameters:
    • key: string — Caller-chosen stable identifier for the shape (per plugin, non-empty)
    • shape: PluginPresentationShapeSpec — The desired shape
    • options?:
      • sheetId?: string — The sheet to create the shape on (defaults to the first sheet; ignored on update — the shape stays on its sheet)
  • Returns: PluginPresentationShapesUpsertResult{ shapeId, created }
  • Throws: PRECONDITION_FAILED if Present mode is not open or the presentation has no sheets; HANDLE_INVALID if sheetId is unknown or not a sheet; VALIDATION on bad args; or if plugin writes are disabled
ts
// Rerunning this call updates the label instead of adding another one.
const { shapeId, created } = await snaptrude.presentation.shapes.upsert("far-label", {
  type: "text",
  text: "FAR: 2.4",
  position: { x: 40, y: 40 },
  color: "blue"
});

remove(key)

Delete the shape for a key.

  • Parameters:
    • key: string — The key passed to upsert (non-empty)
  • Returns: booleantrue if a shape was deleted, false if no shape exists for the key
  • Throws: PRECONDITION_FAILED if Present mode is not open; VALIDATION on an empty key; or if plugin writes are disabled
ts
const removed = await snaptrude.presentation.shapes.remove("far-label");

removeAll()

Delete every shape owned by the calling plugin (across all sheets), in one undo step.

  • Returns: number — The number of shapes deleted
  • Throws: PRECONDITION_FAILED if Present mode is not open; or if plugin writes are disabled
ts
const deleted = await snaptrude.presentation.shapes.removeAll();

list()

List the calling plugin's shapes — one entry per live shape it has upserted. A never-throw read: returns an empty list when Present mode is closed.

  • Returns: PluginPresentationShapesListResult{ shapes }, each { key, shapeId, type }
ts
const { shapes } = await snaptrude.presentation.shapes.list();
const hasLabel = shapes.some((s) => s.key === "far-label");

Errors

Failed calls reject with a typed PluginError — see Error Handling.

CodeWhen
VALIDATIONBad arguments (empty key, malformed shape spec, non-positive geo w/h)
PRECONDITION_FAILEDPresent mode is not open on a mutation, or upsert finds no sheets in the presentation
HANDLE_INVALIDoptions.sheetId is unknown or not a sheet