Customizing Filters
Filter Sphere allows you to extend the default filtering capabilities with your own specific logic. This feature is particularly useful when you need to implement complex or domain-specific filtering that isn’t covered by the built-in filters.
Defining a Custom Filter
To add custom filters to Filter Sphere, you can use the defineTypedFn
function. This allows you to create type-safe, custom filter functions.
Use defineTypedFn
to create a custom filter:
const customFilter = defineTypedFn({ name: "your filter name", define: z .function() .args(schemaToFilter, optionalUserInputSchema) .returns(z.boolean()), implement: (value, userInput) => { // Your filter logic here return value === userInput; },});
- name: A string describing your filter. Ensure it is unique and doesn’t duplicate any built-in filter names.
- By default, the name will be used as the filter label in the UI. You can override this by overriding the
mapFilterName
property in theuseFilterSphere
hook.
- By default, the name will be used as the filter label in the UI. You can override this by overriding the
- define: A Zod schema defining the function signature.
- First argument: The schema of the data being filtered.
- Second argument (optional): The schema for user input, if required.
- implement: The actual filter logic.
Using Custom Filters
Add your custom filters to the filterFnList
when using the useFilterSphere
hook:
import { useFilterSphere, presetFilter } from "@fn-sphere/filter";
const { predicate, context } = useFilterSphere({ schema: yourSchema, filterFnList: [ customFilter, // Other custom filters... ...presetFilter, // Include preset filters if needed ],});
This approach allows you to extend Filter Sphere’s functionality with your own custom filtering logic while maintaining type safety and integration with the existing system.
Here’s an example of using a custom filter function to filter the average of an array of numbers:
scores | average |
---|---|
[1] | 1 |
[1,10] | 5.5 |
[1,2,3,4,5] | 3 |
[6,7,8,9,10] | 8 |
import { z } from "zod";import { Table } from "~/components/table";import { FilterSphereProvider, FilterBuilder, useFilterSphere, presetFilter, defineTypedFn, type FnSchema,} from "@fn-sphere/filter";
const data = [ { scores: [1] }, { scores: [1, 10] }, { scores: [1, 2, 3, 4, 5] }, { scores: [6, 7, 8, 9, 10] },].map((item, index) => ({ ...item, average: item.scores.reduce((acc, curr) => acc + curr) / item.scores.length,}));
const schema = z.object({ scores: z.array(z.number()),});
const dataFilters: FnSchema[] = [ // Define a custom filter function defineTypedFn({ name: "Average score is greater than", define: z .function() // The first argument is the schema that needs filtering // and the second argument is the user input .args(z.array(z.number()), z.number()) .returns(z.boolean()), implement: (value, input) => { // Implement the filter logic const sum = value.reduce((acc, cur) => acc + cur); return sum / value.length > input; }, }), // Preset filters contains all the built-in filters ...presetFilter,];
export default function AdvancedFilter() { const { predicate, context } = useFilterSphere({ schema, // Pass the custom filters to the filterFnList filterFnList: dataFilters, }); return ( <FilterSphereProvider context={context}> <FilterBuilder /> <Table data={data.filter(predicate)} /> </FilterSphereProvider> );}
🚧 Define a generic filter
WIP