Headless callout annotations
A callout is a TextAnnotation with a leader line that points from a text box to a specific spot on the page. Callouts share the text editor surface with regular text annotations, but they have two extra properties: callout (the leader line geometry) and isFitting (which adjusts the text box size to fit the content). Build callouts programmatically when placement comes from coordinates rather than a user dragging on the page.
Looking for the visual side of this? See the tools.contextual slot for replacing the inline text/callout toolbar. This page covers the programmatic surface you’ll call from inside that custom UI.
Callouts are text annotations
Callouts don’t have their own annotation class; they’re TextAnnotation instances with the callout property set. That’s worth knowing because searching the API reference for “callout” won’t surface a dedicated class.
There are two properties that turn a text annotation into a callout.
| Property | Notes |
|---|---|
callout | A NutrientViewer.Callout instance describing the leader line geometry with start, knee (optional), end, and cap. |
isFitting | When true, the text box auto-fits to the content size. Recommended for callouts to avoid empty space in the box. |
When to use this
Reach for callout annotations when you need to:
- Label features in an engineering drawing or schematic from a coordinate set.
- Import annotations from a CAD or analysis tool that emits “label this point with this text” data.
- Build a custom annotation tool in your host app that creates callouts at user-picked positions with your own styling.
- Render a guided tour overlay that points at PDF content using callout annotations rather than HTML overlays.
Example: Create a callout pointing at a coordinate
The minimal callout is a text annotation with callout set and isFitting enabled:
const { TextAnnotation } = NutrientViewer.Annotations;const { Callout } = NutrientViewer;const { Rect, Point } = NutrientViewer.Geometry;
const callout = new TextAnnotation({ pageIndex: 0, text: { format: "plain", value: "Important detail" }, fontSize: 14, fontColor: NutrientViewer.Color.BLACK, backgroundColor: NutrientViewer.Color.fromHex("#FFFDE7"), isFitting: true, boundingBox: new Rect({ left: 250, top: 100, width: 160, height: 60 }), callout: new Callout({ start: new Point({ x: 250, y: 130 }), knee: new Point({ x: 200, y: 200 }), end: new Point({ x: 100, y: 250 }), cap: NutrientViewer.LineCap.openArrow })});
await instance.create(callout);The start point is where the leader leaves the text box. The end point is what the callout points at. The optional knee adds a single bend between the two; omit it for a straight leader.
Example: Convert an existing text annotation to a callout
When you already have a text annotation and want to add a leader line, set the callout property using set() (text annotations are immutable records):
const annotations = await instance.getAnnotations(0);const target = annotations.find( (a) => a instanceof NutrientViewer.Annotations.TextAnnotation);
if (target) { const updated = target .set("isFitting", true) .set( "callout", new NutrientViewer.Callout({ start: new NutrientViewer.Geometry.Point({ x: target.boundingBox.left, y: target.boundingBox.top + 20 }), end: new NutrientViewer.Geometry.Point({ x: 50, y: 200 }), cap: NutrientViewer.LineCap.openArrow }) );
await instance.update(updated);}Example: Import callouts from a CAD-style coordinate list
When the callout positions come from a server or an external tool, map the data into TextAnnotation instances and create them in a single call:
async function importLabels(labels) { const annotations = labels.map((label) => new NutrientViewer.Annotations.TextAnnotation({ pageIndex: label.page, text: { format: "plain", value: label.text }, fontSize: 12, isFitting: true, backgroundColor: NutrientViewer.Color.fromHex("#FFFFFF"), strokeColor: NutrientViewer.Color.fromHex("#1976D2"), boundingBox: new NutrientViewer.Geometry.Rect({ left: label.boxX, top: label.boxY, width: 140, height: 40 }), callout: new NutrientViewer.Callout({ start: new NutrientViewer.Geometry.Point({ x: label.boxX, y: label.boxY + 20 }), end: new NutrientViewer.Geometry.Point({ x: label.targetX, y: label.targetY }), cap: NutrientViewer.LineCap.openArrow }) }) );
await instance.create(annotations);}Related
- Headless text annotations — The underlying text editor surface that callouts inherit from.
- Headless shapes — For drawing leader-style annotations that aren’t tied to a text box.
- Geometry primitives — The
PointandRectclasses used here.