mcpField
D
data-table-filters

data-table-filters

github.com/openstatushq開発2.3k478 回インストール4 週間前に更新
リポジトリ

data-table-filters について

フィルター、ソート、無限スクロール、仮想化に対応したデータテーブルを構築する、shadcn のレジストリです。開発者はスキーマ推論やサーバーサイド連携などの機能を必要に応じて追加できます。

主な機能

  1. 01組み合わせ可能なテーブルブロック
  2. 02組み込みの4種類のフィルター
  3. 03無限スクロールと仮想化
  4. 04JSONからのスキーマ推論
  5. 05URLとクライアント状態のアダプター
  6. 06オプションのAI・MCPブロック

活用シーン

  1. 01フィルターと無限スクロール付きログビューアーの構築
  2. 02JSONデータから列とフィルターを推論
  3. 03Drizzle ORMまたはReact Queryとの連携
  4. 04自然言語フィルターやMCPエンドポイントの追加

MCP 対応

オプションの data-table-mcp ブロックは、AIエージェント向けにステートレスでサーバーレス対応の MCP サーバーエンドポイントを提供します。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/openstatushq/data-table-filters --skill data-table-filters

インストール後、Claude Code で/data-table-filtersを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
ai-filters.md
auto-infer.md
component-catalog.md
drizzle-integration.md
fetch-layer.md
mcp-server.md
schema-api.md
store-adapters.md
scripts/
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-cell12 種類のセルレンダラー(テキスト、コード、数値、バー、ヒートマップ、ゲージ、バッジ、ブール値、星、ステータスコード、レベルインジケーター、タイムスタンプ)
data-table-sheet@data-table-filters/data-table-sheet行の詳細を表示するサイドパネル(セルを自動インストール)
data-table-nuqs@data-table-filters/data-table-nuqsnuqs URL 状態アダプター
data-table-zustand@data-table-filters/data-table-zustandzustand 状態アダプター
data-table-schema@data-table-filters/data-table-schemacol.* ファクトリーを備えた宣言型スキーマシステム
data-table-drizzle@data-table-filters/data-table-drizzleDrizzle ORM のサーバーサイドヘルパー(スキーマを自動インストール)
data-table-query@data-table-filters/data-table-queryReact Query の無限クエリ統合
data-table-filter-command-ai@data-table-filters/data-table-filter-command-aiAI を活用した自然言語からのフィルター推論(プロバイダーに依存しません)
data-table-mcp@data-table-filters/data-table-mcpAI エージェント向け 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 も使用できます。

クイックスタート

  1. 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 が初期化され、必要なブロックがすべてインストールされた動作する /example ルート(タイムラインチャート、フィルター、無限スクロール、行シート)を備えた Next.js アプリが作成されます(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 に進んで独自のテーブルを作成してください。
  2. コアとスキーマをインストールします:npx shadcn@latest add @data-table-filters/data-table @data-table-filters/data-table-schema
  3. 最小限の動作するテーブルをセットアップします(下記を参照)。データの形状が不明な場合は <DataTableAuto data={rows} /> をレンダリングします
  4. 必要に応じて追加ブロックで拡張します

Next.js をお使いですか? data-table-filters repo を参考にしてください。すべてのブロックが接続された完全な 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" />}
/>
シート詳細パネル → 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 のトーストで通知されます。レイアウトで <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()。

references/schema-api.md を参照してください。

自動推論(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)と、ページネーション方式(timestampCursorPagination()(デフォルト、双方向)、opaqueCursorPagination()、または offsetPagination({ size }))を指定します。schemaJsonParser(schema) はプレーンな ISO 文字列からタイムスタンプ列を復元するため、エンドポイントで SuperJSON を採用する必要はありません。2xx 以外のステータス、または解析できないボディの場合、status、url、ボディのスニペットを含む DataTableFetchError がスローされます。

references/fetch-layer.md を参照してください。

ヘッドレステーブル(エンドポイントを指定)

インストール: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 を注入します。cssVars が CSS に適用されているか確認してください。
  • インポートパスが一致しない:shadcn CLI は components.json のエイリアスに従って @/ パスを書き換えます。
  • nuqs:何も起きない、またはクラッシュする:必須のセットアップ手順が 2 つあります。ルートレイアウトに <NuqsAdapter> を配置し、テーブルコンポーネントを <Suspense> で囲んでください。references/store-adapters.md を参照してください。
  • nuqs:読み込み時に URL のフィルターが適用されない:サーバーで解析した検索パラメーターを initialState として nuqs アダプターに渡してください。references/store-adapters.md の SSR ハイドレーションのセクションを参照してください。
  • nuqs:空文字列でフィルターが意図せず表示される:field.string().default("") ではなく、field.string()(デフォルト値は null)を使用してください。
  • シートのドロップダウンが表示されない:フィルターのドロップダウンを表示するには、SheetField.type をフィルタータイプに一致させてください("readonly" は指定しないでください)。フィルター設定から自動的に導出するには、generateSheetFields() を使用してください。
  • フィルターがレンダリングされない:フィルタータイプの文字列が FILTER_COMPONENTS のキーと一致していることを確認してください。
  • Tailwind v4:レジストリは v4 を対象としています。クラス構文は v3 と異なります。

コメント