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

@convadraw/cloudgrid

v1.0.10

Published

High-performance infinite canvas library for React with WebAssembly-powered rendering. Handle 2000+ media items at 60 FPS.

Readme

🌐 CloudGrid

A high-performance, infinite canvas library for React with WebAssembly-powered rendering

CloudGrid is a production-ready React library for building infinite canvas applications with support for images, videos, and text. Built with performance in mind, it uses WebAssembly (AssemblyScript) for critical operations and Web Workers for non-blocking rendering.

NPM Version License: MIT Demo

✨ Features

  • 🚀 High Performance: WebAssembly-powered canvas operations
  • 🎨 2000+ Items: Handle thousands of media items smoothly
  • 🔄 Undo/Redo: Full history management with batch operations
  • 🎯 Smart Selection: Single and multi-select with rubber band selection
  • 📐 Grid Snapping: Configurable grid with dynamic visual feedback
  • 🔍 Smooth Zoom: Animated camera controls with easing
  • 🎭 LOD System: Level-of-detail rendering for optimal memory usage
  • 🧵 Web Workers: Non-blocking grid rendering and image loading
  • 🎨 Color Sorting: Sort media by dominant RGB colors
  • 📦 TypeScript: Full type safety and IntelliSense support
  • 🎨 Customizable UI: Optional toolbar with Tailwind CSS styling
  • Accessible: Keyboard shortcuts for common operations

📦 Installation

npm install @convadraw/cloudgrid

Peer Dependencies:

npm install react react-dom

🚀 Quick Start

Basic Usage

import { CloudGrid } from '@convadraw/cloudgrid';
import '@convadraw/cloudgrid/cloudgrid.css';

function App() {
  return (
    <div style={{ width: '100vw', height: '100vh' }}>
      <CloudGrid />
    </div>
  );
}

With Camera Controls

import { CloudGrid, useCamera, selectItems, zoomToSelected } from '@convadraw/cloudgrid';
import '@convadraw/cloudgrid/cloudgrid.css';

function App() {
  const camera = useCamera();

  const handleFocusCenter = () => {
    camera.animateToPosition(0, 0, 1, 500);
  };

  const handleZoomIn = () => {
    camera.zoom(1.2);
  };

  return (
    <div style={{ width: '100vw', height: '100vh' }}>
      <button onClick={handleFocusCenter}>Center View</button>
      <button onClick={handleZoomIn}>Zoom In</button>
      <CloudGrid />
    </div>
  );
}

Custom Toolbar Positioning

import { CloudGrid } from '@convadraw/cloudgrid';
import '@convadraw/cloudgrid/cloudgrid.css';

function App() {
  return (
    <CloudGrid
      toolbarPosition="top-left"
      statsPanelPosition="top-right"
    />
  );
}

🎯 Core Concepts

Camera System

CloudGrid uses a centralized camera system for viewport management:

import { useCamera } from '@convadraw/cloudgrid';

function MyComponent() {
  const camera = useCamera();

  // Current state
  console.log(camera.scale);      // Current zoom level (1 = 100%)
  console.log(camera.stagePos);   // Camera position {x, y}

  // Basic controls
  camera.zoom(1.5);                // Zoom by factor
  camera.zoomTo(2.0);              // Zoom to specific scale
  camera.pan(100, -50);            // Pan by delta
  camera.resetView();              // Reset to origin

  // Animated controls
  camera.animateToPosition(x, y, scale, duration);
  camera.zoomToFit(bounds, padding, duration);
}

Selection & Manipulation

import { selectItems, zoomToSelected } from '@convadraw/cloudgrid';

// Programmatically select items
selectItems(['img-1', 'img-2', 'img-3']);

// Zoom to selected items
zoomToSelected();

// Delete selected items
deleteSelected();

Media Management

import { addMedia, sortByColor } from '@convadraw/cloudgrid';

// Trigger file upload
addMedia();

// Sort by dominant colors (RGB gradient)
sortByColor();

📚 API Reference

Components

<CloudGrid />

Main canvas component.

Props:

  • toolbarPosition?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'
    • Position of the tools toolbar (default: 'top-left')
  • statsPanelPosition?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'
    • Position of the stats/controls panel (default: 'top-right')

Example:

<CloudGrid
  toolbarPosition="bottom-left"
  statsPanelPosition="top-right"
/>

Hooks

useCamera()

Access camera controls and state.

Returns:

interface CameraControls {
  scale: number;
  stagePos: { x: number; y: number };
  setScale: (scale: number) => void;
  setStagePos: (pos: { x: number; y: number }) => void;
  zoom: (factor: number, centerX?: number, centerY?: number) => void;
  zoomTo: (newScale: number, centerX?: number, centerY?: number) => void;
  pan: (dx: number, dy: number) => void;
  resetView: () => void;
  animateToPosition: (x: number, y: number, targetScale?: number, duration?: number) => void;
  zoomToFit: (bounds: { x: number; y: number; width: number; height: number }, padding?: number, duration?: number) => void;
}

Helper Functions

selectItems(ids: string[])

Programmatically select items by their IDs.

zoomToSelected()

Animate camera to fit currently selected items in view.

zoomToBounds(bounds, padding?, duration?)

Animate camera to specific bounds.

addMedia()

Trigger the file upload dialog.

deleteSelected()

Delete currently selected items.

sortByColor()

Sort all items by dominant RGB colors (creates diagonal gradient).

🎨 Styling

CloudGrid uses Tailwind CSS with a custom dark theme. The default theme uses oklch color space for consistent, vibrant colors.

Custom Theme

You can override the default theme by adding CSS variables:

:root {
  --background: oklch(0.09 0.01 255);
  --foreground: oklch(0.80 0.19 145);
  --primary: oklch(0.40 0.19 145);
  /* ... more variables */
}

See cloudgrid.css for all available CSS variables.

⌨️ Keyboard Shortcuts

| Shortcut | Action | |----------|--------| | Cmd/Ctrl + Z | Undo | | Cmd/Ctrl + Shift + Z | Redo | | Scroll | Pan canvas | | Cmd/Ctrl + Scroll | Zoom in/out | | Drag (Select Tool) | Rubber band selection | | Shift + Click | Toggle selection | | Delete / Backspace | Delete selected |

🏗️ Architecture

Performance Optimizations

  1. WebAssembly: Critical operations (spatial indexing, viewport culling) run in WASM
  2. Web Workers: Grid rendering and image processing off main thread
  3. LOD System: Dynamic image resolution based on zoom level
  4. Viewport Culling: Only visible items are rendered
  5. Blob Caching: Compressed images cached in worker, decoded on-demand
  6. Batch Operations: Group actions create single undo/redo entries

Technology Stack

  • React 18 - UI framework
  • Konva.js - Canvas rendering
  • AssemblyScript - WebAssembly compilation
  • Web Workers - Background processing
  • Tailwind CSS - Styling
  • TypeScript - Type safety

📊 Performance

  • 2000+ media items at 60 FPS
  • <400MB memory usage with 2000 high-res images
  • Smooth animations with hardware acceleration
  • Non-blocking operations via Web Workers
  • Instant undo/redo for all operations

🤝 Examples

Example 1: Focus on Uploaded Images

import { CloudGrid, useCamera } from '@convadraw/cloudgrid';
import { useEffect } from 'react';

function App() {
  useEffect(() => {
    // Listen for custom events
    window.addEventListener('items-added', (e) => {
      const event = e as CustomEvent;
      selectItems(event.detail.ids);
      zoomToSelected();
    });
  }, []);

  return <CloudGrid />;
}

Example 2: Keyboard Navigation

import { CloudGrid, useCamera } from '@convadraw/cloudgrid';
import { useEffect } from 'react';

function App() {
  const camera = useCamera();

  useEffect(() => {
    const handleKeyPress = (e: KeyboardEvent) => {
      if (e.key === 'f') zoomToSelected();
      if (e.key === 'r') camera.resetView();
      if (e.key === 'Home') camera.animateToPosition(0, 0, 1);
    };

    window.addEventListener('keydown', handleKeyPress);
    return () => window.removeEventListener('keydown', handleKeyPress);
  }, [camera]);

  return <CloudGrid />;
}

Example 3: Custom Controls

import { CloudGrid, useCamera, addMedia, sortByColor } from '@convadraw/cloudgrid';

function App() {
  const camera = useCamera();

  return (
    <div style={{ width: '100vw', height: '100vh', position: 'relative' }}>
      <div style={{ position: 'absolute', top: 10, left: 10, zIndex: 1000 }}>
        <button onClick={() => addMedia()}>Upload Images</button>
        <button onClick={() => sortByColor()}>Sort by Color</button>
        <button onClick={() => camera.resetView()}>Reset View</button>
        <span>Zoom: {Math.round(camera.scale * 100)}%</span>
      </div>
      <CloudGrid />
    </div>
  );
}

🔧 Advanced Usage

Custom Media Items

CloudGrid automatically handles uploaded images. For advanced use cases, you can dispatch custom events:

window.dispatchEvent(new CustomEvent('add-item', {
  detail: {
    type: 'image',
    src: 'https://example.com/image.jpg',
    x: 0,
    y: 0,
    width: 400,
    height: 300,
  }
}));

🐛 Troubleshooting

Images not loading

  • Ensure CORS is enabled for external images
  • Check browser console for network errors
  • Verify image URLs are accessible

Performance issues

  • Reduce number of items (recommended: <2000)
  • Use lower resolution images
  • Check if hardware acceleration is enabled in browser

Type errors

  • Ensure @types/react and @types/react-dom are installed
  • Check TypeScript version compatibility (>=4.7)

📄 License

MIT © 2026

🙏 Acknowledgments

🔗 Links


Made with ❤️ by the CloudGrid team