react-datalist-input
Advanced tools
Comparing version 3.0.6 to 3.1.0
@@ -115,6 +115,11 @@ import type { PropsWithChildren, HTMLAttributes, InputHTMLAttributes, ReactNode, CSSProperties, RefObject, MutableRefObject, SetStateAction, Dispatch } from 'react'; | ||
/** | ||
* Alternative function for matching the current input value (needle) and the values of the items array. | ||
* Returns true if item.value is not of type string (all items will be displayed and a custom filter must be used). | ||
*/ | ||
declare const startsWithValueFilter: Filter; | ||
/** | ||
* Default function for matching the current input value (needle) and the values of the items array. | ||
* Returns true if item.value is not of type string (all items will be displayed and a custom filter must be used). | ||
*/ | ||
declare const startsWithValueFilter: Filter; | ||
declare const includesValueFilter: Filter; | ||
declare const useFilters: (items: Array<Item>, value: ComboboxInputProps['value'], filters: Array<Filter>) => [Array<Item>, MutableRefObject<Array<Item>>]; | ||
@@ -157,3 +162,3 @@ declare type LabelOptionProps = { | ||
export type { DatalistInputProps, ComboboxProps, ComboboxInputProps, ListboxProps, ListboxOptionProps, HighlightProps, useComoboxHelpersConfigParams, Item, Filter, }; | ||
export { Combobox, DatalistInput, startsWithValueFilter, useFilters, useComboboxContext, useComboboxControls, useComboboxHelpers, }; | ||
export { Combobox, DatalistInput, startsWithValueFilter, includesValueFilter, useFilters, useComboboxContext, useComboboxControls, useComboboxHelpers, }; | ||
export default DatalistInput; |
@@ -400,3 +400,3 @@ import React, { createContext, forwardRef, useContext, useMemo, useRef, useState, useEffect, useId, useDeferredValue, useCallback } from 'react'; | ||
/** | ||
* Default function for matching the current input value (needle) and the values of the items array. | ||
* Alternative function for matching the current input value (needle) and the values of the items array. | ||
* Returns true if item.value is not of type string (all items will be displayed and a custom filter must be used). | ||
@@ -410,2 +410,12 @@ */ | ||
}; | ||
/** | ||
* Default function for matching the current input value (needle) and the values of the items array. | ||
* Returns true if item.value is not of type string (all items will be displayed and a custom filter must be used). | ||
*/ | ||
var includesValueFilter = function (items, value) { | ||
if (value === void 0) { value = ''; } | ||
return items.filter(function (item) { | ||
return typeof item.value === 'string' ? item.value.toLowerCase().includes(value.toLocaleLowerCase()) : true; | ||
}); | ||
}; | ||
var useFilters = function (items, value, filters) { | ||
@@ -427,3 +437,3 @@ var filteredRef = useRef(items); | ||
var DatalistInput = forwardRef(function (_a, forwardedRef) { | ||
var label = _a.label, _b = _a.showLabel, showLabel = _b === void 0 ? true : _b, items = _a.items, selectedItem = _a.selectedItem, value = _a.value, setValue = _a.setValue, onSelect = _a.onSelect, placeholder = _a.placeholder, _c = _a.isExpanded, isExpanded = _c === void 0 ? DEFAULT_IS_EXPANDED : _c, setIsExpanded = _a.setIsExpanded, _d = _a.filters, filters = _d === void 0 ? [startsWithValueFilter] : _d, inputProps = _a.inputProps, labelProps = _a.labelProps, listboxOptionProps = _a.listboxOptionProps, listboxProps = _a.listboxProps, _e = _a.isExpandedClassName, isExpandedClassName = _e === void 0 ? '' : _e, _f = _a.isCollapsedClassName, isCollapsedClassName = _f === void 0 ? '' : _f, isExpandedStyle = _a.isExpandedStyle, isCollapsedStyle = _a.isCollapsedStyle, props = __rest(_a, ["label", "showLabel", "items", "selectedItem", "value", "setValue", "onSelect", "placeholder", "isExpanded", "setIsExpanded", "filters", "inputProps", "labelProps", "listboxOptionProps", "listboxProps", "isExpandedClassName", "isCollapsedClassName", "isExpandedStyle", "isCollapsedStyle"]); | ||
var label = _a.label, _b = _a.showLabel, showLabel = _b === void 0 ? true : _b, items = _a.items, selectedItem = _a.selectedItem, value = _a.value, setValue = _a.setValue, onSelect = _a.onSelect, placeholder = _a.placeholder, _c = _a.isExpanded, isExpanded = _c === void 0 ? DEFAULT_IS_EXPANDED : _c, setIsExpanded = _a.setIsExpanded, _d = _a.filters, filters = _d === void 0 ? [includesValueFilter] : _d, inputProps = _a.inputProps, labelProps = _a.labelProps, listboxOptionProps = _a.listboxOptionProps, listboxProps = _a.listboxProps, _e = _a.isExpandedClassName, isExpandedClassName = _e === void 0 ? '' : _e, _f = _a.isCollapsedClassName, isCollapsedClassName = _f === void 0 ? '' : _f, isExpandedStyle = _a.isExpandedStyle, isCollapsedStyle = _a.isCollapsedStyle, props = __rest(_a, ["label", "showLabel", "items", "selectedItem", "value", "setValue", "onSelect", "placeholder", "isExpanded", "setIsExpanded", "filters", "inputProps", "labelProps", "listboxOptionProps", "listboxProps", "isExpandedClassName", "isCollapsedClassName", "isExpandedStyle", "isCollapsedStyle"]); | ||
var _g = useStateRef(isExpanded), internalIsExpanded = _g[0], setInternalIsExpanded = _g[1], isExpandedRef = _g[2]; | ||
@@ -476,3 +486,3 @@ var _h = useInternalValue(value, setValue), internalValue = _h[0], setInternalValue = _h[1]; | ||
export { Combobox, DatalistInput, DatalistInput as default, startsWithValueFilter, useComboboxContext, useComboboxControls, useComboboxHelpers, useFilters }; | ||
export { Combobox, DatalistInput, DatalistInput as default, includesValueFilter, startsWithValueFilter, useComboboxContext, useComboboxControls, useComboboxHelpers, useFilters }; | ||
//# sourceMappingURL=index.es.js.map |
@@ -408,3 +408,3 @@ 'use strict'; | ||
/** | ||
* Default function for matching the current input value (needle) and the values of the items array. | ||
* Alternative function for matching the current input value (needle) and the values of the items array. | ||
* Returns true if item.value is not of type string (all items will be displayed and a custom filter must be used). | ||
@@ -418,2 +418,12 @@ */ | ||
}; | ||
/** | ||
* Default function for matching the current input value (needle) and the values of the items array. | ||
* Returns true if item.value is not of type string (all items will be displayed and a custom filter must be used). | ||
*/ | ||
var includesValueFilter = function (items, value) { | ||
if (value === void 0) { value = ''; } | ||
return items.filter(function (item) { | ||
return typeof item.value === 'string' ? item.value.toLowerCase().includes(value.toLocaleLowerCase()) : true; | ||
}); | ||
}; | ||
var useFilters = function (items, value, filters) { | ||
@@ -435,3 +445,3 @@ var filteredRef = React.useRef(items); | ||
var DatalistInput = React.forwardRef(function (_a, forwardedRef) { | ||
var label = _a.label, _b = _a.showLabel, showLabel = _b === void 0 ? true : _b, items = _a.items, selectedItem = _a.selectedItem, value = _a.value, setValue = _a.setValue, onSelect = _a.onSelect, placeholder = _a.placeholder, _c = _a.isExpanded, isExpanded = _c === void 0 ? DEFAULT_IS_EXPANDED : _c, setIsExpanded = _a.setIsExpanded, _d = _a.filters, filters = _d === void 0 ? [startsWithValueFilter] : _d, inputProps = _a.inputProps, labelProps = _a.labelProps, listboxOptionProps = _a.listboxOptionProps, listboxProps = _a.listboxProps, _e = _a.isExpandedClassName, isExpandedClassName = _e === void 0 ? '' : _e, _f = _a.isCollapsedClassName, isCollapsedClassName = _f === void 0 ? '' : _f, isExpandedStyle = _a.isExpandedStyle, isCollapsedStyle = _a.isCollapsedStyle, props = __rest(_a, ["label", "showLabel", "items", "selectedItem", "value", "setValue", "onSelect", "placeholder", "isExpanded", "setIsExpanded", "filters", "inputProps", "labelProps", "listboxOptionProps", "listboxProps", "isExpandedClassName", "isCollapsedClassName", "isExpandedStyle", "isCollapsedStyle"]); | ||
var label = _a.label, _b = _a.showLabel, showLabel = _b === void 0 ? true : _b, items = _a.items, selectedItem = _a.selectedItem, value = _a.value, setValue = _a.setValue, onSelect = _a.onSelect, placeholder = _a.placeholder, _c = _a.isExpanded, isExpanded = _c === void 0 ? DEFAULT_IS_EXPANDED : _c, setIsExpanded = _a.setIsExpanded, _d = _a.filters, filters = _d === void 0 ? [includesValueFilter] : _d, inputProps = _a.inputProps, labelProps = _a.labelProps, listboxOptionProps = _a.listboxOptionProps, listboxProps = _a.listboxProps, _e = _a.isExpandedClassName, isExpandedClassName = _e === void 0 ? '' : _e, _f = _a.isCollapsedClassName, isCollapsedClassName = _f === void 0 ? '' : _f, isExpandedStyle = _a.isExpandedStyle, isCollapsedStyle = _a.isCollapsedStyle, props = __rest(_a, ["label", "showLabel", "items", "selectedItem", "value", "setValue", "onSelect", "placeholder", "isExpanded", "setIsExpanded", "filters", "inputProps", "labelProps", "listboxOptionProps", "listboxProps", "isExpandedClassName", "isCollapsedClassName", "isExpandedStyle", "isCollapsedStyle"]); | ||
var _g = useStateRef(isExpanded), internalIsExpanded = _g[0], setInternalIsExpanded = _g[1], isExpandedRef = _g[2]; | ||
@@ -487,2 +497,3 @@ var _h = useInternalValue(value, setValue), internalValue = _h[0], setInternalValue = _h[1]; | ||
exports["default"] = DatalistInput; | ||
exports.includesValueFilter = includesValueFilter; | ||
exports.startsWithValueFilter = startsWithValueFilter; | ||
@@ -489,0 +500,0 @@ exports.useComboboxContext = useComboboxContext; |
{ | ||
"name": "react-datalist-input", | ||
"version": "3.0.6", | ||
"version": "3.1.0", | ||
"description": "react-datalist-input provides a React datalist/combobox component called DatalistInput. The component contains an input field with a dropdown menu of suggestions based on the current input.", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
109
README.md
@@ -103,4 +103,8 @@ ![Simple demo of DatalistInput](/media/demo.gif) | ||
### Version 3.0.0 | ||
#### Version 3.1.0 | ||
Version 3.1.0 changes the default filter from `startsWith` to `includes` to match the behavior of the datalist HTML 5 element. You can read more information about filtering and how to use a custom filter down below (Filtering). | ||
#### Version 3.0.0 | ||
Full refactor of react-datalist-input. | ||
@@ -150,3 +154,3 @@ | ||
import DataListInput from 'react-datalist-input'; | ||
// Tntegrate the css file if you want to use the default styling | ||
// Integrate the css file if you want to use the default styling | ||
import 'react-datalist-input/dist/styles.css'; | ||
@@ -187,3 +191,3 @@ | ||
})), | ||
[yourItems], | ||
[], | ||
); | ||
@@ -231,4 +235,89 @@ | ||
### Custom Filtering | ||
### Custom Item Components | ||
You can also customize the rendering of each item in the dropdown list by providing a custom component. | ||
```tsx | ||
import { useMemo } from 'react'; | ||
import type { Item } from '../combobox'; | ||
import { DatalistInput, useComboboxControls } from '../combobox'; | ||
type CustomItem = Item & { | ||
description: string; | ||
}; | ||
const items: Array<CustomItem> = [ | ||
{ id: 'Chocolate', value: 'Chocolate', description: 'Chocolate is delicious' }, | ||
{ id: 'Coconut', value: 'Coconut', description: 'Coconut is tasty but watch your head!' }, | ||
{ id: 'Mint', value: 'Mint', description: 'Mint is a herb?' }, | ||
{ id: 'Strawberry', value: 'Strawberry', description: 'Strawberries are red' }, | ||
{ id: 'Vanilla', value: 'Vanilla', description: 'Vanilla is a flavor' }, | ||
]; | ||
const CustomItem = ({ item }: { item: CustomItem }) => { | ||
// Each item is wrapped in a li element, so we don't need to provide a custom li element here. | ||
return ( | ||
<div style={{ display: 'flex', gap: '5px', flexDirection: 'column' }}> | ||
<b>{item.value}</b> | ||
<span>{item.description}</span> | ||
</div> | ||
); | ||
}; | ||
export default function Index() { | ||
const customItems = items.map((item) => ({ | ||
// each item requires an id and value | ||
...item, | ||
// but we can also add a custom component for the item | ||
node: <CustomItem item={item} />, | ||
})); | ||
return ( | ||
<DatalistInput | ||
label={<div>Custom Label</div>} | ||
placeholder="Chocolate" | ||
items={customItems} | ||
onSelect={(i) => console.log(i)} | ||
/> | ||
); | ||
} | ||
``` | ||
**Note:** Please note that by default the Item.value property is used for filtering. In case you want to filter over custom properties, make sure to implement a custom filter function. | ||
### Filtering | ||
By default, the DatalistInput component will filter the dropdown list based on the value of the input element using the `includes` method. This follows the behavior of the datalist HTMl element. You can however provide your own filtering function by passing a custom `filter` function to the DatalistInput component. | ||
For instace, this package exposes a `startsWith` alternative filter functions that you can use as follows: | ||
```jsx | ||
import { DatalistInput, startsWithValueFilter } from 'react-datalist-input'; | ||
const YourComponent = () => { | ||
return <DatalistInput label="Select ice cream flavor" items={items} filters={[startsWithValueFilter]} />; | ||
}; | ||
``` | ||
Now, the dropdown list will only show items that start with the input value. | ||
You can also implement a custom filter function: | ||
```tsx | ||
import type { Filter } from 'react-datalist-input'; | ||
import { DatalistInput } from 'react-datalist-input'; | ||
const YourComponent = () => { | ||
// Custom filter: Display all values that are smaller or equal than the input value | ||
const myFilterFunction: Filter = useCallback( | ||
(items, value) => items.filter((item) => item.value <= value), | ||
[selectedItems], | ||
); | ||
return <DatalistInput label="Select ice cream flavor" items={items} filters={[myFilterFunction]} />; | ||
}; | ||
``` | ||
### Filter Chaining | ||
You can chain custom filters to filter the list of options displayed in the dropdown menu. | ||
@@ -238,12 +327,13 @@ | ||
```jsx | ||
```tsx | ||
import type { Filter } from 'react-datalist-input'; | ||
// Import the default filter startWithValueFilter | ||
import DatalistInput, { startsWithValueFilter } from 'react-datalist-input'; | ||
import { DatalistInput, includesValueFilter } from 'react-datalist-input'; | ||
const YourComponent = () => { | ||
// Custom filter: Only display the first 3 items | ||
const limitOptionsFilter: Filter = useCallback((options, value) => options.slice(0, 3), [selectedItems]); | ||
const limitOptionsFilter: Filter = useCallback((items, value) => items.slice(0, 3), []); | ||
// First we filter by the value using the default filter, then we add a custom filter. | ||
const filters = [startsWithValueFilter, customFilter]; | ||
const filters = [includesValueFilter, customFilter]; | ||
@@ -381,3 +471,4 @@ return <DatalistInput label="Select ice cream flavor" items={items} filters={filters} />; | ||
- `startsWithValueFilter`: A default filter that filters the list of options by the input value. | ||
- `includesValueFilter`: The default filter that filters the list of options based on the value of the input. This filter follows the behavior of the datalist HTML element. | ||
- `startsWithValueFilter`: An alternative filter that filters based on the start of the option's value. | ||
- `useComboboxControls`: A hook to get the state and handlers for the input value and the dropdown expansion state. | ||
@@ -384,0 +475,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
179928
1202
494