# 5app-use-item-list

> Manage indexed collections in React using hooks.

Latest version **0.1.1** (published 2021-02-23) · MIT license · 0 weekly downloads

## Install

```sh
npm install 5app-use-item-list
pnpm add 5app-use-item-list
yarn add 5app-use-item-list
bun add 5app-use-item-list
```

## Health

**Score 30/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.1.1 |
| Published | 2021-02-23 |
| First published | 2021-02-23 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 2 |
| Unpacked size | 103 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | Travis Arnold |
| Maintainers | diondiondion |
| Keywords | react, indexed, collection, lists, accessibility, aria, activedescendant |

## Links

- npm: https://www.npmjs.com/package/5app-use-item-list
- Repository: https://github.com/diondiondion/use-item-list
- Homepage: https://github.com/diondiondion/use-item-list#readme
- Issues: https://github.com/diondiondion/use-item-list/issues
- npm.io page: https://npm.io/package/5app-use-item-list

## Dependencies (2)

- [mitt](https://npm.io/package/mitt.md) ^1.2.0
- [use-constant](https://npm.io/package/use-constant.md) ^1.0.0

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 0.1.1 (latest) — 2021-02-23

## README

# 🕹 useItemList

A primitive React hook used to coordinate indexed collections effortlessly.

## Why?

The ergonmics of managing indexes in React is lacking. When building lower level components for accessibility purposes, managing indexes can become painful and expose internals of an API that consumers shouldn't necessarily need to know about.

This library aims to solve managing indexed collections of items as easily as possible while letting users still compose, optimize, and use React like they are used to.

## API

```jsx
import React, { useRef } from 'react'
import { useItemList } from 'use-item-list'

function Item({ useItem, children }) {
  const ref = useRef()
  const { id, index, highlight, select, selected, useHighlighted } = useItem({
    ref, // required ref used to scroll item into view when highlighted
    value: children, // value passed back in useItemList onSelect
    disabled: false, // prevents item from being highlighted/selected
    text: null, // used for highlightItemByString function
  })
  return (
    <li ref={ref} id={id}>
      {children}
    </li>
  )
}

function List({ value, onChange }) {
  const {
    controllerId,
    listId,
    getHighlightedIndex,
    getHighlightedItem,
    setHighlightedItem,
    moveHighlightedItem,
    clearHighlightedItem,
    selectHighlightedItem,
    useHighlightedItemId,
    highlightItemByString,
    useItem,
  } = useItemList({
    selected: value, // the current selected value
    onSelect: onChange, // callback when item has been selected
  })
  return (
    <ul>
      <Item useItem={useItem}>Item 1</Item>
      <Item useItem={useItem}>Item 2</Item>
      <Item useItem={useItem}>Item 3</Item>
    </ul>
  )
}
```

## Usage

In a somewhat trivial example, we can see how to build a custom select menu:

```jsx
import React, { createContext, useContext, useRef } from 'react'
import { useItemList } from 'use-item-list'

const SelectContext = createContext()

export function Select({ children, value, onChange }) {
  const itemList = useItemList({
    selected: value,
    onSelect: onChange,
  })
  const itemId = itemList.useHighlightedItemId()
  return (
    <SelectContext.Provider value={itemList}>
      <ul
        id={itemList.listId}
        tabIndex={0}
        role="listbox"
        aria-activedescendant={itemId}
        style={{ padding: 0 }}
        onKeyDown={(event) => {
          if (event.key === 'ArrowUp') {
            event.preventDefault()
            itemList.moveHighlightedItem(-1)
          }
          if (event.key === 'ArrowDown') {
            event.preventDefault()
            itemList.moveHighlightedItem(1)
          }
          if (event.key === ' ' || event.key === 'Enter') {
            event.preventDefault()
            itemList.selectHighlightedItem()
          }
          itemList.highlightItemByString(event)
        }}
      >
        {children}
      </ul>
    </SelectContext.Provider>
  )
}

export function Option({ children, text, value }) {
  const { useItem, clearHighlightedItem } = useContext(SelectContext)
  const ref = useRef()
  const { id, highlight, select, selected, useHighlighted } = useItem({
    ref,
    text,
    value,
  })
  const highlighted = useHighlighted()
  return (
    <li
      ref={ref}
      id={id}
      role="option"
      aria-selected={selected}
      onMouseOver={highlight}
      onMouseOut={clearHighlightedItem}
      onMouseDown={select}
    >
      {children} {selected && '✅'}
    </li>
  )
}
```

Now users of our component have an easy-to-use API that resembles the ergonomics of the web's select element:

```jsx
<Select>
  <Option value="apple">Apple 🍎</Option>
  <Option value="banana">Banana 🍌</Option>
  <Option value="pear">Pear 🍐</Option>
</Select>
```

Please note this is not a fully accessible example. See the examples directory for more full-fledged examples.

---
_Source: https://npm.io/package/5app-use-item-list · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
