export default function useKeywordSearch()

in packages/graph-explorer/src/modules/SearchSidebar/useKeywordSearch.ts [81:204]


export default function useKeywordSearch() {
  const queryEngine = useQueryEngine();

  const [searchTerm, setSearchTerm] = useAtom(searchTermAtom);
  const debouncedSearchTerm = useDebounceValue(searchTerm, 600);
  const [selectedVertexType, setSelectedVertexType] = useAtom(
    selectedVertexTypeAtom
  );
  const [selectedAttribute, setSelectedAttribute] = useAtom(
    selectedAttributeAtom
  );
  const [partialMatch, setPartialMatch] = useAtom(partialMatchAtom);

  const exactMatchOptions = [
    { label: "Exact", value: "Exact" },
    { label: "Partial", value: "Partial" },
  ];

  const vtConfigs = useDisplayVertexTypeConfigs();
  const vertexOptions = useMemo(
    () => [
      { label: "All", value: allVerticesValue },
      ...vtConfigs
        .values()
        // Filtering out empty types because the queries need to be updated to support them
        .filter(vtConfig => vtConfig.type !== "")
        .map(vtConfig => ({
          label: vtConfig.displayLabel,
          value: vtConfig.type,
        })),
    ],
    [vtConfigs]
  );

  const attributesOptions = useAtomValue(attributeOptionsSelector);
  const defaultSearchAttribute = useMemo(() => {
    if (queryEngine === "sparql") {
      const rdfsLabel = attributesOptions.find(o => o.label === "rdfs:label");
      return rdfsLabel?.value ?? allAttributesValue;
    } else {
      return idAttributeValue;
    }
  }, [queryEngine, attributesOptions]);

  /** This is the selected attribute unless the attribute is not in the
   * attribute options list (for example, the selected vertex type changed). */
  const safeSelectedAttribute =
    attributesOptions.find(opt => opt.value === selectedAttribute)?.value ??
    defaultSearchAttribute;

  const onSearchTermChange = useCallback(
    (value: string) => {
      setSearchTerm(value);
    },
    [setSearchTerm]
  );

  const onVertexOptionChange = useCallback(
    (value: string) => {
      setSelectedVertexType(value);
    },
    [setSelectedVertexType]
  );

  const onAttributeOptionChange = useCallback(
    (value: string) => {
      setSelectedAttribute(value);
    },
    [setSelectedAttribute]
  );

  const onPartialMatchChange = useCallback(
    (value: boolean) => {
      setPartialMatch(value);
    },
    [setPartialMatch]
  );

  const searchPlaceholder = useMemo(() => {
    const attributes =
      safeSelectedAttribute === allAttributesValue
        ? attributesOptions
            .filter(attr => attr.value !== allAttributesValue)
            .map(attr => attr.label)
            .join(", ")
        : (attributesOptions.find(opt => opt.value === safeSelectedAttribute)
            ?.label ?? safeSelectedAttribute);

    return `Search by ${attributes}`;
  }, [attributesOptions, safeSelectedAttribute]);

  const vertexTypes =
    selectedVertexType === allVerticesValue ? [] : [selectedVertexType];
  const searchByAttributes =
    safeSelectedAttribute === allAttributesValue
      ? attributesOptions
          .filter(attr => attr.value !== allAttributesValue)
          .map(attr => attr.value)
      : [safeSelectedAttribute];

  const query = useKeywordSearchQuery({
    debouncedSearchTerm,
    vertexTypes,
    searchByAttributes,
    exactMatch: !partialMatch,
  });

  return {
    query,
    debouncedSearchTerm,
    onSearchTermChange,
    onVertexOptionChange,
    searchPlaceholder,
    searchTerm,
    selectedVertexType,
    vertexOptions,
    selectedAttribute: safeSelectedAttribute,
    attributesOptions,
    onAttributeOptionChange,
    partialMatch,
    exactMatchOptions,
    onPartialMatchChange,
  };
}