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 🙏

© 2024 – Pkg Stats / Ryan Hefner

pixi-events-x

v1.0.0

Published

Extended Federated Events API. Backwards compatible replacement for PixiJS Event System that supports focus and keyboard events.

Downloads

2

Readme

PixiJS Events X

Extended Federated Events API. Backwards compatible replacement for PixiJS Event System that supports focus and keyboard events.

Feature highlight:

  • focus system with focus, blur, focusin and focusout events
  • keyup and keydown event propagation to focused graph path
  • tab/shift+tab navigation
  • tab order by tabIndex
  • disconnected scene graphs support

Getting started

Install package:

npm install pixi-events-x

Make your PixiJS html mount point focusable (set tabindex attribute). If you also want tab/shift+tab navigation support, make it tabbable (set non-negative tabindex attribute).

<canvas ... tabindex="0" />

Then import module:

import 'pixi-events-x'

Now you can use it like this:

import type { FederatedFocusEvent, FederatedKeyboardEvent } from 'pixi-events-x'

// you can use any descendant of DisplayObject
const someObject = new Container()

// it has to be interactive
someObject.eventMode = 'static'
// make it just focusable (negative values) or also tabbable (zero and positive values)
// it works same as dom `tabindex` attribute
someObject.tabIndex = 0

// subscribe to events
// events work same as their analogs in dom
someObject.on('focus', (event: FederatedFocusEvent) => {})
someObject.on('keydown', (event: FederatedKeyboardEvent) => {})

Disconnected scene graphs

Original PixiJS Event System is meant to provide user ability to manage disconnected scene graphs by nested EventBoundary. You can read more about it here.

pixi-events-x supports this feature too. It provides its own EventBoundary with bindNestedBoundary method that binds two boundaries to propagate events down to disconnected scene graph and manage focus transition. There is also unbindNestedBoundary method to undo binding.

// root of disconnected scene graph
const nestedBoundaryRoot = new Container()
// EventBoundary that will be manage disconnected scene graph
const nestedBoundary = new EventBoundary(nestedBoundaryRoot)

// renderer.eventsX is the same renderer.events, but with proper type
const rootBoundary = renderer.eventsX.rootBoundary
// and yes, they are really the same
console.log(renderer.events === renderer.eventsX) // true

// connection point
const host = rootBoundary.rootTarget.addChild(new Container())
// it should be interactive
host.eventMode = 'static'

rootBoundary.bindNestedBoundary(nestedBoundary, host)

There is an official example of nested boundary. Let's modify it for pixi-events-x compatibility.

import { EventBoundary } from 'pixi-events-x'

class Projector extends DisplayObject {
  constructor(rootBoundary: EventBoundary) {
    this.content = new Container()

    this.rootBoundary = rootBoundary
    this.boundary = new EventBoundary(this.content)

    // same code as in example
    this.originalTransform = new Matrix()
    this.boundary.copyMouseData = (from, to) => { /* ... */ }

    this.evenMode = 'static'

    this.rootBoundary.bindNestedBoundary(this.boundary, this)
  }

  override destroy(options?: boolean | IDestroyOptions | undefined): void {
    this.rootBoundary.unbindNestedBoundary(this.boundary, this)
    this.rootBoundary = null

    super.destroy(options)
  }

  /* ... */
}

const projector = new Projector(renderer.eventsX.rootBoundary)

/* ... */

You can think about disconnected scene graph as shadow dom. Focus behavior will be pretty much the same.

Programmatic focus management

Unlike dom, pixi-events-x doesn't provide focus/blur methods directly on DisplayObject. You should use EventBoundary instead.

const focusableTarget = new Container()
focusableTarget.eventMode = 'static'
focusableTarget.tabindex = -1

const boundary = renderer.eventsX.rootBoundary
boundary.rootTarget.addChild(focusableTarget)

// set focus on target
boundary.focus(focusableTarget)
// current focus target
boundary.activeElement // focusableTarget
// remove focus from current focus target
boundary.blur()
boundary.activeElement // null

// you can set activeElement directly
boundary.activeElement = focusableTarget

// but setting value directly is different from using focus method
// it doesn't care about focusability or interactivity

const nonFocusableTarget = new EventTarget()
focusableTarget.addChild(nonFocusableTarget)

boundary.activeElement = nonFocusableTarget
boundary.activeElement // nonFocusableTarget

boundary.focus(nonFocusableTarget)
boundary.activeElement // null

// instead of setting null value
// focus method also can find first focusable target
// among all parents of non-focusable target
boundary.focus(nonFocusableTarget, false)
boundary.activeElement // focusableTarget

Caveats

Like in dom, the focused target will lose focus if it becomes disconnected from the scene graph. You can disable this feature per EventBoundary by autoBlurDisconnectedTarget property.

renderer.eventsX.rootBoundary.autoBlurDisconnectedTarget = false

Unlike in dom, the focused target will NOT lose focus if it becomes non-focusable or non-interactive.