Package Exports
- @aftui/expresso
Readme
Advanced Filter Builder
A powerful, themeable React component for building complex filter expressions 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 @your-org/advanced-filter-builder
# or
yarn add @your-org/advanced-filter-builder
# or
pnpm add @your-org/advanced-filter-builderPeer Dependencies
Make sure you have React 18+ and Sonner installed:
npm install react react-dom sonnerImportant: 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 */}
</>
);
}Tailwind CSS Setup
This package requires Tailwind CSS. Add the package to your Tailwind content:
// tailwind.config.js
module.exports = {
content: [
'./src/**/*.{js,jsx,ts,tsx}',
'./node_modules/@your-org/advanced-filter-builder/dist/**/*.{js,jsx,ts,tsx}',
],
// ... rest of your config
}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 {
AdvancedFilterBuilder,
type JoinKeyExpression,
type DropdownItem
} from '@your-org/advanced-filter-builder';
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 (
<AdvancedFilterBuilder
fields={fields}
onApply={handleApply}
onCancel={() => console.log('Cancelled')}
/>
);
}Theming
Using Default Theme
<AdvancedFilterBuilder
fields={fields}
onApply={handleApply}
onCancel={handleCancel}
/>Using Dark Theme
import { AdvancedFilterBuilder, darkTheme } from '@your-org/advanced-filter-builder';
<AdvancedFilterBuilder
fields={fields}
onApply={handleApply}
onCancel={handleCancel}
theme={darkTheme}
/>Custom Theme
import {
AdvancedFilterBuilder,
type FilterBuilderThemeConfig
} from '@your-org/advanced-filter-builder';
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",
};
<AdvancedFilterBuilder
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 '@your-org/advanced-filter-builder';
function App() {
const enrichmentFields = [
{ Id: 1, Name: 'Field1', FriendlyName: 'Field 1', Key: 'field1', Section: 'General' },
// ... more fields
];
return (
<FieldsProvider fields={enrichmentFields}>
<AdvancedFilterBuilder {...props} />
</FieldsProvider>
);
}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,
} from '@your-org/advanced-filter-builder';Browser Support
- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
License
MIT
Contributing
Contributions are welcome! Please open an issue or PR.