snowballtools-base/packages/frontend/src/components/shared/UserSelect/UserSelectItem/UserSelectItem.tsx
2024-02-28 23:07:54 +07:00

76 lines
2.1 KiB
TypeScript

import React, { forwardRef, ComponentPropsWithoutRef, useMemo } from 'react';
import { Overwrite, UseComboboxGetItemPropsReturnValue } from 'downshift';
import {
userSelectItemTheme,
UserSelectItemTheme,
} from './UserSelectItem.theme';
import { CheckRadioIcon } from 'components/shared/CustomIcon';
import { UserSelectOption } from 'components/shared/UserSelect';
import { OmitCommon } from 'types/common';
/**
* Represents a type that merges ComponentPropsWithoutRef<'li'> with certain exclusions.
* @type {MergedComponentPropsWithoutRef}
*/
type MergedComponentPropsWithoutRef = OmitCommon<
ComponentPropsWithoutRef<'li'>,
Omit<
Overwrite<UseComboboxGetItemPropsReturnValue, UserSelectOption[]>,
'index' | 'item'
>
>;
export interface UserSelectItemProps
extends MergedComponentPropsWithoutRef,
UserSelectItemTheme {
selected: boolean;
option: UserSelectOption;
hovered?: boolean;
}
const UserSelectItem = forwardRef<HTMLLIElement, UserSelectItemProps>(
({ className, selected, hovered, option, ...props }, ref) => {
const theme = userSelectItemTheme();
const { value, label, imgSrc } = option;
const renderLeftImage = useMemo(
() => (
<div className="grid place-items-center w-10 h-10 rounded-lg bg-blue-400">
<img src={imgSrc} alt={`${value}-logo`} className={theme.img()} />
</div>
),
[imgSrc, value],
);
return (
<li
{...props}
ref={ref}
className={theme.wrapper({ className, active: selected || hovered })}
>
<div className={theme.content()}>
{renderLeftImage}
<p className={theme.label()}>{label}</p>
</div>
{selected && <CheckRadioIcon className={theme.selectedIcon()} />}
</li>
);
},
);
export const EmptyUserSelectItem = () => {
const theme = userSelectItemTheme();
return (
<li className={theme.wrapper()}>
<div className={theme.content()}>
<p className={theme.label()}>No results found</p>
</div>
</li>
);
};
UserSelectItem.displayName = 'UserSelectItem';
export { UserSelectItem };