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

@sunaissu/noteboard

v1.2.1

Published

A highly customizable, responsive React whiteboard canvas for drawing, diagramming, and real-time collaboration.

Readme

@sunaissu/noteboard

A highly customizable, responsive React whiteboard canvas for drawing, diagramming, and real-time collaboration.

npm version license


🚀 Features

  • Rich Toolset — Draw shapes (rectangles, ellipses, diamonds, triangles, stars/polygons), lines, auto-connecting arrows, text, freehand pen, and images.
  • Advanced Elements — Built-in support for Sticky Notes, Callouts, and Frames.
  • Connector Snapping — Arrows and lines snap their endpoints to shape anchor points (edges, corners, center) when drawn near them. A purple ring highlights the snap target.
  • Smart Grouping & Locking — Group shapes, lock elements in place, and control z-order.
  • Collapsible Properties Panel — The entire panel can be collapsed to a thin header bar. Individual property sections (Appearance, Drop Shadow, Text, Line/Arrow, Pen, Shape, Frame) also collapse independently via chevron toggles.
  • Snap-to-Grid & Alignment Guides — Dot-grid overlay, snap-to-grid, and smart alignment tools for precise layouts.
  • Undo / Redo Toolbar Buttons — ↩ / ↪ buttons surface the full undo/redo history directly in the toolbar strip.
  • Right-Click Context Menu — Copy, Paste, Duplicate, Bring Forward / Send Backward, Bring to Front / Send to Back, Select All, and Delete — all accessible via right-click anywhere on the canvas.
  • Keyboard Shortcut Cheatsheet — Press ? (or the ? button in the ☰ menu) to open a modal listing every keyboard shortcut organized by category.
  • Board Management — Export as PNG/JPEG, import/export state as JSON, toggle grid visibility, and clear the canvas with a confirmation prompt.
  • Dark Mode Support — Default light/dark themes with full custom NoteboardTheme override support.
  • Focus Ring — The canvas shows a visible purple focus ring when it receives keyboard focus, aiding accessibility.
  • Read-Only Mode — Lock the board to view-only with a single prop or toggle.
  • Multiplayer Ready — Completely server-agnostic. Integrates with WebSockets or CRDTs via controlled elements + onElementsChange props.
  • Lightweight PreviewsNoteboardPreview renders a static, zero-interaction board thumbnail using the same rendering engine.

📦 Installation

npm install @sunaissu/noteboard @phosphor-icons/react
# or
yarn add @sunaissu/noteboard @phosphor-icons/react
# or
pnpm add @sunaissu/noteboard @phosphor-icons/react

@phosphor-icons/react is a required peer dependency for toolbar and panel icons.


💻 Quick Start

import React, { useState } from 'react';
import { Noteboard } from '@sunaissu/noteboard';
import type { NoteboardElement } from '@sunaissu/noteboard';

export default function App() {
  const [elements, setElements] = useState<NoteboardElement[]>([]);

  return (
    <div style={{ width: '100vw', height: '100vh' }}>
      <Noteboard
        elements={elements}
        onElementsChange={setElements}
        defaultTheme="dark"
      />
    </div>
  );
}

🛠 Props API

| Prop | Type | Default | Description | |---|---|---|---| | theme | 'light' \| 'dark' \| NoteboardTheme | 'dark' | Active theme. Pass a custom NoteboardTheme object to override individual colors. | | defaultTheme | 'light' \| 'dark' | 'dark' | Sets the initial theme before the user toggles. | | initialElements | NoteboardElement[] | [] | Seed elements on first mount. Uncontrolled — ignored after mount. | | initialViewport | NoteboardViewport | undefined | Seed pan & zoom on first mount (e.g. from a saved NoteboardSession). | | elements | NoteboardElement[] | undefined | Fully controlled elements array. Use alongside onElementsChange for real-time collaboration. | | onElementsChange | (elements: NoteboardElement[]) => void | undefined | Fires after every local draw, edit, move, or delete. | | onViewportChange | (viewport: NoteboardViewport) => void | undefined | Fires whenever the user pans or zooms. Use to persist or broadcast the viewport. | | readOnly | boolean | undefined | Controlled read-only mode — hides the toolbar, disables all editing interactions. | | defaultReadOnly | boolean | false | Initial read-only state (uncontrolled). | | onReadOnlyChange | (readOnly: boolean) => void | undefined | Fires when the user toggles read-only mode from the ☰ menu. | | toolbarPosition | 'top' \| 'bottom' \| 'left' \| 'right' | 'bottom' | Position of the main toolbar. | | propertiesPosition | 'top' \| 'bottom' \| 'left' \| 'right' | 'left' | Position of the properties panel. | | slots | ToolSlot[] | DEFAULT_SLOTS | Customize which tools appear in the toolbar and their order. | | activeTool | Tool | undefined | Controlled active tool. | | onToolSelect | (tool: Tool) => void | undefined | Fires when the user switches tools. | | onSave | (session: NoteboardSession) => void | undefined | Adds a Save button to the ☰ menu. Called with a full serialized snapshot. | | threadId | string | undefined | Identifies the room/thread (used with collaboration integrations). | | boardId | string | undefined | Identifies the board instance. |


🔧 Imperative API (ref)

Pass a ref to access the board imperatively:

import { useRef } from 'react';
import { Noteboard } from '@sunaissu/noteboard';
import type { NoteboardRef } from '@sunaissu/noteboard';

function App() {
  const ref = useRef<NoteboardRef>(null);

  return (
    <>
      <Noteboard ref={ref} />
      <button onClick={() => console.log(ref.current?.getElements())}>Log elements</button>
      <button onClick={() => ref.current?.setElements([])}>Clear board</button>
      <button onClick={() => {
        const url = ref.current?.exportImage('png');
        window.open(url);
      }}>Export PNG</button>
    </>
  );
}

| Method | Signature | Description | |---|---|---| | getElements() | () => NoteboardElement[] | Returns the current live elements array. | | setElements() | (elements: NoteboardElement[]) => void | Imperatively replaces the board elements. | | getSession() | () => NoteboardSession | Returns a full DB-ready board snapshot. | | exportImage() | (format?: 'png' \| 'jpeg') => string | Returns the canvas as a data URL. |


📡 Viewport Sync (onViewportChange)

Use onViewportChange to track pan & zoom externally — useful for persisting the viewport or syncing it across clients:

import { useState } from 'react';
import { Noteboard } from '@sunaissu/noteboard';
import type { NoteboardViewport } from '@sunaissu/noteboard';

function App() {
  const [viewport, setViewport] = useState<NoteboardViewport>({ panX: 0, panY: 0, zoom: 1 });

  return (
    <>
      <p>Zoom: {Math.round(viewport.zoom * 100)}%</p>
      <Noteboard onViewportChange={setViewport} />
    </>
  );
}

🤝 Multiplayer & Collaboration

Noteboard is server-agnostic. Pass elements directly from your server state and broadcast updates via onElementsChange:

import { Noteboard } from '@sunaissu/noteboard';
import { useWebSocket } from './your-websocket-hook';

export function MultiplayerBoard() {
  const { elements, sendUpdate } = useWebSocket('wss://your-server.com/room');

  return (
    <Noteboard
      elements={elements}
      onElementsChange={(newElements) => {
        sendUpdate(newElements); // Broadcast local changes to the server
      }}
    />
  );
}

🖼️ Lightweight Previews

Use NoteboardPreview to render a read-only, static snapshot without mounting the full interactive canvas:

import { NoteboardPreview } from '@sunaissu/noteboard';
import type { NoteboardElement } from '@sunaissu/noteboard';

export function DashboardCard({ elements }: { elements: NoteboardElement[] }) {
  return (
    <div className="card">
      <h3>My Board</h3>
      <NoteboardPreview
        elements={elements}
        height={120}
        style={{ borderRadius: '6px', border: '1px solid #ddd' }}
      />
    </div>
  );
}

⌨️ Keyboard Shortcuts

| Shortcut | Action | |---|---| | Ctrl + Z | Undo | | Ctrl + Shift + Z | Redo | | Ctrl + C | Copy selected | | Ctrl + V | Paste | | Ctrl + D | Duplicate selected | | Ctrl + A | Select all | | Ctrl + G | Group selected | | Ctrl + Shift + G | Ungroup | | Delete | Delete selected | | Escape | Deselect / finish text edit | | ] / [ | Bring forward / send backward | | Ctrl + ] / Ctrl + [ | Bring to front / send to back | | Ctrl + Scroll | Zoom in / out | | Scroll | Pan canvas | | G | Toggle grid & snap | | ? | Open keyboard shortcut cheatsheet |

Press ? inside the board at any time to see the full cheatsheet modal.


📋 Changelog

See CHANGELOG.md for a full list of changes across versions.


📜 License

MIT License. See LICENSE for details.