openreplay/frontend/app/components/shared/Select/Select.tsx
Delirium d604f9920b
feat ui: dashboards redesign (#2230)
* feat ui: dashboards redesign start

* more cards

* fix ui: more different cards...

* feat ui: finish cards, all trigger, all icons

* change(ui): added missin const

* feature(ui): new dashboard modal

* feature(ui): new dashboard modal

* change(ui): new cards

* change(ui): dashboard redesign

* change(ui): dashboard redesign

* change(ui): dashboard redesign

* change(ui): modal context and alert form

* change(ui): table card show more with modal

* change(ui): examples

* change(ui): example categorize and other improvements

* change(ui): example categorize and other improvements

* change(ui): performance cards

* change(ui): insights card

* Various style updates in dashboards and other pages. (#2308)

* Various minor style updates

* Various style improvements

* Update ExampleCards.tsx

* change(ui): fixed an issue with card create

* change(ui): fixed an issue with card create

* change(ui): default filters and events order

* change(ui): random data

* Dashboards redesign - improvments (#2313)

* Various minor style updates

* Various style improvements

* Update ExampleCards.tsx

* various minor improvements in dashbaords.

* revised dashboard widget header

* change(ui): sessions by user

* change(ui): funnel example

* change(ui): modal height and scroll

* change(ui): example cards with data

* change(ui): example cards with data

* change(ui): funnel bar text color

* change(ui): example cards overlay click

* change(ui): path analysis filter card

---------

Co-authored-by: Shekar Siri <sshekarsiri@gmail.com>
Co-authored-by: Sudheer Salavadi <connect.uxmaster@gmail.com>
2024-06-27 19:47:34 +02:00

197 lines
5.7 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;
[x: string]: any;
}
export default function <Value extends ValueObject>({
placeholder = 'Select',
name = '',
onChange,
right = false,
plain = false,
options,
isSearchable = false,
components = {},
styles = {},
defaultValue = '',
controlStyle = {},
...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
options={options}
isSearchable={isSearchable}
defaultValue={defaultSelected}
components={{
IndicatorSeparator: () => null,
DropdownIndicator,
ValueContainer: CustomValueContainer,
...components
}}
onChange={(value) => onChange({ name, value: value })}
styles={{ ...customStyles, ...styles }}
theme={(theme) => ({
...theme,
colors: {
...theme.colors,
primary: '#394EFF'
}
})}
blurInputOnSelect={true}
placeholder={placeholder}
{...rest}
/>
);
}
const DropdownIndicator = (
props: DropdownIndicatorProps<true>
) => {
return (
<components.DropdownIndicator {...props}>
<Icon name='chevron-down' size='16' />
</components.DropdownIndicator>
);
};
const 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>
);
};