npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-filter-group

v0.1.6

Published

A React component library for building filter groups

Downloads

579

Readme

react-filter-group

A small, composable React library to build filter groups (nested AND/OR expressions) with first‑class customization: i18n, operators per field type, theming via CSS variables, and UI slots.

  • React 17+ JSX transform (no need to import React in every file)
  • TypeScript types included
  • Customizable operators, labels, and colors
  • Replaceable UI parts (buttons, toggles) via component slots

Installation

npm install react-filter-group
# or
yarn add react-filter-group
# or
pnpm add react-filter-group

Peer dependencies: react, react-dom.

Quick start

The package exports a high-level Filter component that manages a CompositeFilter value and a Provider for configuration.

import { Filter, FilterField, CompositeFilter } from "react-filter-group";

const fields: FilterField[] = [
  { name: "description", label: "Description", type: "text" },
  { name: "statusId", label: "Status", type: "numeric" },
  { name: "createdAt", label: "Creation Date", type: "date" },
];

const initial: CompositeFilter = {
  logic: "and",
  filters: [
    { field: "createdAt", operator: "gte", value: "2025-01-01" },
    { field: "createdAt", operator: "lte", value: "2025-12-31" },
  ],
};

export default function Example() {
  const [value, setValue] = useState<CompositeFilter | null>(initial);

  return (
    <Filter fields={fields} value={value} onChange={(e) => setValue(e.value)} />
  );
}

Configuration and customization

Wrap your app (or the area that renders the filter) in the provider to customize i18n, operators, theme variables, or even swap UI parts.

import {
  Filter,
  FilterGroupConfigProvider,
  FilterField,
  CompositeFilter,
} from "react-filter-group";

<FilterGroupConfigProvider
  value={{
    // 1) i18n (labels)
    messages: {
      addExpression: "Add condition",
      addGroup: "Add group",
      removeGroup: "Remove",
      logicAnd: "AND",
      logicOr: "OR",
    },

    // 2) theme via CSS variables (prefix --rfg-)
    // see the "Theming" section for the full list
    themeVars: {
      accent: "#2563eb",
      radius: "6px",
      // bg, fg, border, input-bg, disabled-bg, disabled-fg, danger, branch, ...
    },

    // 3) operators per field type (partial override)
    operators: {
      text: [
        { value: "contains", label: "Contains" },
        { value: "eq", label: "Equal to" },
        { value: "neq", label: "Not equal" },
      ],
    },

    // 4) optional UI slots (buttons)
    // components: {
    //   LogicButton: ({ logic, toggle }) => (
    //     <button onClick={toggle}>Logic: {logic.toUpperCase()}</button>
    //   ),
    //   AddExpressionButton: ({ onClick }) => (
    //     <button onClick={onClick}>+ Condition</button>
    //   ),
    //   AddGroupButton: ({ onClick }) => (
    //     <button onClick={onClick}>+ Group</button>
    //   ),
    //   RemoveGroupButton: ({ onClick }) => (
    //     <button onClick={onClick}>Remove</button>
    //   ),
    // },
  }}
>
  <Filter fields={fields} value={value} onChange={(e) => setValue(e.value)} />
</FilterGroupConfigProvider>;

Theming (CSS variables)

You can style the component with CSS variables injected by the provider via themeVars. Each key is prefixed with --rfg- internally. All variables have sensible fallbacks.

Available variables used today:

  • --rfg-accent (action/primary color)
  • --rfg-radius (border radius)
  • --rfg-bg (container background)
  • --rfg-fg (text color)
  • --rfg-border (borders)
  • --rfg-input-bg
  • --rfg-button-bg
  • --rfg-button-fg
  • --rfg-button-hover-fg
  • --rfg-disabled-bg
  • --rfg-disabled-fg
  • --rfg-danger (dangerous actions, e.g. remove)
  • --rfg-branch (connector lines in the group tree)

Example:

<FilterGroupConfigProvider value={{ themeVars: { accent: '#7c3aed', radius: '8px' } }}>
  <Filter ... />
</FilterGroupConfigProvider>

Types (summary)

  • FieldType: 'text' | 'numeric' | 'date' | 'boolean'
  • OperatorValue: 'eq' | 'neq' | 'contains' | 'notcontains' | 'startswith' | 'endswith' | 'gt' | 'gte' | 'lt' | 'lte' | 'isempty' | 'isnotempty' | 'isnull' | 'isnotnull'
  • LogicOperator: 'and' | 'or'
  • FilterField: { name: string; label: string; type: FieldType }
  • Operator: { value: OperatorValue; label: string }
  • FilterExpression: { field: string; operator: OperatorValue; value?: string | number | boolean | null }
  • CompositeFilter: { logic: LogicOperator; filters: Array<FilterExpression | CompositeFilter> }

Component props (high-level):

  • Filter
    • fields: FilterField[]
    • value?: CompositeFilter | null
    • onChange?: (e: { value: CompositeFilter | null }) => void

Config Provider API:

  • FilterGroupConfigProvider value?: {
    • operators?: Partial<Record<FieldType, Operator[]>>
    • messages?: Partial
    • themeVars?: Record<string, string>
    • components?: Partial }

Operators

Default operator sets exist for each FieldType. You can override a subset with the provider. There are operators that do not require a value (e.g. isempty, isnotempty, isnull, isnotnull) and the input is hidden automatically.

Internationalization (i18n)

Override any UI label via messages:

  • logicAnd, logicOr
  • addExpression, addGroup, removeGroup

Replacing UI parts (slots)

If you need to integrate with your design system, replace only the pieces you need through components in the provider. The default implementations consume i18n messages, and your overrides can do the same if you call the useFilterGroupConfig() hook.

Slots available:

  • LogicButton: ({ logic: 'and' | 'or', toggle })
  • AddExpressionButton: ({ onClick })
  • AddGroupButton: ({ onClick, disabled, hasFilters })
  • RemoveGroupButton: ({ onClick })

Development

Run the local example (Vite):

npm install
npm run example

Build library (Rollup):

npm run build

Run tests:

npm test

Lint:

npm run lint

Importing locally vs from npm

  • In development (this repo), the example imports from the local src using Vite config and/or TS paths.
  • When installed from npm in an external app, import from react-filter-group directly.

License

MIT