diff --git a/.changeset/orange-colts-give.md b/.changeset/orange-colts-give.md new file mode 100644 index 0000000..fa2fff4 --- /dev/null +++ b/.changeset/orange-colts-give.md @@ -0,0 +1,6 @@ +--- +"@fn-sphere/filter": patch +"@fn-sphere/core": patch +--- + +Update readme diff --git a/packages/core/README.md b/packages/core/README.md index 0f1028a..b0d0f4a 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -1,13 +1,18 @@ # @fn-sphere/core -`@fn-sphere/core` is a library that provides a set of utilities to work with data interactively. It provides a set of tools for filtering, sorting, and transforming data. +The `@fn-sphere/core` package is designed to provide a comprehensive set of utilities for working with data interactively. It offers tools for filtering, sorting, and transforming data, making it easier to handle complex data operations. ## Usages ### Filter ```ts -import { createFilter, commonFilters } from "@fn-sphere/core"; +import { + createFilterSphere, + findFilterableFields, + createFilterPredicate, + presetFilter, +} from "@fn-sphere/core"; import { z } from "zod"; // Define data schema @@ -22,21 +27,131 @@ const zData = z.object({ type Data = z.infer; -// Create a filter sphere -const filterSphere = createFilter(zData, [...commonFilters]); -// Get filterable fields -const availableField = filterSphere.findFilterableField(); -console.log(availableField); +// Get all filterable fields +const availableFields = findFilterableFields({ + schema, + filterFnList, + maxDeep, +}); +console.log(availableFields); const firstField = fields[0]; -const availableFilter = firstField.filterList; -const firstFilter = availableFilter[0]; -console.log(firstFilter); - -const requiredArgs = firstFilter.requiredParameters(); -console.log(requiredArgs); -// Input missing required parameters -firstFilter.input(25); -const filterData = filterSphere.filterData(data, firstFilter); +const availableFilter = firstField.filterFnList; +const firstFilterSchema = availableFilter[0]; +console.log(firstFilterSchema); + +const requiredParameters = getParametersExceptFirst(firstFilterSchema); +console.log(requiredParameters); + +// Create a filter rule for specific field +const filterRule = createSingleFilter({ + name: firstFilterSchema.name, + path: firstField.path, + args: [INPUT_VALUE], +}); + +const predicate = createFilterPredicate({ + schema: zData, + filterFnList: presetFilter, + filterRule, +}); + +// Filter data +const filterData = data.filter(predicate); console.log(filterData); ``` + +## API + +- `createFilterSphere`: Creates a filter sphere with the given schema and filters. +- `findFilterableFields`: Finds the filterable fields in the given schema. +- `createFilterPredicate`: Creates a filter predicate with the given filter sphere and filter rule. +- `presetFilter`: A preset filter function that can be used to filter data. + +## Types + +```ts +// FilterSphere + +const findFilterableFields: ({ + schema, + filterFnList, + maxDeep, +}: { + schema: ZodType; + filterFnList: FnSchema[]; + maxDeep?: number; +}) => FilterField[]; + +const createFilterPredicate: ({ + schema, + filterFnList, + filterRule, +}: { + /** + * The schema of the data. + */ + schema: z.ZodType; + filterFnList: FnSchema[]; + /** + * The filter rule. + */ + filterRule?: FilterRule; +}) => (data: Data) => boolean; + +type FilterField = { + /** + * If it's a empty array, it means the root object + */ + path: FilterPath; + fieldSchema: ZodType; + filterFnList: StandardFnSchema[]; +}; + +// Filter + +interface SingleFilterInput { + /** + * Field path + * + * If it's a empty array, it means the root object. + * If not provided, it means user didn't select a field. + */ + path?: FilterPath; + /** + * Filter name + * + * If not provided, it means user didn't select a filter. + */ + name?: string; + /** + * Arguments for the filter function + */ + args: unknown[]; + invert?: boolean; +} + +interface SingleFilter extends SingleFilterInput { + type: "Filter"; + /** + * Unique id, used for tracking changes or resorting + */ + id: FilterId; +} + +interface FilterGroupInput { + op: "and" | "or"; + conditions: (SingleFilter | FilterGroup)[]; + invert?: boolean; +} + +interface FilterGroup extends FilterGroupInput { + type: "FilterGroup"; + /** + * Unique id, used for tracking changes or resorting + */ + id: FilterId; +} + +type FilterRule = SingleFilter | FilterGroup; +``` diff --git a/packages/filter/README.md b/packages/filter/README.md index f50b0d8..a0eb0d5 100644 --- a/packages/filter/README.md +++ b/packages/filter/README.md @@ -1,47 +1,28 @@ -# @fn-sphere/filter +# Filter Sphere -This package provides a set of filters that can be used to filter data. +Filter Sphere is meant to generate advanced filters based on a zod schema. It is designed to work seamlessly with React, allowing you to create dynamic and complex filter interfaces in your applications. -## Usage +## Installation Install the package: ```sh -npm add @fn-sphere/filter -``` - -Create a filter: +npm install @fn-sphere/filter -```tsx -import { createFilter } from "@fn-sphere/filter"; -import { z } from "zod"; +yarn add @fn-sphere/filter -const YOUR_DATA_SCHEMA = z.object({ - name: z.string(), - age: z.number(), -}); -const YOUR_DATA: z.infer[] = [ - { - name: "John", - age: 30, - }, -]; - -const { getRule, openFilter } = createFilter({ - schema: YOUR_DATA_SCHEMA, -}); +pnpm add @fn-sphere/filter +``` -const initialRule = await getRule(); +Filter Sphere uses zod as its schema engine. You can install it by running: -const { rule, predicate } = await openFilter(); -console.log(rule); -const filteredData = YOUR_DATA.filter(predicate); -console.log(filteredData); +```sh +npm install zod ``` -## React +## Usage -You can use the `useFilter` hook to manage the filter state: +You can use the `useFilterSphere` hook to create a filter: ```tsx import { useFilter } from "@fn-sphere/filter"; @@ -60,33 +41,30 @@ const YOUR_DATA: z.infer[] = [ ]; const Filter = () => { - const { rule, predicate, openFilter } = useFilter({ + const { rule, getPredicate, context } = useFilter({ schema: YOUR_DATA_SCHEMA, + onPredicateChange: (predicate) => { + const filteredData = YOUR_DATA.filter(predicate); + console.log(filteredData); + }, }); - const handleOpenFilter = async () => { - const { rule, predicate } = await openFilter(); - console.log(rule); - const filteredData = YOUR_DATA.filter(predicate); - console.log(filteredData); - }; - - return ; + return ( + + + + ); }; ``` -## Custom filter styles +## Custom Styles You can provide custom styles for the filter styles by using the `FilterThemeProvider` component: ```tsx -import { - FlattenFilterDialog, - FilterThemeProvider, - FilterTheme, -} from "@fn-sphere/filter"; +import { FilterThemeProvider, ThemeSpec } from "@fn-sphere/filter"; -const theme: FilterTheme = {}; +const theme: ThemeSpec = {}; const App = () => { return (