Changelog
@fn-sphere/filter
1.1.0
Minor Changes
- #185
7a93fcdThanks @lawvs! - Add support for Zod enum types in filter predicates and UI components.- Added
enumEqualsandenumNotEqualfilter functions for enum types - Extended
containsandnotContainsfunctions to work withz.enum()schemas - Added enum and enum array data input views for selecting enum values in the filter UI
- Enum filters are defined separately due to runtime type indistinguishability from strings
- Added
Patch Changes
- Updated dependencies [
7a93fcd]:- @fn-sphere/[email protected]
1.0.0
Major Changes
-
15f2755Thanks @lawvs! - ## Migrate to Zod 4- Upgrade all filtering utilities to Zod 4, adopting the new
z.function({ input, output })factory. - Update tests, docs, and playground examples to reflect the revised function schema API.
- Surface tuple-based parameter metadata so filter UIs can materialise runtime validators without accessing private internals.
- Prepare downstream apps for the breaking changes required when upgrading filter definitions to Zod 4.
Migration guide
- Make sure your project is already on Zod 4 before consuming this release. Review the upstream changes at https://zod.dev/v4/changelog to plan any schema updates.
- Replace every
z.function().args(...).returns(...)with the new factory signature.
const equals = defineTypedFn({name: "equals",define: z.function().args(z.string(), z.string()).returns(z.boolean()),define: z.function({ input: [z.string(), z.string()], output: z.boolean() }),implement: (value, target) => value === target,});getParametersExceptFirstnow returns a$ZodTuplerather than a plain array. Usetuple._zod.def.itemswhen you need to inspect or parse arguments at runtime.DataInputViewProps/DataInputViewSpecconsume tuple schemas instead of loose arrays:
// Beforetype DataInputViewProps = {rule: SingleFilter;requiredDataSchema: [] | [z.ZodTypeAny, ...z.ZodTypeAny[]];updateInput: (...input: unknown[]) => void;};type DataInputViewSpec = {name: string;match:| []| [z.ZodTypeAny, ...z.ZodTypeAny[]]| ((parameterSchemas: [] | [z.ZodTypeAny, ...z.ZodTypeAny[]],fieldSchema?: z.ZodTypeAny,) => boolean);view: ComponentType<DataInputViewProps>;};// Aftertype DataInputViewProps = {rule: SingleFilter;requiredDataSchema: $ZodTuple;updateInput: (...input: unknown[]) => void;};type DataInputViewSpec = {name: string;match:| []| [$ZodType, ...$ZodType[]]| $ZodTuple| ((parameterSchemas: $ZodTuple, fieldSchema?: $ZodType) => boolean);view: ComponentType<DataInputViewProps>;};- Update all usages of
DataInputViewSpec.matchto handle the new tuple schema.
const literalUnionView: DataInputViewSpec = {name: "literal union",match: (parameterSchemas) => {if (parameterSchemas.length !== 1) {if (parameterSchemas._zod.def.items.length !== 1) {return false;}const [item] = parameterSchemas;const isUnion = item instanceof z.ZodUnion;const theOnlyItem = parameterSchemas._zod.def.items.at(0);const schemaDef = (theOnlyItem as $ZodTypes)._zod.def;const isUnion = schemaDef.type === "union";if (!isUnion) {return false;}return item.options.every((option: unknown) => option instanceof z.ZodLiteral,return schemaDef.options.every((option) => option._zod.def.type === "literal",);},view: function View({ requiredDataSchema, rule, updateInput }) {const { Select } = useView("components");const { getLocaleText } = useRootRule();const options = useMemo(() => {const unionSchema = requiredDataSchema[0] as z.ZodUnion<[z.ZodLiteral<z.Primitive>]>;const unionSchema = requiredDataSchema._zod.def.items[0] as $ZodUnion<$ZodLiteral[]>;return unionSchema.options.map((item: z.ZodLiteral<z.Primitive>) => ({return unionSchema._zod.def.options.map((item) => {const value = item._zod.def.values[0];const meta = z.globalRegistry.get(item);const metaDesc =meta && meta.description ? meta.description : undefined;return {label: getLocaleText(metaDesc ?? String(value)),value,};});}, [getLocaleText, requiredDataSchema]);return (<Selectoptions={options}value={rule.args[0]}onChange={(value) => {updateInput(value);}}/>);},} - Upgrade all filtering utilities to Zod 4, adopting the new
Patch Changes
- Updated dependencies [
15f2755]:- @fn-sphere/[email protected]
0.8.0
Minor Changes
-
a915a9aThanks @lawvs! - feat(filter)!: retain args by default when filter changes via tryRetainArgs- BREAKING: FieldSelect and FilterSelect now default
tryRetainArgs(andtryRetainFilterfor fields) totrue. Previously, leaving these props undefined defaulted to resettingargs. To restore the old behavior, explicitly passtryRetainArgs={false}(and/ortryRetainFilter={false}). - When switching filters within the same field, if the new filter’s parameter schema is compatible, existing
argsare preserved. - Data input “literal union” options are memoized for stability.
This change improves UX by avoiding unnecessary argument resets when changing a filter, while still allowing users to opt out.
- BREAKING: FieldSelect and FilterSelect now default
Patch Changes
-
Updated dependencies [
82696fa]:- @fn-sphere/[email protected]
0.7.2
Patch Changes
- #105
941d4a9Thanks @Garfield550! - Fix the incorrect version of @types/react in peer dependencies.
0.7.1
Patch Changes
0.7.0
Minor Changes
0.6.0
Minor Changes
-
ef470f1Thanks @lawvs! - Breaking Changes- Now the first field and the first filter will be selected by default when creating a new rule.
- Updated
useFilterSphereto usecreateDefaultRulefor default rule creation. - Updated
useFilterGroupanduseFilterRuleto usecreateDefaultRulewhen no input is provided.
- Updated
- Now the first field and the first filter will be selected by default when creating a new rule.
-
62aeaf0Thanks @lawvs! - ExportfilterableFieldsinuseRootRulehook. RemovefilterableFieldsfromuseFilterRulehook.BREAKING CHANGE: The
filterableFieldsis now exported in theuseRootRulehook instead of theuseFilterRulehook.Migration:
const { filterableFields } = useRootRule();const { filterableFields } = useFilterRule(rule); -
#51
a8b07f2Thanks @lawvs! - Add locale supportsBREAKING CHANGE
- All name of filter has been changed.
- The
booleanFilterhas been removed.
-
9badd88Thanks @lawvs! - Breaking Changes- Renamed
filterGroupprop torulein FilterGroupContainer. - Modified
filterThemein theme-mui-material to useruleinstead offilterGroup.
- Renamed
Patch Changes
-
5f4d54fThanks @lawvs! - RenameupdateRootRuletosetRootRuleinuseRootRulehookMigration:
const { updateRootRule } = useRootRule();const { setRootRule } = useRootRule(); -
200e5a1Thanks @lawvs! - DeprecatedgetRootRulein favor ofrootRuleinuseRootRulehook.Migration:
const { rootRule } = useRootRule();const { getRootRule } = useRootRule(); -
479f048Thanks @lawvs! - Fix logical error intoggleGroupOpfunction within theuseFilterGrouphook -
8337984Thanks @lawvs! - Support custom style for components -
Updated dependencies [
a8b07f2,020bdb1,a8b07f2,01369a8]:- @fn-sphere/[email protected]
0.5.0
Minor Changes
-
ab1a0c6: - Deprecated
onPredicateChangeinuseFilterSphere-
⚠️ BREAKING CHANGES
- The
onRuleChangecallback inuseFilterSpherenow receives an object with bothfilterRuleandpredicateproperties, instead of just thefilterRule. - The
onPredicateChangecallback has been removed. Use thepredicateproperty in theonRuleChangecallback instead.
export interface FilterSphereInput<Data,> extends BasicFilterSphereInput<Data> {onRuleChange?: (data: {filterRule: FilterGroup;predicate: (data: Data) => boolean;}) => void;}const { context } = useFilterSphere({schema: YOUR_DATA_SCHEMA,onRuleChange: ({ predicate }) => {const filteredData = YOUR_DATA.filter(predicate);console.log(filteredData);},}); - The
-
Migration Guide
const { context } = useFilterSphere({schema: YOUR_DATA_SCHEMA,onRuleChange: (filterRule) => {console.log(filterRule);},onPredicateChange: (predicate) => {const filteredData = YOUR_DATA.filter(predicate);console.log(filteredData);},onRuleChange: ({ filterRule, predicate }) => {const filteredData = YOUR_DATA.filter(predicate);console.log(filterRule, filteredData);},}); -
-
87acc5e: - BREAKING CHANGES
updateInputinDataInputViewPropsnow use spread parameter to accept new values.
updateInput([newValue]);updateInput(newValue); -
70565bc: - BREAKING CHANGES
- Increased spacing in templates
- Enhanced
SingleFilterContainerstyling:- Improved vertical alignment of child elements
- Remove
isValidflag fromFilterRule - Move
Add ConditionandAdd Groupbuttons to theFilterGroupContainer
Patch Changes
- 4a6e88a: Support multiple select for literal union
- 03624b8: Add multiple select
- f03f6e2: Remove unnecessary ref prop from data input views
- Updated dependencies [f5eae65]
- Updated dependencies [2b17977]
- @fn-sphere/[email protected]
0.4.0
Minor Changes
-
55b7fb1: - In
useFilterSelect:- The
updateFieldfunction has been deprecated and replaced withsetFieldfor clarity and consistency. - The
updateFilterfunction has been deprecated and replaced withsetFilter. - In
useFilterRule:- The
updateRulefunction has been renamed tosetRule - Added a new
duplicateRulefunction to duplicate a rule. - Added a new
invertRulefunction.
- The
- In
useFilterGroupanduseFilterRule:- The parameter
SingleFilterhas been changed toSingleFilterInputfor simplicity. - The parameter
FilterGrouphas been changed toFilterGroupInputfor simplicity.
- The parameter
- The
-
e05bcbe: Removed inline theme merging logic from
FilterSphereProvider.Introduced
createFilterThemefor theme merging.Migration guide:
<FilterSphereProvider theme={customTheme}>const theme = createFilterTheme(customTheme);<FilterSphereProvider theme={theme}>
Patch Changes
-
0ce4129: Add
tryRetainArgsto allow retainingargswhen filter is changed -
d4c6a7d: - Update
useFilterSpherehook to usepredicateinstead ofgetPredicate:import { useFilterSphere } from "@fn-sphere/filter";const { rule, predicate, context } = useFilterSphere({const { rule, getPredicate, context } = useFilterSphere({schema: YOUR_DATA_SCHEMA,});const filteredData = YOUR_DATA.filter(getPredicate());const filteredData = YOUR_DATA.filter(predicate);- Update
countTotalRules()toget totalRuleCountinuseFilterSpherehook - Add
validRuleCounttouseFilterSpherehook to get the count of valid rules
- Update
-
c5ad41a: Add
countValidRulesfunction touseFilterSpherehookconst { countValidRules } = useFilterSphere();const validRulesCount = countValidRules(); -
311f306: - Added the ability to retain the current filter and arguments when the field is changed in the
useFilterSelecthook.- Introduced the
UpdateFieldOptionstype to specify the behavior when updating the field. - Updated the
FieldSelectcomponent to pass theupdateFieldOptionsto theupdateFieldfunction.
export type UpdateFieldOptions = {/*** Try to continue using the current filter when the field is changed.** @default true*/tryRetainFilter?: boolean;/*** Automatically select the first filter when the field is changed and the filter is not retained.** @default true*/autoSelectFirstFilter?: boolean;/*** Try to continue using the current args when the field is changed.** @default true*/tryRetainArgs?: boolean;};<FieldSelectrule={rule}tryRetainFilterautoSelectFirstFiltertryRetainArgs/>; - Introduced the
-
Updated dependencies [e0f5632]
-
Updated dependencies [744b13e]
-
Updated dependencies [b042713]
- @fn-sphere/[email protected]
0.3.8
Patch Changes
- 19e8e38: Update preset templates
- @fn-sphere/[email protected]
0.3.7
Patch Changes
- 715e792: Add
getLocaleTextAPI- @fn-sphere/[email protected]
0.3.6
Patch Changes
-
b272f24: Export
FnSchema,StandardFnSchemaandGenericFnSchematype from core package.Export
defineGenericFnanddefineTypedFnfrom core package.- @fn-sphere/[email protected]
0.3.5
Patch Changes
-
98b38de: Add field schema to the match function in the
DataInputViewSpec. -
75feec4: Update data input view to handle empty values
If input value is empty string, the input view will update the rule args to
[]instead of[""]. This is to prevent the rule from running with an empty string as an argument.- @fn-sphere/[email protected]
0.3.4
Patch Changes
- 51abfaa: Export
FilterField- @fn-sphere/[email protected]
0.3.3
Patch Changes
-
caeeb9c: Move
createFilterGroupandcreateSingleFilterto core package.Add
getFilterRulemethod tocreateFilterSphere. -
79abaa0: Update readme
-
Updated dependencies [caeeb9c]
-
Updated dependencies [79abaa0]
- @fn-sphere/[email protected]
0.3.2
Patch Changes
- 2a8d304: Add new
resetmethod touseFilterSpherehook - 3ccf45a: Update styles for default templates
- @fn-sphere/[email protected]
0.3.1
Patch Changes
-
aef8fbc: Fix
numberOfRulesshould only count the SingleRule and not the RuleGroup.Return
countTotalRulesfunction touseFilterSpherehook.- @fn-sphere/[email protected]
0.3.0
Minor Changes
-
49df2cd: Add new
FilterSphereProvidercomponent to provide filter context to children components.Add
useFilterSpherehook to access filter predicate.The
FilterBuildercomponent no longer adds a provider to its child components.const { filterRule, schema, predicate } = useFilterSphere<YourData>();const filteredData = data.filter(predicate); -
c66db35: Redesign
useFilterSpherehook to return agetPredicatefunction and acontextobject.import { useFilterSphere } from "@fn-sphere/filter";const { getPredicate, context } = useFilterSphere<YourData>({schema: yourDataSchema,});const predicate = getPredicate();const filteredData = data.filter(predicate);
Patch Changes
-
1c4bfae: Rename
BasicFilterBuilderPropstoBasicFilterSphereInputand update type definitions.Export new type
BasicFilterSphereProps.export interface BasicFilterSphereInput<Data = unknown> {filterRule: FilterGroup;schema: ZodType<Data>;filterFnList?: FnSchema[];fieldDeepLimit?: number;mapFieldName?: (field: FilterField) => string;mapFilterName?: (filterSchema: StandardFnSchema,field: FilterField,) => string;onRuleChange?: (rule: FilterGroup) => void;}export type BasicFilterSphereProps<Data = unknown> = Required<BasicFilterSphereInput<Data>>; -
1ac1c43: Rename
createEmptyFiltertocreateEmptySingleFilterandcreateEmptyFilterGrouptocreateFilterGroup. -
1ac1c43: Add
SingleFilterContainerto template. -
991d8e7: Export
useRootRuleanduseFilterSelecthooks. -
b31b201: Rename
filterListtofilterFnList -
Updated dependencies [b31b201]
- @fn-sphere/[email protected]
0.2.0
Minor Changes
- 742c3af: Refactor API
Patch Changes
- @fn-sphere/[email protected]
0.1.3
Patch Changes
- 1670687: Export presetFilter
0.1.2
Patch Changes
-
b9d3b0a: chore: add type export for filter specs
-
b9d3b0a: Rename and export
FilterRuleinterface SingleFilter {type: "Filter";/*** 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 {/*** Unique id, used for tracking changes or resorting*/id: FilterId;}export interface FilterGroupInput {type: "FilterGroup";op: "and" | "or";conditions: (SingleFilter | FilterGroup)[];invert?: boolean;}export interface FilterGroup extends FilterGroupInput {/*** Unique id, used for tracking changes or resorting*/id: FilterId;}export type FilterRule = SingleFilter | FilterGroup; -
Updated dependencies [336fe84]
-
Updated dependencies [b9d3b0a]
- @fn-sphere/[email protected]
0.1.1
Patch Changes
- d7460ba: export UiSpec
0.1.0
Minor Changes
- 5c84d94: first publish
Patch Changes
- Updated dependencies [5c84d94]
- @fn-sphere/[email protected]