Query list
QueryList holds the query, filtering and keyboard logic behind every component in the package, and renders nothing itself. Use it to build a picker that the other components do not cover.
Usage#
import { QueryList, renderFilteredItems } from "@clawscale/react/select";QueryList takes the shared item props, plus a required renderer.
Examples#
Custom list renderer#
This picker renders inline instead of in a popover.
rendererlays out the whole component. It receives the query, the rendered list and the key handlers. AttachhandleKeyDownandhandleKeyUpto a wrapper, so the arrow keys and Enter work from the input.itemListRendererreplaces the default list. Here it adds a summary line above the options. AttachitemsParentRefto the element that holds the options, so the active option scrolls into view.renderFilteredItemsrenders the matching items, or its second argument when nothing matches.listIdfixes the id of the list. Without it, QueryList generates one, and server and client renders can disagree.
12 of 12 datasets, 8.6B rows
import { Card, Classes, InputGroup, Menu, MenuItem } from "@clawscale/react";
import { type ItemListRenderer, QueryList, renderFilteredItems } from "@clawscale/react/select";
import { useState } from "react";
import { DATASETS, type Dataset, filterDataset, formatRows } from "../_data";
import { renderCheckedDataset } from "../_renderers";
const scrollable = { maxHeight: 216, overflowY: "auto" } as const;
const renderList: ItemListRenderer<Dataset> = (list) => {
const rows = list.filteredItems.reduce((sum, dataset) => sum + dataset.rows, 0);
return (
<>
<div className={Classes.TEXT_MUTED} style={{ margin: "12px 4px 4px" }}>
{list.filteredItems.length} of {list.items.length} datasets, {formatRows(rows)} rows
</div>
<Menu aria-label="Datasets" role="listbox" ulRef={list.itemsParentRef} {...list.menuProps} style={scrollable}>
{renderFilteredItems(list, <MenuItem disabled text="No datasets match." roleStructure="listoption" />)}
</Menu>
</>
);
};
export default function QueryListCustomRenderer() {
const [dataset, setDataset] = useState<Dataset>();
return (
<QueryList<Dataset>
items={DATASETS}
itemPredicate={filterDataset}
itemRenderer={renderCheckedDataset(dataset ? [dataset] : [])}
itemListRenderer={renderList}
listId="dataset-browser"
onItemSelect={setDataset}
renderer={(props) => (
<Card compact onKeyDown={props.handleKeyDown} onKeyUp={props.handleKeyUp} style={{ width: 340 }}>
<InputGroup
aria-activedescendant={props.activeItemId}
aria-label="Filter datasets"
aria-controls={props.listId}
leftIcon="search"
placeholder="Filter datasets"
value={props.query}
onChange={props.handleQueryChange}
/>
{props.itemList}
</Card>
)}
/>
);
}Props interface#
interface QueryListProps extends ListItemsProps<T>@clawscale/react/select| Props | Description |
|---|---|
activeItem | T | CreateNewItem | nullThe currently focused item for keyboard interactions, or Inherited from null to indicate that no item is active. If omitted or undefined, this prop will be uncontrolled (managed by the component's state). Use onActiveItemChange to listen for updates.ListItemsProps |
className | stringA space-delimited list of class names to pass along to a child element. Inherited from Props |
createNewItemFromQuery | (query: string) => T | T[]If provided, allows new items to be created using the current query string. This is invoked when user interaction causes one or many items to be created, either by pressing the Inherited from Enter key or by clicking on the "Create Item" option. It transforms a query string into one or many items type.ListItemsProps |
createNewItemPosition | "first" | "last" = 'last'Determines the position of the Inherited from createNewItem within the list: first or last. Only relevant when createNewItemRenderer is defined.ListItemsProps |
createNewItemRenderer | (query: string, active: boolean, handleClick: React.MouseEventHandler<HTMLElement>) => React.JSX.Element | undefinedCustom renderer to transform the current query string into a selectable "Create Item" option. If this function is provided, a "Create Item" option will be rendered at the end of the list of items. If this function is not provided, a "Create Item" option will not be displayed. Inherited from ListItemsProps |
disabled | boolean = falseWhether the list is disabled. |
initialActiveItem | TInitial active item, useful if the parent component is controlling its selectedItem but not activeItem. |
initialContent | React.ReactNode | nullReact content to render when query is empty. If omitted, all items will be rendered (or result of Inherited from itemListPredicate with empty query). If explicit null, nothing will be rendered when query is empty.ListItemsProps |
itemDisabled | keyof T | ((item: T, index: number) => boolean)Determine if the given item is disabled. Provide a callback function, or simply provide the name of a boolean property on the item that exposes its disabled state. Inherited from ListItemsProps |
itemListPredicate | ItemListPredicate<T>Customize querying of entire Inherited from items array. Return new list of items. This method can reorder, add, or remove items at will. (Supports filter algorithms that operate on the entire set, rather than individual items.)ListItemsProps |
itemListRenderer | ItemListRenderer<T>Custom renderer for the contents of the dropdown. Inherited from ListItemsProps |
itemPredicate | ItemPredicate<T>Customize querying of individual items. Inherited from ListItemsProps |
itemRendererrequired | ItemRenderer<T>Custom renderer for an item in the dropdown list. Receives a boolean indicating whether this item is active (selected by keyboard arrows) and an Inherited from onClick event handler that should be attached to the returned element.ListItemsProps |
itemsrequired | T[]Array of items in the list. Inherited from ListItemsProps |
itemsEqual | ItemsEqualProp<T>Specifies how to test if two items are equal. By default, simple strict equality ( Inherited from ===) is used to compare two items.ListItemsProps |
listId | stringID prefix for generating unique IDs for list options. Defaults to a generated ID. |
menuProps | React.HTMLAttributes<HTMLUListElement>Additional props to apply to the Menu that is created within the QueryList |
noResults | React.ReactNodeReact content to render when filtering items returns zero results. If omitted, nothing will be rendered in this case. Inherited from ListItemsProps |
onActiveItemChange | (activeItem: T | null, isCreateNewItem: boolean) => voidInvoked when user interaction should change the active item: arrow keys move it up/down in the list, selecting an item makes it active, and changing the query may reset it to the first item in the list if it no longer matches the filter. Inherited from ListItemsProps |
onItemSelectrequired | (item: T, event?: React.SyntheticEvent<HTMLElement>) => voidCallback invoked when an item from the list is selected, typically by clicking or pressing Inherited from enter key.ListItemsProps |
onItemsPaste | (items: T[]) => voidCallback invoked when multiple items are selected at once via pasting. Inherited from ListItemsProps |
onKeyDown | React.KeyboardEventHandler<HTMLElement>Callback invoked when user presses a key, after processing QueryList's own key events (up/down to navigate active item). This callback is passed to renderer and (along with onKeyUp) can be attached to arbitrary content elements to support keyboard selection. |
onKeyUp | React.KeyboardEventHandler<HTMLElement>Callback invoked when user releases a key, after processing QueryList's own key events (enter to select active item). This callback is passed to renderer and (along with onKeyDown) can be attached to arbitrary content elements to support keyboard selection. |
onQueryChange | (query: string, event?: React.ChangeEvent<HTMLInputElement>) => voidCallback invoked when the query string changes. Inherited from ListItemsProps |
query | stringQuery string passed to Inherited from itemListPredicate or itemPredicate to filter items. This value is controlled: its state must be managed externally by attaching an onChange handler to the relevant element in your renderer implementation.ListItemsProps |
rendererrequired | (listProps: QueryListRendererProps<T>) => React.JSX.ElementCustomize rendering of the component. Receives an object with props that should be applied to elements as necessary. |
resetOnQuery | boolean = trueWhether the active item should be reset to the first matching item _every time the query changes_ (via prop or by user input). Inherited from ListItemsProps |
resetOnSelect | boolean = falseWhether the active item should be reset to the first matching item _when an item is selected_. The query will also be reset to the empty string. Inherited from ListItemsProps |
scrollToActiveItem | boolean = trueWhen Inherited from activeItem is controlled, whether the active item should _always_ be scrolled into view when the prop changes. If false, only changes that result from built-in interactions (clicking, querying, or using arrow keys) will scroll the active item into view. Ignored if the activeItem prop is omitted (uncontrolled behavior).ListItemsProps |
Renderer props#
renderer receives these props.
interface QueryListRendererProps extends Pick<QueryListState<T>, "activeItem" | "filteredItems" | "query">, Props@clawscale/react/selectAn object describing how to render a QueryList. A QueryList renderer receives this object as its sole argument.
| Props | Description |
|---|---|
activeItemrequired | T | CreateNewItem | nullThe currently focused item (for keyboard interactions). Inherited from QueryListState |
activeItemId | stringID of the currently active item for aria-activedescendant. |
className | stringA space-delimited list of class names to pass along to a child element. Inherited from Props |
filteredItemsrequired | T[]The original Inherited from items array filtered by itemListPredicate or itemPredicate.QueryListState |
handleItemSelectrequired | (item: T, event?: React.SyntheticEvent<HTMLElement>) => voidSelection handler that should be invoked when a new item has been chosen, perhaps because the user clicked it. |
handleKeyDownrequired | React.KeyboardEventHandler<HTMLElement>Keyboard handler for up/down arrow keys to shift the active item. Attach this handler to any element that should support this interaction. |
handleKeyUprequired | React.KeyboardEventHandler<HTMLElement>Keyboard handler for enter key to select the active item. Attach this handler to any element that should support this interaction. |
handlePasterequired | (queries: string[]) => voidHandler that should be invoked when the user pastes one or more values. |
handleQueryChangerequired | React.ChangeEventHandler<HTMLInputElement>Change handler for query string. Attach this to an input element to allow QueryList to control the query. |
itemListrequired | React.ReactNodeRendered elements returned from itemListRenderer prop. |
listIdrequired | stringID of the list container for ARIA relationships. |
queryrequired | stringThe current query string. Inherited from QueryListState |
Item list renderer props#
itemListRenderer receives these props.
interface ItemListRendererProps@clawscale/react/selectAn object describing how to render the list of items. An itemListRenderer receives this object as its sole argument.
| Props | Description |
|---|---|
activeItemrequired | T | CreateNewItem | nullThe currently focused item (for keyboard interactions), or null to indicate that no item is active. |
filteredItemsrequired | T[]Array of items filtered by itemListPredicate or itemPredicate. See items for the full list of items. |
itemsrequired | T[]Array of all items in the list. See filteredItems for a filtered array based on query and predicate props. |
itemsParentRefrequired | React.Ref<HTMLUListElement>A ref handler that should be attached to the parent HTML element of the menu items. This is required for the active item to scroll into view automatically. |
menuProps | React.HTMLAttributes<HTMLUListElement>Props to apply to the Menu created within the itemListRenderer |
queryrequired | stringThe current query string. |
renderCreateItemrequired | () => React.JSX.Element | null | undefinedCall this function to render the "create new item" view component. |
renderItemrequired | (item: T, index: number) => React.JSX.Element | nullCall this function to render an item. This retrieves the modifiers for the item and delegates actual rendering to the owner component's itemRenderer prop. |