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

tinky-multi-select

v1.0.1

Published

Multi-select component for Tinky CLI framework

Readme

tinky-multi-select

A flexible and interactive multi-select component for building command-line interfaces (CLIs) with Tinky.

Features

  • ✅ Multi-selection: Select multiple items from a list using Space.
  • ⌨️ Keyboard Navigation: Navigate through options using Arrow keys.
  • 📜 Scrolling: efficient rendering for long lists with configurable visible window.
  • 🎨 Theming Support: Fully customizable appearance using tinky-theme.
  • 🧩 Headless Mode: Exports hooks (useMultiSelect, useMultiSelectState) for building custom UI implementations with the same logic.
  • 🔍 Filtering Support: Built-in support for highlighting matched text (filtering logic to be implemented by consumer).

Installation

npm install tinky-multi-select
# or
bun add tinky-multi-select
# or
yarn add tinky-multi-select

Basic Usage

import React, { useState } from "react";
import { render, Text, Box } from "tinky";
import { MultiSelect, type Option } from "tinky-multi-select";

const options: Option[] = [
  { label: "Apple", value: "apple" },
  { label: "Banana", value: "banana" },
  { label: "Cherry", value: "cherry" },
  { label: "Date", value: "date" },
  { label: "Elderberry", value: "elderberry" },
];

function App() {
  const [selected, setSelected] = useState<string[]>([]);
  const [submitted, setSubmitted] = useState(false);

  if (submitted) {
    return <Text color="green">You selected: {selected.join(", ")}</Text>;
  }

  return (
    <Box flexDirection="column">
      <Text>Please select your favorite fruits:</Text>
      <Box marginY={1}>
        <MultiSelect
          options={options}
          onChange={setSelected}
          onSubmit={() => setSubmitted(true)}
        />
      </Box>
      <Text color="gray">
        (Press <Text color="bold">Space</Text> to select,{" "}
        <Text color="bold">Enter</Text> to submit)
      </Text>
    </Box>
  );
}

render(<App />);

Keyboard Controls

| Key | Action | | --------- | -------------------------------------- | | / | Navigate through the options | | Space | Toggle selection of the focused option | | Enter | Submit the selection |

API Reference

<MultiSelect />

The main component for rendering the multi-select list.

| Prop | Type | Default | Description | | -------------------- | --------------------------- | ------------ | --------------------------------------------------------------------------------------- | | options | Option[] | Required | Array of data objects to display as options. | | defaultValue | string[] | [] | Array of values that should be selected initially. | | visibleOptionCount | number | 5 | functionality number of items to show at once. Enables scrolling for larger lists. | | isDisabled | boolean | false | If true, the component will not respond to user input. | | highlightText | string | undefined | Substring to highlight within option labels. Useful when implementing search/filtering. | | onChange | (value: string[]) => void | undefined | Callback fired whenever the selection changes. | | onSubmit | (value: string[]) => void | undefined | Callback fired when the user presses Enter. |

Option Interface

interface Option {
  label: string; // Text to display
  value: string; // Unique identifier
}

Headless Usage (Advanced)

If you need complete control over the rendering but want to re-use the interaction logic, you can use the exported hooks.

useMultiSelectState

Manages the internal state of the selection (cursor position, selected items, scrolling).

import { useMultiSelectState } from "tinky-multi-select";

const state = useMultiSelectState({
  options,
  defaultValue: ["apple"],
  visibleOptionCount: 5,
});

// state.visibleOptions -> options currently in view
// state.focusedValue -> value of the currently highlighted option
// state.value -> array of selected values

useMultiSelect

Connects the state to Tinky's input handling system.

import { useMultiSelect } from "tinky-multi-select";

useMultiSelect({
  state, // return value from useMultiSelectState
  isDisabled: false,
});

Theming

This component uses tinky-theme for styling. You can customize the appearance by providing a theme to your ThemeProvider matching the MULTI_SELECT_COMPONENT_NAME.

The styles object structure:

  • container: File-level box style
  • option: Style for individual option row
  • label: Style for the option text
  • focusIndicator: Style for the cursor/pointer
  • selectedIndicator: Style for the checkmark
  • highlightedText: Style for matched text in filter mode

License

MIT