openreplay/frontend/app/components/shared/Select/Select.tsx
Andrey Babushkin fd5c0c9747
Add lokalisation (#3092)
* applied eslint

* add locales and lint the project

* removed error boundary

* updated locales

* fix min files

* fix locales
2025-03-06 17:43:15 +01:00

201 lines
5.1 KiB
TypeScript

import React from 'react';
import Select, { components, DropdownIndicatorProps } from 'react-select';
import { Icon } from 'UI';
import colors from 'App/theme/colors';
const { ValueContainer } = components;
type ValueObject = {
value: string | number;
label: React.ReactNode;
};
interface Props<Value extends ValueObject> {
options: Value[];
isSearchable?: boolean;
defaultValue?: string | number;
plain?: boolean;
components?: any;
styles?: Record<string, any>;
controlStyle?: Record<string, any>;
onChange: (newValue: { name: string; value: Value }) => void;
name?: string;
placeholder?: string;
className?: string;
[x: string]: any;
}
export default function <Value extends ValueObject>({
placeholder = 'Select',
name = '',
onChange,
right = false,
plain = false,
options,
isSearchable = false,
components = {},
styles = {},
defaultValue = '',
controlStyle = {},
className = '',
...rest
}: Props<Value>) {
const defaultSelected = Array.isArray(defaultValue)
? defaultValue.map((value) =>
options.find((option) => option.value === value),
)
: options.find((option) => option.value === defaultValue) || null;
const customStyles = {
option: (provided: any, state: any) => ({
...provided,
whiteSpace: 'nowrap',
transition: 'all 0.3s',
backgroundColor: state.isFocused ? colors['active-blue'] : 'transparent',
color: state.isFocused ? colors.teal : 'black',
fontSize: '14px',
'&:hover': {
transition: 'all 0.2s',
backgroundColor: colors['active-blue'],
},
'&:focus': {
transition: 'all 0.2s',
backgroundColor: colors['active-blue'],
},
}),
menu: (provided: any, state: any) => ({
...provided,
top: 31,
borderRadius: '.5rem',
right: right ? 0 : undefined,
border: `1px solid ${colors['gray-light']}`,
// borderRadius: '3px',
backgroundColor: '#fff',
boxShadow: '1px 1px 1px rgba(0, 0, 0, 0.1)',
position: 'absolute',
minWidth: 'fit-content',
// zIndex: 99,
overflow: 'hidden',
zIndex: 100,
...(right && { right: 0 }),
}),
menuList: (provided: any, state: any) => ({
...provided,
padding: 0,
}),
control: (provided: any) => {
const obj = {
...provided,
border: 'solid thin #ddd',
cursor: 'pointer',
minHeight: '36px',
transition: 'all 0.5s',
'&:hover': {
backgroundColor: colors['gray-lightest'],
transition: 'all 0.2s ease-in-out',
},
...controlStyle,
};
if (plain) {
obj.backgroundColor = 'transparent';
obj.border = '1px solid transparent';
obj.backgroundColor = 'transparent';
obj['&:hover'] = {
borderColor: 'transparent',
backgroundColor: colors['gray-light'],
transition: 'all 0.2s ease-in-out',
};
obj['&:focus'] = {
borderColor: 'transparent',
};
obj['&:active'] = {
borderColor: 'transparent',
};
}
return obj;
},
indicatorsContainer: (provided: any) => ({
...provided,
maxHeight: '34px',
padding: 0,
}),
valueContainer: (provided: any) => ({
...provided,
paddingRight: '0px',
}),
singleValue: (provided: any, state: { isDisabled: any }) => {
const opacity = state.isDisabled ? 0.5 : 1;
const transition = 'opacity 300ms';
return {
...provided,
opacity,
transition,
fontWeight: '500',
};
},
input: (provided: any) => ({
...provided,
'& input:focus': {
border: 'none !important',
},
}),
noOptionsMessage: (provided: any) => ({
...provided,
whiteSpace: 'nowrap !important',
// minWidth: 'fit-content',
}),
};
return (
<Select
className={`${className} btn-event-condition`}
options={options}
isSearchable={isSearchable}
defaultValue={defaultSelected}
components={{
IndicatorSeparator: () => null,
DropdownIndicator,
ValueContainer: CustomValueContainer,
...components,
}}
onChange={(value) => onChange({ name, value })}
styles={{ ...customStyles, ...styles }}
theme={(theme) => ({
...theme,
colors: {
...theme.colors,
primary: '#394EFF',
},
})}
blurInputOnSelect
placeholder={placeholder}
{...rest}
/>
);
}
function DropdownIndicator(props: DropdownIndicatorProps<true>) {
return (
<components.DropdownIndicator {...props}>
<Icon name="chevron-down" size="16" />
</components.DropdownIndicator>
);
}
function CustomValueContainer({ children, ...rest }: any) {
const selectedCount = rest.getValue().length;
const conditional = selectedCount < 3;
let firstChild: any = [];
if (!conditional) {
firstChild = [children[0].shift(), children[1]];
}
return (
<ValueContainer {...rest}>
{conditional ? children : firstChild}
{!conditional && ` and ${selectedCount - 1} others`}
</ValueContainer>
);
}