import { useMemo, useState } from 'react'; import styled from '@emotion/styled'; import { useRecoilValue } from 'recoil'; import { IconApps } from '@/ui/display/icon'; import { useIcons } from '@/ui/display/icon/hooks/useIcons'; import { IconComponent } from '@/ui/display/icon/types/IconComponent'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { arrayToChunks } from '~/utils/array/arrayToChunks'; import { IconButton, IconButtonVariant } from '../button/components/IconButton'; import { LightIconButton } from '../button/components/LightIconButton'; import { IconPickerHotkeyScope } from '../types/IconPickerHotkeyScope'; type IconPickerProps = { disabled?: boolean; dropdownId?: string; onChange: (params: { iconKey: string; Icon: IconComponent }) => void; selectedIconKey?: string; onClickOutside?: () => void; onClose?: () => void; onOpen?: () => void; variant?: IconButtonVariant; className?: string; }; const StyledMenuIconItemsContainer = styled.div` display: flex; flex-direction: row; flex-wrap: wrap; gap: ${({ theme }) => theme.spacing(0.5)}; `; const StyledLightIconButton = styled(LightIconButton)<{ isSelected?: boolean }>` background: ${({ theme, isSelected }) => isSelected ? theme.background.transparent.medium : 'transparent'}; `; const convertIconKeyToLabel = (iconKey: string) => iconKey.replace(/[A-Z]/g, (letter) => ` ${letter}`).trim(); type IconPickerIconProps = { iconKey: string; onClick: () => void; selectedIconKey?: string; Icon: IconComponent; }; const IconPickerIcon = ({ iconKey, onClick, selectedIconKey, Icon, }: IconPickerIconProps) => { const { isSelectedItemIdSelector } = useSelectableList(); const isSelectedItemId = useRecoilValue(isSelectedItemIdSelector(iconKey)); return ( ); }; export const IconPicker = ({ disabled, dropdownId = 'icon-picker', onChange, selectedIconKey, onClickOutside, onClose, onOpen, variant = 'secondary', className, }: IconPickerProps) => { const [searchString, setSearchString] = useState(''); const { goBackToPreviousHotkeyScope, setHotkeyScopeAndMemorizePreviousScope, } = usePreviousHotkeyScope(); const { closeDropdown } = useDropdown(dropdownId); const { getIcons, getIcon } = useIcons(); const icons = getIcons(); const matchingSearchIconKeys = useMemo(() => { const filteredIconKeys = icons ? Object.keys(icons).filter((iconKey) => { if (searchString === '') { return true; } const isMatchingSearchString = [ iconKey, convertIconKeyToLabel(iconKey), ].some((label) => label.toLowerCase().includes(searchString.toLowerCase()), ); return isMatchingSearchString; }) : []; const isSelectedIconMatchingFilter = selectedIconKey && filteredIconKeys.includes(selectedIconKey); const uniqueFilteredIconKeys = [ ...new Set( selectedIconKey && isSelectedIconMatchingFilter ? [selectedIconKey, ...filteredIconKeys] : filteredIconKeys, ), ]; return uniqueFilteredIconKeys.slice(0, 25); }, [icons, searchString, selectedIconKey]); const iconKeys2d = useMemo( () => arrayToChunks(matchingSearchIconKeys.slice(), 5), [matchingSearchIconKeys], ); return (
} dropdownMenuWidth={176} dropdownComponents={ { onChange({ iconKey, Icon: getIcon(iconKey) }); closeDropdown(); }} > { setSearchString(event.target.value); }} />
{ setHotkeyScopeAndMemorizePreviousScope( IconPickerHotkeyScope.IconPicker, ); }} onMouseLeave={goBackToPreviousHotkeyScope} > {matchingSearchIconKeys.map((iconKey) => ( { onChange({ iconKey, Icon: getIcon(iconKey) }); closeDropdown(); }} selectedIconKey={selectedIconKey} Icon={getIcon(iconKey)} /> ))}
} onClickOutside={onClickOutside} onClose={() => { onClose?.(); setSearchString(''); }} onOpen={onOpen} />
); };