特性

IC 模式(内联组合子)

IC 模式使用 FilterGroupIC,组合子位于子节点之间而非分组上。这产生 Notion 风格的构建器,AND/OR 显示在规则之间。

import { AntdFilterBuilder } from '@x-filter/antd';
 
<AntdFilterBuilder
  schema={schema}
  mode="ic"
  value={filter}
  onChange={setFilter}
/>;

使用 convertToICconvertFromIC 在标准和 IC 树类型之间切换。IC 变更函数(addRuleICupdateRuleIC 等)和 icMutationAdapter 可从 @x-filter/core 导入。

锁定节点

在任意分组上设置 locked: true 可阻止对该子树的编辑。锁定的分组无法添加、删除或重排子节点。根分组可被锁定以创建固定结构的构建器。

import { createFilter } from '@x-filter/core';
 
const filter = {
  ...createFilter(),
  locked: true, // 根被锁定 — 子节点仍可编辑
};

使用 @x-filter/coreisLocked() 在自定义适配器中检查锁定状态。

只读模式

向任一适配器传入 readOnly 可渲染静态、不可交互的视图。所有变更控件(添加、删除、拖拽、DSL 编辑器)都会隐藏。键盘导航仍可用于浏览。

<AntdFilterBuilder schema={schema} value={filter} readOnly />

国际化

内置语言包覆盖所有 UI 文案。将任意语言包传入 labels prop:

import { zhCN, enUS, jaJP, locales } from '@x-filter/react';
import { ShadcnFilterBuilder } from '@x-filter/shadcn';
 
<ShadcnFilterBuilder schema={schema} labels={zhCN} />

覆盖单个 key:

<ShadcnFilterBuilder schema={schema} labels={{ ...enUS, addRule: 'Add condition' }} />

所有语言包都是完全类型化的(Required<FilterBuilderLabels>)— 缺失 key 会导致编译错误。

键盘导航

每个构建器都是带 roving tabindex 的 ARIA tree。无需额外配置。

按键行为
Tab将焦点移到过滤树
/ 在规则之间移动
Home / End跳到第一条 / 最后一条
Enter聚焦当前行的第一个编辑控件
Esc从控件退回到所在行
Delete / Backspace删除当前聚焦的规则
Ctrl / Cmd+D克隆当前聚焦的规则

根分组不可被删除或克隆。readOnly 模式下所有变更快捷键被禁用,但导航仍可用。无头的 useFilterKeyboardNav hook 驱动此功能,可在自定义适配器中复用。

响应式与移动端

构建器自动适配窄屏:

  • 纵向堆叠: 低于 sm 断点(640px)时,每条规则的字段/操作符/值各占一行。宽屏恢复横向布局。
  • 触摸拖拽: 注册了 MouseTouchKeyboard 三种 sensor。触摸使用 TouchSensor 延迟激活,避免干扰滚动。拖拽手柄为 44px 触摸目标,touch-action: none
  • 断点 hook: @x-filter/reactuseIsMobile(breakpoint = 640) 是 SSR 安全的(matchMedia 不可用时默认桌面布局)。antd 适配器据此切换 Space 方向,shadcn 适配器使用 Tailwind 响应式类。

预设

使用 useFilterPresets 保存、加载和删除过滤器预设:

import { useFilterPresets } from '@x-filter/react';
 
const { presets, savePreset, loadPreset, deletePreset } = useFilterPresets({
  storage: localStorage, // 或自定义 PresetStorage
});

shadcn 适配器提供 ShadcnPresetBar 组件,开箱即用。

撤销 / 重做

useFilterHistory 为过滤器状态提供撤销/重做支持:

import { useFilterHistory } from '@x-filter/react';
 
const { state, setState, undo, redo, canUndo, canRedo } = useFilterHistory(initialFilter);

useFilterBuilderOrchestrator 自动集成历史 — 传入 history: true 即可启用。

导入

将 JSON 过滤器或 DSL 字符串解析为过滤树:

import { parseFilterInput } from '@x-filter/react';
 
const result = parseFilterInput('{"combinator":"and","children":[]}', 'json');

两个适配器都提供导入对话框组件(AntdImportFilterDialog / ShadcnImportFilterDialog),支持格式自动检测。

查询导出

将同一份 Filter 编译为多种后端查询格式:

格式函数导入路径空过滤器
SQL(参数化)toSQL@x-filter/core/sql{ sql: '', params: [] }
JsonLogictoJsonLogic@x-filter/core/jsonlogictrue
MongoDB 查询toMongoQuery@x-filter/core/mongodb{}
ElasticsearchtoElasticQuery@x-filter/core/elasticsearch{ match_all: {} }

所有导出器支持嵌套分组、AND/OR 组合子、not 取反,以及可选的 fieldMap 重映射字段名。

import { toSQL } from '@x-filter/core/sql';
 
const { sql, params } = toSQL(filter, {
  fieldMap: { status: 'tickets.status' },
});

URL 同步

将过滤器状态持久化到 URL,实现可分享链接:

import { useFilterUrlSync } from '@x-filter/react';
 
const { getFilterFromUrl, setFilterToUrl, error } = useFilterUrlSync({ mode: 'dsl' });
模式URL 形态适用场景
'dsl'(默认)?filter=status:equals:open AND priority:gt:2简洁、人类可读的链接
'json'?filter=%7B%22combinator%22...%7D无损保留全部结构

可选项:paramName(默认 filter)、getSearchParams / setSearchParams 用于自定义适配器(如 Next.js router)。解析失败返回 error 字符串而非抛出异常。