# ShapeDefinition

Import it from `@grafloria/renderer`.

The single geometry contract every node shape implements. Register once via
{@link registerShape} and the shape works across body, selection, shadow,
smart-connection boundary and port positioning — no switch edits required.

```ts
interface ShapeDefinition
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `type` | `string` |  |  |
| `styleMode?` | `'inline' \| 'spread'` |  | How the node body applies node styles. Defaults to 'inline'. |
| `bodyStripKeys?` | `string[]` |  | Style keys dropped from the body's pass-through props (circle: rx, ry). |
| `bodyDeferGeomKeys?` | `string[]` |  | Geometry keys emitted AFTER the pass-through props in the body, so an explicit value overrides one arriving via the styles object. rect defers rx/ry so an explicit cornerRadius wins over a themed borderRadius. |

**Members**

- `outline(width: number, height: number, transform?: OutlineTransform): OutlineSpec` — Outline geometry under a transform (drives body + selection + shadow).
- `boundaryPoint(rect: ShapeRect, side: ShapeSide, cross: number): ShapePoint | null` — Point on the outline for a floating smart-connection attachment on `side`
at cross-axis coordinate `cross` (world coords). Return null to fall back
to the bounding-box edge (rect and unknown shapes do this).
- `portAnchor( width: number, height: number, side: ShapeSide, rank: number, count: number ): ShapePoint` — Local-space port anchor on `side` for port `rank` of `count` on that side.
- `innerRect?(width: number, height: number): InnerRect` — The label box in local coords (0,0 = top-left). Used by the node label
engine to wrap, clip and ellipsis-truncate text inside the silhouette. Optional — omit to accept the padded-bbox default ({@link defaultInnerRect}).
