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

@8x8/oxygen-keyword-search

v3.0.0

Published

Oxygen - keyword search results

Readme

8x8 Oxygen - KeywordSearch

The KeywordSearch component should be used when need to combine search Input with list suggestions as user types in.

Installation

$ yarn add @8x8/oxygen-keyword-search
$ npm install @8x8/oxygen-keyword-search

External Props

  • showSuggestionsDropdown: boolean - boolean(true as default) that shows/hides list of suggestions
  • hasViewAllResults: boolean - boolean(true as default) that offers the "View all results (N)" row. Pass false where no results page sits behind the search: the first suggestion then becomes the first option, and Enter selects it instead of calling onViewAllResults
  • storedSearchValue: string | undefined - represents the applied(stored) filter
  • isLoading: boolean - boolean that indicates that list of suggestions are being fetched
  • searchResults: SearchResults - the results to offer: a flat list of items of either shape, or a list of groups
  • onSearchChange: (value: string) => void - callback function for input change
  • onViewAllResults: (value: string) => void - callback function for "View all results" click/enter
  • onFetchSearchResults: (value: string) => void - callback function that fetch suggestions
  • onClear: () => void - callback function that is called when clear button is fired
  • onSearchResultSelect: (item: SearchResultEntry) => void - callback function for search result item click/enter; receives the selected object by reference, with every property intact
  • background: 'recessed' | 'surface' - which fill the field draws ('recessed' by default, the published look). Use 'surface' on a tinted surface, where the default fill and border are the same token as the surface and an idle field would be invisible against it. Applied through Input's own theme prop, which shallow-merges, so only the fill and border change
  • inputRef: MutableRefObject<HTMLInputElement | null> | ((element: HTMLInputElement | null) => void) - the underlying input, so a host can focus the field (an activation hotkey, or an expandable field that opens focused). Merged with the component's own ref rather than replacing it
  • ariaKeyShortcuts: string - sets aria-keyshortcuts on the input, announcing an activation hotkey such as "/". Registering the key itself is left to the host: which key, and whether the surface listens at all, is application policy, and a document-level listener inside the component would make two instances fight over the same keypress
  • translations: Translations - object of translations strings for different labels/text

Types

    // the legacy item: a bag of numbered strings, joined with a bullet
    interface SearchResultItemType {
      [key: number]: string | undefined
    }

    // the flexible item: only title and subtitle are rendered, every other
    // property is carried through untouched and handed back on select
    interface SearchResultRow {
      id: string | number;
      title: string;
      subtitle?: string;
      [key: string]: unknown;
    }

    type SearchResultEntry = SearchResultItemType | SearchResultRow;

    // a captioned section; items may mix both shapes
    interface SearchResultGroup {
      id: string;
      label?: string;
      items: SearchResultEntry[];
    }

    // the item type is inferred from `searchResults`, so a handler typed to the
    // legacy item keeps compiling; grouped consumers narrow in the handler
    type SearchResults<TItem extends SearchResultEntry = SearchResultEntry> =
      | TItem[]
      | SearchResultGroup<TItem>[];
    interface Translations extends SearchResultTranslations {
      clearButtonTitle: string;
      placeholder: string;
      searchInputAriaLabel: string;
    }

    interface SearchResultTranslations {
      viewAllResultsForText: string;
      viewAllResultsText: string;
      noResultsText: string;
      loadingSearchResultsText: string;
      startTypingText?: string;
      searchResultsAnnouncementText?: string;
      searchResultsAriaLabel?: string;
    }

Usage

    import KeywordSearch from '@8x8/oxygen-keyword-search';
    <KeywordSearch
      translations={{
        clearButtonTitle: 'Clear button',
        placeholder: 'Search',
        searchInputAriaLabel: 'Search input',
        viewAllResultsText: 'View all results',
        noResultsText: "We couldn't find any results for",
        viewAllResultsForText: 'View all results for',
        loadingSearchResultsText: 'Searching for',
        startTypingText: 'Start typing to search',
      }}
      searchResults={
        [
          { 0: 'Joanna Morris' },
          { 0: 'Joanna More', 1: 'Johannesburg – Sales' },
        ]
      }
      showSuggestionsDropdown
      isLoading={false}
      onViewAllResults={(value: string) => {}}
      onSearchResultSelect={(item: SearchResultItemType) => {}}
      onSearchChange={(value: string) => {}}
      onFetchSearchResults={(value: string) => {}}
      onClear={() => {}}
      size="default"
    />