# filter-suggest

> Dynamic filter suggestion for advanced search query syntax

Latest version **3.5.5** (published 2020-01-22) · MIT license · 0 weekly downloads

## Install

```sh
npm install filter-suggest
pnpm add filter-suggest
yarn add filter-suggest
bun add filter-suggest
```

## Health

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

Positive: esm support; no vulnerabilities.

Warnings: low downloads; no types.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 3.5.5 |
| Published | 2020-01-22 |
| First published | 2019-01-24 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | ESM + CommonJS |
| Dependencies | 4 |
| Unpacked size | 26.3 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Dan Kwiatkowski |
| Maintainers | dan-kwiat |
| Keywords | react-component, component, advanced, dynamic, search, input, syntax, filter, query, dropdown, prefix, suggest, suggester, auto |

## Links

- npm: https://www.npmjs.com/package/filter-suggest
- Repository: https://github.com/dan-kwiat/filter-suggest
- Homepage: https://dan-kwiat.github.io/filter-suggest
- npm.io page: https://npm.io/package/filter-suggest

## Dependencies (4)

- [downshift](https://npm.io/package/downshift.md) ^3.2.7
- [@material/react-list](https://npm.io/package/@material/react-list.md) ^0.15.0
- [@rmwc/circular-progress](https://npm.io/package/@rmwc/circular-progress.md) ^5.7.0
- [@material/react-text-field](https://npm.io/package/@material/react-text-field.md) ^0.15.0

## Recent versions

- 3.5.5 (latest) — 2020-01-22
- 3.5.4 — 2019-11-13
- 3.5.3 — 2019-11-12
- 3.5.2 — 2019-11-12
- 3.5.1 — 2019-11-11
- 3.5.0 — 2019-11-11
- 3.4.0 — 2019-10-31
- 3.3.2 — 2019-10-31
- 3.3.1 — 2019-10-31
- 3.3.0 — 2019-10-31
- 3.2.0 — 2019-03-26
- 3.1.2 — 2019-03-21
- 3.1.1 — 2019-03-21
- 3.1.0 — 2019-03-21
- 3.0.1 — 2019-03-20
- … 13 more at https://npm.io/package/filter-suggest/versions

## README

# FilterSuggest

A react component for achieving search-as-you-type functionality on a list of option items.  The actual sorting & filtering of items is left up to you, making it easy to combine data from multiple sources (synchronous & asynchronous).

Implemented using [downshift](http://npmjs.com/package/downshift) and [material-components-web-react](https://github.com/material-components/material-components-web-react).

[![Travis][build-badge]][build]
[![npm package][npm-badge]][npm]
[![Coveralls][coveralls-badge]][coveralls]

[build-badge]: https://img.shields.io/travis/user/repo/master.png?style=flat-square
[build]: https://travis-ci.org/user/repo

[npm-badge]: https://img.shields.io/npm/v/npm-package.png?style=flat-square
[npm]: https://www.npmjs.org/package/npm-package

[coveralls-badge]: https://img.shields.io/coveralls/user/repo/master.png?style=flat-square
[coveralls]: https://coveralls.io/github/user/repo

* [Demo](#demo)
* [Installation](#installation)
* [Examples](#examples)
  * [Sync](#sync)
  * [Async](#async)
* [Props](#props)
* [Styles](#styles)


## Demo

[https://dan-kwiat.github.io/filter-suggest](https://dan-kwiat.github.io/filter-suggest)


## Installation

With Yarn:

```
yarn add filter-suggest
```

Or npm:

```
npm install --save filter-suggest
```

You'll need to have the peer dependencies installed too:

```json
{
  "prop-types": "15.x",
  "react": "16.x"
},
```

## Examples

### Sync

A basic synchronous example using [match-sorter](https://www.npmjs.com/package/match-sorter) to sort items:

```jsx
import React, { useState } from 'react'
import FilterSuggest from 'filter-suggest'
import 'filter-suggest/es/index.css'
import matchSorter from 'match-sorter'

const ITEMS = [
  {
    id: `movie-1`,
    icon: null,
    primary: 'movie:The Big Short',
    secondary: 'Filter by movie',
  },
  // add more items here
]

const Demo = () => {
  const [inputValue, setInputValue] = useState('')
  const sortedItems = inputValue ? matchSorter(
    ITEMS,
    inputValue,
    { keys: ['primary'] }
  ) : []
  return (
    <FilterSuggest
      inputValue={inputValue}
      label='Start typing...'
      onInputValueChange={setInputValue}
      onSelect={item => {
        // deal with selected item here
      }}
      items={sortedItems}
    />
  )
}
```

See the [demo source code](./demo/src) for a more comprehensive synchronous example.

### Async

A basic asynchronous example using a dummy GraphQL endpoint to fetch sorted items:

```jsx
import React, { Component } from 'react'
import debounce from 'lodash.debounce'
import gql from 'graphql-tag'
import { Query } from 'react-apollo'
import FilterSuggest from 'filter-suggest'
import 'filter-suggest/es/index.css'

const DEBOUNCE_TIME = 100
const applyDebounced = debounce((f, x) => f(x), DEBOUNCE_TIME)

const QUERY = gql`
  query GET_ITEMS(
    $search: String!
  ) {
    getItems(
      search: $search
    ) {
      id
      primary
      secondary
    }
  }
`

class AsyncDemo extends Component {
  state = {
    inputValue: '',
    variables: {
      search: '',
    }
  }
  setInputValue = inputValue => {
    this.setState({ inputValue })
  }
  setVariables = variables => {
    this.setState({ variables })
  }
  onInputValueChange = value => {
    this.setInputValue(value)
    applyDebounced(this.setVariables, { search: value })
  }
  render() {
    const { inputValue, variables } = this.state
    return (
      <Query query={QUERY} variables={variables}>
        {({ data, loading, error }) => {
          return (
            <FilterSuggest
              inputValue={inputValue}
              label='Search async'
              loading={loading}
              onInputValueChange={this.onInputValueChange}
              onSelect={item => {
                // handle selected item
              }}
              items={inputValue && data ? data.getItems : []}
            />
          )
        }}
      </Query>
    )
  }
}
```

For a seamless search-as-you-type experience, results should be returned very quickly (say of the order 100ms).  You might want to look at [Elasticsearch completion suggester](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-completion.html) or [PostgreSQL trigram indices](https://www.postgresql.org/docs/current/pgtrgm.html).

See [charity-base-search](https://www.npmjs.com/package/charity-base-search) for a real-world asynchronous example.

## Props

FilterSuggest accepts the following props:

```js
FilterSuggest.propTypes = {
  // Optional class applied to the parent div
  className: PropTypes.string,
  // Error message to render instead of dropdown
  errorMessage: PropTypes.string,
  // The current value of the input (you must handle the state yourself)
  inputValue: PropTypes.string.isRequired,
  // An array of items to render in the dropdown
  items: PropTypes.arrayOf(PropTypes.shape({
    // A unique item id
    id: PropTypes.string.isRequired,
    // An optional icon to render on the left
    icon: PropTypes.element,
    // The main text to display on the item
    primary: PropTypes.string.isRequired,
    // Secondary text to display below the main text (useful for giving prompts)
    secondary: PropTypes.string,
    // You may want to provide additional item props here (for use in the onSelect callback)
  })).isRequired,
  // The input label
  label: PropTypes.string,
  // Optional icon element to prefix the input
  leadingIcon: PropTypes.element,
  // Whether or not the items are loading
  loading: PropTypes.bool,
  // Maximum number of items to render in dropdown list
  maxSuggestions: PropTypes.number,
  // Optional class applied to the dropdown menu
  menuClassName: PropTypes.string,
  // Blur event handler
  onBlur: PropTypes.func,
  // Focus event handler
  onFocus: PropTypes.func,
  // A callback fired whenever an input value change is detected
  onInputValueChange: PropTypes.func.isRequired,
  // A callback fired whenever an item is selected
  onSelect: PropTypes.func.isRequired,
  // Whether or not to render the outlined variant of text field
  outlined: PropTypes.bool,
  // Optional class applied to the input element's parent
  textFieldClassName: PropTypes.string,
}
FilterSuggest.defaultProps = {
  label: 'Start typing...',
  maxSuggestions: 12,
}
```

## Styles

With CSS:

```js
import 'filter-suggest/es/index.css'
```

With Sass:

```js
import 'filter-suggest/es/index.scss'
```

The colour theme can be customised using the following Sass mixin:

```scss
$mdc-theme-primary: #00ff00;
```

For further customisation see MDC Web's mixins for the [text field](https://github.com/material-components/material-components-web/blob/master/packages/mdc-textfield/README.md#sass-mixins) and [list](https://github.com/material-components/material-components-web/blob/master/packages/mdc-list/README.md#sass-mixins).

You may also supply `textFieldClassName` and `menuClassName` props which will be applied to the appropriate components.

---
_Source: https://npm.io/package/filter-suggest · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
