2023-12-13 14:32:57 +03:00
|
|
|
'use client';
|
|
|
|
|
2024-04-22 12:33:22 +03:00
|
|
|
import Select, {
|
2025-02-21 21:15:05 +03:00
|
|
|
type ClearIndicatorProps,
|
2024-04-22 12:33:22 +03:00
|
|
|
components,
|
2025-02-21 21:15:05 +03:00
|
|
|
type DropdownIndicatorProps,
|
|
|
|
type GroupBase,
|
|
|
|
type Props,
|
|
|
|
type StylesConfig
|
2024-04-22 12:33:22 +03:00
|
|
|
} from 'react-select';
|
2023-09-08 02:15:20 +03:00
|
|
|
|
2025-03-12 11:55:43 +03:00
|
|
|
import { useWindowSize } from '@/hooks/use-window-size';
|
2025-02-11 21:07:23 +03:00
|
|
|
import { APP_COLORS, SELECT_THEME } from '@/styling/colors';
|
2023-09-08 02:15:20 +03:00
|
|
|
|
2025-03-12 12:04:50 +03:00
|
|
|
import { IconClose, IconDropArrow, IconDropArrowUp } from '../icons';
|
2025-02-10 01:32:55 +03:00
|
|
|
|
2024-04-22 12:33:22 +03:00
|
|
|
function DropdownIndicator<Option, Group extends GroupBase<Option> = GroupBase<Option>>(
|
|
|
|
props: DropdownIndicatorProps<Option, false, Group>
|
|
|
|
) {
|
|
|
|
return (
|
|
|
|
components.DropdownIndicator && (
|
|
|
|
<components.DropdownIndicator {...props}>
|
2024-05-11 20:53:36 +03:00
|
|
|
{props.selectProps.menuIsOpen ? <IconDropArrowUp size='1.25rem' /> : <IconDropArrow size='1.25rem' />}
|
2024-04-22 12:33:22 +03:00
|
|
|
</components.DropdownIndicator>
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function ClearIndicator<Option, Group extends GroupBase<Option> = GroupBase<Option>>(
|
|
|
|
props: ClearIndicatorProps<Option, false, Group>
|
|
|
|
) {
|
|
|
|
return (
|
|
|
|
components.ClearIndicator && (
|
|
|
|
<components.ClearIndicator {...props}>
|
|
|
|
<IconClose size='1.25rem' />
|
|
|
|
</components.ClearIndicator>
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2025-03-13 23:21:14 +03:00
|
|
|
interface SelectSingleProps<Option, Group extends GroupBase<Option> = GroupBase<Option>>
|
2023-12-28 14:04:44 +03:00
|
|
|
extends Omit<Props<Option, false, Group>, 'theme' | 'menuPortalTarget'> {
|
|
|
|
noPortal?: boolean;
|
2024-04-07 19:22:19 +03:00
|
|
|
noBorder?: boolean;
|
2023-09-08 02:15:20 +03:00
|
|
|
}
|
|
|
|
|
2024-11-21 15:09:51 +03:00
|
|
|
/**
|
|
|
|
* Displays a single-select component.
|
|
|
|
*/
|
2025-02-07 10:54:47 +03:00
|
|
|
export function SelectSingle<Option, Group extends GroupBase<Option> = GroupBase<Option>>({
|
2023-12-28 14:04:44 +03:00
|
|
|
noPortal,
|
2024-04-07 19:22:19 +03:00
|
|
|
noBorder,
|
2023-12-28 14:04:44 +03:00
|
|
|
...restProps
|
2023-11-29 13:07:55 +03:00
|
|
|
}: SelectSingleProps<Option, Group>) {
|
2024-04-22 12:33:22 +03:00
|
|
|
const size = useWindowSize();
|
2023-09-08 02:15:20 +03:00
|
|
|
|
2024-12-13 21:31:09 +03:00
|
|
|
const adjustedStyles: StylesConfig<Option, false, Group> = {
|
|
|
|
container: defaultStyles => ({
|
|
|
|
...defaultStyles,
|
|
|
|
borderRadius: '0.25rem'
|
2023-09-09 20:36:55 +03:00
|
|
|
}),
|
2024-12-13 21:31:09 +03:00
|
|
|
control: (defaultStyles, { isDisabled }) => ({
|
|
|
|
...defaultStyles,
|
|
|
|
borderRadius: '0.25rem',
|
|
|
|
...(noBorder ? { borderWidth: 0 } : {}),
|
|
|
|
cursor: isDisabled ? 'not-allowed' : 'pointer',
|
|
|
|
boxShadow: 'none'
|
|
|
|
}),
|
|
|
|
menuPortal: defaultStyles => ({
|
|
|
|
...defaultStyles,
|
|
|
|
zIndex: 9999
|
|
|
|
}),
|
|
|
|
menuList: defaultStyles => ({
|
|
|
|
...defaultStyles,
|
|
|
|
padding: 0
|
|
|
|
}),
|
|
|
|
option: (defaultStyles, { isSelected }) => ({
|
|
|
|
...defaultStyles,
|
|
|
|
padding: '0.25rem 0.75rem',
|
|
|
|
fontSize: '0.875rem',
|
|
|
|
lineHeight: '1.25rem',
|
2024-12-16 23:52:11 +03:00
|
|
|
backgroundColor: isSelected ? APP_COLORS.bgSelected : defaultStyles.backgroundColor,
|
|
|
|
color: isSelected ? APP_COLORS.fgSelected : defaultStyles.color,
|
2024-12-13 21:31:09 +03:00
|
|
|
borderWidth: '1px',
|
2024-12-16 23:52:11 +03:00
|
|
|
borderColor: APP_COLORS.border
|
2024-12-13 21:31:09 +03:00
|
|
|
}),
|
|
|
|
input: defaultStyles => ({ ...defaultStyles }),
|
|
|
|
placeholder: defaultStyles => ({ ...defaultStyles }),
|
|
|
|
singleValue: defaultStyles => ({ ...defaultStyles }),
|
|
|
|
dropdownIndicator: base => ({
|
|
|
|
...base,
|
|
|
|
paddingTop: 0,
|
|
|
|
paddingBottom: 0
|
|
|
|
}),
|
|
|
|
clearIndicator: base => ({
|
|
|
|
...base,
|
|
|
|
paddingTop: 0,
|
|
|
|
paddingBottom: 0
|
|
|
|
})
|
|
|
|
};
|
2023-09-08 02:15:20 +03:00
|
|
|
|
|
|
|
return (
|
2023-12-28 14:04:44 +03:00
|
|
|
<Select
|
|
|
|
noOptionsMessage={() => 'Список пуст'}
|
2024-04-22 12:33:22 +03:00
|
|
|
components={{ DropdownIndicator, ClearIndicator }}
|
2023-12-28 14:04:44 +03:00
|
|
|
theme={theme => ({
|
|
|
|
...theme,
|
|
|
|
borderRadius: 0,
|
2024-04-22 12:33:22 +03:00
|
|
|
spacing: {
|
2025-03-10 16:02:53 +03:00
|
|
|
...theme.spacing,
|
2024-04-22 12:33:22 +03:00
|
|
|
baseUnit: size.isSmall ? 2 : 4,
|
2024-09-21 20:04:07 +03:00
|
|
|
menuGutter: 2,
|
2024-04-22 12:33:22 +03:00
|
|
|
controlHeight: size.isSmall ? 28 : 38
|
|
|
|
},
|
2023-12-28 14:04:44 +03:00
|
|
|
colors: {
|
|
|
|
...theme.colors,
|
2024-12-16 23:52:11 +03:00
|
|
|
...SELECT_THEME
|
2023-12-28 14:04:44 +03:00
|
|
|
}
|
|
|
|
})}
|
|
|
|
menuPortalTarget={!noPortal ? document.body : null}
|
|
|
|
styles={adjustedStyles}
|
2024-05-12 13:58:28 +03:00
|
|
|
classNames={{ container: () => 'focus-frame' }}
|
2023-12-28 14:04:44 +03:00
|
|
|
{...restProps}
|
|
|
|
/>
|
|
|
|
);
|
2023-09-08 02:15:20 +03:00
|
|
|
}
|