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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@whittakertech/mosaic

v0.1.0

Published

Event-driven, deterministic drag-and-drop engine with constraint validation and rollback

Readme

MosaicJS

npm coverage license
An event-driven, snapshot-based drag-and-drop engine for the modern web.

MosaicJS is a lightweight, framework-agnostic TypeScript library for building precise, reversible, constraint-aware drag-and-drop interactions in the browser.

It belongs to the WhittakerTech ecosystem, but works anywhere the DOM exists — including vanilla JS, React, Vue, and Web Components.

MosaicJS favors correctness, determinism, and reversibility over implicit DOM mutation.


Why MosaicJS?

Most drag-and-drop libraries focus on visual movement first and treat correctness as an afterthought.
MosaicJS inverts that model.

MosaicJS is built around guarantees:

  • Every drag begins with a DOM snapshot
  • Every drop is validated by constraints
  • Invalid operations automatically roll back
  • All state transitions are explicit, deterministic, and observable

If you care about:

  • Undo / rollback safety
  • Predictable state transitions
  • Auditable drag behavior
  • Complex rules that go beyond “can I drop here?”

MosaicJS is designed for you.


Features

  • Snapshot + rollback system
  • Constraint-driven validation
  • Deterministic state machine
  • Unified event API
  • 100% test coverage
  • Framework-agnostic (DOM, React, Vue, Web Components)

Installation

npm install @whittakertech/mosaic

Quick Start

import { Mosaic } from "@whittakertech/mosaic";

const mosaic = new Mosaic({
  root: document.getElementById("root")!,
  selectors: { node: ".item" }
});

mosaic.initialize();

MosaicJS will:

  1. Capture a DOM snapshot on drag start
  2. Evaluate constraints on drop
  3. Roll back automatically when invalid
  4. Broadcast all lifecycle events

Core Concepts

Snapshot System

MosaicJS guarantees DOM safety via snapshotting:

createSnapshot(root);
restoreSnapshot(snapshot);

Invalid drags never leave the DOM in a corrupted state.


Constraints System

const result = checkConstraints(dragged, target, selectors);

Built-in rules include:

  • No self-drop
  • Selector mismatch prevention

Constraints are deterministic, testable, and extensible.


Events Layer

MosaicJS emits structured DOM events for all lifecycle changes:

emit("mosaic:state", {
  from, // Previous state
  to,   // New state
  meta  // Optional metadata
});

Example listener:

window.addEventListener("mosaic:state", (e) => {
  console.log(e.detail.from, "→", e.detail.to);
});

Available events:

  • mosaic:init
  • mosaic:destroy
  • mosaic:state
  • mosaic:mutation:confirmed
  • mosaic:mutation:rejected
  • mosaic:rollback

State Machine

MosaicState defines the full drag lifecycle:

  • idle
  • pointerdown
  • dragging
  • dropping
  • mutated
  • rollback
  • destroyed

All transitions are validated at runtime.
Invalid transitions emit errors and are rejected.


Documentation

Full documentation is available at:

https://mosaicjs.whittakertech.com

Includes:

  • Getting Started
  • API Reference
  • Architecture
  • Snapshot Flow
  • Constraints Design
  • Drag Lifecycle

Run locally:

npm run docs

Roadmap

v0.1 (current)

✓ Snapshot system
✓ Constraints system
✓ Event layer
✓ Mosaic core
✓ Deterministic state machine
✓ 100% test coverage

v0.2

• Public DragController extension points
• Hover target detection
• Enhanced constraints
• Visual markers API

v0.3+

• Grouping & nested drag
• Cross-container constraints
• Plugin system


Contributing

Pull requests are welcome.

Please run tests and linting before submitting:

npm run test
npm run lint

License

MIT © WhittakerTech