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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tc96/filter-builder

v0.1.0

Published

Domain-neutral filter builder for React applications using COSS and Base UI.

Readme

Filter Builder

A domain-neutral, accessible filter builder for React applications built with COSS, Base UI, and Tailwind CSS.

The package provides the interaction and presentation layer for filtering SaaS list, table, and board views. Your application remains responsible for the attribute catalog, operators, option sources, permissions, remote state, querying, and persistence.

Highlights

  • generic typed attributes with consumer-defined operators and options
  • controlled value contract with an internal draft while the popover is open
  • cascading resets: changing an attribute drops incompatible operators/values
  • apply gate that stays disabled until every condition is complete
  • clear action that resets back to a single empty condition
  • accessible popover, form, and grouped selects on Base UI
  • responsive condition rows for desktop and mobile
  • COSS visual primitives implemented on Base UI

Requirements

  • React 19
  • Base UI 1.x
  • Tailwind CSS 4

The package is COSS-first. COSS is distributed as source through its component registry, so this repository owns the small set of COSS primitives required by the view. A future Radix implementation will be a separate adapter and will not change the domain-neutral contract.

Installation

Install the published package with your package manager:

pnpm add @tc96/filter-builder
# or: bun add @tc96/filter-builder
# or: npm install @tc96/filter-builder

The consumer must already provide the peer dependencies:

pnpm add react react-dom @base-ui/react tailwindcss

COSS source location

@tc96/filter-builder is installed from npm and imported from node_modules. It does not need a components.json. Add that file only when the consuming app uses the COSS/shadcn CLI. Map the ui alias to components/patterns so COSS primitives are owned by the app in that directory:

{
  "$schema": "https://ui.shadcn.com/schema.json",
  "tsx": true,
  "aliases": {
    "ui": "@/components/patterns"
  }
}

Then run pnpm dlx shadcn@latest add @coss/ui (or the Bun/npm equivalent).

Tailwind must scan the installed package, and your theme must expose the standard COSS semantic tokens (--color-secondary, --color-popover, --color-muted-foreground, --color-border, --color-input, --color-ring, --radius, --radius-control, and related pairs):

@import "tailwindcss";
@source "../node_modules/@gblsmlo/filter-builder/dist";

Quick start

import {
  FilterBuilder,
  type FilterBuilderAttribute,
  type FilterCondition,
} from "@gblsmlo/filter-builder";
import { useState } from "react";

const attributes: FilterBuilderAttribute[] = [
  {
    id: "status",
    label: "Status",
    valueType: "select",
    operators: [
      { label: "is", value: "is" },
      { label: "is not", value: "is-not" },
    ],
    options: [
      { label: "In progress", value: "in-progress" },
      { label: "Done", value: "done" },
    ],
  },
];

export function ListFilters() {
  const [conditions, setConditions] = useState<FilterCondition[]>([]);

  return (
    <FilterBuilder
      attributes={attributes}
      onValueChange={setConditions}
      value={conditions}
    />
  );
}

onValueChange receives the complete condition set only when the user applies the filter, or an empty array when they clear it. The component is fully controlled: pass the applied value back in and it rebuilds its draft on open.

Use @gblsmlo/filter-builder/core when a non-visual layer only needs the public types and condition helpers (isCompleteFilterCondition, createFilterConditionDraft).

API

FilterBuilder

| Prop | Type | Description | | --- | --- | --- | | attributes | readonly FilterBuilderAttribute[] | Attribute catalog with per-attribute operators and options | | value | readonly FilterCondition[] | Applied conditions owned by the consumer | | onValueChange | (conditions: FilterCondition[]) => void | Called on apply (complete set) or clear (empty) | | triggerLabel | string | Optional trigger button label (defaults to Filtrar) |

Types

interface FilterBuilderOption {
  label: string;
  value: string;
}

interface FilterBuilderAttribute {
  id: string;
  label: string;
  operators: readonly FilterBuilderOption[];
  options: readonly FilterBuilderOption[];
  valueType: "select";
}

interface FilterCondition {
  attributeId: string;
  operator: string;
  value: string;
}

Ownership boundary

| Package owns | Consumer owns | | --- | --- | | popover, form, and grouped condition layout | attribute catalog, operators, and options | | draft editing, cascading resets, and apply gating | meaning of each attribute and operator | | accessible controls and responsive rows | query construction and server filtering | | controlled apply/clear callback | persisting, sharing, and restoring filters |

The package intentionally supports select value conditions joined by an implicit AND. Additional value types and boolean grouping remain consumer/server-owned until a durable contract is defined.

Development

Use Bun 1.3.14 and Node 24.18.0.

bun install
bun run storybook
bun run lint:ci
bun run typecheck
bun test
bun run build

See CONTRIBUTING.md for the contribution workflow and ADR-001 for the adapter decision.

License

MIT © Gabriel Melo.