> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ploterr.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sheet documents

> Make and check the document that holds your sheets.

A paper document holds your sheets. `createEmptyDocument` makes a new one. `validateDocument` checks one that you read from storage.

## Import

```typescript theme={null}
import {
  createEmptyDocument,
  validateDocument,
  findSavedView,
  UnresolvedSavedViewError,
} from '@opengeometry/floorkit';
```

## Example

```typescript theme={null}
import { createEmptyDocument, pageSize } from '@opengeometry/floorkit';

const document = createEmptyDocument();
document.unitSystem = 'metric';
document.sheets.push({
  id: 'ground-plan',
  name: 'Ground floor',
  page: {
    format: 'A3',
    orientation: 'landscape',
    size: pageSize('A3', 'landscape'),
    margin: 10,
  },
  viewports: [],
  annotations: [],
});
const json = JSON.stringify(document);
```

## Notes

* A new document has no sheets.
* Sheet sizes, margins and positions are in millimetres. The origin is the top-left corner.
* The document is plain JSON data. Your app owns it.

## createEmptyDocument

A blank document with no sheets.

```typescript theme={null}
function createEmptyDocument(): PaperDocument;
```

## validateDocument

Structural guard for a deserialized document (validate at the storage boundary).

```typescript theme={null}
function validateDocument(doc: unknown): doc is PaperDocument;
```

## findSavedView

Look up one saved drawing definition without resolving or drawing it.

```typescript theme={null}
function findSavedView(
  viewId: string,
  views: readonly SavedDrawingView[],
): SavedDrawingView | undefined;
```

## UnresolvedSavedViewError

A named view needs a project-level resolver before it can be drawn.

```typescript theme={null}
class UnresolvedSavedViewError extends Error {
  readonly viewportId: string;
  readonly viewId: string;
  readonly code = 'unresolved-saved-view';
  constructor(viewportId: string, viewId: string);
}
```

## Types

### PaperDocument

The serializable paper-space document — the source of truth a consumer stores and syncs (.spec/debt.md "Paper / drawing layer").

```typescript theme={null}
interface PaperDocument {
  version: 1;
  unitSystem?: UnitSystem;
  dimensionStyles?: DimensionStyleRegistry;
  styleId?: PaperStyleId;
  styleOverride?: PaperStyle;
  paperStyles?: PaperStyleRegistry;
  sheets: Sheet[];
}
```

<ResponseField name="version" type="1" required />

<ResponseField name="unitSystem" type="UnitSystem">
  Which conventions the whole drawing set follows: millimetre dimensions and 1:50-style scales, or
  feet-and-inches and 1/4" = 1'-0". A set is one country's practice, so this lives on the document
  rather than per sheet. Absent means `"metric"`, so existing documents are unchanged.
</ResponseField>

<ResponseField name="dimensionStyles" type="DimensionStyleRegistry">
  Named dimension styles, keyed by the id an annotation's `styleId` names. Absent means every
  dimension uses `DEFAULT_DIMENSION_STYLE`.
</ResponseField>

<ResponseField name="styleId" type="PaperStyleId">
  The paper style the whole set is drawn in — a builtin id or one of this document's own
  `paperStyles`.
</ResponseField>

<ResponseField name="styleOverride" type="PaperStyle">
  An overlay on the style: one class changed without forking the preset. Plain JSON, like everything
  else here.
</ResponseField>

<ResponseField name="paperStyles" type="PaperStyleRegistry">
  House styles that travel with the file, resolvable by id. They outrank the builtins and anything a
  host registers.
</ResponseField>

<ResponseField name="sheets" type="Sheet[]" required />

### Sheet

```typescript theme={null}
interface Sheet {
  number?: string;
  id: string;
  name: string;
  page: PageSpec;
  viewports: Viewport[];
  annotations: Annotation[];
  titleblock?: TitleblockInstance;
  styleId?: PaperStyleId;
  styleOverride?: PaperStyle;
}
```

<ResponseField name="number" type="string">
  Explicit sheet reference number; independent of the display name.
</ResponseField>

<ResponseField name="id" type="string" required />

<ResponseField name="name" type="string" required />

<ResponseField name="page" type="PageSpec" required />

<ResponseField name="viewports" type="Viewport[]" required />

<ResponseField name="annotations" type="Annotation[]" required />

<ResponseField name="titleblock" type="TitleblockInstance" />

<ResponseField name="styleId" type="PaperStyleId">
  This sheet's style, outranking the document's.
</ResponseField>

<ResponseField name="styleOverride" type="PaperStyle">
  Layered over the document's overlay, then the viewport's over this.
</ResponseField>

### Viewport

```typescript theme={null}
type Viewport = ViewportBase &
  (
    | {
        source: ViewSource;
        viewId?: never;
      }
    | {
        viewId: string;
        source?: never;
      }
  );
```

### SavedDrawingView

Authored drawing intent.

```typescript theme={null}
type SavedDrawingView =
  | SavedRasterIsometricView
  | (SavedViewBase & {
      kind: 'plan';
      storeyId: string;
      cutHeightAboveStorey: number;
      visibleRange?: {
        below: number;
        above: number;
      };
      elementIds?: string[] | 'all';
      showMassing?: boolean;
    })
  | (SavedViewBase &
      PhysicalDrawingScope & {
        kind: 'section';
        line: {
          start: WorldXZ;
          end: WorldXZ;
        };
        lookSide: 'left' | 'right';
        depth: number;
        verticalCrop: {
          minY: number;
          maxY: number;
        };
      })
  | (SavedViewBase &
      PhysicalDrawingScope & {
        kind: 'elevation';
        origin: WorldXZ;
        lookDirection: WorldXZ;
        crop: {
          left: number;
          right: number;
          bottom: number;
          top: number;
        };
      })
  | (SavedViewBase & {
      kind: 'iso';
      camera: ProjectionCamera & {
        projection_mode: 'Orthographic';
      };
      elementIds?: string[] | 'all';
    });
```

### PaperStyleId

A builtin autocompletes; any other string is a custom (registered) id.

```typescript theme={null}
type PaperStyleId = BuiltinPaperStyleId | (string & {});
```

### PaperStyle

A style, or the overlay a document/sheet/viewport layers on one.

```typescript theme={null}
interface PaperStyle {
  id?: string;
  name?: string;
  extends?: string;
  paper?: {
    color?: string;
    ground?: 'screen' | 'print' | 'both';
  };
  ink?: string;
  ladderStep?: number;
  classes?: Record<string, ClassStyle>;
  edgeClasses?: Record<string, ClassStyle>;
  producerFill?: 'allow' | 'ignore';
  typography?: Typography;
  hand?: HandProfile;
}
```

<ResponseField name="id" type="string" />

<ResponseField name="name" type="string" />

<ResponseField name="extends" type="string">
  The preset this layers on. Resolved depth-first with a cycle guard.
</ResponseField>

<ResponseField
  name="paper"
  type="{
color?: string;
ground?: 'screen' | 'print' | 'both';
}"
/>

<ResponseField name="ink" type="string">
  Default stroke colour for every class.
</ResponseField>

<ResponseField name="ladderStep" type="number">
  Rungs walked on `PEN_LADDER_MM` for every class.
</ResponseField>

<ResponseField name="classes" type="Record<string, ClassStyle>">
  Keyed by `ElementType` (`WALL`, `DOOR`, `SPACECONTAINER`, …).
</ResponseField>

<ResponseField name="edgeClasses" type="Record<string, ClassStyle>">
  Composed on top of the class entry for an HLR edge class (`Hidden`, `VisibleCrease`); the shipped
  `EDGE_CLASS_MODIFIER` is already applied underneath, so these are deltas.
</ResponseField>

<ResponseField name="producerFill" type="'allow' | 'ignore'">
  Whether a producer's explicit `style.fill` reaches the paper. `"allow"` is `resolvePen`'s
  behaviour and the default; presets say `"ignore"`.
</ResponseField>

<ResponseField name="typography" type="Typography" />

<ResponseField name="hand" type="HandProfile">
  Hand-drawn linework. Absent means ruled — every CAD preset.
</ResponseField>

### PaperStyleRegistry

```typescript theme={null}
type PaperStyleRegistry = Record<string, PaperStyle>;
```

### PageSpec

```typescript theme={null}
interface PageSpec {
  format: PageFormat;
  orientation: PageOrientation;
  size: {
    width: number;
    height: number;
  };
  margin: number;
  frame?: SheetFrameOptions;
}
```

<ResponseField name="format" type="PageFormat" required />

<ResponseField name="orientation" type="PageOrientation" required />

<ResponseField
  name="size"
  type="{
width: number;
height: number;
}"
  required
>
  Paper units = millimetres, top-left origin (A4 = 210 × 297).
</ResponseField>

<ResponseField name="margin" type="number" required>
  Uniform inset from every edge. Still the only inset when `frame` is absent, which is what keeps
  existing documents rendering exactly as before.
</ResponseField>

<ResponseField name="frame" type="SheetFrameOptions">
  The printed drawing frame — border, asymmetric filing margin, centring marks and zone grid (ISO
  5457\). Absent means no printed frame, and `margin` alone positions the title block.
</ResponseField>

### Annotation

Sheet annotations, in paper units (mm, top-left origin).

```typescript theme={null}
type Annotation =
  | TextAnnotation
  | DimensionAnnotation
  | MeasureAnnotation
  | AngularMeasureAnnotation
  | RadialMeasureAnnotation
  | LeaderAnnotation
  | ImageAnnotation
  | ShapeAnnotation;
```

### TitleblockInstance

Placement of a title-block template on a sheet, with values bound to the template's named fields (.spec/debt.md "Paper / drawing layer").

```typescript theme={null}
interface TitleblockInstance {
  templateId: string;
  values: Record<string, string>;
}
```

<ResponseField name="templateId" type="string" required />

<ResponseField name="values" type="Record<string, string>" required>
  Values bound by name to the template's fields.
</ResponseField>

### ViewportBase

A live reference into model space, placed on a sheet.

The package does not export this type by name.

```typescript theme={null}
interface ViewportBase {
  representation?: 'vector' | 'raster';
  drawingNumber?: string;
  id: string;
  frame: {
    x: number;
    y: number;
    width: number;
    height: number;
  };
  scale: number;
  scaleId?: string;
  rotationDeg: number;
  clip: boolean;
  viewCenter?: Point2;
  title?: {
    text?: string;
    showScale?: boolean;
  };
  styleId?: PaperStyleId;
  styleOverride?: PaperStyle;
}
```

<ResponseField name="representation" type="'vector' | 'raster'">
  Saved sections/elevations share one view definition across both outputs.
</ResponseField>

<ResponseField name="drawingNumber" type="string">
  Explicit drawing number belonging to this sheet placement.
</ResponseField>

<ResponseField name="id" type="string" required />

<ResponseField
  name="frame"
  type="{
x: number;
y: number;
width: number;
height: number;
}"
  required
>
  Placement rect on the sheet, in paper units (mm, top-left origin).
</ResponseField>

<ResponseField name="scale" type="number" required>
  Dimensionless drawing ratio (paper ÷ real), e.g. 1:50 → 0.02.
</ResponseField>

<ResponseField name="scaleId" type="string">
  Registered scale name (`NamedScale.id`), e.g. "1:50" or "1/4in-1ft".
</ResponseField>

<ResponseField name="rotationDeg" type="number" required />

<ResponseField name="clip" type="boolean" required />

<ResponseField name="viewCenter" type="Point2">
  The model point (metres) placed at the centre of `frame`.
</ResponseField>

<ResponseField
  name="title"
  type="{
text?: string;
showScale?: boolean;
}"
>
  Title drawn beneath the viewport. Absent draws nothing.
</ResponseField>

<ResponseField name="styleId" type="PaperStyleId">
  This viewport's style, outranking the sheet's and the document's — how a 1:20 detail hatches
  differently from the 1:100 plan beside it.
</ResponseField>

<ResponseField name="styleOverride" type="PaperStyle">
  The narrowest overlay: layered over the document's and the sheet's.
</ResponseField>

### ViewSource

What the viewport draws — resolved by the core drawing extractor (§7).

```typescript theme={null}
type ViewSource =
  | {
      kind: 'plan';
      levelId: string;
      cutElevation?: number;
      hideHidden?: boolean;
      entities?: string[] | 'all';
    }
  | {
      kind: 'elevation';
      sectionId: string;
    }
  | {
      kind: 'section';
      sectionId: string;
    }
  | {
      kind: 'iso';
      camera: ProjectionCamera;
    };
```

### SavedRasterIsometricView

Saved rendering intent, independent of generated pixels and sheet placement.

```typescript theme={null}
interface SavedRasterIsometricView {
  id: string;
  name: string;
  kind: 'raster-iso';
  camera: ProjectionCamera & {
    projection_mode: 'Orthographic';
  };
  frame: RasterViewFrame;
  far: number;
  elementIds?: string[] | 'all';
  background: string | null;
}
```

<ResponseField name="id" type="string" required />

<ResponseField name="name" type="string" required />

<ResponseField name="kind" type="'raster-iso'" required />

<ResponseField
  name="camera"
  type="ProjectionCamera & {
projection_mode: 'Orthographic';
}"
  required
/>

<ResponseField name="frame" type="RasterViewFrame" required />

<ResponseField name="far" type="number" required>
  Camera-space clipping distance in metres; must exceed camera.near.
</ResponseField>

<ResponseField name="elementIds" type="string[] | 'all'" />

<ResponseField name="background" type="string | null" required>
  Null means transparent; an opaque background is a #rrggbb colour.
</ResponseField>

### SavedViewBase

The package does not export this type by name.

```typescript theme={null}
interface SavedViewBase {
  id: string;
  name: string;
}
```

### PhysicalDrawingScope

Omitted scope means the entire model; an explicit list never silently drops unsupported IDs.

```typescript theme={null}
interface PhysicalDrawingScope {
  buildingId?: string;
  elementIds?: string[] | 'all';
  settings?: PhysicalDrawingSettings;
}
```

### WorldXZ

World XZ coordinates in metres, written as \[x, z].

The package does not export this type by name.

```typescript theme={null}
type WorldXZ = [number, number];
```

### ProjectionCamera

Projection camera for the extractor.

```typescript theme={null}
type ProjectionCamera = PlanProjectionCamera;
```

### ClassStyle

One element class's treatment.

```typescript theme={null}
interface ClassStyle {
  visible?: boolean;
  weightMm?: number;
  ladderStep?: number;
  ink?: string;
  dash?: number[] | 'none';
  fill?: string | 'none';
  hatch?: string | HatchSpec | 'none';
  cap?: 'butt' | 'round';
  byKind?: Partial<Record<PrimitiveKind, Omit<ClassStyle, 'byKind'>>>;
}
```

<ResponseField name="visible" type="boolean">
  `false` drops the class before projection — it costs nothing downstream.
</ResponseField>

<ResponseField name="weightMm" type="number">
  An explicit lineweight in paper mm. Prefer ladderStep, which keeps the weight a rung on
  `PEN_LADDER_MM`.
</ResponseField>

<ResponseField name="ladderStep" type="number">
  Rungs to walk on `PEN_LADDER_MM`. Steps SUM across the style, the class, its `byKind` entry and
  the edge class.
</ResponseField>

<ResponseField name="ink" type="string">
  Stroke colour, as CSS.
</ResponseField>

<ResponseField name="dash" type="number[] | 'none'">
  Dash runs in paper mm; `"none"` makes the line continuous.
</ResponseField>

<ResponseField name="fill" type="string | 'none'">
  Poché fill for regions; `"none"` removes it.
</ResponseField>

<ResponseField name="hatch" type="string | HatchSpec | 'none'">
  Poché hatch: a key into `HATCH_PATTERNS`, a literal spec, or `"none"`.
</ResponseField>

<ResponseField name="cap" type="'butt' | 'round'" />

<ResponseField name="byKind" type="Partial<Record<PrimitiveKind, Omit<ClassStyle, 'byKind'>>>">
  Per primitive kind, merged over the class entry — how a door's swing (an arc) is drawn lighter
  than its leaf (a line) without a second class.
</ResponseField>

### Typography

```typescript theme={null}
interface Typography {
  fontFamily?: string;
  letterSpacingEm?: number;
  textTransform?: 'none' | 'uppercase';
  scale?: number;
}
```

<ResponseField name="fontFamily" type="string">
  Always terminate the stack in `Helvetica, Arial, sans-serif`: it is one of the PDF standard 14,
  which is what the PDF sets in.
</ResponseField>

<ResponseField name="letterSpacingEm" type="number">
  Tracking, as a fraction of the text height (0.08 = +8 %).
</ResponseField>

<ResponseField name="textTransform" type="'none' | 'uppercase'" />

<ResponseField name="scale" type="number">
  Multiplier on text height. √2 (1.414) is one rung of the ISO 3098 ladder.
</ResponseField>

### HandProfile

The character of hand-drawn linework.

```typescript theme={null}
interface HandProfile {
  salt: number;
  bowAmplitudeMm: number;
  weightRefMm: number;
  fieldLatticeMm: number;
  minLengthMm: number;
  segmentLenMm: number;
  capN: number;
  detail?: {
    amplitudeMm: number;
    latticeMm: number;
  };
  overshootStartMm: number;
  overshootEndMm: number;
  cornerTurnDeg: number;
  crossedProbability: number;
  openGapMinMm: number;
  openGapMaxMm: number;
  strikeTiers: Array<{
    atOrAboveMm: number;
    strikes: number;
  }>;
  restrikeOffsetMm: number;
  restrikeWeightFactor: number;
  restrikeTrimStartMm: number;
  restrikeTrimEndMm: number;
  restrikeWanderMm?: number;
  startBeadMm: number;
  startBeadWidthFactor: number;
  endTaperMm: number;
  endTaperWidthFactor: number;
  weightVariance: number;
  arcCentreOffsetMm: number;
  arcRadiusVar: number;
  arcSweepOverDeg: number;
  arcSweepUnderDeg: number;
  arcRestrikes: number;
  pocheInsetMm: number;
  pocheScribble?: boolean;
  scribbleJitter?: number;
  hatchAngleJitterDeg: number;
  hatchRegionDriftDeg: number;
  hatchSpacingVar: number;
  hatchEndShortMm: number;
  hatchEndOverMm: number;
  textRunRotationDeg: number;
  textBaselineMm: number;
  maxPrimitives: number;
  shedClasses: string[];
  reach?: HandReach;
}
```

<ResponseField name="salt" type="number" required />

<ResponseField name="bowAmplitudeMm" type="number" required>
  Peak displacement of the field, in mm. 0 draws ruled lines.
</ResponseField>

<ResponseField name="weightRefMm" type="number" required>
  The weight the amplitude is quoted at; a stroke's interior samples scale by √(weight /
  weightRefMm), so heavier nibs wander more.
</ResponseField>

<ResponseField name="fieldLatticeMm" type="number" required>
  Cell size of the field. Two faces of a wall a few mm apart sample nearly the same value, so the
  wall keeps its thickness; a long stroke crosses several cells and reads as a shallow S.
</ResponseField>

<ResponseField name="minLengthMm" type="number" required>
  Strokes shorter than this are not subdivided (their ends still follow the field, so they stay
  attached).
</ResponseField>

<ResponseField name="segmentLenMm" type="number" required>
  Sample spacing along a stroke, and the cap on samples per stroke.
</ResponseField>

<ResponseField name="capN" type="number" required />

<ResponseField
  name="detail"
  type="{
amplitudeMm: number;
latticeMm: number;
}"
>
  A second, finer octave of the field laid over the bow — the nervous wander of a fineliner on a
  napkin. Positional like the bow, so shared vertices still agree. Absent means the bow alone;
  `segmentLenMm` must be a fraction of `latticeMm` for the wander to be sampled.
</ResponseField>

<ResponseField name="overshootStartMm" type="number" required>
  Axial overrun past a corner: the start is placed, the finish is a lift.
</ResponseField>

<ResponseField name="overshootEndMm" type="number" required />

<ResponseField name="cornerTurnDeg" type="number" required>
  A turn sharper than this is a corner (pen lifted); shallower is one stroke.
</ResponseField>

<ResponseField name="crossedProbability" type="number" required>
  Share of corners drawn crossed; the rest stop short by an open gap. One decision per corner,
  shared by every stroke that meets there.
</ResponseField>

<ResponseField name="openGapMinMm" type="number" required />

<ResponseField name="openGapMaxMm" type="number" required />

<ResponseField
  name="strikeTiers"
  type="Array<{
atOrAboveMm: number;
strikes: number;
}>"
  required
>
  Strikes by weight band, e.g. `[&#123; atOrAboveMm: 0.35, strikes: 2 &#125;]`.
</ResponseField>

<ResponseField name="restrikeOffsetMm" type="number" required />

<ResponseField name="restrikeWeightFactor" type="number" required />

<ResponseField name="restrikeTrimStartMm" type="number" required />

<ResponseField name="restrikeTrimEndMm" type="number" required />

<ResponseField name="restrikeWanderMm" type="number">
  Each re-strike wanders on its own by this much (mm) instead of tracking the first pass exactly —
  the passes cross and the line goes hairy.
</ResponseField>

<ResponseField name="startBeadMm" type="number" required>
  A short stroke at the start at `startBeadWidthFactor` × weight (a bead when > 1, a ramp when
  \< 1). 0 draws none. Only on strokes long enough to carry one.
</ResponseField>

<ResponseField name="startBeadWidthFactor" type="number" required />

<ResponseField name="endTaperMm" type="number" required>
  A short stroke at the end at `endTaperWidthFactor` × weight. 0 draws none.
</ResponseField>

<ResponseField name="endTaperWidthFactor" type="number" required />

<ResponseField name="weightVariance" type="number" required>
  ± fraction of the nominal weight, one value per emitted stroke.
</ResponseField>

<ResponseField name="arcCentreOffsetMm" type="number" required />

<ResponseField name="arcRadiusVar" type="number" required />

<ResponseField name="arcSweepOverDeg" type="number" required />

<ResponseField name="arcSweepUnderDeg" type="number" required />

<ResponseField name="arcRestrikes" type="number" required>
  Extra arcs at a radial offset — how a pencil re-strikes a swing.
</ResponseField>

<ResponseField name="pocheInsetMm" type="number" required>
  Pull the fill in from the outline by this much: the sliver of paper an inked poché leaves against
  its line. 0 fills to the line.
</ResponseField>

<ResponseField name="pocheScribble" type="boolean">
  Draw the hatch as continuous back-and-forth zigzags across each region — a scribbled poché, ONE
  stroke per run, laid across the region's long axis the way a hand scribbles a wall band — instead
  of separate parallel lines.
</ResponseField>

<ResponseField name="scribbleJitter" type="number">
  Per-vertex jitter of a scribble's pitch and tilt, as a fraction of the spacing — what keeps a
  scribble from reading as ruled hatching.
</ResponseField>

<ResponseField name="hatchAngleJitterDeg" type="number" required>
  Per-line angle jitter, and one drift per region, both in degrees.
</ResponseField>

<ResponseField name="hatchRegionDriftDeg" type="number" required />

<ResponseField name="hatchSpacingVar" type="number" required>
  ± fraction of the spacing, one value per region (so lines stay in register within a region).
</ResponseField>

<ResponseField name="hatchEndShortMm" type="number" required>
  Each hatch line ends between `-short` and `+over` of the boundary.
</ResponseField>

<ResponseField name="hatchEndOverMm" type="number" required />

<ResponseField name="textRunRotationDeg" type="number" required />

<ResponseField name="textBaselineMm" type="number" required />

<ResponseField name="maxPrimitives" type="number" required>
  When the predicted output would exceed this, `shedClasses` are dropped BEFORE synthesis — a
  decision about what is on the sheet, never about where a primitive sits in the array.
</ResponseField>

<ResponseField name="shedClasses" type="string[]" required />

<ResponseField name="reach" type="HandReach">
  How far the hand reaches beyond the building. By default only viewport geometry is redrawn:
  dimensions, the frame and the title block stay ruled, because a drawing that wobbles its
  dimensions is a presentation, not an issue. A napkin sketch is exactly that presentation, and asks
  for all three.
</ResponseField>

### SheetFrameOptions

What a document may say about its frame.

```typescript theme={null}
interface SheetFrameOptions {
  border?: boolean;
  zones?: boolean;
  centringMarks?: boolean;
  margins?: Partial<SheetMargins>;
  bindingEdge?: 'left' | 'top';
}
```

<ResponseField name="border" type="boolean">
  Draw the border rectangle. Default true once `frame` is present at all.
</ResponseField>

<ResponseField name="zones" type="boolean">
  Zone reference grid. Default: on for A3-equivalent and larger.
</ResponseField>

<ResponseField name="centringMarks" type="boolean">
  Centring marks at the middle of each edge. Default true.
</ResponseField>

<ResponseField name="margins" type="Partial<SheetMargins>">
  Override any of the four margins.
</ResponseField>

<ResponseField name="bindingEdge" type="&#x22;left&#x22; | &#x22;top&#x22;">
  Which edge gets the wide filing margin. Default "left".
</ResponseField>

### TextAnnotation

```typescript theme={null}
interface TextAnnotation {
  id: string;
  kind: 'text';
  text: string;
  position: Point2;
  fontSize: number;
  fontFamily?: string;
  color?: string;
  align?: 'left' | 'center' | 'right';
  rotationDeg?: number;
}
```

### DimensionAnnotation

The package does not export this type by name.

```typescript theme={null}
interface DimensionAnnotation {
  id: string;
  kind: 'dimension';
  styleId?: string;
  start: Point2;
  end: Point2;
  offset: number;
  label?: string;
  fontSize: number;
}
```

<ResponseField name="id" type="string" required />

<ResponseField name="kind" type="&#x22;dimension&#x22;" required />

<ResponseField name="styleId" type="string">
  Named style in `PaperDocument.dimensionStyles`. Absent uses the default.
</ResponseField>

<ResponseField name="start" type="Point2" required />

<ResponseField name="end" type="Point2" required />

<ResponseField name="offset" type="number" required>
  Perpendicular offset of the dimension line from the start→end segment.
</ResponseField>

<ResponseField name="label" type="string" />

<ResponseField name="fontSize" type="number" required />

### LeaderAnnotation

The package does not export this type by name.

```typescript theme={null}
interface LeaderAnnotation {
  id: string;
  kind: 'leader';
  styleId?: string;
  target: Point2;
  points: Point2[];
  text: string;
  fontSize: number;
}
```

<ResponseField name="id" type="string" required />

<ResponseField name="kind" type="&#x22;leader&#x22;" required />

<ResponseField name="styleId" type="string">
  Named style in `PaperDocument.dimensionStyles`. Absent uses the default.
</ResponseField>

<ResponseField name="target" type="Point2" required>
  Arrow tip — points at the thing being annotated.
</ResponseField>

<ResponseField name="points" type="Point2[]" required>
  Knee points from the target to the text anchor (last point).
</ResponseField>

<ResponseField name="text" type="string" required />

<ResponseField name="fontSize" type="number" required />

### ImageAnnotation

The package does not export this type by name.

```typescript theme={null}
interface ImageAnnotation {
  id: string;
  kind: 'image';
  src: string;
  rect: {
    x: number;
    y: number;
    width: number;
    height: number;
  };
}
```

<ResponseField name="id" type="string" required />

<ResponseField name="kind" type="&#x22;image&#x22;" required />

<ResponseField name="src" type="string" required>
  Data URL or remote URL; emitters must not require a DOM canvas.
</ResponseField>

<ResponseField
  name="rect"
  type="{
x: number;
y: number;
width: number;
height: number;
}"
  required
/>

### ShapeAnnotation

The package does not export this type by name.

```typescript theme={null}
interface ShapeAnnotation {
  id: string;
  kind: 'shape';
  shape: ShapeKind;
  points: Point2[];
  radius?: number;
  stroke?: string;
  strokeWidth?: number;
  fill?: string;
}
```

<ResponseField name="id" type="string" required />

<ResponseField name="kind" type="&#x22;shape&#x22;" required />

<ResponseField name="shape" type="ShapeKind" required />

<ResponseField name="points" type="Point2[]" required>
  line/polyline: vertices. rect: \[topLeft, bottomRight]. circle: \[center].
</ResponseField>

<ResponseField name="radius" type="number">
  Required for `shape: 'circle'`.
</ResponseField>

<ResponseField name="stroke" type="string" />

<ResponseField name="strokeWidth" type="number" />

<ResponseField name="fill" type="string" />

### PhysicalDrawingSettings

Shared appearance for technical vectors and raster presentation of one saved view.

```typescript theme={null}
interface PhysicalDrawingSettings {
  context?: 'visible' | 'cut-only';
  hiddenLines?: boolean;
  background?: string | null;
  levelLabels?: {
    datum: number;
    unit: 'm' | 'ft';
  };
}
```

<ResponseField name="context" type="'visible' | 'cut-only'">
  Absent means actual cut plus visible context; cut-only applies to sections.
</ResponseField>

<ResponseField name="hiddenLines" type="boolean">
  Absent means hidden lines are omitted from technical vectors.
</ResponseField>

<ResponseField name="background" type="string | null">
  Raster background. Absent means white; null means transparent.
</ResponseField>

<ResponseField
  name="levelLabels"
  type="{
datum: number;
unit: 'm' | 'ft';
}"
>
  Authored storey elevations, relative to this world-height datum in metres.
</ResponseField>

### HandReach

The sheet furniture a hand profile may redraw, besides the building.

```typescript theme={null}
interface HandReach {
  annotations?: boolean;
  frame?: boolean;
  titleblock?: boolean;
}
```

<ResponseField name="annotations" type="boolean">
  Dimension, leader and view-title lines, and un-coloured shape annotations. Labels keep their
  measured value; authored colours (a redline) stay ruled.
</ResponseField>

<ResponseField name="frame" type="boolean">
  The drawing frame: border, zone ticks, centring marks.
</ResponseField>

<ResponseField name="titleblock" type="boolean">
  The title block's boxes and rules (a filled box stays ruled).
</ResponseField>

### ShapeKind

The package does not export this type by name.

```typescript theme={null}
type ShapeKind = 'line' | 'polyline' | 'rect' | 'circle';
```

## Related

* [`AngularMeasureAnnotation`](/floorkit/api/annotations/dimension-geometry#angularmeasureannotation)
* [`BuiltinPaperStyleId`](/floorkit/api/drawings/paper-styles#builtinpaperstyleid)
* [`DimensionStyleRegistry`](/floorkit/api/annotations/dimension-styles#dimensionstyleregistry)
* [`HatchSpec`](/floorkit/api/drawings/pens-and-hatches#hatchspec)
* [`MeasureAnnotation`](/floorkit/api/annotations/dimension-strings#measureannotation)
* [`PageFormat`](/floorkit/api/drawings/page-sizes-and-frames#pageformat)
* [`PageOrientation`](/floorkit/api/drawings/page-sizes-and-frames#pageorientation)
* [`PlanProjectionCamera`](/floorkit/api/drawings/drawing-helpers#planprojectioncamera)
* [`Point2`](/floorkit/api/annotations/dimension-geometry#point2)
* [`PrimitiveKind`](/floorkit/api/drawings/pens-and-hatches#primitivekind)
* [`RadialMeasureAnnotation`](/floorkit/api/annotations/dimension-geometry#radialmeasureannotation)
* [`RasterViewFrame`](/floorkit/api/views/raster-capture#rasterviewframe)
* [`SheetMargins`](/floorkit/api/drawings/page-sizes-and-frames#sheetmargins)
* [`UnitSystem`](/floorkit/api/annotations/dimension-geometry#unitsystem)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.