npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@robinweitzel/floor-planner

v1.1.0

Published

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

Readme

floor-planner

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

Install

npm install floor-planner

Quick start

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)

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

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:

planner.deleteSelected();
planner.flipDoorDirection();

Types

All public types are exported from the package entry point:

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:

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