2022-04-11 11:57:07 +00:00
|
|
|
import React from 'react';
|
|
|
|
|
import _ from 'lodash';
|
2025-12-05 08:43:11 +00:00
|
|
|
import Select, { components } from 'react-select';
|
2026-04-20 08:31:24 +00:00
|
|
|
import CreatableSelect from 'react-select/creatable';
|
2022-04-11 11:57:07 +00:00
|
|
|
import defaultStyles from './styles';
|
2025-12-05 08:43:11 +00:00
|
|
|
const CustomInput = (props) => {
|
2025-12-19 09:03:32 +00:00
|
|
|
return <components.Input {...props} data-cy={`${props.selectProps.dataCy || ''}-select-dropdown-input`} />;
|
2025-12-05 08:43:11 +00:00
|
|
|
};
|
2026-04-20 08:31:24 +00:00
|
|
|
export const SelectComponent = ({
|
|
|
|
|
options = [],
|
|
|
|
|
value,
|
|
|
|
|
onChange,
|
|
|
|
|
closeMenuOnSelect,
|
|
|
|
|
darkMode,
|
|
|
|
|
creatable = false,
|
|
|
|
|
...restProps
|
|
|
|
|
}) => {
|
2025-04-09 17:23:57 +00:00
|
|
|
const selectRef = React.useRef(null);
|
2024-04-19 07:25:16 +00:00
|
|
|
const isDarkMode = darkMode ?? localStorage.getItem('darkMode') === 'true';
|
2026-04-20 08:31:24 +00:00
|
|
|
const SelectElement = creatable ? CreatableSelect : Select;
|
2022-04-11 11:57:07 +00:00
|
|
|
const {
|
2023-01-04 07:58:55 +00:00
|
|
|
isMulti = false,
|
2023-01-03 11:42:43 +00:00
|
|
|
styles = {},
|
2022-12-22 20:39:57 +00:00
|
|
|
isLoading = false,
|
2022-04-11 11:57:07 +00:00
|
|
|
hasSearch = true,
|
|
|
|
|
height,
|
|
|
|
|
width,
|
|
|
|
|
placeholder = 'Select..',
|
|
|
|
|
customOption = undefined,
|
|
|
|
|
defaultValue = null,
|
2023-01-25 12:32:39 +00:00
|
|
|
useMenuPortal = true, // todo: deprecate this prop, use menuPortalTarget instead
|
2022-04-27 12:51:50 +00:00
|
|
|
maxMenuHeight = 250,
|
2022-12-22 20:39:57 +00:00
|
|
|
menuPortalTarget = null,
|
2022-12-26 11:39:12 +00:00
|
|
|
menuPlacement = 'auto',
|
2023-01-03 11:42:43 +00:00
|
|
|
useCustomStyles = false,
|
2023-01-05 06:23:53 +00:00
|
|
|
isDisabled = false,
|
2024-11-20 16:38:21 +00:00
|
|
|
borderRadius,
|
2025-04-09 17:23:57 +00:00
|
|
|
openMenuOnFocus = false,
|
2025-05-09 03:58:19 +00:00
|
|
|
customClassPrefix = '',
|
2025-12-05 08:43:11 +00:00
|
|
|
dataCy = '',
|
2022-04-11 11:57:07 +00:00
|
|
|
} = restProps;
|
2024-11-20 16:38:21 +00:00
|
|
|
const customStyles = useCustomStyles ? styles : defaultStyles(isDarkMode, width, height, styles, borderRadius);
|
2022-04-11 11:57:07 +00:00
|
|
|
const selectOptions =
|
|
|
|
|
Array.isArray(options) && options.length === 0
|
|
|
|
|
? options
|
2024-04-19 11:52:06 +00:00
|
|
|
: options?.map((option) => {
|
2026-02-06 09:12:33 +00:00
|
|
|
if (!option.hasOwnProperty('label')) {
|
|
|
|
|
return _.mapKeys(option, (value, key) => (key === 'value' ? key : 'label'));
|
|
|
|
|
}
|
|
|
|
|
return option;
|
|
|
|
|
});
|
|
|
|
|
const currentValue = value ? selectOptions.find((option) => option.value === value) || value : defaultValue;
|
2023-01-04 07:58:55 +00:00
|
|
|
const handleOnChange = (data) => {
|
|
|
|
|
if (isMulti) {
|
|
|
|
|
onChange(data);
|
|
|
|
|
} else {
|
|
|
|
|
onChange(data.value);
|
|
|
|
|
}
|
2022-04-11 11:57:07 +00:00
|
|
|
};
|
|
|
|
|
const renderCustomOption = (option) => {
|
|
|
|
|
if (customOption) {
|
|
|
|
|
return customOption(option);
|
|
|
|
|
}
|
|
|
|
|
return option.label;
|
|
|
|
|
};
|
|
|
|
|
return (
|
2026-04-20 08:31:24 +00:00
|
|
|
<SelectElement
|
2025-09-11 08:40:20 +00:00
|
|
|
{...restProps}
|
|
|
|
|
ref={selectRef}
|
2025-09-17 06:45:01 +00:00
|
|
|
selectRef={selectRef} // Exposed ref for custom components if needed
|
2025-09-11 08:40:20 +00:00
|
|
|
isLoading={isLoading}
|
|
|
|
|
isDisabled={isDisabled || isLoading}
|
|
|
|
|
options={selectOptions}
|
|
|
|
|
value={currentValue}
|
2026-03-04 14:02:05 +00:00
|
|
|
isSearchable={restProps.isSearchable ?? hasSearch}
|
2025-09-11 08:40:20 +00:00
|
|
|
onChange={handleOnChange}
|
|
|
|
|
placeholder={placeholder}
|
|
|
|
|
styles={customStyles}
|
|
|
|
|
openMenuOnFocus={openMenuOnFocus}
|
|
|
|
|
formatOptionLabel={(option) => renderCustomOption(option)}
|
|
|
|
|
menuPlacement={menuPlacement}
|
|
|
|
|
maxMenuHeight={maxMenuHeight}
|
|
|
|
|
menuPortalTarget={useMenuPortal ? document.body : menuPortalTarget}
|
|
|
|
|
closeMenuOnSelect={closeMenuOnSelect ?? true}
|
|
|
|
|
classNamePrefix={`${customClassPrefix} ${isDarkMode && 'dark-theme'} ${'react-select'}`}
|
2025-12-05 08:43:11 +00:00
|
|
|
components={{
|
|
|
|
|
Input: CustomInput,
|
2025-12-19 09:03:32 +00:00
|
|
|
...restProps.components,
|
2025-12-05 08:43:11 +00:00
|
|
|
}}
|
2025-09-11 08:40:20 +00:00
|
|
|
/>
|
2022-04-11 11:57:07 +00:00
|
|
|
);
|
2026-03-19 07:11:32 +00:00
|
|
|
};
|