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

@veyrajs/core

v0.1.2

Published

Framework-agnostic 2D canvas engine: scene graph, renderer abstraction, camera, events, hit-testing, transforms, controls, serialization, and plugin system.

Readme

@veyrajs/core

npm version license types

A framework-agnostic, TypeScript-first 2D canvas engine — a typed, mutable retained-mode scene graph with a renderer abstraction, camera, federated events, geometric hit-testing, transform controls, versioned serialization, and a day-one command/undo layer.

Use it imperatively, or declaratively through the first-class Vue, React, Svelte, and Angular adapters.

Zero runtime dependencies. The math and geometry are written in-house.


Installation

npm install @veyrajs/core
# or
pnpm add @veyrajs/core
# or
yarn add @veyrajs/core

Quick start

Build a scene with shapes, events, zoom, selection, and undo — in a few lines:

import {
  Stage,
  Layer,
  Rect,
  Circle,
  Vec2,
  History,
  SelectionController,
} from '@veyrajs/core'

// 1. Create a stage bound to a DOM element (DPR-correct canvas under the hood).
const stage = new Stage({
  container: document.querySelector('#app')!,
  width: 800,
  height: 480,
})

// 2. Add a layer, then shapes.
const layer = new Layer()
stage.add(layer)

const rect = new Rect({ x: 40, y: 40, width: 150, height: 90, fill: '#38bdf8' })
layer.add(rect)
layer.add(new Circle({ x: 300, y: 100, radius: 50, fill: '#f472b6' }))

// 3. Mutate properties directly — the engine re-renders on the next frame.
rect.x = 60

// 4. Listen to federated (DOM-style) events.
rect.on('click', () => { rect.x += 20 })

// 5. Camera: zoom about a point, pan, screen ↔ world conversion.
stage.camera.zoomAt(new Vec2(300, 100), 1.2)

// 6. Selection + transform handles + undo/redo, day one.
const history = new History()
const controller = new SelectionController(stage, { history })
// ...user drags a resize handle...
history.undo()
history.redo()

Save & load a scene

Scenes round-trip through versioned JSON, so a document saved today survives future schema changes via registered migrations:

import { SceneSerializer } from '@veyrajs/core'

const serializer = new SceneSerializer()

const json = serializer.toObject(stage)   // → plain, versioned SceneDocument
localStorage.setItem('scene', JSON.stringify(json))

// later…
serializer.fromObject(stage, JSON.parse(localStorage.getItem('scene')!))

Features

  • Typed mutable scene graphStage → Layer → Group/Shape → Node. Real classes you mutate (rect.x = 10) with guarded setters, lazy version-counted world transforms, and typed config objects instead of a stringly-typed attribute bag.
  • Renderer abstraction — nodes emit backend-neutral DrawOp[]; Canvas2DRenderer is the default backend, but no node ever touches a raw 2D context — a WebGL/WebGPU/ Offscreen seam is reserved.
  • Camera & coordinate spaces — explicit screen / world / local spaces via one affine Matrix. Zoom-about-cursor, pan, and a single devicePixelRatio source of truth.
  • Federated events — DOM-style capture → target → bubble with stopPropagation, plus derived click / dblclick / dragstart|move|end / pointerenter|leave / wheel.
  • Geometric hit-testing — reverse-z traversal with a world-AABB prefilter, per-shape containsPoint, and zoom-invariant tolerance (a "5px grab" stays 5px at any zoom).
  • Selection & controlsSelectionManager (single + multi) and a data-driven SelectionController: bounds box, resize handles, rotation, custom cursors. Drags emit undoable commands.
  • Versioned serializationtoObject / fromObject round-trips through a ClassRegistry, with a schema version and a MigrationRunner.
  • Command / undo from day one — every meaningful mutation is a reversible, serializable Command; History gives undo/redo.

Shapes

Rect, Circle, Ellipse, Line, Polygon, Text, Image — each is geometry expressed as DrawOp[] plus a per-shape containsPoint. Add your own by extending Shape and registering it with the ClassRegistry.

API at a glance

| Subsystem | Key exports | | --- | --- | | Math | Vec2, Matrix, Bounds, pointInPolygon, distanceToSegment | | Scene graph | Stage, Layer, Group, Container, Shape, Node | | Shapes | Rect, Circle, Ellipse, Line, Polygon, Text, Image | | Rendering | Canvas2DRenderer, FrameScheduler, DrawOp | | Camera | Camera (zoomAt, screenToWorld, worldToScreen) | | Events | EventManager, SceneEvent, dispatchEvent | | Hit testing | GeometricHitTester (HitTester interface) | | Selection | SelectionManager, SelectionController, DEFAULT_CONTROLS | | Serialization | SceneSerializer, ClassRegistry, MigrationRunner | | Commands | History, SetPropsCommand, AddNodeCommand, RemoveNodeCommand, CompositeCommand |

Conventions

  • Top-left origin, y-down, rotation in degrees clockwise.
  • Scale target: one large image + hundreds of vector shapes at 60fps.
  • Every mutation is a reversible, serializable command (undo/redo day 1).

Using a framework?

Reach for a declarative adapter — same engine, idiomatic components, with an escape hatch back to the underlying node whenever you need it:

| Framework | Package | | --- | --- | | Vue 3 | @veyrajs/vue | | React | @veyrajs/react | | Svelte 5 | @veyrajs/svelte | | Angular 18 | @veyrajs/angular |

Documentation

📖 Full documentation & live demos: https://veyrajs.github.io/Veyrajs/

The docs site (Astro + Starlight) has guides, concept pages (scene graph, camera, events, hit-testing, serialization…), an interactive Examples gallery, and copy-paste recipes (pan & zoom, free drawing, snapping guides, export to PNG, save/load, and more). Source on GitHub.

Requirements

  • Any modern browser with Canvas 2D.
  • TypeScript types ship with the package — no @types needed.

License

MIT © Veyrajs