关于 data-table-filters
这是一个 shadcn 注册表,提供可组合模块,用于构建支持筛选、排序、无限滚动和虚拟化的数据表。开发者可按需逐步添加功能,包括模式推断和服务端集成。
主要功能
- 01可组合的数据表模块
- 02内置 4 种筛选类型
- 03无限滚动与虚拟化
- 04根据 JSON 推断模式
- 05URL 与客户端状态适配器
- 06可选 AI 与 MCP 模块
适用场景
- 01构建带筛选和无限滚动的日志查看器
- 02从 JSON 数据推断表格列与筛选器
- 03将数据表连接到 Drizzle ORM 或 React Query
- 04添加自然语言筛选或 MCP 端点
MCP 相关
可选的 data-table-mcp 模块提供无状态且兼容无服务器环境的 MCP 服务端点,供 AI Agent 使用。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ openstatushq/ data-table-filters --skill data-table-filters安装后在 Claude Code 中输入/data-table-filters确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/ai-filters.mdauto-infer.mdcomponent-catalog.mddrizzle-integration.mdfetch-layer.mdmcp-server.mdschema-api.mdstore-adapters.mdscripts/detect-stack.sh详细介绍
数据表筛选器
一个 shadcn 注册表,用于构建支持无限滚动和虚拟化的可筛选、可排序数据表。先从核心模块开始,再通过可选模块扩展命令面板、单元格渲染器、工作表面板、存储适配器、模式生成、Drizzle ORM 辅助工具和 React Query 集成。
前置要求。 适用于任一 shadcn 库:CLI 默认库、Base UI(
npx shadcn@latest init -d)或 Radix(npx shadcn@latest init -b radix -p lyra)。每次注册表更改和每晚运行时,CI 都会将其安装到两者中并进行类型检查。
注册表模块
使用 npx shadcn@latest add @data-table-filters/<block> 安装任意模块。CLI 会处理依赖项、路径重写和 CSS 变量注入。
| 模块 | 安装 | 新增内容 |
|---|---|---|
| data-table | @data-table-filters/data-table | 核心功能:表格引擎、存储、4 种筛选器类型、内存适配器(63 个文件) |
| data-table-filter-command | @data-table-filters/data-table-filter-command | 带历史记录和键盘快捷键的命令面板 |
| data-table-cell | @data-table-filters/data-table-cell | 12 种单元格渲染器(文本、代码、数字、条形图、热力图、仪表盘、徽章、布尔值、星级、状态码、级别指示器、时间戳) |
| data-table-sheet | @data-table-filters/data-table-sheet | 行详情侧边面板(自动安装单元格) |
| data-table-nuqs | @data-table-filters/data-table-nuqs | nuqs URL 状态适配器 |
| data-table-zustand | @data-table-filters/data-table-zustand | zustand 状态适配器 |
| data-table-schema | @data-table-filters/data-table-schema | 声明式架构系统,包含 col.* 工厂函数 |
| data-table-drizzle | @data-table-filters/data-table-drizzle | Drizzle ORM 服务端辅助工具(自动安装架构) |
| data-table-query | @data-table-filters/data-table-query | React Query 无限查询集成 |
| data-table-filter-command-ai | @data-table-filters/data-table-filter-command-ai | AI 驱动的自然语言 → 筛选器推断(与提供方无关) |
| data-table-mcp | @data-table-filters/data-table-mcp | 面向 AI Agent 的 MCP 服务端点(无状态,兼容无服务器环境) |
| data-table-actions | @data-table-filters/data-table-actions | 根据服务端元数据呈现行操作和批量操作(需要 drizzle) |
| data-table-remote | @data-table-filters/data-table-remote | 由端点清单驱动的无头表格——架构、功能和行标识 |
| data-table-chart | @data-table-filters/data-table-chart | 表格上的时间线图表:按级别堆叠分桶,拖动即可缩放时间筛选器 |
| data-table-example-infinite | @data-table-filters/data-table-example-infinite | 开箱即用的 /example 路由:架构、模拟 API、带 URL 状态的无限表格 |
模块可从 shadcn 注册表目录按名称安装;也可以使用 JSON 格式 https://data-table.openstatus.dev/r/<block>.json。
快速开始
- 运行
scripts/detect-stack.sh检测用户的项目设置。它会报告项目使用的组件库——两者均可。如果输出shadcn/ui: not initialized,请先运行npx shadcn@latest init -d初始化(Radix 用户可运行init -b radix -p lyra),然后继续。还没有项目?运行pnpm dlx shadcn@latest init @data-table-filters/data-table-example-infinite --name logs-viewer --template next -p lyra,即可创建一个初始化了 shadcn 的 Next.js 应用,并安装好可用的/example路由(包含时间线图表、筛选器、无限滚动和行详情面板)以及它所需的所有区块(使用 Radix 时,在-p lyra前添加-b radix)。需要 pnpm(npm i -g pnpm);如果更喜欢使用 npm,npx和npm run dev的用法也一样。然后运行cd logs-viewer,启动开发服务器,打开 http://localhost:3000/example,并编辑app/example/table-schema.ts——或者继续步骤 2,为自己的表格进行配置。 - 安装核心包和架构:
npx shadcn@latest add @data-table-filters/data-table @data-table-filters/data-table-schema - 搭建一个最简可用的表格(见下文);如果数据结构未知,则渲染
<DataTableAuto data={rows} /> - 根据需要添加其他区块
Next.js? 请将 data-table-filters 仓库用作参考——这是一个完整的 Next.js 应用,已接入所有区块。
最简可用表格(内存适配器)
注意:
DataTableInfinite内部会渲染DataTableProvider,后者已使用ControlsProvider和DataTableStoreSync包装子元素。无需单独添加它们。你唯一需要的包装器是DataTableStoreProvider(用于 BYOS 适配器)。
"use client";
import { DataTableInfinite } from "@/components/data-table/data-table-infinite";
import type { DataTableFilterField } from "@/components/data-table/types";
import { useMemoryAdapter } from "@/lib/store/adapters/memory";
import { DataTableStoreProvider } from "@/lib/store/provider/DataTableStoreProvider";
import type { ColumnDef } from "@tanstack/react-table";
const columns: ColumnDef<YourData>[] = [
/* user's columns */
];
const filterFields: DataTableFilterField<YourData>[] = [
/* user's filters */
];
export function MyTable({ data }: { data: YourData[] }) {
const adapter = useMemoryAdapter(/* schema definition */);
return (
<DataTableStoreProvider adapter={adapter}>
<DataTableInfinite
columns={columns}
data={data}
filterFields={filterFields}
/>
</DataTableStoreProvider>
);
}
接入扩展区块
通过 npx shadcn@latest add 安装区块后,将其接入表格。
命令面板 → commandSlot
<DataTableInfinite
commandSlot={<DataTableFilterCommand schema={schema} tableId="my-table" />}
/>
Sheet 详情面板 → sheetSlot
<DataTableInfinite
sheetSlot={
<DataTableSheetDetails title="Details">{content}</DataTableSheetDetails>
}
/>
浮动栏(批量操作)→ floatingBarSlot
将 col.select() 添加到架构中,以启用带复选框的多行选择。使用 DataTableFloatingBar 包装操作——它会从上下文读取选择状态(与 sheetSlot 使用的 DataTableSheetDetails 模式相同)。
// In table-schema.tsx
export const tableSchema = createTableSchema({
select: col.select().size(37),
// ... other columns
});
// In client.tsx
import { DataTableFloatingBar } from "@/components/data-table/data-table-floating-bar";
<DataTableInfinite
floatingBarSlot={
<DataTableFloatingBar>
{({ rows }) => (
<Button variant="outline" size="sm" onClick={() => console.log(rows)}>
Export ({rows.length})
</Button>
)}
</DataTableFloatingBar>
}
/>;
行操作 → data-table-actions
安装:npx shadcn@latest add @data-table-filters/data-table-actions(需要 drizzle 区块)。
在服务端与 Drizzle 处理程序相邻的位置一次性声明操作。列表端点会公开这些操作(meta.actions),并为每行标注适用的操作 ID(_actions);UI 根据该 JSON 进行渲染,不会获知操作的具体作用。
// app/<table>/api/actions.ts
export const actionHandler = createActionHandler({
db,
table,
filters,
columnMapping, // same as createDrizzleHandler, plus the id column
idColumn: "uuid",
basePath: "/<table>/api/actions",
actions: {
acknowledge: {
label: "Acknowledge",
scope: ["row", "bulk", "filter"],
when: { level: ["error"] }, // filter values — evaluated in JS for _actions, compiled to SQL as the WHERE guard
handler: async (ctx, tx) =>
(
await tx
.update(table)
.set({ level: "warning" })
.where(ctx.where)
.returning()
).length,
},
},
});
// GET route: data = actionHandler.annotate(result.data); meta.actions = actionHandler.descriptors
// POST app/<table>/api/actions/[id]/route.ts: actionHandler.execute(id, await req.json(), { actor })
// client.tsx
<DataTableActionsProvider
actions={meta?.actions}
getRowId={(r) => r.uuid}
queryKeyPrefix="<prefix>"
>
<DataTableInfinite
columns={[...generateColumns(schema), createActionsColumn()]}
floatingBarSlot={
<DataTableFloatingBar>
{({ rows }) => <DataTableActionsBar rows={rows} />}
</DataTableFloatingBar>
}
/>
</DataTableActionsProvider>
_actions 仅供参考;处理程序的 ctx.where(ID ∩ when)才是判定依据,因此 applied 可能少于发送的 ID。操作会加入队列(切换状态),而不会立即执行。结果会以 sonner toast 提示——在布局中挂载一次 <Toaster />(npx shadcn@latest add sonner)。
单元格渲染器 → 列定义
import { DataTableCellBadge } from "@/components/data-table/data-table-cell";
// Use in columnDef.cell
自定义筛选器类型 → FILTER_COMPONENTS
核心包已包含全部 4 种筛选器类型。添加自定义类型:
import { FILTER_COMPONENTS } from "@/components/data-table/data-table-filter-controls";
FILTER_COMPONENTS.myCustom = MyCustomFilterComponent;
AI 命令面板 → commandSlot
需要一个用于流式传输 AI 结果的 API 路由。参见 references/ai-filters.md。
<DataTableInfinite
commandSlot={
<DataTableFilterAICommand
schema={filterSchema.definition}
tableSchema={tableSchema.definition}
api="/api/ai-filters"
tableId="my-table"
/>
}
/>
所有插槽属性
DataTableInfinite 接受:commandSlot、sheetSlot、toolbarActions、chartSlot、footerSlot、floatingBarSlot。
完整接入详情请参见 references/component-catalog.md。
存储适配器配置
- memory(默认)——临时存储,零配置。适用于原型开发、嵌入式组件和构建器。
- nuqs——URL 状态。支持分享链接和将筛选器加入书签。需要进行框架配置。
- zustand——客户端状态。适用于已有 zustand 应用及复杂应用状态。
安装适配器区块并替换为相应的提供程序。参见 references/store-adapters.md。
架构生成
安装:npx shadcn@latest add @data-table-filters/data-table-schema
将数据模型映射到 createTableSchema + col.*:
-
string→col.string().filterable("input") -
number→col.number().filterable("slider", { min, max }) -
boolean→col.boolean().filterable("checkbox") -
Date→col.timestamp().filterable("timerange") -
enum→col.enum(values).filterable("checkbox") -
select→col.select()(复选框行选择,而非可筛选项)
预设:col.presets.logLevel()、.httpStatus()、.duration()、.timestamp()、.traceId()、.pathname()、.httpMethod()。
自动推断(从 JSON 零配置生成)
对于没有预定义架构的原始 JSON 数据,可使用 DataTableAuto,或使用较底层的 inferSchemaFromJSON + createTableSchema.fromJSON 流程。此功能会根据数据自动生成列、筛选器、表单字段和列可见性。
DataTableAuto 组件
即插即用组件——传入 JSON 数据,即可获得功能齐全的表格:
import { DataTableAuto } from "@/components/data-table/data-table-auto";
import data from "./data.json";
export default function Page() {
return <DataTableAuto data={data} />;
}
开箱即用地包含命令面板和表单详情面板。查看此仓库中的 /auto 路由,了解可运行的示例。
底层 API
import { inferSchemaFromJSON } from "@/lib/table-schema/infer";
import { createTableSchema } from "@/lib/table-schema";
const schemaJson = inferSchemaFromJSON(data);
const { definition } = createTableSchema.fromJSON(schemaJson);
有关推断规则、智能增强和自定义方式,请参见 references/auto-infer.md。
服务端集成
安装:npx shadcn@latest add @data-table-filters/data-table-drizzle
使用 createDrizzleHandler({ db, table, columnMapping, cursorColumn, schema }) 构建路由处理程序。
对于非 Drizzle ORM:实现响应结构 { data, facets, totalRowCount, filterRowCount, nextCursor, prevCursor }。
参见 references/drizzle-integration.md。
获取层
安装:npx shadcn@latest add @data-table-filters/data-table-query
配置 createDataTableQueryOptions({ queryKeyPrefix, apiEndpoint, searchParamsSerializer })。
默认使用同源 fetch 和 SuperJSON 请求体。对于其他 API,可传入 transport(baseUrl、作为同步/异步函数的 headers、credentials、parseResponse)以及一种 pagination 策略——timestampCursorPagination()(默认,双向)、opaqueCursorPagination() 或 offsetPagination({ size })。schemaJsonParser(schema) 会将时间戳列从普通 ISO 字符串还原,因此端点无需采用 SuperJSON。对于非 2xx 响应或无法解析的请求体,会抛出 DataTableFetchError,其中包含 status、url 和请求体片段。
无头表格(指向某个端点)
安装:npx shadcn@latest add @data-table-filters/data-table-remote
适用于数据和端点由其他地方管理,且应用中无需编写逐列代码的表格。
服务端——发布描述表格的清单:
// app/<table>/api/schema/route.ts
const handler = createTableManifestHandler(
createTableManifest({
schema: tableSchema,
primaryKey: "uuid", // the column that identifies a row on the wire
rowLabel: "{method} {pathname}", // template over column keys, for a11y
capabilities: { facets: true, totalRowCount: true, chart: true },
defaults: { sort: { id: "date", desc: true }, size: 40 },
}),
);
export const GET = (request: Request) => handler(request);
如果清单依赖请求(例如按租户区分列、根据权限显示操作),请传入函数而非值。响应会附带 ETag,因此重新验证时会返回 304。
客户端:
<DataTableRemote
manifestEndpoint="/logs/api/schema" // data endpoint defaults to this minus /schema
searchParamsSerializer={searchParamsSerializer}
initialManifest={snapshot} // optional — skips the round trip before first paint
transport={{ headers: async () => ({ authorization: await token() }) }}
renderers={{ pathname: { cell: (v) => <PathnameCell value={String(v)} /> } }}
/>
要点:
- 功能默认关闭。 仅声明端点已实现的功能;表格会相应降级(客户端分面、计数为空、无实时按钮、无图表),而非渲染空内容。
- 渲染器不会序列化。 命名显示项(
badge、bar、status-code……)会作为数据传递;其余情况使用applyRenderers/renderers属性。描述符保持不变,因此架构仍可往返转换。 - 清单不可信。 列和操作均有数量上限;操作的
href仅限页面来源,除非通过allowedActionOrigins将其他来源列入允许列表。 - 使用快照避免往返请求。
pullManifestModule(url)会写入一个带类型的模块;将其作为initialManifest传入。运行时仍会重新验证。 - 使用
runEndpointConformance({ url, manifest })和formatConformanceReport验证端点。
故障排除
- 缺少 CSS 变量:Core 会注入
--color-success/warning/error/info。请检查 CSS 中是否应用了 cssVars。 - 导入路径不匹配:shadcn CLI 会根据
components.json中的别名重写@/路径。 - nuqs:静默失败或崩溃:需要完成两个设置步骤——在根布局中添加
<NuqsAdapter>,并在表格组件外层添加<Suspense>。请参阅 references/store-adapters.md。 - nuqs:加载时未应用 URL 中的筛选条件:将服务器解析后的搜索参数作为
initialState传递给 nuqs 适配器。请参阅 references/store-adapters.md 中的 SSR Hydration 部分。 - nuqs:空字符串导致出现幽灵筛选条件:使用
field.string()(默认值为 null),而不是field.string().default("")。 - Sheet 下拉菜单缺失:
SheetField.type必须与筛选器类型匹配(不能是"readonly"),才能显示筛选器下拉菜单。使用generateSheetFields()可根据筛选器配置自动生成。 - 筛选器未渲染:请确认筛选器类型字符串与
FILTER_COMPONENTS的键匹配。 - Tailwind v4:Registry 面向 v4。类名语法与 v3 不同。