/* eslint-disable filename-rules/match */ import type { ReactElement, ReactNode } from 'react'; import type { Either, HTMLElementProps } from '@leafygreen-ui/lib'; /** * Prop Enums & Types */ export const ComboboxElement = { Input: 'Input', ClearButton: 'ClearButton', FirstChip: 'FirstChip', LastChip: 'LastChip', MiddleChip: 'MiddleChip', Combobox: 'Combobox', Menu: 'Menu', } as const; export type ComboboxElement = typeof ComboboxElement[keyof typeof ComboboxElement]; /** * Prop types */ export const ComboboxSize = { // TODO: add XSmall & Small variants after the refresh // XSmall: 'xsmall', // Small: 'small', Default: 'default', Large: 'large', } as const; export type ComboboxSize = typeof ComboboxSize[keyof typeof ComboboxSize]; export const TruncationLocation = { start: 'start', middle: 'middle', end: 'end', none: 'none', } as const; export type TruncationLocation = typeof TruncationLocation[keyof typeof TruncationLocation]; export const Overflow = { /** * Combobox will be set to a fixed width, and will expand its height based on the number of Chips selected */ expandY: 'expand-y', /** * Combobox will be set to a fixed height and width (default 100% of container). Chips will be scrollable left-right */ scrollX: 'scroll-x', /** * @deprecated */ expandX: 'expand-x', } as const; export type Overflow = typeof Overflow[keyof typeof Overflow]; export const State = { error: 'error', none: 'none', } as const; export type State = typeof State[keyof typeof State]; export const SearchState = { unset: 'unset', error: 'error', loading: 'loading', } as const; export type SearchState = typeof SearchState[keyof typeof SearchState]; /** * Generic Typing */ export type SelectValueType = M extends true ? Array : string | null; export type onChangeType = M extends true ? (value: SelectValueType) => void : (value: SelectValueType) => void; // Returns the correct empty state for multiselcect / single select export function getNullSelection( multiselect: M ): SelectValueType { if (multiselect) { return [] as Array as SelectValueType; } else { return null as SelectValueType; } } /** * Combobox Props */ export interface ComboboxMultiselectProps { /** * Defines whether a user can select multiple options, or only a single option. * When using TypeScript, `multiselect` affects the valid values of `initialValue`, `value`, and `onChange` */ multiselect?: M; /** * The initial selection. * Must be a string (or array of strings) that matches the `value` prop of a `ComboboxOption`. * Changing the `initialValue` after initial render will not change the selection. */ initialValue?: SelectValueType; /** * A callback called when the selection changes. * Callback receives a single argument that is the new selection, either string, or string array */ onChange?: onChangeType; /** * The controlled value of the Combobox. * Must be a string (or array of strings) that matches the `value` prop of a `ComboboxOption`. * Changing `value` after initial render _will_ affect the selection. * `value` will always take precedence over `initialValue` if both are provided. */ value?: SelectValueType; /** * Defines the overflow behavior of a multiselect combobox. * * `expand-y`: Combobox has fixed width, and additional selections will cause the element to grow in the block direction. * * `expand-x`: Combobox has fixed height, and additional selections will cause the element to grow in the inline direction. * * `scroll-x`: Combobox has fixed height and width, and additional selections will cause the element to be scrollable in the x (horizontal) direction. */ overflow?: M extends true ? Overflow : undefined; } export interface BaseComboboxProps extends Omit, 'onChange'> { /** * Defines the Combobox Options by passing children. Must be `ComboboxOption` or `ComboboxGroup` */ children?: ReactNode; /** * An accessible label for the input, rendered in a