import { useRef } from 'react'; import { isNonEmptyString } from '@sniptt/guards'; import { Key } from 'ts-key-enum'; import { IconPlus } from '@/ui/display/icon'; import { IconComponent } from '@/ui/display/icon/types/IconComponent'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItemSelect } from '@/ui/navigation/menu-item/components/MenuItemSelect'; import { MenuItemSelectAvatar } from '@/ui/navigation/menu-item/components/MenuItemSelectAvatar'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { Avatar } from '@/users/components/Avatar'; import { assertNotNull } from '~/utils/assert'; import { CreateButtonId, EmptyButtonId } from '../constants'; import { useEntitySelectScroll } from '../hooks/useEntitySelectScroll'; import { EntityForSelect } from '../types/EntityForSelect'; import { RelationPickerHotkeyScope } from '../types/RelationPickerHotkeyScope'; import { DropdownMenuSkeletonItem } from './skeletons/DropdownMenuSkeletonItem'; import { CreateNewButton } from './CreateNewButton'; export type SingleEntitySelectBaseProps< CustomEntityForSelect extends EntityForSelect, > = { EmptyIcon?: IconComponent; emptyLabel?: string; entitiesToSelect: CustomEntityForSelect[]; loading?: boolean; onCancel?: () => void; onEntitySelected: (entity?: CustomEntityForSelect) => void; selectedEntity?: CustomEntityForSelect; onCreate?: () => void; showCreateButton?: boolean; SelectAllIcon?: IconComponent; selectAllLabel?: string; isAllEntitySelected?: boolean; isAllEntitySelectShown?: boolean; onAllEntitySelected?: () => void; }; export const SingleEntitySelectBase = < CustomEntityForSelect extends EntityForSelect, >({ EmptyIcon, emptyLabel, entitiesToSelect, loading, onCancel, onEntitySelected, selectedEntity, onCreate, showCreateButton, SelectAllIcon, selectAllLabel, isAllEntitySelected, isAllEntitySelectShown, onAllEntitySelected, }: SingleEntitySelectBaseProps) => { const containerRef = useRef(null); const entitiesInDropdown = [selectedEntity, ...entitiesToSelect].filter( (entity): entity is CustomEntityForSelect => assertNotNull(entity) && isNonEmptyString(entity.name), ); const { preselectedOptionId, resetScroll } = useEntitySelectScroll({ selectableOptionIds: [ EmptyButtonId, ...entitiesInDropdown.map((item) => item.id), ...(showCreateButton ? [CreateButtonId] : []), ], containerRef, }); useScopedHotkeys( Key.Enter, () => { if (showCreateButton && preselectedOptionId === CreateButtonId) { onCreate?.(); } else { const entity = entitiesInDropdown.findIndex( (entity) => entity.id === preselectedOptionId, ); onEntitySelected(entitiesInDropdown[entity]); } resetScroll(); }, RelationPickerHotkeyScope.RelationPicker, [entitiesInDropdown, preselectedOptionId, onEntitySelected], ); useScopedHotkeys( Key.Escape, () => { onCancel?.(); }, RelationPickerHotkeyScope.RelationPicker, [onCancel], ); return (
{loading ? ( ) : entitiesInDropdown.length === 0 && !isAllEntitySelectShown ? ( ) : ( <> {isAllEntitySelectShown && selectAllLabel && onAllEntitySelected && ( onAllEntitySelected()} LeftIcon={SelectAllIcon} text={selectAllLabel} hovered={preselectedOptionId === EmptyButtonId} selected={!!isAllEntitySelected} /> )} {emptyLabel && ( onEntitySelected()} LeftIcon={EmptyIcon} text={emptyLabel} hovered={preselectedOptionId === EmptyButtonId} selected={!selectedEntity} /> )} {entitiesInDropdown?.map((entity) => ( onEntitySelected(entity)} text={entity.name} hovered={preselectedOptionId === entity.id} avatar={ } /> ))} )} {showCreateButton && ( <> )}
); };