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

@ue-too/board-pixi-react-integration

v0.19.2

Published

React bindings for [`@ue-too/board-pixi-integration`](https://www.npmjs.com/package/@ue-too/board-pixi-integration). A component that owns the PixiJS app's lifecycle, and hooks that read the board camera without re-rendering the world.

Readme

@ue-too/board-pixi-react-integration

React bindings for @ue-too/board-pixi-integration. A component that owns the PixiJS app's lifecycle, and hooks that read the board camera without re-rendering the world.

npm version license

Install

bun add @ue-too/board-pixi-react-integration pixi.js react

pixi.js (pinned to 8.20.1) and react (^19) are peer dependencies. @ue-too/board-pixi-integration comes with it.

Mounting a canvas

PixiCanvasApp is the whole setup: provider, canvas, and an overlay layer for HTML drawn on top of the Pixi scene.

import { baseInitApp } from '@ue-too/board-pixi-integration';
import { PixiCanvasApp } from '@ue-too/board-pixi-react-integration';

export const Editor = () => (
    <PixiCanvasApp
        option={{ fullScreen: true }}
        initFunction={baseInitApp}
        canvasClassName="h-full w-full"
    >
        <CameraReadout />
    </PixiCanvasApp>
);

initFunction is your own init when you have one — anything returning a superset of BaseAppComponents. Children render inside OverlayContainer, absolutely positioned over the canvas and sized to it, with pointer-events: none so they never steal input from the board.

For a custom layout, compose the pieces yourself: PixiCanvasProvider → PixiCanvas → OverlayContainer.

Reading the camera

Camera hooks are built on useSyncExternalStore and subscribe to the camera's own events, so a pan re-renders only the components that asked for the position:

import {
    useAllBoardCameraState,
    useBoardCameraState,
} from '@ue-too/board-pixi-react-integration';

const zoom = useBoardCameraState('zoomLevel'); // 'position' | 'rotation' | 'zoomLevel'
const { position, rotation, zoomLevel } = useAllBoardCameraState();

Snapshots are cached by value, so position keeps referential equality between frames where it did not actually move — safe to use in a dependency array.

Everything else hangs off usePixiCanvas(), which returns result, a discriminated union of uninitialized / failed / { success: true, components }:

| Hook | What it gives you | | --------------------------- | ------------------------------------------------------------------ | | usePixiCanvas() | the raw result, for reaching into components directly | | useAppTicker(cb) | a callback on Pixi's ticker, added and removed with the app | | useCanvasSize() | renderer width/height, updated on resize (0 × 0 before init) | | useCoordinateConversion() | a function turning a PointerEvent into world coordinates | | useViewportScrollBar() | scrollbar lengths and offsets for the current camera | | useToggleKmtInput() | enable/disable mouse-and-keyboard input, e.g. for a selection mode | | useCanvasPointerDown(cb) | a native pointerdown listener on the canvas element |

appIsReady(result) is the guard these hooks use internally, and is exported for your own effects.

Typing your components

If your initFunction returns more than BaseAppComponents, augment the registry once and every usePixiCanvas() in the app is typed without a generic:

declare module '@ue-too/board-pixi-react-integration' {
    interface PixiCanvasRegistry {
        components: MyAppComponents;
    }
}

In a project with several different canvases, pass the type per call instead: usePixiCanvas<TrainEditorComponents>().

Notes

  • The hook owns canvas creation. useInitializePixiApp builds a fresh <canvas> inside the container on every initialization and detaches it on teardown. Pixi calls WEBGL_lose_context when a renderer is destroyed, and a canvas whose context was lost cannot be reinitialized — so reusing the element would break the second mount.
  • Init runs once per mount, not per render. option and initFunction are read from refs rather than being effect dependencies, so passing an inline object or closure (the normal thing to do) does not re-initialize Pixi on every render.
  • Init and teardown are serialized through a promise chain, so two initializations never overlap — StrictMode's mount→unmount→mount in development, or a fast remount, tears the previous context fully down before creating the next. Overlapping GL contexts on one canvas hard-freeze the GPU process on some drivers.
  • The provider detects apps destroyed by HMR. React Fast Refresh preserves state while the Pixi app may already be gone, so the provider validates the renderer during render and reports uninitialized instead of handing you a destroyed app.
  • teardownComponents runs every registered cleanup, then the base cleanup if it was not already among them, then destroys the app with removeView. Push your own teardown onto components.cleanups.