import type { FocusEventHandler } from "react"; import { useState } from "react"; import { Combobox, Group, Image, InputBase, Skeleton, Text, useCombobox } from "@mantine/core"; import { clientApi } from "@homarr/api/client"; import { useScopedI18n } from "@homarr/translation/client"; interface IconPickerProps { initialValue?: string; onChange: (iconUrl: string) => void; error?: string | null; onFocus?: FocusEventHandler; onBlur?: FocusEventHandler; } export const IconPicker = ({ initialValue, onChange, error, onFocus, onBlur }: IconPickerProps) => { const [value, setValue] = useState(initialValue ?? ""); const [search, setSearch] = useState(initialValue ?? ""); const t = useScopedI18n("common"); const { data, isFetching } = clientApi.icon.findIcons.useQuery({ searchText: search, }); const combobox = useCombobox({ onDropdownClose: () => combobox.resetSelectedOption(), }); const notNullableData = data?.icons ?? []; const totalOptions = notNullableData.reduce((acc, group) => acc + group.icons.length, 0); const groups = notNullableData.map((group) => { const options = group.icons.map((item) => ( {item.name} )); return ( {options} ); }); return ( { setValue(value); setSearch(value); onChange(value); combobox.closeDropdown(); }} store={combobox} withinPortal > } value={search} onChange={(event) => { combobox.openDropdown(); combobox.updateSelectedOptionIndex(); setSearch(event.currentTarget.value); }} onClick={() => combobox.openDropdown()} onFocus={(event) => { onFocus?.(event); combobox.openDropdown(); }} onBlur={(event) => { onBlur?.(event); combobox.closeDropdown(); setSearch(value || ""); }} rightSectionPointerEvents="none" withAsterisk error={error} label="Icon URL" /> {t("iconPicker.header", { countIcons: data?.countIcons })} {totalOptions > 0 ? ( groups ) : !isFetching ? ( {t("search.nothingFound")} ) : ( Array(15) .fill(0) .map((_, index: number) => ( )) )} ); };