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

pixium

v1.1.0

Published

Helper utilities for PixiJS.

Readme

pixium

Helper library for PixiJS.

Install

npm install pixium

Usage

const { version, createAssetsManager } = require("pixium");

console.log(version());

const loader = createAssetsManager();

const manifest = [
  { alias: "timer_bg", src: "/assets/timer-bg.png" },
  { alias: "logo", src: "/assets/logo.png" },
];

// load(manifest, onProgress?)
await loader.load(manifest, (progress) => {
  console.log("Loading progress:", progress);
});

// has(alias)
console.log(loader.has("timer_bg")); // true

// get(alias)
const timerBgTexture = loader.get("timer_bg");

// unload(manifest)
await loader.unload([{ alias: "logo", src: "/assets/logo.png" }]);

// unloadAll()
await loader.unloadAll();

Scene Manager API

createSceneManager(config) helps you define all pages/scenes in one place and navigate with one function: go(pageId, params?).

It handles:

  • redirects (next)
  • guards (canEnter, canLeave)
  • preloading (preload) before page creation/enter
  • lifecycle hooks (onEnter, onLeave)
  • transition selection (route/page/global fallback)
  • history (back, forward)

Quick start

import { createSceneManager } from "pixium";

const scenes = createSceneManager({
  initial: "boot",
  defaultTransition: { type: "fade", duration: 300 },
  pages: {
    boot: {
      create: () => ({ id: "boot-scene" }),
      next: "menu"
    },
    menu: {
      create: () => ({ id: "menu-scene" }),
      transitions: {
        to: {
          game: { type: "slide-left", duration: 450 }
        }
      }
    },
    game: {
      create: ({ params }) => ({ id: "game-scene", params }),
      onEnter: async ({ params }) => {
        console.log("Entered game with params:", params);
      }
    }
  }
});

await scenes.start();
await scenes.go("game", { level: 2 });
await scenes.back();

Minimum config required from user

  • initial: first page id
  • pages: map of page configs
  • each page must implement create(ctx)

Everything else is optional.

Config shape

type TransitionSpec = {
  type: "none" | "fade" | "slide-left" | "slide-right" | "zoom";
  duration?: number;
  easing?: string;
};

type SceneManagerConfig = {
  initial: string;
  pages: Record<string, {
    preload?: (ctx: {
      id: string;
      params?: Record<string, unknown>;
    }) => void | Promise<void>;
    create: (ctx: { id: string; params?: Record<string, unknown> }) => unknown;
    onEnter?: (ctx: {
      pageId: string;
      fromId: string | null;
      params?: Record<string, unknown>;
      direction: "forward" | "back" | "replace";
      instance: unknown;
    }) => void | Promise<void>;
    onLeave?: (ctx: {
      pageId: string;
      toId: string;
      params?: Record<string, unknown>;
      direction: "forward" | "back" | "replace";
      instance: unknown;
    }) => void | Promise<void>;
    next?: string | ((ctx: {
      fromId: string | null;
      toId: string;
      params?: Record<string, unknown>;
      direction: "forward" | "back" | "replace";
    }) => string | null | Promise<string | null>);
    canEnter?: (ctx: {
      fromId: string | null;
      toId: string;
      params?: Record<string, unknown>;
      direction: "forward" | "back" | "replace";
    }) => boolean | Promise<boolean>;
    canLeave?: (ctx: {
      fromId: string | null;
      toId: string;
      params?: Record<string, unknown>;
      direction: "forward" | "back" | "replace";
    }) => boolean | Promise<boolean>;
    transitionIn?: TransitionSpec;
    transitionOut?: TransitionSpec;
    transitions?: {
      to?: Record<string, TransitionSpec>;
      from?: Record<string, TransitionSpec>;
    };
  }>;
  defaultTransition?: TransitionSpec;
  notFound?: string;
  maxHistory?: number;
  runTransition?: (ctx: {
    fromId: string | null;
    toId: string;
    params?: Record<string, unknown>;
    fromInstance: unknown;
    toInstance: unknown;
    spec: TransitionSpec;
    direction: "forward" | "back" | "replace";
  }) => void | Promise<void>;
};

Preload resources for a page

You can define a per-page preload hook for assets, data, or any async preparation step needed before the scene is entered.

Why use it:

  • avoid frame spikes when entering heavy scenes
  • preload likely-next scenes in the background
  • keep create focused on building scene objects, not fetching resources

Behavior:

  • go(...) automatically calls page preload before create and onEnter
  • scenes.preload(pageId, params?) lets you preload manually (without navigation)
import { Container } from "pixi.js";

const scenes = createSceneManager({
  initial: "menu",
  pages: {
    battle: {
      preload: async ({ params }) => {
        await assets.load(battleManifest(params.level));
      },
      create: () => new Container()
    },
    menu: {
      create: () => new Container()
    }
  }
});

// Manual preload (e.g. while player is on menu)
await scenes.preload("battle", { level: 5 });

// go(...) will also run preload automatically
await scenes.go("battle", { level: 5 });

Check page existence before navigating

Use exists(pageId) when routes are feature-dependent (DLC, experiments, role-based menus).

Why use it:

  • avoid try/catch just to check route registration
  • safely render optional buttons or entries
if (scenes.exists("shop")) {
  await scenes.go("shop");
}

Get current active scene metadata

Use current() whenever systems outside scene code need active scene metadata.

Why use it:

  • HUD/UI needs to know active scene
  • save/replay systems need scene id + params snapshot
  • debug overlays/devtools need live scene introspection

Returns:

  • null when no scene is active yet
  • otherwise { id, instance, params }
const current = scenes.current();

if (current) {
  console.log(current.id);
  console.log(current.instance);
  console.log(current.params);
}

Reload the current scene

Use reload() to recreate the active scene instance. This is useful for restart/retry flows and resetting scene state.

Why use it:

  • level retry button
  • deterministic reset of transient scene state
  • re-enter current route after external state changes
await scenes.reload();

Keep current params when reloading:

await scenes.reload({ keepParams: true });

Destroy cached scene instances

Use destroy(pageId?) to remove a cached scene instance and run its destroy(...) method when available (useful for GPU/resource cleanup).

Why use it:

  • free GPU memory for scenes not needed soon
  • aggressively clean up between large worlds/modes
  • prepare for custom caching/persistence strategies
scenes.destroy("battle");

Destroy the active scene instance directly:

scenes.destroyCurrent();

Check whether a scene is active

Use isActive(pageId) to skip duplicate flow transitions.

Why use it:

  • guard against repeated pause/menu opens
  • prevent re-triggering scene-specific side effects
if (scenes.isActive("pause")) {
  return;
}

Check whether navigation is allowed

Use canGo(pageId, params?) to run route resolution + guards only, without triggering navigation, preload, or lifecycle hooks.

Why use it:

  • disabled/enabled state for buttons
  • menu validation before showing options
  • "preview availability" checks in UI flows

Behavior:

  • resolves redirects first
  • runs canLeave / canEnter
  • does not change history or active scene
if (await scenes.canGo("multiplayer")) {
  await scenes.go("multiplayer");
}

Replace current history entry

Use replace(pageId, params?) when navigation should not create a new history step.

Why use it:

  • boot -> main menu handoff
  • login -> app handoff
  • cutscene -> gameplay handoff
  • checkpoint reloads where current state should be overwritten

Behavior:

  • navigates like go(...)
  • replaces current history entry instead of pushing a new one
  • keeps back() behavior clean and predictable
await scenes.replace("menu");

Scene events (on, off, once)

Use the event system for integrations like analytics, audio, saves, debugging, and devtools without adding scene-manager core logic.

When to use each event:

  • before-change: pre-transition hooks (audio prewarm, analytics "intent", autosave)
  • change: confirmed navigation/reload success (track screen_view, update global UI)
  • error: central error reporting/logging for scene operations

Listener API:

  • on(event, listener): subscribe and keep listening
  • once(event, listener): subscribe for one event occurrence
  • off(event, listener): remove a specific listener
const unsubscribeChange = scenes.on("change", ({ fromId, toId }) => {
  analytics.track("scene_changed", { fromId, toId });
});

scenes.on("before-change", ({ toId }) => {
  audioManager.preWarmForScene(toId);
});

scenes.on("error", ({ operation, error }) => {
  console.error("Scene manager error:", operation, error);
});

// later
unsubscribeChange();

Core methods and when to call them

  • start(params?): boot the manager at initial; usually called once after app init
  • go(pageId, params?): navigate to a scene; your primary route change API
  • replace(pageId, params?): navigate without adding history; overwrite current entry
  • back() / forward(): move through scene history; useful for UI back buttons and debug navigation
  • preload(pageId, params?): warm scene resources early; call from menus/loading flows
  • canGo(pageId, params?): async guard check for UI gating without navigation
  • exists(pageId): validate route registration before offering navigation
  • isActive(pageId): avoid duplicate transitions for already-open scenes
  • current(): read active { id, instance, params } for external systems
  • reload({ keepParams? }): recreate active scene for retry/reset loops
  • destroy(pageId?) / destroyCurrent(): release cached scene instances/resources

Pixi transition example

runTransition is where you animate the old/new Pixi containers.

const scenes = createSceneManager({
  initial: "menu",
  defaultTransition: { type: "fade", duration: 250 },
  runTransition: async ({ fromInstance, toInstance, spec }) => {
    const from = fromInstance as import("pixi.js").Container | null;
    const to = toInstance as import("pixi.js").Container;

    if (spec.type === "fade") {
      // your tween/RAF fade logic here
    }

    if (spec.type === "slide-left") {
      // your tween/RAF slide logic here
    }

    if (spec.type === "zoom") {
      // your tween/RAF zoom logic here
    }
  },
  pages: {
    menu: { create: () => new Container() },
    game: { create: () => new Container(), transitionIn: { type: "slide-left", duration: 400 } }
  }
});

Assets Manager API

createAssetsManager() returns a loader instance that works in any JavaScript runtime where PixiJS Assets is available (framework apps, vanilla apps, and game engines built on PixiJS).

load(manifest, onProgress?)

Loads assets from a manifest and skips aliases already loaded by this loader instance.

  • manifest supports:
    • array format: [{ alias: "timer_bg", src: "/assets/timer-bg.png" }]
    • object format: { timer_bg: "/assets/timer-bg.png" }
  • onProgress receives a value from 0 to 1
await loader.load(manifest, (progress) => {
  console.log("Progress:", progress);
});

get(alias)

Returns a previously loaded asset from PixiJS Assets.

const texture = loader.get("timer_bg");

has(alias)

Checks whether an alias is tracked as loaded by this loader instance.

if (loader.has("timer_bg")) {
  console.log("timer_bg is loaded");
}

unload(manifest)

Unloads only the assets listed in the provided manifest and removes them from tracked loaded aliases.

await loader.unload([{ alias: "logo", src: "/assets/logo.png" }]);

unloadAll()

Unloads all assets currently tracked by this loader instance.

await loader.unloadAll();