"use client"; import React, { useMemo } from "react"; import { cx } from "../../utils"; import { Text } from "../text"; import { FilterOptions, SelectOption, SelectProps } from "./types"; import ReactSelect, { createFilter } from "react-select"; type SelectSize = NonNullable; const SIZE_CLASSES: Record = { sm: "h-12 px-3 rounded-lg", md: "h-14 px-3 rounded-xl", lg: "h-16 px-3 rounded-2xl", }; export const Select: React.FC = React.memo( ({ options, className, controlClassName, value, isCustomStyle = false, placeholder, required, onChange, filterOptions, hasError, error, menuClassName, helperText, label, labelClassName, singleValueClassName, size = "md", variant = "default", "data-cy": dataCy, "data-testid": dataTestId, ...rest }) => { const memoizedFilterOption = useMemo( () => createFilter(filterOptions), [filterOptions] ); const memoizedClassNames = useMemo( () => ({ control: ({ isFocused }: any) => cx( SIZE_CLASSES[size] ?? SIZE_CLASSES.md, "border border-input-border bg-white hover:not-focus:border-input-border-hover", { "border-input-border-selected outline outline-2 outline-input-border-selected": isFocused && !hasError, "border-input-border-critical shadow-none": hasError, }, controlClassName ), indicatorSeparator: () => "hidden", dropdownIndicator: ({ selectProps }: any) => isCustomStyle ? selectProps.value ? "hidden" : "block" : `block text-icon-default ${hasError ? "text-icon-critical" : ""}`, singleValue: () => cx( isCustomStyle ? "text-text text-body1 whitespace-normal" : "text-text-secondary", singleValueClassName ), menu: () => cx( "z-20 mt-2 rounded-input-poppers bg-surface shadow-dark-drop", menuClassName ), option: ({ isFocused, isSelected, label }: any) => cx( "min-h-[40px] px-4 py-2 cursor-pointer", isSelected ? "bg-gray-200 text-text font-semibold" : "bg-white text-text-secondary", !isSelected && "hover:bg-bg-surface-hover", !isSelected && isFocused && "bg-bg-surface-hover", isCustomStyle ? "text-body1 text-text" : "", !isCustomStyle || options[options.length - 1]?.label === label ? "" : "border-b border-border-brand" ), placeholder: () => "text-input-text-placeholder", input: () => "text-text", valueContainer: () => "px-0", }), [ isCustomStyle, controlClassName, menuClassName, options, hasError, size, singleValueClassName, ] ); if (variant === "unstyled") { return ( ); } return (
{label && ( )} {error && ( {error} )} {!error && helperText && ( {helperText} )}
); } ); Select.displayName = "Select"; export type { SelectOption, SelectProps, FilterOptions };