Overlays & Events
Overlays and the presenter console communicate through a central, typed event bus.
Overlays
Overlays attach interactive UI widgets over the stage canvas (such as laser pointers, drawing tools, and navigation buttons):
import { Stage, NavigationOverlay, LaserPointer, Annotation } from "stageroutine";
const stage = new Stage();
stage.overlay(LaserPointer());
stage.overlay(Annotation());
stage.overlay(NavigationOverlay());
Built-in Overlays
LaserPointer(): WebGL glowing red laser pointer.Annotation(): Smooth variable-width ink drawn over slides. The ink color follows the active themeprimarycolor.NavigationOverlay(): With a mouse, hover within the bottom 100 CSS pixels to show navigation controls. Move away to hide them. On touch, tap the bottom zone to show controls and tap outside the controls to dismiss them. Escape also dismisses them.
With NavigationOverlay(), swipe left for the next step or right for the previous step. Interactive and scrollable content keeps its own gestures. Add data-prevent-swipe to custom interactive content to exclude it. Pointer controls are hidden on touch-only devices.
The Presenter Pointer Tool
LaserPointer() and Annotation() share one tool state. Toggle it with P or Escape. While the tool is active, moving shows the laser beam and press-and-drag draws ink. The tools are implemented separately but activate together, so there is no separate draw mode.
| Key | Action |
|---|---|
P | Toggle the pointer tool |
C | Clear annotations (150ms dissolve) |
Cmd/Ctrl+Z or Z | Undo last stroke |
Cmd/Ctrl+Shift+Z or Shift+Z | Redo stroke |
Escape | Exit the pointer tool |
Event System
All communication between the stage, overlays, keyboard shortcuts, and the presenter console flows through a single typed event bus using req: (requests) and evt: (notifications):
| Domain | Requests (req:*) | Notifications (evt:*) |
|---|---|---|
nav: | req:nav:nextStep, req:nav:prevStep, req:nav:nextScene, req:nav:prevScene, req:nav:gotoStep, req:nav:gotoScene | evt:nav:stepChanged, evt:nav:sceneChanged |
stage: | req:stage:requestState | evt:stage:resized, evt:stage:stateChanged |
pointer: | req:pointer:setState | evt:pointer:stateChanged |
Listening and Emitting
// Listen for navigation step changes
stage.on("evt:nav:stepChanged", ({ index, total, scene }) => {
console.log(`Step ${index + 1} of ${total} (${scene})`);
});
// Emit navigation requests programmatically
stage.emit("req:nav:nextStep");
// Toggle pointer mode
stage.emit("req:pointer:setState", { active: true });
Dual-Screen BroadcastChannel
The event bus transparently bridges across browser windows using the browser's native BroadcastChannel. Opening presenter.html on a second display immediately connects to the stage without network sockets or servers.