Documentation Index
Fetch the complete documentation index at: https://woltz.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Live Demo
Instalation
npx shadcn add "https://tarcisioandrade.github.io/rich-domain/packages/react-rich-domain/public/r/filter.json"
Basic Usage
import { useCriteria } from "@/hooks/use-criteria";
import { Filter } from "@/components/filter/filter";
import type { QueryFilter } from "@/lib/filter-utils";
interface User {
id: string;
name: string;
email: string;
status: "active" | "inactive" | "pending";
age: number;
createdAt: Date;
}
// Define filterable fields
const userFields: QueryFilter[] = [
{
field: "name",
fieldLabel: "Name",
type: "string",
},
{
field: "email",
fieldLabel: "Email",
type: "string",
},
{
field: "status",
fieldLabel: "Status",
type: "string",
options: [
{ value: "active", label: "Active" },
{ value: "inactive", label: "Inactive" },
{ value: "pending", label: "Pending" },
],
},
{
field: "age",
fieldLabel: "Age",
type: "number",
},
{
field: "createdAt",
fieldLabel: "Created At",
type: "date",
},
];
function UserFilters() {
const { filters, addOrReplaceByIndex, removeFilter, clearFilters } =
useCriteria<User>();
return (
<Filter
fields={userFields}
filters={filters}
addOrReplaceByIndex={addOrReplaceByIndex}
removeFilter={removeFilter}
clearFilters={clearFilters}
/>
);
}
QueryFilter Type
interface QueryFilter {
// Field path in the entity (e.g., "name", "profile.bio")
field: string;
// Display label for the field
fieldLabel: string;
// Field type determines available operators
type: "string" | "number" | "date" | "boolean";
// Optional: mark if field path traverses a collection (1:N or N:N relation)
isCollection?: boolean;
// Optional: mark if field can be null
isNullable?: boolean;
// Optional: predefined options for select fields
options?: Array<{
value: string;
label: string;
icon?: React.ReactNode;
}>;
}
Field Types and Operators
The Filter component automatically shows the appropriate operators based on field type:
| Type | Operators |
|---|
string | equals, notEquals, contains, startsWith, endsWith, in, notIn, isNull, isNotNull |
number | equals, notEquals, greaterThan, greaterThanOrEqual, lessThan, lessThanOrEqual, between, in, notIn, isNull, isNotNull |
date | equals, notEquals, greaterThan, lessThan, between, isNull, isNotNull |
boolean | equals, notEquals, isNull, isNotNull |
With Options (Select Fields)
For fields with predefined values, use the options property:
const orderFields: QueryFilter[] = [
{
field: "status",
fieldLabel: "Order Status",
type: "string",
options: [
{ value: "draft", label: "Draft", icon: <FileIcon /> },
{ value: "confirmed", label: "Confirmed", icon: <CheckIcon /> },
{ value: "shipped", label: "Shipped", icon: <TruckIcon /> },
{ value: "delivered", label: "Delivered", icon: <PackageIcon /> },
],
},
{
field: "priority",
fieldLabel: "Priority",
type: "string",
options: [
{ value: "low", label: "Low" },
{ value: "medium", label: "Medium" },
{ value: "high", label: "High" },
],
},
];
Nested Fields
Support for nested entity paths:
const userFields: QueryFilter[] = [
{
field: "profile.bio",
fieldLabel: "Bio",
type: "string",
},
{
field: "address.city",
fieldLabel: "City",
type: "string",
},
{
field: "address.country",
fieldLabel: "Country",
type: "string",
options: [
{ value: "US", label: "United States" },
{ value: "BR", label: "Brazil" },
{ value: "UK", label: "United Kingdom" },
],
},
];
Collection Fields
When filtering through a 1:N or N:N relation (e.g., User has many Posts), use isCollection: true:
const userFields: QueryFilter[] = [
{
field: "name",
fieldLabel: "Name",
type: "string",
},
{
// Filtering through a collection requires isCollection: true
field: "posts.title",
fieldLabel: "Post Title",
type: "string",
isCollection: true, // ✅ Required for collections
},
{
field: "posts.status",
fieldLabel: "Post Status",
type: "string",
isCollection: true,
options: [
{ value: "draft", label: "Draft" },
{ value: "published", label: "Published" },
],
},
];
When isCollection: true, the filter will automatically use { quantifier: "some" } to generate the correct Prisma query:
// Without isCollection (incorrect for collections)
{ posts: { title: { contains: "hello" } } } // ❌ Error
// With isCollection: true (correct)
{ posts: { some: { title: { contains: "hello" } } } } // ✅ Works