Skip to content

@web-engine-dev/signals

Godot-style reactive signal system for web-engine.

Features

  • Type-Safe Signals: Generic typed signals
  • Connect/Disconnect: Subscribe to signals
  • One-Shot: Auto-disconnect after first emit
  • Deferred Emit: Queue signals for later
  • Signal Groups: Batch signal operations

Installation

bash
npm install @web-engine-dev/signals
# or
pnpm add @web-engine-dev/signals

Quick Start

typescript
import { Signal, signal } from '@web-engine-dev/signals';

// Create signal
const onDamage = signal<{ amount: number; source: Entity }>();

// Connect listener
const disconnect = onDamage.connect((data) => {
  console.log(`Took ${data.amount} damage from ${data.source}`);
});

// Emit signal
onDamage.emit({ amount: 10, source: enemy });

// Disconnect
disconnect();

API Overview

Signal Creation

typescript
// Using factory
const onDeath = signal<void>();
const onScoreChanged = signal<number>();
const onCollision = signal<{ a: Entity; b: Entity }>();

// Using class
const health = new Signal<number>();

Connecting

typescript
// Basic connect
const disconnect = mySignal.connect(handler);

// One-shot (auto-disconnects)
mySignal.connectOnce(handler);

// With priority (lower = earlier)
mySignal.connect(handler, { priority: 0 });

// Bound to object
mySignal.connect(this.onEvent, { bind: this });

Emitting

typescript
// Immediate emit
mySignal.emit(value);

// Deferred emit (next frame)
mySignal.emitDeferred(value);

// Check if has connections
if (mySignal.hasConnections()) {
  mySignal.emit(value);
}

Component Integration

typescript
class Enemy {
  readonly onDeath = signal<void>();
  readonly onDamaged = signal<number>();

  takeDamage(amount: number) {
    this.health -= amount;
    this.onDamaged.emit(amount);

    if (this.health <= 0) {
      this.onDeath.emit();
    }
  }
}

// Usage
enemy.onDeath.connect(() => {
  spawnLoot(enemy.position);
  addScore(100);
});

Signal Groups

typescript
const group = new SignalGroup();

group.add(health.onChanged);
group.add(mana.onChanged);
group.add(stamina.onChanged);

// Disconnect all at once
group.disconnectAll();

Proprietary software. All rights reserved.