"use client"; import { useCallback, useMemo, useState } from "react"; import { Badge, Card, Center, Group, Stack, Text, Tooltip, UnstyledButton } from "@mantine/core"; import { IconBrandDocker, IconCheck, IconPuzzle } from "@tabler/icons-react"; import type { IntegrationKind } from "@homarr/definitions"; import { useI18n } from "@homarr/translation/client"; import { IntegrationAvatar } from "../components/integration-avatar"; import { SelectGridLayout, selectGridCardHeight } from "../select-grid-layout"; import { buildSortedIntegrations, categoryTranslationKeys, filterIntegrations } from "./integration-grid-shared"; import classes from "./integration-select-grid.module.css"; export interface IntegrationMultiSelectGridProps { selectedKinds: IntegrationKind[]; onSelectionChange: (kinds: IntegrationKind[]) => void; enableMockIntegration?: boolean; onboarding?: boolean; detectedKinds?: Set; } export const IntegrationMultiSelectGrid = ({ selectedKinds: selectedKindsArray, onSelectionChange, enableMockIntegration = false, onboarding = false, detectedKinds, }: IntegrationMultiSelectGridProps) => { const [search, setSearch] = useState(""); const selectedKinds = useMemo(() => new Set(selectedKindsArray), [selectedKindsArray]); const t = useI18n(); const toggleKind = useCallback( (kind: IntegrationKind) => { const current = new Set(selectedKindsArray); if (current.has(kind)) current.delete(kind); else current.add(kind); onSelectionChange(Array.from(current)); }, [onSelectionChange, selectedKindsArray], ); const integrations = useMemo( () => buildSortedIntegrations({ enableMockIntegration, onboarding }), [enableMockIntegration, onboarding], ); const sorted = useMemo(() => { if (!detectedKinds || detectedKinds.size === 0) return integrations; return [ ...integrations.filter((integration) => detectedKinds.has(integration.kind)), ...integrations.filter((integration) => !detectedKinds.has(integration.kind)), ]; }, [detectedKinds, integrations]); const filtered = useMemo(() => filterIntegrations(sorted, search), [search, sorted]); return ( {filtered.map((integration) => { const isSelected = selectedKinds.has(integration.kind); const isDetected = detectedKinds?.has(integration.kind) ?? false; return ( toggleKind(integration.kind)} aria-label={integration.name} aria-pressed={isSelected} > {integration.name} {isSelected && } {isDetected && ( }> {t("integration.grid.detected")} )} {integration.categories.slice(0, 2).map((category) => ( {categoryTranslationKeys[category] ? t(categoryTranslationKeys[category] as never) : category} ))} {integration.widgets.length > 0 ? ( {integration.widgets.map((widgetKind) => ( {t(`widget.${widgetKind}.name`)} ))} } > }> {t("integration.grid.widgetCount", { count: String(integration.widgets.length) })} ) : ( {t("integration.grid.noWidgets")} )} ); })} {filtered.length === 0 && (
{t("common.noResults")}
)}
); };