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

@alisaitteke/seatmap-canvas

v2.7.1

Published

Seatmap Canvas is an advanced, open-source library for interactive seat selection in various settings such as stadiums, theaters, and event spaces. Designed with d3.js, this code version is optimized for developers looking for a customizable and efficient

Readme

Seatmap Canvas

Seatmap Canvas is an advanced, open-source library for interactive seat selection in various settings such as stadiums, theaters, and event spaces. Designed with d3.js, this code version is optimized for developers looking for a customizable and efficient solution to handle seat arrangements and user interactions.

LIVE DEMO

📖 Documentation | 🎯 Live Demo

Features

  • Framework Agnostic - Core library works with vanilla JS, plus official React and Vue 3 wrappers
  • Dynamic Seat Selection - Interactive selection, categorization, and location of seats
  • Custom Background Images - Global and per-block background images with positioning control
  • Customizable Styles - Extensive styling options for seats, blocks, and labels
  • Interactive Seat Models - Define properties like salability, notes, colors, and custom data
  • Block Organization - Organize seats into blocks with titles, colors, and labels
  • Event System - Simplified event listeners for seat interactions

Screenshot

LIVE DEMO

🚀 Framework Plugins & Integrations

🌐 Web Frameworks

📱 Mobile Frameworks


🌐 Web Framework Integrations

| Framework | Status | Package | Documentation | Example | |:----------|:------:|:--------|:-------------:|:-------:| | Vanilla JS | ✅ Available | @alisaitteke/seatmap-canvas | 📖 Documentation | 🎯 Example | | Vue.js 3 | ⚠️ Testing | @alisaitteke/seatmap-canvas/vue | 📖 Documentation | 🎯 Example | | React | ⚠️ Testing | @alisaitteke/seatmap-canvas/react | 📖 Documentation | 🎯 Example | | Next.js | ⚠️ Testing | @alisaitteke/seatmap-canvas/nextjs | 📖 Documentation | 🎯 App RouterPages Router | | Svelte | 🔜 Coming Soon | - | - | - | | Angular | 🔜 Coming Soon | - | - | - | | Nuxt | 🔜 Coming Soon | - | - | - | | Solid.js | 🔜 Coming Soon | - | - | - | | Astro | 🔜 Coming Soon | - | - | - |

📱 Mobile Framework Integrations

| Framework | Platform | Status | Package | Documentation | Example | |:----------|:--------:|:------:|:--------|:-------------:|:-------:| | React Native | iOS • Android | 🔜 Coming Soon | - | - | - | | Flutter | iOS • Android | 🔜 Coming Soon | - | - | - | | Expo | iOS • Android | 🔜 Coming Soon | - | - | - | | Ionic | iOS • Android • Web | 🔜 Coming Soon | - | - | - | | Capacitor | iOS • Android • Web | 🔜 Coming Soon | - | - | - | | .NET MAUI | iOS • Android • Windows • macOS | 🔜 Coming Soon | - | - | - |


LIVE DEMO

What does it do?

In any organization

  • Seat selection
  • Seat categorizing
  • Locating
  • Turnstile and Gate information

Installation

npm install @alisaitteke/seatmap-canvas

Quick Start


Installation

npm install @alisaitteke/seatmap-canvas

Setup (main.ts)

import { createApp } from 'vue';
import App from './App.vue';
import SeatmapCanvasPlugin from '@alisaitteke/seatmap-canvas/vue';
import '@alisaitteke/seatmap-canvas/dist/seatmap.canvas.css';

const app = createApp(App);
app.use(SeatmapCanvasPlugin);
app.mount('#app');

Component Usage

<template>
  <SeatmapCanvas
    :options="seatmapOptions"
    :data="blocks"
    @seat-click="onSeatClick"
  />
</template>

<script setup lang="ts">
const seatmapOptions = {
  legend: true,
  style: {
    seat: {
      hover: '#8fe100',
      selected: '#8fe100',
    }
  }
};

const onSeatClick = (seat) => {
  seat.isSelected() ? seat.unSelect() : seat.select();
};
</script>

Installation

npm install @alisaitteke/seatmap-canvas

Component Usage

import { SeatmapCanvas } from '@alisaitteke/seatmap-canvas/react';
import '@alisaitteke/seatmap-canvas/dist/seatmap.canvas.css';

function App() {
  const handleSeatClick = (seat) => {
    seat.isSelected() ? seat.unSelect() : seat.select();
  };

  return (
    <SeatmapCanvas
      options={{
        legend: true,
        style: {
          seat: { hover: '#8fe100', selected: '#8fe100' }
        }
      }}
      data={blocks}
      onSeatClick={handleSeatClick}
    />
  );
}

Installation

npm install @alisaitteke/seatmap-canvas next react react-dom

App Router (Client Component)

'use client';

import { SeatmapCanvas } from '@alisaitteke/seatmap-canvas/nextjs';
import '@alisaitteke/seatmap-canvas/dist/seatmap.canvas.css';

export default function VenuePage() {
  const handleSeatClick = (seat) => {
    seat.isSelected() ? seat.unSelect() : seat.select();
  };

  return (
    <SeatmapCanvas
      data={blocks}
      options={{ legend: true }}
      onSeatClick={handleSeatClick}
    />
  );
}

Server Component + Data Fetching

import { SeatmapServerWrapper } from '@alisaitteke/seatmap-canvas/nextjs/app-router';
import '@alisaitteke/seatmap-canvas/dist/seatmap.canvas.css';

export default async function VenuePage({ params }) {
  return (
    <SeatmapServerWrapper
      dataSource={`/api/venues/${params.id}/seatmap`}
      options={{ legend: true }}
      revalidate={3600}
    />
  );
}

Pages Router (Dynamic Import)

import { SeatmapCanvas } from '@alisaitteke/seatmap-canvas/nextjs/pages-router';

export default function VenuePage({ data }) {
  return <SeatmapCanvas data={data} />;
}

Quick Setup

const config = {
  resizable: true,
  seat_style: {
    radius: 12,
    color: "#6796ff",
    hover: "#5671ff",
    selected: "#56aa45"
  }
};

const seatmap = new SeatmapCanvas(".container", config);
seatmap.setData(data);

Event Handling

seatmap.addEventListener("seat_click", (seat) => {
  if (seat.selected) {
    seatmap.seatUnselect(seat);
  } else {
    seatmap.seatSelect(seat);
  }
});

// Get selected seats
const selected = seatmap.getSelectedSeats();

Seat Model

{
  "id": 1,
  "title": "49",
  "x": 0,
  "y": 0,
  "salable": true,
  "note": "note test",
  "color":"#ffffff",
  "custom_data": {
    "any": "things"
  }
}

Block Model

{
  "blocks": [{
    "id": 1,
    "title": "Test Block 1",
    "color": "#2c2828",
    "labels": [{ "title": "A", "x": -30, "y": 0 }],
    "seats": [
      { "id": 1, "x": 0, "y": 0, "salable": true, "title": "49" },
      { "id": 2, "x": 30, "y": 0, "salable": true, "title": "47" }
    ]
  }]
}

Configuration Options

{
  click_enable_sold_seats: true,  // Enable clicking on unavailable seats (default: false)
  
  // Global Background Image
  background_image: "assets/stadium.jpg",      // Image URL (PNG, JPG, SVG, WebP, GIF)
  background_opacity: 0.3,                     // 0-1 (default: 0.3)
  background_fit: "cover",                     // "cover" | "contain" | "fill" | "none"
  background_x: 0,                            // Manual X position (optional, auto-detect if null)
  background_y: 0,                            // Manual Y position (optional)
  background_width: 1500,                     // Manual width (optional)
  background_height: 1000                     // Manual height (optional)
}

Global Background

Add a background image to the entire stage:

const seatmap = new SeatmapCanvas(".container", {
  background_image: "assets/concert-hall.jpg",
  background_opacity: 0.3,
  background_fit: "cover"
});

With Manual Positioning:

const seatmap = new SeatmapCanvas(".container", {
  background_image: "assets/stadium.jpg",
  background_x: -500,        // Position X
  background_y: -500,        // Position Y
  background_width: 3000,    // Width
  background_height: 2500,   // Height
  background_opacity: 0.4,
  background_fit: "contain"  // Preserve aspect ratio
});

Block-Level Background

Add custom backgrounds to individual blocks:

{
  blocks: [{
    id: "vip-section",
    title: "VIP Area",
    background_image: "assets/vip-lounge.jpg",
    background_opacity: 0.6,
    background_fit: "cover",
    seats: [...]
  }, {
    id: "general",
    title: "General Admission",
    background_image: "assets/general-area.jpg",
    background_opacity: 0.5,
    seats: [...]
  }]
}

With Manual Positioning:

{
  blocks: [{
    id: "block-a",
    background_image: "section-a.jpg",
    background_x: 100,         // Exact X coordinate
    background_y: 200,         // Exact Y coordinate
    background_width: 500,     // Exact width
    background_height: 400,    // Exact height
    background_opacity: 0.7,
    background_fit: "cover",
    seats: [...]
  }]
}

Fit Modes

  • cover (default) - Image covers entire area, may crop
  • contain - Image fits inside area, preserves aspect ratio
  • fill - Image stretches to fill area
  • none - Image keeps original size, centered

Features

  • Auto-Detection: X, Y, Width, Height auto-calculated from bounds if not specified
  • Clip-Path Masking: Block backgrounds clipped to exact block shape
  • Opacity Control: Adjustable transparency (0-1)
  • Auto-Hide Bounds: Block borders/fills hidden when background exists
  • Zoom Preserved: Bounds calculations still work for zoom levels
  • Format Support: PNG, JPG, SVG, WebP, GIF, all web-compatible formats
  • Performance: Browser-native image loading and caching

Use Cases

Stadium/Arena:

// Stadium overview as background
background_image: "stadium-aerial.jpg"

Theater:

// Stage photo per seating section
blocks: [
  { id: "orchestra", background_image: "orchestra-view.jpg" },
  { id: "balcony", background_image: "balcony-view.jpg" }
]

Restaurant:

// Floor plan as background
background_image: "floor-plan.png",
background_opacity: 0.5,
background_fit: "contain"

Event Space:

// Custom venue layout
background_image: "venue-layout.svg",
background_fit: "contain"

Important Notes

  • Background images don't affect zoom calculations (bounds preserved)
  • Block borders/fills automatically hidden when background assigned
  • CORS: Images must be same-origin or CORS-enabled
  • Performance: Use optimized images (< 500KB recommended)

Links

Author

Contributors

Contributions are welcome! Feel free to submit issues and pull requests.