Active Foundation

Search documentation

Search all pages, headings and text, in the current package or topic or in all documentation.

Filters API

Filter types, operator factories and filter components.

@workspace/active-grid 11.0.0Status unknowncontent differs from the recorded release 11.0.0baseline ce081dc3

The package's own reference

The text below is the package's own API reference, included unchanged. The complete list of exports, generated from the source, is on All exports.

FilterValue discriminated union, operator arrays + factories, evaluateFilter, advancedFilterFn, DateFilterPreset, and the built-in filter components. For tutorial-style how-to see ../guides/filters.md.

FilterValue Types#

typescript
import {type FilterValue, type FilterOperator} from '@workspace/active-grid';

FilterValue is a discriminated union based on the operator:

typescript
type FilterValue = NoValueFilter | SingleValueFilter | RangeFilter;
type NoValueFilter = {  operator: 'isEmpty' | 'isNotEmpty';};
type SingleValueFilter = {  operator: TextOperator | NumberOperator | DateOperator;  value: string | number | boolean;};
type RangeFilter = {  operator: 'between' | 'inRange';  value: string | number;  valueTo: string | number;};

Operator Types#

TypeOperators
TextOperatorcontains, notContains, startsWith, endsWith, equals, notEquals
NumberOperatorequals, notEquals, greaterThan, greaterThanOrEqual, lessThan, lessThanOrEqual
DateOperatoronDate, before, after
RangeOperatorbetween, inRange
NoValueOperatorisEmpty, isNotEmpty

Operator Factories#

typescript
import {  getTextOperators,  getNumberOperators,  getDateOperators,  getBooleanOperators,  getOperatorsForType,} from '@workspace/active-grid';

Each factory takes a required GridTranslateFunction for the labels; there is no English default (pass englishGridTranslator for English).

typescript
type FilterOperatorOption = {  value: FilterOperator;  label: string;  requiresValue: boolean;  requiresSecondValue?: boolean;};
const operators: FilterOperatorOption[] = getNumberOperators(t);// → [{value: 'equals', label: t('grid.operators.equals'), requiresValue: true}, …]

DateFilterPreset#

typescript
import {  type DateFilterPreset,  DEFAULT_DATE_PRESETS,} from '@workspace/active-grid';
typescript
interface DateFilterPreset {  key: string; // Translation key (e.g., 'grid.filter.datePreset.today')  label?: string; // Optional display label — used instead of t(key) when provided  type: 'single' | 'range';  getValue: (presentation?: GridPresentation) => {from: Date; to?: Date};}

DEFAULT_DATE_PRESETS provides 8 built-in presets: today, yesterday, last 7 days, last 30 days, this month, last month, this quarter, this year. Relative presets require an explicit presentation time zone. Their dates carry calendar days, which the date filter serializes as yyyy-MM-dd. Pass a custom array via meta.dateFilterPresets or false to disable. How to write a custom preset without reading the browser's time zone: ../guides/filters.md § Date Filter Configuration.

evaluateFilter / advancedFilterFn / evaluateFilterExpression#

typescript
import {  evaluateFilter,  evaluateFilterExpression,  advancedFilterFn,} from '@workspace/active-grid';
FunctionDescription
evaluateFilter(value, filter)Evaluate a FilterValue against a cell value.
evaluateFilterExpression(row, fe)Evaluate a FilterExpression tree (AND/OR groups) against a full row.
advancedFilterFnFilter function for the engine that supports operator-based filtering.

createLocaleSortFn#

typescript
import {createLocaleSortFn} from '@workspace/active-grid';

Factory that produces a sort function using Intl.Collator for locale-aware string sorting. Default sort uses ASCII codepoints; for locale-correct ordering pass sortFn: createLocaleSortFn(locale) on relevant columns.

typescript
createLocaleSortFn(locale: string, options?: Intl.CollatorOptions)
  • locale is required and must be a non-empty string; there is no host default. An empty or missing locale throws a TypeError.

  • The collator defaults to {numeric: true, sensitivity: 'base'}; options are merged over those defaults.

  • The returned function compares row.getValue(columnId) of two rows and returns a negative number, zero or a positive number. A string is compared as written, a finite number as its string form, and every other value (absent, NaN, ±Infinity, boolean, date, object) as the empty string.

Filter Components#

For custom filter UIs, the package exports the five built-in filter components plus a set of popover primitives.

typescript
import {  TextFilter,  NumberFilter,  DateFilter,  SelectFilter,  BooleanFilter,  FilterPopover,  FilterPopoverTrigger,  FilterPopoverContent,  FilterPopoverHeader,  FilterPopoverBody,  FilterIcon,  FilterClearButton,  FilterCheckboxItem,  FilterDateInput,  FilterNumberInput,  FilterOperatorSelect,  FilterSearchInput,  FilterTextInput,  FilterWrapper,} from '@workspace/active-grid';

In most cases the built-in filter row handles everything automatically based on meta.filterType — these exports are for custom filter-builder UIs and advanced consumers.

The layout contract of the filter row#

All six built-in filters share one internal anatomy, with one rule: the value gives way, the controls never do. That anatomy is an internal component and not a public export -- consumers do not compose it and do not need to know it.

Text
[ value / input            ][ clear 24px ][ menu 24px ]  min-w-0, shrinks to zero     shrink-0      shrink-0
WhatBehaviour
Value areashrinks first, down to zero; text truncates with an ellipsis
Clear button (X)only with an active filter; 24x24 target; does not shrink; never disappears on width
Filter menu button (funnel)always present; 24x24 target; does not shrink
Right-aligned columnmeta.headerAlign: 'right' mirrors the controls to the left; the slots stay the same
Full valueis in the rendered content, so screen readers get it untruncated

A filterable column automatically gets an effective minimum width of 80px. That floor is derived from the cell padding, the two targets and the gaps between them, and protects only the CONTROLS. It deliberately does not keep translated values readable: the same state needs 122px in English and 161px in Spanish, and the count in it is dynamic, so a floor that guarantees text does not exist.

The floor only RAISES. A column with a larger minSize of its own, or a grid with a larger defaultMinSize, is left alone; with settings.showFilterRow: false it does not apply.

A consumer does not need to declare anything for this. There is no prop, no opt-in and no migration, and there is no reason to add an own minWidth or a local CSS workaround for the clear button. A meta.customFilter deliberately falls outside the shell and owns its own anatomy.

Grounds and trade-off: DECISIONS.md ADR-027.

Filter Expression Tree#

For the AND/OR composite-filter UI, the package exports a small typed tree:

typescript
import {  type FilterExpression,  type FilterCondition,  type FilterGroup,  type FilterExpressionNode,  isFilterGroup,  evaluateFilterExpression,} from '@workspace/active-grid';
SymbolTypeDescription
FilterCondition{ id: string; field: string; operator: FilterOperator; value?: unknown; valueTo?: unknown }A single filter condition on a column.
FilterGroup{ id: string; combinator: 'and' | 'or'; children: FilterExpressionNode[] }A group with AND/OR logic combining children.
FilterExpressionNodeFilterCondition | FilterGroupA node in the tree — either a condition leaf or a group.
FilterExpressionFilterGroupRoot of the tree — always a group.
isFilterGroup(node)(node: FilterExpressionNode) => node is FilterGroupType guard. Returns true when the node has a combinator field.
evaluateFilterExpression<TData>(row: TData, expr: FilterExpression) => booleanClient-side row evaluator. Returns true if the row matches the expression.

evaluateFilterExpression ignores an incomplete condition: one without an operator, or without a value its operator reads (undefined, null, '' or a non-finite number; 0 and false are values; a range needs both ends). isEmpty and isNotEmpty need no value. A group judges only its complete children, and a group without any matches every row.

Tutorial: ../guides/filter-builder.md.

Server-mode filtering#

active-grid does not build database queries. In mode="server" the filter and global-search state is forwarded verbatim in ServerFetchParams, and the resource view in @workspace/active-resources translates it into a query server-side (see ./resource-mode.md). The evaluateFilter / advancedFilterFn helpers above apply only to mode="client" in-memory filtering.

This page as Markdown