JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 7
  • Score
    100M100P100Q27138F
  • License MIT

A Storybook-like development environment for Phaser 3 components with interactive testing

Package Exports

  • phaser-viewer
  • phaser-viewer/test
  • phaser-viewer/test-runner

Readme

Phaser Viewer Icon

Phaser Viewer

A Storybook-like development environment for Phaser 3 components with interactive testing capabilities.

Version 0.1.9 Phaser 3.90.0 TypeScript 5.9+ Node.js 18+ MIT License

A lightweight Storybook alternative for Phaser 3 game components


โœจ Features

๐ŸŽฎ Storybook-like UI
Hierarchical sidebar with organized component demos
๐Ÿงช Interactive & Automated Testing
Built-in expect API with visual feedback, play logs, and CLI test runner
๐Ÿ”ฅ Hot Reload
Instant feedback during development with Vite
๐Ÿ“ฆ No Setup Required
Just create .demo.ts files and run npm command
โšก Asset Loading
PreloadScene support for centralized asset management
๐ŸŽฌ Scene Configuration
Customizable canvas size and background color for different project needs
๐ŸŽฏ TypeScript First
Full type safety with automatic component and args inference using advanced TypeScript patterns
๐Ÿ”„ Component Reset
Reset button to restore components to initial state after Play tests while preserving test history
๐Ÿ“ Development Grid System
Smart square grid overlay that perfectly fits your scene size for precise component positioning and alignment

๐Ÿ“ฆ Installation

npm install phaser-viewer
# or
yarn add phaser-viewer
# or
pnpm add phaser-viewer

๐Ÿš€ Quick Start

1๏ธโƒฃ Install phaser-viewer

npm install phaser-viewer

2๏ธโƒฃ Create your component demo

Create a .demo.ts file alongside your component:

// src/Button.demo.ts
import { expect, delay } from 'phaser-viewer';
import { Meta, Demo } from 'phaser-viewer';
import { Button } from './Button'; // Import your component
import * as Phaser from 'phaser';

const meta = {
  component: Button,
  title: 'UI/Button',
  description: 'Interactive button component'
} as const satisfies Meta<typeof Button>;

export default meta;

interface ButtonArgs {
  x: number;
  y: number;
  text: string;
  config?: {
    color?: number;
    width?: number;
    height?: number;
  };
}

export const BasicButton: Demo<typeof meta, ButtonArgs> = {
  name: 'Basic Button',
  args: { x: 400, y: 300, text: 'Click Me!' },
  create: (scene, args) => {
    // Full type inference: args has x, y, text properties
    return new Button(scene, args.x, args.y, args.text, args.config);
  },
  play: async (_scene, component) => {
    // Full type inference: component is Button instance with all methods
    await expect(component.getText(), 'Initial text').toBe('Click Me!');
    
    // Test interaction
    component.emit('pointerdown');
    await delay(100);
    await expect(component.getText(), 'After click').toBe('Clicked!');
  }
};

3๏ธโƒฃ Start the development server

npx phaser-viewer
# or add to package.json scripts:
# "phaser-viewer": "phaser-viewer"

That's it! Your Phaser component viewer will start automatically. No React setup files needed!

๐Ÿ“ Project Structure

your-project/
โ”œโ”€โ”€ src/                   # Your Phaser components and demos
โ”‚   โ”œโ”€โ”€ Button.ts         # Button component implementation  
โ”‚   โ”œโ”€โ”€ Button.demo.ts    # Button component demos
โ”‚   โ”œโ”€โ”€ Sprite.ts         # Sprite component implementation
โ”‚   โ””โ”€โ”€ Sprite.demo.ts    # Sprite component demos
โ”œโ”€โ”€ .phaser-viewer-temp/   # Hidden temp files (auto-generated)
โ””โ”€โ”€ package.json          # Include phaser-viewer script

๐Ÿงช Testing Your Components

Phaser Viewer includes a powerful testing API inspired by @storybook/test. Tests can be run interactively in the browser or automatically via CLI.

Interactive Testing

Test results appear in the Play Logs panel with visual feedback:

import { expect, delay } from 'phaser-viewer';

export const InteractiveButton: Demo<typeof meta, ButtonArgs> = {
  name: 'Interactive Button',
  args: { x: 400, y: 300, text: 'Test Button' },
  create: (scene, args) => {
    // Type inference: args is ButtonArgs, scene is Phaser.Scene
    return new Button(scene, args.x, args.y, args.text);
  },
  play: async (_scene, component) => {
    // Type inference: component is Button instance with all methods
    await expect(component.getText(), 'Initial text').toBe('Test Button');
    await expect(component.visible, 'Should be visible').toBe(true);
    
    // Test button click
    component.emit('pointerdown');
    await delay(100);
    await expect(component.getText(), 'After click').toBe('Clicked!');
    
    // Test multiple clicks
    component.emit('pointerdown');
    await delay(100);
    await expect(component.getText(), 'After second click').toBe('Clicked 2x');
  }
};

Automated Testing (CLI)

Run all Play functions as automated tests:

npx phaser-viewer test

Example Output:

๐Ÿงช Starting Phaser Viewer Test Runner...
๐Ÿ”ง Loaded user config: { filePath: './src/**/*.demo.ts' }
๐ŸŽฏ Play Functions: 2 passed, 1 failed
โŒ Gold - TestableGold: Expected 999, but received 600

How it works:

  • Each Play function becomes a test unit
  • Expect assertions determine pass/fail status
  • Failed tests show detailed error messages
  • Tests run in headless browser environment
  • Automatic dependency installation (vitest, playwright)

โšก Asset Loading with PreloadScene

For components that require assets (images, sounds, etc.), you can create a PreloadScene class to handle asset loading:

1๏ธโƒฃ Create a PreloadScene class

// src/GoldPreloadScene.ts
import * as Phaser from 'phaser';

export class GoldPreloadScene extends Phaser.Scene {
  constructor() {
    super({ key: 'GoldPreloadScene' });
  }
  
  preload() {
    // Load all assets your component needs
    this.load.image('gold', 'img/gold.png');
    this.load.image('silver', 'img/silver.png');
    this.load.audio('coinSound', 'audio/coin.mp3');
  }
}

2๏ธโƒฃ Reference the PreloadScene in your demo

// src/Gold.demo.ts
import { Meta, Demo } from 'phaser-viewer';
import { Gold } from './Gold';
import { GoldPreloadScene } from './GoldPreloadScene';
import * as Phaser from 'phaser';

const meta = {
  component: Gold,
  title: 'Sprites/Gold',
  description: 'Gold coin sprite with preloaded assets',
  preloadScene: GoldPreloadScene  // โ† Add this line
} as const satisfies Meta<typeof Gold>;

export default meta;

interface GoldArgs {
  x: number;
  y: number;
}

export const BasicGold: Demo<typeof meta, GoldArgs> = {
  name: 'Basic Gold Coin',
  args: { x: 400, y: 300 },
  create: (scene, args) => {
    // Assets are already loaded and available!
    // Type inference: args has x, y properties
    return new Gold(scene, args.x, args.y);
  }
};

3๏ธโƒฃ Use assets in your component

// src/Gold.ts
export class Gold extends Phaser.GameObjects.Sprite {
  constructor(scene: Phaser.Scene, x: number, y: number) {
    // The 'gold' texture is already loaded by GoldPreloadScene
    super(scene, x, y, 'gold');
    scene.add.existing(this);
    
    // You can also use other preloaded assets
    this.setInteractive();
    this.on('pointerdown', () => {
      scene.sound.play('coinSound'); // Audio is also preloaded
    });
  }
}

How it works

  1. PreloadScene starts first - Phaser Viewer automatically detects and runs your PreloadScene
  2. Assets are loaded - All assets defined in preload() method are loaded into memory
  3. ViewerScene launches - After loading completes, the viewer scene starts
  4. Assets are available - Your components can immediately use the preloaded assets

This ensures smooth component rendering without loading delays or missing asset errors.

๐ŸŽ›๏ธ Scene Configuration

Phaser Viewer allows you to customize the canvas size and background color to match your project needs:

Basic Scene Configuration

// phaser-viewer.config.ts
import { PhaserViewerConfig } from 'phaser-viewer';

const config: PhaserViewerConfig = {
  filePath: './src/**/*.demo.ts',
  scene: {
    width: 1200,           // Custom canvas width
    height: 800,           // Custom canvas height  
    backgroundColor: '#1a1a2e'  // Custom background color
  }
};

export default config;

Configuration Options

Option Type Default Description
width number 800 Canvas width in pixels
height number 600 Canvas height in pixels
backgroundColor string '#222222' Background color in hex format
displayScale number auto Display scaling factor (0.1-2.0, or omit for responsive auto-scaling)

TypeScript Path Alias Support

Phaser Viewer automatically detects and resolves TypeScript path aliases from your tsconfig.json:

// tsconfig.json
{
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"],
      "@/utils/*": ["./src/utils/*"]
    }
  }
}

// Your demo files can use path aliases
import { Button } from '@/components/Button';
import { COLORS } from '@/utils/colors';

Configuration Options:

// phaser-viewer.config.ts
export default {
  filePath: './src/**/*.demo.ts',
  // Auto-detection is enabled by default
  typescript: {
    autoDetectPaths: true,  // Default: true
    tsconfigPath: './tsconfig.json'  // Optional
  },
  // Or manually configure Vite aliases
  vite: {
    resolve: {
      alias: [
        { find: '@/', replacement: '/path/to/src/' }
      ]
    }
  }
}

๐Ÿ› ๏ธ Commands

Development

  • npx phaser-viewer - Start development server with auto-detected configuration
  • npx phaser-viewer --port 3000 - Start on custom port
  • npx phaser-viewer --help - Show help

Testing

  • npx phaser-viewer test - Run automated tests for all Play functions

Test Runner Features:

  • Headless Testing: Runs components in headless browser environment
  • Play Function Tests: Each Play function becomes a test unit with pass/fail results
  • Error Details: Detailed error messages for failed tests
  • Clean Output: Filtered results without browser noise
  • Automatic Setup: Installs test dependencies automatically (vitest, playwright, @vitest/browser)

Configuration Detection:

  • Automatically loads phaser-viewer.config.ts or phaser-viewer.config.js
  • Generates default configuration file if none exists
  • Supports scene customization (size, background color)
  • Auto-adds .phaser-viewer-temp/ to .gitignore when present

๐Ÿ“ Development Grid System

Phaser Viewer includes a smart grid overlay system to help with precise component positioning during development:

Features

  • Square Grid Cells: Automatically calculates near-square grid cells for better visual alignment
  • Perfect Scene Coverage: Grid lines perfectly span your configured scene dimensions with no cutoff
  • Adaptive Sizing: Automatically adjusts to different screen sizes (100px, 120px, 80px target cells)
  • Always Visible: Grid appears in all demos for consistent development experience

How it Works

For a 1920ร—1080 scene:

  • Calculates 19ร—11 divisions (targeting ~100px square cells)
  • Creates cells of 101.1ร—98.2px (nearly perfect squares)
  • 18 vertical + 10 horizontal lines provide complete coverage
  • No manual configuration needed - works automatically

The grid system is enabled by default and helps developers align components precisely during development without any setup required.


๐Ÿ“„ License

MIT License

๐Ÿค Contributing

Contributions, issues and feature requests are welcome! Feel free to check issues page or contribute to the GitHub repository.


Phaser 3 โ€ข React โ€ข TypeScript