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

focus-target

v0.3.4

Published

Focus management utility that allows React developers to easily create navigation flows.

Downloads

3

Readme

Focus Target

GitHub repo size GitHub npm

Focus Target is a focus management utility that allows React developers to easily create navigation flows and control where and how the focus in the page goes. You can set keyboard shortcuts and define what element will have the initial focus.

You can find a live demo here.

:star2: Features

  • :thumbsup: React Component with a non-intrusive syntax.
  • :gear: Custom hook to provide more flexibility.
  • :keyboard: Set your own keyboard shortcuts. As many as you like.
  • :mag: Initial focus definition.
  • :shield: Built with TypeScript.

:computer: Installation

You can get it through NPM.

npm install --save focus-target

:hammer_and_wrench: Usage

Here's how to use the component:

import React from "react";
import { EventBoundary } from "focus-target";
const targets = [
  {
    name: "firstName",
    keys: [["Control", "Alt", "1"]],
  },
  {
    name: "lastName",
    keys: [["Control", "Alt", "2"]],
  },
  {
    name: "age",
    previous: "lastName",
    keys: [["Control", "Alt", "3"]],
  },
];
export function App() {
  return (
    <EventBoundary targets={targets} initialFocus="firstName">
      <label>First name:</label>
      <input name="firstName" type="text" />
      <label>Last name:</label>
      <input name="lastName" type="text" />
      <label>Age:</label>
      <input name="age" type="number" />
    </EventBoundary>
  );
}

This is the Target type:

 type Target = {
  name: string;
  previous?: string;
  keys: string[][];
}

The EventBoundary takes an array of Target objects. The initialFocus basically receives the name of the input used to apply the focus on once the component mounts.

The targets themselves are composed of the values of the name attribute of the inputs, the event.key value for any keys you decide to use and the previous element. The previous element corresponds to the element that is focused at the moment you press the keys shortcut. Look at this target taken from the example:

{
  name: "age",
  previous: "lastName",
  keys: [["Control", "Alt", "3"]],
}

This target determines that the shortcut Control + Alt + 3 is only going to work if the input with the name lastName is focused at the moment the shortcut is pressed.

EventBoundary only captures events when itself or its inputs are focused. In order to capture events globally, you should use the useFocusTarget hook described further down.

Lastly, you should know that refs and event handlers are being passed to the elements under the hood. They are required to make the event capturing and focus work properly. But they are only going to work if the inputs are at the first nesting level. The following example wouldn't work. Note how the inputs are inside the labels, therefore not in the first nesting level.

export function App() {
  return (
    <EventBoundary targets={targets} initialFocus="firstName">
      <label>
        First name: <input name="firstName" type="text" />
      </label>
      <label>
        Last name: <input name="lastName" type="text" />
      </label>
      <label>
        Age:
        <input name="age" type="number" />
      </label>
    </EventBoundary>
  );
}

Here's how to use the useFocusTarget hook:

import React, { useEffect } from "react";
import { useFocusTarget } from "focus-target";

const targets = [
  {
    name: "firstName",
    keys: [["Control", "Alt", "1"]],
  },
  {
    name: "lastName",
    keys: [["Control", "Alt", "2"]],
  },
  {
    name: "age",
    previous: "lastName",
    keys: [["Control", "Alt", "3"]],
  },
];

export function App() {
  const {
    getRef,
    handleKeyDown,
    handleKeyUp,
    handleFocus,
    focus,
  } = useFocusTarget(targets, false);
  useEffect(() => {
    focus("firstName");
  }, []);
  return (
    <div onKeyDown={handleKeyDown} onKeyUp={handleKeyUp}>
      <label>First name:</label>
      <input
        name="firstName"
        type="text"
        ref={getRef("firstName")}
        onFocus={handleFocus}
      />
      <label>Last name:</label>
      <input
        name="lastName"
        type="text"
        ref={getRef("lastName")}
        onFocus={handleFocus}
      />
      <label>Age:</label>
      <input
        name="age"
        type="number"
        ref={getRef("age")}
        onFocus={handleFocus}
      />
    </div>
  );
}

The useFocusTarget hook can be used instead of the EventBoundary component. It takes two arguments: the targets and a boolean to indicate whether the event capturing will be global or not.

In the above example the global event capturing is deactivated and a div was used to wrap the inputs inside the handleKeyDown and handleKeyUp handlers. Activating global event capturing would make these two handlers be attached to the window object. In addition, useEffect was used to setup the initial focus on the firstName input once the component mounts.

getRef returns a referent to be attached to the correspondent input and handleFocus is used in order to know which component is currently focused.

:email: Contact

If you want to contact me, checkout my website https://andersonsouza.dev.

:page_facing_up: License

This project is licensed under the MIT License.