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

react-search-headless

v1.4.1

Published

Headless React search box

Downloads

9

Readme

react-search-headless

Headless React search box

NPM JavaScript Style Guide

Install


npm install --save react-search-headless

Example

Live example

Purpose

This repository provides a headless search component for React, alongside some out-of-the-box implementations of it.

It provides a bunch of core functions for running a search on a set of data with a host of parameters to control what is searched for, how and how it is returned. This lets you implement your search component UI exactly as you want it, and let the library take care of the search itself.

You can use pretty much any type of data for the search data, the library takes care of dealing with the different type of data, nested data, arrays and arrays of objects.

Additionally, it allows to run a search with different parameters for given entities in your data set. If you have users and teams in one dataset, you can control how a single search across the whole dataset is run differently for users and teams.

If you want a quick implementation instead, you can use the SearchBox and SearchBoxGrouped components directly, with some standard styling parameters, or the complete out-of-the-box StyledSearchBox and StyledSearchBoxGrouped

Much more to come!

Methods & props

prop: parameters

This is the core of the search, defining how you want to match the query and data.

Props

Props name | Required | Type | Description ------------ | ------------- | ------------- | ------------- searchKeys | false | array | If omitted, the search will run on all keys in this object. If defined, lists the keys on which the search must be run. It allows for . notation, i.e.: targeting attributes lower in the object keys tree. searchDepth | false | number | If omitted, the search will run exhaustively through the object keys tree. Allows to define how deep in the tree you want the search to run (useful in case of massive amount of deeply nested data, to improve performance). For most cases, this can be omitted. minCar | false | number | If omitted, the run will run from the first letter typed. Controls when to start running the search before returning results. fuzzySensibility | false | number | Number between 0 and 1, 0 returning only exact matches, 1 returning everything. Controls the degree of fuzzy search sensitivity. Only use for fuzzy searches. idKey | true | string | The key to use as a unique reference for each data row returned by the search. renderName | true | function | A function that takes a returned data row from the search and outputs a human-readable name. Set it to (item) => {} if you don't want it to return anything. renderMeta | true | function | A function that takes a returned data row from the search and outputs a metadata object. Set it to (item) => {} if you don't want it to return anything.

Implementation
const paramSearch = {
	searchKeys: ['name', 'location.address'],
	searchDepth: 2,
	minCar: 4,
	fuzzySensibility: 0.2,
	idKey:  'id',
	renderName: (item) =>  item.firstName && item.lastName,
	renderMeta: (item) =>  item,
}

method: filter()

Takes a data set, search parameters and a query then returns an array of data of the form:

[
	{
		value: `idKey provided`,
		name: `result of renderName`,
		meta: `result of renderMeta`
	},
	{
		...
	}
]
Implementation
import { useSearch } from  'react-search-headless'

const MyComponent = () => {
	const { filter } = useSearch();

	const results = filter(data,parameters,'strict',query);
	
	{/* Do something with results */}

}
Props

Props name | Required | Type | Description ------------ | ------------- | ------------- | ------------- data | true | array | The data to run the search on. This can be any type of array, including an array of objects. parameters | true | object | The parameters objects for the search. Defines how the search is done. See above for more details on object props. searchType | false | string | Can be 'strict' or 'fuzzy'. Strict search will look for an exact match, but non-case sensitive. Fuzzy will rely on Fuse.js to identify a list of approximate matches. query | true | string | The search string you are looking for.

method: filterGrouped()

Takes a data set, search parameters and a query then returns an object of the form:

{
	planets:
	{
		[
			{
				value: `idKey provided`,
				name: `result of renderName`,
				meta: `result of renderMeta`
			},
			{
				...
			}
		]
	},
	satellites:
	{
		[
			{
				value: `idKey provided`,
				name: `result of renderName`,
				meta: `result of renderMeta`
			},
			{
				...
			}
		]
	},
}

where each key in the object is one of the keys provided to searchKeys, or if omitted, the initial data object.

Implementation
import { useSearch } from  'react-search-headless'

const MyComponent = () => {
	const { filterGrouped } = useSearch();

	const results = filterGrouped(data,parameters,'strict',query);
	
	{/* Do something with results */}

}
Props

Props name | Required | Type | Description ------------ | ------------- | ------------- | ------------- data | true | object | The data to run the search on. This can be any type of object. parameters | true | object of parameters prop | The parameters objects for the search, composed of one standard parameter prop object per key you want to search on. Defines how the search is done. See above for more details on object props. Example: parameters={planets: {searchKey: ['name'], idKey: 'id', renderName: (item) => item.name, renderMeta: (item) => item}, satellites: {searchKey: ['parent'], idKey: 'id', renderName: (item) => item.name, renderMeta: (item) => item}} searchType | false | string | Can be 'strict' or 'fuzzy'. Strict search will look for an exact match, but non-case sensitive. Fuzzy will rely on Fuse.js to identify a list of approximate matches. query | true | string | The search string you are looking for.

method: returnAll()

Takes a data set, return it all:

[
	{
		value: `idKey provided`,
		name: `result of renderName`,
		meta: `result of renderMeta`
	},
	{
		...
	}
]
Implementation
import { useSearch } from  'react-search-headless'

const MyComponent = () => {
	const { returnAll } = useSearch();

	const results = returnAll(data,parameters);
	
	{/* Do something with results */}

}
Props

Props name | Required | Type | Description ------------ | ------------- | ------------- | ------------- data | true | object | The data to run the search on. This can be any type of object. parameters | true | object | The parameters objects for the returned results. See above for more details on object props. Only uses idKey, renderName and renderMeta. All other props will be ignored.

method: returnAllGrouped()

Takes a data set, return it all:

{
	planets:
	{
		[
			{
				value: `idKey provided`,
				name: `result of renderName`,
				meta: `result of renderMeta`
			},
			{
				...
			}
		]
	},
	satellites:
	{
		[
			{
				value: `idKey provided`,
				name: `result of renderName`,
				meta: `result of renderMeta`
			},
			{
				...
			}
		]
	},
}
Implementation
import { useSearch } from  'react-search-headless'

const MyComponent = () => {
	const { returnAllGrouped } = useSearch();

	const results = returnAllGrouped(data,parameters);
	
	{/* Do something with results */}

}
Props

Props name | Required | Type | Description ------------ | ------------- | ------------- | ------------- data | true | object | The data to run the search on. This can be any type of object. parameters | true | object of parameters prop | The parameters objects for the search, composed of one standard parameter prop object per key you want to search on. See above for more details on object props. Only uses idKey, renderName and renderMeta. All other props will be ignored.

Components

component: SearchBox

Un-styled search box that includes a suggestions list.

Implementation
import { useSearch } from  'react-search-headless'

const MyComponent = () => {
	const { SearchBox } = useSearch();
	
	return(
		<SearchBox
			data={dataSearchBox}
			parameters={paramsSearchBox}
			searchType='strict'
			suggestions={true}
			onFilter={(value) => {
				console.log(value)
			}}
			onSelect={(group, value) => {
				console.log(group, value)
			}}
		/>
	)
}
Props

Props name | Required | Type | Description ------------ | ------------- | ------------- | ------------- data | true | array | The data to run the search on. This can be any type of array, including an array of objects. parameters | true | object | The parameters objects for the search. Defines how the search is done. See above for more details on object props. searchType | false | string | Can be 'strict' or 'fuzzy'. Strict search will look for an exact match, but non-case sensitive. Fuzzy will rely on Fuse.js to identify a list of approximate matches. suggestions | true | boolean | Whether the search box displays a list of suggestions when returning a result. onFilter | true | function | Callback executed whenever a search is conducted. onSelect | true | function | Callback executed whenever an element is selected in the list of suggestions.

component: SearchBoxGrouped

Un-styled search box using grouped data and that includes a suggestions list.

Implementation
import { useSearch } from  'react-search-headless'

const MyComponent = () => {
	const { SearchBoxGrouped } = useSearch();
	
	return(
		<SearchBoxGrouped
			data={dataSearchBoxGrouped}
			parameters={paramsSearchBoxGrouped}
			searchType='strict'
			suggestions={true}
			onFilter={(value) => {
				console.log(value)
			}}
			onSelect={(group, value) => {
				console.log(group, value)
			}}
		/>
	)
}
Props

Props name | Required | Type | Description ------------ | ------------- | ------------- | ------------- data | true | object | The data to run the search on. This can be any type of object. parameters | true | object of parameters prop | The parameters objects for the search, composed of one standard parameter prop object per key you want to search on. Defined how the search is done. See above for more details on object props. Example: parameters={planets: {searchKey: ['name'], idKey: 'id', renderName: (item) => item.name, renderMeta: (item) => item}, satellites: {searchKey: ['parent'], idKey: 'id', renderName: (item) => item.name, renderMeta: (item) => item}} searchType | false | string | Can be 'strict' or 'fuzzy'. Strict search will look for an exact match, but non-case sensitive. Fuzzy will rely on Fuse.js to identify a list of approximate matches. suggestions | true | boolean | Whether the search box displays a list of suggestions when returning a result. onFilter | true | function | Callback executed whenever a search is conducted. onSelect | true | function | Callback executed whenever an element is selected in the list of suggestions.

component: StyledSearchBox

Fully-styled search box that includes a suggestions list.

Implementation
import { useSearch } from  'react-search-headless'

const MyComponent = () => {
	const { StyledSearchBox } = useSearch();
	
	return(
		<StyledSearchBox
			data={dataSearchBox}
			parameters={paramsSearchBox}
			searchType='strict'
			suggestions={true}
			variant={variant}
			fontSize={fontSize}
			height={height}
			width={width}
			placeholder={placeholder}
			onFilter={(value) => {
				console.log(value)
			}}
			onSelect={(group, value) => {
				console.log(group, value)
			}}
		/>
	)
}
Props

Props name | Required | Type | Description ------------ | ------------- | ------------- | ------------- data | true | array | The data to run the search on. This can be any type of array, including an array of objects. parameters | true | object | The parameters objects for the search. Defines how the search is done. See above for more details on object props. searchType | false | string | Can be 'strict' or 'fuzzy'. Strict search will look for an exact match, but non-case sensitive. Fuzzy will rely on Fuse.js to identify a list of approximate matches. suggestions | true | boolean | Whether the search box displays a list of suggestions when returning a result. onFilter | true | function | Callback executed whenever a search is conducted. onSelect | true | function | Callback executed whenever an element is selected in the list of suggestions. variant | false | string | One of light or dark. Changes the overall style to dark or light mode. By default, light. height | false | number | Search box height in vh. By default, auto. width | false | number | Search box width in vw. By default, auto. fontSize | false | number | Font size in px. By default, auto. placeholder | false | string | Search box placeholder text. By default, empty.

component: StyledSearchBoxGrouped

Fully-styled search box using grouped data and that includes a suggestions list.

Implementation
import { useSearch } from  'react-search-headless'

const MyComponent = () => {
	const { StyledSearchBoxGrouped } = useSearch();
	
	return(
		<StyledSearchBoxGrouped
			data={dataSearchBoxGrouped}
			parameters={paramsSearchBoxGrouped}
			searchType='strict'
			suggestions={true}
			variant={variant}
			fontSize={fontSize}
			height={height}
			width={width}
			placeholder={placeholder}
			onFilter={(value) => {
				console.log(value)
			}}
			onSelect={(group, value) => {
				console.log(group, value)
			}}
		/>
	)
}
Props

Props name | Required | Type | Description ------------ | ------------- | ------------- | ------------- data | true | object | The data to run the search on. This can be any type of object. parameters | true | object of parameters prop | The parameters objects for the search, composed of one standard parameter prop object per key you want to search on. Defined how the search is done. See above for more details on object props. Example: parameters={planets: {searchKey: ['name'], idKey: 'id', renderName: (item) => item.name, renderMeta: (item) => item}, satellites: {searchKey: ['parent'], idKey: 'id', renderName: (item) => item.name, renderMeta: (item) => item}} searchType | false | string | Can be 'strict' or 'fuzzy'. Strict search will look for an exact match, but non-case sensitive. Fuzzy will rely on Fuse.js to identify a list of approximate matches. suggestions | true | boolean | Whether the search box displays a list of suggestions when returning a result. onFilter | true | function | Callback executed whenever a search is conducted. onSelect | true | function | Callback executed whenever an element is selected in the list of suggestions. variant | false | string | One of light or dark. Changes the overall style to dark or light mode. By default, light. height | false | number | Search box height in vh. By default, auto. width | false | number | Search box width in vw. By default, auto. fontSize | false | number | Font size in px. By default, auto. placeholder | false | string | Search box placeholder text. By default, empty.

Usage

Simple search box

import React, { useState } from 'react'
import  { useSearch }  from  'react-search-headless'

const  MyComponent = () => {

	const [results, setResults] = useState();
	const { filter } = useSearch();

	const data = {...}
	const paramsSearch = {
		idKey: 'id',
		renderName: (item) =>  item.firstName && item.lastName,
		renderMeta: (item) =>  item,
	}
	
	return(
	<input
		placeholder='Search anything...'
		onChange={({ target: { value } }) =>
			setResults(
				filter(data,paramsSearch, 'strict', value)
			)}
	/>
	{results &&
	results.length > 0 &&
	results.map((item, index) => (
		<p  key={index}>{JSON.stringify(item.metadata)}</p>
	))}
}

Simple search box with named keys

import React, { useState } from 'react'
import  { useSearch }  from  'react-search-headless'

const  MyComponent = () => {

	const [results, setResults] = useState();
	const { filter } = useSearch();

	const data = {...}
	const paramsSearch = {
		searchKeys: ['lastName'], // We are only searching on lastName
		idKey: 'id',
		renderName: (item) =>  item.firstName && item.lastName,
		renderMeta: (item) =>  item,
	}
	
	return(
	<input
		placeholder='Search anything...'
		onChange={({ target: { value } }) =>
			setResults(
				filter(data,paramsSearch, 'strict', value)
			)}
	/>
	{results &&
	results.length > 0 &&
	results.map((item, index) => (
		<p  key={index}>{JSON.stringify(item.metadata)}</p>
	))}
}

Simple search box with search depth

import React, { useState } from 'react'
import  { useSearch }  from  'react-search-headless'

const  MyComponent = () => {

	const [results, setResults] = useState();
	const { filter } = useSearch();

	const data = {...}
	const paramsSearch = {
		searchDepth: 2, // We are only searching to a depth of 2 levels across all keys, 
		//i.e.: ignoring an attribute such as data.location.address.formatted_address
		idKey: 'id',
		renderName: (item) =>  item.firstName && item.lastName,
		renderMeta: (item) =>  item,
	}
	
	return(
	<input
		placeholder='Search anything...'
		onChange={({ target: { value } }) =>
			setResults(
				filter(data,paramsSearch, 'strict', value)
			)}
	/>
	{results &&
	results.length > 0 &&
	results.map((item, index) => (
		<p  key={index}>{JSON.stringify(item.metadata)}</p>
	))}
}

Grouped filter search box with complex search parameters

import React, { useState } from 'react'
import  { useSearch }  from  'react-search-headless'

const  MyComponent = () => {

	const [results, setResults] = useState();
	const { filterGrouped } = useSearch();

	const data = {...}
	const paramsSearch = {
		planets: {
			searchDepth: 2,
			idKey: 'id',
			renderName: (item) =>  item.name,
			renderMeta: (item) =>  item,
		},
		satellites: {
			searchKeys: ['name','parent.name','mass'],
			idKey: 'id',
			renderName: (item) =>  item.name && ', satellite of ' && item.parent.name,
			renderMeta: (item) =>  item,
		}
	}
	
	return(
	<input
		placeholder='Search anything...'
		onChange={({ target: { value } }) =>
			setResults(
				filterGrouped(data,paramsSearch, 'strict', value)
			)}
	/>
	{results && (
	<div>
		{Object.keys(results).map((item, index) => {
			return (
			<div>
				<div  key={index}>
					<h1>{item}</h1>
				<div>
				{results[item].length > 0 &&
					results[item].map((itemResult, indexResult) => (
						<div
							key={indexResult}
							onClick={() => {
								console.log(JSON.stringify(itemResult))								
								setResults(null)
							}}
						>
							<p>{itemResult.name}</p>
						</div>
				))}
				{results[item].length === 0 && <p>No results</p>}
			</div>
	</div>)

Dependencies

This repository relies on the brilliant library Fuse.js for the fuzzy-search logic.

License

MIT © GwenhaelG