import * as React from 'react';
import classnames from 'classnames';
import {
FloatingFocusManager,
FloatingOverlay,
useMergeRefs,
} from '@floating-ui/react';
import {isTouchScreen, __DEV__, invariant, generateId} from '../utils';
import Icon from '../icons/Icon';
import SubjectIcon from '../subject-icons/SubjectIcon';
import type {IconTypeType as SubjectIconTypeType} from '../subject-icons/SubjectIcon';
import type {IconTypeType} from '../icons/Icon';
import Text from '../text/Text';
import useSelectMenu from './useSelectMenu';
import useFloatingSelectMenu from './useFloatingSelectMenu';
import useSelectMenuAnimations from './useSelectMenuAnimations';
import SelectMenuOption from './SelectMenuOption';
export type SelectMenuOptionType = {
value: string;
label: string;
icon?: {
name: IconTypeType | SubjectIconTypeType;
isSubjectIcon?: boolean;
};
};
export type SelectMenuSizeType = 's' | 'm' | 'l';
export const SIZE = {
S: 's',
M: 'm',
L: 'l',
} as const;
const DEFAULT_SIZE = SIZE.M;
const ICON_SIZE_MAP = {
[SIZE.L]: 32,
[SIZE.M]: 24,
[SIZE.S]: 16,
} as const;
type SelectMenuColorType = 'default' | 'white';
export const COLOR = {
DEFAULT: 'default',
WHITE: 'white',
} as const;
export type SelectMenuPropsType = {
/**
* Optional string. Additional class names.
*/
className?: string;
/**
* Optional string. Select placeholder text.
* @example
* @default 'Select...'
*/
placeholder?: string;
/**
* Optional boolean. Set to true if select is valid.
* @example
* @default false
* */
valid?: boolean;
/**
* Optional boolean. Set to true if select is invalid.
* @example
* @default false
*/
invalid?: boolean;
/**
* Optional array. Select options.
* @example
* @default []
*/
options?: ReadonlyArray;
/**
* Optional array. Select selected options.
* @example
* @default []
*/
selectedOptions?: ReadonlyArray;
/**
* Optional boolean. Set to true, if user can select multiple options.
* @example
*/
multiSelect?: boolean;
/**
* Optional boolean. Set when you want to manually controll select popup menu appearance. If not set, the component will manage it itself.
* @example
* @default undefined
*/
expanded?: boolean;
/**
* Optional boolean. Set when you want to display select popup menu on first render, but you want the component manage it's expanded state itself.
* @example
* @default undefined
*/
defaultExpanded?: boolean;
/**
* Optional boolean. Set to `true` when you want to display option icon (if it has any).
* @example
* @default false
*/
withIcons?: boolean;
/**
* Optional boolean. Set to `true` if you want to disable select.
* @example
*/
disabled?: boolean;
/**
* Set to change the Select size. There are three sizes options: `s`, `m` and `l`.
* @example
* @default "m"
*/
size?: SelectMenuSizeType;
/**
* There are two color variants, `default` and `white`. The default does not have to be specified.
* @example
*/
color?: SelectMenuColorType | null | undefined;
/**
* Optional callback. Called by clicking on the any part of the Select component.
* @example