CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pixi--react

React integration for PixiJS enabling declarative 2D graphics programming with JSX and React patterns.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

jsx-elements.mddocs/

JSX Elements

@pixi/react provides type-safe JSX elements for all PixiJS components through a sophisticated type system. Components must be registered with extend() before use, supporting both prefixed and unprefixed usage patterns.

Capabilities

PixiJS Component Elements

All extended PixiJS components are available as JSX elements with automatic type safety and event handling.

/**
 * Type-safe JSX elements for PixiJS components
 * Components must be registered via extend() before use
 */
interface PixiElements extends PrefixedPixiElements {}

type PrefixedPixiElements = {
  [K in keyof UnprefixedPixiElements as `pixi${Capitalize<string & K>}`]: UnprefixedPixiElements[K];
};

type UnprefixedPixiElements = {
  [K in PixiComponents as K extends keyof NameOverrides ? NameOverrides[K] : Uncapitalize<K>]:
  PixiReactElementProps<typeof PIXI[K]>;
};

type PixiReactElementProps<T extends new (...args: any) => any> =
  BaseNodeProps<InstanceType<T>>
  & GraphicsProps<InstanceType<T>>
  & EventHandlers
  & ConstructorOptions<T>;

Usage Examples:

import { extend } from "@pixi/react";
import { Container, Graphics, Text, Sprite } from "pixi.js";

extend({ Container, Graphics, Text, Sprite });

// Basic element usage
const BasicElements = () => (
  <pixiContainer x={100} y={100} alpha={0.8}>
    <pixiText 
      text="Hello World!" 
      x={50} 
      y={50}
      style={{ fontSize: 24, fill: "white" }}
    />
    <pixiSprite 
      texture={myTexture}
      anchor={0.5}
      interactive
      onPointerDown={(event) => console.log("Clicked!", event)}
    />
  </pixiContainer>
);

// All PixiJS properties are supported
const AdvancedElements = () => (
  <pixiContainer 
    x={200} 
    y={150}
    rotation={Math.PI / 4}
    scale={{ x: 1.5, y: 1.5 }}
    pivot={{ x: 50, y: 50 }}
    alpha={0.9}
    visible={true}
    interactive={true}
    interactiveChildren={true}
    hitArea={new Rectangle(0, 0, 100, 100)}
    mask={maskGraphics}
    filters={[blurFilter]}
    zIndex={10}
  >
    <pixiGraphics 
      draw={(graphics) => {
        graphics.clear();
        graphics.setFillStyle({ color: "red" });
        graphics.rect(0, 0, 100, 100);
        graphics.fill();
      }}
      interactive
      onPointerMove={(event) => {
        console.log("Mouse position:", event.global.x, event.global.y);
      }}
    />
  </pixiContainer>
);

Graphics Elements

Graphics components have special support for the draw callback function.

/**
 * Graphics elements support special draw callback for rendering
 */
type GraphicsProps<T> = T extends Graphics ? { draw: DrawCallback } : unknown;

type DrawCallback = (graphics: Graphics) => void;

Usage Examples:

import { extend } from "@pixi/react";
import { Graphics } from "pixi.js";
import { useCallback, useState } from "react";

extend({ Graphics });

// Simple graphics drawing
const SimpleGraphics = () => {
  const drawRect = useCallback((graphics: Graphics) => {
    graphics.clear();
    graphics.setFillStyle({ color: "blue" });
    graphics.rect(0, 0, 100, 100);
    graphics.fill();
  }, []);

  return <pixiGraphics draw={drawRect} x={100} y={100} />;
};

// Dynamic graphics with state
const DynamicGraphics = () => {
  const [color, setColor] = useState("red");
  
  const drawCircle = useCallback((graphics: Graphics) => {
    graphics.clear();
    graphics.setFillStyle({ color });
    graphics.circle(0, 0, 50);
    graphics.fill();
    graphics.setStrokeStyle({ color: "white", width: 2 });
    graphics.stroke();
  }, [color]);

  return (
    <pixiContainer>
      <pixiGraphics 
        draw={drawCircle}
        x={200}
        y={200}
        interactive
        onPointerTap={() => {
          const colors = ["red", "green", "blue", "yellow"];
          const nextColor = colors[Math.floor(Math.random() * colors.length)];
          setColor(nextColor);
        }}
      />
    </pixiContainer>
  );
};

// Complex graphics shapes
const ComplexGraphics = () => {
  const drawShape = useCallback((graphics: Graphics) => {
    graphics.clear();
    
    // Draw a star shape
    graphics.setFillStyle({ 
      color: "gold",
      alpha: 0.8
    });
    
    const outerRadius = 60;
    const innerRadius = 30;
    const points = 5;
    
    graphics.moveTo(outerRadius, 0);
    
    for (let i = 1; i <= points * 2; i++) {
      const radius = i % 2 === 0 ? outerRadius : innerRadius;
      const angle = (i * Math.PI) / points;
      graphics.lineTo(
        Math.cos(angle) * radius,
        Math.sin(angle) * radius
      );
    }
    
    graphics.closePath();
    graphics.fill();
    
    // Add stroke
    graphics.setStrokeStyle({ color: "orange", width: 3 });
    graphics.stroke();
  }, []);

  return <pixiGraphics draw={drawShape} x={300} y={300} />;
};

Event Handling

All PixiJS events are supported with automatic type conversion from React event props.

/**
 * Event handlers for PixiJS interaction events
 * React event prop names are automatically converted to PixiJS event names
 */
interface EventHandlers {
  // Pointer events
  onPointerDown?: (event: FederatedPointerEvent) => void;
  onPointerUp?: (event: FederatedPointerEvent) => void;
  onPointerMove?: (event: FederatedPointerEvent) => void;
  onPointerTap?: (event: FederatedPointerEvent) => void;
  onPointerOver?: (event: FederatedPointerEvent) => void;
  onPointerOut?: (event: FederatedPointerEvent) => void;
  onPointerEnter?: (event: FederatedPointerEvent) => void;
  onPointerLeave?: (event: FederatedPointerEvent) => void;
  
  // Mouse events
  onMouseDown?: (event: FederatedMouseEvent) => void;
  onMouseUp?: (event: FederatedMouseEvent) => void;
  onMouseMove?: (event: FederatedMouseEvent) => void;
  onMouseOver?: (event: FederatedMouseEvent) => void;
  onMouseOut?: (event: FederatedMouseEvent) => void;
  
  // Touch events
  onTouchStart?: (event: FederatedTouchEvent) => void;
  onTouchEnd?: (event: FederatedTouchEvent) => void;
  onTouchMove?: (event: FederatedTouchEvent) => void;
  
  // Wheel events
  onWheel?: (event: FederatedWheelEvent) => void;
}

Usage Examples:

// Interactive sprite with multiple event handlers
const InteractiveSprite = ({ texture }) => {
  const [isHovered, setIsHovered] = useState(false);
  const [isPressed, setIsPressed] = useState(false);

  return (
    <pixiSprite
      texture={texture}
      interactive
      alpha={isHovered ? 0.8 : 1}
      scale={isPressed ? 0.9 : 1}
      onPointerEnter={() => setIsHovered(true)}
      onPointerLeave={() => setIsHovered(false)}
      onPointerDown={() => setIsPressed(true)}
      onPointerUp={() => setIsPressed(false)}
      onPointerTap={(event) => {
        console.log("Tapped at:", event.global.x, event.global.y);
      }}
      onRightClick={(event) => {
        event.preventDefault();
        console.log("Right clicked!");
      }}
    />
  );
};

// Draggable container
const DraggableContainer = ({ children }) => {
  const [isDragging, setIsDragging] = useState(false);
  const [dragStart, setDragStart] = useState({ x: 0, y: 0 });
  const [position, setPosition] = useState({ x: 0, y: 0 });

  return (
    <pixiContainer
      x={position.x}
      y={position.y}
      interactive
      onPointerDown={(event) => {
        setIsDragging(true);
        setDragStart({
          x: event.global.x - position.x,
          y: event.global.y - position.y,
        });
      }}
      onPointerMove={(event) => {
        if (isDragging) {
          setPosition({
            x: event.global.x - dragStart.x,
            y: event.global.y - dragStart.y,
          });
        }
      }}
      onPointerUp={() => setIsDragging(false)}
      onPointerUpOutside={() => setIsDragging(false)}
    >
      {children}
    </pixiContainer>
  );
};

Component Properties

All PixiJS component properties are supported with full type safety.

/**
 * Base properties available on all PixiJS components
 */
interface BaseNodeProps<T> {
  /** Child components (Container types only) */
  children?: T extends Container ? PixiReactChildNode : never;
  /** React key for list rendering */
  key?: Key;
  /** React ref for imperative access */
  ref?: Ref<T>;
}

/**
 * Constructor options and properties from PixiJS components
 * Automatically inferred from the component class
 */
type ConstructorOptions<T> = ExcludeFunctionProps<T>;

Usage Examples:

// Container with all supported properties
const FullContainer = () => (
  <pixiContainer
    // Transform properties
    x={100}
    y={150}
    rotation={Math.PI / 6}
    scale={{ x: 1.2, y: 1.2 }}
    skew={{ x: 0.1, y: 0 }}
    pivot={{ x: 50, y: 50 }}
    anchor={0.5} // If supported by component
    
    // Display properties
    alpha={0.8}
    visible={true}
    renderable={true}
    
    // Interaction properties
    interactive={true}
    interactiveChildren={true}
    buttonMode={true}
    cursor="pointer"
    
    // Rendering properties
    mask={maskObject}
    filters={[blurFilter, colorFilter]}
    cacheAsBitmap={false}
    
    // Layout properties
    zIndex={5}
    sortableChildren={true}
    
    // Event properties
    onPointerDown={(event) => console.log("Clicked")}
  >
    {/* Children go here */}
  </pixiContainer>
);

// Text with typography properties
const StyledText = () => (
  <pixiText
    text="Styled Text"
    style={{
      fontFamily: "Arial",
      fontSize: 24,
      fill: "white",
      stroke: "black",
      strokeThickness: 2,
      fontWeight: "bold",
      textAlign: "center",
    }}
    anchor={0.5}
    x={400}
    y={300}
  />
);

// Sprite with texture properties
const ConfiguredSprite = ({ texture }) => (
  <pixiSprite
    texture={texture}
    anchor={{ x: 0.5, y: 1 }}
    tint="0xff0000"
    blendMode="multiply"
    pluginName="batch"
    roundPixels={true}
  />
);

Type Safety Features

The JSX element system provides comprehensive type safety:

  • Property Validation: All component properties are type-checked
  • Event Type Safety: Event handlers receive properly typed event objects
  • Generic Support: Components maintain generic type parameters where applicable
  • Conditional Properties: Graphics draw prop only available on Graphics components
  • Ref Types: Refs are properly typed to the underlying PixiJS component

Component Registration

Components must be registered before use:

import { extend } from "@pixi/react";
import { Container, Graphics, Text, Sprite, AnimatedSprite } from "pixi.js";

// Register before using in JSX
extend({
  Container,    // Available as <pixiContainer>
  Graphics,     // Available as <pixiGraphics>
  Text,         // Available as <pixiText>
  Sprite,       // Available as <pixiSprite>
  AnimatedSprite, // Available as <pixiAnimatedSprite>
});

Attempting to use unregistered components will result in TypeScript errors and runtime warnings.

Install with Tessl CLI

npx tessl i tessl/npm-pixi--react

docs

application.md

component-extension.md

hooks.md

index.md

jsx-elements.md

root-creation.md

tile.json