# Stencil Kit

Import these from `@grafloria/element`.

## Functions

### `bindShapeDataPanel`

Bind a shape-data panel into `host`. It follows the diagram's selection:
nodes, edges and multi-selections each get their own sections; nothing
selected shows the empty message.

```ts
function bindShapeDataPanel(
  api: ShapeDataPanelApi,
  host: HTMLElement,
  options: ShapeDataPanelOptions = {}
): ShapeDataPanelHandle
```

### `bindStencilPalette`

Build a stencil palette in `palette` that drops masters onto `canvas`.

```ts
function bindStencilPalette(
  api: StencilPaletteApi,
  hosts: { palette: HTMLElement; canvas: HTMLElement },
  options: StencilPaletteOptions = {}
): StencilPaletteHandle
```

**Parameters**

- `api`: the diagram instance (engine + model + viewport)
- `hosts`: `palette`: where the list renders · `canvas`: the drop target (the element the diagram is mounted in)

### `ensureStencilKitStyles`

Inject the palette stylesheet once per document.

```ts
function ensureStencilKitStyles(doc: Document = document): void
```

## Interfaces

### `ShapeDataPanelApi`

What the panel needs from a diagram: its engine (every edit runs as an
undoable command), its model (the selection), and a subscription to
selection changes that returns its unsubscribe function. A
`DiagramInstance` is all of this, so pass the instance itself.

```ts
interface ShapeDataPanelApi
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `getEngine` | `() => DiagramEngine` |  |  |
| `getModel` | `() => DiagramModel` |  |  |
| `on` | `( event: 'selection:change', handler: (change: DiagramEventMap['selection:change']) => void ) => () => void` |  |  |

### `ShapeDataPanelHandle`

```ts
interface ShapeDataPanelHandle
```

**Members**

- `refresh(): void` — Re-read the selection and rebuild the fields.
- `destroy(): void`

### `ShapeDataPanelOptions`

```ts
interface ShapeDataPanelOptions
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `title?` | `string` |  | Heading above the fields (default "Shape data"). |
| `emptyText?` | `string` |  | Shown when nothing (or more than one thing) is selected. |
| `onEdit?` | `(info: { nodeId: string; key: string; value: unknown }) => void` |  | Called after an edit commits. |

### `StencilPaletteApi`

What the palette needs from a diagram: its engine (a drop runs as one
undoable command), its model, and the viewport that turns the drop point
into world coordinates. A `DiagramInstance` is all of this, so pass the
instance itself.

```ts
interface StencilPaletteApi
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `getEngine` | `() => DiagramEngine` |  |  |
| `getModel` | `() => DiagramModel` |  |  |
| `viewport` | `{ clientToWorld( x: number, y: number, rect: { left: number; top: number; width: number; height: number } ): { x: number; y: number }; }` |  |  |

### `StencilPaletteHandle`

```ts
interface StencilPaletteHandle
```

**Members**

- `setSearch(query: string): void` — Filter the list programmatically (same as typing in the search box).
- `place(masterId: string, world: { x: number; y: number }): Promise<string | null>` — Place a master at a WORLD point without dragging (keyboard / test path).
- `destroy(): void` — Remove listeners and the palette DOM.

### `StencilPaletteOptions`

```ts
interface StencilPaletteOptions
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `stencils?` | `Stencil[]` |  | Sections to show (default: every built-in stencil). |
| `search?` | `boolean` |  | Show the search box (default true). |
| `collapsed?` | `string[]` |  | Stencil ids to render collapsed initially (default: all but the first). |
| `data?` | `(master: NodeTemplate) => Record<string, unknown>` |  | Data merged into every placed master (e.g. a default label). |
| `onPlace?` | `(info: { master: NodeTemplate; nodeId: string; x: number; y: number }) => void` |  | Called after a master is placed on the canvas. |
| `notationTheme?` | `Record<string, { fill?: string; stroke?: string }>` |  | Restyle the shapes per stencil WITHOUT editing any master — the seam that makes stencil colour a host/theme decision instead of baked template data. Keyed by stencil id (`flowchart`, `bpmn`, `uml`, `erd`); each entry overrides the master's own `fill` / `stroke`. Pass `'theme'` for a value to take it from the live theme instead of a literal. |
| `htmlLayer?` | `boolean` |  | Opt a placed master INTO `useHTMLLayer`. Only set this when the host really runs an HTML layer that paints `node.data._html` — with the plain SVG renderer the flag makes the node render as an empty group. |
