import React, { useMemo, useRef, useLayoutEffect, useState } from "react"; import { Box, Text, Stack } from "@mantine/core"; import { useTranslation } from "react-i18next"; import { getSubcategoryLabel, ToolRegistryEntry } from "../../data/toolsTaxonomy"; import ToolButton from "./toolPicker/ToolButton"; import "./toolPicker/ToolPicker.css"; import { SubcategoryGroup, useToolSections } from "../../hooks/useToolSections"; import SubcategoryHeader from "./shared/SubcategoryHeader"; import NoToolsFound from "./shared/NoToolsFound"; import { TFunction } from "i18next"; interface ToolPickerProps { selectedToolKey: string | null; onSelect: (id: string) => void; filteredTools: [string, ToolRegistryEntry][]; isSearching?: boolean; } // Helper function to render tool buttons for a subcategory const renderToolButtons = ( t: TFunction, subcategory: SubcategoryGroup, selectedToolKey: string | null, onSelect: (id: string) => void, showSubcategoryHeader: boolean = true ) => ( {showSubcategoryHeader && ( )} {subcategory.tools.map(({ id, tool }: { id: string; tool: any }) => ( ))} ); const ToolPicker = ({ selectedToolKey, onSelect, filteredTools, isSearching = false }: ToolPickerProps) => { const { t } = useTranslation(); const [quickHeaderHeight, setQuickHeaderHeight] = useState(0); const [allHeaderHeight, setAllHeaderHeight] = useState(0); const scrollableRef = useRef(null); const quickHeaderRef = useRef(null); const allHeaderRef = useRef(null); const quickAccessRef = useRef(null); const allToolsRef = useRef(null); // On resize adjust headers height to offset height useLayoutEffect(() => { const update = () => { if (quickHeaderRef.current) { setQuickHeaderHeight(quickHeaderRef.current.offsetHeight); } if (allHeaderRef.current) { setAllHeaderHeight(allHeaderRef.current.offsetHeight); } }; update(); window.addEventListener("resize", update); return () => window.removeEventListener("resize", update); }, []); const { sections: visibleSections } = useToolSections(filteredTools); const quickSection = useMemo( () => visibleSections.find(s => s.key === 'quick'), [visibleSections] ); const allSection = useMemo( () => visibleSections.find(s => s.key === 'all'), [visibleSections] ); const scrollTo = (ref: React.RefObject) => { const container = scrollableRef.current; const target = ref.current; if (container && target) { const stackedOffset = ref === allToolsRef ? (quickHeaderHeight + allHeaderHeight) : quickHeaderHeight; const top = target.offsetTop - container.offsetTop - (stackedOffset || 0); container.scrollTo({ top: Math.max(0, top), behavior: "smooth" }); } }; // Build flat list by subcategory for search mode const { searchGroups } = useToolSections(isSearching ? filteredTools : []); return ( {isSearching ? ( {searchGroups.length === 0 ? ( ) : ( searchGroups.map(group => renderToolButtons(t, group, selectedToolKey, onSelect)) )} ) : ( <> {quickSection && ( <>
scrollTo(quickAccessRef)} > {t("toolPicker.quickAccess", "QUICK ACCESS")} {quickSection?.subcategories.reduce((acc, sc) => acc + sc.tools.length, 0)}
{quickSection?.subcategories.map(sc => renderToolButtons(t, sc, selectedToolKey, onSelect, false) )} )} {allSection && ( <>
scrollTo(allToolsRef)} > {t("toolPicker.allTools", "ALL TOOLS")} {allSection?.subcategories.reduce((acc, sc) => acc + sc.tools.length, 0)}
{allSection?.subcategories.map(sc => renderToolButtons(t, sc, selectedToolKey, onSelect, true) )} )} {!quickSection && !allSection && } {/* bottom spacer to allow scrolling past the last row */}
)} ); }; export default ToolPicker;