UNPKG

8.48 kBTypeScriptView Raw
1import * as React from "react";
2import { AbstractComponent, type Props } from "@blueprintjs/core";
3import { type CreateNewItem, type ListItemsProps } from "../../common";
4export interface QueryListProps<T> extends ListItemsProps<T> {
5 /**
6 * Initial active item, useful if the parent component is controlling its selectedItem but
7 * not activeItem.
8 */
9 initialActiveItem?: T;
10 /**
11 * Additional props to apply to the `Menu` that is created within the `QueryList`
12 */
13 menuProps?: React.HTMLAttributes<HTMLUListElement>;
14 /**
15 * Callback invoked when user presses a key, after processing `QueryList`'s own key events
16 * (up/down to navigate active item). This callback is passed to `renderer` and (along with
17 * `onKeyUp`) can be attached to arbitrary content elements to support keyboard selection.
18 */
19 onKeyDown?: React.KeyboardEventHandler<HTMLElement>;
20 /**
21 * Callback invoked when user releases a key, after processing `QueryList`'s own key events
22 * (enter to select active item). This callback is passed to `renderer` and (along with
23 * `onKeyDown`) can be attached to arbitrary content elements to support keyboard selection.
24 */
25 onKeyUp?: React.KeyboardEventHandler<HTMLElement>;
26 /**
27 * Customize rendering of the component.
28 * Receives an object with props that should be applied to elements as necessary.
29 */
30 renderer: (listProps: QueryListRendererProps<T>) => React.JSX.Element;
31 /**
32 * Whether the list is disabled.
33 *
34 * @default false
35 */
36 disabled?: boolean;
37}
38/**
39 * An object describing how to render a `QueryList`.
40 * A `QueryList` `renderer` receives this object as its sole argument.
41 */
42export interface QueryListRendererProps<T>// Omit `createNewItem`, because it's used strictly for internal tracking.
43 extends Pick<QueryListState<T>, "activeItem" | "filteredItems" | "query">, Props {
44 /**
45 * Selection handler that should be invoked when a new item has been chosen,
46 * perhaps because the user clicked it.
47 */
48 handleItemSelect: (item: T, event?: React.SyntheticEvent<HTMLElement>) => void;
49 /**
50 * Handler that should be invoked when the user pastes one or more values.
51 *
52 * This callback will use `itemPredicate` with `exactMatch=true` to find a
53 * subset of `items` exactly matching the pasted `values` provided, then it
54 * will invoke `onItemsPaste` with those found items. Each pasted value that
55 * does not exactly match an item will be ignored.
56 *
57 * If creating items is enabled (by providing both `createNewItemFromQuery`
58 * and `createNewItemRenderer`), then pasted values that do not exactly
59 * match an existing item will emit a new item as created via
60 * `createNewItemFromQuery`.
61 *
62 * If `itemPredicate` returns multiple matching items for a particular query
63 * in `queries`, then only the first matching item will be emitted.
64 */
65 handlePaste: (queries: string[]) => void;
66 /**
67 * Keyboard handler for up/down arrow keys to shift the active item.
68 * Attach this handler to any element that should support this interaction.
69 */
70 handleKeyDown: React.KeyboardEventHandler<HTMLElement>;
71 /**
72 * Keyboard handler for enter key to select the active item.
73 * Attach this handler to any element that should support this interaction.
74 */
75 handleKeyUp: React.KeyboardEventHandler<HTMLElement>;
76 /**
77 * Change handler for query string. Attach this to an input element to allow
78 * `QueryList` to control the query.
79 */
80 handleQueryChange: React.ChangeEventHandler<HTMLInputElement>;
81 /** Rendered elements returned from `itemListRenderer` prop. */
82 itemList: React.ReactNode;
83}
84/** Exported for testing, not part of public API */
85export interface QueryListState<T> {
86 /** The currently focused item (for keyboard interactions). */
87 activeItem: T | CreateNewItem | null;
88 /**
89 * The item returned from `createNewItemFromQuery(this.state.query)`, cached
90 * to avoid continuous reinstantions within `isCreateItemRendered`, where
91 * this element will be used to hide the "Create Item" option if its value
92 * matches the current `query`.
93 */
94 createNewItem: T | T[] | undefined;
95 /** The original `items` array filtered by `itemListPredicate` or `itemPredicate`. */
96 filteredItems: T[];
97 /** The current query string. */
98 query: string;
99}
100/**
101 * Query list component.
102 *
103 * @see https://blueprintjs.com/docs/#select/query-list
104 */
105export declare class QueryList<T> extends AbstractComponent<QueryListProps<T>, QueryListState<T>> {
106 static displayName: string;
107 static defaultProps: {
108 disabled: boolean;
109 resetOnQuery: boolean;
110 };
111 /** @deprecated no longer necessary now that the TypeScript parser supports type arguments on JSX element tags */
112 static ofType<U>(): new (props: QueryListProps<U>) => QueryList<U>;
113 private itemsParentRef?;
114 private itemRefs;
115 private refHandlers;
116 /**
117 * Flag indicating that we should check whether selected item is in viewport
118 * after rendering, typically because of keyboard change. Set to `true` when
119 * manipulating state in a way that may cause active item to scroll away.
120 */
121 private shouldCheckActiveItemInViewport;
122 /**
123 * The item that we expect to be the next selected active item (based on click
124 * or key interactions). When scrollToActiveItem = false, used to detect if
125 * an unexpected external change to the active item has been made.
126 */
127 private expectedNextActiveItem;
128 /**
129 * Flag which is set to true while in between an ENTER "keydown" event and its
130 * corresponding "keyup" event.
131 *
132 * When entering text via an IME (https://en.wikipedia.org/wiki/Input_method),
133 * the ENTER key is pressed to confirm the character(s) to be input from a list
134 * of options. The operating system intercepts the ENTER "keydown" event and
135 * prevents it from propagating to the application, but "keyup" is still
136 * fired, triggering a spurious event which this component does not expect.
137 *
138 * To work around this quirk, we keep track of "real" key presses by setting
139 * this flag in handleKeyDown.
140 */
141 private isEnterKeyPressed;
142 constructor(props: QueryListProps<T>);
143 render(): React.JSX.Element;
144 componentDidUpdate(prevProps: QueryListProps<T>): void;
145 scrollActiveItemIntoView(): void;
146 setQuery(query: string, resetActiveItem?: boolean | undefined, props?: Readonly<QueryListProps<T>> & Readonly<{
147 children?: React.ReactNode;
148 }>): void;
149 setActiveItem(activeItem: T | CreateNewItem | null): void;
150 /** default `itemListRenderer` implementation */
151 private renderItemList;
152 /** wrapper around `itemRenderer` to inject props */
153 private renderItem;
154 private renderCreateItemMenuItem;
155 private getActiveElement;
156 private getActiveIndex;
157 private getItemsParentPadding;
158 private handleItemCreate;
159 private handleItemSelect;
160 private handlePaste;
161 private handleKeyDown;
162 private handleKeyUp;
163 private handleInputQueryChange;
164 /**
165 * Get the next enabled item, moving in the given direction from the start
166 * index. A `null` return value means no suitable item was found.
167 *
168 * @param direction amount to move in each iteration, typically +/-1
169 * @param startIndex item to start iteration
170 */
171 private getNextActiveItem;
172 /**
173 * @param createNewItem Checks if this item would match the current query. Cannot check this.state.createNewItem
174 * every time since state may not have been updated yet.
175 */
176 private isCreateItemRendered;
177 private isCreateItemFirst;
178 private canCreateItems;
179 private wouldCreatedItemMatchSomeExistingItem;
180 private maybeResetQuery;
181}
182/**
183 * Get the next enabled item, moving in the given direction from the start
184 * index. A `null` return value means no suitable item was found.
185 *
186 * @param items the list of items
187 * @param itemDisabled callback to determine if a given item is disabled
188 * @param direction amount to move in each iteration, typically +/-1
189 * @param startIndex which index to begin moving from
190 */
191export declare function getFirstEnabledItem<T>(items: T[], itemDisabled?: keyof T | ((item: T, index: number) => boolean), direction?: number, startIndex?: number): T | CreateNewItem | null;