UNPKG

@copilotkit/react-core

Version:

<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />

105 lines (90 loc) 2.78 kB
import { useCallback, useReducer } from "react"; import { randomId } from "@copilotkit/shared"; export type FlatCategoryStoreId = string; export interface UseFlatCategoryStoreReturn<T> { addElement: (value: T, categories: string[]) => FlatCategoryStoreId; removeElement: (id: FlatCategoryStoreId) => void; allElements: (categories: string[]) => T[]; } interface FlatCategoryStoreElement<T> { id: FlatCategoryStoreId; value: T; categories: Set<string>; } const useFlatCategoryStore = <T>(): UseFlatCategoryStoreReturn<T> => { const [elements, dispatch] = useReducer< React.Reducer<Map<FlatCategoryStoreId, FlatCategoryStoreElement<T>>, Action<T>> >(flatCategoryStoreReducer, new Map<FlatCategoryStoreId, FlatCategoryStoreElement<T>>()); const addElement = useCallback((value: T, categories: string[]): FlatCategoryStoreId => { const newId = randomId(); dispatch({ type: "ADD_ELEMENT", value, id: newId, categories, }); return newId; }, []); const removeElement = useCallback((id: FlatCategoryStoreId): void => { dispatch({ type: "REMOVE_ELEMENT", id }); }, []); const allElements = useCallback( (categories: string[]): T[] => { const categoriesSet = new Set(categories); const result: T[] = []; elements.forEach((element) => { if (setsHaveIntersection(categoriesSet, element.categories)) { result.push(element.value); } }); return result; }, [elements], ); return { addElement, removeElement, allElements }; }; export default useFlatCategoryStore; // Action types type Action<T> = | { type: "ADD_ELEMENT"; value: T; id: FlatCategoryStoreId; categories: string[]; } | { type: "REMOVE_ELEMENT"; id: FlatCategoryStoreId }; // Reducer function flatCategoryStoreReducer<T>( state: Map<FlatCategoryStoreId, FlatCategoryStoreElement<T>>, action: Action<T>, ): Map<FlatCategoryStoreId, FlatCategoryStoreElement<T>> { switch (action.type) { case "ADD_ELEMENT": { const { value, id, categories } = action; const newElement: FlatCategoryStoreElement<T> = { id, value, categories: new Set(categories), }; const newState = new Map(state); newState.set(id, newElement); return newState; } case "REMOVE_ELEMENT": { const newState = new Map(state); newState.delete(action.id); return newState; } default: return state; } } function setsHaveIntersection<T>(setA: Set<T>, setB: Set<T>): boolean { const [smallerSet, largerSet] = setA.size <= setB.size ? [setA, setB] : [setB, setA]; for (let item of smallerSet) { if (largerSet.has(item)) { return true; } } return false; }