1 | import * as React from 'react';
|
2 |
|
3 | import { Option } from './filters';
|
4 | import { InstructionsContext, ValueEventContext } from './accessibility/index';
|
5 |
|
6 | import { classNames, noop, scrollIntoView } from './utils';
|
7 |
|
8 | import { formatGroupLabel, getOptionLabel, getOptionValue } from './builtins';
|
9 |
|
10 | import { PlaceholderOrValue, SelectComponents, SelectComponentsConfig } from './components/index';
|
11 | import { StylesConfig } from './styles';
|
12 | import { ThemeConfig } from './theme';
|
13 | import {
|
14 | ActionMeta,
|
15 | FocusDirection,
|
16 | FocusEventHandler,
|
17 | GroupTypeBase,
|
18 | InputActionMeta,
|
19 | KeyboardEventHandler,
|
20 | MenuPlacement,
|
21 | MenuPosition,
|
22 | OptionsType,
|
23 | ValueType,
|
24 | OptionTypeBase,
|
25 | SetValueAction,
|
26 | } from './types';
|
27 |
|
28 | export type MouseOrTouchEvent = React.MouseEvent<HTMLElement> | React.TouchEvent<HTMLElement>;
|
29 | export type FormatOptionLabelContext = 'menu' | 'value';
|
30 | export interface FormatOptionLabelMeta<OptionType extends OptionTypeBase, IsMulti extends boolean> {
|
31 | context: FormatOptionLabelContext;
|
32 | inputValue: string;
|
33 | selectValue: ValueType<OptionType, IsMulti>;
|
34 | }
|
35 |
|
36 | export type SelectComponentsProps = { [key in string]: any };
|
37 |
|
38 | export interface NamedProps<
|
39 | OptionType extends OptionTypeBase = { label: string; value: string },
|
40 | IsMulti extends boolean = false,
|
41 | GroupType extends GroupTypeBase<OptionType> = GroupTypeBase<OptionType>
|
42 | > {
|
43 |
|
44 | 'aria-label'?: string;
|
45 |
|
46 | 'aria-labelledby'?: string;
|
47 |
|
48 | autoFocus?: boolean;
|
49 |
|
50 | backspaceRemovesValue?: boolean;
|
51 |
|
52 | blurInputOnSelect?: boolean;
|
53 |
|
54 | captureMenuScroll?: boolean;
|
55 |
|
56 | className?: string;
|
57 |
|
58 | classNamePrefix?: string | null;
|
59 |
|
60 | closeMenuOnSelect?: boolean;
|
61 | |
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 | closeMenuOnScroll?: boolean | EventListener;
|
74 | |
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 | components?: SelectComponentsConfig<OptionType, IsMulti, GroupType>;
|
84 |
|
85 | controlShouldRenderValue?: boolean;
|
86 |
|
87 | delimiter?: string;
|
88 |
|
89 | escapeClearsValue?: boolean;
|
90 |
|
91 | filterOption?: ((option: Option, rawInput: string) => boolean) | null;
|
92 | /** Formats group labels in the menu as React components */
|
93 | formatGroupLabel?: formatGroupLabel<OptionType, GroupType>;
|
94 | /** Formats option labels in the menu and control as React components */
|
95 | formatOptionLabel?: (option: OptionType, labelMeta: FormatOptionLabelMeta<OptionType, IsMulti>) => React.ReactNode;
|
96 |
|
97 | getOptionLabel?: getOptionLabel<OptionType>;
|
98 |
|
99 | getOptionValue?: getOptionValue<OptionType>;
|
100 |
|
101 | hideSelectedOptions?: boolean;
|
102 |
|
103 | id?: string;
|
104 |
|
105 | inputValue?: string;
|
106 |
|
107 | inputId?: string;
|
108 |
|
109 | instanceId?: number | string;
|
110 |
|
111 | isClearable?: boolean;
|
112 |
|
113 | isDisabled?: boolean;
|
114 |
|
115 | isLoading?: boolean;
|
116 |
|
117 | isOptionDisabled?: (option: OptionType, options: OptionsType<OptionType>) => boolean | false;
|
118 |
|
119 | isOptionSelected?: (option: OptionType, options: OptionsType<OptionType>) => boolean;
|
120 |
|
121 | isMulti?: IsMulti;
|
122 |
|
123 | isRtl?: boolean;
|
124 |
|
125 | isSearchable?: boolean;
|
126 |
|
127 | loadingMessage?: (obj: { inputValue: string }) => string | null;
|
128 |
|
129 | minMenuHeight?: number;
|
130 |
|
131 | maxMenuHeight?: number;
|
132 |
|
133 | menuIsOpen?: boolean;
|
134 | |
135 |
|
136 |
|
137 |
|
138 | menuPlacement?: MenuPlacement;
|
139 |
|
140 | menuPosition?: MenuPosition;
|
141 |
|
142 | menuPortalTarget?: HTMLElement | null;
|
143 |
|
144 | menuShouldBlockScroll?: boolean;
|
145 |
|
146 | menuShouldScrollIntoView?: boolean;
|
147 |
|
148 | name?: string;
|
149 |
|
150 | noOptionsMessage?: (obj: { inputValue: string }) => string | null;
|
151 |
|
152 | onBlur?: FocusEventHandler;
|
153 |
|
154 | onChange?: (value: ValueType<OptionType, IsMulti>, action: ActionMeta<OptionType>) => void;
|
155 |
|
156 | onFocus?: FocusEventHandler;
|
157 |
|
158 | onInputChange?: (newValue: string, actionMeta: InputActionMeta) => void;
|
159 |
|
160 | onKeyDown?: KeyboardEventHandler;
|
161 |
|
162 | onMenuOpen?: () => void;
|
163 |
|
164 | onMenuClose?: () => void;
|
165 |
|
166 | onMenuScrollToTop?: (event: React.SyntheticEvent<HTMLElement>) => void;
|
167 |
|
168 | onMenuScrollToBottom?: (event: React.SyntheticEvent<HTMLElement>) => void;
|
169 |
|
170 | openMenuOnFocus?: boolean;
|
171 |
|
172 | openMenuOnClick?: boolean;
|
173 |
|
174 | options?: ReadonlyArray<OptionType | GroupType>;
|
175 |
|
176 | pageSize?: number;
|
177 |
|
178 | placeholder?: React.ReactNode;
|
179 |
|
180 | screenReaderStatus?: (obj: { count: number }) => string;
|
181 |
|
182 | styles?: StylesConfig<OptionType, IsMulti, GroupType>;
|
183 |
|
184 | theme?: ThemeConfig;
|
185 |
|
186 | tabIndex?: string | null;
|
187 |
|
188 | tabSelectsValue?: boolean;
|
189 |
|
190 | value?: readonly OptionType[] | OptionType | null;
|
191 |
|
192 | defaultInputValue?: string;
|
193 | defaultMenuIsOpen?: boolean;
|
194 | defaultValue?: readonly OptionType[] | OptionType | null;
|
195 | }
|
196 |
|
197 | export interface Props<
|
198 | OptionType extends OptionTypeBase = { label: string; value: string },
|
199 | IsMulti extends boolean = false,
|
200 | GroupType extends GroupTypeBase<OptionType> = GroupTypeBase<OptionType>
|
201 | > extends NamedProps<OptionType, IsMulti, GroupType>,
|
202 | SelectComponentsProps {}
|
203 |
|
204 | export const defaultProps: Props<any>;
|
205 |
|
206 | export interface MenuOptions<OptionType extends OptionTypeBase> {
|
207 | render: OptionType[];
|
208 | focusable: OptionType[];
|
209 | }
|
210 |
|
211 | export interface State<OptionType extends OptionTypeBase> {
|
212 | ariaLiveSelection: string;
|
213 | ariaLiveContext: string;
|
214 | inputIsHidden: boolean;
|
215 | isFocused: boolean;
|
216 | isComposing: boolean;
|
217 | focusedOption: OptionType | null;
|
218 | focusedValue: OptionType | null;
|
219 | menuOptions: MenuOptions<OptionType>;
|
220 | selectValue: OptionsType<OptionType>;
|
221 | }
|
222 |
|
223 | export type ElRef = React.Ref<any>;
|
224 |
|
225 | export default class Select<
|
226 | OptionType extends OptionTypeBase,
|
227 | IsMulti extends boolean = false,
|
228 | GroupType extends GroupTypeBase<OptionType> = GroupTypeBase<OptionType>
|
229 | > extends React.Component<Props<OptionType, IsMulti, GroupType>, State<OptionType>> {
|
230 | static defaultProps: Props<any>;
|
231 |
|
232 |
|
233 |
|
234 |
|
235 | blockOptionHover: boolean;
|
236 | clearFocusValueOnUpdate: boolean;
|
237 | commonProps: any;
|
238 | components: SelectComponents<OptionType, IsMulti, GroupType>;
|
239 | hasGroups: boolean;
|
240 | initialTouchX: number;
|
241 | initialTouchY: number;
|
242 | inputIsHiddenAfterUpdate: boolean | null;
|
243 | instancePrefix: string;
|
244 | openAfterFocus: boolean;
|
245 | scrollToFocusedOptionOnUpdate: boolean;
|
246 | userIsDragging: boolean | null;
|
247 |
|
248 |
|
249 |
|
250 |
|
251 | controlRef: ElRef;
|
252 | getControlRef: (ref: HTMLElement) => void;
|
253 | focusedOptionRef: ElRef;
|
254 | getFocusedOptionRef: (ref: HTMLElement) => void;
|
255 | menuListRef: ElRef;
|
256 | getMenuListRef: (ref: HTMLElement) => void;
|
257 | inputRef: ElRef;
|
258 | getInputRef: (ref: HTMLElement) => void;
|
259 |
|
260 |
|
261 |
|
262 |
|
263 | cacheComponents: (components: SelectComponents<OptionType, IsMulti, GroupType>) => void;
|
264 |
|
265 |
|
266 |
|
267 |
|
268 |
|
269 | onMenuOpen(): void;
|
270 | onMenuClose(): void;
|
271 | onInputChange(newValue: string, actionMeta: InputActionMeta): void;
|
272 |
|
273 |
|
274 |
|
275 |
|
276 |
|
277 | focusInput(): void;
|
278 | blurInput(): void;
|
279 |
|
280 |
|
281 | focus(): void;
|
282 | blur(): void;
|
283 |
|
284 | openMenu(focusOption: 'first' | 'last'): void;
|
285 | focusValue(direction: 'previous' | 'next'): void;
|
286 |
|
287 | focusOption(direction: FocusDirection): void;
|
288 | setValue: (newValue: ValueType<OptionType, IsMulti>, action: SetValueAction, option?: OptionType) => void;
|
289 | selectOption: (newValue: OptionType) => void;
|
290 | removeValue: (removedValue: OptionType) => void;
|
291 | clearValue: () => void;
|
292 | popValue: () => void;
|
293 |
|
294 |
|
295 |
|
296 |
|
297 |
|
298 | getCommonProps(): {
|
299 | cx: any;
|
300 | clearValue: () => void;
|
301 | getStyles: (key: string, props: {}) => {};
|
302 | getValue: () => OptionType[];
|
303 | hasValue: boolean;
|
304 | isMulti: boolean;
|
305 | isRtl: boolean;
|
306 | options: OptionsType<any>;
|
307 | selectOption: (newValue: OptionType) => void;
|
308 | setValue: (newValue: ValueType<OptionType, IsMulti>, action: SetValueAction, option?: OptionType) => void;
|
309 | selectProps: Readonly<{
|
310 | children?: React.ReactNode;
|
311 | }> &
|
312 | Readonly<Props<OptionType, IsMulti, GroupType>>;
|
313 | };
|
314 |
|
315 | getNextFocusedValue(nextSelectValue: OptionsType<OptionType>): OptionType;
|
316 |
|
317 | getNextFocusedOption(options: OptionsType<OptionType>): OptionType;
|
318 | getOptionLabel: getOptionLabel<OptionType>;
|
319 | getOptionValue: getOptionValue<OptionType>;
|
320 | getStyles: (key: string, props: {}) => {};
|
321 | getElementId: (element: 'group' | 'input' | 'listbox' | 'option') => string;
|
322 | getActiveDescendentId: () => any;
|
323 |
|
324 |
|
325 |
|
326 |
|
327 | announceAriaLiveSelection: (props: { event: string; context: ValueEventContext }) => void;
|
328 | announceAriaLiveContext: (props: { event: string; context?: InstructionsContext }) => void;
|
329 |
|
330 | hasValue(): boolean;
|
331 | hasOptions(): boolean;
|
332 | countOptions(): number;
|
333 | isClearable(): boolean;
|
334 | isOptionDisabled(option: OptionType, selectValue: OptionsType<OptionType>): boolean;
|
335 | isOptionSelected(option: OptionType, selectValue: OptionsType<OptionType>): boolean;
|
336 | filterOption(option: {}, inputValue: string): boolean;
|
337 | formatOptionLabel(data: OptionType, context: FormatOptionLabelContext): React.ReactNode;
|
338 | formatGroupLabel: formatGroupLabel<OptionType, GroupType>;
|
339 |
|
340 |
|
341 |
|
342 |
|
343 |
|
344 | onMenuMouseDown: (event: React.MouseEvent<HTMLElement>) => void;
|
345 | onMenuMouseMove: (event: React.MouseEvent<HTMLElement>) => void;
|
346 | onControlMouseDown: (event: MouseOrTouchEvent) => void;
|
347 | onDropdownIndicatorMouseDown: (event: MouseOrTouchEvent) => void;
|
348 | onClearIndicatorMouseDown: (event: MouseOrTouchEvent) => void;
|
349 | onScroll: (event: Event) => void;
|
350 |
|
351 |
|
352 |
|
353 |
|
354 |
|
355 | startListeningComposition(): void;
|
356 | stopListeningComposition(): void;
|
357 | onCompositionStart: () => void;
|
358 | onCompositionEnd: () => void;
|
359 |
|
360 |
|
361 |
|
362 |
|
363 |
|
364 | startListeningToTouch(): void;
|
365 | stopListeningToTouch(): void;
|
366 | onTouchStart: (event: TouchEvent) => void;
|
367 | onTouchMove: (event: TouchEvent) => void;
|
368 | onTouchEnd: (event: TouchEvent) => void;
|
369 | onControlTouchEnd: (event: React.TouchEvent<HTMLElement>) => void;
|
370 | onClearIndicatorTouchEnd: (event: React.TouchEvent<HTMLElement>) => void;
|
371 | onDropdownIndicatorTouchEnd: (event: React.TouchEvent<HTMLElement>) => void;
|
372 |
|
373 |
|
374 |
|
375 |
|
376 |
|
377 | handleInputChange: (event: React.KeyboardEvent<HTMLInputElement>) => void;
|
378 | onInputFocus: (event: React.FocusEvent<HTMLInputElement>) => void;
|
379 | onInputBlur: (event: React.FocusEvent<HTMLInputElement>) => void;
|
380 | onOptionHover: (focusedOption: OptionType) => void;
|
381 | shouldHideSelectedOptions: () => boolean;
|
382 |
|
383 |
|
384 |
|
385 |
|
386 |
|
387 | onKeyDown: (event: React.KeyboardEvent<HTMLElement>) => void;
|
388 |
|
389 |
|
390 |
|
391 |
|
392 |
|
393 | buildMenuOptions(
|
394 | props: Props<OptionType, IsMulti, GroupType>,
|
395 | selectValue: OptionsType<OptionType>,
|
396 | ): MenuOptions<OptionType>;
|
397 |
|
398 |
|
399 |
|
400 |
|
401 | constructAriaLiveMessage(): string;
|
402 |
|
403 | renderInput(): React.ReactNode;
|
404 | renderPlaceholderOrValue(): PlaceholderOrValue<OptionType, IsMulti, GroupType> | null;
|
405 | renderClearIndicator(): React.ReactNode;
|
406 | renderLoadingIndicator(): React.ReactNode;
|
407 | renderIndicatorSeparator(): React.ReactNode;
|
408 | renderDropdownIndicator(): React.ReactNode;
|
409 | renderMenu(): React.ReactNode;
|
410 | renderFormField(): React.ReactNode;
|
411 |
|
412 | renderLiveRegion(): React.ReactNode;
|
413 | }
|