Skip to content

Filter

HTMLRevoGridElement (Extended from global)

Section titled “HTMLRevoGridElement (Extended from global)”
interface HTMLRevoGridElement {
/** Global row search observed by AdvanceFilterPlugin. */
quickFilter?: QuickFilterInput;
/** Template-friendly alias for `quickFilter`. */
'quick-filter'?: QuickFilterInput
}

AdditionalData (Extended from @revolist/revogrid)

Section titled “AdditionalData (Extended from @revolist/revogrid)”
interface AdditionalData {
/** @deprecated Use `grid.quickFilter` instead. */
quickFilter?: QuickFilterInput
}

HTMLRevoGridElementEventMap (Extended from global)

Section titled “HTMLRevoGridElementEventMap (Extended from global)”
interface HTMLRevoGridElementEventMap {
beforefilteroptionsourcerow: FilterOptionSourceRowEventDetail;
beforefilteroptionvalue: FilterOptionValueEventDetail;
beforequickfilterapply: QuickFilterApplyEventDetail;
afterquickfilterapply: QuickFilterApplyEventDetail;
filterastchange: FilterAstChangeEventDetail;
filterasterror: FilterAstErrorEventDetail
}

ColumnRegular (Extended from @revolist/revogrid)

Section titled “ColumnRegular (Extended from @revolist/revogrid)”
interface ColumnRegular {
/**
* Preferred value control for this column in canonical Filter AST editors.
* Surface-specific `valueEditors` overrides take precedence.
*/
filterAstValueEditor?: FilterAstEditorSliderValueEditor
}

FilterCaptions (Extended from @revolist/revogrid)

Section titled “FilterCaptions (Extended from @revolist/revogrid)”
interface FilterCaptions {
/**
* Label shown by an inactive selection control in the filter header.
*/
selectionAll: string;
/**
* The title of the selection filter
*/
selectionTitle: string;
/**
* Placeholder for the selection filter search input.
*/
selectionSearchPlaceholder: string;
/** Excel-mode primary action label. */
selectionApply: string;
/** Excel-mode dismissal label. */
selectionCancel: string;
/** Excel-mode all-values row label. */
selectionSelectAll: string;
/** Excel-mode search-results row label. */
selectionSelectAllSearchResults: string;
/** Excel-mode union-with-applied-selection label. */
selectionAddCurrentSelection: string;
/** Excel-mode action that flips only the currently visible values. */
selectionInvertVisible: string;
/** Accessible label for the Excel-mode invert-visible action. */
selectionInvertVisibleAria: string;
/** Excel-mode label for null and empty values. */
selectionBlanks: string;
/**
* The title of the slider filter
*/
sliderTitle: string;
/**
* The title of the date filter
*/
dateTitle: string;
/**
* The popup header title before the column name.
*/
popupHeaderTitle: string;
/**
* The popup header separator between title and column name.
*/
popupHeaderSeparator: string;
/**
* Formats the popup header column name from the full column data.
*/
popupHeaderColumnName: (column: ShowData) => string;
/**
* Accessible label for the popup header filter icon when the column has active filters.
*/
popupHeaderActive: string;
/**
* The popup header close icon accessible label and title.
*/
popupHeaderClose: string;
/** Accessible label for a column's compact header-filter control. */
filterHeaderLabel: (column: ColumnRegular) => string;
/** Inactive compact-header placeholder for free-text filters. */
filterHeaderSearch: string;
/** Inactive compact-header placeholder for date filters. */
filterHeaderAnyDate: string;
/** Inactive compact-header placeholder for boolean filters. */
filterHeaderEither: string;
/** Inactive compact-header placeholder for array filters. */
filterHeaderAnyItem: string;
/** Inactive compact-header placeholder for numeric and generic value filters. */
filterHeaderAnyValue: string;
/** Inactive compact-header placeholder for application-defined structured filters. */
structuredFilterHeaderPlaceholder: string;
/** Inactive compact-header placeholders owned by the built-in structured filters. */
tokenListHeaderPlaceholder: string;
fuzzyHeaderPlaceholder: string;
regexHeaderPlaceholder: string;
chipBadgeHeaderPlaceholder: string;
ratingProgressHeaderPlaceholder: string;
ratingProgressHeaderProgressPlaceholder: string;
ratingProgressHeaderScorePlaceholder: string;
timeMatrixHeaderAnyTime: string;
arrayTagsHeaderPlaceholder: string;
/** Localized selection-count sentence used by header tooltips and assistive text. */
filterHeaderSelectionSummary: (
selected: number,
total: number,
details?: string,
) => string;
/**
* The button label for opening the Pro expression filter editor.
*/
expressionButton: string;
/**
* The title shown above the expression editor.
*/
expressionTitle: string;
/**
* Placeholder text for the expression editor.
*/
expressionPlaceholder: string;
/**
* Accessible label for applying expression text immediately.
*/
expressionApply: string;
/** Status shown when an expression parses and validates successfully. */
expressionValid: string;
/** Accessible label for the expression autocomplete list. */
expressionSuggestions: string;
/**
* Label shown before expression validation errors.
* @deprecated Expression validation details are now shown in the expression tooltip.
*/
expressionInvalid: string
}

ColumnFilterConfig (Extended from @revolist/revogrid)

Section titled “ColumnFilterConfig (Extended from @revolist/revogrid)”
interface ColumnFilterConfig {
/**
* Delegates filter execution to an external data source while preserving
* the advanced filter UI and transport events. When enabled, the plugin
* emits `beforefilterapply` but skips local row trimming; the host is
* responsible for loading and installing the filtered rows.
*/
external?: boolean;
/**
* Shows the compact filter button in column headers. Set to `false` when
* filtering is controlled by another surface such as a mounted AST editor.
* Filtering itself remains enabled. Defaults to `true`.
*/
columnFilterButton?: boolean;
/** Enables and configures the grouped rule-builder. Omit to keep grouped view disabled. */
groupedFilter?: GroupedFilterConfig;
/** Registered Pro popup body types selected by a column's existing `filter` field. */
structuredFilterTypes?: readonly StructuredFilterType[];
/** Complete aggregate data supplied by a remote backend for structured popup bodies. */
structuredFilterAggregates?: StructuredFilterAggregateProvider;
/** Array/tag value extraction, globally or by column property. */
arrayTags?: ArrayTagsOptions;
/** Faceted-list display labels, globally or by column property. */
facetedList?: FacetedListOptions;
/** Canonical Pro filter tree. It wins over collection-based initial filter state. */
filterAst?: FilterAst;
/** Timezone, week, fiscal-calendar, and visible-operator policy for date/datetime filters. */
date?: DateFilterConfig;
/**
* Whether the filter panel allows the same operator more than once per column.
* Defaults to true. Set to false to make visible operators mutually exclusive.
*/
allowDuplicateOperators?: boolean;
/**
* The configuration for the selection filter
*/
selection?: SelectionConfig;
/**
* The configuration for the slider filter.
*
* @example
* ```ts
* grid.filter = {
* slider: {
* headerView: 'range',
* showRangeDisplay: true,
* showRangeInputs: true,
* formatInputValue: value => value.toFixed(2),
* parseInputValue: value => Number(value.replace(',', '.')),
* },
* };
* ```
*/
slider?: SliderFilterConfig;
/**
* The configuration for the Pro advanced filter popup header.
*/
popupHeader?: FilterPopupHeaderConfig;
/**
* Opt-in current-column expression editor for advanced filters.
* When enabled, the popup appends an expandable expression panel below the regular filter controls.
* Valid expressions compile into the existing `multiFilterItems` filter model.
*
* @example
* ```ts
* grid.filter = {
* expressions: {
* enabled: true,
* applyDebounceMs: 300,
* errorTooltipLabel: 'Expression validation details',
* formatDiagnostic: diagnostic => translateExpressionDiagnostic(diagnostic),
* },
* };
* ```
*/
expressions?: boolean | ExpressionFilterConfig
}
export function defineAdvancedFilterConfig(
config: AdvancedFilterConfig,
): ColumnFilterConfig;

AdvancedFilterConfig (Extended from index.ts)

Section titled “AdvancedFilterConfig (Extended from index.ts)”
export type AdvancedFilterConfig = Omit<ColumnFilterConfig, 'localization'> & {
localization?: AdvancedFilterLocalization;
};

AdvancedFilterLocalization (Extended from index.ts)

Section titled “AdvancedFilterLocalization (Extended from index.ts)”
export type AdvancedFilterLocalization = Partial<Omit<CoreFilterLocalization, 'captions' | 'filterNames'>> & {
/** Partial core captions plus captions for Pro and application-defined filter bodies. */
captions?: Partial<CoreFilterCaptions> & Record<string, AdvancedFilterCaptionValue>;
/** Partial core names plus names for Pro and application-defined operators. */
filterNames?: Partial<CoreFilterLocalization['filterNames']> & Record<string, string>;
};

interface SetFilterAstOptions {
/** Keep the latest toolbar quick-filter query and compose it with the replacement AST. */
preserveQuickFilter?: boolean
}

Plugins The AdvanceFilterPlugin extends the filtering capabilities of a RevoGrid component by introducing advanced, customizable filter options, such as selection and range-based filters. This plugin enhances the grid’s filter functionality, allowing users to interact with and manipulate data effectively.

Key Features:

  • Custom Filters: Introduces custom filter types including selection and slider for more flexible data filtering. These filters allow users to select specific values or define a range for filtering data.
  • Event Integration: Listens for BEFORE_HEADER_RENDER_EVENT to determine the applicability of filters for a given column, ensuring that only relevant filters are displayed.
  • Dynamic Content Rendering: Uses a HyperFunc to dynamically render filter UI components in the grid’s header through filter-owned abstract controls and selection list rendering.
  • Enhanced Filter Management: Provides methods to manage excluded values from filters and to generate selection lists based on current data, facilitating complex filter interactions.

Usage:

  • Integrate AdvanceFilterPlugin into a RevoGrid instance to enable advanced filtering features. Add the plugin to the grid’s plugins array during initialization.
import { AdvanceFilterPlugin } from '@revolist/revogrid-pro'
const grid = document.createElement('revo-grid');
grid.plugins = [AdvanceFilterPlugin];

This plugin is essential for applications that require sophisticated filtering mechanisms, enabling users to perform more nuanced data queries and enhancing the overall data exploration experience.

  • Optional FilterPlugin: Replaces an existing core FilterPlugin while preserving its filter configuration.
  • Auto-installed TooltipPlugin: Shows shared hover and keyboard-focus details for active-filter badge info icons.
class AdvanceFilterPlugin {
initConfig(config: ColumnFilterConfig);
beforeshow(data: ShowData): void;
async headerclick(...args: Parameters<FilterPlugin['headerclick']>);
async onFilterChange(
filterItems: Parameters<FilterPlugin['onFilterChange']>[0],
changedProp?: ColumnProp,
);
runFiltering(...args: Parameters<FilterPlugin['runFiltering']>);
emit<T = any>(eventName: string, detail?: T);
/** Returns the normalized global quick-filter payload currently in effect. */
getQuickFilter();
getRowFilter(
rows: DataType[],
_filterItems: Parameters<FilterPlugin['getRowFilter']>[1],
_columnByProp: Record<string, ColumnRegular>,
): TrimmedEntity;
/** Evaluates cascade options against every canonical condition except their own field. */
getContextAwareRowFilter(
rows: DataType[],
columnProp: ColumnProp,
columnByProp: Record<string, ColumnRegular>,
): TrimmedEntity;
/** Registers or replaces one structured filter popup body for this plugin. */
registerStructuredFilterType(type: StructuredFilterType);
/** Removes one structured filter popup body registration. */
unregisterStructuredFilterType(id: string);
/** Returns one registered structured filter type by stable id. */
getStructuredFilterType(id: string);
/** Canonical active state used by headers even when grouped AST cannot be projected. */
hasActiveFilterForColumn(prop: ColumnProp);
/** Resolves one structured column into a compact, data-independent header model. */
getStructuredFilterHeader(column: ColumnRegular);
/** Resolves a registered filter's own popup or inline header control. */
getStructuredFilterHeaderControl(
column: ColumnRegular,
): FilterHeaderControl | undefined;
async doFiltering(...args: Parameters<FilterPlugin['doFiltering']>);
/** Returns a defensive clone of the currently applied canonical tree. */
getFilterAst(): FilterAst | undefined;
/** Mounts the canonical grouped Filter AST editor into an application-owned host. */
mountFilterAstEditor(
host: HTMLElement,
options: FilterAstEditorMountOptions = {},
): FilterAstEditorHandle;
/** Atomically replaces the canonical tree. Undefined clears it; quick filtering is cleared unless preserved. */
async setFilterAst(ast?: FilterAst, options: SetFilterAstOptions = {}): Promise<void>;
async clearFiltering();
isSelectionCascadeEnabled();
hasCustomSelectionItems(columnProp: ColumnProp);
/** Returns whether a row may contribute values to advanced filter options. */
isFilterOptionSourceRow(row?: DataType);
/** Resolves a parsed cell value before it contributes advanced-filter options. */
getFilterOptionValue(
row: DataType,
column: ColumnRegular,
rowType?: DimensionRows,
rowIndex?: number,
);
getContextAwareSelectionList(
columnProp: ColumnProp,
exlude = new Set<string>(),
sourceRowTypes?: DimensionRows[],
);
getContextAwareSelectionItems(
columnProp: ColumnProp,
exlude = new Set<string>(),
sourceRowTypes = resolveSelectionFilterConfig(
this.filterConfig?.selection,
columnProp,
).sourceRowTypes,
);
getExcludedValues(columnProp: ColumnProp);
getSelectionList(
columnProp: ColumnProp,
exlude = new Set<string>(),
sourceRowTypes?: DimensionRows[],
): { value: string, label: string }[];
/** Mounts a framework-neutral active-filter badge list backed by this plugin. */
createFilterBadges(root: HTMLElement, options: AdvancedFilterBadgesOptions = {});
destroy();
}

export function getExtraByOperator(operator: DateFilterOperator): ExtraField | undefined;

export function getStartOfToday();

export function getStartOfYesterday();

export function getStartOfThisMonth();

export function getStartOfLastMonth();

export function getStartOfThisQuarter();

export function getStartOfThisYear();

FILTER_DATE: string;

export type DateFilterOperatorWithDatePickerExtra =
| 'equals' | 'before' | 'after' | 'onOrBefore' | 'onOrAfter' | 'notEqual';

export type DateFilterOperatorWithDateRangeExtra = 'between';

interface DateRangeValue {
operator: DateFilterOperator;
fromDate?: string;
toDate?: string
}

datetimeFilterOperators: ("datetimeEquals" | "datetimeBefore" | "datetimeAfter" | "datetimeOnOrBefore" | "datetimeOnOrAfter" | "datetimeBetween" | "datetimeNotEqual" | "datetimeIsEmpty" | "datetimeIsNotEmpty" | "datetimeToday" | "datetimeYesterday" | "datetimeLast7Days" | "datetimeNext30Days" | "datetimeThisWeek" | "datetimeLastWeek" | "datetimeNextWeek" | "datetimeThisMonth" | "datetimeLastMonth" | "datetimeThisQuarter" | "datetimeNextQuarter" | "datetimePreviousQuarter" | "datetimeThisYear" | "datetimeNextYear" | "datetimePreviousYear" | "datetimeThisFiscalQuarter" | "datetimeNextFiscalQuarter" | "datetimePreviousFiscalQuarter" | "datetimeThisFiscalYear" | "datetimeNextFiscalYear" | "datetimePreviousFiscalYear")[];

Browser-local compatibility registry used outside an AdvanceFilterPlugin instance.

DATE_FILTERS: Record<"equals" | "before" | "after" | "onOrBefore" | "onOrAfter" | "between" | "notEqual" | "isEmpty" | "isNotEmpty" | "today" | "yesterday" | "last7Days" | "next30Days" | "thisWeek" | "lastWeek" | "nextWeek" | "thisMonth" | "lastMonth" | "thisQuarter" | "nextQuarter" | "previousQuarter" | "thisYear" | "nextYear" | "previousYear" | "thisFiscalQuarter" | "nextFiscalQuarter" | "previousFiscalQuarter" | "thisFiscalYear" | "nextFiscalYear" | "previousFiscalYear", CustomFilter<any, LogicFunctionExtraParam>>;

Browser-local datetime registry. AdvanceFilterPlugin installs an isolated per-grid registry.

DATETIME_FILTERS: Record<"datetimeEquals" | "datetimeBefore" | "datetimeAfter" | "datetimeOnOrBefore" | "datetimeOnOrAfter" | "datetimeBetween" | "datetimeNotEqual" | "datetimeIsEmpty" | "datetimeIsNotEmpty" | "datetimeToday" | "datetimeYesterday" | "datetimeLast7Days" | "datetimeNext30Days" | "datetimeThisWeek" | "datetimeLastWeek" | "datetimeNextWeek" | "datetimeThisMonth" | "datetimeLastMonth" | "datetimeThisQuarter" | "datetimeNextQuarter" | "datetimePreviousQuarter" | "datetimeThisYear" | "datetimeNextYear" | "datetimePreviousYear" | "datetimeThisFiscalQuarter" | "datetimeNextFiscalQuarter" | "datetimePreviousFiscalQuarter" | "datetimeThisFiscalYear" | "datetimeNextFiscalYear" | "datetimePreviousFiscalYear", CustomFilter<any, LogicFunctionExtraParam>>;

FILTER_DATETIME: string;

export function isDateFilterOperator(operator: unknown): operator is DateFilterOperator;

Resolves the authored menu order for one date/datetime column.

export function resolveDateFilterOperators(
config?: DateFilterConfig,
prop?: ColumnProp,
): DateFilterOperator[];

export function toDatetimeFilterOperator(operator: DateFilterOperator): DatetimeFilterOperator;

standardDateFilterOperators: readonly ["equals", "before", "after", "onOrBefore", "onOrAfter", "between", "notEqual", "isEmpty", "isNotEmpty", "today", "yesterday", "last7Days", "next30Days", "thisWeek", "lastWeek", "nextWeek", "thisMonth", "lastMonth", "thisQuarter", "nextQuarter", "previousQuarter", "thisYear", "nextYear", "previousYear"];

fiscalDateFilterOperators: readonly ["thisFiscalQuarter", "nextFiscalQuarter", "previousFiscalQuarter", "thisFiscalYear", "nextFiscalYear", "previousFiscalYear"];

filterOperators: readonly ["equals", "before", "after", "onOrBefore", "onOrAfter", "between", "notEqual", "isEmpty", "isNotEmpty", "today", "yesterday", "last7Days", "next30Days", "thisWeek", "lastWeek", "nextWeek", "thisMonth", "lastMonth", "thisQuarter", "nextQuarter", "previousQuarter", "thisYear", "nextYear", "previousYear", "thisFiscalQuarter", "nextFiscalQuarter", "previousFiscalQuarter", "thisFiscalYear", "nextFiscalYear", "previousFiscalYear"];

export type DateFilterOperator = typeof filterOperators[number];

export type DatetimeFilterOperator = `datetime${Capitalize<DateFilterOperator>}`;

export function validateDateFilterConfig(config?: DateFilterConfig);

export function resolveDateFilterSettings(
config?: DateFilterConfig,
prop?: ColumnProp,
): ResolvedDateFilterSettings;

export function detectTemporalFilterFamily(column?: ColumnRegular): TemporalFilterFamily | undefined;

export function temporalFilterFamily(column?: ColumnRegular): TemporalFilterFamily;

export function createTemporalFilters(
runtime: TemporalFilterRuntime,
family: TemporalFilterFamily,
operators: readonly string[],
);

export function getBrowserTimeZone();

Projects an instant into Gregorian civil fields in an IANA timezone.

export function getCivilParts(instant: Date, timeZone: string): CivilDateTime;

Returns every instant represented by a civil second in an IANA timezone.

export function getPossibleInstants(value: CivilDateTime, timeZone: string): Date[];

Period boundaries advance through a timezone gap to its first valid civil instant.

export function resolveCivilBoundary(value: CivilDateTime, timeZone: string): Date;

export function resolveExactCivilInstant(value: CivilDateTime, timeZone: string): Date | undefined;

Validates an IANA timezone at the shared date boundary.

export function assertIanaTimeZone(timeZone: string, label = 'timeZone'): void;

Calendar and clock fields interpreted in a specific IANA timezone.

interface CivilDateTime {
readonly year: number;
readonly month: number;
readonly day: number;
readonly hour: number;
readonly minute: number;
readonly second: number
}

class TemporalFilterRuntime {
configure(config?: DateFilterConfig);
beginRun(referenceInstant = new Date());
/** Calendar date containing this run's captured instant for one resolved column timezone. */
referenceDate(prop?: ColumnProp): ISODateString;
/** Resolves this run's captured instant in an editor-specific timezone. */
referenceDateForTimeZone(timeZone: string): ISODateString;
settings(prop?: ColumnProp);
isValidControl(value: string, family: TemporalFilterFamily, prop?: ColumnProp);
matches(
family: TemporalFilterFamily,
operator: string,
rowValue: unknown,
extra: unknown,
context?: FilterEvaluationContext,
);
buildTransport(
filterItems: MultiFilterItem,
columns: ColumnRegular[],
canonicalAst?: FilterAst,
): TemporalFilterContext;
}

export type TemporalTimeZoneMode = 'user' | 'organization' | 'utc' | 'explicit';

interface FiscalYearStart {
/** One-based calendar month. */
month: number;
day: number
}

interface DateFilterSettings {
timezoneMode?: TemporalTimeZoneMode;
userTimeZone?: string;
organizationTimeZone?: string;
timeZone?: string;
/** Sunday is 0 and Saturday is 6. Defaults to Monday. */
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
fiscalYearStart?: FiscalYearStart;
/** Ordered operator allowlist for this date/datetime menu. */
operators?: readonly DateFilterOperator[]
}

interface DateFilterConfig {
/** Partial settings keyed by column property. */
columns?: Record<string, DateFilterSettings | undefined>
}

interface ResolvedDateFilterSettings {
timezoneMode: TemporalTimeZoneMode;
timeZone: string;
weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6;
fiscalYearStart: FiscalYearStart
}

export type TemporalFilterFamily = 'date' | 'datetime';

interface TemporalResolvedCondition {
family: TemporalFilterFamily;
operator: string;
/** Inclusive UTC boundary. Null means unbounded. */
start: string | null;
/** Exclusive UTC boundary. Null means unbounded. */
endExclusive: string | null
}

interface TemporalColumnContext {
timeZone: string;
timezoneMode: TemporalTimeZoneMode;
/** Calendar semantics required to resolve rolling/aligned remote windows. */
weekStartsOn: ResolvedDateFilterSettings['weekStartsOn'];
fiscalYearStart: FiscalYearStart
}

JSON-safe temporal envelope forwarded with remote filtering.

interface TemporalFilterContext {
referenceInstant: string;
columns: Record<string, TemporalColumnContext>;
/** Entries use `<column property>:<filter id>` or a stable `:ast:<node path>` suffix. */
conditions: Record<string, TemporalResolvedCondition[]>
}

Column filter family for boolean primitive values.

FILTER_BOOLEAN: string;

Operators exposed by the advanced boolean filter family.

/** Operators exposed by the advanced boolean filter family. */
export type BooleanFilterOperator = 'isTrue' | 'isFalse';

Advanced-filter definitions for strict boolean primitive matching.

BOOLEAN_FILTERS: {
isTrue: { columnFilterType: string; name: "Yes"; func: LogicFunction<any, LogicFunctionExtraParam>; };
isFalse: { columnFilterType: string; name: "No"; func: LogicFunction<any, LogicFunctionExtraParam>; };
};

export function booleanFilterCaption(
labels: StructuredFilterLabels,
id: BooleanFilterCaptionId,
): string;

export function booleanFilterMessage(
labels: StructuredFilterLabels,
id: BooleanFilterCaptionId,
values: BooleanFilterMessageValues = {},
): string;

export function booleanFilterFallbackMessage(
id: BooleanFilterCaptionId,
values: BooleanFilterMessageValues = {},
): string;

Stable localization keys and complete English fallbacks for boolean filters.

BOOLEAN_FILTER_LOCALIZATION: Readonly<{ filterNames: Readonly<{ isTrue: "Yes"; isFalse: "No"; triStateBoolean: "Is Yes or No"; }>; captions: Readonly<{ triStateBooleanTitle: "Boolean value"; triStateBooleanDescription: "Show rows by their exact boolean value."; triStateBooleanChoice: "Boolean filter"; triStateBooleanAll: "All"; triStateBooleanYes: "Yes"; triStateBooleanNo: "No"; triStateBooleanBlankTitle: "Treat blank as “No”"; triStateBooleanBlankAriaLabel: "Treat blank as No"; triStateBooleanMatchedRows: "{matched} of {total} rows"; }>; }>;

export type BooleanFilterCaptionId = keyof typeof BOOLEAN_FILTER_LOCALIZATION.captions;

export type BooleanFilterMessageValues = Readonly<Record<string, string | number>>;

Column filter family for array-valued cells.

FILTER_ARRAY: string;

Strict, valueless operators for array-valued cells.

/** Strict, valueless operators for array-valued cells. */
export type ArrayFilterOperator = 'isEmptyArray' | 'isNotEmptyArray';

Advanced-filter definitions for strict array length matching.

ARRAY_FILTERS: {
isEmptyArray: { columnFilterType: string; name: "Is empty array"; func: LogicFunction<any, LogicFunctionExtraParam>; };
isNotEmptyArray: { columnFilterType: string; name: "Is not empty array"; func: LogicFunction<any, LogicFunctionExtraParam>; };
};

Stable localization keys and English fallbacks for strict array operators.

ARRAY_FILTER_LOCALIZATION: Readonly<{ filterNames: Readonly<{ isEmptyArray: "Is empty array"; isNotEmptyArray: "Is not empty array"; }>; }>;

export type SliderRange = { fromValue: number; toValue: number };

interface GroupedFilterPreviewResult {
matching: number;
total: number
}

Options for the opt-in grouped rule-builder UI. Omit groupedFilter from the column filter config to keep grouped view disabled.

interface GroupedFilterConfig {
/** Set for a partially loaded datasource so page rows are never presented as the dataset total. */
remote?: boolean;
/** Optional server-backed exact match count. Superseded edits abort the supplied signal. */
preview?(request: {
ast?: FilterAst;
signal: AbortSignal;
}): GroupedFilterPreviewResult | Promise<GroupedFilterPreviewResult>
}

Options for mounting the canonical grouped Filter AST editor into application UI.

interface FilterAstEditorMountOptions {
/** Defaults to `builder`; explicit config is deeply merged over the preset. */
preset?: FilterAstEditorPreset;
config?: FilterAstEditorConfig;
/** Field selected first when a new condition is added. */
currentProp?: ColumnProp;
/** Called after Cancel restores the latest mounted or applied baseline. */
onCancel?(): void;
/** Direct typed localization overrides for this mounted surface. */
translations?: GroupedFilterTranslationOverrides;
/**
* Predeclared condition slots kept by persistent-condition layouts. The
* effective AST may omit cleared slots without removing them from the UI.
*/
conditionSlots?: readonly FilterAstCondition[];
/** Field/operator-scoped value control overrides for this mounted surface. */
valueEditors?: readonly FilterAstEditorValueEditorOverride[]
}

interface FilterAstEditorSliderValueEditor {
kind: 'slider';
/** Defaults to the minimum finite value in the column source. */
min?: number;
/** Defaults to the maximum finite value in the column source. */
max?: number;
/** Native range step. Defaults to `1`. */
step?: number | 'any';
/** Formats the visible and accessible current-value label. */
formatValue?(value: number): string
}

interface FilterAstEditorValueEditorOverride {
field: ColumnProp;
/** Omit to apply the editor to every compatible operator for the field. */
operator?: FilterAstCondition['operator'];
editor: FilterAstEditorSliderValueEditor
}

export type FilterAstEditorPreset = 'builder' | 'fixed-list' | 'read-only';

export type FilterAstEditorInteractionState = 'editable' | 'read-only' | 'disabled';

interface FilterAstEditorStructureOptions {
shape?: 'tree' | 'flat';
rootOperator?: 'editable' | 'and' | 'or';
incompatibleAst?: 'reject' | 'read-only';
conditionSlots?: 'dynamic' | 'persistent'
}

interface FilterAstEditorTreeCapabilities {
add?: 'conditions-and-groups' | 'conditions' | 'none';
removeCondition?: boolean;
removeGroup?: boolean;
reorder?: 'all' | 'conditions' | 'groups' | 'none';
negate?: boolean;
changeNestedOperator?: boolean
}

interface FilterAstEditorConditionCapabilities {
changeField?: boolean;
changeOperator?: boolean;
changeValue?: boolean;
clear?: boolean;
activateOnValidValue?: boolean;
activateValueless?: boolean
}

interface FilterAstEditorCapabilities {
tree?: FilterAstEditorTreeCapabilities;
condition?: FilterAstEditorConditionCapabilities;
actions?: { apply?: boolean; cancel?: boolean; reset?: boolean; clearAll?: boolean }
}

interface FilterAstEditorHeaderPresentation {
title?: boolean;
description?: boolean
}

interface FilterAstEditorStatusPresentation {
ruleSummary?: boolean;
preview?: boolean
}

interface FilterAstEditorModePresentation {
allowed?: readonly ('rules' | 'text')[];
initial?: 'rules' | 'text';
switch?: boolean
}

interface FilterAstEditorGroupPresentation {
label?: boolean;
rootInstruction?: boolean;
logicControl?: boolean;
actions?: boolean
}

interface FilterAstEditorConditionPresentation {
field?: 'control' | 'label' | 'hidden';
operator?: 'control' | 'label' | 'hidden';
/** Visual treatment for an operator label or editable operator control. */
operatorAppearance?: 'plain' | 'badge';
removeAction?: boolean;
reorderHandle?: boolean;
clearAction?: boolean
}

interface FilterAstEditorFooterPresentation {
apply?: boolean;
cancel?: boolean;
reset?: boolean
}

interface FilterAstEditorPresentation {
header?: false | FilterAstEditorHeaderPresentation;
status?: false | FilterAstEditorStatusPresentation;
mode?: FilterAstEditorModePresentation;
group?: FilterAstEditorGroupPresentation;
condition?: FilterAstEditorConditionPresentation;
footer?: false | FilterAstEditorFooterPresentation;
clearAll?: boolean
}

interface FilterAstEditorWorkflowOptions {
mode?: 'staged' | 'immediate';
debounceMs?: number;
reset?: 'empty' | 'baseline'
}

interface FilterAstEditorConfig {
structure?: FilterAstEditorStructureOptions;
capabilities?: FilterAstEditorCapabilities;
presentation?: FilterAstEditorPresentation;
workflow?: FilterAstEditorWorkflowOptions;
interaction?: FilterAstEditorInteractionState
}

Lifecycle and synchronization handle for an externally mounted Filter AST editor.

interface FilterAstEditorHandle {
/** Replace the editor baseline and discard its current draft without applying it. */
reset(ast?: FilterAst): void;
/** Unmount effects and listeners and release the host. Idempotent. */
destroy(): void
}

Props for the RangeSlider component.

The slider keeps its own visual controls synchronized with optional editable inputs. Use formatInputValue and parseInputValue together when the input text must follow a custom number format, such as comma decimals.

Example:

slider: {
headerView: 'range',
showRangeInputs: true,
formatValue: value => value.toFixed(2),
formatInputValue: value => value.toFixed(2).replace('.', ','),
parseInputValue: value => Number(value.replace(',', '.')),
}
interface RangeSliderProps {
/** Minimum value for the range */
min: number;
/** Maximum value for the range */
max: number;
/** Current value for the start of the range */
fromValue: number;
/** Current value for the end of the range */
toValue: number;
/** Value-domain increment for native range handles. Defaults to the slider's decimal precision. */
step?: number;
/** Whether to show tooltips on hover */
showTooltips?: boolean;
/** Whether to show the current range values above the slider */
showRangeDisplay?: boolean;
/** Whether to show numeric inputs for editing the selected range */
showRangeInputs?: boolean;
/** Disable both native range handles. */
disabled?: boolean;
/** Scaling used to preserve decimals in native range inputs. Defaults to 100. */
scaleFactor?: number;
/** Extra class on the shared slider root. */
className?: string;
/** Extra class on the shared dual-handle control. */
controlClassName?: string;
/** Extra classes retained by feature adapters. */
fromClassName?: string;
toClassName?: string;
/** Accessible names for the two native range handles. */
fromAriaLabel?: string;
toAriaLabel?: string;
/**
* Optional function to format values inside the editable inputs.
* Defaults to `String(value)`, which keeps dot decimals independent of the
* browser's localized number input rendering.
*/
formatInputValue?: (value: number) => string;
/**
* Optional function to parse editable input text back to a number.
* Return `NaN` to ignore incomplete or invalid text while the user is typing.
* The default parser accepts both dot and comma decimal separators.
*/
parseInputValue?: (value: string) => number;
/** Callback fired when the range values change */
onRangeChange: (range: SliderRange) => void;
/** Callback fired when a native handle commits its change. */
onRangeCommit?: (range: SliderRange) => void;
/**
* Optional function to format read-only labels and tooltips.
* Editable inputs use `formatInputValue` so display labels and input text can
* intentionally use different formats.
*/
formatValue?: (value: number) => string;
/** Optional handle-specific display/accessible value formatters. */
formatFromValue?: (value: number) => string;
formatToValue?: (value: number) => string
}

Active column details available while formatting advanced-filter slider labels.

interface SliderFilterFormatContext {
/** Property of the column whose filter popup is open. */
readonly columnProp: ColumnProp;
/** Full owning column definition. */
readonly column: ColumnRegular
}

Header representation used for slider-filter columns.

/** Header representation used for slider-filter columns. */
export type SliderFilterHeaderView = 'slider' | 'range';

SliderFilterConfig (Extended from index.ts)

Section titled “SliderFilterConfig (Extended from index.ts)”

Public slider-filter presentation options. Filtering remains numeric.

/** Public slider-filter presentation options. Filtering remains numeric. */
export type SliderFilterConfig = Omit<
Pick<
RangeSliderProps,
| 'showTooltips'
| 'showRangeDisplay'
| 'showRangeInputs'
| 'formatValue'
| 'formatInputValue'
| 'parseInputValue'
>,
'formatValue'
> & {
/**
* Slider-filter representation rendered by FilterHeaderPlugin.
* Defaults to `slider`; use `range` for a compact formatted from-to summary.
*/
headerView?: SliderFilterHeaderView;
/** Formats the slider section title with access to the active column. */
formatTitle?: (context: SliderFilterFormatContext) => string | undefined;
/** Formats labels and tooltips with access to the active column. */
formatValue?: (value: number, context: SliderFilterFormatContext) => string;
};

export type SelectionItem = {
value: string;
label: string;
[key: string]: any;
};

export type GetItemsFn = (
prop: ColumnProp,
request?: { search?: string; signal?: AbortSignal },
) => Promise<SelectionItem[]> | SelectionItem[];

export type SelectionQuickSearchFilterContext = {
/** Current column prop for the selection filter popup. */
columnProp: ColumnProp;
/** Normalized search text typed into the selection popup. */
search: string;
/** Normalized option value used by selection filtering. */
value: string;
/** Display label for the option. */
label: string;
/** Original item returned by the default option loader or custom `selection.getItems`. */
item: SelectionItem;
};

export type SelectionQuickSearchFilter = (
context: SelectionQuickSearchFilterContext,
) => boolean;

export type SelectionQuickSearchFilterValue = {
search: string;
matchingValues: Set<string>;
};

export type SelectionItemTemplateProps = {
/** Current column prop for the selection filter popup. */
columnProp: ColumnProp;
/** Original item returned by the default option loader or custom `selection.getItems`. */
item: SelectionItem;
/** Normalized option value used by selection filtering. */
value: string;
/** Display label for the option. */
label: string;
/** Whether this option is currently included in the filter result. */
checked: boolean;
/** Whether this option is unavailable in the current cascade context. */
disabled: boolean;
};

export type SelectionItemTemplate = (
h: HyperFunc<VNode>,
props: SelectionItemTemplateProps,
) => any;

Read-only metadata column appended to the selection option grid. Its prop reads from the corresponding SelectionItem, so custom loaders can expose counts, progress, avatars, or any other option-level metadata.

/**
* Read-only metadata column appended to the selection option grid.
* Its `prop` reads from the corresponding `SelectionItem`, so custom loaders
* can expose counts, progress, avatars, or any other option-level metadata.
*/
export type SelectionOptionColumn = ColumnRegular;

export type SelectionOptionProgressContext = SelectionItemTemplateProps;

export type SelectionOptionProgressMaxContext = {
/** Current filtered column property. */
columnProp: ColumnProp;
/** Loaded option items in their current filter-list scope. */
items: readonly SelectionItem[];
/** Finite progress values resolved from those items. */
values: readonly number[];
};

Responsive progress presentation owned by a selection option row.

/** Responsive progress presentation owned by a selection option row. */
export type SelectionOptionProgressConfig = {
/** Item metadata property containing the numeric value. Defaults to `count`. */
valueProp?: ColumnProp;
/** Custom value resolver. Takes precedence over `valueProp`. */
getValue?: (context: SelectionOptionProgressContext) => number;
/** Numeric range minimum. Defaults to zero. */
min?: number;
/** Fixed numeric range maximum. Defaults to the largest loaded option value. */
max?: number;
/** Dynamic range maximum resolver. Takes precedence over `max`. */
getMax?: (context: SelectionOptionProgressMaxContext) => number;
/** Show the formatted value after the progress track. Defaults to true. */
showValue?: boolean;
/** Formats the numeric value displayed after the track. */
formatValue?: (value: number, context: SelectionOptionProgressContext) => string;
/** Accessible name for the progressbar. */
ariaLabel?: string | ((value: number, context: SelectionOptionProgressContext) => string);
};

export type SelectionGridSettings = Partial<{
additionalData: HTMLRevoGridElement['additionalData'];
autoSizeColumn: HTMLRevoGridElement['autoSizeColumn'];
canFocus: HTMLRevoGridElement['canFocus'];
colSize: HTMLRevoGridElement['colSize'];
columnTypes: HTMLRevoGridElement['columnTypes'];
editors: HTMLRevoGridElement['editors'];
frameSize: HTMLRevoGridElement['frameSize'];
hideAttribution: HTMLRevoGridElement['hideAttribution'];
noHorizontalScrollTransfer: HTMLRevoGridElement['noHorizontalScrollTransfer'];
range: HTMLRevoGridElement['range'];
readonly: HTMLRevoGridElement['readonly'];
resize: HTMLRevoGridElement['resize'];
rowDefinitions: HTMLRevoGridElement['rowDefinitions'];
rowHeaders: HTMLRevoGridElement['rowHeaders'];
rowSize: HTMLRevoGridElement['rowSize'];
theme: HTMLRevoGridElement['theme'];
tree: HTMLRevoGridElement['tree'];
useClipboard: HTMLRevoGridElement['useClipboard'];
}>;

export type SelectionCascadeOptionVisibility = 'hide' | 'disable' | 'show';

export type SelectionCascadeConfig = {
/**
* Enables context-aware selection options.
* When true, selection values are calculated from rows matching active filters
* in other columns, excluding the current column filter itself.
*/
enabled?: boolean;
/**
* Controls how values outside the current cascade context are presented.
* - `hide`: omit context-invalid values.
* - `disable`: show context-invalid values with disabled controls.
* - `show`: show every value with interactive controls.
* Defaults to `hide` when cascading is enabled. Existing exclusions are
* preserved in every mode.
*/
optionVisibility?: SelectionCascadeOptionVisibility;
/**
* Shows active filter dependency order badges next to header filter icons.
* Disabled by default. Set to true to show dependency badges.
*/
showDependencyNumbers?: boolean;
};

export type SelectionConfig = {
/**
* Enables the staged Windows Excel-style selection-filter interaction.
* The default selection filter remains unchanged when omitted.
*/
excelMode?: 'windows';
sortDirection?: 'asc' | 'desc' | 'none';
/**
* Opt in to server-backed option search through the second `getItems`
* argument. When omitted, custom items are searched locally so existing
* loaders that ignore the request remain backward compatible.
* A record can opt in individual column properties.
*/
remoteSearch?: boolean | Record<string, boolean>;
/**
* Reuse the owning column's cell template for selection option content.
* Explicit `itemTemplate` renderers take precedence.
* - Pass a boolean to apply it globally to all selection-filter columns.
* - Pass a record keyed by column prop to opt in per column.
*/
syncCellTemplate?: boolean | Record<string, boolean>;
/**
* Row stores used by local filter option and structured-aggregate collectors.
* Defaults to all row stores for backward compatibility. Set to `['rgRow']`
* to derive filter values from the main data source only and ignore pinned rows.
*/
sourceRowTypes?: DimensionRows[];
/**
* Controls whether typing in the selection popup search input also applies a
* hidden `quickSearch` filter to the grid rows.
* Defaults to true for backward compatibility. Set to false to only narrow
* the popup option list while keeping the grid rows unchanged until checkbox
* selection values are changed.
*/
quickSearchFiltering?: boolean;
/**
* Custom matcher for the selection popup quick search.
* Use it when option values are IDs but users should search rendered labels,
* names, or metadata. The same matcher is used to build the hidden grid-row
* quick search when `quickSearchFiltering` is enabled.
* - Pass a function to apply it globally to all selection-filter columns.
* - Pass a record keyed by column prop to override per column.
*/
quickSearchFilter?:
| SelectionQuickSearchFilter
| Record<string, SelectionQuickSearchFilter>;
/**
* Optional grouping for selection filter option rows.
* - Pass a config to apply it globally to all selection-filter columns.
* - Pass a record keyed by column prop to override per column.
*/
grouping?: GroupingOptions | Record<string, GroupingOptions>;
/**
* Provide a custom loader for selection list items.
* - Pass a function to apply it globally to all columns.
* - Pass a record keyed by column prop to override per column;
* columns without an entry fall back to the default store-based lookup.
*/
getItems?: GetItemsFn | Record<string, GetItemsFn>;
/**
* Custom renderer for selection option content.
* The plugin still renders and controls the checkbox; this template replaces
* the label content next to it, so icons and custom item metadata can be shown
* without changing selection semantics.
* - Pass a function to apply it globally to all columns.
* - Pass a record keyed by column prop to override per column.
*/
itemTemplate?: SelectionItemTemplate | Record<string, SelectionItemTemplate>;
/**
* Additional read-only columns rendered after the owned checkbox/label column.
* Pass an array globally or a record keyed by the filtered column prop.
*/
optionColumns?: SelectionOptionColumn[] | Record<string, SelectionOptionColumn[]>;
/**
* Renders a responsive progress track and value inside the selection-owned option row.
* Pass one config globally or a record keyed by filtered column prop; use `false` to
* suppress a global/per-column entry.
*/
optionProgress?:
| SelectionOptionProgressConfig
| Record<string, SelectionOptionProgressConfig | false>;
/**
* Custom plugins for the nested selection option grid.
* - Pass an array to apply it globally to all selection-filter columns.
* - Pass a record keyed by column prop to override per column.
*/
plugins?: GridPlugin[] | Record<string, GridPlugin[]>;
/**
* Optional settings for the nested selection option grid.
* `source`, `columns`, and `grouping` stay controlled by the filter list.
* - Pass an object to apply it globally to all selection-filter columns.
* - Pass a record keyed by column prop to override per column.
*/
gridSettings?: SelectionGridSettings | Record<string, SelectionGridSettings>;
/**
* Optional context-aware option loading for selection filters.
*/
cascadeOptions?: SelectionCascadeConfig;
};

export type FilterPopupHeaderConfig = {
/**
* Hide the advanced filter popup header.
*/
hidden?: boolean;
};

Selection filter type

FIlTER_SELECTION: "none" | "empty" | "notEmpty" | "eq" | "notEq" | "begins" | "contains" | "notContains" | "eqN" | "neqN" | "gt" | "gte" | "lt" | "lte";

Quick search filter type

FIlTER_QUICK_SEARCH: "none" | "empty" | "notEmpty" | "eq" | "notEq" | "begins" | "contains" | "notContains" | "eqN" | "neqN" | "gt" | "gte" | "lt" | "lte";

Slider filter type

FIlTER_SLIDER: "none" | "empty" | "notEmpty" | "eq" | "notEq" | "begins" | "contains" | "notContains" | "eqN" | "neqN" | "gt" | "gte" | "lt" | "lte";

Hidden Pro expression filter type.

FIlTER_EXPRESSION: "none" | "empty" | "notEmpty" | "eq" | "notEq" | "begins" | "contains" | "notContains" | "eqN" | "neqN" | "gt" | "gte" | "lt" | "lte";

Cancelable event emitted before a row contributes selection options or slider bounds.

BEFORE_FILTER_OPTION_SOURCE_ROW_EVENT: string;

Mutable value-resolution event emitted while advanced filter options are collected.

BEFORE_FILTER_OPTION_VALUE_EVENT: string;

BEFORE_QUICK_FILTER_APPLY_EVENT: string;

AFTER_QUICK_FILTER_APPLY_EVENT: string;

FILTER_AST_CHANGE_EVENT: string;

FILTER_AST_ERROR_EVENT: string;

interface QuickFilterApplyEventDetail {
quickFilter?: QuickFilter;
source: DataType[];
columns: ColumnRegular[]
}

export type FilterOptionSourceRowEventDetail = {
row: DataType;
};

export type FilterOptionValueEventDetail = {
row: DataType;
column: ColumnRegular;
rowType?: DimensionRows;
rowIndex?: number;
value: unknown;
};

export type ProFilterItemsChangeDetail = {
prop: ColumnProp;
multiFilterItems: MultiFilterItem;
};

export type ProFilterItemsChangeListener = (detail: ProFilterItemsChangeDetail) => void;

export type ProFilterItemsChangeSubscription = (
listener: ProFilterItemsChangeListener,
) => () => void;

class AdvancedFilterBadgesController {
getItems(): readonly AdvancedFilterBadgeItem[];
refresh();
async clear();
destroy();
}

export function filterBadgesCaption(
captions: FilterBadgesCaptions | undefined,
id: FilterBadgesCaptionId,
): string;

export function filterBadgesMessage(
captions: FilterBadgesCaptions | undefined,
id: FilterBadgesCaptionId,
values: Readonly<Record<string, string | number>>,
): string;

Stable localization keys and English fallbacks for active-filter badges.

FILTER_BADGES_LOCALIZATION: Readonly<{ captions: Readonly<{ filterBadgesAriaLabel: "Active filters"; filterBadgesEmpty: "No active filters"; filterBadgesShowDetails: "Show details for {label}"; filterBadgesRemove: "Remove {label} filter"; filterBadgesRelationAnd: "AND"; filterBadgesRelationOr: "OR"; filterBadgesExcludedCount: "{count} excluded"; filterBadgesValueCountOne: "{count} value"; filterBadgesValueCountMany: "{count} values"; filterBadgesExcludedValues: "Excluded values: {values}"; filterBadgesValues: "Values: {values}"; filterBadgesNone: "None"; filterBadgesNotSet: "Not set"; filterBadgesYes: "Yes"; filterBadgesNo: "No"; filterBadgesItemCountOne: "{count} item"; filterBadgesItemCountMany: "{count} items"; filterBadgesConfigured: "Configured"; }>; }>;

export type FilterBadgesCaptionId = keyof typeof FILTER_BADGES_LOCALIZATION.captions;

export type FilterBadgesCaptions = Partial<Record<FilterBadgesCaptionId, string>>;

export type AdvancedFilterBadgeRenderValue = Node | string | number | null | undefined
| readonly AdvancedFilterBadgeRenderValue[];

interface AdvancedFilterBadgeFormatContext {
prop: ColumnProp;
filter: FilterData;
index: number;
column?: ColumnRegular;
operatorName: string
}

interface AdvancedFilterBadgePresentation {
/** Compact value summary. The controller adds the column name. */
summary: string;
/** Complete plain-text explanation shown through the info control. */
details?: string
}

AdvancedFilterBadgeItem (Extended from index.ts)

Section titled “AdvancedFilterBadgeItem (Extended from index.ts)”
interface AdvancedFilterBadgeItem {
key: string;
label: string;
details?: string;
remove: () => Promise<void>;
readOnly: boolean
}

interface AdvancedFilterBadgeRenderContext {
item: AdvancedFilterBadgeItem;
remove: () => Promise<void>
}

interface AdvancedFilterBadgesRenderContext {
items: readonly AdvancedFilterBadgeItem[];
clear: () => Promise<void>;
root: HTMLElement;
readOnly: boolean
}

interface AdvancedFilterBadgesSlots {
/** Content rendered before the plugin-owned badge list. */
start?: (context: AdvancedFilterBadgesRenderContext) => AdvancedFilterBadgeRenderValue;
/** Content rendered after the plugin-owned badge list. */
end?: (context: AdvancedFilterBadgesRenderContext) => AdvancedFilterBadgeRenderValue
}

interface AdvancedFilterBadgesOptions {
/** Extra class names added to the list root. */
className?: string;
/** Extra class names added to each default badge. */
badgeClassName?: string;
/** Extra class names added to each default remove button. */
removeButtonClassName?: string;
/** Extra class names added to the default empty state. */
emptyClassName?: string;
ariaLabel?: string;
emptyLabel?: string;
/** Localized default labels and message templates used by the built-in badge renderer. */
captions?: FilterBadgesCaptions;
removeAriaLabel?: (item: AdvancedFilterBadgeItem) => string;
detailsAriaLabel?: (item: AdvancedFilterBadgeItem) => string;
formatLabel?: (context: AdvancedFilterBadgeFormatContext) => string;
formatDetails?: (context: AdvancedFilterBadgeFormatContext) => string | undefined;
/** Rich content for the label shell. Strings are always appended as text. */
renderBadge?: (context: AdvancedFilterBadgeRenderContext) => AdvancedFilterBadgeRenderValue;
/** Replaces the default empty-state content. */
renderEmpty?: (context: AdvancedFilterBadgesRenderContext) => AdvancedFilterBadgeRenderValue;
/** Replaces the complete list rendering while retaining filter actions. */
render?: (context: AdvancedFilterBadgesRenderContext) => AdvancedFilterBadgeRenderValue;
/** Content slots around the plugin-owned badge list. */
slots?: AdvancedFilterBadgesSlots;
onChange?: (items: readonly AdvancedFilterBadgeItem[]) => void
}

Enables the plugin-owned active-filter badge list.

/** Enables the plugin-owned active-filter badge list. */
export type AdvancedFilterBadgesConfig = boolean | AdvancedFilterBadgesOptions;

@internal Source adapter owned by AdvanceFilterPlugin.

interface AdvancedFilterBadgesSource {
grid: HTMLRevoGridElement;
getFilterItems: () => MultiFilterItem;
getColumns: () => ColumnRegular[];
getOperatorName: (filter: FilterData) => string;
getPresentation?: (context: AdvancedFilterBadgeFormatContext) => AdvancedFilterBadgePresentation | undefined;
isReadOnly?: () => boolean;
applyFilterItems: (items: MultiFilterItem) => void | Promise<void>;
subscribeFilterItemsChange: (listener: () => void) => () => void
}

export function filterCaption(
captions: FilterCaptionSource | undefined,
id: FilterCaptionId,
): string;

export function filterMessage(
captions: FilterCaptionSource | undefined,
id: FilterCaptionId,
values: Readonly<Record<string, string | number>>,
): string;

Stable localization keys and English fallbacks shared by filter surfaces.

FILTER_LOCALIZATION: Readonly<{ captions: Readonly<{ structuredFilterHeaderPlaceholder: "Choose…"; filterHeaderSearch: "Search…"; filterHeaderAnyDate: "Any date"; filterHeaderEither: "Either"; filterHeaderAnyItem: "Any item"; filterHeaderAnyValue: "Any value"; selectionAll: "All"; popupHeaderTitle: "Filter"; popupHeaderSeparator: "·"; popupHeaderActive: "Active"; popupHeaderClose: "Close filter"; popupConditionClear: "Clear {label}"; sliderTitle: "Select range"; 'filter.value.blank': "Blank"; 'filter.value.empty': "Empty"; 'filter.value.true': "True"; 'filter.value.false': "False"; 'filter.value.unsupported': "Unsupported value"; 'filter.value.more': "+{count} more"; }>; }>;

export type FilterCaptionId = keyof typeof FILTER_LOCALIZATION.captions;

export function expressionDiagnostic(
id: ExpressionDiagnosticId,
values: Readonly<Record<string, string | number>> = {},
);

Stable localization keys and English fallbacks for expression filtering.

EXPRESSION_FILTER_LOCALIZATION: Readonly<{ filterNames: Readonly<{ expression: "Expression"; }>; captions: Readonly<{ expressionButton: "Expression"; expressionTitle: "Filter expression"; expressionApply: "Apply"; expressionErrorTooltip: "Expression error details"; expressionValid: "Parsed"; expressionSuggestions: "Expression suggestions"; expressionPlaceholder: string; }>; diagnostics: Readonly<{ unexpectedToken: "Unexpected token \"{token}\"."; expectedClosingParenthesis: "Expected closing parenthesis."; expectedFilterOperator: "Expected a filter operator."; expectedFilterValue: "Expected a filter value."; expectedBetweenAnd: "Expected \"and\" in a between expression."; expectedUpperBound: "Expected the upper bound value."; expectedStructuredPayload: "Expected a structured filter payload."; expectedStructuredField: "Expected a structured value field."; expectedColonAfterField: "Expected \":\" after \"{field}\"."; expectedStructuredFieldValue: "Expected a value for \"{field}\"."; expectedStructuredClosingBrace: "Expected closing brace for structured value."; expectedArrayValue: "Expected an array value."; expectedStructuredClosingBracket: "Expected closing bracket for structured value."; expectedListValue: "Expected a list value."; expectedValueListClosingParenthesis: "Expected closing parenthesis for value list."; unclosedString: "Unclosed string literal."; unexpectedCharacter: "Unexpected character \"{character}\"."; invalidStructuredExpression: "Invalid structured filter expression."; invalidStructuredPayload: "Invalid structured filter payload."; unavailableSelectionValue: "Expression contains a selection value that is not available for this column."; currentColumnOnly: "Expression can only reference the current column \"{column}\"."; unsupportedOperator: "Unsupported expression operator \"{operator}\"."; numericUnavailable: "Numeric operators are not available for this column."; dateUnavailable: "Date operators are not available for this column."; betweenUnavailable: "Between expressions require number, slider, or date filters for this column."; selectionUnavailable: "Selection operators require the selection filter for this column."; arrayUnavailable: "Array operators require the array filter for this column."; unknownColumn: "Unknown column reference \"{column}\"."; ambiguousColumn: "Column reference \"{column}\" matches more than one column. Use its property instead."; unknownFunction: "Unsupported expression function \"{function}\"."; expectedFunctionColumn: "Function \"{function}\" expects one column reference."; expectedFunctionClosingParenthesis: "Expected closing parenthesis after function \"{function}\"."; aggregateUnavailable: "Function \"{function}\" cannot be evaluated because column data is unavailable."; }>; }>;

export type ExpressionDiagnosticId = keyof typeof EXPRESSION_FILTER_LOCALIZATION.diagnostics;

export function selectionFilterCaption(
captions: SelectionCaptions | undefined,
id: SelectionFilterCaptionId,
): string;

Stable localization keys and English fallbacks for selection filters.

SELECTION_FILTER_LOCALIZATION: Readonly<{ captions: Readonly<{ selectionApply: "Apply"; selectionCancel: "Cancel"; selectionSelectAll: "(Select All)"; selectionSelectAllSearchResults: "(Select All Search Results)"; selectionAddCurrentSelection: "Add current selection to filter"; selectionInvertVisible: "Invert visible"; selectionInvertVisibleAria: "Invert the visible values"; selectionBlanks: "(Blanks)"; selectionEmpty: "Empty"; selectionSearchPlaceholder: "Search..."; selectionSearchAria: "Search values"; selectionSelectAllAria: "Select all values"; }>; }>;

export type SelectionFilterCaptionId = keyof typeof SELECTION_FILTER_LOCALIZATION.captions;

Stable English filter-name fallbacks for date and datetime operators.

TEMPORAL_FILTER_LOCALIZATION: Readonly<{ filterNames: Readonly<{ equals: "Equals"; before: "Before"; after: "After"; onOrBefore: "On or before"; onOrAfter: "On or after"; between: "Between"; notEqual: "Not equal"; isEmpty: "Is blank"; isNotEmpty: "Is not blank"; today: "Today"; yesterday: "Yesterday"; last7Days: "Last 7 days"; next30Days: "Next 30 days"; thisWeek: "This week"; lastWeek: "Last week"; nextWeek: "Next week"; thisMonth: "This month"; lastMonth: "Last month"; thisQuarter: "This quarter"; nextQuarter: "Next quarter"; previousQuarter: "Previous quarter"; thisYear: "This year"; nextYear: "Next year"; previousYear: "Previous year"; thisFiscalQuarter: "This fiscal quarter"; nextFiscalQuarter: "Next fiscal quarter"; previousFiscalQuarter: "Previous fiscal quarter"; thisFiscalYear: "This fiscal year"; nextFiscalYear: "Next fiscal year"; previousFiscalYear: "Previous fiscal year"; }>; captions: Readonly<{ rangeFrom: "From"; rangeTo: "To"; }>; }>;

export type TemporalFilterNameId = keyof typeof TEMPORAL_FILTER_LOCALIZATION.filterNames;

export function normalizeQuickFilterText(text: unknown): string;

export function normalizeQuickFilterInput(
input?: QuickFilterInput,
): NormalizedQuickFilterInput;

export function isSameQuickFilterInput(
previous: NormalizedQuickFilterInput,
next: NormalizedQuickFilterInput,
);

export function normalizeQuickFilterValue(value: unknown): string;

Compile global search into ANDed tokens containing per-field OR conditions.

export function quickFilterToFilterAst(
quickFilter: QuickFilter | undefined,
columns: QuickFilterColumn[],
): FilterAst | undefined;

export function rowMatchesQuickFilter(
row: DataType,
quickFilter: QuickFilter,
columns: QuickFilterColumn[],
): boolean;

DEFAULT_QUICK_FILTER_DEBOUNCE_MS: 150;

export type QuickFilterInput =
| string
| {
text: string;
columns?: ColumnProp[];
debounceMs?: number;
};

Normalized, transport-safe quick-filter payload.

interface QuickFilter {
text: string;
columns?: ColumnProp[]
}

interface NormalizedQuickFilterInput {
quickFilter?: QuickFilter;
debounceMs: number
}

interface QuickFilterColumn {
prop: ColumnProp;
column?: ColumnRegular;
getValue?: (row: DataType) => unknown
}

export type FilterAstPrimitive = string | number | boolean | null;

export type FilterAstValue = FilterAstPrimitive | FilterAstValue[] | { [key: string]: FilterAstValue };

export type FilterAstValueType =
| 'string'
| 'number'
| 'boolean'
| 'date'
| 'datetime'
| 'array'
| 'unknown';

export type FilterAstGroupOperator = 'and' | 'or';

export type FilterAstEvaluationMode =
| 'selectionExclusion'
| 'selectionMembership'
| 'dateObject'
| 'coercedNumericRange'
| 'localTemporal';

interface FilterAstCondition {
type: 'condition';
field: ColumnProp;
operator: FilterAstOperator;
valueType: FilterAstValueType;
value?: FilterAstValue;
/** Optional evaluator behavior required by the condition's input representation. */
evaluationMode?: FilterAstEvaluationMode
}

interface FilterAstGroup {
type: 'group';
operator: FilterAstGroupOperator;
children: FilterAst[]
}

interface FilterAstNot {
type: 'not';
child: FilterAst
}

export type FilterAst = FilterAstCondition | FilterAstGroup | FilterAstNot;

export type FilterAstOperator =
| 'equal'
| 'notEqual'
| 'beginsWith'
| 'contains'
| 'quickContains'
| 'notContains'
| 'greaterThan'
| 'greaterThanOrEqual'
| 'lessThan'
| 'lessThanOrEqual'
| 'between'
| 'in'
| 'notIn'
| 'isBlank'
| 'isNotBlank'
| 'isTrue'
| 'isFalse'
| 'isEmptyArray'
| 'isNotEmptyArray'
| 'dateEquals'
| 'dateBefore'
| 'dateAfter'
| 'dateOnOrBefore'
| 'dateOnOrAfter'
| 'dateBetween'
| 'dateNotEqual'
| 'today'
| 'yesterday'
| 'last7Days'
| 'next30Days'
| 'thisWeek'
| 'lastWeek'
| 'nextWeek'
| 'thisMonth'
| 'lastMonth'
| 'thisQuarter'
| 'nextQuarter'
| 'previousQuarter'
| 'thisYear'
| 'nextYear'
| 'previousYear'
| 'thisFiscalQuarter'
| 'nextFiscalQuarter'
| 'previousFiscalQuarter'
| 'thisFiscalYear'
| 'nextFiscalYear'
| 'previousFiscalYear'
| (string & {});

interface FilterExecutionContext {
/** One instant captured for the entire apply operation. */
now: string;
/** Default IANA timezone used by relative-date adapters. */
timeZone: string;
/** Effective JSON-safe blank policy by column property for remote evaluators. */
blankSemantics?: Record<string, {
null: boolean;
undefined: boolean;
emptyString: boolean;
whitespaceOnlyString: boolean;
emptyArray: boolean;
missingProperty: boolean;
/** True when the application also uses a non-serializable `isBlank` callback. */
customEvaluator: boolean;
}>
}

export type FilterAstOrigin = 'config' | 'api' | 'ui' | 'quickFilter' | 'clear';

interface FilterAstDiagnostic {
code: string;
message: string;
path: string
}

interface FilterAstChangeEventDetail {
filterAst?: FilterAst;
executionContext: FilterExecutionContext;
origin: FilterAstOrigin;
projectable: boolean
}

interface FilterAstErrorEventDetail {
attemptedAst?: unknown;
diagnostics: FilterAstDiagnostic[];
origin: FilterAstOrigin
}

export type FilterAstCustomEvaluators = Record<string, LogicFunction>;

CANONICAL_FILTER_OPERATORS: Set<FilterAstOperator>;

VALUELESS_FILTER_AST_OPERATORS: Set<FilterAstOperator>;

ARRAY_VALUE_FILTER_AST_OPERATORS: Set<FilterAstOperator>;

FILTER_TYPE_TO_AST_OPERATOR: {
eq: string;
eqN: string;
is: string;
notEq: string;
neqN: string;
begins: string;
contains: string;
notContains: string;
gt: string;
gte: string;
lt: string;
lte: string;
empty: string;
isEmpty: string;
notEmpty: string;
isNotEmpty: string;
isTrue: string;
isFalse: string;
isEmptyArray: string;
isNotEmptyArray: string;
equals: string;
before: string;
after: string;
onOrBefore: string;
onOrAfter: string;
notEqual: string;
today: string;
yesterday: string;
last7Days: string;
next30Days: string;
thisWeek: string;
lastWeek: string;
nextWeek: string;
thisMonth: string;
lastMonth: string;
thisQuarter: string;
nextQuarter: string;
previousQuarter: string;
thisYear: string;
nextYear: string;
previousYear: string;
thisFiscalQuarter: string;
nextFiscalQuarter: string;
previousFiscalQuarter: string;
thisFiscalYear: string;
nextFiscalYear: string;
previousFiscalYear: string;
};

AST_TO_FILTER_TYPE: {
equal: string;
notEqual: string;
beginsWith: string;
contains: string;
notContains: string;
greaterThan: string;
greaterThanOrEqual: string;
lessThan: string;
lessThanOrEqual: string;
isBlank: string;
isNotBlank: string;
isTrue: string;
isFalse: string;
isEmptyArray: string;
isNotEmptyArray: string;
dateEquals: string;
dateBefore: string;
dateAfter: string;
dateOnOrBefore: string;
dateOnOrAfter: string;
dateNotEqual: string;
today: string;
yesterday: string;
last7Days: string;
next30Days: string;
thisWeek: string;
lastWeek: string;
nextWeek: string;
thisMonth: string;
lastMonth: string;
thisQuarter: string;
nextQuarter: string;
previousQuarter: string;
thisYear: string;
nextYear: string;
previousYear: string;
thisFiscalQuarter: string;
nextFiscalQuarter: string;
previousFiscalQuarter: string;
thisFiscalYear: string;
nextFiscalYear: string;
previousFiscalYear: string;
};

export function validateFilterAst(
ast: unknown,
customEvaluators: FilterAstCustomEvaluators = {},
): FilterAstValidationResult;

export function cloneFilterAst(ast?: FilterAst): FilterAst | undefined;

export function normalizeFilterAstValue(value: unknown, ancestors = new Set<object>()): FilterAstValue | undefined;

interface FilterAstValidationResult {
valid: boolean;
diagnostics: FilterAstDiagnostic[]
}

export function filterAstDiagnostic(
id: FilterAstDiagnosticId,
values: Readonly<Record<string, string | number>> = {},
);

Stable English fallbacks for canonical filter-AST validation diagnostics.

FILTER_AST_LOCALIZATION: Readonly<{ diagnostics: Readonly<{ invalidNode: "Filter AST nodes must be objects."; maxDepth: "Filter AST nesting cannot exceed 100 levels."; cycle: "Filter AST must not contain cycles."; invalidGroupOperator: "Group operator must be \"and\" or \"or\"."; emptyGroup: "Filter groups must contain at least one child."; missingChild: "Not nodes require exactly one child."; invalidDiscriminator: "Node type must be \"condition\", \"group\", or \"not\"."; invalidField: "Condition field must be a ColumnProp string or number."; invalidOperator: "Condition operator must be a non-empty string."; unknownOperator: "Unknown filter operator \"{operator}\"."; invalidValueType: "Condition valueType is not recognized."; unexpectedValue: "Operator \"{operator}\" does not accept a value."; missingValue: "Operator \"{operator}\" requires a value."; invalidArrayValue: "Operator \"{operator}\" requires {requirement}."; valueTypeMismatch: "Condition value does not match valueType \"{valueType}\"."; nonFiniteNumber: "AST numbers must be finite."; nonJsonValue: "AST values must be JSON-safe."; valueCycle: "AST values must not contain cycles."; nonPlainObject: "AST object values must be plain JSON objects."; }>; }>;

export type FilterAstDiagnosticId = keyof typeof FILTER_AST_LOCALIZATION.diagnostics;

export function multiFilterItemsToFilterAst(
filterItems: MultiFilterItem,
columns: ColumnRegular[] = [],
): FilterAst | undefined;

export function expressionAstToFilterAst(
ast: ExpressionAst,
currentField: ColumnProp,
column?: ColumnRegular,
columns: ColumnRegular[] = column ? [column] : [],
): FilterAst;

export function filterTypeToAstOperator(
type: string,
valueType: FilterAstValueType = 'unknown',
): FilterAstOperator;

export function inferFilterAstValueType(
column: ColumnRegular | undefined,
operator: string,
value: unknown,
): FilterAstValueType;

export function projectFilterAstToMultiFilterItems(
ast?: FilterAst,
customOperators: ReadonlySet<string> = new Set(),
): FilterAstProjection;

export function collectFilterAstFields(ast?: FilterAst, fields = new Set<string>()): Set<string>;

Removes one field’s conditions while preserving the remaining boolean tree.

export function omitFilterAstField(ast: FilterAst | undefined, field: ColumnProp): FilterAst | undefined;

Read-only flattened model used only to keep application badges visible for arbitrary trees.

export function filterAstToBadgeItems(ast?: FilterAst): MultiFilterItem;

export function combineFilterAsts(operator: 'and' | 'or', asts: (FilterAst | undefined)[]): FilterAst | undefined;

interface FilterAstProjection {
projectable: boolean;
multiFilterItems: MultiFilterItem;
fields: Set<string>
}

export function compileFilterAst(ast: FilterAst, options: CompileFilterAstOptions): CompiledFilterAst;

interface CompileFilterAstOptions {
columns: ColumnRegular[];
operators: Record<string, LogicFunction>;
customEvaluators?: FilterAstCustomEvaluators;
blankSemantics?: BlankSemantics;
getQuickFilterValue?: (row: DataType, column: ColumnRegular) => unknown
}

interface CompiledFilterAst {
matches(row: DataType): boolean
}

export type StructuredFilterAggregateScope = 'all' | 'visible';

export type StructuredFilterAggregateNeed = 'values' | 'uniqueValues' | 'valueCounts' | 'numericRange';

interface StructuredFilterValueCount {
readonly value: unknown;
readonly count: number
}

interface StructuredFilterNumericRange {
readonly values: readonly number[];
readonly count: number;
readonly min?: number;
readonly max?: number
}

interface StructuredFilterAggregateResultMap {
values: readonly unknown[];
uniqueValues: readonly unknown[];
valueCounts: readonly StructuredFilterValueCount[];
numericRange: StructuredFilterNumericRange
}

interface StructuredFilterAggregateProviderRequest {
readonly typeId: string;
readonly column: ColumnRegular;
readonly need: StructuredFilterAggregateNeed;
readonly scope: StructuredFilterAggregateScope
}

Supplies complete, server-produced aggregate data for remote or partially loaded grids. Return undefined to use the provider-backed local-row fallback for that request. Keep results immutable for the lifetime of the open popup.

interface StructuredFilterAggregateProvider {
/** Prevent page-local fallback when this provider represents a partial remote row source. */
readonly complete?: boolean;
get(
request: StructuredFilterAggregateProviderRequest,
): StructuredFilterAggregateResultMap[StructuredFilterAggregateNeed] | undefined;
/** Optional compact, type-specific model (for example server-binned histogram data). */
getPrepared?(request: {
readonly typeId: string;
readonly column: ColumnRegular;
}): unknown
}

interface StructuredFilterAggregateAccess {
get<K extends StructuredFilterAggregateNeed>(
need: K,
scope?: StructuredFilterAggregateScope,
): StructuredFilterAggregateResultMap[K]
}

interface StructuredFilterLabels {
operator(operatorId: string): string;
caption(captionId: string, fallback: string): string
}

Text-only condition presentation used by compact, non-editor surfaces.

interface StructuredFilterConditionPresentation {
/** Short value summary; the consuming surface adds the column name. */
readonly summary: string;
/** Optional value-first summary used by the grouped editor's full-width cell. */
readonly groupedSummary?: string;
/** Optional complete human-readable explanation exposed by an info control. */
readonly details?: string
}

interface StructuredFilterPresentationContext {
readonly condition: Readonly<StructuredFilterOwnedCondition>;
readonly column: ColumnRegular;
readonly config?: ColumnFilterConfig;
readonly labels: StructuredFilterLabels;
readonly dateSettings?: ResolvedDateFilterSettings
}

export type StructuredFilterHeaderPlaceholderContext = Omit<
StructuredFilterPresentationContext,
'condition'
>;

Optional finite-selection metadata consumed by the shared filter-header ratio badge.

interface StructuredFilterHeaderSelection {
readonly values: readonly FilterHeaderTemplateValue[];
readonly totalCount: number
}

StructuredFilterHeaderSelectionContext (Extended from index.ts)

Section titled “StructuredFilterHeaderSelectionContext (Extended from index.ts)”
interface StructuredFilterHeaderSelectionContext {
/** Aggregate access is present when the type declares aggregate needs. */
readonly aggregates?: StructuredFilterAggregateAccess
}

StructuredFilterOwnedCondition (Extended from index.ts)

Section titled “StructuredFilterOwnedCondition (Extended from index.ts)”
export type StructuredFilterOwnedCondition = Omit<FilterData, 'type'> & { type: string };

StructuredFilterCondition (Extended from index.ts)

Section titled “StructuredFilterCondition (Extended from index.ts)”
export type StructuredFilterCondition = Omit<StructuredFilterOwnedCondition, 'id'> & {
id?: FilterData['id'];
};

interface StructuredFilterBodyContext {
readonly h: HyperFunc<VNode>;
readonly typeId: string;
readonly column: ColumnRegular;
/** Current filter configuration for structured types with per-column options. */
readonly config?: ColumnFilterConfig;
readonly conditions: readonly Readonly<StructuredFilterOwnedCondition>[];
readonly labels: StructuredFilterLabels;
/** Resolved per-column temporal settings for date-aware bodies. */
readonly dateSettings?: ResolvedDateFilterSettings;
/** Civil date resolved from this run's captured instant in this column's timezone. */
readonly dateReferenceDate?: ISODateString;
/** Resolves the same captured instant in a structured editor's own timezone override. */
readonly dateReferenceDateForTimeZone?: (timeZone: string) => ISODateString;
readonly aggregates?: StructuredFilterAggregateAccess;
/** Compact editor-ready data supplied by a remote aggregate provider. */
readonly preparedData?: unknown;
replaceConditions(conditions: readonly StructuredFilterCondition[]): Promise<void>;
commit(conditions: readonly StructuredFilterCondition[]): Promise<void>
}

interface StructuredFilterType {
/** Stable id selected through a column's existing `filter` field. */
readonly id: string;
/** Ordinary operator ids this body may emit and owns. */
readonly operatorIds: readonly string[];
/** Canonical predicate intent used by compact grouped-editor labels. Transport ids stay unchanged. */
readonly groupedOperatorSemantics?: Readonly<Record<string, FilterAstOperator>>;
/** Close the grouped value popover after this type commits a complete pick. */
readonly groupedEditorCloseOnCommit?: boolean;
/** Provider-backed projections made available lazily to the body. */
readonly aggregateNeeds?: readonly StructuredFilterAggregateNeed[];
/** Validates a canonical condition operand before it can replace active state. */
readonly validateValue?: (value: unknown, operatorId: string) => boolean;
/** Mounts the same interactive body in alternate grid-owned surfaces. */
readonly mount?: (host: HTMLElement, context: StructuredFilterBodyContext) => void | (() => void);
/** Popup body renderer; popup chrome and lifecycle remain grid-owned. */
readonly render: (context: StructuredFilterBodyContext) => VNode | VNode[] | null | undefined;
/**
* Resolves this type's default filter-header control. Static popup visuals can
* be declared directly; interactive controls can use the body context to
* inspect aggregates and replace their owned conditions.
*/
readonly headerControl?: FilterHeaderControl | (
(context: StructuredFilterBodyContext) => FilterHeaderControl | undefined
);
/** Short inactive text for compact filter headers. The column title is already shown above it. */
readonly headerPlaceholder?: string | ((
context: StructuredFilterHeaderPlaceholderContext
) => string);
/** Describes the type-owned value without leaking its transport representation. */
readonly describeCondition?: (
context: StructuredFilterPresentationContext,
) => StructuredFilterConditionPresentation | undefined;
/** Describes a finite selection without coupling the header to one structured filter type. */
readonly getHeaderSelection?: (
context: StructuredFilterHeaderSelectionContext,
) => StructuredFilterHeaderSelection | undefined
}

class StructuredFilterTypeRegistry {
register(type: StructuredFilterType);
unregister(id: string);
get(id: string);
getByOperator(operatorId: string);
values();
clear();
resolve(filter?: boolean | string | string[]);
}

export function replaceStructuredFilterConditions(
items: MultiFilterItem,
prop: ColumnProp,
operatorIds: readonly string[],
replacements: readonly StructuredFilterCondition[],
);

Creates one lazy value/aggregate cache for one popup body render.

export function createStructuredFilterAggregateAccess({
typeId,
column,
dataStores,
sourceRowTypes,
needs,
isSourceRow,
getValue,
isVisibleRow,
provider,
sourceValueCache,
}: StructuredFilterAggregateOptions): StructuredFilterAggregateAccess;

interface StructuredFilterAggregateOptions {
readonly typeId: string;
readonly column: ColumnRegular;
readonly dataStores: RowDataSources;
/** Row stores allowed to contribute local values. Undefined preserves all-store behavior. */
readonly sourceRowTypes?: readonly DimensionRows[];
readonly needs: readonly StructuredFilterAggregateNeed[];
readonly isSourceRow: (row?: DataType) => boolean;
readonly getValue: (
row: DataType,
column: ColumnRegular,
rowType?: DimensionRows,
rowIndex?: number,
) => unknown;
/** Local visible-scope predicate with the current aggregate column excluded. */
readonly isVisibleRow?: (
row: DataType,
rowType: DimensionRows,
rowIndex: number,
) => boolean;
readonly provider?: StructuredFilterAggregateProvider;
/** Popup-scoped raw values shared by aggregate families for the same column and scope. */
readonly sourceValueCache?: Map<string, readonly unknown[]>
}

export function structuredFilterSection(title: string, content: VNode | VNode[], description?: string);

export function structuredFilterLabel(text: string, control: VNode);

export function structuredFilterTextInput(options: {
value?: string;
placeholder?: string;
ariaLabel: string;
invalid?: boolean;
onInput(value: string, event: InputEvent): void;
});

export function structuredFilterButton(options: {
label: string;
pressed?: boolean;
disabled?: boolean;
onClick(event: MouseEvent): void;
});

export function structuredFilterInlineError(message: string);

Builds the operator-owned runtime shared by the regular and grouped filter surfaces.

export function createStructuredFilterBodyContext({
type,
column,
conditions,
options,
replace,
commit = replace,
}: {
type: StructuredFilterType;
column: import('@revolist/revogrid').ColumnRegular;
conditions: readonly Readonly<StructuredFilterOwnedCondition>[];
options: StructuredFilterContextOptions;
replace(conditions: readonly StructuredFilterCondition[]): Promise<void>;
commit?(conditions: readonly StructuredFilterCondition[]): Promise<void>;
}): StructuredFilterBodyContext;

export function renderStructuredFilterBodies(
data: ShowData,
types: readonly StructuredFilterType[],
options: StructuredFilterContextOptions & {
multiFilterItems: MultiFilterItem;
config?: ColumnFilterConfig;
filterNames: Readonly<Record<string, string>>;
dataStores: RowDataSources;
isSourceRow: StructuredFilterAggregateOptions['isSourceRow'];
getValue: StructuredFilterAggregateOptions['getValue'];
dateReferenceDate?: import('../../dates').ISODateString;
change(filterItems: MultiFilterItem, changedProp?: ColumnProp): Promise<void>;
onFilterItemsChange: ProFilterItemsChangeListener;
},
);

interface StructuredFilterContextOptions {
config?: ColumnFilterConfig;
filterNames: Readonly<Record<string, string>>;
dataStores: RowDataSources;
sourceRowTypes?: readonly DimensionRows[];
isSourceRow: StructuredFilterAggregateOptions['isSourceRow'];
getValue: StructuredFilterAggregateOptions['getValue'];
isVisibleRow?: StructuredFilterAggregateOptions['isVisibleRow'];
dateReferenceDate?: import('../../dates').ISODateString;
dateReferenceDateForTimeZone?: (timeZone: string) => import('../../dates').ISODateString;
/** Shared for the lifetime of one popup so sibling rules reuse one aggregate pass. */
runtimeCache?: Map<string, StructuredFilterRuntimeSnapshot>;
/** Shared raw values so sibling aggregate families do not rescan one column. */
sourceValueCache?: Map<string, readonly unknown[]>
}

Resolves a localized caption and replaces its named, text-only placeholders.

export function structuredFilterMessage(
labels: StructuredFilterLabels,
id: string,
fallback: string,
values: StructuredFilterMessageValues = {},
);

Human-readable scalar formatting shared by compact filter surfaces.

export function formatStructuredScalar(
value: unknown,
labels: StructuredFilterLabels,
);

Bounded summary for list-valued conditions; complete values remain in details.

export function summarizeStructuredValues(
values: readonly unknown[],
labels: StructuredFilterLabels,
limit = 3,
);

export type StructuredFilterMessageValues = Readonly<Record<string, string | number>>;

Derives the compact structured-filter header without depending on plugin lifecycle state.

export function resolveStructuredFilterHeader({
column,
types,
filterAstProjectable,
multiFilterItems,
effectiveFilterAst,
filterNames,
config,
getAggregates,
}: ResolveStructuredFilterHeaderOptions): ResolvedStructuredFilterHeader | undefined;

interface ResolveStructuredFilterHeaderOptions {
readonly column: ColumnRegular;
readonly types: readonly StructuredFilterType[];
readonly filterAstProjectable: boolean;
readonly multiFilterItems: MultiFilterItem;
readonly effectiveFilterAst?: FilterAst;
readonly filterNames: Readonly<Record<string, string>>;
readonly config?: ColumnFilterConfig;
readonly getAggregates: (
type: StructuredFilterType,
column: ColumnRegular,
) => StructuredFilterAggregateAccess | undefined
}

interface ResolvedStructuredFilterHeader {
readonly type: StructuredFilterType;
readonly homogeneous: boolean;
readonly conditions: readonly Readonly<FilterData>[];
readonly presentation: FilterHeaderPresentation;
readonly selection?: ReturnType<NonNullable<StructuredFilterType['getHeaderSelection']>>
}

Resolves concise inactive copy while leaving complete column context to accessible labels.

export function resolveStructuredFilterHeaderPlaceholder(
type: StructuredFilterType,
context: StructuredFilterHeaderPlaceholderContext,
): string;

createStructuredAggregateVisibleRowPredicate

Section titled “createStructuredAggregateVisibleRowPredicate”

Builds the lazy local-row predicate used by visible-scope structured aggregates. The aggregate’s own column is omitted while trim layers owned by other plugins remain respected.

export function createStructuredAggregateVisibleRowPredicate({
columnProp,
ast,
dataStores,
columns,
operators,
customEvaluators,
blankSemantics,
getQuickFilterValue,
}: StructuredAggregateVisibilityOptions): NonNullable<StructuredFilterAggregateOptions['isVisibleRow']>;

StructuredAggregateVisibilityOptions (Extended from index.ts)

Section titled “StructuredAggregateVisibilityOptions (Extended from index.ts)”
interface StructuredAggregateVisibilityOptions {
readonly columnProp: ColumnProp;
readonly ast?: FilterAst;
readonly dataStores: RowDataSources
}

fuzzyStructuredFilterType: {
id: string;
operatorIds: string[];
aggregateNeeds: "uniqueValues"[];
describeCondition: ({ condition, labels }: StructuredFilterPresentationContext) => { summary: string; details: string; } | undefined;
mount: (host: HTMLElement, context: StructuredFilterBodyContext) => PreactRootDisposer;
render: (context: StructuredFilterBodyContext) => any;
};

export function clampFuzzyThreshold(value: unknown);

export function normalizeFuzzyFilterValue(value: unknown): FuzzyFilterValue;

export function fuzzyCondition(value: FuzzyFilterValue): StructuredFilterCondition[];

export function fuzzyStateFromConditions(
conditions: readonly Readonly<{ type: string; value?: unknown }>[],
);

Deterministic, dependency-free similarity used by both preview and predicate.

export function fuzzyScore(value: unknown, term: string);

export function rankFuzzyValues(
values: readonly unknown[],
filter: FuzzyFilterValue,
limit = DEFAULT_FUZZY_PREVIEW_LIMIT,
candidateLimit = DEFAULT_FUZZY_PREVIEW_CANDIDATE_LIMIT,
): readonly FuzzyPreviewItem[];

Splits display text using a deterministic longest-common-subsequence match.

export function fuzzyHighlightParts(value: string, term: string): readonly FuzzyHighlightPart[];

FILTER_FUZZY: string;

FUZZY_OPERATOR: string;

DEFAULT_FUZZY_THRESHOLD: 0.55;

DEFAULT_FUZZY_PREVIEW_LIMIT: 5;

Keeps preview work bounded when a column has very high cardinality.

DEFAULT_FUZZY_PREVIEW_CANDIDATE_LIMIT: 2000;

interface FuzzyFilterValue {
readonly term: string;
readonly threshold: number
}

interface FuzzyPreviewItem {
readonly value: string;
readonly score: number
}

interface FuzzyHighlightPart {
readonly text: string;
readonly matched: boolean
}

fuzzyFilter: LogicFunction<any, LogicFunctionExtraParam>;

FUZZY_FILTERS: {
[FUZZY_OPERATOR]: { columnFilterType: string; name: "Fuzzy search"; func: LogicFunction<any, LogicFunctionExtraParam>; };
};

export function defineFuzzyEditor(host: HTMLElement, context: StructuredFilterBodyContext);

export function FuzzyEditor({ context }: { context: StructuredFilterBodyContext });

export function fuzzyCaption(labels: StructuredFilterLabels, id: FuzzyCaptionId);

export function fuzzyMessage(labels: StructuredFilterLabels, id: FuzzyCaptionId, values: StructuredFilterMessageValues = {});

FUZZY_LOCALIZATION: Readonly<{ filterNames: Readonly<{ fuzzy: "Fuzzy search"; }>; captions: Readonly<{ fuzzyHeaderPlaceholder: "Similar to…"; fuzzyTitle: "Fuzzy search"; fuzzyQuery: "Search for"; fuzzyPlaceholder: "Type a name or value"; fuzzyNoMatches: "No values meet this strictness."; fuzzyLoose: "loose"; fuzzyStrict: "strict"; fuzzyTolerance: "Match strictness"; fuzzyStrictnessValue: "{percent}% strict"; 'filter.fuzzy.description': "Fuzzy match “{term}” at {threshold}"; }>; }>;

export type FuzzyCaptionId = keyof typeof FUZZY_LOCALIZATION.captions;

regexStructuredFilterType: {
id: string;
operatorIds: string[];
aggregateNeeds: "uniqueValues"[];
describeCondition: ({ condition, labels }: StructuredFilterPresentationContext) => { summary: string; details: string; } | undefined;
mount: (host: HTMLElement, context: StructuredFilterBodyContext) => PreactRootDisposer;
render: (context: StructuredFilterBodyContext) => any;
};

Keep supported flags JSON-safe, duplicate-free, and in a stable display order.

export function normalizeRegexFlags(value: unknown);

export function normalizeRegexFilterValue(value: unknown): RegexFilterValue;

export function regexModeFromOperator(type: unknown): RegexFilterMode;

export function regexOperatorFromMode(mode: RegexFilterMode): RegexFilterOperator;

export function regexValidationError(value: RegexFilterValue);

Returns undefined for invalid input so callers can retain the last valid condition.

export function regexCondition(state: RegexFilterState): StructuredFilterCondition[] | undefined;

export function regexStateFromConditions(
conditions: readonly Readonly<{ type: string; value?: unknown }>[],
): RegexFilterState;

export function previewRegexValues(
values: readonly unknown[],
state: RegexFilterState,
limit = REGEX_PREVIEW_LIMIT,
scanLimit = REGEX_PREVIEW_SCAN_LIMIT,
): RegexPreview;

FILTER_REGEX: string;

REGEX_MATCHES: string;

REGEX_NOT_MATCHES: string;

REGEX_PREVIEW_LIMIT: 2;

Keep live popup preview work bounded for high-cardinality remote/local columns.

REGEX_PREVIEW_SCAN_LIMIT: 10000;

export type RegexFilterMode = 'matches' | 'not-matches';

export type RegexFilterOperator = typeof REGEX_MATCHES | typeof REGEX_NOT_MATCHES;

interface RegexFilterValue {
readonly pattern: string;
readonly flags: string
}

interface RegexFilterState {
readonly mode: RegexFilterMode
}

interface RegexPreview {
readonly values: readonly string[];
readonly total: number;
readonly more: number;
/** True when `total` is only a lower bound because the scan limit was reached. */
readonly truncated: boolean
}

regexMatches: LogicFunction<any, LogicFunctionExtraParam>;

regexNotMatches: LogicFunction<any, LogicFunctionExtraParam>;

REGEX_FILTERS: {
[REGEX_MATCHES]: { columnFilterType: string; name: "Matches pattern"; func: LogicFunction<any, LogicFunctionExtraParam>; };
[REGEX_NOT_MATCHES]: { columnFilterType: string; name: "Does not match pattern"; func: LogicFunction<any, LogicFunctionExtraParam>; };
};

export function defineRegexEditor(host: HTMLElement, context: StructuredFilterBodyContext);

export function RegexEditor({ context }: { context: StructuredFilterBodyContext });

export function regexFilterCaption(labels: StructuredFilterLabels, id: RegexFilterCaptionId);

export function regexFilterMessage(
labels: StructuredFilterLabels,
id: RegexFilterCaptionId,
values: RegexFilterMessageValues = {},
);

REGEX_FILTER_LOCALIZATION: Readonly<{ filterNames: Readonly<{ regexMatches: "Matches pattern"; regexNotMatches: "Does not match pattern"; }>; captions: Readonly<{ regexHeaderPlaceholder: "Pattern…"; regexTitle: "Regex / pattern"; regexPlaceholder: "^example\\d+$"; regexPatternInput: "Regular expression pattern"; regexFlags: "Active flags"; regexOptions: "Pattern options"; regexIgnoreCase: "ignore case"; regexMultiline: "multiline"; regexNoMatches: "No matching values"; regexMoreMatches: "…{count} more"; regexPreviewLimited: "Preview limited for this high-cardinality column."; regexInvalid: "Invalid pattern — the previous valid filter is still applied."; regexValid: "Valid pattern"; regexEmpty: "Enter a pattern to filter values."; regexUnsafeExpression: "Potentially unsafe regular expression"; regexInvalidExpression: "Invalid regular expression"; 'filter.regex.matchesDescription': "Matches {expression}"; 'filter.regex.notMatchesDescription': "Does not match {expression}"; }>; }>;

export type RegexFilterCaptionId = keyof typeof REGEX_FILTER_LOCALIZATION.captions;

export type RegexFilterMessageValues = Readonly<Record<string, string | number>>;

tokenListStructuredFilterType: {
id: string;
operatorIds: string[];
aggregateNeeds: "uniqueValues"[];
describeCondition: ({ condition, labels }: StructuredFilterPresentationContext) => { summary: string; details: string; } | undefined;
mount: (host: HTMLElement, context: StructuredFilterBodyContext) => PreactRootDisposer;
render: (context: StructuredFilterBodyContext) => any;
};

export function normalizeTokenList(values: readonly unknown[]);

Splits clipboard-sized input into normalized, stable-order tokens.

export function parseTokenList(value: string);

export function hasTokenListDelimiter(value: string);

export function mergeTokenLists(current: readonly string[], additions: readonly unknown[]);

export function tokenListSuggestions(
values: readonly unknown[],
selected: readonly string[],
draft: string,
limit = 8,
);

export function tokenListModeFromOperator(type: unknown): TokenListMode;

export function tokenListOperatorFromMode(mode: TokenListMode): TokenListOperator;

export function tokenListCondition(
tokens: readonly string[],
mode: TokenListMode,
): StructuredFilterCondition[];

export function tokenListStateFromConditions(
conditions: readonly Readonly<{ type: string; value?: unknown }>[],
);

FILTER_TOKEN_LIST: string;

TOKEN_LIST_ANY_OF: string;

TOKEN_LIST_NONE_OF: string;

export type TokenListMode = 'any-of' | 'none-of';

export type TokenListOperator = typeof TOKEN_LIST_ANY_OF | typeof TOKEN_LIST_NONE_OF;

tokenListAnyOf: LogicFunction<any, LogicFunctionExtraParam>;

tokenListNoneOf: LogicFunction<any, LogicFunctionExtraParam>;

TOKEN_LIST_FILTERS: {
[TOKEN_LIST_ANY_OF]: { columnFilterType: string; name: "Is any of"; func: LogicFunction<any, LogicFunctionExtraParam>; };
[TOKEN_LIST_NONE_OF]: { columnFilterType: string; name: "None of"; func: LogicFunction<any, LogicFunctionExtraParam>; };
};

export function defineTokenListEditor(host: HTMLElement, context: StructuredFilterBodyContext);

export function TokenListEditor({ context }: { context: StructuredFilterBodyContext });

export function tokenListCaption(labels: StructuredFilterLabels, id: TokenListCaptionId);

export function tokenListMessage(
labels: StructuredFilterLabels,
id: TokenListCaptionId,
values: TokenListMessageValues = {},
);

TOKEN_LIST_LOCALIZATION: Readonly<{ filterNames: Readonly<{ tokenListAnyOf: "Is any of"; tokenListNoneOf: "None of"; }>; captions: Readonly<{ tokenListHeaderPlaceholder: "Any of…"; tokenListTitle: "Token list"; tokenListMode: "Match mode"; tokenListAnyOfLabel: "any of"; tokenListNoneOfLabel: "none of"; tokenListValues: "Values"; tokenListRemove: "Remove {token}"; tokenListMore: "+{count} more"; tokenListPlaceholder: "paste or type…"; tokenListSuggestions: "Suggested values"; tokenListCountOne: "{count} token"; tokenListCountMany: "{count} tokens"; 'filter.tokenList.noneOfDescription': "None of: {values}"; 'filter.tokenList.anyOfDescription': "Any of: {values}"; }>; }>;

export type TokenListCaptionId = keyof typeof TOKEN_LIST_LOCALIZATION.captions;

export type TokenListMessageValues = Readonly<Record<string, string | number>>;

facetedListStructuredFilterType: {
id: string;
operatorIds: string[];
aggregateNeeds: "valueCounts"[];
describeCondition: ({ condition, column, config, labels }: StructuredFilterPresentationContext) => { summary: string; details: string; } | undefined;
getHeaderSelection: ({ condition, column, config, aggregates, labels }: StructuredFilterHeaderSelectionContext) => { values: { value: string; label: string; count: number; }[]; totalCount: number; } | undefined;
mount: (host: HTMLElement, context: StructuredFilterBodyContext) => PreactRootDisposer;
render: (context: StructuredFilterBodyContext) => any;
};

export function isFacetedScalar(value: unknown): value is FacetedScalar;

JSON-safe typed identity; unlike display text it keeps 1, “1”, and true distinct.

export function facetedScalarId(value: FacetedScalar);

export function facetedScalarLabel(value: FacetedScalar, labels = DEFAULT_FACETED_SCALAR_LABEL_TEXT);

export function resolveFacetedListLabelFormatter(
options: FacetedListOptions | undefined,
property: ColumnProp,
): FacetedListLabelFormatter | undefined;

export function normalizeFacetedValues(values: readonly unknown[]);

export function createFacetedListOptions(
allCounts: readonly StructuredFilterValueCount[],
visibleCounts: readonly StructuredFilterValueCount[] = [],
labels: FacetedScalarLabelText = DEFAULT_FACETED_SCALAR_LABEL_TEXT,
formatLabel?: (value: FacetedScalar) => string | undefined,
);

export function facetedListStateFromConditions(
conditions: readonly Readonly<{ id?: unknown; type: string; value?: unknown }>[],
allValues: readonly FacetedScalar[],
): FacetedListState;

export function facetedListCondition(
selectedValues: readonly FacetedScalar[],
allValues: readonly FacetedScalar[],
conditionId?: number,
): StructuredFilterCondition[];

FILTER_FACETED_LIST: string;

FACETED_LIST_INCLUDE: string;

FACETED_LIST_EXCLUDE: string;

FACETED_LIST_RENDER_LIMIT: 200;

export type FacetedListOperator = typeof FACETED_LIST_INCLUDE | typeof FACETED_LIST_EXCLUDE;

export type FacetedScalar = string | number | boolean | null;

interface FacetedListFormatLabelContext {
readonly property: ColumnProp;
readonly column?: FilterEvaluationContext['column']
}

Presents one stored scalar facet without changing its typed filter identity.

/** Presents one stored scalar facet without changing its typed filter identity. */
export type FacetedListLabelFormatter = (
value: FacetedScalar,
context: FacetedListFormatLabelContext,
) => string | undefined;

interface FacetedListColumnOptions {
readonly formatLabel?: FacetedListLabelFormatter
}

interface FacetedListOptions {
readonly formatLabel?: FacetedListLabelFormatter;
readonly columns?: Readonly<Record<string, FacetedListColumnOptions>>
}

interface FacetedListOption {
readonly id: string;
readonly value: FacetedScalar;
readonly label: string;
readonly count: number;
readonly visibleCount: number
}

interface FacetedListState {
readonly selected: readonly FacetedScalar[];
readonly conditionId?: number
}

interface FacetedScalarLabelText {
readonly blank: string;
readonly empty: string;
readonly true: string;
readonly false: string
}

DEFAULT_FACETED_SCALAR_LABEL_TEXT: {
blank: string;
empty: string;
true: string;
false: string;
};

facetedListInclude: LogicFunction<any, LogicFunctionExtraParam>;

facetedListExclude: LogicFunction<any, LogicFunctionExtraParam>;

FACETED_LIST_FILTERS: {
[FACETED_LIST_INCLUDE]: { columnFilterType: string; name: "Is any selected value"; func: LogicFunction<any, LogicFunctionExtraParam>; };
[FACETED_LIST_EXCLUDE]: { columnFilterType: string; name: "Excludes selected values"; func: LogicFunction<any, LogicFunctionExtraParam>; };
};

export function defineFacetedListEditor(host: HTMLElement, context: StructuredFilterBodyContext);

export function FacetedListEditor({ context }: { context: StructuredFilterBodyContext });

export function facetedListCaption(labels: StructuredFilterLabels, id: FacetedListCaptionId);

export function facetedListMessage(labels: StructuredFilterLabels, id: FacetedListCaptionId, values: StructuredFilterMessageValues = {});

FACETED_LIST_LOCALIZATION: Readonly<{ filterNames: Readonly<{ facetedListInclude: "Is any selected value"; facetedListExclude: "Excludes selected values"; }>; captions: Readonly<{ facetedListBlank: "(Blank)"; facetedListEmpty: "(Empty)"; facetedListTrue: "True"; facetedListFalse: "False"; facetedListTitle: "Filter by values"; facetedListSelectAll: "Select all"; facetedListSearch: "Search values"; facetedListSearchPlaceholder: "Search..."; facetedListActions: "Value selection actions"; facetedListInvert: "Invert"; facetedListOnlyVisible: "Only visible"; facetedListValues: "Available values"; facetedListCount: "{visible} visible of {total} total rows"; facetedListNoMatches: "No values match your search."; facetedListNoValues: "No values available."; facetedListLimit: "Showing {visible} of {total} values. Search to narrow the list."; 'filter.facetedList.excludeDescription': "Excludes: {values}"; 'filter.facetedList.includeDescription': "Includes: {values}"; }>; }>;

export type FacetedListCaptionId = keyof typeof FACETED_LIST_LOCALIZATION.captions;

Creates the built-in type with optional safe per-badge presentation metadata.

export function createChipBadgeStructuredFilterType(
options?: ChipBadgeTogglesOptions,
): StructuredFilterType;

chipBadgeStructuredFilterType: StructuredFilterType;

export function orderChipBadgeValues(
values: readonly ChipBadgeScalar[],
order: readonly ChipBadgeScalar[] = [],
);

export function isChipBadgeScalar(value: unknown): value is ChipBadgeScalar;

export function isDefaultChipBadgeBlank(value: unknown);

JSON-safe typed identity; display labels never participate in matching.

export function chipBadgeScalarId(value: ChipBadgeScalar);

export function normalizeChipBadgeValues(values: readonly unknown[]);

export function defaultChipBadgeLabel(value: ChipBadgeScalar, labels = DEFAULT_CHIP_BADGE_LABEL_TEXT);

export function resolveChipBadgeDescriptor(
value: ChipBadgeScalar,
column: ColumnRegular,
selected: boolean,
options?: ChipBadgeTogglesOptions,
labels: ChipBadgeLabelText = DEFAULT_CHIP_BADGE_LABEL_TEXT,
): ChipBadgeDescriptor;

Checks the exact JSON-safe selection transport shape before it is applied.

export function isValidChipBadgeFilterValue(value: unknown): value is ChipBadgeFilterValue;

Parses transport state once for compact, filter-owned presentation surfaces.

export function describeChipBadgeValue(
value: unknown,
column: ColumnRegular,
options?: ChipBadgeTogglesOptions,
labels: ChipBadgeLabelText = DEFAULT_CHIP_BADGE_LABEL_TEXT,
);

export function resolveVisibleChipBadgeLimit(options?: ChipBadgeTogglesOptions);

export function chipBadgeStateFromConditions(
conditions: readonly Readonly<{ id?: unknown; type: string; value?: unknown }>[],
allValues: readonly ChipBadgeScalar[],
): ChipBadgeState;

export function chipBadgeCondition(
selectedValues: readonly ChipBadgeScalar[],
allValues: readonly ChipBadgeScalar[],
includeBlanks: boolean,
hasBlanks: boolean,
conditionId?: number,
): StructuredFilterCondition[];

FILTER_CHIP_BADGE_TOGGLES: string;

CHIP_BADGE_SELECTION: string;

Avoid mounting an unbounded number of interactive pills for high-cardinality columns.

DEFAULT_VISIBLE_CHIP_BADGES: 200;

export type ChipBadgeScalar = string | number | boolean;

interface ChipBadgeFilterValue {
readonly values: readonly ChipBadgeScalar[];
readonly includeBlanks: boolean
}

interface ChipBadgeDescriptor {
/** Plain-text label. It is rendered as text, never interpreted as HTML. */
readonly label: string;
/** Optional classes applied to the pill button. */
readonly className?: string;
/** Optional CSS color used for the pill's swatch and selected accent. */
readonly color?: string
}

interface ChipBadgeDescriptorContext {
readonly value: ChipBadgeScalar;
readonly column: ColumnRegular;
readonly selected: boolean
}

interface ChipBadgeTogglesOptions {
/** Formats a value or returns safe presentation metadata for its pill. */
readonly badge?: (
context: ChipBadgeDescriptorContext,
) => string | ChipBadgeDescriptor | null | undefined;
/** Maximum pills mounted at once. The complete value set still drives condition semantics. */
readonly maxVisibleBadges?: number;
/** Preferred display order; values not listed remain in aggregate order. */
readonly order?: readonly ChipBadgeScalar[]
}

interface ChipBadgeState {
readonly conditionId?: number
}

interface ChipBadgeLabelText {
readonly true: string;
readonly false: string
}

DEFAULT_CHIP_BADGE_LABEL_TEXT: {
true: string;
false: string;
};

chipBadgeSelection: LogicFunction<any, LogicFunctionExtraParam>;

CHIP_BADGE_FILTERS: {
[CHIP_BADGE_SELECTION]: { columnFilterType: string; name: "Matches selected badges"; func: LogicFunction<any, LogicFunctionExtraParam>; };
};

export function defineChipBadgeTogglesEditor(
host: HTMLElement,
context: StructuredFilterBodyContext,
options?: ChipBadgeTogglesOptions,
);

export function ChipBadgeTogglesEditor({
context,
options,
}: {
context: StructuredFilterBodyContext;
options?: ChipBadgeTogglesOptions;
});

export function chipBadgeCaption(labels: StructuredFilterLabels, id: ChipBadgeCaptionId);

export function chipBadgeMessage(labels: StructuredFilterLabels, id: ChipBadgeCaptionId, values: StructuredFilterMessageValues = {});

CHIP_BADGE_LOCALIZATION: Readonly<{ filterNames: Readonly<{ chipBadgeSelection: "Matches selected badges"; }>; captions: Readonly<{ chipBadgeHeaderPlaceholder: "Any"; chipBadgeTrue: "True"; chipBadgeFalse: "False"; chipBadgeTitle: "Filter by badges"; chipBadgeValues: "Available badge values"; chipBadgeToggleLabel: "{label}, {state}"; chipBadgeSelected: "selected"; chipBadgeNotSelected: "not selected"; chipBadgeNoValues: "No badge values available."; chipBadgeTruncated: "Showing first {visible} of {total} badges."; chipBadgeIncludeBlanks: "Include blanks"; chipBadgeSelectedCount: "{selected} of {total} selected"; chipBadgeBadgeSummaryOne: "1 selected"; chipBadgeBadgeSummaryMany: "{count} selected"; chipBadgeBadgeBlanksIncluded: "blanks included"; chipBadgeBadgeBlanksExcluded: "blanks excluded"; chipBadgeNoneSelected: "No badges selected"; }>; }>;

export type ChipBadgeCaptionId = keyof typeof CHIP_BADGE_LOCALIZATION.captions;

Creates an opt-in histogram brush type with deterministic presentation options.

export function createHistogramBrushStructuredFilterType(
options?: HistogramBrushOptions,
): StructuredFilterType;

histogramBrushStructuredFilterType: StructuredFilterType;

export function resolveHistogramChartTypes(
chart?: HistogramBrushChartOptions,
): readonly DistributionChartType[];

export function resolveInitialHistogramChartType(
chart: HistogramBrushChartOptions | undefined,
types = resolveHistogramChartTypes(chart),
): DistributionChartType | undefined;

export function histogramModelFromPreparedData(value: unknown): HistogramModel | undefined;

export function toHistogramNumber(value: unknown): number | undefined;

export function createHistogramModel(
aggregate: StructuredFilterNumericRange,
options: Pick<HistogramBrushOptions, 'bins' | 'scale'> = {},
): HistogramModel;

export function parseHistogramBrushFilterValue(value: unknown): HistogramBrushFilterValue | undefined;

export function histogramBrushStateFromConditions(
conditions: readonly Readonly<{ id?: unknown; type: string; value?: unknown }>[],
model: HistogramModel,
): HistogramBrushState;

export function histogramBrushCondition(
selectedMin: number,
selectedMax: number,
model: Pick<HistogramModel, 'min' | 'max'>,
conditionId?: number,
): StructuredFilterCondition[];

export function histogramBrushMatchCount(model: Pick<HistogramModel, 'values'>, min: number, max: number);

export function histogramPosition(value: number, model: Pick<HistogramModel, 'min' | 'max' | 'scale'>);

export function histogramValueAtPosition(position: number, model: Pick<HistogramModel, 'min' | 'max' | 'scale'>);

export function histogramBinIsSelected(bin: HistogramBin, min: number, max: number);

FILTER_HISTOGRAM_BRUSH: string;

HISTOGRAM_BRUSH_BETWEEN: string;

HISTOGRAM_BRUSH_STEPS: 1000;

export type HistogramBrushScale = 'linear' | 'log';

interface HistogramBrushFilterValue {
readonly min: number;
readonly max: number;
readonly inclusive: true
}

interface HistogramBrushFormatContext {
readonly column: import('@revolist/revogrid').ColumnRegular
}

interface HistogramBrushOptions {
/** Fixed bar count or deterministic Sturges-rule bins. Defaults to `auto`. */
readonly bins?: number | 'auto';
/** Uses logarithmic bin/brush geometry when all values are positive. */
readonly scale?: HistogramBrushScale;
/** Formats bounds and handle value text. */
readonly formatValue?: (value: number, context: HistogramBrushFormatContext) => string;
/** Formats the selected row count. */
readonly formatMatchCount?: (count: number, context: HistogramBrushFormatContext) => string;
/** Presentation-only chart configuration. Filtering and prepared-data contracts are unchanged. */
readonly chart?: HistogramBrushChartOptions
}

HistogramBrushChartTooltipContext (Extended from index.ts)

Section titled “HistogramBrushChartTooltipContext (Extended from index.ts)”
interface HistogramBrushChartTooltipContext {
readonly index: number;
readonly selected: boolean;
readonly minLabel: string;
readonly maxLabel: string
}

interface HistogramBrushChartOptions {
/** Initial preferred chart style. Falls back to the first enabled type. */
readonly type?: DistributionChartType;
/** Ordered styles users may switch between. One hides the switch; an empty list hides the chart. */
readonly types?: readonly DistributionChartType[];
readonly height?: number;
readonly showPoints?: boolean;
readonly formatTooltip?: (
bin: HistogramBin,
context: HistogramBrushChartTooltipContext,
) => DistributionChartTooltip
}

interface HistogramBin {
readonly min: number;
readonly max: number;
readonly count: number
}

interface HistogramModel {
/** Finite numeric values sorted ascending for logarithmic-time range counts. */
readonly values: readonly number[];
readonly min?: number;
readonly max?: number;
readonly scale: HistogramBrushScale;
readonly bins: readonly HistogramBin[]
}

Compact server-produced histogram; raw row values are intentionally omitted.

interface HistogramPreparedData {
readonly kind: 'histogramBrush';
readonly count: number;
readonly min: number;
readonly max: number;
readonly scale: HistogramBrushScale;
readonly bins: readonly HistogramBin[]
}

interface HistogramBrushState {
readonly min?: number;
readonly max?: number;
readonly conditionId?: number
}

histogramBrushBetween: LogicFunction<any, LogicFunctionExtraParam>;

HISTOGRAM_BRUSH_FILTERS: {
[HISTOGRAM_BRUSH_BETWEEN]: { columnFilterType: string; name: "Is in histogram range"; func: LogicFunction<any, LogicFunctionExtraParam>; };
};

export function defineHistogramBrushEditor(
host: HTMLElement,
context: StructuredFilterBodyContext,
options?: HistogramBrushOptions,
);

export function HistogramBrushEditor({
context,
options,
}: {
context: StructuredFilterBodyContext;
options?: HistogramBrushOptions;
});

export function histogramBrushCaption(labels: StructuredFilterLabels, id: HistogramBrushCaptionId);

export function histogramBrushMessage(labels: StructuredFilterLabels, id: HistogramBrushCaptionId, values: StructuredFilterMessageValues = {});

export function histogramBrushChartTypeCaption(
labels: StructuredFilterLabels,
type: import('../../../distribution-chart').DistributionChartType,
);

HISTOGRAM_BRUSH_LOCALIZATION: Readonly<{ filterNames: Readonly<{ histogramBrushBetween: "Is in histogram range"; }>; captions: Readonly<{ histogramBrushTitle: "Histogram range"; histogramBrushDescription: "Choose a numeric range. The chart shows the distribution."; histogramBrushNoValues: "No numeric values available."; histogramBrushMatchOne: "1 match"; histogramBrushMatchMany: "{count} matches"; histogramBrushItem: "item"; histogramBrushItems: "items"; histogramBrushSelected: "Selected"; histogramBrushOutsideSelection: "Outside selection"; histogramBrushChart: "Value distribution"; histogramBrushChartTypes: "Chart style"; histogramBrushChartBar: "Bar"; histogramBrushChartLine: "Line"; histogramBrushChartArea: "Area"; histogramBrushDescriptionNoChart: "Choose a numeric range."; histogramBrushMinimum: "Minimum value"; histogramBrushMaximum: "Maximum value"; histogramBrushRemoteCount: "Count updates after apply"; }>; }>;

export type HistogramBrushCaptionId = keyof typeof HISTOGRAM_BRUSH_LOCALIZATION.captions;

createRatingProgressThresholdStructuredFilterType

Section titled “createRatingProgressThresholdStructuredFilterType”

Creates the opt-in rating/progress threshold type with bounded numeric presentation options.

export function createRatingProgressThresholdStructuredFilterType(
options?: RatingProgressThresholdOptions,
): StructuredFilterType;

ratingProgressThresholdStructuredFilterType

Section titled “ratingProgressThresholdStructuredFilterType”
ratingProgressThresholdStructuredFilterType: StructuredFilterType;

export function normalizeRatingProgressOptions(
options: RatingProgressThresholdOptions = {},
): NormalizedRatingProgressOptions;

Produces a stable finite value aligned to the configured bounded domain.

export function normalizeRatingProgressValue(
value: unknown,
options: Pick<NormalizedRatingProgressOptions, 'max' | 'step'>,
);

export function ratingProgressStateFromConditions(
conditions: readonly Readonly<{ id?: unknown; type: string; value?: unknown }>[],
options: NormalizedRatingProgressOptions,
): RatingProgressState;

export function ratingProgressCondition(
operator: RatingProgressOperator,
value: unknown,
options: NormalizedRatingProgressOptions,
conditionId?: number,
): StructuredFilterCondition[];

FILTER_RATING_PROGRESS_THRESHOLD: string;

RATING_PROGRESS_GTE: string;

RATING_PROGRESS_EQ: string;

RATING_PROGRESS_LTE: string;

RATING_PROGRESS_OPERATORS: readonly ["ratingProgressThresholdGte", "ratingProgressThresholdEq", "ratingProgressThresholdLte"];

export type RatingProgressOperator = typeof RATING_PROGRESS_OPERATORS[number];

export type RatingProgressUnit = 'stars' | 'percent' | 'score';

interface RatingProgressFormatContext {
readonly column: ColumnRegular;
readonly unit: RatingProgressUnit;
readonly max: number;
readonly step: number;
readonly operator: RatingProgressOperator
}

interface RatingProgressThresholdOptions {
/** Determines the visual control and default formatting. Defaults to `stars`. */
readonly unit?: RatingProgressUnit;
/** Inclusive upper bound. Defaults to 5 for stars and 100 otherwise. */
readonly max?: number;
/** Accessible control increment. Defaults to 1. */
readonly step?: number;
/** Formats the live value label and native control value text. */
readonly formatValue?: (value: number, context: RatingProgressFormatContext) => string
}

interface NormalizedRatingProgressOptions {
readonly unit: RatingProgressUnit;
readonly max: number;
readonly step: number;
readonly formatValue?: RatingProgressThresholdOptions['formatValue']
}

interface RatingProgressState {
readonly operator: RatingProgressOperator;
readonly value: number;
readonly active: boolean;
readonly conditionId?: number
}

ratingProgressGte: LogicFunction<any, LogicFunctionExtraParam>;

ratingProgressEq: LogicFunction<any, LogicFunctionExtraParam>;

ratingProgressLte: LogicFunction<any, LogicFunctionExtraParam>;

RATING_PROGRESS_FILTERS: {
[RATING_PROGRESS_GTE]: { columnFilterType: string; name: "At least"; func: LogicFunction<any, LogicFunctionExtraParam>; };
[RATING_PROGRESS_EQ]: { columnFilterType: string; name: "Exactly"; func: LogicFunction<any, LogicFunctionExtraParam>; };
[RATING_PROGRESS_LTE]: { columnFilterType: string; name: "At most"; func: LogicFunction<any, LogicFunctionExtraParam>; };
};

export function defineRatingProgressThresholdEditor(
host: HTMLElement,
context: StructuredFilterBodyContext,
options?: RatingProgressThresholdOptions,
);

export function RatingProgressThresholdEditor({
context,
options,
}: {
context: StructuredFilterBodyContext;
options?: RatingProgressThresholdOptions;
});

Compact visual for discrete star domains; other configurations retain the text fallback.

export function createRatingProgressHeaderTemplate(
options: NormalizedRatingProgressOptions,
): FilterHeaderTemplateFunc | undefined;

export function ratingProgressCaption(labels: StructuredFilterLabels, id: RatingProgressCaptionId);

export function ratingProgressMessage(
labels: StructuredFilterLabels,
id: RatingProgressCaptionId,
values: RatingProgressMessageValues = {},
);

export function ratingProgressDescription(labels: StructuredFilterLabels, stars: boolean);

RATING_PROGRESS_LOCALIZATION: Readonly<{ filterNames: Readonly<{ ratingProgressThresholdGte: "At least"; ratingProgressThresholdEq: "Exactly"; ratingProgressThresholdLte: "At most"; }>; descriptionFallbacks: Readonly<{ stars: "Choose a rating threshold."; progress: "Choose a progress threshold."; }>; captions: Readonly<{ ratingProgressHeaderPlaceholder: "Any rating"; ratingProgressHeaderProgressPlaceholder: "Any progress"; ratingProgressHeaderScorePlaceholder: "Any score"; ratingProgressTitle: "Rating & progress threshold"; ratingProgressDescription: "Choose a progress threshold."; ratingProgressOperator: "Threshold operator"; ratingProgressStars: "Rating threshold"; ratingProgressStarValue: "{value} stars"; ratingProgressValueStars: "{value} of {max} stars"; ratingProgressCompletion: "Completion {operator}"; ratingProgressValue: "Threshold value"; }>; }>;

export type RatingProgressCaptionId = keyof typeof RATING_PROGRESS_LOCALIZATION.captions;

export type RatingProgressMessageValues = Readonly<Record<string, string | number>>;

createStatisticalPresetsStructuredFilterType

Section titled “createStatisticalPresetsStructuredFilterType”

Creates the opt-in statistical presets type. Statistics refresh on popup render; applied JSON-safe thresholds remain stable across source changes until the user selects a preset again.

export function createStatisticalPresetsStructuredFilterType(
options?: StatisticalPresetsOptions,
): StructuredFilterType;

statisticalPresetsStructuredFilterType: StructuredFilterType;

export function statisticalModelsFromPreparedData(value: unknown): readonly StatisticalPresetModel[] | undefined;

Counts a resolved preset against the summary’s sorted values in logarithmic time.

export function countStatisticalPresetMatches(
sortedValues: readonly number[],
preset: StatisticalPresetFilterValue,
);

Deterministic sorted linear-interpolation quantile (R-7).

export function statisticalQuantile(sortedValues: readonly number[], probability: number);

Computes deterministic population statistics from finite numeric values only.

export function createStatisticalSummary(
aggregate: Pick<StructuredFilterNumericRange, 'values'>,
): StatisticalSummary;

export function matchesStatisticalPreset(value: number, preset: StatisticalPresetFilterValue);

export function createStatisticalPresetModels(
summary: StatisticalSummary,
): readonly StatisticalPresetModel[];

export function parseStatisticalPresetFilterValue(value: unknown): StatisticalPresetFilterValue | undefined;

export function statisticalPresetStateFromConditions(
conditions: readonly Readonly<{ id?: unknown; type: string; value?: unknown }>[],
);

export function statisticalPresetCondition(
model: StatisticalPresetModel | undefined,
conditionId?: number,
): StructuredFilterCondition[];

FILTER_STATISTICAL_PRESETS: string;

STATISTICAL_PRESET_OPERATOR: string;

STATISTICAL_PRESET_IDS: readonly ["top10Percent", "aboveAverage", "bottomQuartile", "outliersTwoSigma", "negativeOnly"];

export type StatisticalPresetId = typeof STATISTICAL_PRESET_IDS[number];

interface StatisticalPresetFilterValue {
readonly preset: StatisticalPresetId;
readonly lower: number | null;
readonly upper: number | null;
readonly lowerInclusive: boolean;
readonly upperInclusive: boolean;
readonly outside: boolean
}

interface StatisticalPresetFormatContext {
readonly column: ColumnRegular;
readonly preset: StatisticalPresetId
}

Presentation options for statistical presets. Statistics refresh when the popup body renders; applied conditions keep their serialized bounds until the user selects a preset again.

interface StatisticalPresetsOptions {
/** Formats computed means, quantiles, and deviation boundaries. */
readonly formatValue?: (value: number, context: StatisticalPresetFormatContext) => string;
/** Formats each preset's matching finite-row count. */
readonly formatMatchCount?: (count: number, context: StatisticalPresetFormatContext) => string
}

interface StatisticalSummary {
readonly values: readonly number[];
readonly count: number;
readonly mean?: number;
readonly firstQuartile?: number;
readonly ninetiethPercentile?: number;
readonly standardDeviation?: number
}

interface StatisticalPresetModel {
readonly id: StatisticalPresetId;
readonly condition: StatisticalPresetFilterValue;
readonly matchCount: number
}

interface StatisticalPresetsPreparedData {
readonly kind: 'statisticalPresets';
readonly models: readonly StatisticalPresetModel[]
}

statisticalPresetPredicate: LogicFunction<any, LogicFunctionExtraParam>;

STATISTICAL_PRESET_FILTERS: {
[STATISTICAL_PRESET_OPERATOR]: { columnFilterType: string; name: "Statistical preset"; func: LogicFunction<any, LogicFunctionExtraParam>; };
};

export function defineStatisticalPresetsEditor(
host: HTMLElement,
context: StructuredFilterBodyContext,
options?: StatisticalPresetsOptions,
);

export function StatisticalPresetsEditor({
context,
options,
}: {
context: StructuredFilterBodyContext;
options?: StatisticalPresetsOptions;
});

export function formatStatisticalPresetValue(
value: number,
preset: StatisticalPresetId,
column: ColumnRegular,
options?: StatisticalPresetsOptions,
);

Compact resolved predicate shared by popup rows, headers, badges, and tooltips.

export function formatStatisticalPresetBoundary(
value: StatisticalPresetFilterValue,
column: ColumnRegular,
labels: StructuredFilterLabels,
options?: StatisticalPresetsOptions,
);

export function statisticalPresetsCaption(labels: StructuredFilterLabels, id: StatisticalPresetsCaptionId);

export function statisticalPresetsMessage(
labels: StructuredFilterLabels,
id: StatisticalPresetsCaptionId,
values: StatisticalPresetsMessageValues = {},
);

export function statisticalPresetCaption(labels: StructuredFilterLabels, preset: StatisticalPresetId);

STATISTICAL_PRESETS_LOCALIZATION: Readonly<{ filterNames: Readonly<{ statisticalPreset: "Statistical preset"; }>; captions: Readonly<{ statisticalPresetTop10: "Top 10%"; statisticalPresetAboveAverage: "Above average"; statisticalPresetBottomQuartile: "Bottom quartile"; statisticalPresetOutliers: "Outliers (> 2σ)"; statisticalPresetNegative: "Negative only"; statisticalPresetOutsideRange: "< {lower} or > {upper}"; statisticalPresetRowsOne: "{count} row"; statisticalPresetRowsMany: "{count} rows"; statisticalPresetsTitle: "Statistical presets"; statisticalPresetsChoices: "Statistical preset choices"; statisticalPresetsNoValues: "No numeric values available."; }>; }>;

STATISTICAL_PRESET_CAPTIONS: Readonly<Record<"top10Percent" | "aboveAverage" | "bottomQuartile" | "outliersTwoSigma" | "negativeOnly", "statisticalPresetTop10" | "statisticalPresetAboveAverage" | "statisticalPresetBottomQuartile" | "statisticalPresetOutliers" | "statisticalPresetNegative" | "statisticalPresetOutsideRange" | "statisticalPresetRowsOne" | "statisticalPresetRowsMany" | "statisticalPresetsTitle" | "statisticalPresetsChoices" | "statisticalPresetsNoValues">>;

export type StatisticalPresetsCaptionId = keyof typeof STATISTICAL_PRESETS_LOCALIZATION.captions;

export type StatisticalPresetsMessageValues = Readonly<Record<string, string | number>>;

Creates an opt-in calendar range with calendar/date presentation options.

export function createCalendarRangeStructuredFilterType(
options?: CalendarRangeOptions,
): StructuredFilterType;

calendarRangeStructuredFilterType: StructuredFilterType;

export function parseCalendarRangeValue(value: unknown): CalendarRangeFilterValue | undefined;

export function calendarRangeStateFromConditions(
conditions: readonly Readonly<{ id?: unknown; type: string; value?: unknown }>[],
): CalendarRangeState;

export function calendarDateFilterStateFromConditions(
conditions: readonly Readonly<{ id?: unknown; type: string; value?: unknown }>[],
operators: readonly CalendarDateOperator[] = CALENDAR_DATE_OPERATORS,
): CalendarDateFilterState;

Returns no value for a partial/invalid range so callers cannot accidentally clear or commit it.

export function calendarRangeCondition(
from: string | undefined,
to: string | undefined,
conditionId?: number,
): StructuredFilterCondition[] | undefined;

export function calendarDateCondition(
operator: CalendarDateOperator,
from: string | undefined,
to?: string,
conditionId?: number,
): StructuredFilterCondition[] | undefined;

export function resolveCalendarRangeOptions(
column: ColumnRegular,
settings: ResolvedDateFilterSettings,
options: CalendarRangeOptions = {},
): ResolvedCalendarRangeOptions;

export function validateCalendarRangeSelection(
from: ISODateString,
to: ISODateString,
options: ResolvedCalendarRangeOptions,
): { readonly range: CalendarRangeFilterValue; readonly reason?: CalendarRangeValidationFailure | string };

Shared compact/full presentation used by calendar chips, headers, badges, and tooltips.

export function formatCalendarRangeLabel(
range: CalendarRangeFilterValue,
options: ResolvedCalendarRangeOptions,
compact = true,
);

export function formatCalendarDateConditionLabel(
operator: CalendarDateOperator,
range: CalendarRangeFilterValue,
options: ResolvedCalendarRangeOptions,
compact = true,
);

export function isCalendarRangeDateDisabled(date: ISODateString, options: ResolvedCalendarRangeOptions);

export function calendarRangeMonthDates(month: string, weekStartsOn: number);

export function calendarRangeToday(timeZone: string, now = new Date()): ISODateString;

export function calendarRangeKeyboardDate(
date: ISODateString,
key: string,
weekStartsOn: number,
isDisabled: (date: ISODateString) => boolean = () => false,
): ISODateString | undefined;

export function createCalendarRangeFilters(
runtime: TemporalFilterRuntime = new TemporalFilterRuntime(),
): Record<CalendarDateOperator, CustomFilter>;

FILTER_CALENDAR_RANGE: string;

interface CalendarRangeFilterValue {
readonly from: ISODateString;
readonly to: ISODateString;
readonly inclusive: true
}

interface CalendarRangeFormatContext {
readonly column: ColumnRegular;
readonly locale: string;
readonly timeZone: string
}

export type CalendarRangeCalendarOptions = Omit<CalendarProps,
| 'month'
| 'focusedDate'
| 'referenceDate'
| 'selection'
| 'preview'
| 'locale'
| 'weekStartsOn'
| 'minDate'
| 'maxDate'
| 'isDateDisabled'
| 'onMonthChange'
| 'onFocusedDateChange'
| 'onSelect'
| 'onPreviewDateChange'
>;

CalendarRangeValidationContext (Extended from index.ts)

Section titled “CalendarRangeValidationContext (Extended from index.ts)”
interface CalendarRangeValidationContext {
readonly operator: CalendarDateOperator;
readonly isDateDisabled: (date: ISODateString) => boolean
}

interface CalendarRangeValidationOptions {
/** Inclusive minimum number of selected calendar days. */
readonly minDays?: number;
/** Inclusive maximum number of selected calendar days. */
readonly maxDays?: number;
/** Defaults to true for compatibility. */
readonly allowSameDay?: boolean;
/** Defaults to true for compatibility with ranges spanning unavailable dates. */
readonly allowDisabledDates?: boolean;
readonly validate?: (
range: CalendarRangeFilterValue,
context: CalendarRangeValidationContext,
) => boolean | string
}

export type CalendarRangeValidationFailure =
| 'sameDay'
| 'tooShort'
| 'tooLong'
| 'containsDisabledDate'
| 'invalid';

interface CalendarRangeOptions {
/** Ordered operator allow-list. Defaults to between plus all single-date operators. */
readonly operators?: readonly CalendarDateOperator[];
/** Dates that cannot be selected, either as ISO date-only values or a predicate. */
readonly disabledDates?: readonly string[] | ((date: ISODateString, context: CalendarRangeFormatContext) => boolean);
/** Sunday is 0 and Saturday is 6. Inherits `filter.date` when omitted. */
readonly weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
/** IANA timezone used to resolve today's calendar date. Inherits `filter.date` when omitted. */
readonly timeZone?: string;
readonly locale?: string;
/** Earliest selectable date, inclusive. */
readonly minDate?: ISODateString;
/** Latest selectable date, inclusive. */
readonly maxDate?: ISODateString;
/** Shows adjacent-month dates instead of preserving empty month geometry. */
readonly showOutsideDays?: boolean;
/** Allows visible adjacent-month dates to be selected. */
readonly allowOutsideMonthSelection?: boolean;
/** Keeps a stable six-week grid when true. Defaults to true. */
readonly fixedWeeks?: boolean;
/** Adds a compact Today action below the month. */
readonly showTodayButton?: boolean;
/** Independent shared-calendar configuration. Nested values override compatible flat aliases. */
readonly calendar?: CalendarRangeCalendarOptions;
readonly showOperator?: boolean;
readonly showSelectionSummary?: boolean;
readonly showClearButton?: boolean;
readonly showCalendar?: boolean;
readonly rangeValidation?: CalendarRangeValidationOptions;
readonly onInvalidRange?: (
range: CalendarRangeFilterValue,
reason: CalendarRangeValidationFailure | string,
context: CalendarRangeValidationContext,
) => void;
/** Intl options used by the selected-range chip. */
readonly dateFormat?: Intl.DateTimeFormatOptions;
/** Overrides selected-range date labels. */
readonly formatDate?: (date: ISODateString, context: CalendarRangeFormatContext) => string
}

ResolvedCalendarRangeOptions (Extended from index.ts)

Section titled “ResolvedCalendarRangeOptions (Extended from index.ts)”
interface ResolvedCalendarRangeOptions {
readonly operators: readonly CalendarDateOperator[];
readonly disabledDates: ReadonlySet<string> | CalendarRangeOptions['disabledDates'];
readonly weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6;
readonly dateFormat: Intl.DateTimeFormatOptions;
readonly formatDate?: CalendarRangeOptions['formatDate'];
readonly minDate?: ISODateString;
readonly maxDate?: ISODateString;
readonly showOutsideDays: boolean;
readonly allowOutsideMonthSelection: boolean;
readonly fixedWeeks: boolean;
readonly showTodayButton: boolean;
readonly calendar: CalendarRangeCalendarOptions;
readonly showOperator: boolean;
readonly showSelectionSummary: boolean;
readonly showClearButton: boolean;
readonly showCalendar: boolean;
readonly rangeValidation: Required<Pick<CalendarRangeValidationOptions,
'allowSameDay' | 'allowDisabledDates'
>> & Pick<CalendarRangeValidationOptions, 'minDays' | 'maxDays' | 'validate'>;
readonly onInvalidRange?: CalendarRangeOptions['onInvalidRange']
}

interface CalendarRangeState {
readonly range?: CalendarRangeFilterValue;
readonly conditionId?: number;
readonly active: boolean
}

CalendarDateFilterState (Extended from index.ts)

Section titled “CalendarDateFilterState (Extended from index.ts)”
interface CalendarDateFilterState {
readonly operator: CalendarDateOperator
}

CALENDAR_RANGE_FILTERS: Record<"calendarRangeBetween" | "calendarRangeEquals" | "calendarRangeNotEqual" | "calendarRangeBefore" | "calendarRangeOnOrBefore" | "calendarRangeAfter" | "calendarRangeOnOrAfter", CustomFilter<any, LogicFunctionExtraParam>>;

export function isCalendarDateOperator(value: unknown): value is CalendarDateOperator;

export function resolveCalendarDateOperators(
operators: readonly CalendarDateOperator[] | undefined,
): readonly CalendarDateOperator[];

CALENDAR_RANGE_BETWEEN: string;

CALENDAR_DATE_OPERATOR_SEMANTICS: Readonly<{ readonly calendarRangeEquals: "equals"; readonly calendarRangeNotEqual: "notEqual"; readonly calendarRangeBefore: "before"; readonly calendarRangeOnOrBefore: "onOrBefore"; readonly calendarRangeAfter: "after"; readonly calendarRangeOnOrAfter: "onOrAfter"; }>;

CALENDAR_DATE_SINGLE_OPERATORS: ("calendarRangeEquals" | "calendarRangeNotEqual" | "calendarRangeBefore" | "calendarRangeOnOrBefore" | "calendarRangeAfter" | "calendarRangeOnOrAfter")[];

CALENDAR_DATE_OPERATORS: readonly ["calendarRangeBetween", ...("calendarRangeEquals" | "calendarRangeNotEqual" | "calendarRangeBefore" | "calendarRangeOnOrBefore" | "calendarRangeAfter" | "calendarRangeOnOrAfter")[]];

export type CalendarDateSingleOperator = keyof typeof CALENDAR_DATE_OPERATOR_SEMANTICS;

export type CalendarDateOperator = typeof CALENDAR_DATE_OPERATORS[number];

export function defineCalendarRangeEditor(
host: HTMLElement,
context: StructuredFilterBodyContext,
options?: CalendarRangeOptions,
);

export function CalendarRangeEditor({
context,
options,
}: {
context: StructuredFilterBodyContext;
options?: CalendarRangeOptions;
});

export function calendarRangeCaption(
labels: StructuredFilterLabels,
id: CalendarRangeCaptionId,
): string;

Public localization keys and English fallbacks for the calendar-range filter.

CALENDAR_RANGE_LOCALIZATION: Readonly<{ filterNames: Readonly<{ calendarRangeBetween: "Is in calendar range"; calendarRangeEquals: "Is on"; calendarRangeNotEqual: "Is not on"; calendarRangeBefore: "Is before"; calendarRangeOnOrBefore: "Is on or before"; calendarRangeAfter: "Is after"; calendarRangeOnOrAfter: "Is on or after"; }>; captions: Readonly<{ calendarRangeTitle: "Calendar range"; calendarRangeOperator: "Date operator"; calendarRangeBetween: "between"; calendarRangeChooseEnd: "Choose end date"; calendarRangeEmpty: "No range selected"; calendarRangeClear: "Clear date range"; calendarRangePreviousMonth: "Previous month"; calendarRangeNextMonth: "Next month"; calendarRangePreviousYear: "Previous year"; calendarRangeNextYear: "Next year"; calendarRangeChooseMonth: "Choose month"; calendarRangeCalendar: "Calendar"; calendarRangeToday: "Today"; calendarRangeInvalid: "Choose a valid range."; calendarRangeSameDay: "Choose two different dates."; calendarRangeTooShort: "Select a longer range."; calendarRangeTooLong: "Select a shorter range."; calendarRangeContainsDisabledDate: "The range contains an unavailable date."; }>; }>;

export type CalendarRangeCaptionId = keyof typeof CALENDAR_RANGE_LOCALIZATION.captions;

Creates the opt-in relative / rolling date-window body.

export function createRelativeWindowStructuredFilterType(
options?: RelativeWindowOptions,
): StructuredFilterType;

relativeWindowStructuredFilterType: StructuredFilterType;

export function parseRelativeWindowValue(value: unknown): RelativeDateWindowExpression | undefined;

export function relativeWindowStateFromConditions(
conditions: readonly Readonly<{ id?: unknown; type: string; value?: unknown }>[],
): RelativeWindowState;

export function relativeWindowCondition(
expression: unknown,
conditionId?: number,
): StructuredFilterCondition[] | undefined;

export function resolveRelativeWindowPreview(
today: ISODateString,
expression: RelativeDateWindowExpression,
settings: Pick<ResolvedDateFilterSettings, 'weekStartsOn' | 'fiscalYearStart'>,
): RelativeDateWindowRange | undefined;

export function createRelativeWindowFilters(
runtime: TemporalFilterRuntime = new TemporalFilterRuntime(),
): Record<typeof RELATIVE_WINDOW_OPERATOR, CustomFilter>;

FILTER_RELATIVE_WINDOW: string;

RELATIVE_WINDOW_OPERATOR: string;

interface RelativeWindowState {
readonly active: boolean;
readonly expression?: RelativeDateWindowExpression;
readonly conditionId?: number;
readonly invalid?: boolean
}

RELATIVE_WINDOW_FILTERS: Record<"relativeWindow", CustomFilter<any, LogicFunctionExtraParam>>;

export function defineRelativeWindowEditor(
host: HTMLElement,
context: StructuredFilterBodyContext,
options?: RelativeWindowOptions,
);

export function RelativeWindowEditor({
context,
options,
}: {
context: StructuredFilterBodyContext;
options?: RelativeWindowOptions;
});

export function relativeWindowCaption(labels: StructuredFilterLabels, id: RelativeWindowCaptionId);

export function relativeWindowMessage(
labels: StructuredFilterLabels,
id: RelativeWindowCaptionId,
values: RelativeWindowMessageValues = {},
);

export function relativeWindowPresetCaption(
labels: StructuredFilterLabels,
preset: RelativeDateWindowPreset,
);

export function relativeWindowUnitCaption(
labels: StructuredFilterLabels,
unit: RelativeDateWindowUnit,
amount: number,
);

export function relativeWindowRollingDetail(labels: StructuredFilterLabels);

RELATIVE_WINDOW_LOCALIZATION: Readonly<{ filterNames: Readonly<{ relativeWindow: "Is in relative window"; }>; detailFallbacks: Readonly<{ rolling: "Rolling"; }>; captions: Readonly<{ relativeWindowLast7Days: "Last 7 days"; relativeWindowToday: "Today"; relativeWindowThisMonth: "This month"; relativeWindowThisQuarter: "This quarter"; relativeWindowYtd: "YTD"; relativeWindowOverdue: "Overdue"; relativeWindowBeforeDate: "Before {date}"; relativeWindowInvalidPreview: "Choose a valid window"; relativeWindowTitle: "Relative / rolling window"; relativeWindowDescription: "Filter dates relative to the current day."; relativeWindowEmpty: "No window selected"; relativeWindowInvalidSaved: "The saved relative window is invalid. Choose a new window or clear it."; relativeWindowClear: "Clear"; relativeWindowPresets: "Date presets"; relativeWindowCustom: "Custom window"; relativeWindowDirection: "Direction"; relativeWindowLast: "Last"; relativeWindowNext: "Next"; relativeWindowAmount: "Amount"; relativeWindowUnit: "Unit"; relativeWindowDay: "day"; relativeWindowDays: "Days"; relativeWindowWeek: "week"; relativeWindowWeeks: "Weeks"; relativeWindowMonth: "month"; relativeWindowMonths: "Months"; relativeWindowQuarter: "quarter"; relativeWindowQuarters: "Quarters"; relativeWindowYear: "year"; relativeWindowYears: "Years"; relativeWindowRolling: "Rolling (re-evaluate daily)"; relativeWindowInvalidAmount: "Enter a whole number greater than zero."; relativeWindowCustomSummary: "{direction} {amount} {unit}"; }>; }>;

RELATIVE_WINDOW_PRESET_CAPTIONS: Readonly<Record<RelativeDateWindowPreset, "relativeWindowLast7Days" | "relativeWindowToday" | "relativeWindowThisMonth" | "relativeWindowThisQuarter" | "relativeWindowYtd" | "relativeWindowOverdue" | "relativeWindowBeforeDate" | "relativeWindowInvalidPreview" | "relativeWindowTitle" | "relativeWindowDescription" | "relativeWindowEmpty" | "relativeWindowInvalidSaved" | "relativeWindowClear" | "relativeWindowPresets" | "relativeWindowCustom" | "relativeWindowDirection" | "relativeWindowLast" | "relativeWindowNext" | "relativeWindowAmount" | "relativeWindowUnit" | "relativeWindowDay" | "relativeWindowDays" | "relativeWindowWeek" | "relativeWindowWeeks" | "relativeWindowMonth" | "relativeWindowMonths" | "relativeWindowQuarter" | "relativeWindowQuarters" | "relativeWindowYear" | "relativeWindowYears" | "relativeWindowRolling" | "relativeWindowInvalidAmount" | "relativeWindowCustomSummary">>;

export type RelativeWindowCaptionId = keyof typeof RELATIVE_WINDOW_LOCALIZATION.captions;

export type RelativeWindowMessageValues = Readonly<Record<string, string | number>>;

export function resolveRelativeWindowOptions(
options?: RelativeWindowOptions,
): ResolvedRelativeWindowOptions;

export function relativeWindowExpressionKey(expression: RelativeDateWindowExpression): string;

DEFAULT_RELATIVE_WINDOW_PRESETS: readonly RelativeDateWindowPreset[];

A user-defined shortcut button backed by a valid, stable relative-window expression.

interface RelativeWindowShortcut {
readonly id: string;
readonly label: string;
readonly expression: RelativeDateWindowExpression;
readonly ariaLabel?: string;
readonly title?: string;
readonly disabled?: boolean
}

export type RelativeWindowPresetOption = RelativeDateWindowPreset | RelativeWindowShortcut;

interface RelativeWindowCustomWindowOptions {
readonly directions?: readonly RelativeDateWindowDirection[];
readonly units?: readonly RelativeDateWindowUnit[];
readonly showRolling?: boolean;
readonly defaultValue?: Readonly<{
direction: RelativeDateWindowDirection;
amount: number;
unit: RelativeDateWindowUnit;
rolling: boolean;
}>
}

interface RelativeWindowOptions {
readonly locale?: string;
readonly dateFormat?: Intl.DateTimeFormatOptions;
/** Built-in preset ids and custom shortcuts, in display order. `false` hides the shortcut group. */
readonly presets?: false | readonly RelativeWindowPresetOption[];
/** Custom last/next editor configuration. `false` hides the custom editor. */
readonly customWindow?: false | RelativeWindowCustomWindowOptions;
readonly showHeading?: boolean;
readonly showPreview?: boolean
}

ResolvedRelativeWindowShortcut (Extended from index.ts)

Section titled “ResolvedRelativeWindowShortcut (Extended from index.ts)”
interface ResolvedRelativeWindowShortcut {
readonly builtInPreset?: RelativeDateWindowPreset
}

interface ResolvedRelativeWindowCustomWindow {
readonly directions: readonly RelativeDateWindowDirection[];
readonly units: readonly RelativeDateWindowUnit[];
readonly showRolling: boolean;
readonly defaultValue: Extract<RelativeDateWindowExpression, { mode: 'custom' }>
}

interface ResolvedRelativeWindowOptions {
readonly locale?: string;
readonly dateFormat?: Intl.DateTimeFormatOptions;
readonly presets: readonly ResolvedRelativeWindowShortcut[];
readonly customWindow: false | ResolvedRelativeWindowCustomWindow;
readonly showHeading: boolean;
readonly showPreview: boolean
}

Creates an opt-in temporal histogram/brush with deterministic presentation options.

export function createTimelineBrushStructuredFilterType(
options?: TimelineBrushOptions,
): StructuredFilterType;

timelineBrushStructuredFilterType: StructuredFilterType;

export function timelineModelFromPreparedData(
value: unknown,
granularity: TimelineBrushGranularity,
): TimelineBrushModel | undefined;

export function resolveTimelineBrushOptions(
column: ColumnRegular,
settings: ResolvedDateFilterSettings,
options: TimelineBrushOptions = {},
): ResolvedTimelineBrushOptions;

export function timelineBrushFamily(values: readonly unknown[], column: ColumnRegular): TemporalFilterFamily;

export function parseTimelineBrushPoints(
values: readonly unknown[],
family: TemporalFilterFamily,
timeZone: string,
): readonly TimelineBrushPoint[];

export function createTimelineBrushModel(
values: readonly unknown[],
family: TemporalFilterFamily,
options: Pick<ResolvedTimelineBrushOptions, 'granularity' | 'binCap' | 'timeZone'> & {
weekStartsOn?: ResolvedTimelineBrushOptions['weekStartsOn'];
fiscalYearStart?: ResolvedTimelineBrushOptions['fiscalYearStart'];
},
): TimelineBrushModel;

export function parseTimelineBetweenValue(value: unknown): TimelineBetweenValue | undefined;

export function timelineBrushStateFromConditions(
conditions: readonly Readonly<{ id?: unknown; type: string; value?: unknown }>[],
model: TimelineBrushModel,
): TimelineBrushState;

export function timelineBrushCondition(
start: number,
end: number,
model: TimelineBrushModel,
conditionId?: number,
): StructuredFilterCondition[];

export function timelineBrushPosition(index: number, binCount: number);

export function timelineBrushIndex(position: number, binCount: number);

export function timelineBrushBinSelected(index: number, start: number, end: number);

export function formatTimelineBrushLabel(
value: string,
options: ResolvedTimelineBrushOptions,
includeYear = true,
);

export function createTimelineBrushFilters(
runtime: TemporalFilterRuntime = new TemporalFilterRuntime(),
): Record<typeof TIMELINE_BETWEEN, CustomFilter>;

FILTER_TIMELINE_BRUSH: string;

TIMELINE_BETWEEN: string;

TIMELINE_BRUSH_STEPS: 1000;

export type TimelineBrushGranularity = 'day' | 'week' | 'month' | 'year' | 'fiscalYear';

interface TimelineBetweenValue {
readonly from: string;
readonly to: string;
readonly inclusive: true
}

interface TimelineBrushFormatContext {
readonly column: ColumnRegular;
readonly granularity: TimelineBrushGranularity;
readonly locale: string;
readonly timeZone: string;
readonly weekStartsOn: ResolvedDateFilterSettings['weekStartsOn'];
readonly fiscalYearStart: ResolvedDateFilterSettings['fiscalYearStart']
}

interface TimelineBrushOptions {
/** Initial calendar resolution. Falls back to the first enabled granularity. */
readonly granularity?: TimelineBrushGranularity;
/** Calendar resolutions that users can select. Defaults to day, week, month, and year. */
readonly granularities?: readonly TimelineBrushGranularity[];
/** Maximum number of rendered bars after deterministic coarsening. Defaults to 48. */
readonly binCap?: number;
/** IANA timezone used for calendar bins and labels. Inherits `filter.date`. */
readonly timeZone?: string;
/**
* Intl options or a callback for boundary and selection labels. Omit this to
* use compact month/day labels within one year and two-digit years across years.
* An explicit value is used verbatim.
*/
readonly format?: Intl.DateTimeFormatOptions | ((value: string, context: TimelineBrushFormatContext) => string);
readonly locale?: string;
/** Presentation-only chart configuration. Filtering and prepared-data contracts are unchanged. */
readonly chart?: TimelineBrushChartOptions
}

TimelineBrushChartTooltipContext (Extended from index.ts)

Section titled “TimelineBrushChartTooltipContext (Extended from index.ts)”
interface TimelineBrushChartTooltipContext {
readonly index: number;
readonly selected: boolean;
readonly fromLabel: string;
readonly toLabel: string
}

interface TimelineBrushChartOptions {
readonly type?: DistributionChartType;
readonly height?: number;
readonly showPoints?: boolean;
readonly formatTooltip?: (
bin: TimelineBrushBin,
context: TimelineBrushChartTooltipContext,
) => DistributionChartTooltip
}

ResolvedTimelineBrushOptions (Extended from index.ts)

Section titled “ResolvedTimelineBrushOptions (Extended from index.ts)”
interface ResolvedTimelineBrushOptions {
readonly binCap: number;
readonly granularities: readonly TimelineBrushGranularity[];
readonly format: NonNullable<TimelineBrushOptions['format']>;
/** Whether `format` is the adaptive built-in default rather than a user override. */
readonly usesDefaultFormat: boolean
}

interface TimelineBrushPoint {
readonly instant: Date;
readonly date: ISODateString;
readonly boundary: string
}

interface TimelineBrushBin {
readonly from: ISODateString;
readonly to: ISODateString;
readonly count: number;
/** Inclusive UTC instants for datetime-family filtering. */
readonly fromInstant?: string;
readonly toInstant?: string
}

interface TimelineBrushModel {
readonly family: TemporalFilterFamily;
readonly granularity: TimelineBrushGranularity;
readonly effectiveGranularity: TimelineBrushGranularity;
readonly bins: readonly TimelineBrushBin[]
}

interface TimelineBrushPreparedData {
readonly kind: 'timelineBrush';
readonly models: Partial<Record<TimelineBrushGranularity, TimelineBrushModel>>
}

interface TimelineBrushState {
readonly start: number;
readonly end: number;
readonly conditionId?: number
}

TIMELINE_BRUSH_FILTERS: Record<"timelineBetween", CustomFilter<any, LogicFunctionExtraParam>>;

export function defineTimelineBrushEditor(
host: HTMLElement,
context: StructuredFilterBodyContext,
options?: TimelineBrushOptions,
);

export function TimelineBrushEditor({
context,
options,
}: {
context: StructuredFilterBodyContext;
options?: TimelineBrushOptions;
});

export function timelineBrushCaption(labels: StructuredFilterLabels, id: TimelineBrushCaptionId);

export function timelineBrushMessage(
labels: StructuredFilterLabels,
id: TimelineBrushCaptionId,
values: TimelineBrushMessageValues = {},
);

export function timelineGranularityCaption(
labels: StructuredFilterLabels,
granularity: TimelineBrushGranularity,
);

TIMELINE_BRUSH_LOCALIZATION: Readonly<{ filterNames: Readonly<{ timelineBetween: "Is in timeline range"; }>; captions: Readonly<{ timelineBrushTitle: "Timeline"; timelineBrushDescription: "Brush a date range over time."; timelineBrushNoRange: "No range selected"; timelineBrushSummary: "{from} → {to} · by {granularity}"; timelineBrushNoValues: "No valid dates available."; timelineBrushItem: "item"; timelineBrushItems: "items"; timelineBrushSelected: "Selected"; timelineBrushOutsideSelection: "Outside selection"; timelineBrushChart: "Timeline distribution"; timelineBrushStart: "Range start"; timelineBrushEnd: "Range end"; timelineBrushGranularity: "Timeline granularity"; timelineBrushDay: "day"; timelineBrushWeek: "week"; timelineBrushMonth: "month"; timelineBrushYear: "year"; timelineBrushFiscalYear: "fiscal year"; }>; }>;

TIMELINE_GRANULARITY_CAPTIONS: Readonly<Record<TimelineBrushGranularity, "timelineBrushTitle" | "timelineBrushDescription" | "timelineBrushNoRange" | "timelineBrushSummary" | "timelineBrushNoValues" | "timelineBrushItem" | "timelineBrushItems" | "timelineBrushSelected" | "timelineBrushOutsideSelection" | "timelineBrushChart" | "timelineBrushStart" | "timelineBrushEnd" | "timelineBrushGranularity" | "timelineBrushDay" | "timelineBrushWeek" | "timelineBrushMonth" | "timelineBrushYear" | "timelineBrushFiscalYear">>;

export type TimelineBrushCaptionId = keyof typeof TIMELINE_BRUSH_LOCALIZATION.captions;

export type TimelineBrushMessageValues = Readonly<Record<string, string | number>>;

Creates an opt-in weekday/hour matrix with one lossless structured condition.

export function createTimeMatrixStructuredFilterType(
options?: TimeMatrixOptions,
): StructuredFilterType;

timeMatrixStructuredFilterType: StructuredFilterType;

export function timeMatrixCellKey(weekday: number, hour: number);

export function timeMatrixCellSelected(cells: ReadonlySet<string>, weekday: number, hour: number);

export function timeMatrixCellsFromRanges(ranges: readonly TimeMatrixRange[]);

export function timeMatrixRangesFromCells(cells: ReadonlySet<string>): readonly TimeMatrixRange[];

export function parseTimeMatrixValue(value: unknown): TimeMatrixFilterValue | undefined;

export function timeMatrixStateFromConditions(
conditions: readonly Readonly<{ id?: unknown; type: string; value?: unknown }>[],
): TimeMatrixState;

export function timeMatrixCondition(
cells: ReadonlySet<string>,
timeZone: string,
conditionId?: number,
): StructuredFilterCondition[];

export function timeMatrixPresetCells(preset: TimeMatrixPreset | ResolvedTimeMatrixPreset);

export function timeMatrixCellsEqual(left: ReadonlySet<string>, right: ReadonlySet<string>);

export function timeMatrixSelectionSummary(
cells: ReadonlySet<string>,
timeZone: string,
options: TimeMatrixSelectionSummaryOptions = {},
);

export function resolveTimeMatrixOptions(
column: ColumnRegular,
settings: ResolvedDateFilterSettings,
options: TimeMatrixOptions = {},
): ResolvedTimeMatrixOptions;

export function createTimeMatrixFilters(): Record<typeof TIME_MATRIX_OPERATOR, CustomFilter>;

FILTER_TIME_MATRIX: string;

TIME_MATRIX_OPERATOR: string;

TIME_MATRIX_VERSION: 1;

More ranges are necessarily redundant because the matrix has 168 cells.

TIME_MATRIX_MAX_INPUT_RANGES: number;

interface TimeMatrixRange {
/** Sunday is 0 and Saturday is 6. */
readonly weekday: number;
/** Inclusive whole-hour boundary. */
readonly startHour: number;
/** Exclusive whole-hour boundary. */
readonly endHour: number
}

interface TimeMatrixFilterValue {
readonly version: typeof TIME_MATRIX_VERSION;
readonly timeZone: string;
readonly ranges: readonly TimeMatrixRange[]
}

export type TimeMatrixPreset = 'businessHours' | 'weekends' | 'nights';

interface TimeMatrixPresetWindow {
/** Optional visible label override for this shortcut. */
readonly label?: string;
/** Optional tooltip override describing the configured shortcut. */
readonly description?: string;
/** Sunday is 0 and Saturday is 6. */
readonly days?: readonly number[];
/** Inclusive whole-hour boundary. */
readonly startHour?: number;
/** Exclusive whole-hour boundary. Values before startHour create an overnight window. */
readonly endHour?: number
}

interface TimeMatrixPresetOptions {
readonly businessHours?: false | TimeMatrixPresetWindow;
readonly weekends?: false | Omit<TimeMatrixPresetWindow, 'startHour' | 'endHour'>;
readonly nights?: false | TimeMatrixPresetWindow
}

interface ResolvedTimeMatrixPreset {
readonly id: TimeMatrixPreset;
readonly days: readonly number[];
readonly startHour: number;
readonly endHour: number;
readonly label?: string;
readonly description?: string
}

interface TimeMatrixWorkingHours {
/** Inclusive whole-hour boundary. */
readonly startHour: number;
/** Exclusive whole-hour boundary. */
readonly endHour: number
}

interface TimeMatrixOptions {
/** IANA timezone used for matching. Inherits the column's date settings. */
readonly timeZone?: string;
readonly locale?: string;
/** Sunday is 0 and Saturday is 6. Inherits the column's date settings. */
readonly weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
readonly useAmPm?: boolean;
/** Context shading only; filtering remains driven by the selected cells. */
readonly workingHours?: false | TimeMatrixWorkingHours;
/** Sunday is 0 and Saturday is 6. Defaults to both. */
readonly weekendDays?: readonly number[];
/** Hides schedule-context legend without changing matrix behavior. */
readonly showLegend?: boolean;
/** Configure each built-in shortcut, use false per shortcut to hide it, or false to hide all. */
readonly presets?: false | TimeMatrixPresetOptions
}

interface ResolvedTimeMatrixOptions {
readonly column: ColumnRegular;
readonly timeZone: string;
readonly locale: string;
readonly weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6;
readonly useAmPm: boolean;
readonly workingHours?: TimeMatrixWorkingHours;
readonly weekendDays: readonly number[];
readonly showLegend: boolean;
readonly presets: readonly ResolvedTimeMatrixPreset[]
}

interface TimeMatrixState {
readonly value?: TimeMatrixFilterValue;
readonly conditionId?: number
}

interface TimeMatrixSelectionSummaryOptions {
readonly weekdayLabel?: (weekday: number) => string;
readonly hourLabel?: (hour: number) => string;
readonly message?: (id: TimeMatrixCaptionId, values: TimeMatrixMessageValues) => string
}

TIME_MATRIX_FILTERS: Record<"timeMatrix", CustomFilter<any, LogicFunctionExtraParam>>;

export function defineTimeMatrixEditor(
host: HTMLElement,
context: StructuredFilterBodyContext,
options?: TimeMatrixOptions,
);

export function TimeMatrixEditor({
context,
options,
}: {
context: StructuredFilterBodyContext;
options?: TimeMatrixOptions;
});

Creates the non-interactive schedule summary rendered inside the shared popup trigger.

export function createTimeMatrixHeaderTemplate(
options: TimeMatrixHeaderTemplateOptions,
): FilterHeaderTemplateFunc;

interface TimeMatrixHeaderTemplateOptions {
readonly labels: StructuredFilterLabels;
readonly hourLabel: (hour: number) => string;
readonly weekStartsOn: number
}

export function timeMatrixCaption(
labels: StructuredFilterLabels,
id: TimeMatrixCaptionId,
): string;

export function timeMatrixMessage(
labels: StructuredFilterLabels,
id: TimeMatrixCaptionId,
values: TimeMatrixMessageValues = {},
): string;

export function timeMatrixFallbackMessage(
id: TimeMatrixCaptionId,
values: TimeMatrixMessageValues = {},
): string;

export function timeMatrixWeekdayCaption(
labels: StructuredFilterLabels,
weekday: number,
);

export function timeMatrixFallbackWeekdayCaption(weekday: number);

Stable localization keys and complete English fallbacks for the activity-time matrix.

TIME_MATRIX_LOCALIZATION: Readonly<{ filterNames: Readonly<{ timeMatrix: "Matches time matrix"; }>; captions: Readonly<{ timeMatrixAriaTitle: "Time-of-day and weekday matrix"; timeMatrixTitle: "Time-of-day / weekday"; timeMatrixDescription: "Select the weekday and hour combinations to include."; timeMatrixGrid: "Weekday by hour selection"; timeMatrixClear: "Clear"; timeMatrixPresets: "Time presets"; timeMatrixLegend: "Schedule context"; timeMatrixLegendSelected: "Selected"; timeMatrixLegendOutsideWorkHours: "Outside work hours"; timeMatrixLegendWeekend: "Weekend"; timeMatrixCellLabel: "{day}, {start}–{end}, {state}"; timeMatrixCellStateSelected: "selected"; timeMatrixCellStateNotSelected: "not selected"; timeMatrixWeekdayShortSunday: "Sun"; timeMatrixWeekdayShortMonday: "Mon"; timeMatrixWeekdayShortTuesday: "Tue"; timeMatrixWeekdayShortWednesday: "Wed"; timeMatrixWeekdayShortThursday: "Thu"; timeMatrixWeekdayShortFriday: "Fri"; timeMatrixWeekdayShortSaturday: "Sat"; timeMatrixSummaryEmpty: "No times selected"; timeMatrixWeekdayRange: "{start}–{end}"; timeMatrixSummaryRange: "{days}, {start}–{end} selected"; timeMatrixSummaryHoursOneDay: "{hours} hours across {days} day · {timeZone}"; timeMatrixSummaryHoursManyDays: "{hours} hours across {days} days · {timeZone}"; timeMatrixHeaderAnyTime: "Any time"; timeMatrixHeaderEveryDay: "Every day"; timeMatrixHeaderAllDay: "All day"; timeMatrixHeaderRange: "{start}–{end}"; timeMatrixHeaderCustomDays: "{days} days"; timeMatrixHeaderCustomHours: "{hours} hours · Custom"; timeMatrixBadgeSummaryOne: "1 hour selected"; timeMatrixBadgeSummaryMany: "{hours} hours selected"; timeMatrixBadgeDetails: "{selection} · {timeZone}"; 'timeMatrixPreset.businessHours': "Business hours"; 'timeMatrixPreset.weekends': "Weekends"; 'timeMatrixPreset.nights': "Nights"; 'timeMatrixPresetDescription.businessHours': "Mon–Fri, 08:00–20:00"; 'timeMatrixPresetDescription.weekends': "Saturday and Sunday"; 'timeMatrixPresetDescription.nights': "Every day, 22:00–06:00"; }>; }>;

export type TimeMatrixCaptionId = keyof typeof TIME_MATRIX_LOCALIZATION.captions;

export type TimeMatrixMessageValues = Readonly<Record<string, string | number>>;

triStateBooleanStructuredFilterType: {
id: string;
operatorIds: string[];
aggregateNeeds: "valueCounts"[];
validateValue: typeof isValidTriStateBooleanValue;
mount: (host: HTMLElement, context: StructuredFilterBodyContext) => PreactRootDisposer;
describeCondition: ({ condition, labels }: StructuredFilterPresentationContext) => { details?: string | undefined; summary: string; } | undefined;
render: (context: StructuredFilterBodyContext) => any;
};

Checks the exact transport shape emitted for an active boolean condition.

export function isValidTriStateBooleanValue(value: unknown): value is TriStateBooleanFilterValue;

Restores only the JSON-safe state emitted by this structured filter.

export function parseTriStateBooleanValue(value: unknown): TriStateBooleanState;

export function triStateBooleanStateFromConditions(
conditions: readonly Readonly<{ id?: unknown; type: string; value?: unknown }>[],
): TriStateBooleanState;

export function triStateBooleanCondition(
state: TriStateBooleanChoice,
coerceBlank: boolean,
conditionId?: number,
): StructuredFilterCondition[];

export function triStateBooleanMatches(
value: LogicFunctionParam,
state: TriStateBooleanChoice,
coerceBlank: boolean,
context?: FilterEvaluationContext,
);

FILTER_TRI_STATE_BOOLEAN: string;

TRI_STATE_BOOLEAN_OPERATOR: string;

TRI_STATE_BOOLEAN_CHOICES: readonly ["all", "yes", "no"];

export type TriStateBooleanChoice = typeof TRI_STATE_BOOLEAN_CHOICES[number];

interface TriStateBooleanFilterValue {
readonly state: Exclude<TriStateBooleanChoice, 'all'>;
readonly coerceBlank: boolean
}

interface TriStateBooleanState {
readonly state: TriStateBooleanChoice;
readonly coerceBlank: boolean;
readonly conditionId?: number
}

triStateBoolean: LogicFunction<any, LogicFunctionExtraParam>;

TRI_STATE_BOOLEAN_FILTERS: {
[TRI_STATE_BOOLEAN_OPERATOR]: { columnFilterType: string; name: "Is Yes or No"; func: LogicFunction<any, LogicFunctionExtraParam>; };
};

export function defineTriStateBooleanEditor(host: HTMLElement, context: StructuredFilterBodyContext);

export function TriStateBooleanEditor({ context }: { context: StructuredFilterBodyContext });

arrayTagsStructuredFilterType: {
id: string;
operatorIds: string[];
aggregateNeeds: "values"[];
validateValue: typeof isValidArrayTagsFilterValue;
describeCondition: ({ condition, column, config, labels }: StructuredFilterPresentationContext) => { summary: string; details: string; };
getHeaderSelection: ({ condition, column, config, aggregates, labels }: StructuredFilterHeaderSelectionContext) => { values: { value: string; label: string; count: number; }[]; totalCount: number; } | undefined;
mount: (host: HTMLElement, context: StructuredFilterBodyContext) => PreactRootDisposer;
render: (context: StructuredFilterBodyContext) => any;
};

export function resolveArrayTagsAccessor(
options: ArrayTagsOptions | undefined,
property: ColumnProp,
): ArrayTagsAccessor;

export function resolveArrayTagsLabelFormatter(
options: ArrayTagsOptions | undefined,
property: ColumnProp,
): ArrayTagsLabelFormatter | undefined;

export function isArrayTagValue(value: unknown): value is ArrayTagValue;

JSON-safe typed identity; labels do not participate in equality.

export function arrayTagId(value: ArrayTagValue);

export function arrayTagLabel(
value: ArrayTagValue,
labels: ArrayTagLabelText = DEFAULT_ARRAY_TAG_LABEL_TEXT,
);

Keeps compact labels unless typed-distinct values would look identical.

export function arrayTagLabels(
values: readonly ArrayTagValue[],
labels: ArrayTagLabelText = DEFAULT_ARRAY_TAG_LABEL_TEXT,
formatLabel?: (value: ArrayTagValue) => string | undefined,
);

Removes unsupported values and duplicates while retaining first-seen order.

export function normalizeArrayTags(values: readonly unknown[]);

export function flattenArrayTagValues(
cellValues: readonly unknown[],
accessor: ArrayTagsAccessor = value => value,
property: ColumnProp = '',
column?: FilterEvaluationContext['column'],
limit = Number.POSITIVE_INFINITY,
);

Checks the lossless transport shape before canonical state is replaced.

export function isValidArrayTagsFilterValue(value: unknown): value is ArrayTagsFilterValue;

Restores only the JSON-safe shape emitted by this filter.

export function parseArrayTagsFilterValue(value: unknown): ArrayTagsFilterValue;

export function arrayTagsStateFromConditions(
conditions: readonly Readonly<{ id?: unknown; type: string; value?: unknown }>[],
): ArrayTagsState;

export function arrayTagsCondition(
value: ArrayTagsFilterValue,
conditionId?: number,
): StructuredFilterCondition[];

export function arrayTagsMatches(
cellValue: unknown,
filterValue: unknown,
accessor: ArrayTagsAccessor = value => value,
context?: FilterEvaluationContext,
);

export function createArrayTagsFilters(options?: ArrayTagsOptions): Record<typeof ARRAY_TAGS_MATCH, CustomFilter>;

FILTER_ARRAY_TAGS: string;

ARRAY_TAGS_MATCH: string;

ARRAY_TAGS_MODES: readonly ["any", "all", "none"];

Keeps a high-cardinality column from creating an unbounded tag picker.

ARRAY_TAGS_OPTION_LIMIT: 200;

export type ArrayTagsMode = typeof ARRAY_TAGS_MODES[number];

export type ArrayTagValue = string | number | boolean | null;

interface ArrayTagsFilterValue {
readonly mode: ArrayTagsMode;
readonly values: readonly ArrayTagValue[];
readonly emptyOnly: boolean;
readonly exact: boolean
}

interface ArrayTagsState {
readonly conditionId?: number
}

interface ArrayTagsAccessorContext {
readonly property: ColumnProp;
readonly column?: FilterEvaluationContext['column'];
readonly model?: FilterEvaluationContext['model']
}

Returns the array whose members should be treated as tags for one cell.

/** Returns the array whose members should be treated as tags for one cell. */
export type ArrayTagsAccessor = (
cellValue: unknown,
context: ArrayTagsAccessorContext,
) => unknown;

interface ArrayTagsFormatLabelContext {
readonly property: ColumnProp;
readonly column?: FilterEvaluationContext['column']
}

Presents one stored scalar tag without changing its typed filter identity.

/** Presents one stored scalar tag without changing its typed filter identity. */
export type ArrayTagsLabelFormatter = (
value: ArrayTagValue,
context: ArrayTagsFormatLabelContext,
) => string | undefined;

interface ArrayTagsColumnOptions {
readonly accessor?: ArrayTagsAccessor;
readonly formatLabel?: ArrayTagsLabelFormatter
}

interface ArrayTagsOptions {
readonly accessor?: ArrayTagsAccessor;
readonly formatLabel?: ArrayTagsLabelFormatter;
readonly columns?: Readonly<Record<string, ArrayTagsColumnOptions>>
}

interface ArrayTagLabelText {
readonly blank: string;
readonly true: string;
readonly false: string;
readonly stringType: string;
readonly numberType: string;
readonly booleanType: string;
readonly nullType: string
}

DEFAULT_ARRAY_TAG_LABEL_TEXT: {
blank: string;
true: string;
false: string;
stringType: string;
numberType: string;
booleanType: string;
nullType: string;
};

ARRAY_TAGS_FILTERS: Record<"arrayTagsMatch", CustomFilter<any, LogicFunctionExtraParam>>;

export function defineArrayTagsEditor(host: HTMLElement, context: StructuredFilterBodyContext);

export function ArrayTagsEditor({ context }: { context: StructuredFilterBodyContext });

export function arrayTagsCaption(labels: StructuredFilterLabels, id: ArrayTagsCaptionId);

export function arrayTagsMessage(labels: StructuredFilterLabels, id: ArrayTagsCaptionId, values: StructuredFilterMessageValues = {});

ARRAY_TAGS_LOCALIZATION: Readonly<{ filterNames: Readonly<{ arrayTagsMatch: "Matches array tags"; }>; captions: Readonly<{ arrayTagsHeaderPlaceholder: "Any tags"; arrayTagsBlank: "Blank"; arrayTagsTrue: "True"; arrayTagsFalse: "False"; arrayTagsTypeString: "string"; arrayTagsTypeNumber: "number"; arrayTagsTypeBoolean: "boolean"; arrayTagsTypeNull: "blank"; arrayTagsStringType: "string"; arrayTagsNumberType: "number"; arrayTagsBooleanType: "boolean"; arrayTagsBlankType: "blank"; arrayTagsTitle: "Array / tags"; arrayTagsDescription: "Choose tags and how each cell array should match them."; arrayTagsMode: "Tag match mode"; arrayTagsAny: "has any"; arrayTagsAll: "has all"; arrayTagsNone: "has none"; arrayTagsModeAny: "any"; arrayTagsModeAll: "all"; arrayTagsModeNone: "none"; arrayTagsAvailable: "Available tags"; arrayTagsNoValues: "No tags found in array values."; arrayTagsEmptyOnly: "Empty list only"; arrayTagsExact: "Exact set match"; arrayTagsSelected: "{summary}"; arrayTagsSelectedEmpty: "Empty arrays only"; arrayTagsSelectedOne: "1 tag selected"; arrayTagsSelectedMany: "{count} tags selected"; arrayTagsEmptyListsOnly: "empty lists only"; arrayTagsExactSet: "exact set"; arrayTagsSummaryOne: "1 tag"; arrayTagsSummaryMany: "{count} tags"; }>; }>;

export type ArrayTagsCaptionId = keyof typeof ARRAY_TAGS_LOCALIZATION.captions;

Built-ins are registered by the Pro filter plugin but remain column opt-in.

BUILT_IN_STRUCTURED_FILTER_TYPES: readonly StructuredFilterType[];

export function formatGroupedFilterMessage(
template: string,
values: Readonly<Record<string, string | number>> = {},
);

export function groupedFilterMessage(
translations: GroupedFilterTranslations,
key: GroupedFilterLabelKey,
values?: Readonly<Record<string, string | number>>,
);

export function resolveGroupedFilterTranslations(
captions?: Readonly<Record<string, unknown>>,
overrides: GroupedFilterTranslationOverrides = {},
): GroupedFilterTranslations;

DEFAULT_GROUPED_FILTER_LABELS: { readonly launcher: "Groups"; readonly noConditions: "No filter conditions"; readonly builderAria: "Grouped filter builder"; readonly title: "Grouped filter"; readonly description: "Build a reusable canonical filter tree."; readonly incompatibleShape: "This filter cannot be edited with the selected layout ({path})."; readonly ruleOne: "{count} rule"; readonly ruleMany: "{count} rules"; readonly groupOne: "{count} group"; readonly groupMany: "{count} groups"; readonly countSeparator: " · "; readonly matchCount: "{matching} of {total} rows"; readonly viewAria: "Grouped filter view"; readonly rulesView: "Rules"; readonly textView: "Text"; readonly expressionMirrorAria: "Filter expression mirror"; readonly readableSummary: "Readable summary"; readonly readableSummaryDescription: "Read-only summary of the rules"; readonly reset: "Reset"; readonly cancel: "Cancel"; readonly apply: "Apply"; readonly applying: "Applying…"; readonly rootGroupAria: "Root filter group matching {quantifier} rules"; readonly nestedGroupAria: "Nested filter group matching {quantifier} rules"; readonly logicToggleAria: "Match {quantifier} rules. Switch to {nextQuantifier}"; readonly quantifierAll: "all"; readonly quantifierAny: "any"; readonly logicAnd: "AND"; readonly logicOr: "OR"; readonly logicNot: "NOT"; readonly rootInstruction: "Keep rows where these rules match"; readonly group: "Group"; readonly quantifierCount: "{quantifier} of {count}"; readonly inverted: "Inverted"; readonly invert: "Invert"; readonly removeGroup: "Remove group"; readonly emptyGroup: "Add a condition or group to begin."; readonly addCondition: "Add condition"; readonly addGroup: "Add group"; readonly fieldAria: "Filter field"; readonly operatorAria: "Filter operator"; readonly removeCondition: "Remove condition"; readonly clearCondition: "Clear {field} filter"; readonly applyCondition: "Apply {field} filter"; readonly clearAll: "Clear all"; readonly activeConditionCount: "{active} of {total} filters active"; readonly reorderHandle: "Reorder item {position} of {count}"; readonly reorderInstructions: "Drag to reorder. Press Alt+Arrow Up or Alt+Arrow Down to move within this group."; readonly reorderMoved: "Item reordered."; readonly fromValue: "From value"; readonly toValue: "To value"; readonly commaSeparatedValuesAria: "Comma-separated values"; readonly listPlaceholder: "value 1, value 2"; readonly editorUnavailable: "Editor unavailable for this value"; readonly filterValueAria: "Filter value"; readonly removeValueAria: "Remove {label}"; readonly addValueAria: "Add filter value"; readonly addValuePlaceholder: "Add…"; readonly searchValuesPlaceholder: "Search values…"; readonly valuesListAria: "Filter values"; readonly booleanTrue: "true"; readonly booleanFalse: "false"; readonly valuePlaceholder: "value"; readonly negatedOperator: "does not {label}"; readonly previewRemote: "Rows update on Apply"; readonly previewUpdating: "Updating preview…"; readonly previewTooLarge: "Apply to count matches"; };

DEFAULT_GROUPED_OPERATOR_SENTENCE_LABELS: {
equal: string;
notEqual: string;
beginsWith: string;
contains: string;
quickContains: string;
notContains: string;
greaterThan: string;
greaterThanOrEqual: string;
lessThan: string;
lessThanOrEqual: string;
between: string;
in: string;
notIn: string;
isBlank: string;
isNotBlank: string;
isTrue: string;
isFalse: string;
isEmptyArray: string;
isNotEmptyArray: string;
dateEquals: string;
dateNotEqual: string;
dateBefore: string;
dateAfter: string;
dateOnOrBefore: string;
dateOnOrAfter: string;
dateBetween: string;
today: string;
yesterday: string;
last7Days: string;
next30Days: string;
thisWeek: string;
lastWeek: string;
nextWeek: string;
thisMonth: string;
lastMonth: string;
thisQuarter: string;
nextQuarter: string;
previousQuarter: string;
thisYear: string;
nextYear: string;
previousYear: string;
};

DEFAULT_GROUPED_OPERATOR_SUMMARY_LABELS: {
equal: string;
notEqual: string;
beginsWith: string;
contains: string;
quickContains: string;
notContains: string;
greaterThan: string;
greaterThanOrEqual: string;
lessThan: string;
lessThanOrEqual: string;
between: string;
in: string;
notIn: string;
isBlank: string;
isNotBlank: string;
isTrue: string;
isFalse: string;
isEmptyArray: string;
isNotEmptyArray: string;
};

DEFAULT_GROUPED_NEGATED_SENTENCE_LABELS: {
beginsWith: string;
};

DEFAULT_GROUPED_FILTER_VALIDATION_MESSAGES

Section titled “DEFAULT_GROUPED_FILTER_VALIDATION_MESSAGES”
DEFAULT_GROUPED_FILTER_VALIDATION_MESSAGES: { readonly invalidNode: "The filter rule is incomplete or malformed."; readonly maxDepth: "The filter contains too many nested groups."; readonly cycle: "The filter contains a circular group reference."; readonly invalidGroupOperator: "Choose whether this group matches all rules or any rule."; readonly emptyGroup: "Add at least one condition to this group."; readonly missingChild: "Add a condition or group after NOT."; readonly invalidDiscriminator: "The filter contains an unsupported rule type."; readonly invalidField: "Choose a field for this rule."; readonly invalidOperator: "{field}: choose a filter operator."; readonly unknownOperator: "{field}: “{operator}” is not a supported filter."; readonly invalidValueType: "{field}: “{operator}” uses an unsupported value type."; readonly unexpectedValue: "{field}: “{operator}” does not accept a value."; readonly missingValue: "{field}: enter a value for “{operator}”."; readonly invalidArrayValue: "{field}: enter {requirement} for “{operator}”."; readonly valueTypeMismatch: "{field}: enter a valid {valueType} value for “{operator}”."; readonly nonFiniteNumber: "{field}: enter a finite number for “{operator}”."; readonly nonJsonValue: "{field}: the value for “{operator}” cannot be saved."; readonly valueCycle: "{field}: the value for “{operator}” contains a circular reference."; readonly nonPlainObject: "{field}: the value for “{operator}” must be a plain object."; readonly arrayOneOrMore: "one or more values"; readonly arrayExactlyTwo: "two values"; readonly genericField: "{field}: {message}"; readonly generic: "{message}"; };

export type GroupedFilterLabelKey = keyof typeof DEFAULT_GROUPED_FILTER_LABELS;

export type GroupedFilterLabels = Record<GroupedFilterLabelKey, string>;

export type GroupedFilterValidationMessageKey = keyof typeof DEFAULT_GROUPED_FILTER_VALIDATION_MESSAGES;

export type GroupedFilterValidationMessages = Record<GroupedFilterValidationMessageKey, string>;

interface GroupedFilterTranslations {
labels: GroupedFilterLabels;
operatorSentence: Readonly<Partial<Record<FilterAstOperator, string>>>;
operatorSummary: Readonly<Partial<Record<FilterAstOperator, string>>>;
negatedOperatorSentence: Readonly<Partial<Record<FilterAstOperator, string>>>;
validation: GroupedFilterValidationMessages
}

interface GroupedFilterTranslationOverrides {
labels?: Partial<GroupedFilterLabels>;
operatorSentence?: Partial<Record<FilterAstOperator, string>>;
operatorSummary?: Partial<Record<FilterAstOperator, string>>;
negatedOperatorSentence?: Partial<Record<FilterAstOperator, string>>;
validation?: Partial<GroupedFilterValidationMessages>
}

DEFAULT_GROUPED_FILTER_TRANSLATIONS: {
labels: { readonly launcher: "Groups"; readonly noConditions: "No filter conditions"; readonly builderAria: "Grouped filter builder"; readonly title: "Grouped filter"; readonly description: "Build a reusable canonical filter tree."; readonly incompatibleShape: "This filter cannot be edited with the selected layout ({path})."; readonly ruleOne: "{count} rule"; readonly ruleMany: "{count} rules"; readonly groupOne: "{count} group"; readonly groupMany: "{count} groups"; readonly countSeparator: " · "; readonly matchCount: "{matching} of {total} rows"; readonly viewAria: "Grouped filter view"; readonly rulesView: "Rules"; readonly textView: "Text"; readonly expressionMirrorAria: "Filter expression mirror"; readonly readableSummary: "Readable summary"; readonly readableSummaryDescription: "Read-only summary of the rules"; readonly reset: "Reset"; readonly cancel: "Cancel"; readonly apply: "Apply"; readonly applying: "Applying…"; readonly rootGroupAria: "Root filter group matching {quantifier} rules"; readonly nestedGroupAria: "Nested filter group matching {quantifier} rules"; readonly logicToggleAria: "Match {quantifier} rules. Switch to {nextQuantifier}"; readonly quantifierAll: "all"; readonly quantifierAny: "any"; readonly logicAnd: "AND"; readonly logicOr: "OR"; readonly logicNot: "NOT"; readonly rootInstruction: "Keep rows where these rules match"; readonly group: "Group"; readonly quantifierCount: "{quantifier} of {count}"; readonly inverted: "Inverted"; readonly invert: "Invert"; readonly removeGroup: "Remove group"; readonly emptyGroup: "Add a condition or group to begin."; readonly addCondition: "Add condition"; readonly addGroup: "Add group"; readonly fieldAria: "Filter field"; readonly operatorAria: "Filter operator"; readonly removeCondition: "Remove condition"; readonly clearCondition: "Clear {field} filter"; readonly applyCondition: "Apply {field} filter"; readonly clearAll: "Clear all"; readonly activeConditionCount: "{active} of {total} filters active"; readonly reorderHandle: "Reorder item {position} of {count}"; readonly reorderInstructions: "Drag to reorder. Press Alt+Arrow Up or Alt+Arrow Down to move within this group."; readonly reorderMoved: "Item reordered."; readonly fromValue: "From value"; readonly toValue: "To value"; readonly commaSeparatedValuesAria: "Comma-separated values"; readonly listPlaceholder: "value 1, value 2"; readonly editorUnavailable: "Editor unavailable for this value"; readonly filterValueAria: "Filter value"; readonly removeValueAria: "Remove {label}"; readonly addValueAria: "Add filter value"; readonly addValuePlaceholder: "Add…"; readonly searchValuesPlaceholder: "Search values…"; readonly valuesListAria: "Filter values"; readonly booleanTrue: "true"; readonly booleanFalse: "false"; readonly valuePlaceholder: "value"; readonly negatedOperator: "does not {label}"; readonly previewRemote: "Rows update on Apply"; readonly previewUpdating: "Updating preview…"; readonly previewTooLarge: "Apply to count matches"; };
operatorSentence: Readonly<Partial<Record<FilterAstOperator, string>>>;
operatorSummary: Readonly<Partial<Record<FilterAstOperator, string>>>;
negatedOperatorSentence: Readonly<Partial<Record<FilterAstOperator, string>>>;
validation: { readonly invalidNode: "The filter rule is incomplete or malformed."; readonly maxDepth: "The filter contains too many nested groups."; readonly cycle: "The filter contains a circular group reference."; readonly invalidGroupOperator: "Choose whether this group matches all rules or any rule."; readonly emptyGroup: "Add at least one condition to this group."; readonly missingChild: "Add a condition or group after NOT."; readonly invalidDiscriminator: "The filter contains an unsupported rule type."; readonly invalidField: "Choose a field for this rule."; readonly invalidOperator: "{field}: choose a filter operator."; readonly unknownOperator: "{field}: “{operator}” is not a supported filter."; readonly invalidValueType: "{field}: “{operator}” uses an unsupported value type."; readonly unexpectedValue: "{field}: “{operator}” does not accept a value."; readonly missingValue: "{field}: enter a value for “{operator}”."; readonly invalidArrayValue: "{field}: enter {requirement} for “{operator}”."; readonly valueTypeMismatch: "{field}: enter a valid {valueType} value for “{operator}”."; readonly nonFiniteNumber: "{field}: enter a finite number for “{operator}”."; readonly nonJsonValue: "{field}: the value for “{operator}” cannot be saved."; readonly valueCycle: "{field}: the value for “{operator}” contains a circular reference."; readonly nonPlainObject: "{field}: the value for “{operator}” must be a plain object."; readonly arrayOneOrMore: "one or more values"; readonly arrayExactlyTwo: "two values"; readonly genericField: "{field}: {message}"; readonly generic: "{message}"; };
};

between: LogicFunction<any, SliderRange | undefined>;

notContains: LogicFunction<any, Set<any> | undefined>;

Converts slider-owned state into the abstract filter-header control contract.

export function createRangeSliderHeaderControl(
slider: RangeSliderProps,
): Extract<FilterHeaderControl, { kind: 'inline' }>;

RangeSlider renders a dual-handle range control for the Pro slider filter. The slider track and numeric inputs are separate controls that share one normalized scaled-value state.

RangeSlider: FunctionalComponent<RangeSliderProps>;

Range inputs can contain decimals while native range inputs work most predictably with integers. Slider logic stores values as scaled integers and converts back to numbers only when displaying values or emitting filter state.

SLIDER_SCALE_FACTOR: 100;

Renderer shared by the Stencil filter shell and Preact structured editors.

export function renderRangeSlider(h: RangeSliderElementFactory, props: RangeSliderProps);

Preact adapter for the shared slider renderer.

export function PreactRangeSlider(props: RangeSliderProps);

Shared native single-thumb slider for scalar thresholds and tolerances.

export function SingleValueSlider({
min,
max,
value,
step = 1,
disabled = false,
id,
className = '',
ariaLabel,
ariaValueText,
onChange,
onCommit,
onKeyDown,
}: SingleValueSliderProps): any;

export type SingleValueSliderProps = {
min: number;
max: number;
value: number;
step?: number | string;
disabled?: boolean;
id?: string;
className?: string;
ariaLabel: string;
ariaValueText?: string;
onChange: (value: number, event: Event & { currentTarget: HTMLInputElement }) => void;
onCommit?: (value: number, event: Event & { currentTarget: HTMLInputElement }) => void;
onKeyDown?: (event: KeyboardEvent) => void;
};

export function mergeFilterConfigs(
base?: ColumnFilterConfig,
override?: ColumnFilterConfig,
): ColumnFilterConfig | undefined;

export function createAdvancedFilterConfig(
config?: ColumnFilterConfig,
temporalRuntime?: TemporalFilterRuntime,
): ColumnFilterConfig;

export function createDefaultFilterTypes(): Record<string, string[]>;

export function resetFilterConfigState(state: {
filterByType: Record<string, string[]>;
filterNameIndexByType: Record<string, string>;
filterFunctionsIndexedByType: Record<string, LogicFunction>;
});

expressionFilterFunction: (value: any, extra?: LogicFunctionExtraParam, context?: FilterEvaluationContext<DataType, ColumnRegular<ColumnProp, DataType<any, ColumnProp>>> | undefined, temporalRuntime?: TemporalFilterRuntime | undefined) => boolean;

ADVANCED_FILTERS: {
[FIlTER_SELECTION]: { columnFilterType: "none" | "empty" | "notEmpty" | "eq" | "notEq" | "begins" | "contains" | "notContains" | "eqN" | "neqN" | "gt" | "gte" | "lt" | "lte"; name: "none" | "empty" | "notEmpty" | "eq" | "notEq" | "begins" | "contains" | "notContains" | "eqN" | "neqN" | "gt" | "gte" | "lt" | "lte"; func: LogicFunction<any, LogicFunctionExtraParam>; };
[FIlTER_SLIDER]: { columnFilterType: "none" | "empty" | "notEmpty" | "eq" | "notEq" | "begins" | "contains" | "notContains" | "eqN" | "neqN" | "gt" | "gte" | "lt" | "lte"; name: "none" | "empty" | "notEmpty" | "eq" | "notEq" | "begins" | "contains" | "notContains" | "eqN" | "neqN" | "gt" | "gte" | "lt" | "lte"; func: LogicFunction<any, LogicFunctionExtraParam>; };
[FIlTER_QUICK_SEARCH]: { columnFilterType: "none" | "empty" | "notEmpty" | "eq" | "notEq" | "begins" | "contains" | "notContains" | "eqN" | "neqN" | "gt" | "gte" | "lt" | "lte"; name: "none" | "empty" | "notEmpty" | "eq" | "notEq" | "begins" | "contains" | "notContains" | "eqN" | "neqN" | "gt" | "gte" | "lt" | "lte"; func: LogicFunction<any, LogicFunctionExtraParam>; };
};

ADVANCED_FILTER_NAMES: {
[FIlTER_EXPRESSION]: string;
};

popUpContent: (data: ShowData, { multiFilterItems, onFilterItemsChange, subscribeFilterItemsChange, dataStores, isSourceRow, getFilterOptionValue, getItems, searchItems, itemTemplate, optionColumns, optionProgress, quickSearchFilter, grouping, plugins, gridSettings, excelMode, excelCaptions, sortDirection, onApply, onCancel, config, change, onClose, onOpenGrouped, structuredBodies, structuredOperatorIds, }: { multiFilterItems: MultiFilterItem; onFilterItemsChange: ProFilterItemsChangeListener; subscribeFilterItemsChange: ProFilterItemsChangeSubscription; dataStores: RowDataSources; isSourceRow?: ((row?: DataType | undefined) => boolean) | undefined; getFilterOptionValue?: ((row: DataType, column: ColumnRegular<ColumnProp, DataType<any, ColumnProp>>, rowType?: DimensionRows | undefined, rowIndex?: number | undefined) => unknown) | undefined; getItems: () => SelectionItem[] | Promise<SelectionItem[]>; searchItems?: ((search: string, signal: AbortSignal) => Promise<SelectionItem[]>) | undefined; itemTemplate?: SelectionItemTemplate | undefined; optionColumns?: SelectionOptionColumn[] | undefined; optionProgress?: SelectionOptionProgressConfig | undefined; quickSearchFilter?: SelectionQuickSearchFilter | undefined; grouping?: GroupingOptions | undefined; plugins?: typeof BasePlugin[] | undefined; gridSettings?: Partial<{ additionalData: AdditionalData; autoSizeColumn: boolean | AutoSizeColumnConfig; canFocus: boolean; colSize: number; columnTypes: { [name: string]: ColumnType<DataType<any, ColumnProp>>; }; editors: Editors; frameSize: number; hideAttribution: boolean; noHorizontalScrollTransfer: boolean; range: boolean; readonly: boolean; resize: boolean; rowDefinitions: RowDefinition[]; rowHeaders: boolean | RowHeaders; rowSize: number; theme: string; tree: TreeConfig | undefined; useClipboard: boolean | ClipboardConfig; }> | undefined; excelMode?: "windows" | undefined; excelCaptions?: SelectionExcelControlCaptions | undefined; sortDirection?: "none" | "asc" | "desc" | undefined; onApply?: (() => void | Promise<void>) | undefined; onCancel?: (() => void) | undefined; config?: ColumnFilterConfig | undefined; change(filterItems: MultiFilterItem): Promise<void>; onClose?(): void; onOpenGrouped?(): void; structuredBodies?: VNode[] | undefined; structuredOperatorIds?: readonly string[] | undefined; }) => any;

popUpBottomContent: (data: ShowData, options: { multiFilterItems: MultiFilterItem; onFilterItemsChange: ProFilterItemsChangeListener; subscribeFilterItemsChange: ProFilterItemsChangeSubscription; getItems: () => SelectionItem[] | Promise<SelectionItem[]>; expressionColumns?: ExpressionColumnReference[] | undefined; expressionRows?: readonly DataType[] | undefined; getExpressionValue?(row: DataType, column: ExpressionColumnReference): unknown; config?: ColumnFilterConfig | undefined; change(filterItems: MultiFilterItem, changedProp?: ColumnProp | undefined): Promise<void>; }) => any;

export type FilterPopupTransactionMode = 'staged' | 'excel';

Owns one popup draft and its current-column commit boundary.

class FilterPopupTransaction {
owns(filterItems: MultiFilterItem);
mergeInto(canonical: MultiFilterItem);
}

export function hasMeaningfulFilterValue(value: unknown);

export function hasActiveFiltersForColumn(
columnProp: ColumnProp | undefined,
multiFilterItems: MultiFilterItem,
);

export function isActiveFilter(filter: FilterData);

Allocates a filter id that cannot collide with any existing column item.

export function getNextFilterItemId(items: MultiFilterItem);

Deep-clones the mutable filter model used by popup editors.

export function cloneFilterItems(items: MultiFilterItem): MultiFilterItem;

Commits only one popup column into the latest canonical model. Other columns deliberately retain their current references so concurrent changes survive.

export function mergeFilterColumn(
current: MultiFilterItem,
draft: MultiFilterItem,
prop: ColumnProp,
): MultiFilterItem;

export type FilterHeaderTemplateValue = {
value: string;
label: string;
count: number;
};

Plain-text state retained by the grid-owned accessible trigger shell.

interface FilterHeaderPresentation {
active: boolean;
summary: string;
details?: string
}

Shared visual-template contract for every popup-style filter header.

/** Shared visual-template contract for every popup-style filter header. */
export type FilterHeaderTemplateProps = {
column: ColumnRegular;
columnProp: ColumnProp;
conditions: readonly Readonly<FilterData>[];
presentation: FilterHeaderPresentation;
/** @deprecated Use `presentation.active`. */
active: boolean;
/** @deprecated Use `presentation.summary`. */
text: string;
/** Selection-only compatibility data. */
values: FilterHeaderTemplateValue[];
/** Selection-only compatibility data. */
totalCount?: number;
/** Selection-only compatibility option. */
showCount: boolean;
};

Renders non-interactive content inside the grid-owned filter button. Return undefined to use the standard accessible text/count fallback.

/**
* Renders non-interactive content inside the grid-owned filter button.
* Return `undefined` to use the standard accessible text/count fallback.
*/
export type FilterHeaderTemplateFunc = (
h: HyperFunc<any>,
props: FilterHeaderTemplateProps,
) => VNodeResponse;

Renders an interactive control inside the grid-owned filter-header boundary.

/** Renders an interactive control inside the grid-owned filter-header boundary. */
export type FilterHeaderInlineTemplateFunc = FilterHeaderTemplateFunc;

Filter-type-owned header presentation. The grid retains the outer layout, accessibility, popup trigger, and interaction boundary.

/**
* Filter-type-owned header presentation. The grid retains the outer layout,
* accessibility, popup trigger, and interaction boundary.
*/
export type FilterHeaderControl =
| {
readonly kind: 'popup';
/** Optional visual content rendered inside the accessible popup trigger. */
readonly template?: FilterHeaderTemplateFunc;
}
| {
readonly kind: 'inline';
/** Interactive control rendered inside the shared non-sorting boundary. */
readonly template: FilterHeaderInlineTemplateFunc;
/** Optional stable class retained for type-specific presentation. */
readonly className?: string;
};

FilterHeaderTriggerState (Extended from header-template.types.ts)

Section titled “FilterHeaderTriggerState (Extended from header-template.types.ts)”
export type FilterHeaderTriggerState = Omit<
FilterHeaderTemplateProps,
'column' | 'columnProp' | 'conditions' | 'presentation'
> & {
conditions?: FilterHeaderTemplateProps['conditions'];
presentation?: FilterHeaderPresentation;
};

export function renderFilterPopupHeader(
data: ShowData,
{
multiFilterItems,
active,
captions,
onClose,
}: FilterPopupHeaderOptions,
);

export type FilterPopupHeaderOptions = {
multiFilterItems: MultiFilterItem;
active?: boolean;
captions?: Partial<FilterCaptions>;
onClose?(): void;
};

export function isValuelessFilterType(type: unknown);

VALUELESS_FILTER_TYPES: Set<string>;

Isolates popup inputs from the host grid and owns popup dismissal listeners.

export function bindFilterPanelBoundary(
panel: HTMLRevogrFilterPanelElement,
{
onDismiss,
onEscape,
}: {
onDismiss: () => void;
onEscape: () => void;
},
);

export function renderPopupConditions(
data: ShowData,
{
multiFilterItems,
config,
change,
onFilterItemsChange,
excludedTypes = [],
}: {
multiFilterItems: MultiFilterItem;
config?: ColumnFilterConfig;
change(filterItems: MultiFilterItem): Promise<void>;
onFilterItemsChange: ProFilterItemsChangeListener;
excludedTypes?: readonly string[];
},
);

Owns one manually mounted Preact root and guarantees its effects are disposed.

export function mountPreactRoot(host: HTMLElement, child: ComponentChild): PreactRootDisposer;

Bridges an outer renderer’s nullable element ref to one disposable nested root.

export function disposableElementRef(
mount: (host: HTMLElement) => void | PreactRootDisposer,
);

export type PreactRootDisposer = () => void;

export function isFilterOptionSourceRow(row?: DataType);

export function getFilterOptionSourceRows(
stores: RowDataSources,
sourceRowTypes?: DimensionRows[],
): DataType[];

export function compileExpressionFilter(
text: string,
context: ExpressionColumnContext,
): ExpressionCompileResult;

Normalizes the public expression config into one internal shape with defaults.

Returns undefined when expressions are disabled so callers can keep opt-in rendering, filter registration, and stale-state cleanup behind one predicate.

export function normalizeExpressionConfig(
config?: ColumnFilterConfig['expressions'],
): NormalizedExpressionConfig | undefined;

export function evaluateExpression(
ast: ExpressionAst,
value: unknown,
context?: FilterEvaluationContext,
temporalRuntime?: TemporalFilterRuntime,
): boolean;

expressionFilter: (value: unknown, extra?: ExpressionFilterValue | undefined, context?: FilterEvaluationContext<DataType, ColumnRegular<ColumnProp, DataType<any, ColumnProp>>> | undefined, temporalRuntime?: TemporalFilterRuntime | undefined) => boolean;

export function ExpressionHighlight({
text,
diagnostics = [],
className = '',
}: {
text: string;
diagnostics?: ExpressionDiagnostic[];
className?: string;
});

export function highlightExpression(text: string, diagnostics: ExpressionDiagnostic[] = []);

Serializes JSON-safe filter state as a readable, typed expression literal.

export function serializeExpressionLiteral(value: unknown): string;

export function isCoreFilterType(value: string): value is FilterType;

export function isExpressionOperator(value: string): value is ExpressionOperator;

EXPRESSION_FILTER_OPERATORS: { readonly empty: "empty"; readonly notEmpty: "notEmpty"; readonly eq: "eq"; readonly notEq: "notEq"; readonly begins: "begins"; readonly contains: "contains"; readonly notContains: "notContains"; readonly eqN: "eqN"; readonly neqN: "neqN"; readonly gt: "gt"; readonly gte: "gte"; readonly lt: "lt"; readonly lte: "lte"; };

EXPRESSION_DATE_OPERATORS: { readonly equals: "equals"; readonly before: "before"; readonly after: "after"; readonly onOrBefore: "onOrBefore"; readonly onOrAfter: "onOrAfter"; readonly between: "between"; readonly notEqual: "notEqual"; readonly isEmpty: "isEmpty"; readonly isNotEmpty: "isNotEmpty"; readonly today: "today"; readonly yesterday: "yesterday"; readonly last7Days: "last7Days"; readonly next30Days: "next30Days"; readonly thisWeek: "thisWeek"; readonly lastWeek: "lastWeek"; readonly nextWeek: "nextWeek"; readonly thisMonth: "thisMonth"; readonly lastMonth: "lastMonth"; readonly thisQuarter: "thisQuarter"; readonly nextQuarter: "nextQuarter"; readonly previousQuarter: "previousQuarter"; readonly thisYear: "thisYear"; readonly nextYear: "nextYear"; readonly previousYear: "previousYear"; readonly thisFiscalQuarter: "thisFiscalQuarter"; readonly nextFiscalQuarter: "nextFiscalQuarter"; readonly previousFiscalQuarter: "previousFiscalQuarter"; readonly thisFiscalYear: "thisFiscalYear"; readonly nextFiscalYear: "nextFiscalYear"; readonly previousFiscalYear: "previousFiscalYear"; };

EXPRESSION_SELECTION_OPERATORS: { readonly is: "is"; readonly in: "in"; readonly notIn: "notIn"; };

EXPRESSION_ARRAY_OPERATORS: { readonly isEmptyArray: "isEmptyArray"; readonly isNotEmptyArray: "isNotEmptyArray"; };

Exact transport form used by structured filter bodies in Expression mode.

EXPRESSION_STRUCTURED_OPERATOR: string;

EXPRESSION_SYMBOL_OPERATORS: { readonly '=': "eq"; readonly '!=': "notEq"; readonly '>': "gt"; readonly '>=': "gte"; readonly '<': "lt"; readonly '<=': "lte"; };

export type ExpressionFilterOperator =
| typeof EXPRESSION_FILTER_OPERATORS[keyof typeof EXPRESSION_FILTER_OPERATORS]
| typeof EXPRESSION_DATE_OPERATORS[keyof typeof EXPRESSION_DATE_OPERATORS]
| typeof EXPRESSION_SELECTION_OPERATORS[keyof typeof EXPRESSION_SELECTION_OPERATORS]
| typeof EXPRESSION_ARRAY_OPERATORS[keyof typeof EXPRESSION_ARRAY_OPERATORS]
| typeof EXPRESSION_STRUCTURED_OPERATOR;

export type ExpressionSymbolOperator = keyof typeof EXPRESSION_SYMBOL_OPERATORS;

export type ExpressionOperator = ExpressionFilterOperator | ExpressionSymbolOperator;

DATE_PERIOD_PHRASES: { readonly today: "today"; readonly yesterday: "yesterday"; readonly 'last 7 days': "last7Days"; readonly 'next 30 days': "next30Days"; readonly 'this week': "thisWeek"; readonly 'last week': "lastWeek"; readonly 'next week': "nextWeek"; readonly 'this month': "thisMonth"; readonly 'last month': "lastMonth"; readonly 'this quarter': "thisQuarter"; readonly 'next quarter': "nextQuarter"; readonly 'previous quarter': "previousQuarter"; readonly 'this year': "thisYear"; readonly 'next year': "nextYear"; readonly 'previous year': "previousYear"; readonly 'this fiscal quarter': "thisFiscalQuarter"; readonly 'next fiscal quarter': "nextFiscalQuarter"; readonly 'previous fiscal quarter': "previousFiscalQuarter"; readonly 'this fiscal year': "thisFiscalYear"; readonly 'next fiscal year': "nextFiscalYear"; readonly 'previous fiscal year': "previousFiscalYear"; };

VALUELESS_OPERATORS: Set<ExpressionOperator>;

LIST_OPERATORS: Set<ExpressionOperator>;

NUMERIC_OPERATORS: Set<ExpressionOperator>;

DATE_OPERATORS: Set<ExpressionOperator>;

SELECTION_OPERATORS: Set<ExpressionOperator>;

ARRAY_OPERATORS: Set<ExpressionOperator>;

VALID_OPERATORS: Set<ExpressionOperator>;

OPERATOR_START_WORDS: Set<string>;

export function defineExpressionPanel(el: HTMLElement, props: ExpressionPanelProps);

export type ExpressionPanelProps = {
data: ShowData;
multiFilterItems: MultiFilterItem;
onFilterItemsChange: ProFilterItemsChangeListener;
subscribeFilterItemsChange: ProFilterItemsChangeSubscription;
config?: ColumnFilterConfig;
getItems: () => Promise<SelectionItem[]> | SelectionItem[];
columns?: ExpressionColumnReference[];
rows?: readonly DataType[];
getValue?(row: DataType, column: ExpressionColumnReference): unknown;
change(filterItems: MultiFilterItem): Promise<void>;
};

export function parseExpression(text: string): ExpressionParseResult;

export function serializeExpressionFilters(filters: FilterData[] = []);

Creates the next filter item map after replacing one column’s expression-owned filters.

The advanced filter panel receives mutable filter state from the core filter panel, but expression apply logic should produce a fresh map before notifying sibling Pro controls. This keeps the helper reusable in tests and avoids hidden prop mutation from the expression UI.

export function replaceColumnFilters(
multiFilterItems: MultiFilterItem,
prop: ColumnProp,
filters: FilterData[],
): MultiFilterItem;

export function syncFilterItemsTarget(
target: MultiFilterItem,
source: MultiFilterItem,
): void;

export function tokenizeExpression(text: string): {
tokens: ExpressionToken[];
diagnostics: ExpressionDiagnostic[];
};

Boolean operator supported by the advanced filter expression AST.

/**
* Boolean operator supported by the advanced filter expression AST.
*/
export type ExpressionBooleanOperator = 'and' | 'or';

Parsed expression tree used by the hidden expression filter evaluator.

/**
* Parsed expression tree used by the hidden expression filter evaluator.
*/
export type ExpressionAst =
| ExpressionConditionNode
| {
kind: 'binary';
op: ExpressionBooleanOperator;
left: ExpressionAst;
right: ExpressionAst;
};

Single current-column condition parsed from an expression.

/**
* Single current-column condition parsed from an expression.
*/
export type ExpressionConditionNode = {
/** Condition node discriminator. */
kind: 'condition';
/** Optional field reference by column property or display label. */
field?: string;
/** Stable property resolved from a field label/property during compilation. */
resolvedField?: ColumnProp;
/** Filter family used to evaluate referenced temporal values correctly. */
resolvedFamily?: string;
/** Filter, date, selection, or symbolic operator. */
operator: ExpressionOperator;
/** Literal values consumed by the operator. */
values: ExpressionLiteral[];
};

Literal value parsed from expression text.

/**
* Literal value parsed from expression text.
*/
export type ExpressionLiteral =
| string
| number
| boolean
| null
| ExpressionLiteral[]
| ExpressionFunctionValue
| { [key: string]: ExpressionLiteral };

Supported value functions in filter expressions.

/** Supported value functions in filter expressions. */
export type ExpressionFunctionName = 'avg' | 'abs' | 'len';

Parsed function value. Column references are resolved during compilation.

/** Parsed function value. Column references are resolved during compilation. */
export type ExpressionFunctionValue = {
kind: 'function';
name: string;
field: string;
argumentType?: 'column' | 'number' | 'string';
resolvedField?: ColumnProp;
/** Function result prepared once when the expression is compiled. */
computedValue?: number;
};

Validation or parsing diagnostic associated with an expression text range.

/**
* Validation or parsing diagnostic associated with an expression text range.
*/
export type ExpressionDiagnostic = {
/** Human-readable diagnostic message. */
message: string;
/** Inclusive start offset in the expression text. */
start: number;
/** Exclusive end offset in the expression text. */
end: number;
};

Token categories produced by the expression tokenizer.

/**
* Token categories produced by the expression tokenizer.
*/
export type ExpressionTokenType =
| 'word'
| 'string'
| 'number'
| 'operator'
| 'paren'
| 'brace'
| 'bracket'
| 'colon'
| 'comma'
| 'invalid';

Token emitted by the expression tokenizer for parsing and highlighting.

/**
* Token emitted by the expression tokenizer for parsing and highlighting.
*/
export type ExpressionToken = {
/** Token category. */
type: ExpressionTokenType;
/** Raw token value without quote delimiters for string tokens. */
value: string;
/** Inclusive start offset in the expression text. */
start: number;
/** Exclusive end offset in the expression text. */
end: number;
};

Result of parsing expression text.

/**
* Result of parsing expression text.
*/
export type ExpressionParseResult = {
/** Parsed AST when expression syntax is valid enough to build one. */
ast?: ExpressionAst;
/** Tokens produced from the source expression text. */
tokens: ExpressionToken[];
/** Parser and tokenizer diagnostics. */
diagnostics: ExpressionDiagnostic[];
};

Hidden filter value stored in multiFilterItems for expression predicates.

/**
* Hidden filter value stored in `multiFilterItems` for expression predicates.
*/
export type ExpressionFilterValue = {
/** Original expression text used for serialization back into the editor. */
text: string;
/** Parsed expression tree used at filter evaluation time. */
ast: ExpressionAst;
};

Configuration for the Pro advanced filter expression editor.

Expression filtering is opt-in through grid.filter.expressions. When enabled, the advanced filter popup renders a current-column expression editor and compiles valid expressions into the existing RevoGrid filter model.

/**
* Configuration for the Pro advanced filter expression editor.
*
* Expression filtering is opt-in through `grid.filter.expressions`. When enabled,
* the advanced filter popup renders a current-column expression editor and compiles
* valid expressions into the existing RevoGrid filter model.
*/
export type ExpressionFilterConfig = {
/**
* Enables or disables the expression editor.
* Set to `false` to disable expressions when passing an object config.
*/
enabled?: boolean;
/**
* Delay in milliseconds before applying expression edits after typing.
* Use `0` for immediate validation/application in tests or highly reactive UIs.
*/
applyDebounceMs?: number;
/**
* Label for the button that opens the expression editor.
*/
buttonLabel?: string;
/**
* Placeholder shown in the expression textarea when it is empty.
*/
placeholder?: string;
/**
* Accessible label/title for the validation tooltip trigger shown on invalid expressions.
*/
errorTooltipLabel?: string;
/**
* Formats an expression diagnostic for the validation tooltip.
*
* Use this to localize diagnostic text or map low-level parser/compiler messages
* to product-specific wording. Multiple diagnostics are formatted individually
* and joined with new lines.
*/
formatDiagnostic?: (diagnostic: ExpressionDiagnostic, diagnostics: ExpressionDiagnostic[]) => string;
};

Expression configuration after defaults are applied.

/**
* Expression configuration after defaults are applied.
*/
export type NormalizedExpressionConfig = Required<ExpressionFilterConfig>;

Column-specific context needed to validate and compile expression text.

/**
* Column-specific context needed to validate and compile expression text.
*/
export type ExpressionColumnContext = {
/** Current column property. */
prop: ColumnProp;
/** Current column display name. */
name?: string;
/** Filter panel column metadata. */
data: ShowData;
/** Selection options available for current-column selection expressions. */
selectionItems?: ExpressionSelectionOption[];
/** Available columns used to validate compatible persisted cross-column expressions. */
columns?: ExpressionColumnReference[];
/** Current provider source used to prepare aggregate functions once. */
rows?: readonly DataType[];
/** Resolves a source value consistently with the grid's column parser. */
getValue?: (row: DataType, column: ExpressionColumnReference) => unknown;
/** Optional popup-scoped aggregate cache for function compilation. */
getAverage?: (column: ExpressionColumnReference) => number | undefined;
};

Column metadata exposed to expression compilation.

/** Column metadata exposed to expression compilation. */
export type ExpressionColumnReference = {
prop: ColumnProp;
name?: string;
data: ShowData;
};

One keyboard-selectable expression completion.

/** One keyboard-selectable expression completion. */
export type ExpressionSuggestion = {
id: string;
label: string;
insertText: string;
detail: string;
kind: 'operator' | 'keyword' | 'function';
};

Result of compiling expression text into RevoGrid filter items.

/**
* Result of compiling expression text into RevoGrid filter items.
*/
export type ExpressionCompileResult = {
/** Filter items that should replace current-column expression-owned filters. */
filters: FilterData[];
/** Validation diagnostics that should prevent applying filters when present. */
diagnostics: ExpressionDiagnostic[];
};

Selection option available to expression selection operators.

/**
* Selection option available to expression selection operators.
*/
export type ExpressionSelectionOption = {
/** Normalized selection value used by the selection filter model. */
value: string;
/** User-facing selection label. */
label: string;
};

Value normalization helpers shared by expression evaluation and future expression integrations. They intentionally mirror the lightweight coercion used by the existing Pro filter predicates instead of introducing a separate expression runtime.

Normalizes a value for case-insensitive text and selection comparisons.

export function normalizeExpressionText(value: unknown);

Coerces a value for numeric expression comparisons.

export function toExpressionNumber(value: unknown);

Coerces a value to a timestamp for date expression comparisons.

export function toExpressionDateTime(value: unknown);

Compares values by their calendar date string, matching existing Pro date-filter semantics.

export function isSameCalendarDate(value: unknown, compare: unknown);

Detects values that should prefer date comparison over numeric comparison.

export function isDateLikeValue(value: unknown);

export function formatDefaultBadgeLabel(
context: AdvancedFilterBadgeFormatContext,
presentation: AdvancedFilterBadgePresentation,
captions?: FilterBadgesCaptions,
);

export function formatDefaultBadgePresentation(
context: AdvancedFilterBadgeFormatContext,
captions?: FilterBadgesCaptions,
): AdvancedFilterBadgePresentation;

export function renderAdvancedFilterBadges(
context: AdvancedFilterBadgesRenderContext,
options: AdvancedFilterBadgesOptions,
controllerId: number,
);

export function clearAdvancedFilterBadges(root: HTMLElement);

Reuses a dropdown column’s normalized display label without changing stored identity.

export function columnDropdownValueLabel(
column: ColumnRegular | null | undefined,
value: unknown,
);

Resolves the user-visible dropdown value while preserving unknown members.

export function columnDropdownDisplayValue(
column: ColumnRegular | null | undefined,
value: unknown,
): unknown;

export function createDefaultCondition(
fields: GroupedFilterFieldOption[],
prop?: ColumnProp,
): FilterAstCondition | undefined;

export function conditionWithOperator(
condition: FilterAstCondition,
operator: GroupedFilterOperatorOption,
currentOperator?: GroupedFilterOperatorOption,
): FilterAstCondition;

Creates an invalid/empty editor draft without changing the predefined predicate identity.

export function clearConditionValue(
condition: FilterAstCondition,
operator: GroupedFilterOperatorOption,
): FilterAstCondition;

Whether a persistent slot draft currently contains an effective value.

export function hasConditionValue(
condition: FilterAstCondition,
operator: GroupedFilterOperatorOption,
): boolean;

export function defaultRange(valueType: FilterAstValueType): FilterAstValue[];

export function GroupedFilterCondition({
condition,
negated,
fields,
replace,
remove,
translations = DEFAULT_GROUPED_FILTER_TRANSLATIONS,
config,
enabled = true,
editorOpen = false,
valueEditorLayout = 'popover',
popoverTarget,
popoverTheme,
openEditor,
closeEditor,
clearSlot,
activateSlot,
}: {
condition: FilterAstCondition;
negated: boolean;
fields: GroupedFilterFieldOption[];
replace(
condition: FilterAstCondition,
negated: boolean,
operator?: GroupedFilterFieldOption['operators'][number],
): void;
remove(): void;
translations?: GroupedFilterTranslations;
config: NormalizedFilterAstEditorConfig;
enabled?: boolean;
editorOpen?: boolean;
valueEditorLayout?: 'popover' | 'inline';
popoverTarget?: HTMLElement | null;
popoverTheme?: string | null;
openEditor?(): void;
closeEditor?(): void;
clearSlot?(condition: FilterAstCondition): void;
activateSlot?(): void;
});

export function normalizeFilterAstEditorConfig(
preset: FilterAstEditorPreset = 'builder',
overrides?: FilterAstEditorConfig,
): NormalizedFilterAstEditorConfig;

export function findFilterAstShapeIssue(ast: FilterAst | undefined, config: NormalizedFilterAstEditorConfig): string | undefined;

export type NormalizedFilterAstEditorConfig = DeepRequired<FilterAstEditorConfig>;

export function renderGroupedFilterPopup(
data: ShowData,
{
ast,
fields,
validate,
preview,
apply,
close,
captions,
translations,
}: {
ast?: FilterAst;
fields: GroupedFilterFieldOption[];
validate(ast?: FilterAst): FilterAstDiagnostic[];
preview(ast: FilterAst | undefined, signal: AbortSignal): GroupedFilterPreview | Promise<GroupedFilterPreview>;
apply(ast?: FilterAst): Promise<void>;
close(): void;
captions?: Partial<FilterCaptions> & Readonly<Record<string, unknown>>;
translations?: GroupedFilterTranslationOverrides;
},
);

export function IconButton({
label,
icon,
onClick,
className = '',
disabled = false,
}: {
label: string;
icon: string;
onClick(): void;
className?: string;
disabled?: boolean;
});

export function TextIconButton({
label,
icon,
onClick,
disabled = false,
}: {
label: string;
icon: string;
onClick(): void;
disabled?: boolean;
});

Owns the application-mounted grouped editor surface and its DOM lifecycle.

export function mountExternalFilterAstEditor({
grid,
host,
initialAst: sourceAst,
options,
getFields,
validate,
preview,
apply,
captions,
onDestroy,
}: ExternalFilterAstEditorContext): FilterAstEditorHandle;

Builds grouped-editor field metadata without depending on the plugin lifecycle object.

export function createGroupedFilterFields({
currentProp,
columns: sourceColumns,
registry,
config,
filterNames,
structuredContext,
getColumnFilterTypes,
getSelectionEditor,
}: CreateGroupedFilterFieldsOptions): GroupedFilterFieldOption[];

interface CreateGroupedFilterFieldsOptions {
readonly currentProp?: ColumnProp;
readonly columns: readonly ColumnRegular[];
readonly registry: StructuredFilterTypeRegistry;
readonly config?: ColumnFilterConfig;
readonly filterNames: Readonly<Record<string, string>>;
readonly structuredContext: Omit<
StructuredFilterContextOptions,
'isVisibleRow' | 'runtimeCache' | 'dateReferenceDate' | 'sourceRowTypes'
> & {
isVisibleRow(columnProp: ColumnProp): StructuredFilterContextOptions['isVisibleRow'];
dateReferenceDate(columnProp: ColumnProp): StructuredFilterContextOptions['dateReferenceDate'];
sourceRowTypes(columnProp: ColumnProp): StructuredFilterContextOptions['sourceRowTypes'];
};
readonly getColumnFilterTypes: (
filter: ColumnRegular['filter'],
prop: ColumnProp,
) => readonly string[];
readonly getSelectionEditor: (column: ColumnRegular) => GroupedFilterOperatorEditor | undefined
}

export function GroupedFilterGroup({
group,
groupPath,
wrapperPath,
negated,
root,
fields,
update,
append,
remove,
toggleNot,
renderNode,
reorder,
translations = DEFAULT_GROUPED_FILTER_TRANSLATIONS,
config,
}: {
group: FilterAstGroup;
groupPath: FilterAstEditorPath;
wrapperPath: FilterAstEditorPath;
negated: boolean;
root?: boolean;
fields: GroupedFilterFieldOption[];
update(path: FilterAstEditorPath, updater: (node: FilterAst) => FilterAst): void;
append(path: FilterAstEditorPath, child: FilterAst): void;
remove(path: FilterAstEditorPath): void;
toggleNot(): void;
renderNode(node: FilterAst, path: FilterAstEditorPath): ComponentChildren;
reorder: GroupedFilterReorderController;
translations?: GroupedFilterTranslations;
config: NormalizedFilterAstEditorConfig;
});

export function sentenceOperatorLabel(
option: GroupedFilterOperatorOption,
translations: GroupedFilterTranslations = DEFAULT_GROUPED_FILTER_TRANSLATIONS,
);

export function getConditionOperatorVariants(
options: GroupedFilterOperatorOption[],
translations: GroupedFilterTranslations = DEFAULT_GROUPED_FILTER_TRANSLATIONS,
);

export function getConditionOperatorKey(
operator: FilterAstOperator,
negated: boolean,
variants: ConditionOperatorVariant[],
);

export function findEquivalentConditionOperatorVariant(
operator: FilterAstOperator,
negated: boolean,
variants: ConditionOperatorVariant[],
);

interface ConditionOperatorVariant {
key: string;
option: GroupedFilterOperatorOption;
negated: boolean;
label: string
}

export function getEditorNodeId(node: FilterAst);

export function updateEditorNode(
ast: FilterAst,
path: FilterAstEditorPath,
update: (node: FilterAst) => FilterAst,
): FilterAst;

export function appendEditorNode(
ast: FilterAst,
groupPath: FilterAstEditorPath,
child: FilterAst,
): FilterAst;

export function removeEditorNode(
ast: FilterAst,
path: FilterAstEditorPath,
): FilterAst | undefined;

Moves one group child before the requested insertion index, including across nested groups.

export function moveEditorNodeById(
ast: FilterAst,
sourceId: number,
targetGroupId: number,
targetIndex: number,
): FilterAst;

Checks a tree move without mutating or rebuilding the editor AST.

export function canMoveEditorNodeById(
ast: FilterAst,
sourceId: number,
targetGroupId: number,
targetIndex: number,
);

export function toggleEditorNot(
ast: FilterAst,
path: FilterAstEditorPath,
): FilterAst;

export function toEditorRoot(ast?: FilterAst): FilterAstGroup;

export function fromEditorRoot(root: FilterAstGroup): FilterAst | undefined;

Reports an effective condition that cannot be represented by the predefined slots.

export function findPersistentConditionSlotIssue(
slots: readonly FilterAstCondition[],
effectiveAst?: FilterAst,
): string | undefined;

Builds persistent UI slots and overlays the values currently present in the effective AST.

export function createPersistentConditionSlotState(
slots: readonly FilterAstCondition[],
effectiveAst?: FilterAst,
clearCondition: (condition: FilterAstCondition) => FilterAstCondition = (condition) => {
const { value: _value, ...withoutValue } = condition;
if (condition.operator === 'between' || condition.operator === 'dateBetween') {
const empty = condition.valueType === 'number' ? Number.NaN : '';
return { ...withoutValue, value: [empty, empty] };
}
return withoutValue;
},
): PersistentConditionSlotState;

Projects persistent UI slots back to the canonical AST consumed by filtering.

export function fromPersistentConditionSlots(
root: FilterAstGroup,
enabledNodeIds: ReadonlySet<number>,
): FilterAst | undefined;

export function countFilterAstNodes(
ast?: FilterAst,
includeCondition: (condition: FilterAstCondition) => boolean = () => true,
);

export function summarizeFilterAst(
ast: FilterAst,
fieldLabels: Record<string, string> = {},
operatorLabels: Record<string, string> = {},
valuePresenters: Record<string, (condition: Readonly<FilterAstCondition>) => string | undefined> = {},
translations: GroupedFilterTranslations = DEFAULT_GROUPED_FILTER_TRANSLATIONS,
): string;

export function conditionPresenterKey(field: FilterAstCondition['field'], operator: string);

export type FilterAstEditorPath = Array<number | 'not'>;

interface PersistentConditionSlotState {
root: FilterAstGroup;
enabledNodeIds: Set<number>
}

export function defineGroupedFilterPanel(el: HTMLElement, props: GroupedFilterPanelProps);

interface GroupedFilterFieldOption {
field: ColumnProp;
label: string;
operators: GroupedFilterOperatorOption[]
}

interface GroupedFilterOperatorOption {
operator: FilterAstOperator;
/** Canonical predicate used for presentation while `operator` remains the transport id. */
semanticOperator?: FilterAstOperator;
label: string;
valueType: FilterAstValueType;
/** Operator-owned value UI used when the scalar fallback would be lossy. */
editor?: GroupedFilterOperatorEditor;
/** Filter-owned readable value used by the Text mirror instead of transport objects. */
describeValue?(condition: Readonly<FilterAstCondition>): string | undefined;
/** Returns the editor-specific empty draft used when a persistent slot is cleared. */
clearCondition?(condition: Readonly<FilterAstCondition>): FilterAstCondition
}

interface GroupedFilterPanelProps {
ast?: FilterAst;
/** Stable condition definitions rendered by persistent-condition layouts. */
conditionSlots?: readonly FilterAstCondition[];
/** Explicit synchronization token. Changing it replaces the current draft baseline. */
baselineKey?: unknown;
fields: GroupedFilterFieldOption[];
validate(ast?: FilterAst): FilterAstDiagnostic[];
preview(ast: FilterAst | undefined, signal: AbortSignal): GroupedFilterPreview | Promise<GroupedFilterPreview>;
apply(ast?: FilterAst): Promise<void>;
cancel(): void;
/** Filter-config captions keyed by `groupedFilter.*`. */
captions?: Readonly<Record<string, unknown>>;
/** Direct typed overrides for standalone panel integrations. */
translations?: GroupedFilterTranslationOverrides;
config?: NormalizedFilterAstEditorConfig;
/** Internal adapter policy: external mounts expand editors in flow. */
valueEditorLayout?: 'popover' | 'inline';
shapeNotice?: string
}

interface GroupedFilterPreview {
matching?: number;
total?: number;
label?: string
}

export function GroupedFilterReorderHandle({
nodeId,
groupId,
index,
count,
label,
controller,
disabled = false,
}: {
nodeId: number;
groupId: number;
index: number;
count: number;
label: string;
controller: GroupedFilterReorderController;
disabled?: boolean;
});

export function createGroupedFilterDragGhost(source: HTMLElement, event: DragEvent);

interface GroupedFilterDropTarget {
readonly groupId: number;
readonly index: number
}

interface GroupedFilterReorderController {
readonly draggedNodeId?: number;
readonly dropTarget?: GroupedFilterDropTarget;
readonly instructionsId: string;
start(event: DragEvent, nodeId: number, source: HTMLElement): void;
over(event: DragEvent, target: GroupedFilterDropTarget): void;
drop(event: DragEvent, target: GroupedFilterDropTarget): void;
end(): void;
moveWithinGroup(nodeId: number, groupId: number, index: number, count: number, direction: -1 | 1): void
}

export function GroupedScalarValueEditor({
condition,
operator,
change,
translations = DEFAULT_GROUPED_FILTER_TRANSLATIONS,
}: GroupedFilterValueChangeProps & { translations?: GroupedFilterTranslations });

export function GroupedSelectionValueEditor({
condition,
editor,
change,
translations = DEFAULT_GROUPED_FILTER_TRANSLATIONS,
}: GroupedFilterSpecializedValueEditorProps<GroupedFilterSelectionEditor>);

export function GroupedSliderValueEditor({
condition,
editor,
change,
translations = DEFAULT_GROUPED_FILTER_TRANSLATIONS,
}: GroupedFilterSpecializedValueEditorProps<GroupedFilterSliderEditor>);

export function GroupedStructuredValueEditor({
condition,
editor,
change,
remove,
close,
}: GroupedFilterSpecializedValueEditorProps<GroupedFilterStructuredEditor> & {
remove(): void;
});

interface GroupedFilterSelectionItem {
value: string;
label: string;
[key: string]: unknown
}

interface GroupedFilterSliderEditor {
kind: 'slider';
min: number;
max: number;
step?: number | 'any';
formatValue?(value: number): string
}

interface GroupedFilterSelectionEditor {
kind: 'selection';
getItems(): GroupedFilterSelectionItem[] | Promise<GroupedFilterSelectionItem[]>;
searchItems?(
search: string,
signal: AbortSignal,
): GroupedFilterSelectionItem[] | Promise<GroupedFilterSelectionItem[]>;
matches?(item: GroupedFilterSelectionItem, normalizedSearch: string): boolean
}

interface GroupedFilterStructuredEditor {
kind: 'structured';
family: string;
mount(
host: HTMLElement,
condition: FilterAstCondition,
change: (condition: FilterAstCondition) => void,
remove: () => void,
close?: () => void,
): void | (() => void)
}

export type GroupedFilterOperatorEditor =
| GroupedFilterSliderEditor
| GroupedFilterSelectionEditor
| GroupedFilterStructuredEditor;

Converts canonical diagnostics into field-aware, fully localizable grouped-editor messages.

export function formatGroupedFilterDiagnostic(
diagnostic: FilterAstDiagnostic,
ast: FilterAst | undefined,
fields: readonly GroupedFilterFieldOption[],
translations: GroupedFilterTranslations,
);

Adds configured presentation controls without coupling them to the canonical AST.

export function configureGroupedFilterValueEditors({
fields,
columns,
overrides = [],
getSliderBounds,
}: GroupedFilterValueEditorConfigContext): GroupedFilterFieldOption[];

export function GroupedFilterValueEditor({
condition,
operator,
change,
remove,
close,
translations = DEFAULT_GROUPED_FILTER_TRANSLATIONS,
}: GroupedFilterValueEditorProps);

interface GroupedFilterValueEditorProps {
condition: FilterAstCondition;
operator: GroupedFilterOperatorOption;
change(condition: FilterAstCondition): void;
remove(): void;
close?(): void;
translations?: GroupedFilterTranslations
}

export type GroupedFilterValueChangeProps = Pick<
GroupedFilterValueEditorProps,
'condition' | 'operator' | 'change'
>;

GroupedFilterSpecializedValueEditorProps (Extended from value-editor.types.ts)

Section titled “GroupedFilterSpecializedValueEditorProps (Extended from value-editor.types.ts)”
export type GroupedFilterSpecializedValueEditorProps<
Editor extends GroupedFilterOperatorEditor,
> = Omit<GroupedFilterValueChangeProps, 'operator'> & {
editor: Editor;
close?: GroupedFilterValueEditorProps['close'];
translations?: GroupedFilterTranslations;
};

export function FilterValueAutocompleteList({
anchorRef,
id,
ariaLabel,
options,
activeIndex,
onActiveIndexChange,
onSelect,
}: {
anchorRef: RefObject<HTMLDivElement>;
id: string;
ariaLabel: string;
options: readonly FilterValueAutocompleteOption[];
activeIndex: number;
onActiveIndexChange(index: number): void;
onSelect(option: FilterValueAutocompleteOption): void;
});

FILTER_VALUE_AUTOCOMPLETE_LIMIT: 8;

interface FilterValueAutocompleteOption {
readonly value: string;
readonly label: string
}

Shared presentation for distribution-backed brush filters. Domain editors own the chart data and translate slider positions to their filter conditions.

export function BrushRange({
chart,
slider,
startLabel,
selectionLabel,
endLabel,
legacyClassPrefix,
}: BrushRangeProps);

interface BrushRangeProps {
readonly chart?: DistributionChartProps | null;
readonly slider: RangeSliderProps;
readonly startLabel: ComponentChildren;
readonly selectionLabel: ComponentChildren;
readonly endLabel: ComponentChildren;
/** Retains the established filter-specific selectors while sharing the markup owner. */
readonly legacyClassPrefix?: string
}

Build completion detail from the datasource state that won the remote request.

export function createQuickFilterCompletionDetail(
providers: PluginProviders,
quickFilter?: QuickFilter,
): QuickFilterApplyEventDetail;

Build the advanced selection option renderer from the owning column template.

export function createSelectionCellTemplate({
column,
columnProp,
additionalData,
}: SelectionCellTemplateOptions): SelectionItemTemplate | undefined;

export function normalizeSelectionFilterConfig(
config?: ColumnFilterConfig,
): ColumnFilterConfig | undefined;

export function resolveSelectionFilterConfig(
selection: SelectionConfig | undefined,
prop: ColumnProp,
): ResolvedSelectionFilterConfig;

export function normalizeSelectionItems(items: SelectionItem[]): SelectionItem[];

export type ResolvedSelectionFilterConfig = {
excelMode?: SelectionConfig['excelMode'];
sortDirection?: SelectionConfig['sortDirection'];
remoteSearch: boolean;
getItems?: GetItemsFn;
itemTemplate?: SelectionItemTemplate;
optionColumns?: SelectionOptionColumn[];
optionProgress?: SelectionOptionProgressConfig;
quickSearchFilter?: SelectionQuickSearchFilter;
grouping?: GroupingOptions;
plugins?: GridPlugin[];
gridSettings?: SelectionGridSettings;
sourceRowTypes?: DimensionRows[];
syncCellTemplate: boolean;
};

export function isSelectionFilterActive(data: ShowData);

export function renderSelectionContent(
data: ShowData,
{
multiFilterItems,
onFilterItemsChange,
subscribeFilterItemsChange,
getItems,
searchItems,
itemTemplate,
optionColumns,
optionProgress,
quickSearchFilter,
grouping,
plugins,
gridSettings,
excelMode,
excelCaptions,
sortDirection,
onApply,
onCancel,
config = {},
change,
}: SelectionContentOptions,
);

export type SelectionContentOptions = {
multiFilterItems: MultiFilterItem;
onFilterItemsChange: ProFilterItemsChangeListener;
subscribeFilterItemsChange: ProFilterItemsChangeSubscription;
getItems: () => Promise<SelectionItem[]> | SelectionItem[];
searchItems?: (search: string, signal: AbortSignal) => Promise<SelectionItem[]>;
itemTemplate?: SelectionItemTemplate;
optionColumns?: SelectionOptionColumn[];
optionProgress?: SelectionOptionProgressConfig;
quickSearchFilter?: SelectionQuickSearchFilter;
grouping?: GroupingOptions;
plugins?: GridPlugin[];
gridSettings?: SelectionGridSettings;
excelMode?: 'windows';
excelCaptions?: SelectionExcelControlCaptions;
sortDirection?: 'asc' | 'desc' | 'none';
onApply?: () => void | Promise<void>;
onCancel?: () => void;
config?: ColumnFilterConfig;
change(filterItems: MultiFilterItem, changedProp?: ColumnProp): Promise<void>;
};

export function createFilterDependencyBadgeController(
plugin: FilterDependencyBadgePlugin,
getFilterConfig: () => ColumnFilterConfig | undefined,
): FilterDependencyBadgeController;

export function getContextAwareSelectionList(
plugin: FilterPluginLike,
columnProp: ColumnProp,
exclude = new Set<string>(),
sourceRowTypes?: DimensionRows[],
): SelectionItem[];

Returns every context-valid source occurrence for header counts and summaries.

export function getContextAwareSelectionItems(
plugin: FilterPluginLike,
columnProp: ColumnProp,
exclude = new Set<string>(),
sourceRowTypes?: DimensionRows[],
): SelectionItem[];

export function createExcelDateSelectionItems(
items: SelectionItem[],
{
blanksLabel = SELECTION_FILTER_LOCALIZATION.captions.selectionBlanks,
locale,
}: { blanksLabel?: string; locale?: string } = {},
): SelectionItem[];

SELECTION_FILTER_KEYS: string;

export function resolveExcelSelectionPreset(
data: ShowData,
excelMode?: 'windows',
): ExcelSelectionPreset;

export function resolveExcelSelectionCaptions(
captions?: Partial<FilterCaptions>,
): SelectionExcelCaptions;

export function prepareExcelSelectionItems(
items: SelectionItem[],
preset: ExcelSelectionPreset,
captions: SelectionExcelCaptions,
);

export function resolveExcelSelectionPlugins(
plugins: GridPlugin[] | undefined,
preset: ExcelSelectionPreset,
): GridPlugin[] | undefined;

export function resolveExcelSelectionGridSettings(
gridSettings: SelectionGridSettings | undefined,
preset: ExcelSelectionPreset,
): SelectionGridSettings | undefined;

SELECTION_BLANK_ITEM: string;

export type SelectionExcelCaptions = {
apply: string;
cancel: string;
selectAll: string;
selectAllSearchResults: string;
addCurrentSelection: string;
invertVisible?: string;
invertVisibleAria?: string;
blanks: string;
search?: string;
selectAllAria?: string;
};

export type SelectionExcelControlCaptions = Omit<SelectionExcelCaptions, 'blanks'>;

export type ExcelSelectionPreset = {
enabled: boolean;
dateHierarchy: boolean;
};

Resolves normal and Excel selection-popup behavior from one configuration owner.

export function resolveSelectionPopupOptions({
data,
prop,
filterConfig,
cascadeEnabled,
getDefaultItems,
getContextAwareItems,
}: ResolveSelectionPopupOptions);

export type ResolveSelectionPopupOptions = {
data: ShowData;
prop: ColumnProp;
filterConfig?: ColumnFilterConfig;
cascadeEnabled: boolean;
getDefaultItems: (sourceRowTypes?: DimensionRows[]) => SelectionItem[];
getContextAwareItems: (sourceRowTypes?: DimensionRows[]) => SelectionItem[];
getExcludedItems?: (sourceRowTypes?: DimensionRows[]) => SelectionItem[];
};

Resolves option values and their shared range once for a virtual selection grid update.

export function createSelectionProgressModel(
config: SelectionOptionProgressConfig,
rows: readonly SelectionListRow[],
columnProp: ColumnProp,
): SelectionProgressModel;

export function parseValue(
originalValue: string | undefined,
originalLabel?: string,
emptyLabel = SELECTION_FILTER_LOCALIZATION.captions.selectionEmpty,
): { value: string; label: string };

export function parseSelectionValues(
originalValue: unknown,
originalLabel?: string,
): { value: string; label: string }[];

export function getSelectionValueKeys(value: unknown): string[];

Derives finite numeric slider bounds from provider-backed source stores.

export function getSliderBounds({
column,
dataStores,
isSourceRow,
getValue,
}: SliderBoundsOptions): { min: number; max: number };

export type SliderBoundsOptions = {
column: ColumnRegular;
dataStores: RowDataSources;
isSourceRow(row?: DataType): boolean;
getValue(
row: DataType,
column: ColumnRegular,
rowType?: DimensionRows,
rowIndex?: number,
): unknown;
};

export type RangeSliderElementFactory = (
type: string,
props: Record<string, unknown> | null,
...children: unknown[]
) => unknown;

Renders the dual native range inputs used as slider handles. Shared runtime helpers keep handle position, highlighted track, labels, tooltips, and optional editable inputs synchronized.

export function renderSliderControl(h: RangeSliderElementFactory, runtime: RangeSliderRuntime);

Renders optional editable range inputs for the selected slider range. Inputs intentionally use type="text" with inputMode="decimal" so custom formatters control comma/dot decimals instead of browser-localized number UI.

export function renderRangeInputs(h: RangeSliderElementFactory, runtime: RangeSliderRuntime);

export function scaleSliderValue(value: number, scaleFactor = SLIDER_SCALE_FACTOR);

Compares ranges in the same scaled space used by the native handles.

export function isFullSliderRange(
range: SliderRange,
bounds: Pick<RangeSliderProps, 'min' | 'max' | 'scaleFactor'>,
);

export function unscaleSliderValue(value: number, scaleFactor = SLIDER_SCALE_FACTOR);

export function normalizeSliderState({
min,
max,
fromValue,
toValue,
scaleFactor = SLIDER_SCALE_FACTOR,
}: SliderStateInput): ScaledSliderState;

export function clampScaledValue(value: number, minInt: number, maxInt: number);

export function normalizeFromSlider(fromValueInt: number, toValueInt: number);

export function normalizeToSlider(fromValueInt: number, toValueInt: number);

export function normalizeFromInputValue(
value: number,
currentToValueInt: number,
state: Pick<ScaledSliderState, 'minInt' | 'maxInt'>,
scaleFactor = SLIDER_SCALE_FACTOR,
);

export function normalizeToInputValue(
value: number,
currentFromValueInt: number,
state: Pick<ScaledSliderState, 'minInt' | 'maxInt'>,
scaleFactor = SLIDER_SCALE_FACTOR,
);

export function toSliderRange(
fromValueInt: number,
toValueInt: number,
scaleFactor = SLIDER_SCALE_FACTOR,
): SliderRange;

export function toSliderDisplayValue(valueInt: number, scaleFactor = SLIDER_SCALE_FACTOR);

export function formatSliderInputValue(value: number);

Default formatter shared by slider labels, tooltips, and header ranges.

export function formatSliderValue(value?: number);

Default editable input parser. Accepts both 640.42 and 640,42; returns NaN for empty text so partial edits do not reset the current slider selection while the user is typing.

export function parseSliderInputValue(value: string);

export type ScaledSliderState = {
minInt: number;
maxInt: number;
fromValueInt: number;
toValueInt: number;
};

export type SliderStateInput = {
min: number;
max: number;
fromValue: number;
toValue: number;
scaleFactor?: number;
};

export function getCurrentRange(runtime: RangeSliderRuntime);

export function syncRangeText(runtime: RangeSliderRuntime);

export function updateTooltip(
slider: HTMLInputElement,
tooltip: HTMLDivElement,
state: ScaledSliderState,
formatValue: NonNullable<RangeSliderProps['formatValue']>,
scaleFactor = 100,
);

export function getTooltipCenterPosition(
percent: number,
parentWidth: number,
tooltipWidth: number,
edgePadding = 8,
);

export function hideTooltip(tooltip: HTMLDivElement);

export function fillSlider(
from: HTMLInputElement,
to: HTMLInputElement,
controlSlider: HTMLInputElement,
);

export function syncVisuals(runtime: RangeSliderRuntime);

export function setToggleAccessible(runtime: RangeSliderRuntime);

export function emitRangeChange(runtime: RangeSliderRuntime);

export function emitRangeCommit(runtime: RangeSliderRuntime);

export function preventInvalidNumberKey(event: KeyboardEvent);

export type RangeSliderRefs = {
fromSlider?: HTMLInputElement;
toSlider?: HTMLInputElement;
fromInput?: HTMLInputElement;
toInput?: HTMLInputElement;
fromLabel?: HTMLSpanElement;
toLabel?: HTMLSpanElement;
fromTooltip?: HTMLDivElement;
toTooltip?: HTMLDivElement;
};

export type RangeSliderRuntime = {
refs: RangeSliderRefs;
state: ScaledSliderState;
scaleFactor: number;
nativeStep: number;
formatValue: NonNullable<RangeSliderProps['formatValue']>;
formatFromValue: NonNullable<RangeSliderProps['formatValue']>;
formatToValue: NonNullable<RangeSliderProps['formatValue']>;
formatInputValue: NonNullable<RangeSliderProps['formatInputValue']>;
parseInputValue: NonNullable<RangeSliderProps['parseInputValue']>;
showTooltips: boolean;
onRangeChange: RangeSliderProps['onRangeChange'];
onRangeCommit?: RangeSliderProps['onRangeCommit'];
disabled: boolean;
controlClassName?: string;
fromClassName?: string;
toClassName?: string;
fromAriaLabel?: string;
toAriaLabel?: string;
scheduleSyncVisuals: () => void;
syncVisuals: () => void;
};

@jsxImportSource preact

export function TimeMatrixLegend({
label,
selected,
outsideWorkHours,
weekend,
}: {
label: string;
selected: string;
outsideWorkHours?: string;
weekend?: string;
});

export function TimeMatrixScheduleGrid(props: TimeMatrixScheduleGridProps);

interface TimeMatrixDayLabel {
readonly weekday: number;
readonly short: string;
readonly long: string
}

interface TimeMatrixScheduleGridProps {
readonly days: readonly TimeMatrixDayLabel[];
readonly cells: ReadonlySet<string>;
readonly focused: string;
readonly weekendDays: readonly number[];
readonly workingHours?: TimeMatrixWorkingHours;
readonly gridLabel: string;
readonly hourLabel: (hour: number) => string;
readonly cellLabel: (
day: TimeMatrixDayLabel,
start: string,
end: string,
selected: boolean,
) => string;
readonly matrixRef: RefObject<HTMLDivElement>;
readonly onFocus: (key: string) => void;
readonly onKeyDown: (
event: h.JSX.TargetedKeyboardEvent<HTMLButtonElement>,
weekday: number,
hour: number,
) => void;
readonly onClick: (
event: h.JSX.TargetedMouseEvent<HTMLButtonElement>,
weekday: number,
hour: number,
selected: boolean,
) => void;
readonly onPointerDown: (
event: h.JSX.TargetedPointerEvent<HTMLButtonElement>,
weekday: number,
hour: number,
selected: boolean,
) => void;
readonly onPointerEnter: (weekday: number, hour: number) => void
}

export function ExcelSearchControls({
searchInput,
hasSearch,
allSelected,
indeterminate,
captions,
addCurrentSelection,
onSelectAll,
onInvertVisible,
onAddCurrentSelection,
}: ExcelSearchControlsProps);

export function ExcelFilterActions({
captions,
onApply,
onCancel,
}: {
captions?: SelectionExcelControlCaptions;
onApply: () => void;
onCancel?: () => void;
});

export type ExcelSearchControlsProps = {
searchInput: ComponentChildren;
hasSearch: boolean;
allSelected?: boolean;
indeterminate?: boolean;
captions?: SelectionExcelControlCaptions;
addCurrentSelection?: boolean;
onSelectAll: (checked: boolean) => void;
onInvertVisible: () => void;
onAddCurrentSelection: (checked: boolean) => void;
};

Selects only search matches by excluding every hidden key.

export function createExcelSearchExclude(
allKeys: Iterable<string>,
matchingKeys: ReadonlySet<string>,
);

Unions applied selections with search selections using exclusion-set intersection.

export function addAppliedSelectionToExcelSearch(
searchExclude: ReadonlySet<string>,
appliedExclude: ReadonlySet<string>,
);

Excel clears only an all-selected Apply; all-unselected must keep excluding every value.

export function normalizeExcelApplyExclude(
exclude: ReadonlySet<string>,
_allKeys: ReadonlySet<string>,
);

SelectionGrid: ({ columnProp, rows, itemTemplate, optionColumns, optionProgress, grouping, plugins, gridSettings, onCheckedChange, }: SelectionGridProps) => preact.JSX.Element;

SELECTION_REMOTE_SEARCH_DEBOUNCE_MS: 150;

List: ({ columnProp, subscribeFilterItemsChange, getItems, searchItems, exclude: initialExclude, search, searchPlaceholder, searchAriaLabel, selectAllAriaLabel, filter, quickFilter, quickSearchFilter, sortDirection, itemTemplate, optionColumns, optionProgress, grouping, plugins, gridSettings, excelMode, excelCaptions, searchLabels, blanksLast, onApply, onCancel, }: ListProps) => preact.JSX.Element;

defineList: (el: HTMLElement, props: ListProps) => PreactRootDisposer;

Search: ({ search, selectAll, invertVisible, searchValue, placeholder, searchAriaLabel, selectAllAriaLabel, allSelected, indeterminate, excelMode, captions, addCurrentSelection, setAddCurrentSelection, onEnter, }: SearchProps) => preact.JSX.Element;

export function TriStateCheckbox({
checked,
indeterminate,
ariaLabel,
onChange,
}: TriStateCheckboxProps);

export type TriStateCheckboxProps = {
checked?: boolean;
indeterminate?: boolean;
ariaLabel?: string;
onChange: (checked: boolean) => void;
};

export type SelectionListOption = {
text: string;
checked: boolean;
disabled: boolean;
indeterminate: boolean;
filterKeys: string[];
item: SelectionItem;
};

export type SelectionListRow = {
value: string;
label: string;
checked: boolean;
disabled: boolean;
indeterminate: boolean;
filterKeys: string[];
item: SelectionItem;
[key: string]: any;
};

interface ListProps {
columnProp: ColumnProp;
subscribeFilterItemsChange?: ProFilterItemsChangeSubscription;
getItems: () => Promise<SelectionItem[]> | SelectionItem[];
searchItems?: (search: string, signal: AbortSignal) => Promise<SelectionItem[]>;
exclude?: Set<string>;
search?: string;
searchPlaceholder?: string;
searchAriaLabel?: string;
selectAllAriaLabel?: string;
filter: (excluded: Set<string>) => void;
quickFilter: (txt: string, matchingValues?: Set<string>) => void;
quickSearchFilter?: SelectionQuickSearchFilter;
sortDirection?: 'asc' | 'desc' | 'none';
itemTemplate?: SelectionItemTemplate;
optionColumns?: SelectionOptionColumn[];
optionProgress?: SelectionOptionProgressConfig;
grouping?: GroupingOptions;
plugins?: GridPlugin[];
gridSettings?: SelectionGridSettings;
excelMode?: 'windows';
excelCaptions?: SelectionExcelControlCaptions;
searchLabels?: boolean;
blanksLast?: boolean;
onApply?: () => void | Promise<void>;
onCancel?: () => void
}

EMPTY_EXCLUDE: Set<string>;

FILTER_LIST_ROW_HEIGHT: 28;

FILTER_LIST_MAX_VISIBLE_ROWS: 8;

FILTER_LIST_MAX_HEIGHT: number;

export function withSelectionCascadeAvailability(
item: SelectionItem,
disabled: boolean,
): SelectionItem;

export function normalizeSelectionValue(value?: string);

export function createSelectionMap(items: SelectionItem[], exclude: Set<string>);

export function applyExcludeToSelectionMap(
data: Map<string, SelectionListOption>,
exclude: ReadonlySet<string>,
);

Refreshes available options without dropping values the user has excluded in the current popup. Context-aware loaders can temporarily stop returning those values once the main grid applies the exclusion, but they must remain in the chooser so the user can select them again.

export function mergeSelectionMapWithExcludedOptions(
current: Map<string, SelectionListOption>,
next: Map<string, SelectionListOption>,
exclude: ReadonlySet<string>,
);

export function getSelectionItemFilterKeys(
item: SelectionItem,
fallback = normalizeSelectionValue(item.value),
);

export function getSelectionFilterKeys(
data: Map<string, SelectionListOption>,
optionKeys: Iterable<string> = data.keys(),
);

export function getTreeSelectionCascadeKeys(
data: Map<string, SelectionListOption>,
value: string,
);

export function filterSelectionMapBySearch(
data: Map<string, SelectionListOption>,
searchText: string,
quickSearchFilter?: SelectionQuickSearchFilter,
columnProp: ColumnProp = '',
searchLabels = false,
);

export function getSelectionSearchResult(
data: Map<string, SelectionListOption>,
searchText: string,
quickSearchFilter?: SelectionQuickSearchFilter,
columnProp: ColumnProp = '',
searchLabels = false,
);

export function getSelectionQuickSearchMatchingValues(
data: Map<string, SelectionListOption>,
searchText: string,
quickSearchFilter?: SelectionQuickSearchFilter,
columnProp: ColumnProp = '',
searchLabels = false,
);

export function sortSelectionRows(
filteredData: Map<string, SelectionListOption>,
sortDirection?: 'asc' | 'desc' | 'none',
blanksLast = false,
): SelectionListRow[];

export function countGroupedSelectionRows(rows: SelectionListRow[], groupingProps: ColumnProp[] = []);