Advanced filtering / query builders
A builder over a typed predicate tree
1 of 5 files
Usage
import { AdvancedFilter, emptyTree } from "@gpuixui/data";
import { useState } from "react";
const [tree, setTree] = useState<FilterTree>(emptyTree);
<AdvancedFilter
fields={[
{ field: "status", label: "Status" },
{ field: "size", label: "Size" },
]}
tree={tree}
onChange={setTree}
/>;API
The tree's own readers are exported beside the builder:
| Export | What it does |
|---|---|
emptyTree | the empty all group, which matches everything |
FilterTree | the schema a stored query is decoded and validated through |
isFilterTree(value) | whether a value is a tree this release can read |
readFilterTree(value) | Option<FilterTree>: a stored query, or the refusal |
filterByTree(rows, tree, valueOf) | the rows a tree keeps |
matchesTree(tree, row, valueOf) | whether one row matches |
describeTree(tree) | the sentence a tree reads as |
AdvancedFilter
| Prop | Type | Default | Consequence |
|---|---|---|---|
fields | AdvancedFilterField[] | — | the fields a clause may name; a blank label reads as the field's own name, a value that is not a list offers no field, and a list that offers none — or whose entries name a blank field — paints no Add control |
tree | FilterTree | — | the tree the builder paints |
onChange | (next: FilterTree) => void | — | receives every edited tree |
title | string | Filters | the title above the builder; a blank title reads as Filters |
className | string | — | joined after the recipe |
testId | string | — | the builder's id; a clause is ${testId}-${slot}-… |
AdvancedFilterField
| Field | Type | Consequence |
|---|---|---|
field | string | the field a clause reads, and the fallback name when the label is blank |
label | string | the words the builder shows for it |
A saved query
A tree is stored data: a saved query outlives the release that wrote it, and a store or a hand-edited record can hand back a node or a comparison this build does not carry. Decode it before it reaches a builder or a table:
const saved = readFilterTree(storedQuery);
Option.match(saved, {
onNone: () => promptToRebuildTheQuery(),
onSome: (tree) => setTree(tree),
});A tree this release cannot read is refused, never approximated: the table
keeps no rows rather than showing every record the query meant to hide, and
describeTree answers a filter this release cannot read. The builder paints
that sentence with Clear, so a reader can recover from a query whose clauses it
cannot edit. A null/undefined query is no filter at all — useTable and the
builder read it as the empty tree.
A tree the schema can read may still name no field: a query saved before its
field was picked carries a blank field, which the tree's schema accepts. The
builder does not refuse it — there is a clause to edit — it reads the missing
name as Field, so the row is named and its sentence says which part is absent.
Edit this page on GitHubpackages/data/docs/advanced-filter.mdx