@whittakertech/mosaic
v0.1.0
Published
Event-driven, deterministic drag-and-drop engine with constraint validation and rollback
Maintainers
Readme
MosaicJS
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/mosaicQuick Start
import { Mosaic } from "@whittakertech/mosaic";
const mosaic = new Mosaic({
root: document.getElementById("root")!,
selectors: { node: ".item" }
});
mosaic.initialize();MosaicJS will:
- Capture a DOM snapshot on drag start
- Evaluate constraints on drop
- Roll back automatically when invalid
- 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:initmosaic:destroymosaic:statemosaic:mutation:confirmedmosaic:mutation:rejectedmosaic:rollback
State Machine
MosaicState defines the full drag lifecycle:
idlepointerdowndraggingdroppingmutatedrollbackdestroyed
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 docsRoadmap
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 lintLicense
MIT © WhittakerTech
