Skip to content

Commit faa336e

Browse files
committed
Consolidate types
1 parent 1d29d7a commit faa336e

File tree

8 files changed

+210
-194
lines changed

8 files changed

+210
-194
lines changed

src/components/Typeahead/Typeahead.tsx

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
import cx from 'classnames';
2-
import React, { CSSProperties, forwardRef, ReactNode, useState } from 'react';
2+
import React, {
3+
CSSProperties,
4+
forwardRef,
5+
InputHTMLAttributes,
6+
ReactNode,
7+
useState,
8+
} from 'react';
39

4-
import { TypeaheadContext, TypeaheadRef, useTypeahead } from '../../core';
10+
import {
11+
TypeaheadContext,
12+
TypeaheadProps,
13+
TypeaheadRef,
14+
useTypeahead,
15+
} from '../../core';
516
import { useOverlay } from '../../hooks';
617

718
import ClearButton from '../ClearButton';
@@ -23,22 +34,32 @@ import {
2334

2435
import {
2536
Align,
37+
LabelKey,
2638
Option,
27-
RenderToken,
28-
RenderTokenProps,
39+
OptionHandler,
2940
Size,
3041
TypeaheadInputProps,
31-
TypeaheadProps,
32-
TypeaheadChildProps,
33-
TypeaheadChildren,
3442
SelectEvent,
3543
} from '../../types';
3644

37-
export interface RenderMenuProps extends MenuProps {
38-
newSelectionPrefix?: ReactNode;
39-
onItemSelect: (option: Option) => void;
40-
paginationText?: ReactNode;
41-
renderMenuItemChildren?: RenderMenuItemChildren;
45+
export type TypeaheadChildren =
46+
| ReactNode
47+
| ((props: TypeaheadChildProps) => ReactNode);
48+
49+
export interface TypeaheadChildProps {
50+
getInputProps: (
51+
props?: InputHTMLAttributes<HTMLInputElement>
52+
) => Omit<TypeaheadInputProps, 'referenceElementRef'>;
53+
hideMenu: () => void;
54+
isMenuShown: boolean;
55+
labelKey: LabelKey;
56+
onClear: () => void;
57+
onHide: () => void;
58+
onRemove: OptionHandler;
59+
results: Option[];
60+
selected: Option[];
61+
text: string;
62+
toggleMenu: () => void;
4263
}
4364

4465
export interface TypeaheadComponentProps extends TypeaheadProps {
@@ -113,6 +134,13 @@ export interface TypeaheadComponentProps extends TypeaheadProps {
113134
style?: CSSProperties;
114135
}
115136

137+
export interface RenderMenuProps extends MenuProps {
138+
newSelectionPrefix?: ReactNode;
139+
onItemSelect: (option: Option) => void;
140+
paginationText?: ReactNode;
141+
renderMenuItemChildren?: RenderMenuItemChildren;
142+
}
143+
116144
const defaultRenderMenu = (
117145
results: Option[],
118146
menuProps: RenderMenuProps,
@@ -126,6 +154,19 @@ const defaultRenderMenu = (
126154
/>
127155
);
128156

157+
export interface RenderTokenProps {
158+
disabled?: boolean;
159+
labelKey: LabelKey;
160+
onRemove?: OptionHandler;
161+
tabIndex?: number;
162+
}
163+
164+
export type RenderToken = (
165+
option: Option,
166+
props: RenderTokenProps,
167+
idx: number
168+
) => JSX.Element;
169+
129170
const defaultRenderToken = (
130171
option: Option,
131172
props: RenderTokenProps,

src/components/TypeaheadInputSingle/TypeaheadInputSingle.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export default {
1111
component: TypeaheadInputSingle,
1212
} as Meta;
1313

14-
interface Args extends Omit<TypeaheadInputProps, 'size'> {
14+
interface Args extends TypeaheadInputProps {
1515
hintText?: string;
1616
isInvalid?: boolean;
1717
isValid?: boolean;

src/core/useTypeahead.ts

Lines changed: 130 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import isEqual from 'fast-deep-equal';
22
import React, {
3+
ChangeEvent,
4+
FocusEventHandler,
5+
InputHTMLAttributes,
6+
KeyboardEventHandler,
37
Ref,
48
useCallback,
59
useEffect,
@@ -21,10 +25,12 @@ import {
2125
import useValidateProps from './useValidateProps';
2226

2327
import {
28+
AllowNew,
2429
FilterByCallback,
25-
InternalProps,
30+
Id,
31+
LabelKey,
2632
Option,
27-
TypeaheadProps,
33+
SelectHint,
2834
TypeaheadState,
2935
} from '../types';
3036

@@ -147,6 +153,128 @@ export interface TypeaheadRef {
147153
toggleMenu: () => void;
148154
}
149155

156+
export interface TypeaheadProps {
157+
/**
158+
* Allows the creation of new selections on the fly. Note that any new items
159+
* will be added to the list of selections, but not the list of original
160+
* options unless handled as such by `Typeahead`'s parent.
161+
*
162+
* If a function is specified, it will be used to determine whether a custom
163+
* option should be included. The return value should be true or false.
164+
*/
165+
allowNew?: AllowNew;
166+
/**
167+
* Autofocus the input when the component initially mounts.
168+
*/
169+
autoFocus?: boolean;
170+
/**
171+
* Whether or not filtering should be case-sensitive.
172+
*/
173+
caseSensitive?: boolean;
174+
/**
175+
* The initial value displayed in the text input.
176+
*/
177+
defaultInputValue?: string;
178+
/**
179+
* Whether or not the menu is displayed upon initial render.
180+
*/
181+
defaultOpen?: boolean;
182+
/**
183+
* Specify any pre-selected options. Use only if you want the component to
184+
* be uncontrolled.
185+
*/
186+
defaultSelected?: Option[];
187+
/**
188+
* Either an array of fields in `option` to search, or a custom filtering
189+
* callback.
190+
*/
191+
filterBy?: string[] | FilterByCallback;
192+
/**
193+
* Highlights the menu item if there is only one result and allows selecting
194+
* that item by hitting enter. Does not work with `allowNew`.
195+
*/
196+
highlightOnlyResult?: boolean;
197+
/**
198+
* An html id attribute, required for assistive technologies such as screen
199+
* readers.
200+
*/
201+
id?: Id;
202+
/**
203+
* Whether the filter should ignore accents and other diacritical marks.
204+
*/
205+
ignoreDiacritics?: boolean;
206+
inputProps?: InputHTMLAttributes<HTMLInputElement>;
207+
/**
208+
* Specify the option key to use for display or a function returning the
209+
* display string. By default, the selector will use the `label` key.
210+
*/
211+
labelKey?: LabelKey;
212+
/**
213+
* Number of input characters that must be entered before showing results.
214+
*/
215+
minLength?: number;
216+
/**
217+
* Whether or not multiple selections are allowed.
218+
*/
219+
multiple?: boolean;
220+
/**
221+
* Invoked when the input is blurred. Receives an event.
222+
*/
223+
onBlur?: FocusEventHandler<HTMLInputElement>;
224+
/**
225+
* Invoked whenever items are added or removed. Receives an array of the
226+
* selected options.
227+
*/
228+
onChange?: (selected: Option[]) => void;
229+
/**
230+
* Invoked when the input is focused. Receives an event.
231+
*/
232+
onFocus?: FocusEventHandler<HTMLInputElement>;
233+
/**
234+
* Invoked when the input value changes. Receives the string value of the
235+
* input.
236+
*/
237+
onInputChange?: (text: string, event: ChangeEvent<HTMLInputElement>) => void;
238+
/**
239+
* Invoked when a key is pressed. Receives an event.
240+
*/
241+
onKeyDown?: KeyboardEventHandler<HTMLInputElement>;
242+
/**
243+
* Invoked when menu visibility changes.
244+
*/
245+
onMenuToggle?: (isOpen: boolean) => void;
246+
247+
/**
248+
* Whether or not the menu should be displayed. `undefined` allows the
249+
* component to control visibility, while `true` and `false` show and hide
250+
* the menu, respectively.
251+
*/
252+
open?: boolean;
253+
/**
254+
* Full set of options, including pre-selected options. Must either be an
255+
* array of objects (recommended) or strings.
256+
*/
257+
options: Option[];
258+
/**
259+
* The selected option(s) displayed in the input. Use this prop if you want
260+
* to control the component via its parent.
261+
*/
262+
selected?: Option[];
263+
selectHint?: SelectHint;
264+
}
265+
266+
type OptionalProps<T, K extends keyof T> = Partial<Pick<T, K>> &
267+
Required<Omit<T, K>>;
268+
269+
/**
270+
* Most props used internally become "required" since they're given default
271+
* values.
272+
*/
273+
export type InternalProps = OptionalProps<
274+
Required<Omit<TypeaheadProps, 'onChange'>>,
275+
'id' | 'open' | 'selected' | 'selectHint'
276+
>;
277+
150278
function useTypeahead(
151279
{ onChange, ...partialProps }: TypeaheadProps,
152280
ref?: Ref<TypeaheadRef>

src/core/useValidateProps.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { useEffect } from 'react';
2-
import { InputProps, TypeaheadProps } from '../types';
1+
import { HTMLAttributes, useEffect } from 'react';
2+
3+
import { TypeaheadProps } from './useTypeahead';
34
import { isFunction, warn } from '../utils';
45

56
interface InputPropItem {
67
alt: string;
7-
prop: keyof InputProps;
8+
prop: keyof HTMLAttributes<HTMLInputElement>;
89
}
910

1011
const INPUT_PROPS_BLACKLIST: InputPropItem[] = [

src/hooks/useAsync.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import usePrevious from '@restart/hooks/usePrevious';
55

66
import { isFunction } from '../utils';
77

8-
import type { Option, TypeaheadProps } from '../types';
8+
import { TypeaheadProps } from '../core';
9+
import type { Option } from '../types';
910

1011
export interface UseAsyncProps extends TypeaheadProps {
1112
/**

0 commit comments

Comments
 (0)