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
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
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
181318
1209
510
1