@pipe0/react-sdk
Version:
React utils to work with pipe0
142 lines (141 loc) • 5.35 kB
JavaScript
import { getInitialSearchTableData, getSearchTableDataAggregates, } from "@pipe0/client-sdk";
import { createColumnHelper, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, useReactTable, } from "@tanstack/react-table";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
const globalFilterFn = (row, columnId, filterValue) => {
const value = row.getValue(columnId);
if (Array.isArray(value)) {
return value.some((item) => String(item).toLowerCase().includes(filterValue.toLowerCase()));
}
return String(value).toLowerCase().includes(filterValue.toLowerCase());
};
function useDebounce(cb, config = {}) {
const { initialValue = "", timeout = 400 } = config;
const [value, setValue] = useState(initialValue);
const cbRef = useRef(cb);
cbRef.current = cb;
const setImmediately = useCallback((v) => {
setValue(v);
cbRef.current(v);
}, []);
useEffect(() => {
const handle = setTimeout(() => {
cbRef.current(value);
}, timeout);
return () => clearTimeout(handle);
}, [value, timeout]);
return [value, setValue, setImmediately];
}
const columnHelper = createColumnHelper();
const columns = [
columnHelper.accessor("searchId", {
filterFn: "includesString",
enableGlobalFilter: true,
}),
columnHelper.accessor((row) => row.defaultOutputFields || [], {
id: "outputFields",
filterFn: "arrIncludes",
enableGlobalFilter: true,
}),
columnHelper.accessor((row) => row.tags || [], {
id: "tags",
filterFn: "arrIncludes",
enableGlobalFilter: true,
}),
columnHelper.accessor((row) => row.provider, {
id: "providers",
enableGlobalFilter: true,
}),
];
export function useSearchCatalogTable(config = {}) {
const [category, setCategory] = useState(null);
const { initialColumnFilters: initialColumnFilters = [] } = config;
const initialSearchTableData = useMemo(() => getInitialSearchTableData(category), [category]);
const table = useReactTable({
columns,
data: initialSearchTableData,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getFilteredRowModel: getFilteredRowModel(),
globalFilterFn: globalFilterFn,
getColumnCanGlobalFilter: (column) => column.columnDef.enableGlobalFilter !== false,
initialState: {
columnFilters: initialColumnFilters,
pagination: {
pageSize: 10,
},
},
});
const columnFilters = table.getState().columnFilters;
const { searchIdsByOutputField, searchIdsByTag, searchIdsByProvider, sortedTagEntries, sortedOutputFieldEntries, sortedProviderEntries, searchEntriesByBaseSearch, } = useMemo(() => {
return getSearchTableDataAggregates(initialSearchTableData, category);
}, [category, initialSearchTableData]);
const [expandedSidebarSections, setExpandedSidebarSections] = useState(["tags"]);
const [globalFilterInput, setGlobalFilterInput, setGlobalFilterImmediately] = useDebounce((v) => {
if (v === table.getState().globalFilter)
return;
table.setGlobalFilter(v);
if (v) {
setCategory(null);
table.setColumnFilters([]);
}
});
const addColumnFilter = (id, value) => {
setGlobalFilterImmediately("");
table.setColumnFilters([
{ id: "categories", value: category },
{ id, value },
]);
};
const resetColumnFilters = () => {
setGlobalFilterImmediately("");
table.setColumnFilters([{ id: "categories", value: null }]);
};
const removeColumnFilter = (id) => {
table.getColumn(id)?.setFilterValue(null);
};
const isFilterChecked = (id, value) => {
return columnFilters.some((f) => f.id === id && f.value === value);
};
const filterByField = (id, fieldName) => {
setExpandedSidebarSections([id]);
setGlobalFilterImmediately("");
table.setColumnFilters([
{ id: "categories", value: null },
{ id, value: fieldName },
]);
};
const tableState = table.getState();
const showFeaturedSearches = !globalFilterInput &&
category === null &&
tableState.columnFilters.every((e) => e.id === "categories") &&
tableState.pagination.pageIndex === 0;
const handleCategoryChange = useCallback((category) => {
setCategory(category);
table.setColumnFilters([]);
setGlobalFilterImmediately("");
}, [table, setGlobalFilterImmediately]);
return {
table,
sidebar: {
sortedOutputFieldEntries,
sortedTagEntries,
sortedProviderEntries,
searchIdsByOutputField,
searchIdsByProvider,
searchIdsByTag,
expandedSidebarSections,
setExpandedSidebarSections,
removeColumnFilter,
addColumnFilter,
},
searchEntriesByBaseSearch,
filterByField,
globalFilterInput,
setGlobalFilterInput,
isFilterChecked,
resetColumnFilters,
category,
setCategory: handleCategoryChange,
showFeaturedSearches,
};
}