mirror of
https://github.com/gosticks/DefinitelyTyped.git
synced 2026-06-28 14:20:12 +00:00
Add types for Menu.Divider and Menu.Header (#32299)
* add Menu.Divider and Menu.Header to Menu class * remove csstype dependency, just grab it from React * update renderToken prop definition from v3.0 upgrade * add typings for <Token /> and other exported Components, update tests * fix labelKey type to only allow for property names of an object where the value is a string * add ClearButton test
This commit is contained in:
committed by
Pranav Senthilnathan
parent
7abf322d4e
commit
2e803abbff
316
types/react-bootstrap-typeahead/index.d.ts
vendored
316
types/react-bootstrap-typeahead/index.d.ts
vendored
@@ -4,37 +4,121 @@
|
||||
// Rajab Shakirov <https://github.com/radziksh>
|
||||
// Paito Anderson <https://github.com/PaitoAnderson>
|
||||
// Andreas Richter <https://github.com/arichter83>
|
||||
// Dale Fenton <https://github.com/dalevfenton>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// TypeScript Version: 2.8
|
||||
// TODO: <Token> components
|
||||
// TypeScript Version: 2.9
|
||||
|
||||
import * as React from 'react';
|
||||
import * as CSS from 'csstype';
|
||||
export type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
|
||||
export type StringPropertyNames<T extends object> = { [K in keyof T]: T[K] extends string ? K : never }[keyof T];
|
||||
|
||||
export interface TypeaheadFilterbyProps {
|
||||
filterBy: string[];
|
||||
labelKey: (string | (() => void));
|
||||
multiple: boolean;
|
||||
selected: any[];
|
||||
caseSensitive: boolean;
|
||||
ignoreDiacritics: boolean;
|
||||
/* ---------------------------------------------------------------------------
|
||||
Constants and Enumerated Types
|
||||
--------------------------------------------------------------------------- */
|
||||
export type TypeaheadModel = string|object;
|
||||
export type TypeaheadBsSizes = 'large' | 'lg' | 'small' | 'sm';
|
||||
export type TypeaheadAlign = 'justify' | 'left' | 'right';
|
||||
// if options is an object, only let labelKey be a key of that object, whose value is a string
|
||||
// or a custom label function that takes a single option and returns a string for the label
|
||||
export type TypeaheadLabelKey<T extends TypeaheadModel> = T extends object ? (StringPropertyNames<T> | ((option: T) => string)) : never;
|
||||
// don't allow onBlur, onChange, onFocus or onKeyDown as members of inputProps
|
||||
// those props should be supplied directly to <Typeahead /> or <AsyncTypeahead />
|
||||
export interface InputProps extends Omit<React.InputHTMLAttributes<'input'>, 'onBlur'|'onChange'|'onFocus'|'onKeyDown'> { }
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
Typeahead Contexts
|
||||
--------------------------------------------------------------------------- */
|
||||
export interface TypeaheadContext<T extends TypeaheadModel> {
|
||||
activeIndex?: number;
|
||||
hintText?: string;
|
||||
initialItem?: T;
|
||||
isOnlyResult?: boolean;
|
||||
onActiveItemChange?: (options: T) => void;
|
||||
onAdd?: (option: T) => void;
|
||||
onInitialItemChange?: (option: T) => void;
|
||||
onMenuItemClick?: (option: T, e: Event) => void;
|
||||
selectHintOnEnter?: boolean;
|
||||
}
|
||||
|
||||
export interface TypeaheadState<T extends TypeaheadModel> {
|
||||
activeIndex: number|null;
|
||||
activeItem: T|null;
|
||||
initialItem: T|null;
|
||||
isFocused: boolean;
|
||||
selected: T[];
|
||||
showMenu: boolean;
|
||||
shownResults: number;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface TypeaheadMenuProps<T> {
|
||||
export interface InputContainerPropsSingle<T extends TypeaheadModel> {
|
||||
'aria-activedescendant': string;
|
||||
'aria-autocomplete': 'list' | 'both';
|
||||
'aria-expanded': boolean | 'true' | 'false';
|
||||
'aria-haspopup': 'listbox';
|
||||
'aria-owns': string;
|
||||
autoComplete: string;
|
||||
disabled: boolean;
|
||||
inputRef: React.LegacyRef<HTMLInputElement>;
|
||||
onBlur: (e: Event) => void;
|
||||
onChange: (selected: T[]) => void;
|
||||
onClick: (e: Event) => void;
|
||||
onFocus: (e: Event) => void;
|
||||
onKeyDown: (e: Event) => void;
|
||||
placeholder: string|null;
|
||||
role: 'combobox';
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface InputContainerPropsMultiple<T extends TypeaheadModel> extends Omit<InputContainerPropsSingle<T>, 'role'> {
|
||||
inputClassName: string;
|
||||
labelKey: TypeaheadLabelKey<T>;
|
||||
onRemove: (e: Event) => void;
|
||||
renderToken: (selectedItem: T, props: TypeaheadMenuProps<T>, index: number) => React.ReactNode;
|
||||
role: '';
|
||||
selected: T[];
|
||||
}
|
||||
|
||||
export type HintedInputContextKeys = 'hintText' | 'initialItem' | 'onAdd' | 'selectHintOnEnter';
|
||||
export interface HintedInputContext<T extends TypeaheadModel> extends Pick<TypeaheadContext<T>, HintedInputContextKeys> {}
|
||||
|
||||
export type MenuItemContextKeys = 'activeIndex' | 'isOnlyResult' | 'onActiveItemChange' | 'onInitialItemChange' | 'onMenuItemClick';
|
||||
export interface MenuItemContext<T extends TypeaheadModel> extends Pick<TypeaheadContext<T>, MenuItemContextKeys> {}
|
||||
|
||||
export interface TokenContext {
|
||||
active: boolean;
|
||||
onBlur: (e: any) => void;
|
||||
onClick: (e: any) => void;
|
||||
onFocus: (e: any) => void;
|
||||
onKeyDown: (e: any) => void;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
Typeahead Props and Component
|
||||
--------------------------------------------------------------------------- */
|
||||
export interface TypeaheadContainerProps<T extends TypeaheadModel> {
|
||||
activeIndex: number | null;
|
||||
activeItem: T | null;
|
||||
initialItem: T | null;
|
||||
isFocused: boolean;
|
||||
selected: T[];
|
||||
showMenu: boolean;
|
||||
shownResults: number;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface TypeaheadProps<T> {
|
||||
/* For localized accessibility: Should return a string indicating the number of results for screen readers. Receives the current results. */
|
||||
export interface TypeaheadProps<T extends TypeaheadModel> {
|
||||
/* For localized accessibility: Should return a string indicating the number of results for screen readers.
|
||||
Receives the current results. */
|
||||
a11yNumResults?: () => void;
|
||||
|
||||
/* For localized accessibility: Should return a string indicating the number of selections for screen readers. Receives the current selections. */
|
||||
/* For localized accessibility: Should return a string indicating the number of selections for screen readers.
|
||||
Receives the current selections. */
|
||||
a11yNumSelected?: () => void;
|
||||
|
||||
/* Specify menu alignment. The default value is justify, which makes the menu as wide as the input and truncates long values.
|
||||
Specifying left or right will align the menu to that side and the width will be determined by the length of menu item values. */
|
||||
align?: 'justify' | 'left' | 'right';
|
||||
align?: TypeaheadAlign;
|
||||
|
||||
/* Allows the creation of new selections on the fly. Any new items will be added to the list of selections,
|
||||
but not the list of original options unless handled as such by Typeahead's parent.
|
||||
@@ -49,7 +133,7 @@ export interface TypeaheadProps<T> {
|
||||
bodyContainer?: boolean;
|
||||
|
||||
/* Specify the size of the input. */
|
||||
bsSize?: 'large' | 'lg' | 'small' | 'sm';
|
||||
bsSize?: TypeaheadBsSizes;
|
||||
|
||||
/* Whether or not filtering should be case-sensitive. */
|
||||
caseSensitive?: boolean;
|
||||
@@ -60,6 +144,9 @@ export interface TypeaheadProps<T> {
|
||||
/* The initial value displayed in the text input. */
|
||||
defaultInputValue?: string;
|
||||
|
||||
/* Whether or not the menu is displayed upon initial render. */
|
||||
defaultOpen?: boolean;
|
||||
|
||||
/* Specify any pre-selected options. Use only if you want the component to be uncontrolled. */
|
||||
defaultSelected?: T[];
|
||||
|
||||
@@ -74,7 +161,10 @@ export interface TypeaheadProps<T> {
|
||||
emptyLabel?: string;
|
||||
|
||||
/* Either an array of fields in option to search, or a custom filtering callback. */
|
||||
filterBy?: (string[] | ((option: T | string, props: TypeaheadFilterbyProps) => boolean));
|
||||
filterBy?: (string[] | ((option: T, props: AllTypeaheadOwnAndInjectedProps<T>) => boolean));
|
||||
|
||||
/* Whether or not to automatically adjust the position of the menu when it reaches the viewport boundaries. */
|
||||
flip?: boolean;
|
||||
|
||||
/* Highlights the menu item if there is only one result and allows selecting that item by hitting enter.
|
||||
Does not work with allowNew. */
|
||||
@@ -84,7 +174,7 @@ export interface TypeaheadProps<T> {
|
||||
ignoreDiacritics?: boolean;
|
||||
|
||||
/* Props to be applied directly to the input. onBlur, onChange, onFocus, and onKeyDown are ignored. */
|
||||
inputProps?: object;
|
||||
inputProps?: InputProps;
|
||||
|
||||
/* Bootstrap 4 only. Adds the `is-invalid` classname to the `form-control`. */
|
||||
isInvalid?: boolean;
|
||||
@@ -95,8 +185,9 @@ export interface TypeaheadProps<T> {
|
||||
/* Bootstrap 4 only. Adds the `is-valid` classname to the `form-control`. */
|
||||
isValid?: boolean;
|
||||
|
||||
/* Specify which option key to use for display or a render function. By default, the selector will use the label key. */
|
||||
labelKey?: string | ((option: T | string) => string);
|
||||
/* Specify which option key to use for display or a render function.
|
||||
By default, the selector will use the label key. */
|
||||
labelKey?: TypeaheadLabelKey<T>;
|
||||
|
||||
/* Maximum height of the dropdown menu. */
|
||||
maxHeight?: string;
|
||||
@@ -105,6 +196,9 @@ export interface TypeaheadProps<T> {
|
||||
so as not to render too many DOM nodes in the case of large data sets. */
|
||||
maxResults?: number;
|
||||
|
||||
/* Id applied to the top-level menu element. Required for accessibility. */
|
||||
menuId?: string;
|
||||
|
||||
/* Number of input characters that must be entered before showing results. */
|
||||
minLength?: number;
|
||||
|
||||
@@ -115,28 +209,35 @@ export interface TypeaheadProps<T> {
|
||||
newSelectionPrefix?: string;
|
||||
|
||||
/* Invoked when the input is blurred. Receives an event. */
|
||||
onBlur?: (e: Event) => any;
|
||||
onBlur?: (e: Event) => void;
|
||||
|
||||
/* Invoked whenever items are added or removed. Receives an array of the selected options. */
|
||||
onChange?: (selected: T[]) => any;
|
||||
onChange?: (selected: T[]) => void;
|
||||
|
||||
/* Invoked when the input is focused. Receives an event. */
|
||||
onFocus?: (e: Event) => any;
|
||||
onFocus?: (e: Event) => void;
|
||||
|
||||
/* Invoked when the input value changes. Receives the string value of the input, as well as the original event. */
|
||||
onInputChange?: (input: string, e: Event) => any;
|
||||
onInputChange?: (input: string, e: Event) => void;
|
||||
|
||||
/* Invoked when a key is pressed. Receives an event. */
|
||||
onKeyDown?: (e: Event) => any;
|
||||
onKeyDown?: (e: Event) => void;
|
||||
|
||||
/* Invoked when the menu is hidden. */
|
||||
onMenuHide?: (e: Event) => any;
|
||||
/* DEPRECATED: Invoked when the menu is hidden. */
|
||||
onMenuHide?: () => void;
|
||||
|
||||
/* Invoked when the menu is shown. */
|
||||
onMenuShow?: (e: Event) => any;
|
||||
/* DEPRECATED: Invoked when the menu is shown. */
|
||||
onMenuShow?: () => void;
|
||||
|
||||
/* Invoked when menu visibility changes. */
|
||||
onMenuToggle?: (show: boolean) => void;
|
||||
|
||||
/* Invoked when the pagination menu item is clicked. */
|
||||
onPaginate?: (e: Event) => any;
|
||||
onPaginate?: (e: Event, numResults: number) => void;
|
||||
|
||||
/* Whether or not the menu should be displayed. undefined allows the component to control visibility,
|
||||
while true and false show and hide the menu, respectively. */
|
||||
open?: boolean;
|
||||
|
||||
/* Full set of options, including any pre-selected options. */
|
||||
options: T[];
|
||||
@@ -151,13 +252,13 @@ export interface TypeaheadProps<T> {
|
||||
placeholder?: string;
|
||||
|
||||
/* Callback for custom menu rendering. */
|
||||
renderMenu?: (results: Array<T | string>, menuProps: any) => any;
|
||||
renderMenu?: (results: T[], menuProps: any) => React.ReactNode;
|
||||
|
||||
/* Provides a hook for customized rendering of menu item contents. */
|
||||
renderMenuItemChildren?: (option: T, props: TypeaheadMenuProps<T>, index: number) => any;
|
||||
renderMenuItemChildren?: (option: T, props: TypeaheadMenuProps<T>, index: number) => React.ReactNode;
|
||||
|
||||
/* Provides a hook for customized rendering of tokens when multiple selections are enabled. */
|
||||
renderToken?: (selectedItem: T | string, onRemove: () => void) => any;
|
||||
renderToken?: (selectedItem: T, props: TypeaheadMenuProps<T>, index: number) => React.ReactNode;
|
||||
|
||||
/* The selected option(s) displayed in the input. Use this prop if you want to control the component via its parent. */
|
||||
selected?: T[];
|
||||
@@ -166,9 +267,13 @@ export interface TypeaheadProps<T> {
|
||||
selectHintOnEnter?: boolean;
|
||||
}
|
||||
|
||||
export const Typeahead: React.ClassicComponentClass<TypeaheadProps<any>>;
|
||||
export type AllTypeaheadOwnAndInjectedProps<T extends TypeaheadModel> = TypeaheadProps<T> & TypeaheadContainerProps<T>;
|
||||
export class Typeahead<T extends TypeaheadModel> extends React.Component<TypeaheadProps<T>> { }
|
||||
|
||||
export interface AsyncTypeaheadProps<T> extends TypeaheadProps<T> {
|
||||
/* ---------------------------------------------------------------------------
|
||||
AsyncTypeahead Props and Component
|
||||
--------------------------------------------------------------------------- */
|
||||
export interface AsyncTypeaheadProps<T extends TypeaheadModel> extends TypeaheadProps<T> {
|
||||
/* Delay, in milliseconds, before performing search. */
|
||||
delay?: number;
|
||||
|
||||
@@ -179,45 +284,148 @@ export interface AsyncTypeaheadProps<T> extends TypeaheadProps<T> {
|
||||
onSearch: (query: string) => void;
|
||||
|
||||
/* Message displayed in the menu when there is no user input. */
|
||||
promptText?: string;
|
||||
promptText?: React.ReactNode;
|
||||
|
||||
/* Message to display in the menu while the request is pending. */
|
||||
searchText?: string;
|
||||
searchText?: React.ReactNode;
|
||||
|
||||
/* Whether or not the component should cache query results. */
|
||||
useCache?: boolean;
|
||||
}
|
||||
|
||||
export const AsyncTypeahead: React.ClassicComponentClass<AsyncTypeaheadProps<any>>;
|
||||
export class AsyncTypeahead<T extends TypeaheadModel> extends React.Component<AsyncTypeaheadProps<T>> { }
|
||||
|
||||
export interface HighligherProps<T> {
|
||||
key?: string;
|
||||
search: string;
|
||||
optionId?: any;
|
||||
/* ---------------------------------------------------------------------------
|
||||
TypeaheadInputSingle & TypeaheadInputMulti Props and Component
|
||||
--------------------------------------------------------------------------- */
|
||||
export interface BaseTypeaheadInputProps extends React.InputHTMLAttributes<'input'> {
|
||||
type: 'text';
|
||||
}
|
||||
|
||||
export const Highlighter: React.ClassicComponentClass<HighligherProps<any>>;
|
||||
export interface TypeaheadSingleInputWithHocProps<T extends TypeaheadModel> extends
|
||||
Omit<BaseTypeaheadInputProps, keyof InputContainerPropsSingle<T>>,
|
||||
InputContainerPropsSingle<T> {}
|
||||
|
||||
export interface MenuProps<T> {
|
||||
export interface TypeaheadMulitInputWithHocProps<T extends TypeaheadModel> extends
|
||||
Omit<BaseTypeaheadInputProps, keyof InputContainerPropsMultiple<T>>,
|
||||
HintedInputContext<T>,
|
||||
InputContainerPropsMultiple<T> {}
|
||||
|
||||
export type TypeaheadInputPropKeys = 'bsSize'|'disabled'|'inputProps'|'labelKey'|'multiple'|
|
||||
'onBlur'|'onChange'|'onFocus'|'onKeyDown'|'placeholder'|'renderToken'|'selected';
|
||||
|
||||
export type TypeaheadInputProps<T extends TypeaheadModel> = Pick<TypeaheadProps<T>, TypeaheadInputPropKeys>;
|
||||
|
||||
export class TypeaheadInputSingle<T extends TypeaheadModel> extends React.Component<TypeaheadSingleInputWithHocProps<T>> { }
|
||||
export class TypeaheadInputMulti<T extends TypeaheadModel> extends React.Component<TypeaheadMulitInputWithHocProps<T>> { }
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
Highlighter Props and Component
|
||||
--------------------------------------------------------------------------- */
|
||||
export interface HighligherProps {
|
||||
children: React.ReactNode;
|
||||
search: string;
|
||||
}
|
||||
|
||||
export class Highlighter extends React.PureComponent<HighligherProps> { }
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
ClearButton Props and Component
|
||||
--------------------------------------------------------------------------- */
|
||||
export interface ClearButtonProps extends React.HTMLAttributes<'button'> {
|
||||
bsSize?: TypeaheadBsSizes;
|
||||
label?: string;
|
||||
onClick: React.HTMLAttributes<'button'>['onClick']; // make onClick requried
|
||||
}
|
||||
|
||||
export const ClearButton: React.FunctionComponent<ClearButtonProps>;
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
Loader Props and Component
|
||||
--------------------------------------------------------------------------- */
|
||||
export interface LoaderProps {
|
||||
bsSize: TypeaheadBsSizes;
|
||||
}
|
||||
|
||||
export const Loader: React.FunctionComponent<LoaderProps>;
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
AutosizeInput Props and Component
|
||||
--------------------------------------------------------------------------- */
|
||||
export interface AutosizeInputProps extends Pick<React.InputHTMLAttributes<'input'>, 'className' | 'style'> {
|
||||
inputClassName?: string;
|
||||
inputRef?: React.LegacyRef<HTMLInputElement>;
|
||||
inputStyle?: Pick<React.CSSProperties, 'boxSizing' | 'width'>;
|
||||
style: React.CSSProperties;
|
||||
}
|
||||
|
||||
export class AutosizeInput extends React.Component<AutosizeInputProps> { }
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
Menu Props and Component
|
||||
--------------------------------------------------------------------------- */
|
||||
export interface MenuProps {
|
||||
id: string;
|
||||
className?: string;
|
||||
emptyLabel?: string;
|
||||
innerRef?: string;
|
||||
innerRef?: React.LegacyRef<HTMLUListElement>;
|
||||
maxHeight?: string;
|
||||
style?: CSS.Properties;
|
||||
style?: React.CSSProperties;
|
||||
text?: string;
|
||||
}
|
||||
|
||||
export const Menu: React.ClassicComponentClass<MenuProps<any>>;
|
||||
export type MenuHeaderProps = Omit<React.HTMLProps<'li'>, 'className'>;
|
||||
|
||||
export interface MenuItemProps<T> {
|
||||
export class Menu extends React.Component<MenuProps> {
|
||||
static Divider: React.FunctionComponent;
|
||||
static Header: React.FunctionComponent<MenuHeaderProps>;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
TypeaheadMenu Props and Component
|
||||
--------------------------------------------------------------------------- */
|
||||
// prop names that Typeahead provides to TypeaheadMenu
|
||||
export type TypeaheadMenuPropsPick = 'labelKey' | 'newSelectionPrefix'| 'options' | 'renderMenuItemChildren';
|
||||
export interface TypeaheadMenuProps<T extends TypeaheadModel> extends MenuProps, Pick<AllTypeaheadOwnAndInjectedProps<T>, TypeaheadMenuPropsPick> {}
|
||||
export class TypeaheadMenu<T extends TypeaheadModel> extends React.Component<TypeaheadMenuProps<T>> { }
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
Menu Item Props and Component
|
||||
--------------------------------------------------------------------------- */
|
||||
export interface BaseMenuItemProps extends React.HTMLProps<'li'> {
|
||||
active?: boolean;
|
||||
}
|
||||
export class BaseMenuItem extends React.Component<BaseMenuItemProps> { }
|
||||
|
||||
export interface MenuItemProps<T extends TypeaheadModel> extends BaseMenuItemProps {
|
||||
option: T;
|
||||
position: number;
|
||||
label?: string;
|
||||
active?: boolean;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
onClick?: (e: Event) => any;
|
||||
onMouseDown?: (e: Event) => any;
|
||||
}
|
||||
|
||||
export const MenuItem: React.ClassicComponentClass<MenuItemProps<any>>;
|
||||
export class MenuItem<T extends TypeaheadModel> extends React.Component<MenuItemProps<T>> { }
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
Overlay Props and Component
|
||||
--------------------------------------------------------------------------- */
|
||||
export type OverlayTypeaheadProps = Pick<TypeaheadProps<any>, 'align' | 'dropup' | 'flip' | 'onMenuHide' | 'onMenuShow' | 'onMenuToggle'>;
|
||||
|
||||
export interface OverlayProps extends OverlayTypeaheadProps {
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
container: HTMLElement;
|
||||
referenceElement?: HTMLElement;
|
||||
show?: boolean;
|
||||
}
|
||||
|
||||
export class Overlay extends React.Component<OverlayProps> { }
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
Token Props and Component
|
||||
--------------------------------------------------------------------------- */
|
||||
export interface TokenProps extends React.HTMLProps<'div'> {
|
||||
active?: boolean;
|
||||
onRemove?: () => void; // Token does not invoke onRemove with any parameters
|
||||
}
|
||||
|
||||
export class Token extends React.Component<TokenProps> { }
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"csstype": "^2.2.0"
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,78 @@
|
||||
import * as React from 'react';
|
||||
import { Typeahead, Highlighter, Menu, MenuItem } from 'react-bootstrap-typeahead';
|
||||
import { ClearButton, Typeahead, Highlighter, Menu, MenuItem, Token } from 'react-bootstrap-typeahead';
|
||||
|
||||
const options = [
|
||||
{ name: 'Alabama', population: 4780127, capital: 'Montgomery', region: 'South' },
|
||||
{ name: 'Alaska', population: 710249, capital: 'Juneau', region: 'West' },
|
||||
{ name: 'Arizona', population: 6392307, capital: 'Phoenix', region: 'West' },
|
||||
{ name: 'Arkansas', population: 2915958, capital: 'Little Rock', region: 'South' },
|
||||
{ name: 'California', population: 37254503, capital: 'Sacramento', region: 'West' },
|
||||
{ name: 'Colorado', population: 5029324, capital: 'Denver', region: 'West' },
|
||||
interface State {
|
||||
capital: string;
|
||||
name: string;
|
||||
population: number;
|
||||
region: string;
|
||||
setValue: (value: State) => void;
|
||||
}
|
||||
interface GroupedStates {
|
||||
[key: string]: State[];
|
||||
}
|
||||
type StringPropertyNames<T> = { [K in keyof T]: T[K] extends string ? K : never }[keyof T];
|
||||
type StateKeysValid = StringPropertyNames<State>;
|
||||
const options: State[] = [
|
||||
{ name: 'Alabama', population: 4780127, capital: 'Montgomery', region: 'South', setValue: () => {} },
|
||||
{ name: 'Alaska', population: 710249, capital: 'Juneau', region: 'West', setValue: () => {} },
|
||||
{ name: 'Arizona', population: 6392307, capital: 'Phoenix', region: 'West', setValue: () => {} },
|
||||
{ name: 'Arkansas', population: 2915958, capital: 'Little Rock', region: 'South', setValue: () => {} },
|
||||
{ name: 'California', population: 37254503, capital: 'Sacramento', region: 'West', setValue: () => {} },
|
||||
{ name: 'Colorado', population: 5029324, capital: 'Denver', region: 'West', setValue: () => {} },
|
||||
];
|
||||
|
||||
const stateNames = options.map(o => o.name);
|
||||
|
||||
const groups: GroupedStates = options.reduce((accum: GroupedStates, option: State) => {
|
||||
const optKey = option.name.slice(0, 1).toLowerCase();
|
||||
if (accum[optKey] !== undefined) {
|
||||
accum[optKey].push(option);
|
||||
} else {
|
||||
accum[optKey] = [option];
|
||||
}
|
||||
return accum;
|
||||
}, {});
|
||||
|
||||
class BasicExample extends React.Component {
|
||||
state = {
|
||||
multiple: false,
|
||||
};
|
||||
|
||||
genCustomMenu = () => {
|
||||
const menuItems = Object.keys(groups).reduce((accum, letter) => {
|
||||
const header = [
|
||||
<Menu.Divider key={`${letter}-start`} />,
|
||||
<Menu.Header key={`${letter}-header`}>
|
||||
{`States starting with: ${letter.toUpperCase()}`}
|
||||
<ClearButton onClick={() => {}} />
|
||||
</Menu.Header>,
|
||||
<Menu.Divider key={`${letter}-end`} />,
|
||||
];
|
||||
const states = groups[letter].map((state: State, index: number) => {
|
||||
return (<MenuItem key={state.name} position={index} option={state}>{state.name}</MenuItem>);
|
||||
});
|
||||
return [...accum, ...header, ...states];
|
||||
}, [] as JSX.Element[]);
|
||||
|
||||
return menuItems;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { multiple } = this.state;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Typeahead
|
||||
options={stateNames}
|
||||
placeholder="Choose a name"
|
||||
/>
|
||||
<Typeahead
|
||||
options={stateNames}
|
||||
placeholder="Choose a name"
|
||||
multiple
|
||||
filterBy={(option, props) => (props.text.indexOf(option) !== -1)}
|
||||
/>
|
||||
<Typeahead
|
||||
labelKey="name"
|
||||
multiple={multiple}
|
||||
@@ -33,7 +86,7 @@ class BasicExample extends React.Component {
|
||||
multiple={multiple}
|
||||
options={options}
|
||||
maxHeight='300px'
|
||||
filterBy={(option, props) => (props.text.indexOf(option) !== -1) }
|
||||
filterBy={(option, props) => (props.text.indexOf(option.name) !== -1) }
|
||||
placeholder="Choose a state..."
|
||||
/>
|
||||
<Typeahead
|
||||
@@ -41,7 +94,7 @@ class BasicExample extends React.Component {
|
||||
multiple={multiple}
|
||||
options={options}
|
||||
maxHeight='300px'
|
||||
filterBy={(option, {text}) => (text.indexOf(option) !== -1) }
|
||||
filterBy={(option, {text}) => (text.indexOf(option.name) !== -1) }
|
||||
placeholder="Choose a state..."
|
||||
/>
|
||||
<Typeahead
|
||||
@@ -49,7 +102,7 @@ class BasicExample extends React.Component {
|
||||
options={options}
|
||||
placeholder="Choose a state..."
|
||||
renderMenuItemChildren={ (option, props, index) =>
|
||||
<Highlighter key="name" search={props.text}>
|
||||
<Highlighter key="name" search={props.text || ""}>
|
||||
{option.name} {index}
|
||||
</Highlighter>
|
||||
}
|
||||
@@ -69,6 +122,23 @@ class BasicExample extends React.Component {
|
||||
))}
|
||||
</Menu>
|
||||
</Typeahead>
|
||||
<Typeahead
|
||||
labelKey="name"
|
||||
options={options}
|
||||
placeholder="Choose a state..."
|
||||
renderToken={(selectedItem, props, index) => {
|
||||
return <Token
|
||||
active
|
||||
disabled={false}
|
||||
tabIndex={5}
|
||||
href="https://test.com"
|
||||
onRemove={() => console.log(props.text)}>
|
||||
{selectedItem.name}<ClearButton onClick={() => {}} />
|
||||
</Token>;
|
||||
}}
|
||||
>
|
||||
<Menu id="menu-id">{...this.genCustomMenu()}</Menu>
|
||||
</Typeahead>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user