npm package: @robinweitzel/floor-planner
Description: Interactive 2D floor-plan editor — draw walls, place doors/windows and furniture on an HTML Canvas
Author: RobinWeitzel
Latest version: 1.1.0

# floor-planner

Interactive 2D floor-plan editor — draw walls, place doors/windows and furniture on an HTML Canvas.

## Install

```bash
npm install floor-planner
```

## Quick start

```ts
import { FloorPlanner } from 'floor-planner';

// 1. Create
const planner = new FloorPlanner(document.getElementById('editor')!, {
  mode: 'edit',
  snap: { grid: true, endpoint: true, gridSize: 10 },
  selectableTypes: ['sofa'],
});

// 2. Register furniture types before placing them
planner.registerFurniture({
  id: 'sofa', label: 'Sofa', shape: 'rectangle',
  defaultWidth: 80, defaultHeight: 35,
});

// 3. Activate a tool
planner.setTool('furniture', { typeId: 'sofa' });

// 4. Listen for events
planner.on('change', ({ plan }) => saveToServer(plan));

// 5. Serialize / restore
const data = planner.toJSON();
planner.loadJSON(data);

// 6. Clean up
planner.destroy();
```

## API

### `new FloorPlanner(container, options?)`

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `mode` | `'edit' \| 'view'` | `'edit'` | Initial interaction mode |
| `snap.grid` | `boolean` | `true` | Snap to grid |
| `snap.endpoint` | `boolean` | `true` | Snap to wall endpoints |
| `snap.gridSize` | `number` | `10` | Grid cell size in px |
| `selectableTypes` | `string[]` | `[]` | Furniture type IDs selectable in view mode |
| `maxHistoryDepth` | `number` | `50` | Undo stack limit |
| `shortcuts` | `ShortcutMap` | *(see below)* | Override or disable keyboard shortcuts |

### Methods

| Method | Description |
|--------|-------------|
| `registerFurniture(config)` | Register a furniture type so it can be placed on the plan |
| `setMode(mode)` | Switch between `'edit'` and `'view'` modes |
| `setTool(tool, options?)` | Activate a drawing/editing tool (see below) |
| `toJSON()` | Serialize the floor plan to a plain object |
| `loadJSON(data)` | Replace the floor plan with previously serialized data (clears undo) |
| `on(event, handler)` | Subscribe to an event; returns an unsubscribe function |
| `undo()` | Undo the last change |
| `redo()` | Redo the last undone change |
| `deleteSelected()` | Delete the currently selected item |
| `flipDoorDirection()` | Flip the swing direction of the selected door |
| `zoomToFit()` | Pan and zoom the viewport to fit all content |
| `destroy()` | Remove listeners, stop render loop, disconnect observers |

### `setTool(tool, options?)`

| Tool | Options | Description |
|------|---------|-------------|
| `'select'` | — | Select, move, resize, and rotate items |
| `'wall'` | — | Draw walls by clicking start and end points |
| `'furniture'` | `{ typeId: string }` | Place a registered furniture type |
| `'opening'` | `{ type: 'door' \| 'window' }` | Place a door or window on a wall |

### `registerFurniture(config)`

```ts
interface FurnitureTypeConfig {
  id: string;           // unique type identifier
  label: string;        // display name
  shape: 'rectangle' | 'circle' | 'ellipse';
  defaultWidth: number;
  defaultHeight: number;
}
```

## Events

| Event | Payload | Fired when |
|-------|---------|------------|
| `'select'` | `{ item: FurnitureItemData \| null }` | Item selected/deselected in view mode |
| `'change'` | `{ plan: FloorPlanData }` | Any mutation (wall drawn, furniture moved, etc.) |
| `'tool:complete'` | `{ tool: ToolType; result: unknown }` | A tool finishes an operation |

## Keyboard shortcuts

Default shortcuts (all configurable via `options.shortcuts`):

| Action | Default key | Description |
|--------|-------------|-------------|
| `undo` | `Ctrl/Cmd+Z` | Undo the last change |
| `redo` | `Ctrl/Cmd+Shift+Z` | Redo the last undone change |
| `delete` | `Delete` / `Backspace` | Remove the selected item |
| `flipDirection` | `F` | Flip door swing direction |
| `escape` | `Escape` | Cancel the current wall chain |

### Customizing shortcuts

```ts
const planner = new FloorPlanner(container, {
  shortcuts: {
    delete: { key: 'x' },              // rebind delete to 'x'
    flipDirection: false,               // disable flip shortcut
    undo: { key: 'z', ctrlOrCmd: true }, // keep default (or customize)
  },
});
```

Set any action to `false` to disable it. Omitted actions keep their defaults.
You can also call actions programmatically:

```ts
planner.deleteSelected();
planner.flipDoorDirection();
```

## Types

All public types are exported from the package entry point:

```ts
import type {
  FloorPlannerOptions,
  FloorPlannerMode,
  ToolType,
  FloorPlanData,
  FurnitureTypeConfig,
  FurnitureItemData,
  WallData,
  OpeningData,
  FloorPlannerEventMap,
  SnapOptions,
  ShortcutMap,
  KeyBinding,
  Point,
  Rect,
} from 'floor-planner';
```

## Per-item selectability

In view mode, items are selectable if their `typeId` is in `selectableTypes`. You can also override this per-item by setting `selectable: true | false` in the item's data:

```ts
planner.loadJSON({
  version: 1,
  walls: [],
  openings: [],
  furniture: [
    { id: '1', typeId: 'sofa', x: 100, y: 100, rotation: 0,
      width: 80, height: 35, selectable: true },
  ],
});
```

## License

ISC