data-table-filters

repository·main·Indexed 24 days ago

https://github.com/openstatushq/data-table-filters

A toolkit for building filterable React data tables featuring a declarative schema builder, pre-built UI components, and a pluggable state management system (BYOS). It supports various state adapters including nuqs, zustand, and memory, and provides specialized cell renderers for TanStack Table. The library can be installed via shadcn blocks and includes advanced features like AI-powered natural language filter inference and an MCP server endpoint for AI agents.

Tokens
62.1K
Snippets
125
Records
246
Agent score
78%

What's inside data-table-filters

  1. Deploy data-tables via configuration files

    main

    The project's architectural goal is to enable the deployment of data tables using configuration files. This approach relies on a system that includes:

    • A simple API endpoint to receive configurations.
    • A CLI command to deploy configurations via the API.
    • A TypeScript SDK for configuration validation (or direct support for yaml).
    • A versioning strategy to manage breaking changes (e.g., using paths like logs.run/v1, logs.run/eab5f3, or logs.run/2025-03).

    Configuration files are expected to include definitions for filter fields and components.

  2. How Three-Pass Filtering works

    main

    The data layer uses a three-pass filtering strategy to prevent UI issues like slider bounds collapsing when a user adjusts them. This strategy ensures that facet counts and slider ranges remain stable.

    1. Pass 1 (Date only): Apply only the date range filter. This establishes the base time window for all facet computations.
    2. Pass 2 (Date + non-slider filters): Add checkbox, input, and other non-slider filters. Use these conditions to compute the min/max bounds for sliders. Because the slider values themselves are excluded from this pass, moving a slider won't shrink its own available range.
    3. Pass 3 (All filters): Apply all filters, including the current slider values. This pass is used for the final data query, row counts, and checkbox facets.
  3. Understand Sheet Field types and Filter Dropdowns

    main

    When using generateSheetFields(), the type of each field is automatically derived from its filter configuration. This type determines if the sheet row displays a filter dropdown:

    SheetField.typeDerived fromSheet dropdown options
    "readonly"No filter configNo dropdown — plain display + copy only
    "checkbox".filterable("checkbox")"Include" (adds value to array filter)
    "input".filterable("input")"Include" (sets text filter)
    "slider".filterable("slider")"Less or equal", "Greater or equal", "Equal to"
    "timerange".filterable("timerange")"Exact timestamp", "Same hour", "Same day"

    To get the dropdown in a manual sheetFields definition, ensure the type matches the corresponding filterFields entry.

  4. Avoid OFFSET Pagination with Frequent Data Updates

    main

    Do not use OFFSET for pagination in datasets where new items are frequently prepended (live updates). When new items are added to the top of the list, existing offsets shift, which causes duplicate items to appear in subsequent 'load more' queries. Use cursor-based pagination (e.g., using timestamps) instead.

    // AVOID THIS PATTERN for live data
    const data = await sql`
      SELECT * FROM table 
      ORDER BY timestamp DESC 
      LIMIT ${limit} 
      OFFSET ${offset}
    `;
  5. Use AI to filter commandDisabled fields

    main

    Fields configured with .commandDisabled() are hidden from the manual command palette's auto-suggestions, but they are still included in the AI prompt.

    This is useful for fields that are difficult to type manually (like complex date ranges) but easy to express in natural language (e.g., "last 24 hours").

    date: col
      .timestamp()
      .label("Date")
      .commandDisabled()  // Hidden from manual palette, available to AI
      .sortable(),
  6. How the data-table architecture works

    main

    The data-table-filters system is organized into three distinct layers that work together to provide a complete filtering and data display experience:

    1. Table Schema: A declarative builder used to define columns, filters, display types, sorting, and row details in a single location. It uses col.* builders and presets to define the data structure.
    2. State Management: A pluggable adapter system that manages filter state. You can choose between URL-based state (using nuqs) or client-side memory state (using Zustand).
    3. UI Components: Pre-built React components that consume the schema and state. This includes DataTableInfinite for tables, DataTableFilterControls for UI inputs, DataTableFilterCommand for command palettes, and DataTableSheetDetails for row details.

    Data Flow: Table Schema $\rightarrow$ Generators $\rightarrow$ Components

  7. Understand the scope of non-standard components in the /infinite example

    main

    Components located within the _components folder are non-standard and specific to the /infinite example. They are not intended for general use across different projects because they are highly specialized for specific implementation details within the /infinite route.

    These components are typically utilized in the following locations:

    • filterFields[number].component (defined in constants.tsx)
    • columns[0].cell (defined in columns.tsx)
    • DataTableSheetDetails (defined in popover-percentile.tsx)

    If you are looking for reusable or generic components, do not use the _components folder. Instead, look in:

    • @/components/custom
    • @/components/data-table/{data-table-column}
  8. Implement Cursor Pagination for infinite scroll

    main

    The data layer uses cursor-based pagination instead of offset pagination. This provides stable performance on large tables and prevents data shifting when new rows are inserted.

    Implementation Logic

    • Cursor Type: Use a timestamp column (e.g., date) as the cursor.
    • Next Page (Older rows): WHERE date < cursor ORDER BY date DESC LIMIT size
    • Previous Page (Newer rows): WHERE date > cursor ORDER BY date ASC LIMIT size (Note: you must reverse the results on the client or server to maintain order).
    • Communication: The client sends the cursor and direction. The server responds with nextCursor and prevCursor.
  9. How the BYOS (Bring Your Own Store) pattern works

    main

    The project uses a pluggable adapter pattern for managing filter state. This allows you to choose the storage mechanism that best fits your application requirements. You can use built-in adapters or implement the StoreAdapter interface for a custom solution.

    Built-in Adapters:

    • nuqs: URL-based state (enables shareable URLs and browser history support).
    • zustand: Client-side state (ideal for integrating with an existing Zustand store).
    • memory: Ephemeral in-memory state (suitable for embedded tables or builders).
  10. Understand schema inference heuristics

    main

    The auto-inference engine uses specific patterns in your data to determine the column type (ColKind) and the appropriate filter UI (FilterType).

    Data patternInferred typeFilter type
    ISO 8601 strings (2024-01-15T...)timestamptimerange
    Unix-ms numbers (13-digit, 2001–2286)timestamptimerange
    All true/falsebooleancheckbox
    All numbers (min $\neq$ max)numberslider
    All numbers (min = max)numberinput
    Strings with $\le$ 10 distinct valuesenumcheckbox
    Strings with $>$ 10 distinct valuesstringinput
    Arrays of strings with $\le$ 10 distinct itemsarraycheckbox
    Plain objectsrecordnone
    Mixed/ambiguous typesstringinput
  11. How AI Filters work with the Command Palette

    main

    The AI command palette shares the same input field as the standard command palette. The system distinguishes between structured queries and natural language:

    1. Structured Input: Queries like host:api or latency:100-500 are parsed instantly by the existing parser without calling the AI.
    2. Natural Language: Queries like "slow requests from eu regions" trigger a request to your API route. The AI then streams back a structured JSON object matching your table schema.

    Streaming Behavior:

    • Input and Checkbox filters update immediately as values arrive in the stream.
    • Slider and Timerange filters wait until both bounds (min/max or start/end) are present before applying to prevent UI flashing.

    Validation: After the stream completes, the library performs a final validation pass to clamp slider values to bounds, strip invalid checkbox options, and convert ISO date strings to Date objects.