import classNames from "classnames"; import * as React from "react"; import { Button, DISPLAYNAME_PREFIX, HTMLInputProps, IInputGroupProps, InputGroup, IPopoverProps, Keys, Popover, Position, Utils, } from "reui-core"; import { Classes, IListItemsProps } from "../../common"; import { IQueryListRendererProps, QueryList } from "../query-list/queryList"; export interface ISelectProps extends IListItemsProps { /** * Whether the dropdown list can be filtered. * Disabling this option will remove the `InputGroup` and ignore `inputProps`. * @default true */ filterable?: boolean; /** * Whether the component is non-interactive. * Note that you'll also need to disable the component's children, if appropriate. * @default false */ disabled?: boolean; /** * Props to spread to the query `InputGroup`. Use `query` and * `onQueryChange` instead of `inputProps.value` and `inputProps.onChange` * to control this input. Use `inputRef` instead of `ref`. */ inputProps?: IInputGroupProps & HTMLInputProps; /** Props to spread to `Popover`. Note that `content` cannot be changed. */ popoverProps?: Partial & object; /** * Whether the filtering state should be reset to initial when the popover closes. * The query will become the empty string and the first item will be made active. * @default false */ resetOnClose?: boolean; } export interface ISelectState { isOpen: boolean; } export class Select extends React.PureComponent, ISelectState> { public static displayName = `${DISPLAYNAME_PREFIX}.Select`; public static ofType() { return Select as new (props: ISelectProps) => Select; } private TypedQueryList = QueryList.ofType(); private input?: HTMLInputElement | null; private list?: QueryList | null; private previousFocusedElement: HTMLElement | undefined; private refHandlers = { input: (ref: HTMLInputElement | null) => { this.input = ref; const { inputProps = {} } = this.props; Utils.safeInvoke(inputProps.inputRef, ref); }, queryList: (ref: QueryList | null) => (this.list = ref), }; constructor(props: ISelectProps, context?: any) { super(props, context); this.state = { isOpen: false }; } public render() { // omit props specific to this component, spread the rest. const { filterable, inputProps, popoverProps, ...restProps } = this.props; return ( ); } public componentDidUpdate(_prevProps: ISelectProps, prevState: ISelectState) { if (this.state.isOpen && !prevState.isOpen && this.list != null) { this.list.scrollActiveItemIntoView(); } } private renderQueryList = (listProps: IQueryListRendererProps) => { // not using defaultProps cuz they're hard to type with generics (can't use on static members) const { filterable = true, disabled = false, inputProps = {}, popoverProps = {} } = this.props; const input = ( ); const { handleKeyDown, handleKeyUp } = listProps; return (
{this.props.children}
{filterable ? input : undefined} {listProps.itemList}
); }; private maybeRenderClearButton(query: string) { return query.length > 0 ?