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

@wedeho/vue-table-map

v1.1.1

Published

A Vue 3 plugin for creating and displaying interactive table seating plans with drag-drop, zoom, pan, and multi-floor support

Readme

Vue Table Map

🪑 A Vue 3 plugin to create and display interactive table maps with drag-drop, zoom, pan and multi-floor support

npm version License: MIT

✨ Features

  • 🎯 Interactive table map creation - Add, move and resize tables
  • 🔄 Multiple shapes - Rectangle, square and round
  • 🪑 Chair configuration - Define the number and position of chairs per side
  • 🔄 Table rotation - Free rotation from -180° to +180°
  • 🏢 Multi-floor support - Manage multiple floors/levels (Ground floor, Floor 1, Basement, etc.)
  • 🔍 Zoom and Pan - Smooth navigation with mouse wheel and drag to move the view
  • 🎨 Customizable - Complete API with props, events, slots and exposed methods
  • 📱 Responsive - Infinite canvas with horizontal and vertical scrolling
  • 👀 Read-only mode - Display without editing capabilities
  • 💾 Import/Export - JSON configuration to save and load your plans

📦 Installation

npm install @julienp/vue-table-map

🚀 Basic Usage

Global Installation

import { createApp } from 'vue'
import VueTableMap from '@wedeho/vue-table-map'
import '@wedeho/vue-table-map/dist/style.css'

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

Direct Component Import

<script setup>
import { ref } from 'vue'
import { TableMapCanvas } from '@julienp/vue-table-map'
import '@wedeho/vue-table-map/dist/style.css'

const tables = ref([])
</script>

<template>
  <TableMapCanvas
    v-model="tables"
    :readonly="false"
  />
</template>

📖 Documentation

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | modelValue | Array | [] | Tables to display (v-model) | | initialTables | Array | [] | Initial tables (alternative to v-model) | | readonly | Boolean | false | Read-only mode | | width | Number | 1200 | Canvas width | | height | Number | 800 | Canvas height | | gridSize | Number | 20 | Grid size (snap) | | showToolbar | Boolean | false | Show default toolbar | | showZoomControls | Boolean | true | Show zoom controls | | showFloorSelector | Boolean | true | Show floor selector | | showInfoPanel | Boolean | false | Show information panel | | showEditPanel | Boolean | true | Show edit panel | | controlsPosition | String | 'top' | Controls position ('top' or 'bottom') | | maxZoom | Number | 5 | Maximum zoom level | | minZoom | Number | 0.1 | Minimum zoom level |

Note on responsiveness: The width and height props are used as default values, but the canvas automatically adapts to its container size (100% width and height). Use CSS to define the parent container dimensions.

Note on controls: Zoom and floor selection controls are positioned inside the canvas as floating elements, horizontally centered. Use the controlsPosition prop to place them at the top or bottom.

Events

| Event | Payload | Description | |-------|---------|-------------| | @update:modelValue | tables: Array | Emitted when tables change (v-model) | | @table-added | table: Object | Emitted when a table is added | | @table-updated | table: Object | Emitted when a table is modified | | @table-removed | tableId: String | Emitted when a table is removed | | @table-selected | table: Object | Emitted when a table is selected | | @table-click | { table, event } | Emitted when a table is clicked (readonly) | | @floor-changed | floor: Number | Emitted when the floor changes |

Exposed Methods (via ref)

<script setup>
import { ref } from 'vue'

const canvasRef = ref(null)

// Add a table
const addTable = () => {
  canvasRef.value?.addTable('rectangle')
}

// Remove the selected table
const removeTable = () => {
  canvasRef.value?.removeTable()
}

// Get all tables
const getTables = () => {
  return canvasRef.value?.getTables()
}
</script>

<template>
  <TableMapCanvas ref="canvasRef" />
</template>

List of Methods

  • addTable(shape) - Add a table ('rectangle', 'square', 'round')
  • removeTable() - Remove the selected table
  • updateTable(updates) - Update the selected table
  • selectTable(tableId) - Select a table
  • deselectTable() - Deselect the current table
  • setFloor(floor) - Change floor
  • clearTables() - Remove all tables
  • clearCurrentFloor() - Remove tables from the current floor
  • exportTables() - Export configuration
  • importTables(data) - Import a configuration
  • getTables() - Get all tables
  • getSelectedTable() - Get the selected table
  • getCurrentFloor() - Get the current floor
  • zoomIn() - Zoom in
  • zoomOut() - Zoom out
  • resetZoom() - Reset zoom

Slots

Customize the interface with available slots:

table-content

Customize the content displayed in each table:

<TableMapCanvas v-model="tables">
  <template #table-content="{ table, index }">
    <div style="text-align: center;">
      <strong>{{ table.name }}</strong>
      <div>{{ table.seats }} seats</div>
    </div>
  </template>
</TableMapCanvas>

toolbar

Replace the default toolbar:

<TableMapCanvas :show-toolbar="true">
  <template #toolbar="{ addTable, deleteSelected }">
    <button @click="addTable('rectangle')">Add Table</button>
    <button @click="deleteSelected">Delete</button>
  </template>
</TableMapCanvas>

Other Available Slots

  • zoom-controls - Custom zoom controls
  • floor-selector - Custom floor selector
  • info-panel - Custom information panel

Table Structure

{
  id: 'unique-id',
  name: 'Table 1',
  shape: 'rectangle', // 'rectangle' | 'square' | 'round'
  x: 100,
  y: 100,
  width: 140,
  height: 80,
  seats: 6,
  rotation: 0, // -180 to 180
  floor: 0, // 0 = Ground floor, 1+ = Floors, -1- = Basements
  chairLayoutTop: 2, // For rectangle/square
  chairLayoutRight: 1,
  chairLayoutBottom: 2,
  chairLayoutLeft: 1
}

💡 Examples

Example 1: Custom Interface

<script setup>
import { ref } from 'vue'
import { TableMapCanvas } from '@julienp/vue-table-map'

const canvasRef = ref(null)
const tables = ref([])

const addRectangle = () => canvasRef.value?.addTable('rectangle')
const addRound = () => canvasRef.value?.addTable('round')
const deleteTable = () => canvasRef.value?.removeTable()
const exportPlan = () => {
  const data = canvasRef.value?.exportTables()
  console.log('Export:', data)
}
</script>

<template>
  <div>
    <div class="toolbar">
      <button @click="addRectangle">➕ Rectangle</button>
      <button @click="addRound">➕ Round</button>
      <button @click="deleteTable">🗑️ Delete</button>
      <button @click="exportPlan">💾 Export</button>
    </div>

    <TableMapCanvas
      ref="canvasRef"
      v-model="tables"
      :show-toolbar="false"
      :show-edit-panel="false"
      @table-selected="table => console.log('Selected:', table)"
    />
  </div>
</template>

Example 2: Read-only Mode with Custom Content

<script setup>
import { ref } from 'vue'
import { TableMapCanvas } from '@julienp/vue-table-map'

const tables = ref([
  {
    id: '1',
    name: 'VIP Table',
    shape: 'round',
    x: 200,
    y: 200,
    width: 120,
    height: 120,
    seats: 8,
    floor: 0,
    isVip: true
  }
])

const handleTableClick = ({ table }) => {
  alert(`Table: ${table.name}\nSeats: ${table.seats}`)
}
</script>

<template>
  <TableMapCanvas
    v-model="tables"
    :readonly="true"
    @table-click="handleTableClick"
  >
    <template #table-content="{ table }">
      <div style="text-align: center; color: #1e293b;">
        <div style="font-weight: bold; font-size: 14px;">
          {{ table.name }}
        </div>
        <div style="font-size: 12px; color: #64748b;">
          {{ table.seats }} seats
        </div>
        <div v-if="table.isVip" style="color: gold; font-size: 16px;">
          ⭐
        </div>
      </div>
    </template>
  </TableMapCanvas>
</template>

Example 3: Multi-floor with Initial Data

<script setup>
import { ref } from 'vue'
import { TableMapCanvas } from '@julienp/vue-table-map'

const tables = ref([
  // Ground floor
  {
    id: '1',
    name: 'Table 1',
    shape: 'rectangle',
    x: 150,
    y: 150,
    width: 140,
    height: 80,
    seats: 6,
    floor: 0,
    chairLayoutTop: 2,
    chairLayoutRight: 1,
    chairLayoutBottom: 2,
    chairLayoutLeft: 1
  },
  // Floor 1
  {
    id: '2',
    name: 'Table 2',
    shape: 'round',
    x: 200,
    y: 200,
    width: 100,
    height: 100,
    seats: 6,
    floor: 1
  }
])

const handleFloorChange = (floor) => {
  console.log('Active floor:', floor)
}
</script>

<template>
  <TableMapCanvas
    v-model="tables"
    @floor-changed="handleFloorChange"
  />
</template>

🎮 Controls

Edit Mode

  • Move a table: Click and drag
  • Resize: Use the handles on corners and edges
  • Select: Click on a table
  • Zoom: Mouse wheel or +/- buttons
  • Pan: Drag the background (when no table selected) or Shift+Drag
  • Edit: Double-click or "Edit" button when selected

Read-only Mode

  • Zoom: Mouse wheel
  • Pan: Click and drag
  • Table click: @table-click event

🎨 Style Customization

The plugin uses scoped CSS. You can override styles if needed:

/* Customize tables */
.table-element {
  /* your styles */
}

/* Customize chairs */
.chair-element {
  /* your styles */
}

🛠️ Development

# Install dependencies
npm install

# Development with Hot Module Replacement
npm run dev

# Build library
npm run build:lib

# Build demo
npm run build

npm publish --access public

📝 License

MIT © Julien PARDONS / Wedeho

🤝 Contributing

Contributions are welcome! Feel free to open an issue or pull request.

🐛 Support

To report a bug or request a feature, please create an issue.