react-datalist-input
Advanced tools
Comparing version 3.1.0 to 3.2.0-next-1
import type { PropsWithChildren, HTMLAttributes, InputHTMLAttributes, ReactNode, CSSProperties, RefObject, MutableRefObject, SetStateAction, Dispatch } from 'react'; | ||
import React from 'react'; | ||
interface ComboboxContext { | ||
declare type ComboboxContext = { | ||
contextAvailable: boolean; | ||
@@ -8,3 +8,4 @@ listboxId?: string; | ||
isExpanded?: boolean; | ||
} | ||
currentInputValue?: string; | ||
}; | ||
declare const ComboboxContext: React.Context<ComboboxContext>; | ||
@@ -31,4 +32,4 @@ declare const useComboboxContext: () => ComboboxContext; | ||
declare type ClassName<Params> = HTMLAttributes<HTMLLIElement>['className'] | ClassNameFunction<Params>; | ||
declare type useComoboxHelpersConfigParams = { | ||
itemsRef: MutableRefObject<Array<Item>>; | ||
declare type UseComboboxHelpersConfigParams = { | ||
itemsRef: MutableRefObject<Item[]>; | ||
listboxRef: RefObject<HTMLElement>; | ||
@@ -48,3 +49,3 @@ comboboxInputRef: RefObject<HTMLInputElement>; | ||
*/ | ||
declare const useComboboxHelpers: ({ itemsRef, listboxRef, comboboxInputRef, onSelect, isExpandedRef, setIsExpanded, setValue, setSelectedItem, }: useComoboxHelpersConfigParams) => { | ||
declare function useComboboxHelpers({ itemsRef, listboxRef, comboboxInputRef, onSelect, isExpandedRef, setIsExpanded, setValue, setSelectedItem, }: UseComboboxHelpersConfigParams): { | ||
closeOnEscape: (e: KeyboardEvent) => void; | ||
@@ -59,15 +60,17 @@ handleClickOutside: (e: MouseEvent) => void; | ||
}; | ||
interface ComboboxInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'value'> { | ||
declare type ComboboxInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'value'> & { | ||
value?: string; | ||
} | ||
}; | ||
/** | ||
* The textbox input field. | ||
* Does currently not implement aria-activedescendant which is not obligatory for datalist input components. | ||
* Autocomplete off to prevent browser autocomplete from interfering with our own; can be overriden with props. | ||
* Autocomplete off to prevent browser autocomplete from interfering with our own; can be overridden with props. | ||
*/ | ||
declare const ComboboxInput: React.ForwardRefExoticComponent<ComboboxInputProps & React.RefAttributes<HTMLInputElement>>; | ||
interface HighlightProps extends HTMLAttributes<HTMLElement> { | ||
declare const ComboboxInput: React.ForwardRefExoticComponent<Omit<InputHTMLAttributes<HTMLInputElement>, "value"> & { | ||
value?: string | undefined; | ||
} & React.RefAttributes<HTMLInputElement>>; | ||
declare type HighlightProps = HTMLAttributes<HTMLElement> & { | ||
currentInput?: string; | ||
as?: 'mark' | 'span'; | ||
} | ||
}; | ||
/** | ||
@@ -95,7 +98,8 @@ * Optional highlight component for the listbox option text. | ||
declare const Listbox: React.ForwardRefExoticComponent<ListboxProps & React.RefAttributes<HTMLUListElement>>; | ||
interface ComboboxProps { | ||
declare type ComboboxProps = { | ||
listboxId?: ComboboxContext['listboxId']; | ||
selectedItemId?: ComboboxContext['selectedItemId']; | ||
isExpanded?: ComboboxContext['isExpanded']; | ||
} | ||
currentInputValue?: ComboboxContext['currentInputValue']; | ||
}; | ||
declare type Combobox = React.FC<PropsWithChildren<ComboboxProps>> & { | ||
@@ -112,3 +116,3 @@ ComboboxInput: typeof ComboboxInput; | ||
declare const Combobox: Combobox; | ||
interface Item extends Record<string, any> { | ||
declare type Item = Record<string, unknown> & { | ||
id: string; | ||
@@ -118,4 +122,4 @@ value: string; | ||
label?: string; | ||
} | ||
declare type Filter = (items: Array<Item>, value?: ComboboxInputProps['value']) => Array<Item>; | ||
}; | ||
declare type Filter = (items: Item[], value?: ComboboxInputProps['value']) => Item[]; | ||
/** | ||
@@ -131,3 +135,3 @@ * Alternative function for matching the current input value (needle) and the values of the items array. | ||
declare const includesValueFilter: Filter; | ||
declare const useFilters: (items: Array<Item>, value: ComboboxInputProps['value'], filters: Array<Filter>) => [Array<Item>, MutableRefObject<Array<Item>>]; | ||
declare function useFilters(items: Item[], value: ComboboxInputProps['value'], filters: Filter[]): [Item[], MutableRefObject<Item[]>]; | ||
declare type LabelOptionProps = { | ||
@@ -142,11 +146,11 @@ showLabel?: false; | ||
declare type DatalistInputProps = LabelOptionProps & Omit<HTMLAttributes<HTMLDivElement>, 'onSelect'> & { | ||
items: Array<Item>; | ||
items: Item[]; | ||
selectedItem?: Item; | ||
value?: ComboboxInputProps['value']; | ||
setValue?: useComoboxHelpersConfigParams['setValue']; | ||
onSelect?: useComoboxHelpersConfigParams['onSelect']; | ||
setValue?: UseComboboxHelpersConfigParams['setValue']; | ||
onSelect?: UseComboboxHelpersConfigParams['onSelect']; | ||
isExpanded?: ComboboxContext['isExpanded']; | ||
setIsExpanded?: useComoboxHelpersConfigParams['setIsExpanded']; | ||
setIsExpanded?: UseComboboxHelpersConfigParams['setIsExpanded']; | ||
placeholder?: ComboboxInputProps['placeholder']; | ||
filters?: Array<Filter>; | ||
filters?: Filter[]; | ||
inputProps?: ComboboxInputProps; | ||
@@ -169,4 +173,4 @@ labelProps?: LabelProps; | ||
declare const DatalistInput: React.ForwardRefExoticComponent<DatalistInputProps & React.RefAttributes<HTMLDivElement>>; | ||
export type { DatalistInputProps, ComboboxProps, ComboboxInputProps, ListboxProps, ListboxOptionProps, HighlightProps, useComoboxHelpersConfigParams, Item, Filter, }; | ||
export type { DatalistInputProps, ComboboxProps, ComboboxInputProps, ListboxProps, ListboxOptionProps, HighlightProps, UseComboboxHelpersConfigParams, Item, Filter, }; | ||
export { Combobox, DatalistInput, startsWithValueFilter, includesValueFilter, useFilters, useComboboxContext, useComboboxControls, useComboboxHelpers, }; | ||
export default DatalistInput; |
@@ -106,2 +106,3 @@ import React, { createContext, forwardRef, useContext, useMemo, useRef, useState, useEffect, useId, useDeferredValue, useCallback } from 'react'; | ||
isExpanded: DEFAULT_IS_EXPANDED, | ||
currentInputValue: '', | ||
}); | ||
@@ -132,3 +133,3 @@ var useComboboxContext = function () { return useContext(ComboboxContext); }; | ||
*/ | ||
var useComboboxHelpers = function (_a) { | ||
function useComboboxHelpers(_a) { | ||
var itemsRef = _a.itemsRef, listboxRef = _a.listboxRef, comboboxInputRef = _a.comboboxInputRef, onSelect = _a.onSelect, isExpandedRef = _a.isExpandedRef, setIsExpanded = _a.setIsExpanded, setValue = _a.setValue, setSelectedItem = _a.setSelectedItem; | ||
@@ -276,7 +277,7 @@ /** | ||
}; | ||
}; | ||
} | ||
/** | ||
* The textbox input field. | ||
* Does currently not implement aria-activedescendant which is not obligatory for datalist input components. | ||
* Autocomplete off to prevent browser autocomplete from interfering with our own; can be overriden with props. | ||
* Autocomplete off to prevent browser autocomplete from interfering with our own; can be overridden with props. | ||
*/ | ||
@@ -340,3 +341,3 @@ var ComboboxInput = forwardRef(function (_a, forwardedRef) { | ||
} | ||
isExpandedRef.current = isExpanded; // dragpointer to the old value | ||
isExpandedRef.current = isExpanded; // drag pointer to the old value | ||
}, [isExpanded]); | ||
@@ -352,5 +353,5 @@ // TODO https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-live instead of title | ||
var Combobox = function (_a) { | ||
var listboxId = _a.listboxId, selectedItemId = _a.selectedItemId, _b = _a.isExpanded, isExpanded = _b === void 0 ? true : _b, children = _a.children; | ||
var currentInputValue = _a.currentInputValue, listboxId = _a.listboxId, selectedItemId = _a.selectedItemId, _b = _a.isExpanded, isExpanded = _b === void 0 ? true : _b, children = _a.children; | ||
var id = useId(); | ||
return (React.createElement(ComboboxContext.Provider, { value: { contextAvailable: true, listboxId: listboxId || id, selectedItemId: selectedItemId, isExpanded: isExpanded } }, children)); | ||
return (React.createElement(ComboboxContext.Provider, { value: { currentInputValue: currentInputValue, contextAvailable: true, listboxId: listboxId || id, selectedItemId: selectedItemId, isExpanded: isExpanded } }, children)); | ||
}; | ||
@@ -367,5 +368,5 @@ Combobox.ComboboxInput = ComboboxInput; | ||
*/ | ||
function useStateRef(initalState) { | ||
var _a = useState(initalState), state = _a[0], setState = _a[1]; | ||
var ref = useRef(initalState); | ||
function useStateRef(initialState) { | ||
var _a = useState(initialState), state = _a[0], setState = _a[1]; | ||
var ref = useRef(initialState); | ||
var setStateRef = function (newState) { | ||
@@ -398,3 +399,3 @@ setState(newState); | ||
*/ | ||
var useInternalSelectedItem = function (item) { | ||
function useInternalSelectedItem(item) { | ||
var _a = useState(item), selectedItem = _a[0], setSelectedItem = _a[1]; | ||
@@ -405,3 +406,3 @@ useEffect(function () { | ||
return [selectedItem, setSelectedItem]; | ||
}; | ||
} | ||
/** | ||
@@ -427,3 +428,3 @@ * Alternative function for matching the current input value (needle) and the values of the items array. | ||
}; | ||
var useFilters = function (items, value, filters) { | ||
function useFilters(items, value, filters) { | ||
var filteredRef = useRef(items); | ||
@@ -435,3 +436,3 @@ var filtered = useMemo(function () { return filters.reduce(function (currentItems, filter) { return filter(currentItems, value); }, items); }, [items, filters, value]); | ||
return [filtered, filteredRef]; | ||
}; | ||
} | ||
/** | ||
@@ -485,3 +486,3 @@ * DatalistInput implements all lower-level components for you and provides a simple API for controlling the combobox. | ||
return (React.createElement("div", __assign({}, props, { ref: forwardedRef, className: "react-datalist-input__container ".concat(props.className) }), | ||
React.createElement(Combobox, { listboxId: listboxProps === null || listboxProps === void 0 ? void 0 : listboxProps.id, selectedItemId: internalSelectedItem === null || internalSelectedItem === void 0 ? void 0 : internalSelectedItem.id, isExpanded: internalIsExpanded }, | ||
React.createElement(Combobox, { listboxId: listboxProps === null || listboxProps === void 0 ? void 0 : listboxProps.id, selectedItemId: internalSelectedItem === null || internalSelectedItem === void 0 ? void 0 : internalSelectedItem.id, isExpanded: internalIsExpanded, currentInputValue: internalValue }, | ||
showLabel && (React.createElement("label", __assign({}, labelProps, { className: "react-datalist-input__label ".concat(labelProps === null || labelProps === void 0 ? void 0 : labelProps.className), htmlFor: (inputProps === null || inputProps === void 0 ? void 0 : inputProps.id) || internalTextboxId }), label)), | ||
@@ -488,0 +489,0 @@ React.createElement(ComboboxInput, __assign({}, inputProps, { ref: comboboxInputRef, id: (inputProps === null || inputProps === void 0 ? void 0 : inputProps.id) || internalTextboxId, placeholder: placeholder, value: internalValue, onClick: handleWith(expandOnFocus, inputProps === null || inputProps === void 0 ? void 0 : inputProps.onClick), onFocus: handleWith(expandOnFocus, inputProps === null || inputProps === void 0 ? void 0 : inputProps.onFocus), onChange: handleWith(handleChange, inputProps === null || inputProps === void 0 ? void 0 : inputProps.onChange), onKeyDown: handleWith(handleKeyDownOnInput, inputProps === null || inputProps === void 0 ? void 0 : inputProps.onKeyDown), "aria-label": !showLabel && typeof label === 'string' ? label : undefined, className: "react-datalist-input__textbox ".concat(inputProps === null || inputProps === void 0 ? void 0 : inputProps.className) })), |
@@ -114,2 +114,3 @@ 'use strict'; | ||
isExpanded: DEFAULT_IS_EXPANDED, | ||
currentInputValue: '', | ||
}); | ||
@@ -140,3 +141,3 @@ var useComboboxContext = function () { return React.useContext(ComboboxContext); }; | ||
*/ | ||
var useComboboxHelpers = function (_a) { | ||
function useComboboxHelpers(_a) { | ||
var itemsRef = _a.itemsRef, listboxRef = _a.listboxRef, comboboxInputRef = _a.comboboxInputRef, onSelect = _a.onSelect, isExpandedRef = _a.isExpandedRef, setIsExpanded = _a.setIsExpanded, setValue = _a.setValue, setSelectedItem = _a.setSelectedItem; | ||
@@ -284,7 +285,7 @@ /** | ||
}; | ||
}; | ||
} | ||
/** | ||
* The textbox input field. | ||
* Does currently not implement aria-activedescendant which is not obligatory for datalist input components. | ||
* Autocomplete off to prevent browser autocomplete from interfering with our own; can be overriden with props. | ||
* Autocomplete off to prevent browser autocomplete from interfering with our own; can be overridden with props. | ||
*/ | ||
@@ -348,3 +349,3 @@ var ComboboxInput = React.forwardRef(function (_a, forwardedRef) { | ||
} | ||
isExpandedRef.current = isExpanded; // dragpointer to the old value | ||
isExpandedRef.current = isExpanded; // drag pointer to the old value | ||
}, [isExpanded]); | ||
@@ -360,5 +361,5 @@ // TODO https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-live instead of title | ||
var Combobox = function (_a) { | ||
var listboxId = _a.listboxId, selectedItemId = _a.selectedItemId, _b = _a.isExpanded, isExpanded = _b === void 0 ? true : _b, children = _a.children; | ||
var currentInputValue = _a.currentInputValue, listboxId = _a.listboxId, selectedItemId = _a.selectedItemId, _b = _a.isExpanded, isExpanded = _b === void 0 ? true : _b, children = _a.children; | ||
var id = React.useId(); | ||
return (React__default["default"].createElement(ComboboxContext.Provider, { value: { contextAvailable: true, listboxId: listboxId || id, selectedItemId: selectedItemId, isExpanded: isExpanded } }, children)); | ||
return (React__default["default"].createElement(ComboboxContext.Provider, { value: { currentInputValue: currentInputValue, contextAvailable: true, listboxId: listboxId || id, selectedItemId: selectedItemId, isExpanded: isExpanded } }, children)); | ||
}; | ||
@@ -375,5 +376,5 @@ Combobox.ComboboxInput = ComboboxInput; | ||
*/ | ||
function useStateRef(initalState) { | ||
var _a = React.useState(initalState), state = _a[0], setState = _a[1]; | ||
var ref = React.useRef(initalState); | ||
function useStateRef(initialState) { | ||
var _a = React.useState(initialState), state = _a[0], setState = _a[1]; | ||
var ref = React.useRef(initialState); | ||
var setStateRef = function (newState) { | ||
@@ -406,3 +407,3 @@ setState(newState); | ||
*/ | ||
var useInternalSelectedItem = function (item) { | ||
function useInternalSelectedItem(item) { | ||
var _a = React.useState(item), selectedItem = _a[0], setSelectedItem = _a[1]; | ||
@@ -413,3 +414,3 @@ React.useEffect(function () { | ||
return [selectedItem, setSelectedItem]; | ||
}; | ||
} | ||
/** | ||
@@ -435,3 +436,3 @@ * Alternative function for matching the current input value (needle) and the values of the items array. | ||
}; | ||
var useFilters = function (items, value, filters) { | ||
function useFilters(items, value, filters) { | ||
var filteredRef = React.useRef(items); | ||
@@ -443,3 +444,3 @@ var filtered = React.useMemo(function () { return filters.reduce(function (currentItems, filter) { return filter(currentItems, value); }, items); }, [items, filters, value]); | ||
return [filtered, filteredRef]; | ||
}; | ||
} | ||
/** | ||
@@ -493,3 +494,3 @@ * DatalistInput implements all lower-level components for you and provides a simple API for controlling the combobox. | ||
return (React__default["default"].createElement("div", __assign({}, props, { ref: forwardedRef, className: "react-datalist-input__container ".concat(props.className) }), | ||
React__default["default"].createElement(Combobox, { listboxId: listboxProps === null || listboxProps === void 0 ? void 0 : listboxProps.id, selectedItemId: internalSelectedItem === null || internalSelectedItem === void 0 ? void 0 : internalSelectedItem.id, isExpanded: internalIsExpanded }, | ||
React__default["default"].createElement(Combobox, { listboxId: listboxProps === null || listboxProps === void 0 ? void 0 : listboxProps.id, selectedItemId: internalSelectedItem === null || internalSelectedItem === void 0 ? void 0 : internalSelectedItem.id, isExpanded: internalIsExpanded, currentInputValue: internalValue }, | ||
showLabel && (React__default["default"].createElement("label", __assign({}, labelProps, { className: "react-datalist-input__label ".concat(labelProps === null || labelProps === void 0 ? void 0 : labelProps.className), htmlFor: (inputProps === null || inputProps === void 0 ? void 0 : inputProps.id) || internalTextboxId }), label)), | ||
@@ -496,0 +497,0 @@ React__default["default"].createElement(ComboboxInput, __assign({}, inputProps, { ref: comboboxInputRef, id: (inputProps === null || inputProps === void 0 ? void 0 : inputProps.id) || internalTextboxId, placeholder: placeholder, value: internalValue, onClick: handleWith(expandOnFocus, inputProps === null || inputProps === void 0 ? void 0 : inputProps.onClick), onFocus: handleWith(expandOnFocus, inputProps === null || inputProps === void 0 ? void 0 : inputProps.onFocus), onChange: handleWith(handleChange, inputProps === null || inputProps === void 0 ? void 0 : inputProps.onChange), onKeyDown: handleWith(handleKeyDownOnInput, inputProps === null || inputProps === void 0 ? void 0 : inputProps.onKeyDown), "aria-label": !showLabel && typeof label === 'string' ? label : undefined, className: "react-datalist-input__textbox ".concat(inputProps === null || inputProps === void 0 ? void 0 : inputProps.className) })), |
{ | ||
"name": "react-datalist-input", | ||
"version": "3.1.0", | ||
"version": "3.2.0-next-1", | ||
"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", |
@@ -29,3 +29,3 @@ ![Simple demo of DatalistInput](/media/demo.gif) | ||
_But DatalistInput is also intented to be easy to extend:_ | ||
_But DatalistInput is also intended to be easy to extend:_ | ||
@@ -88,3 +88,3 @@ ```jsx | ||
This package does not implement the optional `aria-activedescendant` property but rather programatically shifts focus to the active item. This might be up to change in the future! | ||
This package does not implement the optional `aria-activedescendant` property but rather programmatically shifts focus to the active item. This might be up to change in the future! | ||
@@ -105,2 +105,8 @@ ## Feedback & Issues | ||
#### Version 3.2.0 | ||
- Better `Item` type definition to make it easier to extend the items array. | ||
- Renamed `useComoboxHelpersConfigParams` to `UseComboboxHelpersConfigParams`. | ||
- `useComboboxContext` now exposes the `currentInputValue`, which can be handy when implementing custom item components with highlighting. | ||
#### Version 3.1.0 | ||
@@ -242,3 +248,3 @@ | ||
import type { Item } from '../combobox'; | ||
import { DatalistInput, useComboboxControls } from '../combobox'; | ||
import { DatalistInput, useComboboxControls, useComboboxContext } from '../combobox'; | ||
@@ -258,5 +264,15 @@ type CustomItem = Item & { | ||
const CustomItem = ({ item }: { item: CustomItem }) => { | ||
// get access to the combobox context for highlighting, etc. | ||
const { currentInputValue, selectedItemId } = useComboboxContext(); | ||
// 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' }}> | ||
<div | ||
style={{ | ||
display: 'flex', | ||
gap: '5px', | ||
flexDirection: 'column', | ||
background: item.id === selectedItemId ? 'gray' : 'white', | ||
}} | ||
> | ||
<b>{item.value}</b> | ||
@@ -293,3 +309,3 @@ <span>{item.description}</span> | ||
For instace, this package exposes a `startsWith` alternative filter functions that you can use as follows: | ||
For instance, this package exposes a `startsWith` alternative filter functions that you can use as follows: | ||
@@ -494,3 +510,3 @@ ```jsx | ||
- `DatalistInputProps`: The props accepted by the DatalistInput component. | ||
- `ComboxboxProps`: The props accepted by the low-level Combobox component. | ||
- `ComboboxProps`: The props accepted by the low-level Combobox component. | ||
- `ComboboxInputProps`: The props accepted by the low-level ComboboxInput component. | ||
@@ -500,2 +516,2 @@ - `ListboxProps`: The props accepted by the low-level Listbox component. | ||
- `HighlightProps`: The props accepted by the low-level Highlight component. | ||
- `useComoboxHelpersConfigParams`: The params for the low-level `useComboboxHelpers` hook. | ||
- `UseComboboxHelpersConfigParams`: The params for the low-level `useComboboxHelpers` hook. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
181318
1209
510
1