import { Autocomplete, Box, CloseButton, createStyles, Group, Image, Loader, ScrollArea, SelectItemProps, Stack, Text, Title, } from '@mantine/core'; import { UseFormReturnType } from '@mantine/form'; import { IconSearch } from '@tabler/icons'; import { useTranslation } from 'next-i18next'; import { forwardRef } from 'react'; import { humanFileSize } from '../../../../../../tools/humanFileSize'; import { NormalizedIconRepositoryResult } from '../../../../../../tools/server/images/abstract-icons-repository'; import { AppType } from '../../../../../../types/app'; import { DebouncedAppIcon } from '../Shared/DebouncedAppIcon'; interface IconSelectorProps { form: UseFormReturnType AppType>; data: NormalizedIconRepositoryResult[] | undefined; isLoading: boolean; disallowAppNameProgagation: () => void; allowAppNamePropagation: boolean; } export const IconSelector = ({ form, data, isLoading, allowAppNamePropagation, disallowAppNameProgagation, }: IconSelectorProps) => { const { t } = useTranslation('layout/modals/add-app'); const { classes } = useStyles(); const a = data === undefined ? [] : data.flatMap((repository) => repository.entries.map((entry) => ({ url: entry.url, label: entry.name, size: entry.size, value: entry.url, group: repository.name, copyright: repository.copyright, })) ); return ( {t('appearance.icon.autocomplete.title')} {t('appearance.icon.autocomplete.text')} } icon={} rightSection={ form.values.appearance.iconUrl.length > 0 ? ( form.setFieldValue('appearance.iconUrl', '')} /> ) : null } itemComponent={AutoCompleteItem} className={classes.textInput} data={a} limit={25} label={t('appearance.icon.label')} description={t('appearance.icon.description', { suggestionsCount: data?.reduce((a, b) => a + b.count, 0) ?? 0, })} filter={(search, item) => item.value .toLowerCase() .replaceAll('_', '') .replaceAll(' ', '-') .includes(search.toLowerCase().replaceAll('_', '').replaceAll(' ', '-')) } variant="default" withAsterisk dropdownComponent={(props: any) => } dropdownPosition="bottom" required onChange={(event) => { if (allowAppNamePropagation) { disallowAppNameProgagation(); } form.setFieldValue('appearance.iconUrl', event); }} value={form.values.appearance.iconUrl} /> {(!data || isLoading) && ( {t('appearance.icon.noItems.title')} {t('appearance.icon.noItems.text')} )} ); }; const useStyles = createStyles(() => ({ textInput: { flexGrow: 1, }, })); const AutoCompleteItem = forwardRef( ({ label, size, copyright, url, ...others }: ItemProps, ref) => (
({ backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[2], borderRadius: theme.radius.md, })} p={2} > {label} {humanFileSize(size, false)} {copyright && ( © {copyright} )}
) ); interface ItemProps extends SelectItemProps { url: string; group: string; size: number; copyright: string | undefined; }