ToolJet/frontend/src/_ui/Select/SelectComponent.jsx
Nakul Nagargade 433e1bd4c4
Enhance TypeScript support in frontend configuration (#15576)
* test: verify pre-commit hook

* fix: clean up code formatting and improve readability across multiple components

* chore: update subproject commit reference in frontend/ee

* chore: update eslint to version 9.26.0 and remove unused dependencies from package.json

fix: update submodule reference in server/ee

* chore: refactor ESLint configuration and add quiet linting script; update components to disable specific ESLint rules

* chore: add GitHub Copilot review instructions for App Builder team

Covers backward compatibility rules, styling conventions, state management,
resolution system, widget definitions, and common review flags.

* chore: add review instructions for App Builder, Data Migrations, Server Widget Config, Widget Components, and Widget Config

* Enhance TypeScript support in frontend configuration

- Added TypeScript parser and linting rules to ESLint configuration.
- Updated Babel configuration to include TypeScript preset.
- Modified package.json and package-lock.json to include TypeScript and related dependencies.
- Introduced tsconfig.json for TypeScript compiler options.
- Updated Webpack configuration to support .ts and .tsx file extensions.
- Adjusted linting and formatting scripts to include TypeScript files.

* chore: update TypeScript ESLint packages and subproject commits

---------

Co-authored-by: kavinvenkatachalam <kavin.saratha@gmail.com>
Co-authored-by: Johnson Cherian <johnsonc.dev@gmail.com>
2026-03-19 12:41:32 +05:30

82 lines
2.7 KiB
JavaScript

import React from 'react';
import _ from 'lodash';
import Select, { components } from 'react-select';
import defaultStyles from './styles';
const CustomInput = (props) => {
return <components.Input {...props} data-cy={`${props.selectProps.dataCy || ''}-select-dropdown-input`} />;
};
export const SelectComponent = ({ options = [], value, onChange, closeMenuOnSelect, darkMode, ...restProps }) => {
const selectRef = React.useRef(null);
const isDarkMode = darkMode ?? localStorage.getItem('darkMode') === 'true';
const {
isMulti = false,
styles = {},
isLoading = false,
hasSearch = true,
height,
width,
placeholder = 'Select..',
customOption = undefined,
defaultValue = null,
useMenuPortal = true, // todo: deprecate this prop, use menuPortalTarget instead
maxMenuHeight = 250,
menuPortalTarget = null,
menuPlacement = 'auto',
useCustomStyles = false,
isDisabled = false,
borderRadius,
openMenuOnFocus = false,
customClassPrefix = '',
dataCy = '',
} = restProps;
const customStyles = useCustomStyles ? styles : defaultStyles(isDarkMode, width, height, styles, borderRadius);
const selectOptions =
Array.isArray(options) && options.length === 0
? options
: options?.map((option) => {
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;
const handleOnChange = (data) => {
if (isMulti) {
onChange(data);
} else {
onChange(data.value);
}
};
const renderCustomOption = (option) => {
if (customOption) {
return customOption(option);
}
return option.label;
};
return (
<Select
{...restProps}
ref={selectRef}
selectRef={selectRef} // Exposed ref for custom components if needed
isLoading={isLoading}
isDisabled={isDisabled || isLoading}
options={selectOptions}
value={currentValue}
isSearchable={restProps.isSearchable ?? hasSearch}
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'}`}
components={{
Input: CustomInput,
...restProps.components,
}}
/>
);
};