OPEN SOURCE / HEADLESS TYPESCRIPT

Explain what's already on the screen.

Annotations that know where to go. Attach notes to actual chart marks, diagram nodes, DOM regions and reports—without giving up control of rendering or application state.

DOM-free core · Collision-aware layout · Optional adapters

01 / INTERACTIVE

Placement, as it happens.

This is the actual annotation layout engine—not a prerecorded animation. Change the conditions and watch it recalculate.

LIVE GEOMETRYHOST-CONTROLLED SVG
RESPONSE / NORMALIZED SAMPLE INDEX →
LAYOUT SCORE—
NOTES PLACED—
NOTE OVERLAP—

CONFIGURE THE SCENE

Move the conditions.
Keep the context.

Every update recomputes note candidates against obstacles and existing placements.

Real resolveAnnotationLayout and renderAnnotationsSvg. Inspect source ↗

02 / THE BOUNDARY

You own the surface.
We handle the callouts.

Bring geometry from the thing you already render. Receive deterministic placements, paths and a scored quality report.

↗

Anchor to reality.

Points, boxes, DOM ranges, chart marks and diagram edges become anchors for shared annotation data.

▱

Make room for meaning.

Explore candidate placements, avoid known obstacles, and route connectors around crowded regions.

⌗

Render your way.

Output SVG, use React components or draw the geometry yourself. Application state remains yours.

03 / REAL EXAMPLES

See the annotations land.

Every example runs real repository code. Open the demo, examine the source, and bring the same patterns to your host.

Annotations over a generated Vega visualization

VEGA / VEGA-LITE

Explain generated marks.

Resolve annotated targets after the chart renderer produces its geometry.
Annotations around Mermaid diagram elements

MERMAID

Turn diagrams into evidence.

Explain rendered nodes and messages without owning the diagram language.

04 / GET STARTED

Plain objects in.
Render-ready output.

Use the headless core, pass host coordinates, and choose a renderer. Optional adapters stay opt-in.

npm install @ponchia/annotations

Start with an existing SVG or a measured DOM box. The same model supports every optional adapter.

quick-start.ts
import {
  resolveAnnotationLayout,
  renderAnnotationsSvg
} from '@ponchia/annotations';

const layout = resolveAnnotationLayout({
  annotations: [{
    id: 'peak',
    anchor: {
      type: 'point',
      point: { x: 280, y: 90 }
    },
    note: { title: 'Peak response' },
    placement: { side: 'right' }
  }],
  bounds: { x: 0, y: 0, width: 640, height: 360 }
});

const svg = renderAnnotationsSvg(layout, {
  title: 'Chart notes'
});