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

@aftui/expresso

v1.0.6

Published

A powerful, themeable expression builder for creating complex filter logic

Readme

Expresso

A powerful, themeable expression builder for creating complex filter logic with a visual drag-and-drop interface.

Features

  • 🎨 Fully Themeable - Injectable theme system with default light and dark themes
  • 🔧 Comprehensive Operators - Comparison, arithmetic, logical, and conditional expressions
  • 🎯 Drag & Drop - Intuitive interface for organizing expressions
  • 💾 Presets - Save and load frequently used configurations
  • 📋 Import/Export - Share expressions via JSON
  • ⏱️ Undo/Redo - Full history support with keyboard shortcuts
  • 🔍 Search - Find specific values within expressions
  • Validation - Real-time error detection

Installation

npm install @aftui/expresso
# or
yarn add @aftui/expresso
# or
pnpm add @aftui/expresso

Peer Dependencies

This package requires React 19+ and several peer dependencies:

npm install react react-dom sonner lucide-react @radix-ui/react-dropdown-menu @radix-ui/react-label @radix-ui/react-popover @radix-ui/react-select @radix-ui/react-switch

Important: This package uses Sonner for toast notifications. You must include the <Toaster /> component in your app:

import { Toaster } from 'sonner';

function App() {
  return (
    <>
      <Toaster />
      {/* Your app content */}
    </>
  );
}

Styling

Expresso uses Vanilla Extract for styling, providing a zero-runtime CSS-in-JS solution. All styles are bundled with the component, so no additional setup is required.

SSR Frameworks (Astro, Next.js, Remix)

This component uses Radix UI which requires client-side rendering. When using with SSR frameworks:

Astro

---
import { Expresso } from '@aftui/expresso';
---

<Expresso
  client:only="react"
  fields={fields}
  onApply={handleApply}
/>

Next.js (App Router)

'use client' // Add this at the top of your component file

import { Expresso } from '@aftui/expresso'

Next.js (Pages Router)

import dynamic from 'next/dynamic'

const Expresso = dynamic(
  () => import('@aftui/expresso').then(mod => ({ default: mod.Expresso })),
  { ssr: false }
)

Quick Start

import {
  Expresso,
  type JoinKeyExpression,
  type DropdownItem
} from '@aftui/expresso';
import { Toaster } from 'sonner';

function App() {
  const fields: DropdownItem[] = [
    { name: 'Price', key: 'price' },
    { name: 'Status', key: 'status' },
    { name: 'Category', key: 'category' },
  ];

  const handleApply = (expression: JoinKeyExpression | JoinKeyExpression[]) => {
    console.log('Filter expression:', expression);
    // Use the expression in your application
  };

  return (
    <>
      <Toaster />
      <Expresso
        fields={fields}
        onApply={handleApply}
        onCancel={() => console.log('Cancelled')}
      />
    </>
  );
}

Theming

Using Default Theme

<Expresso
  fields={fields}
  onApply={handleApply}
  onCancel={handleCancel}
/>

Using Dark Theme

import { Expresso, darkTheme } from '@aftui/expresso';

<Expresso
  fields={fields}
  onApply={handleApply}
  onCancel={handleCancel}
  theme={darkTheme}
/>

Custom Theme

import {
  Expresso,
  type FilterBuilderThemeConfig
} from '@aftui/expresso';

const customTheme: FilterBuilderThemeConfig = {
  theme: {
    primary: "222.2 47.4% 11.2%",
    accent: "142.1 76.2% 36.3%", // Green accent
    // ... other theme properties
  },
  radius: "0.75rem",
};

<Expresso
  theme={customTheme}
  {...otherProps}
/>

See THEMING.md for complete theming documentation.

Props

| Prop | Type | Required | Description | |------|------|----------|-------------| | fields | DropdownItem[] | Yes | Array of available fields | | onApply | (expression) => void | Yes | Callback when user applies filter | | onCancel | () => void | Yes | Callback when user cancels | | defaultExpression | JoinKeyExpression \| JoinKeyExpression[] | No | Initial expression | | operatorConfig | OperatorConfig | No | Custom operator configuration | | creationMetaData | CreationMetaData | No | Metadata for new expressions | | customCategoryContent | Record<string, ReactNode> | No | Custom field category content | | theme | FilterBuilderThemeConfig | No | Custom theme |

Expression Format

Expressions are structured JSON objects:

{
  "operator": "and",
  "expressions": [
    {
      "operator": "gt",
      "left": { "valueType": "EnrichmentField", "fieldId": "Price" },
      "right": { "valueType": "constant", "value": 100 }
    },
    {
      "operator": "eq",
      "left": { "valueType": "EnrichmentField", "fieldId": "Status" },
      "right": { "valueType": "constant", "value": "Active" }
    }
  ]
}

Optional: Section Dropdown

If you need the Section Dropdown feature (for enrichment fields with sections), wrap your app with FieldsProvider:

import { FieldsProvider } from '@aftui/expresso';

function App() {
  const enrichmentFields = [
    { Id: 1, Name: 'Field1', FriendlyName: 'Field 1', Key: 'field1', Section: 'General' },
    // ... more fields
  ];

  return (
      <Expresso {...props} />
  );
}

If you don't use FieldsProvider, the Section Dropdown will simply not appear (graceful degradation).

TypeScript Support

This package is written in TypeScript and includes full type definitions.

import type {
  JoinKeyExpression,
  AnyExpressionType,
  DropdownItem,
  FilterBuilderThemeConfig,
  OperatorConfig,
} from '@aftui/expresso';

Backward Compatibility

For backward compatibility, the AdvancedFilterBuilder component name is also exported as an alias to Expresso. However, we recommend using Expresso for new projects:

// New (recommended)
import { Expresso } from '@aftui/expresso';

// Old (still works)
import { AdvancedFilterBuilder } from '@aftui/expresso';

Browser Support

  • Chrome/Edge (latest)
  • Firefox (latest)
  • Safari (latest)

Repository

License

MIT

Contributing

Contributions are welcome! Please open an issue or pull request at the GitHub repository.